<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://blog.kristijan.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.kristijan.org/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-01-12T13:55:44+11:00</updated><id>https://blog.kristijan.org/feed.xml</id><title type="html">Kristian’s Blog</title><subtitle>A minimal, responsive, and powerful Jekyll theme for presenting professional writing.</subtitle><entry><title type="html">TMUX Flash Copy</title><link href="https://blog.kristijan.org/posts/TMUX-Flash-Copy/" rel="alternate" type="text/html" title="TMUX Flash Copy" /><published>2026-01-12T00:00:00+11:00</published><updated>2026-01-12T13:54:56+11:00</updated><id>https://blog.kristijan.org/posts/TMUX%20Flash%20Copy</id><content type="html" xml:base="https://blog.kristijan.org/posts/TMUX-Flash-Copy/"><![CDATA[<p>There is a popular neovim plugin called <a href="https://github.com/folke/flash.nvim" target="_blank">flash.nvim</a>, which amongst other things, allows you to quickly jump to a word in your code. It’s a great tool for developers who want to quickly navigate their codebase.</p>

<p>I was looking for something similar, but for <a href="https://github.com/tmux/tmux" target="_blank">tmux</a>. I wanted to be able to search visible words in the current tmux pane, then copy that word to the system clipboard by pressing the associated label key.</p>

<p>I built <a href="https://github.com/Kristijan/flash-copy.tmux" target="_blank">https://github.com/Kristijan/flash-copy.tmux</a>, with the aim to bring that functionality to tmux.</p>

<p><img src="assets/images/tmux-flash-copy-demo.gif" alt="Demonstration of tmux-flash-copy in action" /></p>

<p>In the demonstration above, you can see how it works.</p>
<ol>
  <li>I launch the TMUX Flash Copy plugin using the default key binding <code class="language-plaintext highlighter-rouge">&lt;tmux prefix&gt; Shift + f</code></li>
  <li>The word <code class="language-plaintext highlighter-rouge">option_override</code> is what I want to copy, so I start searching for it. You can see as I search, words are highlighted in the pane and labels are assigned with each match.</li>
  <li>I press the label key <code class="language-plaintext highlighter-rouge">j</code> associated with the word <code class="language-plaintext highlighter-rouge">option_override</code>, and it’s copied to the system clipboard.</li>
</ol>

<blockquote class="prompt-tip">
  <p>You can automatically paste the copied text by holding the semicolon <code class="language-plaintext highlighter-rouge">;</code> modifier key while selecting the label.</p>
</blockquote>

<p>I tried to implement as many of the visual features from flash.nvim as possible, and added a few of my own which made sense:</p>
<ul>
  <li>Dynamic Search: Type to filter words in real-time as you search.</li>
  <li>Overlay Labels: Single key selection with labels overlayed on matches in the pane.</li>
  <li>Dimmed Display: Non-matching content is dimmed for visual focus.</li>
  <li>Clipboard Copy: Selected text is immediately copied to the system clipboard.</li>
  <li>Auto-paste Modifier: Use semicolon key as a modifier to automatically paste selected text.</li>
  <li>Configurable Word Boundaries: Honours tmux’s <code class="language-plaintext highlighter-rouge">word-separators</code> by default, with override support.</li>
</ul>

<p>There are many customisable options available, including:</p>
<ul>
  <li>Customising the prompt position, indicator, and colour.</li>
  <li>Changing the colours used for highlighted matches and labels.</li>
  <li>Using either case sensitive or case insensitive searching.</li>
</ul>

<p>You can find a lot more detail and configuration options in the <a href="https://github.com/Kristijan/flash-copy.tmux/blob/master/README.md">README</a>, and I welcome any feedback or contributions.</p>]]></content><author><name></name></author><category term="tmux" /><category term="python" /><category term="tmux" /><summary type="html"><![CDATA[There is a popular neovim plugin called flash.nvim, which amongst other things, allows you to quickly jump to a word in your code. It’s a great tool for developers who want to quickly navigate their codebase.]]></summary></entry><entry><title type="html">TMUX FZF Pane Switch</title><link href="https://blog.kristijan.org/posts/TMUX-fzf-pane-switcher/" rel="alternate" type="text/html" title="TMUX FZF Pane Switch" /><published>2024-10-27T00:00:00+11:00</published><updated>2026-01-12T12:30:12+11:00</updated><id>https://blog.kristijan.org/posts/TMUX%20fzf%20pane%20switcher</id><content type="html" xml:base="https://blog.kristijan.org/posts/TMUX-fzf-pane-switcher/"><![CDATA[<p>If you currently use <a href="https://github.com/alexander-naumov/gnu-screen" target="_blank">screen</a> as your terminal window manager, you should take a look at <a href="https://github.com/tmux/tmux" target="_blank">tmux</a>. This isn’t a screen vs tmux post, but I made the switch a few years back, and I’ve become a lot more productive as a result of it.</p>

<p>tmux has a concept of sessions, windows, and panes. A session is a collection of one or more windows, and a window can contain one or more panes. At work, I use sessions a lot. I’ll have a session that contains all my VIOS, another for all my NIM’s, and another for all my test servers. To switch from one session to another, you press <code class="language-plaintext highlighter-rouge">prefix + s</code> to bring up the current list of sessions, arrow down to the session, and hit enter. You can expand the session list to show all the windows, and from there further select the exact window from the session you want to go to.</p>

<p>This flow I find time consuming. I’d much rather bring up the list of sessions, and search to narrow down where I want to switch to. So piggy backing on another tool that I use, I wrote a small little tmux plugin that brings up a fzf window with my sessions, windows, and panes, and lets me quickly get to the pane I want.</p>

<p><a href="https://github.com/Kristijan/fzf-pane-switch.tmux" target="_blank">https://github.com/Kristijan/fzf-pane-switch.tmux</a></p>

<p>Using the plugin with the default mapping of <code class="language-plaintext highlighter-rouge">prefix + s</code>, I now get a <a href="https://github.com/junegunn/fzf" target="_blank">fzf</a> window where I can narrow my search by filtering on the <code class="language-plaintext highlighter-rouge">#{window_name}</code>, <code class="language-plaintext highlighter-rouge">#{pane_title}</code>, or <code class="language-plaintext highlighter-rouge">#{pane_current_command}</code>. I’ve got a demo video below that shows it in action.</p>

<p><img src="assets/images/tmux-fzf-pane-switch-demo.gif" alt="Demonstration of tmux-fzf-pane-switch in action" /></p>

<p>If you use tmux, hopefully you’ll see the benefit in using it.</p>]]></content><author><name></name></author><category term="tmux" /><category term="fzf" /><category term="scripting" /><category term="shell-scripting" /><category term="tmux" /><summary type="html"><![CDATA[If you currently use screen as your terminal window manager, you should take a look at tmux. This isn’t a screen vs tmux post, but I made the switch a few years back, and I’ve become a lot more productive as a result of it.]]></summary></entry><entry><title type="html">AIX/VIOS Security Advisories</title><link href="https://blog.kristijan.org/posts/AIX-VIOS-security-advisories/" rel="alternate" type="text/html" title="AIX/VIOS Security Advisories" /><published>2024-01-17T00:00:00+11:00</published><updated>2024-01-17T16:59:14+11:00</updated><id>https://blog.kristijan.org/posts/AIX%20VIOS%20security%20advisories</id><content type="html" xml:base="https://blog.kristijan.org/posts/AIX-VIOS-security-advisories/"><![CDATA[<p>IBM provide a number of resources to keep up to date with security advisory announcements. IBM X-Force Exchange provide an API, IBM Support provide email notifications (along with RSS/Atom feeds), and there is also a JSON feed that comes from <a href="https://esupport.ibm.com/customercare/flrt/doc?page=aparJSON" target="_blank">https://esupport.ibm.com/customercare/flrt/doc?page=aparJSON</a>. For my requirements, I’ve found the JSON feed to contain the data that I need at a glance. It provides me with an abstract, the URL to the advisory, if the fix requires a reboot, and the CVE number along with its associated CVSS score.</p>

<p>This is enough information for me to quickly triage a security advisory and determine if I need to look into it in any further detail. However, looking at raw JSON data isn’t pretty, and I wanted it presented in a format that was a little more involved than what I could do with <a href="https://jqlang.github.io/jq" target="_blank"><code class="language-plaintext highlighter-rouge">jq</code></a>. I ended up writing something in python that you can find on my <a href="https://github.com/Kristijan/aix_security_advisories" target="_blank">GitHub page</a> that produces the below formatted table.</p>

<p><img src="https://raw.githubusercontent.com/Kristijan/aix_security_advisories/main/assets/screenshot.png" alt="aix_security_advisories.py screenshot" />
<em>aix_security_advisories.py screenshot</em></p>

