The problem is well known. We can do the best possible Ansible automation, but if nobody uses it, it is dead! Ansible integrates very well with many systems like enterprise batch scheduling, monitoring, or any web APIs. But many AIX colleagues learned to use “the running man” smitty in the 90s and it is still the most favorite AIX tool. Mine too. I want to integrate Ansible into smitty!
Before we start
My plan is to integrate the Ansible playbooks I wrote to deploy Linux LPARs (first, second). This is not the first time I do custom SMIT menus for my tasks. The documentation is available on the IBM’s site. You can find there more information than I could ever write in the article.
Before you start making any changes, please (PLEASE!) back up your smitty ODM. It is easy:
# mkdir /my/smit/backup
# cp /usr/lib/objrepos/sm_* /my/smit/backup
If you did something wrong, you can restore it by copying the files back:
# cp /my/smit/backup/sm_* /usr/lib/objrepos/
That’s said, let’s start!
smitty ODM
As you already know the whole smitty configuration is in the ODM. But not at the standard ODM location in /etc/objrepos
. That’s why if you issue the commands like odmget
, they don’t show you anything. You must prepend them with the variable ODMDIR
like:
# ODMDIR=/usr/lib/objrepos odmget sm_name_hdr
You can export the variable if you plan to work with the smitty ODM, but I prefer to write it in every command. If you export the variable, it can affect many AIX commands that rely on ODM.
There are only 4 ODM classes for smitty:
sm_menu_opt
sm_name_hdr
sm_cmd_hdr
sm_cmd_opt
In this example, I use only 3 of them - sm_menu_opt
, sm_cmd_opt
, and sm_cmd_hdr
.
To create new entries in the classes, you must create a text file with the information. You don’t need several files, you can pack everything into one file. My file is called linux.odm
.
Step 1. Find the place for our tasks
Our first task is to find a suitable place for our future smitty menus. You start smitty
(or direct smitty nim
in my case) and look through menus.
My first pick for the definition of Linux installation resources is - smitty nim → Perform NIM Administration Tasks → Manage Resources. Here I’d like to have a task to define NFS share with Linux installation code. After I’ve found the place, I press F8 (or Esc-8 - Image). It shows me the current fast path, I can use to get into the menu directly.
The same fast path I will use in my ODM file to define a new task. We are ready to write our first ODM entry:
sm_menu_opt:
id = "nim_res"
id_seq_num = "100"
next_id = "nim_define_linux_res"
text = "Define Linux installation resources"
text_msg_file = ""
text_msg_set = ""
text_msg_id = ""
next_type = "d"
alias = "n"
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
As you see most of the fields are empty. If you want to add localization and some help, you can fill them with your message files. I usually add some help but this is another topic. As always you can read more about it in IBM’s documentation.
What is important here are the fields with values:
id
- we define our parent fast path, where we want to add our task.id_seq_name
- the sequence number to determine the order of the tasks in the menu. Check the already-defined numbers (ODMDIR=/usr/lib/objrepos odmget -q "id=nim_res" sm_menu_opt | grep id_seq_num
) and choose a number that is not in use. I chose 100 and it will be guaranteed the last entry.next_id
- this is the fast path to our future task. It must be unique in the ODM. Otherwise smitty can run something else ;-)text
- will be shown as a menu title in case no message files are defined or no message is found.next_type
-d
means that there will be a dialog screen if the user selects the menu.alias
- we don’t define any aliases.
You can check if everything works as it should by adding the values into ODM:
# ODMDIR=/usr/lib/objrepos odmadd linux.odm
If you find the new menu entry in smitty nim_res, then you did everything right!
Don’t forget to restore the smitty ODM after every test. Otherwise you will get too many entries in the menu!
Step 2. Add dialog to the menu
We defined earlier that we have a dialog named “nim_define_linux_res
”. Even if it is a dialog we must first define a header for the dialog and the command which will run when the user presses Enter. It is done in the class sm_cmd_hdr:
sm_cmd_hdr:
id = "nim_define_linux_res"
option_id = "nim_linux_res_opt"
has_name_select = "n"
name = "Define Linux installation resources"
name_msg_file = ""
name_msg_set = ""
name_msg_id = ""
ask = "y"
exec_mode = "n"
ghost = "n"
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
cmd_to_exec = "\
x() {
:
}
x"
Let’s take a look at some of the options:
option_id
- defines where to find all possible entries on the dialog screen. We will add them later, but we must choose a unique name for all of them.has_name_select
- if it is set to “y” the user must first select some value before going to the dialog. We don’t have it, so I set it to “n”.ask
- if the option is set to “y”, smit asks for additional confirmation before starting the command. I always find it good to get such confirmation.exec_mode
- is how smit should work with the command’s output. “n” means the output will be shown after the command completes its run. There are many different options. Many years ago I decided that “n” is the best default option for me. But if a job runs too long, it is time to change the option to the default “p”.ghost
- is to define some dialog like “ghost” dialog, that exists but is not shown. Our dialog is a “normal” one. The option must be set to “n”.cmd_to_exec
- this is the command that runs after the user presses Enter. As you see I defined an empty function namedx
and run it. This is a very easy way to test what happens if I select different options. Note that I end the first line with the backslash (\) right after the quote (“) to show that this is a multi-line value. There are no more backslashes in the command. The next important note - I set the last quote (“) just afterx
. Don’t add any newlines or spaces after the name of the function. Smitty will add the space and your options afterx
on its own.
Step 3. Add dialog options
The dialog options go into the class sm_cmd_opt
like below:
sm_cmd_opt:
id = "nim_linux_res_opt"
id_seq_num = "010"
name = "Linux distribution"
name_msg_file = ""
name_msg_set = ""
name_msg_id = ""
op_type = "r"
entry_type = "n"
entry_size = "0"
required = "y"
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
disp_values = "Red Hat Enterprise Linux,SUSE Linux Enterprise,Ubuntu"
aix_values = "rhel,sles,ubuntu"
id
- is the name we defined in the previous stepid_seq_num
- similar to the menus this is the order how the options are displayed on the dialogrequired
- if the user must enter (or choose like in the example above) some value for the fieldop_type
- the type of dialog option. It can be “n” (or empty) for a normal input line. It can be “l” if we want to generate a list of the options with some command. Or it can be “r” if we provide all possible selects indisp_values
andaix_values
.entry_type
- depends onop_type
. Because we provide all possible values, we have “n” here which means “not editable”. Otherwise, you can use “t” for text, “#” for numbers, “x” for hexadecimal numbers, “f” for file paths, and “r” for raw text. Depending on theentry_type
you can limit the field by settingentry_size
.
Now you know how to define the dialog options and we define the rest of them.
sm_cmd_opt:
id = "nim_linux_res_opt"
id_seq_num = "020"
name = "Linux version"
name_msg_file = ""
name_msg_set = ""
name_msg_id = ""
op_type = ""
entry_type = "t"
entry_size = "8"
required = "y"
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
sm_cmd_opt:
id = "nim_linux_res_opt"
id_seq_num = "030"
name = "Path to ISO image"
name_msg_file = ""
name_msg_set = ""
name_msg_id = ""
op_type = ""
entry_type = "f"
entry_size = "255"
required = "y"
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
Command to run
I didn’t show you the command in Step 2. But it is not the secret. I simply do some checks and start ansible-playbook there:
cmd_to_exec = "\
x() {
lt=$1
lver=$2
iso=$3
if [[ -z $lver ]] ; then
print -u2 -- "No distribution version is specified"
exit 1
fi
if [[ -z $iso ]] ; then
print -u2 -- "No path to ISO image is specified"
exit 1
fi
if [[ ! -f $iso ]] ; then
print -u2 -- "ISO image $iso does not exist"
exit 1
fi
cd /nim/linux/playbooks
/opt/freeware/bin/ansible-playbook prepare_linux_resources.yml -e linux_type="$lt" -e linux_version="$lver" -e iso_image="$iso"
}
x"
You can do it better!
Time to test!
After you finish writing the ODM file, add the entries into the smitty ODM and check that it works:
# ODMDIR=/usr/lib/objrepos odmadd linux.odm
# smitty
If something goes wrong, restore the smitty ODM from your backup and try it again!
Special offer for readers of the Power DevOps Newsletter!
Have you ever wondered how I manage thousands of IBM Power LPARs while simultaneously crafting this newsletter? It might sound like a daunting task, but it’s not just a dream! Imagine the possibility of juggling your responsibilities effortlessly and having more time to focus on what you love. If this resonates with you, don’t miss out on my exclusive offer just for Power DevOps Newsletter readers! Let’s unlock your potential together!
The second playbook?
I think the procedure is very easy and clear.
you search the place for your menu
you define the dialog header and the command to run
you define the dialog options
The best way to learn is to make as many mistakes as you can.
This is the reason why the second playbook will be your homework! ;-)
If something goes wrong, you can restore the ODM from the backup.
Your old-fashioned AIX colleagues will be happy.
One last thing - my own smitty
If you don’t want to change IBM-provided smitty menus, you can always create your own smitty.
Create a new directory for your smitty ODM database
# mkdir /etc/mitty
Copy the original smitty ODM into the directory
# cp /usr/lib/objrepos/sm_* /etc/mitty
Delete the original data from your ODM’s copy
# for i in cmd_hdr cmd_opt menu_opt name_hdr ; do ODMDIR=/etc/mitty odmdelete -o sm_${i} ; done
Create your own ODM definitions file like we did above. Please note that all your menus must belong to
top_menu
. Or you can create many different menus you need for your work.
# vi my.odm
Define the root node for your menu
sm_menu_opt:
id = "__ROOT__"
id_seq_num = "0"
next_id = "top_menu"
text = "My MITTY"
next_type = "m"
alias = ""
text_msg_file = ""
text_msg_set = ""
text_msg_id = ""
help_msg_id = ""
help_msg_loc = ""
help_msg_base = ""
help_msg_book = ""
Add your definitions to your ODM
# ODMDIR=/etc/mitty odmadd my.odm
Test that it works
# smitty -o /etc/mitty
Create your own commands
# alias mitty='smitty -o /etc/mitty'
# alias mit='smit -o /etc/mitty'
# alias mmit='msmit -o /etc/mitty'
mitty
is the pun to the name of my friend Dmitry Mironov. Because of the well-known political situation, he is not the IBM Champion in name anymore, but he is still the real IBM Champion doing a great job for the big Russian-speaking IBM Power community.
Have fun creating your own AIX SMIT menus!
Andrey
Hi, I am Andrey Klyachkin, IBM Champion and IBM AIX Community Advocate. It means I don’t work for IBM. Over the last 20 years, I worked with many different IBM Power customers all over the world both on-premise and in the cloud. I specialize in automating IBM Power infrastructures making them even more robust and agile. I co-authored several IBM Redbooks and IBM Power certifications. I am an active Red Hat Certified Engineer and Instructor.
Follow me on LinkedIn, Twitter, and YouTube.
Meet me at events like IBM TechXchange, Common Europe Congress, and GSE Germany’s IBM Power Working group sessions.