Automating Baremetal Node Creation for Ironic

Sometime your shell scripts get out of control. Sometimes you are proud of them. Sometimes….both.

I need to be able to re-add a bunch of nodes to an OpenStack cluster on a regular basis. Yes, I could do this with Ansible, but, well, Ansible is great for doing something via SSH, and this just needs to be done here and now. So shell is fine.

This started as a one liner, and got a bit bigger.

This is a utility script that I keep modifying as I need new things from it. I have not cleaned it up or anything, but I find it works OK as is and is not too big that I lose sight of what it is doing.

It reads a csv file that has the list of nodes in it. The order of fields is

name,ipmi_ip, mac1, mac2,resource-class

The second MAC address is ignored for now.

#! /usr/bin/bash 
#set -x
 
 
check_enroll(){
    ironic_host_name=$1
    ironic_ipmi_address=$2
    ironic_pxe_interface_mac=$3
 
    openstack baremetal node show  $ironic_host_name 2>&1 > /dev/null
 
    if [ $? -eq 0 ]
    then
	echo  $ironic_host_name  already exists
	return 0
    else
	echo  $ironic_host_name  does not yet  exist
	return 1	
    fi
}
 
 
ironic_enroll(){
    ironic_host_name=$1
    ironic_ipmi_address=$2
    ironic_pxe_interface_mac=$3
    ironic_resource_name=$4   
 
    echo "ironic_host_name: " $ironic_host_name
    echo "ironic ipmi interface: " $ironic_ipmi_address
    echo "ironic pxe interface mac address: " $ironic_pxe_interface_mac
 
    openstack baremetal node show  $ironic_host_name 2>&1 > /dev/null
 
    if [ $? -eq 0 ]
    then
	echo  $ironic_host_name  already exists
	return [0]
    fi
    echo enrolling  $ironic_host_name
set -x
    openstack baremetal node create \
        --driver ipmi \
        --name ${ironic_host_name} \
        --driver-info ipmi_username=${IPMI_USERNAME} \
        --driver-info ipmi_password=${IPMI_PASSWD} \
        --driver-info ipmi_address=${ironic_ipmi_address} \
        --driver-info ipmi_terminal_port=8901 \
        --resource-class $ironic_resource_name \
        --property cpus=1 \
        --property memory_mb=512 \
        --property local_gb=1 \
        --property cpu_arch=arm64 \
        --property capabilities='boot_mode:uefi' \
        --driver-info deploy_kernel=${IRONIC_DEPLOY_KERNEL} \
        --driver-info deploy_ramdisk=${IRONIC_DEPLOY_INITRD}
set +x
    # Add this to enable console
    #       --console-interface ipmitool-socat \	
    #       --deploy-interface iscsi \
	#       --deploy-interface direct \
	#       --raid-interface agent \
 
    sleep 10
 
    NODE_UUID=$(openstack baremetal node list | grep ${ironic_host_name} | awk '{print $2}' | tr '\012' ' ' | awk '{print $1}')
    echo "*** IRONIC NODE UUID = " ${NODE_UUID} " ***"
 
    echo "*** IRONIC Baremetal node show" ${NODE_UUID} " ***"
    openstack baremetal node show ${NODE_UUID}
 
    echo "*** IRONIC Baremetal node console enable" ${NODE_UUID} " ***"
    openstack baremetal node console enable ${NODE_UUID}
 
    echo "*** IRONIC Creating baremetal port added for node " ${NODE_UUID} " ***"
    openstack baremetal port create ${ironic_pxe_interface_mac} --node ${NODE_UUID}
 
    sleep 10
 
    echo "*** IRONIC baremetal node validate " ${NODE_UUID} " ***"
    openstack baremetal node validate ${NODE_UUID}
 
    sleep 10
 
    echo "*** IRONIC baremetal node manage " ${NODE_UUID} " ***"
    openstack baremetal node manage ${NODE_UUID}
 
    sleep 10
 
    echo "*** IRONIC baremetal node inspect " ${NODE_UUID} " ***"
    openstack baremetal node inspect ${NODE_UUID}
 
    sleep 10
 
    echo "*** IRONIC Baremetal node show" ${NODE_UUID} " ***"
    openstack baremetal node show ${NODE_UUID}
 
    echo "*** IRONIC Baremetal node provide" ${NODE_UUID} " ***"
    openstack baremetal node provide ${NODE_UUID}
 
    echo "*** IRONIC Baremetal node show" ${NODE_UUID} " ***"
    openstack baremetal node show ${NODE_UUID}
 
    # Show Hypervisor Stats
    echo "*** OpenStack Hypervisor stats show ***"
    openstack hypervisor stats show
 
    echo "*** OpenStack Hypervisor show " ${NODE_UUID} " ***"
    openstack hypervisor show ${NODE_UUID}
} 
 
 
ipmi_check(){
    ironic_host_name=$1
    ironic_ipmi_address=$2
    ironic_pxe_interface_mac=$3
    echo  ipmitool -H $ironic_ipmi_address -U $IPMI_USERNAME -I lanplus -P $IPMI_PASSWD  power status
    ipmitool -H $ironic_ipmi_address -U $IPMI_USERNAME -I lanplus -P $IPMI_PASSWD  power status
}
 
 
IPMI_USERNAME=ADMIN
IPMI_PASSWD=`cat ipmi_passwd.txt`
PROJECT_DIR=$(pwd)
DEPLOY_KERNEL='ironic-deploy-kernel'
DEPLOY_INITRD='ironic-deploy-initrd'
 
 
IRONIC_DEPLOY_KERNEL=$( openstack image show ${DEPLOY_KERNEL} -f value -c id )
IRONIC_DEPLOY_INITRD=$( openstack image show ${DEPLOY_INITRD} -f value -c id )
 