<p>I’m not using all the available data in the output. Additional items include a link to download a fix (if available) and a list of impacted filesets and versions. It’s not data that I need at a quick glance, and it’s all available at the advisory URL. If anyone wants that data included in the table, I welcome contributions, but also happy to add it in. All this is just me trying to have a better understanding of working with python, and making my day-to-day easier.</p>]]></content><author><name></name></author><category term="aix" /><category term="vios" /><category term="advisories" /><category term="aix" /><category term="python" /><category term="security" /><category term="vios" /><summary type="html"><![CDATA[IBM provide a number of resources to keep up to date with security advisory announcements. IBM X-Force Exchange provide an API, IBM Support provide email notifications (along with RSS/Atom feeds), and there is also a JSON feed that comes from https://esupport.ibm.com/customercare/flrt/doc?page=aparJSON. For my requirements, I’ve found the JSON feed to contain the data that I need at a glance. It provides me with an abstract, the URL to the advisory, if the fix requires a reboot, and the CVE number along with its associated CVSS score.]]></summary></entry><entry><title type="html">HMC Profile Diff</title><link href="https://blog.kristijan.org/posts/HMC-profile-diff/" rel="alternate" type="text/html" title="HMC Profile Diff" /><published>2023-01-16T00:00:00+11:00</published><updated>2023-01-16T18:06:00+11:00</updated><id>https://blog.kristijan.org/posts/HMC%20profile%20diff</id><content type="html" xml:base="https://blog.kristijan.org/posts/HMC-profile-diff/"><![CDATA[<p>More often than not, I find myself having to compare two Hardware Management Console (HMC) logical partition (LPAR) profile configurations. Sometimes this is to ensure that a profile in a disaster recovery site matches that of its production counterpart. Other times, it’s to make sure all members of a cluster have identical resource configurations.</p>

<p>In a perfect world, I’d be manging the LPAR configurations using something like Terraform, but this currently isn’t an option. I can login to the HMC and manually verify the profiles (which is what I’ve been doing), but this is tedious and prone to error when you need to compare many profile pairs.</p>

<p>The HMC, a few major version releases ago, introduced a REST API that exposes all the profile data. I’ve written a script to collect this data, and present it in a more user friendly format for consumption. You can find the <a href="https://github.com/Kristijan/hmc_profile_diff" target="_blank">HMC profile diff</a> script hosted on my GitHub.</p>

<p>Below are some screenshots of the script output.</p>

<p><img src="https://raw.githubusercontent.com/Kristijan/hmc_profile_diff/main/img/demo.gif" alt="Demo" /></p>

<p><img src="https://raw.githubusercontent.com/Kristijan/hmc_profile_diff/main/img/compare_all.png" alt="Compare All" width="700" height="400" />
<em>Compare all LPAR profile attributes</em></p>

<p><img src="https://raw.githubusercontent.com/Kristijan/hmc_profile_diff/main/img/compare_diffonly.png" alt="Compare Diff Only" width="700" height="400" />
<em>Compare all LPAR profile attributes and only show differences</em></p>]]></content><author><name></name></author><category term="hmc" /><category term="python" /><category term="hmc" /><summary type="html"><![CDATA[More often than not, I find myself having to compare two Hardware Management Console (HMC) logical partition (LPAR) profile configurations. Sometimes this is to ensure that a profile in a disaster recovery site matches that of its production counterpart. Other times, it’s to make sure all members of a cluster have identical resource configurations.]]></summary></entry><entry><title type="html">AIX paging space</title><link href="https://blog.kristijan.org/posts/AIX-paging-space/" rel="alternate" type="text/html" title="AIX paging space" /><published>2022-11-06T00:00:00+11:00</published><updated>2022-11-07T16:51:33+11:00</updated><id>https://blog.kristijan.org/posts/AIX%20paging%20space</id><content type="html" xml:base="https://blog.kristijan.org/posts/AIX-paging-space/"><![CDATA[<p>An AIX installation will come with a default configured paging space logical volume (<code class="language-plaintext highlighter-rouge">hd6</code>). You can increase the size of the logical volume to suit your needs, but at some stage, you may have a requirement to either expand the logical volume greater than the size of the rootvg, or more than 64GB (the current maximum size of a paging logical volume). There are a number of best practises when it comes to paging space on AIX.</p>

<ol>
  <li>Don’t span paging logical volumes across different disks.</li>
  <li>Create additional paging logical volumes of equal size. As paging space is allocated in a round-robin type manner, smaller paging spaces will fill up quicker than larger ones.</li>
  <li>If you can’t increase the default paging logical volume <code class="language-plaintext highlighter-rouge">hd6</code> to be equal size of all other additional paging logical volumes, deactivate it.</li>
</ol>

<p>As a rule of thumb, I generally try and keep my <code class="language-plaintext highlighter-rouge">rootvg</code> volume groups relatively lean. I’ve been bitten way too often with failed <a href="https://www.ibm.com/docs/en/aix/7.2?topic=m-multibos-command" target="_blank">multibos</a> creations due to insufficient free capacity in the <code class="language-plaintext highlighter-rouge">rootvg</code> volume group. More often than not, this is because someone has increased the size of the <code class="language-plaintext highlighter-rouge">hd6</code> paging space. Depending on the size of your <code class="language-plaintext highlighter-rouge">rootvg</code>, you may wish to impose a maximum size limit on the <code class="language-plaintext highlighter-rouge">hd6</code> paging logical volume. Any requirements for an increase to (or additional) paging space, should be created on a separate volume.</p>

<p>If I have such a requirement for additional paging space (say the largest possible paging size of 64GB), I will create a separate volume group (for example, <code class="language-plaintext highlighter-rouge">pagingvg</code>) and allocate LUN’s of 64GB in size. Each paging logical volume will consume the entire LUN, and I will deactivate <code class="language-plaintext highlighter-rouge">hd6</code> (see example below).</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>lsps <span class="nt">-a</span>
<span class="go">Page Space      Physical Volume   Volume Group    Size %Used   Active    Auto    Type   Chksum
paging01        hdisk2            pagingvg     61344MB     0     yes     yes      lv       0
paging00        hdisk1            pagingvg     61344MB     0     yes     yes      lv       0
hd6             hdisk0            rootvg        8192MB     0      no     yes      lv       0
</span><span class="gp">#</span><span class="w"> </span>lspv <span class="nt">-l</span> hdisk1
<span class="go">hdisk1:
LV NAME               LPs     PPs     DISTRIBUTION          MOUNT POINT
paging00              1917    1917    384..383..383..383..384 N/A
</span><span class="gp">#</span><span class="w"> </span>lspv <span class="nt">-l</span> hdisk2
<span class="go">hdisk2:
LV NAME               LPs     PPs     DISTRIBUTION          MOUNT POINT
paging01              1917    1917    384..383..383..383..384 N/A
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>I then have the below script that runs at boot. It will deactivate the default paging device (<code class="language-plaintext highlighter-rouge">hd6</code>) if an alternate paging space is active, and greater in size.</p>

<div file="/etc/rc.d/init.d/deactivate_paging.sh" class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="rouge-code"><pre><span class="c">#!/bin/ksh</span>
<span class="c">#</span>
<span class="c"># Script      : deactivate_paging.sh</span>
<span class="c">#</span>
<span class="c"># Description : Script runs at boot and will deactivate the default</span>
<span class="c">#               AIX paging device (hd6) if an alternate paging space is</span>
<span class="c">#               active, and greater in size.</span>
<span class="c">#</span>
<span class="c"># Usage       : Script takes no parameters.</span>

