Deploying AIX eFixes using NIM at scale with Puppet
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).
Prepare NIM resources
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 here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(nim01) # lsnim -l 7200TL5SP4_lpp
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
(nim01) # ls -l /nim/lpp/7200TL5SP4_lpp/emgr/ppc
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
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 here.
1
2
3
4
5
6
7
8
9
10
(nim01) # lsnim -l 7200TL5SP4_emgr
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
Contents of /nim/bundles/7200TL5SP4_emgr
1
2
3
E:IJ39876s3a.220506.epkg.Z
E:IJ41139m4a.220809.epkg.Z
E:1121201a.220804.epkg.Z
Installing fixes on AIX hosts
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.
Push
Installing a single fix from a NIM lpp_source resource.
1
2
3
4
5
6
7
(nim01) # nim -o cust -a lpp_source=7200TL5SP4_lpp -a filesets=E:1121201a.220804.epkg.Z aix01
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER LABEL OPERATION RESULT
=========== ============== ================= ==============
1 1121201a INSTALL SUCCESS
Return Status = SUCCESS
Installing multiple fixes from a NIM installp_bundle resource.
1
2
3
4
5
6
7
8
9
(nim01) # nim -o cust -a lpp_source=7200TL5SP4_lpp -a installp_bundle=7200TL5SP4_emgr aix01
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
Pull
Installing a single fix from a NIM lpp_source resource.
1
2
3
4
5
6
7
(aix01) # nimclient -o cust -a lpp_source=7200TL5SP4_lpp -a filesets=E:1121201a.220804.epkg.Z
Initializing log /var/adm/ras/emgr.log ...
EPKG NUMBER LABEL OPERATION RESULT
=========== ============== ================= ==============
1 1121201a INSTALL SUCCESS
Return Status = SUCCESS
Installing multiple fixes from a NIM installp_bundle resource.
1
2
3
4
5
6
7
8
9
(aix01) # nimclient -o cust -a lpp_source=7200TL5SP4_lpp -a installp_bundle=7200TL5SP4_emgr
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
Deploying fixes at scale with Puppet Tasks
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.
Task metadata
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
{
"description": "A task for installing/uninstalling AIX fixes.",
"parameters": {
"install": {
"description": "Set to true to install efix, or set to false to uninstall efix.",
"type": "Boolean"
},
"lpp_source": {
"description": "NIM lpp_source containing the efix(s).",
"type": "String[1]"
},
"fix_name": {
"description": "Name of a single efix to be installed/uninstalled.\n\tWhen installing, the 'fix_name' is the name of the package (e.g. IJ31191m1a.210322.epkg.Z).\n\tWhen uninstalling, the 'fix_name' is the name of the label (e.g. IJ31191m1a).",
"type": "Optional[String[1]]"
},
"installp_bundle": {
"description": "Name of installp_bundle to use when installing multiple efixes.",
"type": "Optional[String[1]]"
},
"reboot": {
"description": "If true, the system is rebooted after installing/uninstalling the efix(s).",
"type": "Boolean"
}
},
"puppet_task_version": 1,
"supports_noop": false
}
Task
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
#!/opt/puppetlabs/puppet/bin/ruby
#
# A task for installing/uninstalling AIX fixes
require 'puppet'
require 'json'
# Set FACTERLIB so custom facts resolve
Puppet.initialize_settings
ENV['FACTERLIB'] = Puppet.settings['factpath']
require 'facter'
# Sanity check that we're an AIX host
if Facter.value(:operatingsystem) == "AIX" then
params = JSON.parse(STDIN.read)
install = params['install']
lpp_source = params['lpp_source']
fix_name = params['fix_name']
installp_bundle = params['installp_bundle']
reboot = params['reboot']
if install then
# Check if we have either a fix_name or installp_bundle set
if params.key?("installp_bundle") then
fix = "installp_bundle=#{installp_bundle}"
elsif params.key?("fix_name") then
fix = "filesets=E:#{fix_name}"
else
print "You need to specify either a fix_name or installp_bundle."
exit(2)
end
# Install efix(s)
system("/usr/sbin/nimclient", "-o", "cust", "-a", "lpp_source=#{lpp_source}", "-a", "#{fix}")
if $?.exitstatus != 0
print "efix failed to install."
exit(2)
end
else
# Uninstall efix
if params.key?("fix_name") then
system("/usr/sbin/nimclient", "-o", "cust", "-a", "lpp_source=#{lpp_source}", "-a", "filesets=E:#{fix_name}", "-a", "installp_flags=u")
if $?.exitstatus != 0
print "efix failed to uninstall."
exit(2)
end
else
print "You need to specify a fix_name to uninstall."
end
end
# Reboot
if reboot then
system("/usr/bin/echo '/usr/sbin/shutdown -r +3' | /usr/bin/at now")
end
else
print "Task only supported on AIX."
exit(1)
end
Running the Task
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
$ puppet task show patch::aix_efix
patch::aix_efix - A task for installing/uninstalling AIX fixes.
USAGE:
$ puppet task run patch::aix_efix install=<value> lpp_source=<value> reboot=<value> [fix_name=<value>] [installp_bundle=<value>] <[--nodes, -n <node-names>] | [--query, -q <'query'>]>
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.
$ puppet task run patch::aix_efix install=true lpp_source=7200TL5SP4_lpp reboot=false installp_bundle=7200TL5SP4_emgr -n aix01
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