maas-autobuilder/manage-maas-nodes.sh
Arif Ali efab2d3628
Updates on configs
* Add comments to the default.config file
* move the node_count to the default.config, this will allow to use
  customised value if needed
* If pod-console-logging tag is to be added, then add correctly,
  Otherwise, if we are adding fresh pods after tag creation, the pods
  will fail to add. This also allows for other cases to be fulfilled if
  required
2020-12-31 12:47:34 +00:00

442 lines
14 KiB
Bash
Executable File

#!/bin/bash
# set -x
. functions.sh
# Storage type
storage_format="raw"
# Models for nic and storage
nic_model="virtio"
stg_bus="scsi"
# Time between building VMs
build_fanout=60
maas_assign_networks()
{
maas_auto_assign_networks $1
}
# Attempts to auto assign all the networks for a host
# Note: This only works straight after a commissioning of a machine
maas_auto_assign_networks()
{
system_id=$1
# Grabs all the interfaces that are attached to the system
node_interfaces=$(maas ${maas_profile} interfaces read ${system_id} \
| jq ".[] | {id:.id, name:.name, mode:.links[].mode, subnet:.links[].subnet.id, vlan:.vlan.vid }" --compact-output)
# This for loop will go through all the interfaces and enable Auto-Assign
# on all ports
for interface in ${node_interfaces}
do
int_id=$(echo $interface | jq ".id" | sed s/\"//g)
subnet_id=$(echo $interface | jq ".subnet" | sed s/\"//g)
mode=$(echo $interface | jq ".mode" | sed s/\"//g)
vlan=$(echo $interface | jq ".vlan" | sed s/\"//g)
# Although the vlan would have been set the discovered vlan wouldn't,
# and therefore link[] and discovery[] list won't exist. So we grab
# the subnet details from subnets that have the vlan assigned/discovered
# at commissioning stage
if [[ $subnet_id == null ]] ; then
subnet_line=$(maas admin subnets read | jq ".[] | {subnet_id:.id, vlan:.vlan.vid, vlan_id:.vlan.id}" --compact-output | grep "vlan\":$vlan,")
subnet_id=$(echo $subnet_line | jq .subnet_id | sed s/\"//g)
fi
# If vlan is the external network, then we want to grab IP via DHCP
# from the external network. Other networks would be auto mode
if [[ $vlan -eq $external_vlan ]] && [[ $mode != "dhcp" ]]; then
new_mode="DHCP"
elif [[ $mode != "auto" ]] && [[ $mode != "dhcp" ]] ; then
new_mode="AUTO"
fi
# Then finally set link details for all the interfaces that haven't
# been configured already
if [[ $new_mode != "AUTO" ]] || [[ $new_mode != "DHCP" ]]; then
assign_network=$(maas ${maas_profile} interface link-subnet ${system_id} ${int_id} mode=${new_mode} subnet=${subnet_id})
fi
done
}
# Calls the 3 functions that creates the VMs
create_vms() {
install_deps
maas_login
create_storage
build_vms
}
# Calls the 3 functions that creates the VMs
create_juju() {
install_deps
maas_login
create_storage "juju"
build_vms "juju"
}
# Calls the functions that destroys and cleans up all the VMs
wipe_vms() {
install_deps
maas_login
destroy_vms
}
# Fixes all the networks on all the VMs
network_auto()
{
install_deps
maas_login
for ((virt="$node_start"; virt<=node_count; virt++)); do
printf -v virt_node %s-%02d "$compute" "$virt"
system_id=$(maas_system_id ${virt_node})
maas_auto_assign_networks ${system_id} &
done
wait
}
commission_vm()
{
system_id=$1
commission_machine=$(maas ${maas_profile} machine commission ${system_id})
# Ensure that the machine is in ready state before the next step
ensure_machine_in_state ${system_id} "Ready"
maas_auto_assign_networks ${system_id}
}
recommission_vms()
{
install_deps
maas_login
for ((virt="$node_start"; virt<=node_count; virt++)); do
printf -v virt_node %s-%02d "$compute" "$virt"
system_id=$(maas_system_id ${virt_node})
commission_vm ${system_id} &
sleep ${build_fanout}
done
wait
}
# Creates the disks for all the nodes
create_storage() {
# To keep a track of how many juju VMs we have created
only_juju="false"
node_count_bak=$node_count
if [[ $1 == "juju" ]] ; then
node_count=0
if [[ $juju_count -lt 1 ]] ; then
echo "WARNING: requested only create juju, but juju_count = ${juju_count}"
return 0
fi
fi
for ((virt="$node_start"; virt<=node_count; virt++)); do
printf -v virt_node %s-%02d "$compute" "$virt"
# Create th directory where the storage files will be located
mkdir -p "$storage_path/$virt_node"
# For all the disks that are defined in the array, create a disk
for ((disk=0;disk<${#disks[@]};disk++)); do
file_name="$storage_path/$virt_node/$virt_node-d$((${disk} + 1)).img"
if [[ ! -f $file_name ]] ; then
/usr/bin/qemu-img create -f "$storage_format" "${file_name}" "${disks[$disk]}"G &
fi
done
done
for ((juju=1; juju<=juju_count; juju++)); do
printf -v virt_node %s-%02d "$hypervisor_name-juju" "$juju"
# Create th directory where the storage files will be located
mkdir -p "$storage_path/$virt_node"
file_name="$storage_path/$virt_node/$virt_node.img"
if [[ ! -f $file_name ]] ; then
/usr/bin/qemu-img create -f "$storage_format" ${file_name} "${juju_disk}"G &
fi
done
node_count=$node_count_bak
wait
}
# The purpose of this function is to stop, release the nodes and wipe the disks
# to save space, and then so that the machines in MAAS can be re-used
wipe_disks() {
juju_total=1
doing_juju="false"
for ((virt="$node_start"; virt<=node_count; virt++)); do
if [[ $juju_total -le $juju_count ]] ; then
printf -v virt_node %s-%02d "$hypervisor_name-juju" "$juju_total"
doing_juju="true"
(( virt-- ))
(( juju_total++ ))
else
printf -v virt_node %s-%02d "$compute" "$virt"
doing_juju="false"
fi
system_id=$(maas_system_id ${virt_node})
# Release the machine in MAAS
release_machine=$(maas ${maas_profile} machine release ${system_id})
# Ensure that the machine is in ready state before the next step
ensure_machine_in_state ${system_id} "Ready"
# Stop the machine if it is running
# It's probably stopped anyway as per the release above
virsh --connect qemu:///system shutdown "$virt_node"
# Remove the disks
if [[ $doing_juju == "true" ]] ; then
rm -rf "$storage_path/$virt_node/$virt_node.img"
else
for ((disk=0;disk<${#disks[@]};disk++)); do
rm -rf "$storage_path/$virt_node/$virt_node-d$((${disk} + 1)).img" &
done
fi
done
# Re-create the storage again from scratch
create_storage
wait
}
machine_exists()
{
node_name=$1
virsh_machine=$(virsh list --all --name | grep ${node_name})
if [[ $virsh_machine != "" ]] ; then
macaddr=$(virsh domiflist ${node_name} | grep br0 | awk '{print $5}')
echo $macaddr
else
echo "false"
fi
}
# Builds the VMs from scratch, and then adds them to MAAS
build_vms() {
# To keep a track of how many juju VMs we have created
juju_total=1
only_juju="false"
if [[ $1 == "juju" ]] ; then
only_juju="true"
if [[ $juju_count -lt 1 ]] ; then
echo "WARNING: requested only create juju, but juju_count = ${juju_count}"
return 0
fi
fi
for ((virt="$node_start"; virt<=node_count; virt++)); do
# Based on the bridges array, it will generate these amount of MAC
# addresses and then create the network definitions to add to
# virt-install
macaddr=()
network_spec=""
# Based on the type of network we are using we will assign variables
# such that this can be either bridge or network type
if [[ $network_type == "bridge" ]] ; then
net_prefix="bridge"
net_type=(${bridges[@]})
elif [[ $network_type == "network" ]] ; then
net_prefix="network"
net_type=(${networks[@]})
fi
# Now define the network definition
for ((mac=0;mac<${#net_type[@]};mac++)); do
macaddr+=($(printf '52:54:00:%02x:%02x:%02x\n' "$((RANDOM%256))" "$((RANDOM%256))" "$((RANDOM%256))"))
network_spec+=" --network=$net_prefix="${net_type[$mac]}",mac="${macaddr[$mac]}",model=$nic_model"
done
if [[ $juju_total -le $juju_count ]] ; then
printf -v virt_node %s-%02d "$hypervisor_name-juju" "$juju_total"
ram="$juju_ram"
vcpus="$juju_cpus"
node_type="juju"
network_spec="--network=$net_prefix="${net_type[0]}",mac="${macaddr[0]}",model=$nic_model"
disk_spec="--disk path=$storage_path/$virt_node/$virt_node.img"
disk_spec+=",format=$storage_format,size=${juju_disk},bus=$stg_bus,io=native,cache=directsync"
# So that we have the right amount of VMs
(( virt-- ))
(( juju_total++ ))
# This will ensure that we only create the juju VMs
[[ $only_juju == "true" ]] && [[ $juju_total -gt $juju_count ]] && virt=$(( $node_count + 1 ))
else
printf -v virt_node %s-%02d "$compute" "$virt"
# Based on the variables in hypervisor.config, we define the variables
# for ram and cpus. This also allows a number of control nodes that
# can be defined as part of full set of nodes.
ram="$node_ram"
vcpus="$node_cpus"
node_type="compute"
if [[ $virt -le $control_count ]] ; then
ram="$control_ram"
vcpus="$control_cpus"
node_type="control"
fi
# Based on the disks array, it will create a definition to add these
# disks to the VM
disk_spec=""
for ((disk=0;disk<${#disks[@]};disk++)); do
disk_spec+=" --disk path=$storage_path/$virt_node/$virt_node-d$((${disk} + 1)).img"
disk_spec+=",format=$storage_format,size=${disks[$disk]},bus=$stg_bus,io=native,cache=directsync"
done
fi
# Check to see if the libvirt machine already exists. If it exists
# then just use the same one again and commission in MAAS
check_machine=$(machine_exists ${virt_node})
if [[ $check_machine != "false" ]] ; then
macaddr=$check_machine
maas_add_node ${virt_node} ${macaddr} ${node_type} &
sleep ${build_fanout}
continue
fi
# Creates the VM with all the attributes given
virt-install -v --noautoconsole \
--print-xml \
--autostart \
--boot network,hd,menu=on \
--video qxl,vram=256 \
--channel spicevmc \
--name "$virt_node" \
--ram "$ram" \
--vcpus "$vcpus" \
--console pty,target_type=serial \
--graphics spice,clipboard_copypaste=no,mouse_mode=client,filetransfer_enable=off \
--cpu host-passthrough,cache.mode=passthrough \
--controller "$stg_bus",model=virtio-scsi,index=0 \
$disk_spec \
$network_spec > "$virt_node.xml" &&
# Create the Vm based on the XML file defined in the above command
virsh define "$virt_node.xml"
# Start the VM
virsh start "$virt_node" &
# Call the maas_add_node function, this will add the node to MAAS
maas_add_node ${virt_node} ${macaddr[0]} ${node_type} &
# Wait some time before building the next, this helps with a lot of DHCP requests
# and ensures that all VMs are commissioned and deployed.
sleep ${build_fanout}
done
wait
}
destroy_vms() {
juju_total=1
doing_juju="false"
for ((virt="$node_start"; virt<=node_count; virt++)); do
if [[ $juju_total -le $juju_count ]] ; then
printf -v virt_node %s-%02d "$hypervisor_name-juju" "$juju_total"
doing_juju="true"
(( virt-- ))
(( juju_total++ ))
else
printf -v virt_node %s-%02d "$compute" "$virt"
doing_juju="false"
fi
# If the domain is running, this will complete, else throw a warning
virsh --connect qemu:///system destroy "$virt_node"
# Actually remove the VM
virsh --connect qemu:///system undefine "$virt_node"
# Remove the three storage volumes from disk
if [[ $doing_juju = "true" ]] ; then
virsh vol-delete --pool "$virt_node" "$virt_node.img"
else
for ((disk=0;disk<${#disks[@]};disk++)); do
virsh vol-delete --pool "$virt_node" "$virt_node-d$((${disk} + 1)).img"
done
fi
# Remove the folder storage is located
rm -rf "$storage_path/$virt_node/"
sync
# Remove the XML definitions for the VM
rm -f "$virt_node.xml" \
"/etc/libvirt/qemu/$virt_node.xml" \
"/etc/libvirt/storage/$virt_node.xml" \
"/etc/libvirt/storage/autostart/$virt_node.xml"
# Now remove the VM from MAAS
system_id=$(maas_system_id ${virt_node})
delete_machine=$(maas ${maas_profile} machine delete ${system_id})
done
}
show_help() {
echo "
-c Creates everything
-w Removes everything
-d Releases VMs, Clears Disk
-n Updates all the networks on all VMs
-r Recommission all VMs
-j Only create juju VM
"
}
# Initialise the configs
read_configs
while getopts ":cwjdnr" opt; do
case $opt in
c)
create_vms
;;
w)
wipe_vms
;;
d)
wipe_disks
;;
n)
network_auto
;;
r)
recommission_vms
;;
j)
create_juju
;;
\?)
printf "Unrecognized option: -%s. Valid options are:" "$OPTARG" >&2
show_help
exit 1
;;
esac
done