<span class="k">if </span>lsps <span class="nt">-ac</span> | <span class="nb">grep</span> <span class="nt">-Evq</span> <span class="s1">'^#|^hd6'</span><span class="p">;</span> <span class="k">then</span>
  <span class="c"># Get size of default paging space</span>
  <span class="nv">hd6_size</span><span class="o">=</span><span class="si">$(</span>lsps <span class="nt">-a</span> | <span class="nb">awk</span> <span class="s1">'/^hd6/{ print $4 }'</span><span class="si">)</span>

  <span class="c"># Create array of other paging space attributes</span>
  <span class="nb">set</span> <span class="nt">-A</span> paging_name <span class="si">$(</span>lsps <span class="nt">-a</span> | <span class="nb">awk</span> <span class="s1">'!/^hd6/ &amp;&amp; (NR!=1){ print $1 }'</span><span class="si">)</span>
  <span class="nb">set</span> <span class="nt">-A</span> paging_size <span class="si">$(</span>lsps <span class="nt">-a</span> | <span class="nb">awk</span> <span class="s1">'!/^hd6/ &amp;&amp; (NR!=1){ print $4 }'</span><span class="si">)</span>
  <span class="nb">set</span> <span class="nt">-A</span> paging_active <span class="si">$(</span>lsps <span class="nt">-a</span> | <span class="nb">awk</span> <span class="s1">'!/^hd6/ &amp;&amp; (NR!=1){ print $6 }'</span><span class="si">)</span>

  <span class="c"># Default paging space (hd6) will be turned off if any single</span>
  <span class="c"># alternate paging space is active, and greater in size than</span>
  <span class="c"># the default paging space</span>
  <span class="nv">count</span><span class="o">=</span>0
  <span class="k">while</span> <span class="o">[[</span> <span class="s2">"</span><span class="k">${</span><span class="nv">count</span><span class="k">}</span><span class="s2">"</span> <span class="nt">-lt</span> <span class="s2">"</span><span class="k">${#</span><span class="nv">paging_name</span><span class="p">[*]</span><span class="k">}</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">do
    if</span> <span class="o">[[</span> <span class="o">(</span> <span class="s2">"</span><span class="k">${</span><span class="nv">paging_active</span><span class="p">[</span><span class="nv">$count</span><span class="p">]</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"yes"</span> <span class="o">)</span> <span class="o">&amp;&amp;</span> <span class="o">(</span> <span class="s2">"</span><span class="k">${</span><span class="nv">paging_size</span><span class="p">[</span><span class="nv">$count</span><span class="p">]%??</span><span class="k">}</span><span class="s2">"</span> <span class="nt">-gt</span> <span class="s2">"</span><span class="k">${</span><span class="nv">hd6_size</span><span class="p">%??</span><span class="k">}</span><span class="s2">"</span> <span class="o">)</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
      <span class="o">{</span>
        <span class="nb">echo</span> <span class="s2">"At least one alternate paging space detected and active [</span><span class="k">${</span><span class="nv">paging_name</span><span class="p">[</span><span class="nv">$count</span><span class="p">]</span><span class="k">}</span><span class="s2">]"</span>
        <span class="nb">echo</span> <span class="s1">'Deactivating default paging space hd6...'</span>
        swapoff /dev/hd6
      <span class="o">}</span> <span class="o">&gt;</span> /dev/console
      <span class="nb">exit
    </span><span class="k">else</span>
      <span class="o">((</span> count+<span class="o">=</span>1 <span class="o">))</span>
    <span class="k">fi
  done
fi</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Console output during system boot.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>alog <span class="nt">-t</span> console <span class="nt">-o</span>
<span class="c">...
...
...
</span><span class="go">         0 Mon Nov  7 10:23:14 AEDT 2022 At least one alternate paging space detected and active [paging00]
         0 Mon Nov  7 10:23:14 AEDT 2022 Deactivating default paging space hd6...
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>You can find some good information regarding paging space placement best practices on IBM’s website - <a href="https://www.ibm.com/support/pages/paging-space-placement-best-practices" target="_blank">https://www.ibm.com/support/pages/paging-space-placement-best-practices</a></p>]]></content><author><name></name></author><category term="aix" /><category term="aix" /><category term="paging" /><summary type="html"><![CDATA[An AIX installation will come with a default configured paging space logical volume (hd6). You can increase the size of the logical volume to suit your needs, but at some stage, you may have a requirement to either expand the logical volume greater than the size of the rootvg, or more than 64GB (the current maximum size of a paging logical volume). There are a number of best practises when it comes to paging space on AIX.]]></summary></entry><entry><title type="html">Deploying AIX eFixes using NIM at scale with Puppet</title><link href="https://blog.kristijan.org/posts/Deploying-AIX-eFixes-using-NIM-at-scale-with-Puppet/" rel="alternate" type="text/html" title="Deploying AIX eFixes using NIM at scale with Puppet" /><published>2022-09-10T00:00:00+10:00</published><updated>2022-09-10T10:01:08+10:00</updated><id>https://blog.kristijan.org/posts/Deploying%20AIX%20eFixes%20using%20NIM%20at%20scale%20with%20Puppet</id><content type="html" xml:base="https://blog.kristijan.org/posts/Deploying-AIX-eFixes-using-NIM-at-scale-with-Puppet/"><![CDATA[<p>Most will be familiar with using the <code class="language-plaintext highlighter-rouge">emgr</code> command to install emergency fixes (eFixes) on AIX. You can additionally use a Network Installation Management <a href="https://www.ibm.com/docs/en/aix/7.2?topic=installing-network-installation-management" target="_blank">(NIM)</a> server in either a push or pull operation to install fixes, which is handy when deploying at scale (more on this later in the post with deploying fixes at scale with Puppet).</p>

<h2 id="prepare-nim-resources">Prepare NIM resources</h2>

<p>There is a little setup work that you first need to perform on the NIM server to make this possible. At a minimum, on the NIM server, you will require a lpp_source resource to place the fixes in. Creating a lpp_source resource is outside the scope of this post, but you can find additional information <a href="https://www.ibm.com/docs/en/aix/7.2?topic=resource-defining-lpp-source" target="_blank">here</a>.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre><span class="gp">(nim01) #</span><span class="w"> </span>lsnim <span class="nt">-l</span> 7200TL5SP4_lpp
<span class="go">7200TL5SP4_lpp:
   class       = resources
   type        = lpp_source
   comments    = AIX 7.2 TL5 SP4 lppsource
   arch        = power
   Rstate      = ready for use
   prev_state  = unavailable for use
   location    = /nim/lpp/7200TL5SP4_lpp
   simages     = yes
   alloc_count = 0
   server      = master
</span><span class="gp">(nim01) #</span><span class="w"> </span><span class="nb">ls</span> <span class="nt">-l</span> /nim/lpp/7200TL5SP4_lpp/emgr/ppc
<span class="go">total 64320
-rw-r--r--    1 root     system     28191901 Aug 16 00:49 1121201a.220804.epkg.Z
-rw-r--r--    1 root     system        49935 Jun 11 03:37 IJ39876s3a.220506.epkg.Z
-rw-r--r--    1 root     system      4683895 Aug 15 16:08 IJ41139m4a.220809.epkg.Z
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Optionally, if you’re installing multiple fixes at the same time, you can create a NIM installp_bundle resource. Creating an installp_bundle resource is outside the scope of this post, but you can find additional information <a href="https://www.ibm.com/docs/en/aix/7.2?topic=resource-defining-installp-bundle" target="_blank">here</a>.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="gp">(nim01) #</span><span class="w"> </span>lsnim <span class="nt">-l</span> 7200TL5SP4_emgr
<span class="go">7200TL5SP4_emgr:
   class       = resources
   type        = installp_bundle
   comments    = AIX 7.2 TL5 SP4 emgr_bundle
   Rstate      = ready for use
   prev_state  = unavailable for use
   location    = /nim/bundles/7200TL5SP4_emgr
   alloc_count = 0
   server      = master
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Contents of <code class="language-plaintext filepath highlighter-rouge">/nim/bundles/7200TL5SP4_emgr</code></p>

<div file="/nim/bundles/7200TL5SP4_emgr" class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>E:IJ39876s3a.220506.epkg.Z
E:IJ41139m4a.220809.epkg.Z
E:1121201a.220804.epkg.Z
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="installing-fixes-on-aix-hosts">Installing fixes on AIX hosts</h2>

<p>You have two options when it comes to installing the fixes onto AIX hosts using the NIM server. You can either push the fixes from the NIM server to the AIX host, or you can pull the fixes from the AIX host.</p>

<h3 id="push">Push</h3>

<p>Installing a single fix from a NIM lpp_source resource.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="gp">(nim01) #</span><span class="w"> </span>nim <span class="nt">-o</span> cust <span class="nt">-a</span> <span class="nv">lpp_source</span><span class="o">=</span>7200TL5SP4_lpp <span class="nt">-a</span> <span class="nv">filesets</span><span class="o">=</span>E:1121201a.220804.epkg.Z aix01
<span class="go">
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER       LABEL               OPERATION              RESULT
===========       ==============      =================      ==============
1                 1121201a            INSTALL                SUCCESS
Return Status = SUCCESS
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Installing multiple fixes from a NIM installp_bundle resource.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="gp">(nim01) #</span><span class="w"> </span>nim <span class="nt">-o</span> cust <span class="nt">-a</span> <span class="nv">lpp_source</span><span class="o">=</span>7200TL5SP4_lpp <span class="nt">-a</span> <span class="nv">installp_bundle</span><span class="o">=</span>7200TL5SP4_emgr aix01
<span class="go">
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER       LABEL               OPERATION              RESULT
===========       ==============      =================      ==============
1                 IJ39876s3a          INSTALL                SUCCESS
2                 IJ41139m4a          INSTALL                SUCCESS
3                 1121201a            INSTALL                SUCCESS
Return Status = SUCCESS
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="pull">Pull</h3>

<p>Installing a single fix from a NIM lpp_source resource.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="gp">(aix01) #</span><span class="w"> </span>nimclient <span class="nt">-o</span> cust <span class="nt">-a</span> <span class="nv">lpp_source</span><span class="o">=</span>7200TL5SP4_lpp <span class="nt">-a</span> <span class="nv">filesets</span><span class="o">=</span>E:1121201a.220804.epkg.Z
<span class="go">
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER       LABEL               OPERATION              RESULT
===========       ==============      =================      ==============
1                 1121201a            INSTALL                SUCCESS
Return Status = SUCCESS
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Installing multiple fixes from a NIM installp_bundle resource.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="gp">(aix01) #</span><span class="w"> </span>nimclient <span class="nt">-o</span> cust <span class="nt">-a</span> <span class="nv">lpp_source</span><span class="o">=</span>7200TL5SP4_lpp <span class="nt">-a</span> <span class="nv">installp_bundle</span><span class="o">=</span>7200TL5SP4_emgr
<span class="go">
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER       LABEL               OPERATION              RESULT
===========       ==============      =================      ==============
1                 IJ39876s3a          INSTALL                SUCCESS
2                 IJ41139m4a          INSTALL                SUCCESS
3                 1121201a            INSTALL                SUCCESS
Return Status = SUCCESS
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="deploying-fixes-at-scale-with-puppet-tasks">Deploying fixes at scale with Puppet Tasks</h2>

<p>If you’re using Puppet Enterprise, and can use Puppet Tasks, here is one that allows you to install both a single fix, or multiple fixes using the above mentioned methods.</p>

<h3 id="task-metadata">Task metadata</h3>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="rouge-code"><pre><span class="p">{</span><span class="w">
    </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A task for installing/uninstalling AIX fixes."</span><span class="p">,</span><span class="w">
    </span><span class="nl">"parameters"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"install"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Set to true to install efix, or set to false to uninstall efix."</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Boolean"</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"lpp_source"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"NIM lpp_source containing the efix(s)."</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"String[1]"</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"fix_name"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Name of a single efix to be installed/uninstalled.</span><span class="se">\n\t</span><span class="s2">When installing, the 'fix_name' is the name of the package (e.g. IJ31191m1a.210322.epkg.Z).</span><span class="se">\n\t</span><span class="s2">When uninstalling, the 'fix_name' is the name of the label (e.g. IJ31191m1a)."</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Optional[String[1]]"</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"installp_bundle"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Name of installp_bundle to use when installing multiple efixes."</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Optional[String[1]]"</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"reboot"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"If true, the system is rebooted after installing/uninstalling the efix(s)."</span><span class="p">,</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Boolean"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"puppet_task_version"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
    </span><span class="nl">"supports_noop"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="task">Task</h3>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="rouge-code"><pre><span class="c1">#!/opt/puppetlabs/puppet/bin/ruby</span>
<span class="c1">#</span>
<span class="c1"># A task for installing/uninstalling AIX fixes</span>
<span class="nb">require</span> <span class="s1">'puppet'</span>
<span class="nb">require</span> <span class="s1">'json'</span>

<span class="c1"># Set FACTERLIB so custom facts resolve</span>
<span class="no">Puppet</span><span class="p">.</span><span class="nf">initialize_settings</span>
<span class="no">ENV</span><span class="p">[</span><span class="s1">'FACTERLIB'</span><span class="p">]</span> <span class="o">=</span> <span class="no">Puppet</span><span class="p">.</span><span class="nf">settings</span><span class="p">[</span><span class="s1">'factpath'</span><span class="p">]</span>
<span class="nb">require</span> <span class="s1">'facter'</span>

<span class="c1"># Sanity check that we're an AIX host</span>
<span class="k">if</span> <span class="no">Facter</span><span class="p">.</span><span class="nf">value</span><span class="p">(</span><span class="ss">:operatingsystem</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"AIX"</span> <span class="k">then</span>
    <span class="n">params</span>          <span class="o">=</span> <span class="no">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="no">STDIN</span><span class="p">.</span><span class="nf">read</span><span class="p">)</span>
    <span class="n">install</span>         <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'install'</span><span class="p">]</span>
    <span class="n">lpp_source</span>      <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'lpp_source'</span><span class="p">]</span>
    <span class="n">fix_name</span>        <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'fix_name'</span><span class="p">]</span>
    <span class="n">installp_bundle</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'installp_bundle'</span><span class="p">]</span>
    <span class="n">reboot</span>          <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'reboot'</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">install</span> <span class="k">then</span>
        <span class="c1"># Check if we have either a fix_name or installp_bundle set</span>
        <span class="k">if</span> <span class="n">params</span><span class="p">.</span><span class="nf">key?</span><span class="p">(</span><span class="s2">"installp_bundle"</span><span class="p">)</span> <span class="k">then</span>
            <span class="n">fix</span> <span class="o">=</span> <span class="s2">"installp_bundle=</span><span class="si">#{</span><span class="n">installp_bundle</span><span class="si">}</span><span class="s2">"</span>
        <span class="k">elsif</span> <span class="n">params</span><span class="p">.</span><span class="nf">key?</span><span class="p">(</span><span class="s2">"fix_name"</span><span class="p">)</span> <span class="k">then</span>
            <span class="n">fix</span> <span class="o">=</span> <span class="s2">"filesets=E:</span><span class="si">#{</span><span class="n">fix_name</span><span class="si">}</span><span class="s2">"</span>
        <span class="k">else</span>
            <span class="nb">print</span> <span class="s2">"You need to specify either a fix_name or installp_bundle."</span>
            <span class="nb">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
        <span class="k">end</span>

        <span class="c1"># Install efix(s)</span>
        <span class="nb">system</span><span class="p">(</span><span class="s2">"/usr/sbin/nimclient"</span><span class="p">,</span> <span class="s2">"-o"</span><span class="p">,</span> <span class="s2">"cust"</span><span class="p">,</span> <span class="s2">"-a"</span><span class="p">,</span> <span class="s2">"lpp_source=</span><span class="si">#{</span><span class="n">lpp_source</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"-a"</span><span class="p">,</span> <span class="s2">"</span><span class="si">#{</span><span class="n">fix</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
        <span class="k">if</span> <span class="vg">$?</span><span class="p">.</span><span class="nf">exitstatus</span> <span class="o">!=</span> <span class="mi">0</span>
            <span class="nb">print</span> <span class="s2">"efix failed to install."</span>
            <span class="nb">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
        <span class="k">end</span>
    <span class="k">else</span>
        <span class="c1"># Uninstall efix</span>
        <span class="k">if</span> <span class="n">params</span><span class="p">.</span><span class="nf">key?</span><span class="p">(</span><span class="s2">"fix_name"</span><span class="p">)</span> <span class="k">then</span>
            <span class="nb">system</span><span class="p">(</span><span class="s2">"/usr/sbin/nimclient"</span><span class="p">,</span> <span class="s2">"-o"</span><span class="p">,</span> <span class="s2">"cust"</span><span class="p">,</span> <span class="s2">"-a"</span><span class="p">,</span> <span class="s2">"lpp_source=</span><span class="si">#{</span><span class="n">lpp_source</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"-a"</span><span class="p">,</span> <span class="s2">"filesets=E:</span><span class="si">#{</span><span class="n">fix_name</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"-a"</span><span class="p">,</span> <span class="s2">"installp_flags=u"</span><span class="p">)</span>
            <span class="k">if</span> <span class="vg">$?</span><span class="p">.</span><span class="nf">exitstatus</span> <span class="o">!=</span> <span class="mi">0</span>
                <span class="nb">print</span> <span class="s2">"efix failed to uninstall."</span>
                <span class="nb">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
            <span class="k">end</span>
        <span class="k">else</span>
            <span class="nb">print</span> <span class="s2">"You need to specify a fix_name to uninstall."</span>
        <span class="k">end</span>
    <span class="k">end</span>

    <span class="c1"># Reboot</span>
    <span class="k">if</span> <span class="n">reboot</span> <span class="k">then</span>
        <span class="nb">system</span><span class="p">(</span><span class="s2">"/usr/bin/echo '/usr/sbin/shutdown -r +3' | /usr/bin/at now"</span><span class="p">)</span>
    <span class="k">end</span>
<span class="k">else</span>
  <span class="nb">print</span> <span class="s2">"Task only supported on AIX."</span>
  <span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">end</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="running-the-task">Running the Task</h3>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="rouge-code"><pre><span class="gp">$</span><span class="w"> </span>puppet task show patch::aix_efix
<span class="go">
patch::aix_efix - A task for installing/uninstalling AIX fixes.

USAGE:
</span><span class="gp">$</span><span class="w"> </span>puppet task run patch::aix_efix <span class="nb">install</span><span class="o">=</span>&lt;value&gt; <span class="nv">lpp_source</span><span class="o">=</span>&lt;value&gt; <span class="nv">reboot</span><span class="o">=</span>&lt;value&gt; <span class="o">[</span><span class="nv">fix_name</span><span class="o">=</span>&lt;value&gt;] <span class="o">[</span><span class="nv">installp_bundle</span><span class="o">=</span>&lt;value&gt;] &lt;<span class="o">[</span><span class="nt">--nodes</span>, <span class="nt">-n</span> &lt;node-names&gt;] | <span class="o">[</span><span class="nt">--query</span>, <span class="nt">-q</span> &lt;<span class="s1">'query'</span><span class="o">&gt;]&gt;</span>
<span class="go">
PARAMETERS:
- install : Boolean
    Set to true to install efix, or set to false to uninstall efix.
- lpp_source : String[1]
    NIM lpp_source containing the efix(s).
- reboot : Boolean
    If true, the system is rebooted after installing/uninstalling the efix(s).
- fix_name : Optional[String[1]]
    Name of a single efix to be installed/uninstalled.
        When installing, the 'fix_name' is the name of the package (e.g. IJ31191m1a.210322.epkg.Z).
        When uninstalling, the 'fix_name' is the name of the label (e.g. IJ31191m1a).
- installp_bundle : Optional[String[1]]
    Name of installp_bundle to use when installing multiple efixes.

</span><span class="gp">$</span><span class="w"> </span>puppet task run patch::aix_efix <span class="nb">install</span><span class="o">=</span><span class="nb">true </span><span class="nv">lpp_source</span><span class="o">=</span>7200TL5SP4_lpp <span class="nv">reboot</span><span class="o">=</span><span class="nb">false </span><span class="nv">installp_bundle</span><span class="o">=</span>7200TL5SP4_emgr <span class="nt">-n</span> aix01
<span class="go">Starting job ...
Note: The task will run only on permitted nodes.
New job ID: 83786
Nodes: 1

Started on aix01 ...
Finished on node aix01
  STDOUT:

    Initializing log /var/adm/ras/emgr.log ...
    EPKG NUMBER       LABEL               OPERATION              RESULT
    ===========       ==============      =================      ==============
    1                 IJ39876s3a          INSTALL                SUCCESS
    2                 IJ41139m4a          INSTALL                SUCCESS
    3                 1121201a            INSTALL                SUCCESS
    Return Status = SUCCESS

Job completed. 1/1 nodes succeeded.
Duration: 1 min, 3 sec
</span></pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name></name></author><category term="aix" /><category term="aix" /><category term="nim" /><category term="puppet" /><summary type="html"><![CDATA[Most will be familiar with using the emgr command to install emergency fixes (eFixes) on AIX. You can additionally use a Network Installation Management (NIM) server in either a push or pull operation to install fixes, which is handy when deploying at scale (more on this later in the post with deploying fixes at scale with Puppet).]]></summary></entry><entry><title type="html">Display client LPAR WWPNs from the HMC</title><link href="https://blog.kristijan.org/posts/LPAR-WWPNs-from-the-HMC/" rel="alternate" type="text/html" title="Display client LPAR WWPNs from the HMC" /><published>2022-08-13T00:00:00+10:00</published><updated>2024-01-17T16:21:26+11:00</updated><id>https://blog.kristijan.org/posts/LPAR%20WWPNs%20from%20the%20HMC</id><content type="html" xml:base="https://blog.kristijan.org/posts/LPAR-WWPNs-from-the-HMC/"><![CDATA[<p>There are several ways to find the WWPNs for a virtual fibre channel adapter. You can log into the individual LPAR’s, get them from the Hardware Management Console (HMC), or from another asset discovery tool that may contain this data.</p>

<p>Using <a href="https://ezh.sourceforge.net" target="_blank">EZH</a> functions originally written by Brian Smith, I’ve added a function named <code class="language-plaintext highlighter-rouge">lparwwpn</code> that takes a list of LPAR names as arguments, and prints the virtual fibre channel WWPNs.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span><span class="nb">source </span>lparwwpn
<span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span>lparwwpn aix1 aix2
<span class="go">
aix1 [POWER-FRAME-1]
c0XXXXXXXXXXXXf2,c0XXXXXXXXXXXXf3
c0XXXXXXXXXXXXf4,c0XXXXXXXXXXXXf5
c0XXXXXXXXXXXXf6,c0XXXXXXXXXXXXf7
c0XXXXXXXXXXXXf8,c0XXXXXXXXXXXXf9

aix2 [POWER-FRAME-2]
c0XXXXXXXXXXXX20,c0XXXXXXXXXXXX21
c0XXXXXXXXXXXX22,c0XXXXXXXXXXXX23
c0XXXXXXXXXXXX24,c0XXXXXXXXXXXX25
c0XXXXXXXXXXXX26,c0XXXXXXXXXXXX27
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Save the contents of the shell script below to a file named <code class="language-plaintext highlighter-rouge">lparwwpn</code>, and copy it over to the HMC.</p>

<blockquote class="prompt-tip">
  <p>You can name the file anything you like, just adjust the <code class="language-plaintext highlighter-rouge">source</code> command above accordingly.</p>
</blockquote>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="rouge-code"><pre>lparframelookup <span class="o">()</span> <span class="o">{</span>
    <span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> system<span class="p">;</span> <span class="k">do
        while </span><span class="nb">read</span> <span class="nt">-r</span> lpar<span class="p">;</span> <span class="k">do
            if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$lpar</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"</span><span class="nv">$*</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
                </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">system</span><span class="k">}</span><span class="s2">"</span><span class="p">;</span>
            <span class="k">fi
        done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-m</span> <span class="s2">"</span><span class="nv">$system</span><span class="s2">"</span> <span class="nt">-r</span> lpar <span class="nt">-F</span> name<span class="o">)</span>
    <span class="k">done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-r</span> sys <span class="nt">-F</span> <span class="s2">"name,state"</span> | <span class="nb">grep</span> <span class="nt">-E</span> <span class="s2">"Standby|Operating"</span> | <span class="nb">cut</span> <span class="nt">-d</span>, <span class="nt">-f</span> 1<span class="o">)</span> | <span class="nb">tail</span> <span class="nt">-n</span> 1
<span class="o">}</span>

checklpar <span class="o">()</span> <span class="o">{</span>
    <span class="nv">count</span><span class="o">=</span>0<span class="p">;</span>
    <span class="k">if</span> <span class="o">[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
        while </span><span class="nb">read</span> <span class="nt">-r</span> system<span class="p">;</span> <span class="k">do
            while </span><span class="nb">read</span> <span class="nt">-r</span> l<span class="p">;</span> <span class="k">do
                if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$l</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then
                    </span><span class="nv">count</span><span class="o">=</span><span class="k">$((</span>count <span class="o">+</span><span class="m">1</span><span class="k">))</span>
                <span class="k">fi
            done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-m</span> <span class="s2">"</span><span class="nv">$system</span><span class="s2">"</span> <span class="nt">-r</span> lpar <span class="nt">-F</span> name<span class="o">)</span>
        <span class="k">done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-r</span> sys <span class="nt">-F</span> <span class="s2">"name,state"</span> | <span class="nb">grep</span> <span class="nt">-E</span> <span class="s2">"Standby|Operating"</span> | <span class="nb">cut</span> <span class="nt">-d</span>, <span class="nt">-f</span> 1<span class="o">)</span>
        <span class="nv">l</span><span class="o">=</span><span class="s2">""</span>
        <span class="k">if</span> <span class="o">[</span> <span class="nv">$count</span> <span class="nt">-eq</span> 0 <span class="o">]</span><span class="p">;</span> <span class="k">then
            </span><span class="nb">echo</span> <span class="s2">"ERROR:  LPAR not found: </span><span class="nv">$1</span><span class="s2">"</span>
            <span class="k">return </span>1
        <span class="k">fi
        if</span> <span class="o">[</span> <span class="nv">$count</span> <span class="nt">-gt</span> 1 <span class="o">]</span><span class="p">;</span> <span class="k">then
            </span><span class="nb">echo</span> <span class="s2">"ERROR:  Multiple LPAR's with same name </span><span class="nv">$1</span><span class="s2">"</span>
            <span class="k">return </span>2
        <span class="k">fi
    else
        </span><span class="nb">unset </span>input
        <span class="nb">unset </span>lpararray
        <span class="nb">echo</span> <span class="s2">"Select LPAR: "</span>
        <span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> system<span class="p">;</span> <span class="k">do
            while </span><span class="nb">read</span> <span class="nt">-r</span> l<span class="p">;</span> <span class="k">do
                </span><span class="nv">count</span><span class="o">=</span><span class="k">$((</span>count <span class="o">+</span><span class="m">1</span><span class="k">))</span>
                <span class="nb">printf</span> <span class="s2">"%5s. %-20s %-20s</span><span class="se">\n</span><span class="s2">"</span> <span class="nv">$count</span> <span class="s2">"</span><span class="nv">$l</span><span class="s2">"</span> <span class="s2">"</span><span class="si">$(</span>lssyscfg <span class="nt">-r</span> lpar <span class="nt">-m</span> <span class="se">\"</span><span class="s2">"</span><span class="k">${</span><span class="nv">system</span><span class="k">}</span><span class="s2">"</span><span class="se">\"</span> <span class="nt">-F</span> state <span class="nt">--filter</span> <span class="nv">lpar_names</span><span class="o">=</span><span class="se">\"</span><span class="s2">"</span><span class="k">${</span><span class="nv">l</span><span class="k">}</span><span class="s2">"</span><span class="se">\"</span><span class="si">)</span><span class="s2">"</span>
                lpararray[<span class="nv">$count</span><span class="o">]=</span><span class="s2">"</span><span class="nv">$l</span><span class="s2">"</span>
            <span class="k">done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-m</span> <span class="s2">"</span><span class="nv">$system</span><span class="s2">"</span> <span class="nt">-r</span> lpar <span class="nt">-F</span> name<span class="o">)</span>
        <span class="k">done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-r</span> sys <span class="nt">-F</span> <span class="s2">"name,state"</span> | <span class="nb">grep</span> <span class="nt">-E</span> <span class="s2">"Standby|Operating"</span> | <span class="nb">cut</span> <span class="nt">-d</span>, <span class="nt">-f</span> 1<span class="o">)</span>
        <span class="nb">echo
        </span><span class="k">while</span> <span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="k">${</span><span class="nv">lpararray</span><span class="p">[</span><span class="nv">$input</span><span class="p">]</span><span class="k">}</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">do
            </span><span class="nb">printf</span> <span class="s2">"%s</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"Enter LPAR number (1-</span><span class="nv">$count</span><span class="s2">, </span><span class="se">\"</span><span class="s2">q</span><span class="se">\"</span><span class="s2"> to quit): "</span><span class="p">;</span>
            <span class="nb">read</span> <span class="nt">-r</span> input
            <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$input</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"q"</span> <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$input</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"Q"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then return </span>1<span class="p">;</span> <span class="k">fi
        done
        </span><span class="nv">lpar</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">lpararray</span><span class="p">[</span><span class="nv">$input</span><span class="p">]</span><span class="k">}</span><span class="s2">"</span>
        checklpar <span class="s2">"</span><span class="nv">$lpar</span><span class="s2">"</span> <span class="o">||</span> <span class="k">return </span>2
    <span class="k">fi</span>
<span class="o">}</span>