echo "Ironic Deploy Kernel: " ${IRONIC_DEPLOY_KERNEL}
echo "Ironic Deploy Initrd: " ${IRONIC_DEPLOY_INITRD}
 
 
 
#input='jades.csv'
#input='mystiques.csv'
input='nodes.csv'
 
while IFS= read -r line
do
 
  IFS=', ' read -r -a array <<< "$line"
  echo Processing ${array[0]}
  check_enroll ${array[0]} ${array[1]} ${array[2]}
 
  if [ $? -eq 1 ]
  then     
      ipmi_check ${array[0]} ${array[1]} ${array[2]}
      ironic_enroll ${array[0]} ${array[1]} ${array[2]} ${array[4]}
  fi
 
done < "$input"

If I were to rework this, I would unroll the loop, and perform all of the same actions first; create the nodes, then port, validate etc. That would avoid the need for the sleep commands when doing it in bulk. However, for just adding a single node, it would break things, and that is more important right now.

Here is my current nodes.csv file.

mystique01-r097,10.76.97.185,98:03:9B:AD:49:0C,98:03:9B:AD:49:0D,baremetal-mystique
jade01-r097,10.76.97.173,1c:34:da:71:01:66,1c:34:da:71:01:67,baremetal-jade2
jade02-r097,10.76.97.174,1c:34:da:51:a0:8c,1c:34:da:51:a0:8d,baremetal-jade2
jade03-r097,10.76.97.175,0c:42:a1:52:1d:8c,0c:42:a1:52:1d:8d,baremetal-jade2
jade04-r097,10.76.97.176,1c:34:da:51:d6:c0,1c:34:da:51:d6:c1,baremetal-jade2
jade05-r097,10.76.97.177,98:03:9b:ad:67:20,98:03:9b:ad:67:21,baremetal-jade2
jade06-r097,10.76.97.178,1c:34:da:5a:c7:b0,1c:34:da:5a:c7:b1,baremetal-jade2
jade07-r097,10.76.97.179,98:03:9b:ad:67:38,98:03:9b:ad:67:39,baremetal-jade2
jade08-r097,10.76.97.180,1c:34:da:72:95:4e,1c:34:da:72:95:4f,baremetal-jade2
jade09-r097,10.76.97.181,b8:59:9f:c7:5c:6e,b8:59:9f:c7:5c:6f,baremetal-jade2
jade10-r097,10.76.97.182,98:03:9b:ad:7e:7c,98:03:9b:ad:7e:7d,baremetal-jade2
jade11-r097,10.76.97.183,0C:42:A1:45:3D:24,0C:42:A1:45:3D:25,baremetal-jade2
jade12-r097,10.76.97.184,B8:59:9F:AC:15:4C,B8:59:9F:AC:15:4D,baremetal-jade2


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.