<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Strava LTD</title>
	<atom:link href="https://strava.ltd/feed/" rel="self" type="application/rss+xml" />
	<link>https://strava.ltd</link>
	<description>Services of IT infrastructure, AIX Operating System and IBM pSeries, IBM Power, PureStorage PureArrays and DevOps Ansible, Terraform, Infrastructure as a Code</description>
	<lastBuildDate>Tue, 03 Mar 2026 20:26:08 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://strava.ltd/wp-content/uploads/2024/02/cropped-logo_strava-140_transparent-32x32.png</url>
	<title>Strava LTD</title>
	<link>https://strava.ltd</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>AIX: Welcome to the ODM</title>
		<link>https://strava.ltd/2025/09/12/aix-welcome-to-the-odm/</link>
		
		<dc:creator><![CDATA[nicolas]]></dc:creator>
		<pubDate>Fri, 12 Sep 2025 08:30:30 +0000</pubDate>
				<category><![CDATA[aix]]></category>
		<category><![CDATA[C]]></category>
		<guid isPermaLink="false">https://strava.ltd/?p=310</guid>

					<description><![CDATA[AIX friend, aren&#8217;t you proud to be a big boy and to tease your linux kiddos with your big ODM? Let&#8217;s make them cry then. Today we are not going to f@ck around. We use C language baby, yeah! Like many things in C, we start defining a structure, but this structure is a required IBM stuff and it looks this way, store that in a file called create_class.cre: Then, let&#8217;s define some functions in an odm.h file: And then the implementation of these functions in odm.c: Alright, that looks sexy but what do I do with all this mess]]></description>
										<content:encoded><![CDATA[<p>AIX friend, aren&#8217;t you proud to be a big boy and to tease your linux kiddos with your big ODM? Let&#8217;s make them cry then. Today we are not going to f@ck around. We use C language baby, yeah!</p>
<p>Like many things in C, we start defining a structure, but this structure is a required IBM stuff and it looks this way, store that in a file called create_class.cre:</p>
<pre class="brush: cpp; title: ; notranslate">
class mystuff {
  char		Customer&#x5B;100];
  int		ActivationDate;
  int		ExpirationDate;
  char		Key&#x5B;100];
  char		Product&#x5B;100];
  char		Version&#x5B;100];
};
</pre>
<p>Then, let&#8217;s define some functions in an odm.h file:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;odmi.h&gt;
#include &lt;errno.h&gt;
#include &lt;strings.h&gt;
#include &lt;time.h&gt;
#include &lt;unistd.h&gt;

#include &quot;create_class.h&quot;

typedef struct mystuff mystuff_t;

#define TRIAL_PERIOD  2592000

int create_odm_class();
int write_odm();
int check_odm_class();
mystuff_t *read_odm();

</pre>
<p>And then the implementation of these functions in odm.c:</p>
<pre class="brush: cpp; title: ; notranslate">
#include &quot;odm.h&quot;

#ifdef __PPC__

int create_odm_class() {
  char *error_message;

  if(DEBUG&gt;1) printf(&quot;Creation of class mystuff.\n&quot;);
  syslog(LOG_DEBUG, &quot;Creation of ODM class.&quot;);
  if(odm_create_class(mystuff_CLASS)!=0) {
    odm_err_msg ( odmerrno, &amp;error_message );
    if(DEBUG&gt;1) printf(&quot;Problem accessing ODM. %s&quot;, error_message);
    syslog(LOG_ERR, &quot;Problem accessing ODM. %s&quot;, error_message);
    return(1);
  }

  return(0);
}

int write_odm() {
  struct mystuff *data2write;
  data2write=(struct mystuff*)malloc(sizeof(struct mystuff));

  time_t now = time(NULL);

  data2write-&gt;ActivationDate = now;

  odm_add_obj(mystuff_CLASS, data2write);
  return(0);
}

int check_odm_class() {
  char *error_message;

  if(odm_mount_class(&quot;mystuff&quot;)==(CLASS_SYMBOL)-1) {
    odm_err_msg ( odmerrno, &amp;error_message );
    if(DEBUG&gt;1) printf(&quot;&#x5B;check_odm_class] Error searching for class mystuff #%d: %s\n&quot;, odmerrno, error_message);
    syslog(LOG_ERR, &quot;&#x5B;check_odm_class] Error searching for class mystuff #%d: %s&quot;, odmerrno, error_message);
    if(odmerrno==0) {
      create_odm_class();
      write_odm();
    } else {
      if(DEBUG) printf(&quot;&#x5B;create_odm_class] Class mystuff created successfully.\n&quot;);
      syslog(LOG_DEBUG, &quot;&#x5B;create_odm_class] Class mystuff created successfully.&quot;);
    }
  }

  return(0);
}

mystuff_t *read_odm() {
  struct tm ts;
  char buf&#x5B;80];
  mystuff_t *data2read;
  data2read=(struct mystuff*)malloc(sizeof(struct mystuff));

  odm_get_first(mystuff_CLASS, NULL, data2read);
  if(DEBUG&gt;1) {
    ts = *localtime((const time_t *)&amp;data2read-&gt;ActivationDate);
    strftime(buf, sizeof(buf), &quot;%a %Y-%m-%d %H:%M:%S %Z&quot;, &amp;ts);
    printf(&quot;\n&#x5B;read_odm] Activation Date: %ld &#x5B;%s]\n&quot;, data2read-&gt;ActivationDate, buf);
    printf(&quot;&#x5B;read_odm] Customer: %s\n&quot;, data2read-&gt;Customer);
    printf(&quot;&#x5B;read_odm] Key: %s\n&quot;, data2read-&gt;Key);
    printf(&quot;\n&quot;);
  }
  syslog(LOG_DEBUG, &quot;&#x5B;read_odm] Activation Date: %ld; Key: %s&quot;, data2read-&gt;ActivationDate, data2read-&gt;Key);

  return(data2read);
}
</pre>
<p>Alright, that looks sexy but what do I do with all this mess buddy!? That:</p>
<pre class="brush: cpp; title: ; notranslate">
int main(int argc, char **argv) {
  check_odm_class();
  return(0);
}
</pre>
<p>And this is already the time for compilation baby! Here is your Makefile:</p>
<pre class="brush: bash; title: ; notranslate">
CC=gcc
OS ?= $(shell uname -s)
CFLAGS=-g -ggdb -Wall 
LFLAGS=-L/opt/freeware/lib
LDFLAGS=-lodm -lerrlog -lm

SRC:= src

all: mystuff

src/create_class.o:
	/usr/bin/odmcreate -h src/create_class.cre
	$(CC) -g -ggdb  -c src/create_class.c -o src/create_class.o

%.o: $(SRC)/%.c
	$(CC) $(CFLAGS) -c $&lt; -o $@

mystuff: src/create_class.o src/odm.o
	$(CC) $(CFLAGS) $(LFLAGS) $(LDFLAGS) src/main.c src/create_class.o src/odm.o -o build/mystuff 

clean:
	\rm -f build/mystuff src/*.o .toc src/create_class.?

</pre>
<p>If you do not understand it all, do not call me, I am in holidays.<br />
So that means you can literally store anything in the ODM and access and read it back anytime with this set of functions. Be aware that anyone with ODM skills can access them also using the set of get_odm commands. So for sensitive informations, you will need to encrypt that.</p>
<p>Have fun! I&#8217;ll see you next time.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ansible: create Volume Groups &#038; filesystems on AIX</title>
		<link>https://strava.ltd/2025/09/12/ansible-volume-groups-filesystems-fun-on-aix/</link>
		
		<dc:creator><![CDATA[nicolas]]></dc:creator>
		<pubDate>Fri, 12 Sep 2025 07:45:40 +0000</pubDate>
				<category><![CDATA[ansible]]></category>
		<guid isPermaLink="false">https://strava.ltd/?p=294</guid>

					<description><![CDATA[Today we are going to create a Volume Group and a list of JFS2 filesystems programmatically using Ansible on an AIX 7.x system. Let&#8217;s not make you languish any further, here we go: - name: Create stuffvg and its filesystems hosts: target remote_user: root collections: - ibm.power_aix var: prefix: &#34;stuff&#34; tasks: - name: Be sure the wanted disks are usable with a cfgmgr ansible.builtin.shell: cfgmgr - name: Create &#34;{{ prefix }}vg&#34; ibm.power_aix.lvg: state: present vg_name: &#34;{{ prefix }}vg&#34; pvs: hdisk1 vg_type: scalable At this stage we already have a scalable Volume Group named stuffvg. Now, let&#8217;s add some filesystems in]]></description>
										<content:encoded><![CDATA[<p>Today we are going to create a Volume Group and a list of JFS2 filesystems programmatically using Ansible on an AIX 7.x system. Let&#8217;s not make you languish any further, here we go:</p>
<pre class="brush: yaml; title: ; notranslate">
- name: Create stuffvg and its filesystems
  hosts: target
  remote_user: root
  collections:
    - ibm.power_aix
  var:
    prefix: &quot;stuff&quot;

  tasks:
  - name: Be sure the wanted disks are usable with a cfgmgr
    ansible.builtin.shell: cfgmgr

  - name: Create &quot;{{ prefix }}vg&quot;
    ibm.power_aix.lvg:
      state: present
      vg_name: &quot;{{ prefix }}vg&quot;
      pvs: hdisk1
      vg_type: scalable

</pre>
<p>At this stage we already have a scalable Volume Group named stuffvg. Now, let&#8217;s add some filesystems in it but first thing first, we then need to create the jfs2log LV:</p>
<pre class="brush: yaml; title: ; notranslate">
  - name: Create the jfs2Log lv
    aix_lvol:
      vg: &quot;{{ prefix }}vg&quot; 
      lv: stuffj2log
      lv_type: jfs2log
      size: 128M

  - name: Logform the jfs2log
    ansible.builtin.shell: yes | /usr/sbin/logform -V jfs2 /dev/stuffj2log
</pre>
<p>Now we are ready to create our Logical Volumes:</p>
<pre class="brush: yaml; title: ; notranslate">
  - name: Create LVs
    aix_lvol:
      vg: &quot;{{ prefix }}vg&quot;
      lv: 	&quot;{{ item.name }}&quot;
      lv_type: 	&quot;{{ item.type }}&quot;
      size: 	&quot;{{ item.size }}&quot;
    loop:
      - { name: &#039;stuff_users&#039;,	type: &#039;jfs2&#039;, 	size: &#039;20G&#039; }
      - { name: &#039;stuffora19c&#039;,	type: &#039;jfs2&#039;, 	size: &#039;2G&#039; }
      - { name: &#039;stuff_ora&#039;, 	type: &#039;jfs2&#039;, 	size: &#039;3G&#039; }
</pre>
<p>Now it&#8217;s time to create JFS2 filesystems on our freshly made LV, and to mount them:</p>
<pre class="brush: yaml; title: ; notranslate">
 - name: Creation of JFS2 filesystems
    ibm.power_aix.filesystem:
      state:		present
      device: 	  	&quot;{{ item.device }}&quot;
      filesystem: 	&quot;{{ item.mountpoint }}&quot;
      fs_type:		jfs2
      auto_mount:	true
    loop:
      - { device: &#039;stuffora&#039;,	        mountpoint: &#039;/home/oracle&#039; }
      - { device: &#039;stuff_users&#039;,	mountpoint: &#039;/home/users&#039; }
      - { device: &#039;stuffora19c&#039;,	mountpoint: &#039;/home/oracle/product/v19c&#039; }

  - name: Mount FS
    ansible.builtin.shell: mount &quot;{{ item }}&quot;
    with_items:
      - &quot;/home/oracle&quot;
      - &quot;/home/users&quot;
      - &quot;/home/oracle/product/v19c&quot;
</pre>
<p>Last but not least, some exotic stuff to finish, as I know you are kind of that:</p>
<pre class="brush: yaml; title: ; notranslate">
  - name: chlv -x 3000 hd1
    ibm.power_aix.lvol:
      vg: rootvg
      lv: hd1
      extra_opts: &quot;-x 3000&quot;

  - name: Increase size of a filesystem
    ibm.power_aix.filesystem:
      filesystem: /home
      state: present
      attributes: size=25G
</pre>
<p>And here we are. No more excuse to create twice the same FS.</p>
<p>I&#8217;ll see you next time.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So you want an AIX versioned WPAR?</title>
		<link>https://strava.ltd/2025/09/05/so-you-want-an-aix-versioned-wpar/</link>
		
		<dc:creator><![CDATA[nicolas]]></dc:creator>
		<pubDate>Fri, 05 Sep 2025 15:41:54 +0000</pubDate>
				<category><![CDATA[virtualisation]]></category>
		<guid isPermaLink="false">https://strava.ltd/?p=232</guid>

					<description><![CDATA[You cannot get rid of your oldies but goodies AIX 5.x? No problemo, create an AIX versioned WPAR. In our example, we create an AIX5.3 on a AIX 7.2 host lpar: rendev -l hdisk1 -n aix53_rootvg mkwpar -D devname=aix53_rootvg rootvg=yes -C -B /mksysb/mksysb0139 -t -n aix53 -l -O &#x5B;...] Once created, you can then wait for the migration day with confidence. Once the source lpar has been shutdowned, configure the IP addresses into the wpar: chwpar -N interface=en0 address=10.30.191.130 netmask=255.255.255.0 aix53 chwpar -N interface=en0 address=10.30.191.131 netmask=255.255.255.0 aix53 chwpar -N interface=en0 address=10.30.191.132 netmask=255.255.255.0 aix53 chwpar -N interface=en1 address=10.30.194.130 netmask=255.255.255.0 aix53 chwpar]]></description>
										<content:encoded><![CDATA[<p>You cannot get rid of your oldies but goodies AIX 5.x? No problemo, create an AIX versioned WPAR. In our example, we create an AIX5.3 on a AIX 7.2 host lpar:</p>
<pre class="brush: plain; title: ; notranslate">
rendev -l hdisk1 -n aix53_rootvg
mkwpar -D devname=aix53_rootvg rootvg=yes -C -B /mksysb/mksysb0139 -t -n aix53 -l -O
&#x5B;...]
</pre>
<p>Once created, you can then wait for the migration day with confidence. Once the source lpar has been shutdowned, configure the IP addresses into the wpar:</p>
<pre class="brush: plain; title: ; notranslate">
chwpar -N interface=en0 address=10.30.191.130 netmask=255.255.255.0 aix53
chwpar -N interface=en0 address=10.30.191.131 netmask=255.255.255.0 aix53
chwpar -N interface=en0 address=10.30.191.132 netmask=255.255.255.0 aix53

chwpar -N interface=en1 address=10.30.194.130 netmask=255.255.255.0 aix53
chwpar -N interface=en1 address=10.30.194.131 netmask=255.255.255.0 aix53
chwpar -N interface=en1 address=10.30.194.132 netmask=255.255.255.0 aix53
</pre>
<p>You can do so for multiple addresses, including IP aliases into the wpar on the same physical interface/</p>
<p>To map new or migrated disks (by SAN for example), you can use this same chwpar command:</p>
<pre class="brush: plain; title: ; notranslate">
chwpar -D devname=hdisk2 devtype=disk aix53
chwpar -D devname=hdisk3 devtype=disk aix53
chwpar -D devname=hdisk4 devtype=disk aix53
</pre>
<p>Once the disks are added, login into the wpar using clogin, and pass a cfgmgr in order to load the newly mapped disks. You should then be able to import your Volume Group and or create a new one.</p>
<p>Have fun :/</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Disk pathes &#038; SCSI Reservations on AIX 7.x</title>
		<link>https://strava.ltd/2025/09/05/disk-pathes-scsi-reservations-on-aix-7-x/</link>
		
		<dc:creator><![CDATA[nicolas]]></dc:creator>
		<pubDate>Fri, 05 Sep 2025 14:28:34 +0000</pubDate>
				<category><![CDATA[storage]]></category>
		<guid isPermaLink="false">https://strava.ltd/?p=220</guid>

					<description><![CDATA[If your errpt is filling with disk errors on one specific path ID, there is a chance your disk is locked up by a single Path Reservation. In this case, you can query and clear this reservation if you are totally sure no other system is using the same locked disk: &#x5B;root@aixboix /root]# devrsrv -f -c release -l hdisk28 Device Reservation State Information ================================================== Device Name : hdisk28 Device Open On Current Host? : YES ODM Reservation Policy : NO RESERVE Device Reservation State : SINGLE PATH RESERVE Device is currently Open on this host by a process. Do you]]></description>
										<content:encoded><![CDATA[<p>If your errpt is filling with disk errors on one specific path ID, there is a chance your disk is locked up by a single Path Reservation. In this case, you can query and clear this reservation if you are totally sure no other system is using the same locked disk:</p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;root@aixboix /root]# devrsrv -f -c release -l hdisk28
Device Reservation State Information
==================================================
Device Name                     :  hdisk28
Device Open On Current Host?    :  YES
ODM Reservation Policy          :  NO RESERVE
Device Reservation State        :  SINGLE PATH RESERVE
Device is currently Open on this host by a process.
Do you want to continue y/n:y
The command was successful.
The reservation has been cleared on the device.
</pre>
<p>Simply.</p>
<p>Then, I advice to clear up the errpt logs and check few minutes later if no new error log appeared:</p>
<pre class="brush: plain; title: ; notranslate">&#x5B;root@aix ~]# errclear 0
&#x5B;root@aixbox ~]# 
</pre>
<p>Remember you can visualize your disk pathes ID, parents device, WWPN, LUN number and its status with the following lspah options:</p>
<pre class="brush: plain; title: ; notranslate">&#x5B;root@aix ~]# for D in `lspv | awk {&#039; print $1 &#039;}`; do echo $D: ; lspath -l $D -F&quot;path_id;connection:parent:path_status:status&quot; ; echo ;  done
hdisk130:
0;524a9376d185dd12,ca000000000000:fscsi4:Available:Enabled
1;524a9376d185dd02,ca000000000000:fscsi5:Available:Enabled

hdisk12:
0;524a9376d185dd12,e0000000000000:fscsi4:Available:Enabled
1;524a9376d185dd02,e0000000000000:fscsi5:Available:Enabled
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ansible: how to check a fileset version on AIX</title>
		<link>https://strava.ltd/2024/02/10/aix-monitoring-with-prometheus/</link>
		
		<dc:creator><![CDATA[nicolas]]></dc:creator>
		<pubDate>Sat, 10 Feb 2024 09:27:07 +0000</pubDate>
				<category><![CDATA[ansible]]></category>
		<category><![CDATA[aix]]></category>
		<category><![CDATA[lpp_facts]]></category>
		<guid isPermaLink="false">https://strava.ltd/?p=1</guid>

					<description><![CDATA[If you wonder or struggle to compare a fileset, or ptf, or package version on AIX, then you are on the right place. First thing first, let&#8217;s gather our filesets details in the ansible_facts: - name: Extract bos.mp64 fileset version ibm.power_aix.lpp_facts: filesets: - bos.adt.base - bos.adt.lib - bos.mp64 Then we extract the version string from the dict: - set_fact: version_string: &#34;{{ item.key }}&#34; loop: &#34;{{ ansible_facts.filesets&#x5B;&#039;bos.mp64&#039;].levels &#124; dict2items }}&#34; when: item.value.vrmf is defined register: version_fact - name: Check bos.mp64 version debug: msg: &#34;ifix #IJ04311 needs to be applied: bos.mp64 {{ version_string }}.&#34; when: &#34;&#039;bos.mp64&#039; in ansible_facts.filesets and version_string is version(&#039;7.1.5.43&#039;,]]></description>
										<content:encoded><![CDATA[
<p>If you wonder or struggle to compare a fileset, or ptf, or package version on AIX, then you are on the right place. First thing first, let&#8217;s gather our filesets details in the ansible_facts:</p>
<pre><pre class="brush: yaml; title: ; notranslate"> - name: Extract bos.mp64 fileset version
   ibm.power_aix.lpp_facts:
     filesets:
       - bos.adt.base
       - bos.adt.lib
       - bos.mp64</pre></pre>
<p><br />Then we extract the version string from the dict:</p>
<pre><pre class="brush: yaml; title: ; notranslate">  - set_fact:
      version_string: &quot;{{ item.key }}&quot;
    loop: &quot;{{ ansible_facts.filesets&#x5B;&#039;bos.mp64&#039;].levels | dict2items }}&quot;
    when: item.value.vrmf is defined
    register: version_fact

  - name: Check bos.mp64 version
    debug:
      msg: &quot;ifix #IJ04311 needs to be applied: bos.mp64 {{ version_string }}.&quot;
    when: &quot;&#039;bos.mp64&#039; in ansible_facts.filesets and version_string is version(&#039;7.1.5.43&#039;, &#039;&amp;amp;amp;lt;&#039;)&quot;
</pre></pre>
<p>And finally the playbook output:</p>
<pre><pre class="brush: plain; title: ; notranslate">ok: &#x5B;aixbox] =&amp;amp;amp;gt; 
(item=
  {&#039;key&#039;: &#039;7.1.5.43&#039;, 
   &#039;value&#039;: 
     {&#039;vrmf&#039;: 
       {&#039;ver&#039;: 7, &#039;rel&#039;: 1, &#039;mod&#039;: 5, &#039;fix&#039;: 43},
       &#039;state&#039;: &#039;committed&#039;,
       &#039;type&#039;: &#039;install&#039;,
       &#039;description&#039;: &#039;Base Operating System 64-bit Multiprocessor Runtime&#039;,
       &#039;emgr_locked&#039;: False,
       &#039;sources&#039;: &#x5B;&#039;/usr/lib/objrepos&#039;, &#039;/etc/objrepos&#039;]
       }
    }
) =&amp;amp;amp;gt; {&quot;ansible_facts&quot;: 
       {&quot;version_string&quot;: &quot;7.1.5.43&quot;},
       &quot;ansible_loop_var&quot;: &quot;item&quot;,
       &quot;changed&quot;: false,
       &quot;item&quot;: 
       {&quot;key&quot;: &quot;7.1.5.43&quot;,
        &quot;value&quot;: 
          {&quot;description&quot;: &quot;Base Operating System 64-bit Multiprocessor Runtime&quot;, 
           &quot;emgr_locked&quot;: false,
           &quot;sources&quot;: &#x5B;&quot;/usr/lib/objrepos&quot;, &quot;/etc/objrepos&quot;],          
           &quot;state&quot;: &quot;committed&quot;,
           &quot;type&quot;: &quot;install&quot;,
           &quot;vrmf&quot;: 
             {&quot;fix&quot;: 43, &quot;mod&quot;: 5, &quot;rel&quot;: 1, &quot;ver&quot;: 7}
          }
        }
      }

TASK &#x5B;Check bos.mp64 version]
skipping: &#x5B;aixbox] =&amp;amp;amp;gt; 
  {&quot;false_condition&quot;: 
    &quot;&#039;bos.mp64&#039; in ansible_facts.filesets and version_string is version(&#039;7.1.5.43&#039;, &#039;&amp;amp;amp;lt;&#039;)&quot;}</pre></pre>
<p> Yes, you are welcomed. ^^</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