lparwwpn <span class="o">()</span> <span class="o">{</span>
    <span class="k">for </span>lpar <span class="k">in</span> <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span><span class="p">;</span> <span class="k">do
        </span><span class="nv">frame</span><span class="o">=</span><span class="si">$(</span>lparframelookup <span class="s2">"</span><span class="k">${</span><span class="nv">lpar</span><span class="k">}</span><span class="s2">"</span><span class="si">)</span>
        <span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">%s [%s]</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"</span><span class="k">${</span><span class="nv">lpar</span><span class="k">}</span><span class="s2">"</span> <span class="s2">"</span><span class="k">${</span><span class="nv">frame</span><span class="k">}</span><span class="s2">"</span>
        checklpar <span class="s2">"</span><span class="nv">$lpar</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="nb">eval </span>lshwres <span class="nt">-m</span> <span class="s2">"</span><span class="k">${</span><span class="nv">frame</span><span class="k">}</span><span class="s2">"</span> <span class="nt">-r</span> virtualio <span class="nt">--rsubtype</span> <span class="nb">fc</span> <span class="nt">--level</span> lpar <span class="nt">--filter</span> <span class="se">\"</span><span class="nv">lpar_names</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">lpar</span><span class="k">}</span><span class="s2">"</span><span class="se">\"</span> | <span class="nb">cut</span> <span class="nt">-d</span> <span class="s1">'='</span> <span class="nt">-f11</span> | <span class="nb">sed</span> <span class="s1">'s/\"//'</span> | <span class="nb">sort</span><span class="p">;</span>
    <span class="k">done</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I’ve recently come across <a href="https://github.com/opokam/eezh" target="_blank">EEZH</a>, which appears to be a fork of Brian Smith’s original EZH code. Might be more beneficial to add <code class="language-plaintext highlighter-rouge">lparwwpn</code> into that project.</p>

<p>While we’re on the subject of displaying WWPNs, here is a recent post from <a href="https://twitter.com/cgibbo" target="_blank">Chris Gibson</a> on <a href="https://gibsonnet.net/blog/cgaix/html/Displaying_WWPN_information_on_Power10_Systems.html" target="_blank">Displaying WWPN information on Power10 Systems</a>.</p>]]></content><author><name></name></author><category term="hmc" /><category term="hmc" /><category term="scripting" /><category term="shell" /><category term="shell-scripting" /><category term="storage" /><summary type="html"><![CDATA[There are several ways to find the WWPNs for a virtual fibre channel adapter. You can log into the individual LPAR’s, get them from the Hardware Management Console (HMC), or from another asset discovery tool that may contain this data.]]></summary></entry><entry><title type="html">AIX mksysb creation date</title><link href="https://blog.kristijan.org/posts/AIX-mksysb-creation/" rel="alternate" type="text/html" title="AIX mksysb creation date" /><published>2022-07-24T00:00:00+10:00</published><updated>2022-07-27T16:46:17+10:00</updated><id>https://blog.kristijan.org/posts/AIX%20mksysb%20creation</id><content type="html" xml:base="https://blog.kristijan.org/posts/AIX-mksysb-creation/"><![CDATA[<p>Something that I do quite frequently is verify that I have a valid mksysb image for the AIX LPAR that I’m about to make changes on (for example, before applying a service pack). You can do this from the AIX LPAR itself using the <code class="language-plaintext highlighter-rouge">nimclient</code> command.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre><span class="gp">kristijan@aix13 #</span><span class="w"> </span>nimclient <span class="nt">-l</span> <span class="nt">-L</span> <span class="nt">-t</span> mksysb aix13 | <span class="nb">grep </span>aix13
<span class="go">aix13_220720_img     mksysb
aix13_220713_img     mksysb
</span><span class="gp">kristijan@aix13 #</span><span class="w"> </span>nimclient <span class="nt">-l</span> <span class="nt">-l</span> aix13_220720_img
<span class="go">aix13_220720_img:
   class         = resources
   type          = mksysb
   creation_date = Wed Jul 20 00:17:25 2022
   source_image  = aix13
   arch          = power
   Rstate        = ready for use
   prev_state    = unavailable for use
   location      = /mksysb/aix13/aix13_220720_img
   version       = 7
   release       = 2
   mod           = 5
   oslevel_r     = 7200-05
   oslevel_s     = 7200-05-04-2220
   alloc_count   = 0
   server        = master
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>In my AIX environment, I define a “valid” mksysb as one that was created within the last 2 weeks. Anything created after that date I’d be hesitant in restoring from. Parsing the <code class="language-plaintext highlighter-rouge">creation_date</code> with a shell script isn’t all that elegant. The python <a href="https://docs.python.org/3/library/datetime.html" target="_blank">datetime</a> module allows us to parse this easily.</p>

<p>The script does assume (on line 18) that your NIM mksysb resource names contain the hostname you’re running the script from.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/env python3
#
# Check that there is at least one mksysb for the client, and
# that the creation date of the mksysb is not older than 15 days
</span>
<span class="kn">import</span> <span class="n">sys</span>
<span class="kn">import</span> <span class="n">socket</span>
<span class="kn">import</span> <span class="n">subprocess</span>
<span class="kn">from</span> <span class="n">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>

<span class="c1"># Get hostname
</span><span class="n">hostname</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="nf">gethostname</span><span class="p">()</span>

<span class="c1"># Get current time
</span><span class="n">current_time</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="nf">now</span><span class="p">()</span>

<span class="c1"># Create list of mksysb resources from the NIM server
</span><span class="n">nim_mksysb_list</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="nf">check_output</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">/usr/sbin/nimclient -l -L -t mksysb </span><span class="si">{</span><span class="n">hostname</span><span class="si">}</span><span class="s"> | /usr/bin/awk </span><span class="sh">'</span><span class="s">/</span><span class="si">{</span><span class="n">hostname</span><span class="si">}</span><span class="s">/{{ print $1 }}</span><span class="sh">'"</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="sh">'</span><span class="s">utf-8</span><span class="sh">'</span><span class="p">).</span><span class="nf">split</span><span class="p">()</span>
<span class="c1"># If the subprocess above returns no values, the result is a
# single item list with an empty string. Let's strip that out.
</span><span class="n">nim_mksysb_list</span> <span class="o">=</span> <span class="nf">filter</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">nim_mksysb_list</span><span class="p">)</span>

<span class="c1"># Parse list of NIM mksysb backups and compare creation date
</span><span class="k">if</span> <span class="n">nim_mksysb_list</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">mksysb</span> <span class="ow">in</span> <span class="n">nim_mksysb_list</span><span class="p">:</span>
        <span class="n">mksysb_creation_time</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="nf">check_output</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">/usr/sbin/nimclient -l -l </span><span class="si">{</span><span class="n">mksysb</span><span class="si">}</span><span class="s"> | /usr/bin/awk -F = </span><span class="sh">'</span><span class="s">/creation_date/{{ print $2 }}</span><span class="sh">'"</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="sh">'</span><span class="s">utf-8</span><span class="sh">'</span><span class="p">).</span><span class="nf">strip</span><span class="p">()</span>
        <span class="n">mksysb_creation_time</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="nf">strptime</span><span class="p">(</span><span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">mksysb_creation_time</span><span class="p">),</span> <span class="sh">'</span><span class="s">%c</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">elapsed</span> <span class="o">=</span> <span class="n">current_time</span> <span class="o">-</span> <span class="n">mksysb_creation_time</span>
        <span class="k">if</span> <span class="n">elapsed</span><span class="p">.</span><span class="n">days</span> <span class="o">&lt;</span> <span class="mi">15</span><span class="p">:</span>
            <span class="c1"># mksysb found on NIM and is not older than 15 days
</span>            <span class="n">sys</span><span class="p">.</span><span class="nf">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="c1"># List is empty, no mksysb backups on NIM.
</span>    <span class="n">sys</span><span class="p">.</span><span class="nf">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="c1"># If we've made it this far, all mksysb's are older than 15 days
</span><span class="n">sys</span><span class="p">.</span><span class="nf">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The above script will return the following exit codes:</p>

<table>
  <thead>
    <tr>
      <th>Exit code</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0</code></td>
      <td>mksysb found and is not older than 15 days</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1</code></td>
      <td>no mksysb found</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">2</code></td>
      <td>all mksysbs found are older than 15 days</td>
    </tr>
  </tbody>
</table>

<p>The use of exit codes to determine the validity of a mksysb is because its intended use is part of a larger pipeline of checks that occur before an AIX LPAR is patched. It forms one of many pre-checks that are run on an AIX LPAR before it’s deemed healthy to be patched.</p>]]></content><author><name></name></author><category term="aix" /><category term="python" /><category term="scripting" /><category term="shell" /><category term="shell-scripting" /><summary type="html"><![CDATA[Something that I do quite frequently is verify that I have a valid mksysb image for the AIX LPAR that I’m about to make changes on (for example, before applying a service pack). You can do this from the AIX LPAR itself using the nimclient command.]]></summary></entry><entry><title type="html">Migrating from SDDPCM to AIXPCM (the easy way)</title><link href="https://blog.kristijan.org/posts/Migrating-from-SDDPCM-to-AIXPCM/" rel="alternate" type="text/html" title="Migrating from SDDPCM to AIXPCM (the easy way)" /><published>2018-07-30T00:00:00+10:00</published><updated>2022-06-04T15:45:50+10:00</updated><id>https://blog.kristijan.org/posts/Migrating%20from%20SDDPCM%20to%20AIXPCM</id><content type="html" xml:base="https://blog.kristijan.org/posts/Migrating-from-SDDPCM-to-AIXPCM/"><![CDATA[<p>For a while now, IBM have diverted their efforts in storage multipathing from SDDPCM to the <a href="https://www-01.ibm.com/support/docview.wss?uid=ssg1S1010218" target="_blank">default AIX PCM</a>. This brings a few advantages, but specifically for me, it means the driver is now updated as part of the AIX system maintenance, and is no longer something I need to maintain separately. All significant functionality that SDDPCM provides, can now be provided by the default AIX PCM driver. Additionally, SDDPCM is not supported on POWER 9 hardware.</p>

<p>For those currently using SDDPCM, removing the driver can be somewhat complicated, and even more so when the boot LUN (rootvg LUN) is being managed by SDDPCM. Buried deep in the Multipath Subsystem Device Driver Users Guide is a command called <code class="language-plaintext highlighter-rouge">manage_disk_drivers</code>. The <code class="language-plaintext highlighter-rouge">manage_disk_drivers</code> command can be used to display a list of storage families, and the driver that manages or supports each family. The command also allows us to easily switch (with a reboot if you boot from an SDDPCM managed device) the driver from SDDPCM to AIXPCM (or vice versa). Below I detail how to switch from SDDPCM to AIXPCM when using LUN’s presented to the host via SVC.</p>

<h2 id="existing-driver-manging-ibmsvc">Existing driver manging IBMSVC</h2>

<p>From the man page for <code class="language-plaintext highlighter-rouge">manage_disk_drivers</code></p>

<blockquote>
  <p>If the present driver attribute is set to NO_OVERRIDE, the AIX operating system selects an alternate path control module (PCM), such as Subsystem Device Driver Path Control Module (SDDPCM), if it is installed.</p>
</blockquote>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>manage_disk_drivers <span class="nt">-l</span>
<span class="go">Device              Present Driver        Driver Options
2810XIV             AIX_AAPCM             AIX_AAPCM,AIX_non_MPIO
DS4100              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4200              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4300              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4500              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4700              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4800              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS3950              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS5020              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DCS3700             AIX_APPCM             AIX_APPCM
DCS3860             AIX_APPCM             AIX_APPCM
DS5100/DS5300       AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS3500              AIX_APPCM             AIX_APPCM
XIVCTRL             MPIO_XIVCTRL          MPIO_XIVCTRL,nonMPIO_XIVCTRL
2107DS8K            NO_OVERRIDE           NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
IBMFlash            NO_OVERRIDE           NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
IBMSVC              NO_OVERRIDE           NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="switch-to-using-aixpcm">Switch to using AIXPCM</h2>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>manage_disk_drivers <span class="nt">-d</span> IBMSVC <span class="nt">-o</span> AIX_AAPCM
<span class="go"> ********************** ATTENTION *************************
  For the change to take effect the system must be rebooted
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>After the reboot, you will now see AIX_AAPCM as the present driver being used.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>manage_disk_drivers <span class="nt">-l</span>
<span class="go">Device              Present Driver        Driver Options
2810XIV             AIX_AAPCM             AIX_AAPCM,AIX_non_MPIO
DS4100              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4200              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4300              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4500              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4700              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS4800              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS3950              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS5020              AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DCS3700             AIX_APPCM             AIX_APPCM
DCS3860             AIX_APPCM             AIX_APPCM
DS5100/DS5300       AIX_SDDAPPCM          AIX_APPCM,AIX_SDDAPPCM
DS3500              AIX_APPCM             AIX_APPCM
XIVCTRL             MPIO_XIVCTRL          MPIO_XIVCTRL,nonMPIO_XIVCTRL
2107DS8K            NO_OVERRIDE           NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
IBMFlash            NO_OVERRIDE           NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
IBMSVC              AIX_AAPCM             NO_OVERRIDE,AIX_AAPCM,AIX_non_MPIO
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>From here, you can do one of two things. Leave the SDDPCM driver installed, as this will allow for easy rollback should you experience performance issues, or other driver related problems. Or completely remove the SDDPCM driver from the LPAR.</p>

<p>A few things to keep in mind.</p>

<ul>
  <li>If you’ve modified the <code class="language-plaintext highlighter-rouge">queue_depth</code> attribute on the hdisk, this will be reset to the AIXPCM default of 20. There is already a <a href="https://www.ibm.com/developerworks/aix/library/au-aix-mpio/index.html" target="_blank">good write up</a> on best practises and considerations when working with the default AIXPCM driver.</li>
  <li>When using SDDPCM, you would have used the <code class="language-plaintext highlighter-rouge">pcmpath</code> command to display and manage devices. As above, someone has already written a <a href="https://www.ibm.com/developerworks/aix/library/au-aix-multipath-io-mpio/index.html" target="_blank">good write up</a> on resiliency and problem determination, and some common <code class="language-plaintext highlighter-rouge">lsmpio</code> commands you’ll want to know.</li>
</ul>

<p>Taking the IBM recommendations into account, I’ll set the hdisk attributes accordingly.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>lsdev <span class="nt">-Cc</span> disk <span class="nt">-F</span> name | <span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> hdisk<span class="p">;</span> <span class="k">do </span>chdev <span class="nt">-l</span> <span class="k">${</span><span class="nv">hdisk</span><span class="k">}</span> <span class="nt">-a</span> <span class="nv">queue_depth</span><span class="o">=</span>32 <span class="nt">-a</span> <span class="nv">reserve_policy</span><span class="o">=</span>no_reserve <span class="nt">-a</span> <span class="nv">algorithm</span><span class="o">=</span>shortest_queue <span class="nt">-P</span><span class="p">;</span> <span class="k">done</span>
<span class="go">hdisk0 changed
hdisk1 changed
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Another handy command, which isn’t related to the overall driver migration, is using <code class="language-plaintext highlighter-rouge">chdef</code> to change the default values of the predefined attributes in ODM. Any future LUN’s presented to the host will now have the <code class="language-plaintext highlighter-rouge">queue_depth</code>, <code class="language-plaintext highlighter-rouge">reserve_policy</code>, and <code class="language-plaintext highlighter-rouge">algorithm</code> set to the values I want.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>chdef <span class="nt">-a</span> <span class="nv">queue_depth</span><span class="o">=</span>32 <span class="nt">-c</span> disk <span class="nt">-s</span> fcp <span class="nt">-t</span> mpioosdisk
<span class="go">queue_depth changed
</span><span class="gp">#</span><span class="w"> </span>chdef <span class="nt">-a</span> <span class="nv">reserve_policy</span><span class="o">=</span>no_reserve <span class="nt">-c</span> disk <span class="nt">-s</span> fcp <span class="nt">-t</span> mpioosdisk
<span class="go">reserve_policy changed
</span><span class="gp">#</span><span class="w"> </span>chdef <span class="nt">-a</span> <span class="nv">algorithm</span><span class="o">=</span>shortest_queue <span class="nt">-c</span> disk <span class="nt">-s</span> fcp <span class="nt">-t</span> mpioosdisk
<span class="go">algorithm changed
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="rollback">Rollback</h2>

<p>Should you need to go back to using SDDPCM as the driver, and haven’t removed it, you can use <code class="language-plaintext highlighter-rouge">manage_disk_drivers</code> to flip back and reboot.</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="gp">#</span><span class="w"> </span>manage_disk_drivers <span class="nt">-d</span> IBMSVC <span class="nt">-o</span> NO_OVERRIDE
<span class="go"> ********************** ATTENTION *************************
 For the change to take effect the system must be rebooted
</span></pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name></name></author><category term="aix" /><category term="aix" /><category term="aixpcm" /><category term="sddpcm" /><category term="storage" /><summary type="html"><![CDATA[For a while now, IBM have diverted their efforts in storage multipathing from SDDPCM to the default AIX PCM. This brings a few advantages, but specifically for me, it means the driver is now updated as part of the AIX system maintenance, and is no longer something I need to maintain separately. All significant functionality that SDDPCM provides, can now be provided by the default AIX PCM driver. Additionally, SDDPCM is not supported on POWER 9 hardware.]]></summary></entry><entry><title type="html">HMC Elastic CoD detail function</title><link href="https://blog.kristijan.org/posts/HMC-Elastic-CoD-detail-function/" rel="alternate" type="text/html" title="HMC Elastic CoD detail function" /><published>2015-11-19T00:00:00+11:00</published><updated>2024-01-17T16:21:26+11:00</updated><id>https://blog.kristijan.org/posts/HMC%20Elastic%20CoD%20detail%20function</id><content type="html" xml:base="https://blog.kristijan.org/posts/HMC-Elastic-CoD-detail-function/"><![CDATA[<p>IBM have created a <a href="https://www-304.ibm.com/support/customercare/ss/escod/home" target="_blank">self-service portal</a> for its customers to allow them to request their own Elastic Capacity on Demand codes for their registered systems. In my time using the new website, the codes have been generated and sent to me via email on average between 30 &amp; 45 minutes. This significantly reduces not only the time taken to get new codes posted to the <a href="https://www-912.ibm.com/pod/pod" target="_blank">POD website</a>, but also eliminates the process of having to reach out to your IBM representative to request them from the COD office in the USA. The website does require a number of fields to be filled in for the code to be generated automatically:</p>

<ul>
  <li>System type</li>
  <li>System serial number</li>
  <li>Anchor card CCIN</li>
  <li>Anchor card serial number</li>
  <li>Anchor card unique identifier</li>
  <li>Resource identifier</li>
  <li>Activate resources</li>
  <li>Sequence number</li>
  <li>Entry check</li>
</ul>

<p>All this information can be gathered from either the HMC GUI or the CLI. Preferring to work on the CLI, I’ve written a function (inspiration from Brian Smith) that collects and generates all the data the website requires in a nice to read format (well, nicer to read than what’s presented via the <code class="language-plaintext highlighter-rouge">lscod</code> command).</p>

<div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="rouge-code"><pre><span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span><span class="nb">source </span>onoffdetails
<span class="go"> 
</span><span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span>onoffdetails
<span class="go">Usage: onoffdetails [managed system] [mem | proc]
 
</span><span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span>onoffdetails 9119-FHB-SN1234567 mem
<span class="go"> 
Memory details for 9119-FHB-SN1234567
 
                   System type : 9119
          System serial number : 12-34567
              Anchor card CCIN : 52C4
     Anchor card serial number : 00-236D000
 Anchor card unique identifier : 316405567831037C
           Resource identifier : D973
            Activate resources : 0540
               Sequence number : 0046
                   Entry check : A3
 
</span><span class="gp">kristijan@hmc:~&gt;</span><span class="w"> </span>onoffdetails 9119-FHB-SN1234567 proc
<span class="go"> 
Processor details for 9119-FHB-SN1234567
 
                   System type : 9119
          System serial number : 12-34567
              Anchor card CCIN : 52C4
     Anchor card serial number : 00-236D000
 Anchor card unique identifier : 316405567831037C
           Resource identifier : D971
            Activate resources : 0450
               Sequence number : 0045
                   Entry check : A1
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>Function code is below, you just need to copy it over to the HMC, and then source it after you’ve logged in.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="rouge-code"><pre><span class="c"># Script: onoffdetails</span>
<span class="c">#</span>
<span class="c"># Usage: Gathers all the details required to self request On/Off</span>
<span class="c">#        Capacity on Demand from IBM's self-service portal.</span>
<span class="c">#        (https://www-304.ibm.com/support/customercare/ss/escod/home)</span>
<span class="c">#</span>
<span class="c"># Change log:</span>
<span class="c">#    Date       Who                   Comment</span>
<span class="c">#    ----       --                    -------</span>
<span class="c">#    18/11/15   Kristian Milos        Initial write.</span>
<span class="c">#</span>
onoffdetails <span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$# </span><span class="nt">-lt</span> 2 <span class="o">]</span><span class="p">;</span> <span class="k">then
       </span><span class="nb">printf</span> <span class="s2">"Usage: onoffdetails [managed system] [mem | proc]</span><span class="se">\n</span><span class="s2">"</span>
<span class="k">else
       </span><span class="nv">COUNT</span><span class="o">=</span>0
       <span class="nv">ERROR</span><span class="o">=</span>0
       <span class="k">while </span><span class="nb">read </span>SYSTEM<span class="p">;</span> <span class="k">do
              if</span> <span class="o">[</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then
                     </span><span class="nv">COUNT</span><span class="o">=</span><span class="k">$((</span>COUNT <span class="o">+</span><span class="m">1</span><span class="k">))</span>
              <span class="k">fi
       done</span> &lt; &lt;<span class="o">(</span>lssyscfg <span class="nt">-r</span> sys <span class="nt">-F</span> <span class="s2">"name"</span><span class="o">)</span>
       <span class="k">if</span> <span class="o">[</span> <span class="k">${</span><span class="nv">COUNT</span><span class="k">}</span> <span class="nt">-eq</span> 0 <span class="o">]</span><span class="p">;</span> <span class="k">then
              </span><span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">ERROR:  System not found: </span><span class="nv">$1</span><span class="se">\n\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"Known managed systems:</span><span class="se">\n</span><span class="s2">"</span>
              lssyscfg <span class="nt">-r</span> sys <span class="nt">-F</span> name
              <span class="nv">ERROR</span><span class="o">=</span>1
       <span class="k">fi
 
       if</span> <span class="o">[[</span> <span class="nv">$2</span> <span class="o">=</span> <span class="s2">"mem"</span> <span class="o">||</span> <span class="nv">$2</span> <span class="o">=</span> <span class="s2">"proc"</span> <span class="o">&amp;&amp;</span> <span class="k">${</span><span class="nv">ERROR</span><span class="k">}</span> <span class="o">!=</span> 1 <span class="o">]]</span><span class="p">;</span> <span class="k">then
              </span><span class="nv">SYSTEM</span><span class="o">=</span><span class="nv">$1</span>
              <span class="nv">RESOURCE</span><span class="o">=</span><span class="nv">$2</span>
 
              <span class="nv">sys_type</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> sys_type<span class="si">)</span>
              <span class="nv">sys_serial_num</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> sys_serial_num<span class="si">)</span>
              <span class="nv">anchor_card_ccin</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> anchor_card_ccin<span class="si">)</span>
              <span class="nv">anchor_card_serial_num</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> anchor_card_serial_num<span class="si">)</span>
              <span class="nv">anchor_card_unique_id</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> anchor_card_unique_id<span class="si">)</span>
              <span class="nv">resource_id</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> resource_id<span class="si">)</span>
              <span class="nv">activated_resources</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> activated_resources<span class="si">)</span>
              <span class="nv">sequence_num</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> sequence_num<span class="si">)</span>
              <span class="nv">entry_check</span><span class="o">=</span><span class="si">$(</span>lscod <span class="nt">-m</span> <span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span> <span class="nt">-t</span> code <span class="nt">-r</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="nt">-c</span> onoff <span class="nt">-F</span> entry_check<span class="si">)</span>
 
              <span class="k">if</span> <span class="o">[</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="o">==</span> <span class="s2">"mem"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
                     </span><span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">Memory details for </span><span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span><span class="se">\n\n</span><span class="s2">"</span>
              <span class="k">elif</span> <span class="o">[</span> <span class="k">${</span><span class="nv">RESOURCE</span><span class="k">}</span> <span class="o">==</span> <span class="s2">"proc"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
                     </span><span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">Processor details for </span><span class="k">${</span><span class="nv">SYSTEM</span><span class="k">}</span><span class="se">\n\n</span><span class="s2">"</span>
              <span class="k">fi
              </span><span class="nb">printf</span> <span class="s2">"                   System type : </span><span class="k">${</span><span class="nv">sys_type</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"          System serial number : </span><span class="k">${</span><span class="nv">sys_serial_num</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"              Anchor card CCIN : </span><span class="k">${</span><span class="nv">anchor_card_ccin</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"     Anchor card serial number : </span><span class="k">${</span><span class="nv">anchor_card_serial_num</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">" Anchor card unique identifier : </span><span class="k">${</span><span class="nv">anchor_card_unique_id</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"           Resource identifier : </span><span class="k">${</span><span class="nv">resource_id</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"            Activate resources : </span><span class="k">${</span><span class="nv">activated_resources</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"               Sequence number : </span><span class="k">${</span><span class="nv">sequence_num</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
              <span class="nb">printf</span> <span class="s2">"                   Entry check : </span><span class="k">${</span><span class="nv">entry_check</span><span class="k">}</span><span class="se">\n</span><span class="s2">"</span>
       <span class="k">else
              </span><span class="nb">printf</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">Usage: onoffdetails [managed system] [mem | proc]</span><span class="se">\n</span><span class="s2">"</span>
       <span class="k">fi
fi</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name></name></author><category term="hmc" /><category term="cod" /><category term="elastic-capacity-on-demand" /><category term="hmc" /><category term="scripting" /><category term="shell" /><category term="shell-scripting" /><summary type="html"><![CDATA[IBM have created a self-service portal for its customers to allow them to request their own Elastic Capacity on Demand codes for their registered systems. In my time using the new website, the codes have been generated and sent to me via email on average between 30 &amp; 45 minutes. This significantly reduces not only the time taken to get new codes posted to the POD website, but also eliminates the process of having to reach out to your IBM representative to request them from the COD office in the USA. The website does require a number of fields to be filled in for the code to be generated automatically:]]></summary></entry></feed>