Skip to content

Instantly share code, notes, and snippets.

@ThinGuy
Created June 29, 2022 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ThinGuy/9fda64c8bebfe99df06e4a5db97aa762 to your computer and use it in GitHub Desktop.
Save ThinGuy/9fda64c8bebfe99df06e4a5db97aa762 to your computer and use it in GitHub Desktop.
Updated lxd-maas microcloud
#!/usr/bin/env bash
# vim: set et ts=2 sw=2 filetype=bash :
[[ $_ != $0 ]] || { printf "\n\e[2G\e[1mPlease source this script!\e[0m ( e.g. \"source ${BASH_SOURCE[0]}\" )\n\n"; sleep 1;exit; }
maas-microcloud-lxd() {
[[ -n ${FDEBUG} && ${FDEBUG} = true ]] && { set -x &>/dev/null; }
local DESC="${FUNCNAME}: Deploy a LXD Cluster via MAAS command line"
local CI_TZ='America/Los_Angeles'
local CI_LC='en_US.UTF-8'
local CI_TC=${CI_LC:3:2}
if [[ -n ${CI_TC} && $(curl -slSL -w %{http_code} -o /dev/null ${CI_TC,,}.archive.ubuntu.com) -eq 200 ]];then
local CI_CC=${CI_TC}
local CI_APT_MIRROR=${CI_CC,,}.archive.ubuntu.com
else
local CI_APT_MIRROR=archive.ubuntu.com
fi
local CI_PKG_UPG=true
local CI_PKG_UPD=true
local ENABLE_GPU=false
local BASE_TAG="microcloud-lxd"
local STORAGE_POOL_DEVICE=
local STORAGE_POOL_TYPE=file
local WAIT=false
local -a CI_PKG_LIST=(
bridge-utils
build-essential
jq
prips
squashfuse
unzip
zfsutils-linux
)
maas-microcloud-lxd_usage() {
printf "\n\e[2G${DESC}\n\n"
printf "\e[2G\e[1mUsage\e[0m: ${FUNCNAME%%_*} [-c <count>] [-t <tag>] [-d <distro>] (-p storage-pool block device)\n\n"
printf "\e[4G -c, --count\e[20GNumber of nodes (Min: 3) \n"
printf "\e[4G -t, --tag \e[20GExisting tag to use when selecting nodes\n"
printf "\e[4G -d, --distro\e[20GName of Ubuntu Distro (Default: bionic)\n"
printf "\e[4G -p, --pool-device\e[20GPhysical disk to use for Storage Pool (Optional: default uses file method)\n"
printf "\e[4G -m, --mtag\e[20GName of this microcloud (default: \"microcloud-lxd-<random 6 char str>\")\n"
printf "\e[4G -w, --wait\e[20GWait for nodes to finish deploying before exiting ${FUNCNAME%%_*}\n"
printf "\e[4G -h, --help\e[20GThis message\n"
printf "\n\n"
}
ARGS=$(getopt -o n:c:t:d:p:dhwm: -l count:,tag:,distro:,pool-device:,help,desc,wait,mtag: -n ${FUNCNAME} -- "$@")
eval set -- "$ARGS"
while true ; do
case "$1" in
-n|-c|--count) local COUNT=${2};shift 2;;
-t|--tag) local TAG=${2};local TAG=${TAG,,};shift 2;;
-m|--mtag) export MICROCLOUD_TAG=${2};local TAG=${TAG,,};shift 2;;
-d|--distro) local DISTRO=${2};local DISTRO=${DISTRO,,};shift 2;;
-p|--pool-device) local STORAGE_POOL_DEVICE=${2};local STORAGE_POOL_DEVICE=${STORAGE_POOL_DEVICE,,};local STORAGE_POOL_TYPE=device;shift 2;;
-w|--wait) local WAIT=true;shift 1;;
--desc) printf "\n\e[2G${DESC}\n";return 0;;
-h|--help) ${FUNCNAME}_usage;return 2;;
--) shift;break;;
esac
done
if [[ -f /snap/bin/maas ]];then
local MAAS_VER=$(snap info maas|awk '/^installed/{gsub(/~.*/,"",$2);print $2}')
else
command -v maas &>/dev/null || { printf "\n\n\e[2G\e[2G\e[38;2;255;255;0mSorry! \e[0m\e[38;2;0;255;0m maas-cli \e[0m\e[1m2.5+\e[0m is required for this demo.\n\e[9GPlease install and configure version MAAS 2.5 or later\n\n";return 1; }
[[ $(dpkg-query 2>/dev/null -s maas|grep -oP '(?<=Version: )[^?]{3}'|sed 's/\.//') -lt 25 ]] && { printf "\n\n\e[2G\e[2G\e[38;2;255;255;0mSorry! \e[0mMAAS \e[38;2;0;255;0m2.5\e[0m\e[1m+\e[0m is required for this demo.\n\e[9GYou are running version \e[38;2;255;255;0m$(dpkg-query -s maas|grep -oP '(?<=Version: )[^~]+')\e[0m\n\n";return 1; }
local MAAS_VER=$(dpkg-query 2>/dev/null -s maas|grep -oP '(?<=Version: )[^?]{3}'|sed 's/\.//')
fi
command -v jq &>/dev/null || sudo apt install jq -y
local OK='\u00A0\e[38;2;0;255;0m\u2713\e[0m\u00A0\n'
local FAILED='\u00A0\e[38;2;255;0;0m\u2718\u00A0\n'
printf -- "\n\e[1mMicro-cloud Demo - LXD\e[0m\n\n"
printf -- " - Powered by \e[1m$(lsb_release -ds)\e[0m${OK}\n"
printf -- " - Provisioning by \e[1mMAAS ${MAAS_VER}${OK}\n"
printf -- " - Featuring \e[1mLXD $(snap info lxd|awk '/installed:/{print $2}') with clustering\e[0m${OK}\n"
[[ -z ${MAAS_PROFILE} ]] && { read -srp "$(printf "Please enter your MAAS profile name: ")" MAAS_PROFILE_INPUT;local MAAS_PROFILE=$MAAS_PROFILE_INPUT; }
#Validation and error handling
local -a VALID_TAGS=($(maas ${MAAS_PROFILE} tags read|jq -r '.[].name'))
local -a VALID_DISTROS=($(maas ${MAAS_PROFILE} boot-resources read|jq -r '.[]|"\(select((.name|startswith("grub")|not) and (.name|startswith("ubuntu")) and (.name|startswith("pxe")|not)).name|sub("ubuntu/"; ""))"'|sort -uV))
# If not a physical disk, set storage pool to use a file
[[ ${STORAGE_POOL_TYPE} = device ]] && { printf "\e[3G- Storage Pool on Cluster Hosts will be using block device ${STORAGE_POOL_DEVICE} \n\n"; local STORAGE_POOL_TYPE=device; } || { local STORAGE_POOL_TYPE=file;local STORAGE_POOL_DEVICE="/var/snap/lxd/common/lxd/disks/local.img";printf "\e[3G- Storage Pool on Cluster Hosts will be file-based \n\n"; }
[[ ${COUNT} =~ ^[0-9]+$ ]] || { local COUNT=3;printf "\e[3G- Setting Node count to ${COUNT}\n\n"; }
[[ ${COUNT} =~ ^[0-9]+$ && ${COUNT} -lt 3 ]] && { local COUNT=3;printf "\e[3G- Minimum LXD Cluster node count is ${COUNT}. Setting Node count to ${COUNT}.\n\n"; }
[[ -z ${TAG} ]] && { printf "\e[2GERROR: No tag name given ${TAG}\n\n\e[2GValid tags are:\n";printf "\e[4G- %s\n" ${VALID_TAGS[@]};return 1; }
[[ -n ${TAG} && -n $(grep -P '(^|\s)\K'${TAG}'(?=\s|$)' <<< ${VALID_TAGS[@]}) ]] || { printf "\e[2GERROR: No tags exist named ${TAG}\n\n\e[2GValid tags are:\n";printf "\e[4G- %s\n" ${VALID_TAGS[@]};return 1; }
[[ -n ${TAG} ]] && { printf "\e[3G- Using tag \"${TAG}\" as primary machine constraint\n\n"; }
[[ -n ${DISTRO} ]] || { local DISTRO="bionic"; }
[[ -n ${DISTRO} && -n $(grep -P '(^|\s)\K'${DISTRO}'(?=\s|$)' <<< ${VALID_DISTROS[@]}) ]] || { printf "\e[2GERROR: invalid distro: ${DISTRO}\n\n\e[2GValid distros for LXD Clusters are:\n";printf "\e[4G- %s\n" ${VALID_DISTROS[@]};return 1; }
[[ -n ${DISTRO} ]] && { printf "\e[3G- Setting distro to ${DISTRO}\n\n"; }
printf "\n\e[3G- Gathering values from to use for setting up the lxd-cluster. Please wait..."
#Get values we'll be replacing in lxd-cluster script template
maas refresh
local MAAS_LIST="$(maas list|awk '/'${MAAS_PROFILE}'/')"
local MAAS_API=$(awk '{print $3}' <<< "${MAAS_LIST}")
local MAAS_IP=$(grep -oP '(?<=http://)[^:|^/]+' <<< "${MAAS_LIST}")
local MAAS_URL=$(grep -oP 'http://(?<=http://|https://)[^S]+S/' <<< "${MAAS_LIST}")
local MAAS_SUBNET=$(maas ${MAAS_PROFILE} subnets read|jq -r '.[]|select(.vlan.fabric_id==0).cidr')
local MAAS_DOMAIN=$(maas ${MAAS_PROFILE} domains read|jq -r '.[]|select((.authoritative==true) and .id==0).name')
# IFS=$'\n' && declare -ag MAAS_SSH_HOST_KEYS=($(maas ${MAAS_PROFILE} sshkeys read|jq -r '.[]|"\(.key)"'))
if [[ -n ${MAAS_API} && -n ${MAAS_URL} && -n ${MAAS_SUBNET} && -n ${MAAS_IP} && -n ${MAAS_DOMAIN} ]];then
printf "${OK}"
else
printf "${FAILED}\e[2GThere was an issue gathering lxd-cluster values from maas. Make you are running this while logged into the maas-cli. Quitting\n\n"
echo
for v in API URL SUBNET IP DOMAIN;do eval echo MAAS_$v=\$MAAS_$v;done
echo
return 1
fi
[[ ${COUNT} -eq 1 ]] && W= || W=s
if [[ ${STORAGE_POOL_TYPE} = device ]];then
printf "\n\e[3G- Finding ${COUNT} machine${W} :\n\e[5G- Marked as \"Ready\"\n\e[5G- Tagged with \"${TAG}\"\n"
local READY_TAGGED_MACHINES=($(maas ${MAAS_PROFILE} machines read|jq -r '.[]|select(.physicalblockdevice_set[].name|contains("'${STORAGE_POOL_DEVICE##*/}'"))|select((.tag_names[]|contains("'"${TAG}"'")) and .status == 4)|"\(.hostname):\(.system_id)"'|head -n${COUNT}|sort -V))
[[ ${#READY_TAGGED_MACHINES[@]} -lt 3 ]] && { printf "\e[2G\e[2G\e[38;2;255;255;0mSorry! \e[0mCould not find enough machines to create a LXD Cluster.\n\n\e[9GMachines Required: 3\n\e[9GMachines Found:\e[4C\e[38;2;255;0;0m${#READY_TAGGED_MACHINES[@]}\n\n";return 1; }
[[ ${#READY_TAGGED_MACHINES[@]} -lt ${COUNT} && ${#READY_TAGGED_MACHINES[@]} -ge 3 ]] && { read -erp "$(printf "\n\e[2G - Could only find ${#READY_TAGGED_MACHINES[@]} machine${W} with the ${TAG} tag. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
[[ ${#READY_TAGGED_MACHINES[@]} -lt ${COUNT} ]] && { read -erp "$(printf "\n\e[2G - Could only find ${#READY_TAGGED_MACHINES[@]} machines with the ${TAG} tag. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
local COUNT=${#READY_TAGGED_MACHINES[@]}
else
printf "\n\e[3G- Finding ${COUNT} machine${W} :\n\e[5G- Marked as \"Ready\"\e[5G- Tagged with \"${TAG}\"\n\e[5G- Has physical disk named ${STORAGE_POOL_DEVICE}\n"
local -a READY_TAGGED_MACHINES=($(maas ${MAAS_PROFILE} machines read|jq -r '.[]|select((.tag_names[]|contains("'"${TAG}"'")) and .status == 4)|"\(.hostname):\(.system_id)"'|head -n${COUNT}|sort -V))
[[ ${#READY_TAGGED_MACHINES[@]} -lt 3 ]] && { printf "\e[2G\e[2G\e[38;2;255;255;0mSorry! \e[0mCould not find enough machines to create a LXD Cluster.\n\n\e[9GMachines Required: 3\n\e[9GMachines Found:\e[4C\e[38;2;255;0;0m${#READY_TAGGED_MACHINES[@]}\n\n";return 1; }
[[ ${#READY_TAGGED_MACHINES[@]} -lt ${COUNT} && ${#READY_TAGGED_MACHINES[@]} -ge 3 ]] && { read -erp "$(printf "\n\e[2G - Could only find ${#READY_TAGGED_MACHINES[@]} machine${W} with the ${TAG} tag. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
[[ ${#READY_TAGGED_MACHINES[@]} -lt ${COUNT} ]] && { read -erp "$(printf "\n\e[2G - Could only find ${#READY_TAGGED_MACHINES[@]} machine${W} with the ${TAG} tag. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
local COUNT=${#READY_TAGGED_MACHINES[@]}
fi
printf "\n\e[2GAllocating the following Host${W} to the LXD Pods:\n"
printf -- "\e[2G - %s\n" ${READY_TAGGED_MACHINES[@]}|sed 's/:/ \(/g;s/.$/&\)/g';echo
local -a ALLOCATED_MACHINES=($(printf "%s\n" ${READY_TAGGED_MACHINES[@]##*:}|xargs -I{} -n1 -P0 maas ${MAAS_PROFILE} machines allocate system_id={}|jq -r '"\(.hostname):\(.system_id)"'|sort -uV))
[[ ${#ALLOCATED_MACHINES[@]} -lt 3 ]] && { printf "\e[2G\e[2G\e[38;2;255;255;0mSorry! \e[0mCould not allocate enough machines to create a LXD Cluster.\n\n\e[9GMachines Required: 3\n\e[9GMachines Found:\e[4C\e[38;2;255;0;0m${#ALLOCATED_MACHINES[@]}\n\n";return 1; }
[[ ${#ALLOCATED_MACHINES[@]} -lt ${COUNT} && ${#ALLOCATED_MACHINES[@]} -ge 3 ]] && { read -erp "$(printf "\n\e[2G - Could only allocate ${#ALLOCATED_MACHINES[@]} machine${W}. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
[[ ${#ALLOCATED_MACHINES[@]} -lt ${COUNT} ]] && { read -erp "$(printf "\n\e[2G - Could only allocate ${#ALLOCATED_MACHINES[@]} machines. Continue? [y/n] : ")" CONT; [[ ${CONT,,} =~ y ]] && echo || return 0; }
local COUNT=${#ALLOCATED_MACHINES[@]}
# The first element in the array will be the Cluster Primary
local LXD_PRIMARY=${ALLOCATED_MACHINES[0]%%:*}
# Preconfigure the system keys in /etc/ssh so we can setup the cluster without any prompts or exchanging ssh keys
local -a KEY_TYPES=(rsa dsa ecdsa)
xargs -n1 -P0 bash -c 'ssh-keygen &>/dev/null -t $0 -f /tmp/lxd_cluster_ssh_host_$0_key -P ""' <<< ${KEY_TYPES[@]}
local SSH_HOST_KEYS="$(printf "\nssh_keys:\n";xargs -n1 -P1 bash -c 'printf " $0_private: |\n$(cat /tmp/lxd_cluster_ssh_host_$0_key|sed '"'"'s/^.*$/ &/g'"'"')\n\n $0_public: $(cat /tmp/lxd_cluster_ssh_host_$0_key.pub)\n\n"' <<< ${KEY_TYPES[@]})"
#Remove preseeded ssh keys from local machine
rm -rf /tmp/lxd_cluster_ssh_host* /tmp/lxd_cluster_user_ssh*
# Get SSH Public keys from local accounts. Remove duplicates
local SSH_PUB_KEYS="$((if [[ -n $(find 2>/dev/null ~/.ssh -iname "*.pub") ]];then
echo ssh_authorized_keys:
find 2>/dev/null ~/.ssh -iname "*.pub"|xargs -n1 -P1 bash -c 'printf -- '"'"' - %s\n'"'"' "$(cat $0)"'
fi
)|awk '!seen[$0]++')"
# Create correct the stanza for disk or file based storage pool
[[ ${STORAGE_POOL_DEVICE} =~ dev || ${STORAGE_POOL_DEVICE} =~ sd ]] && local LXD_STORAGE_POOL="$(cat <<EOF
storage_pools:
- config:
source: ${STORAGE_POOL_DEVICE}
description: 'Default LXD Storage Pool'
name: local
driver: zfs
EOF
)"
[[ ! ${STORAGE_POOL_DEVICE} =~ dev && ! ${STORAGE_POOL_DEVICE} =~ sd ]] && local LXD_STORAGE_POOL="$(cat <<EOF
storage_pools:
- config:
size: 100GB
source: /var/snap/lxd/common/lxd/disks/local.img
zfs.pool_name: local
description: ""
name: local
driver: zfs
EOF
)"
#Indent yaml for use in LXD preeseed yaml
local LXD_SSH_PUB_KEYS="$(echo;echo "${SSH_PUB_KEYS}"|sed 's/^/ /g')"
# Create a string of the Cluster hosts that we can for SSH config files (thus the added asterisk)
# (easier to remove the asterisk in a variable than to add it, so it's added to main variable)
local CLUSTER_HOST_LIST=$(printf "%s*\n" ${ALLOCATED_MACHINES[@]%%:*}|paste -sd" "|sort -uV)
# Create Package List for Cluster hosts
local CI_PACKAGES=$([[ ${#CI_PKG_LIST[@]} -ge 1 ]] && printf "packages: [$(printf '%s\n' ${CI_PKG_LIST[@]}|paste -sd',')]\n")
#Make LXD Image Script to preseed LXD Clusters image store
local LXD_IMAGE_SCRIPT="$(cat <<EOF|base64 -w0
#!/bin/bash
printf "\e[1mLXD Image Copy Tool\e[0m\n"
/snap/bin/lxc image copy ubuntu-daily:f local: --copy-aliases --public
EOF
)"
#Make LXD Cluster Script and convert to base64 to include in cloud-init user-data
local LXD_CLUSTER_SCRIPT="$(cat <<EOF|base64 -w0
#!/bin/bash
if [[ \$(hostname 2>/dev/null -s) = ${LXD_PRIMARY} ]];then
cat <<EOT|sudo lxd init --preseed
config:
core.https_address: \$(dig +short @${MAAS_IP} \$(hostname -f)):8443
core.trust_password: ubuntu
maas.api.key: ${MAAS_API}
maas.api.url: ${MAAS_URL}
networks:
- config:
ipv4.address: auto
ipv4.nat: 'true'
ipv6.address: none
ipv6.nat: 'false'
name: lxdbr0
type: bridge
${LXD_STORAGE_POOL}
profiles:
- name: default
description: 'Default LXD Profile'
config:
user.user-data: |
#cloud-config
${LXD_SSH_PUB_KEYS}
devices:
eth0:
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: /
pool: local
type: disk
- name: privileged
description: 'Privileged LXD Profile'
config:
linux.kernel_modules: ip_tables,ip6_tables,netlink_diag,nf_nat,overlay
migration.incremental.memory: 'true'
raw.lxc: |-
lxc.cgroup.devices.allow = c 10:237 rwm
lxc.apparmor.profile = unconfined
lxc.cgroup.devices.allow = b 7:* rwm
security.nesting: 'true'
security.privileged: 'true'
user.user-data: |
#cloud-config
${LXD_SSH_PUB_KEYS}
devices:
eth0:
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: /
pool: local
type: disk
kvm:
path: /dev/kvm
type: unix-char
mem:
path: /dev/mem
type: unix-char
loop-control:
path: /dev/loop-control
type: unix-char
loop0:
path: /dev/loop0
type: unix-block
loop1:
path: /dev/loop1
type: unix-block
loop2:
path: /dev/loop2
type: unix-block
loop3:
path: /dev/loop3
type: unix-block
loop4:
path: /dev/loop4
type: unix-block
loop5:
path: /dev/loop5
type: unix-block
loop6:
path: /dev/loop6
type: unix-block
loop7:
path: /dev/loop7
type: unix-block
- name: maas
description: 'MAAS LXD Profile'
config:
user.user-data: |
#cloud-config
${LXD_SSH_PUB_KEYS}
devices:
eth0:
maas.subnet.ipv4: ${MAAS_SUBNET}
name: eth0
nictype: bridged
parent: br0
type: nic
root:
path: /
pool: local
type: disk
- name: maas-privileged
description: 'MAAS Privileged LXD Profile'
config:
linux.kernel_modules: ip_tables,ip6_tables,netlink_diag,nf_nat,overlay
migration.incremental.memory: 'true'
raw.lxc: |-
lxc.cgroup.devices.allow = c 10:237 rwm
lxc.apparmor.profile = unconfined
lxc.cgroup.devices.allow = b 7:* rwm
security.nesting: 'true'
security.privileged: 'true'
user.user-data: |
#cloud-config
${LXD_SSH_PUB_KEYS}
devices:
eth0:
maas.subnet.ipv4: ${MAAS_SUBNET}
name: eth0
nictype: bridged
parent: br0
type: nic
root:
path: /
pool: local
type: disk
kvm:
path: /dev/kvm
type: unix-char
mem:
path: /dev/mem
type: unix-char
loop-control:
path: /dev/loop-control
type: unix-char
loop0:
path: /dev/loop0
type: unix-block
loop1:
path: /dev/loop1
type: unix-block
loop2:
path: /dev/loop2
type: unix-block
loop3:
path: /dev/loop3
type: unix-block
loop4:
path: /dev/loop4
type: unix-block
loop5:
path: /dev/loop5
type: unix-block
loop6:
path: /dev/loop6
type: unix-block
loop7:
path: /dev/loop7
type: unix-block
cluster:
server_name: \$(hostname 2>/dev/null -s)
enabled: true
member_config: []
cluster_address: ''
cluster_certificate: ''
server_address: ''
cluster_password: ''
EOT
elif [[ \$(hostname 2>/dev/null -s) != ${LXD_PRIMARY} ]];then
while [[ \$(sudo ssh 2>/dev/null -i /etc/ssh/ssh_host_rsa_key -tt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${LXD_PRIMARY} 'test -f /var/snap/lxd/common/lxd/server.crt';echo \$?) -ne 0 ]];do sleep 5;done
cat <<EOT|sudo lxd init --preseed
config: {}
networks: []
storage_pools: []
profiles: []
cluster:
server_name: \$(hostname -s)
enabled: true
member_config:
- entity: storage-pool
name: local
key: source
value: ${STORAGE_POOL_DEVICE}
description: ''
- entity: storage-pool
name: local
key: volatile.initial_source
value: ${STORAGE_POOL_DEVICE}
description: ''
- entity: storage-pool
name: local
key: zfs.pool_name
value: local
description: ''
cluster_address: ${LXD_PRIMARY}.${MAAS_DOMAIN}:8443
cluster_certificate: |
\$(sudo ssh 2>/dev/null -i /etc/ssh/ssh_host_rsa_key -tt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${LXD_PRIMARY} 'sed -e ":a;N;$!ba;s/\n/\n\n/g" /var/snap/lxd/common/lxd/server.crt'|sed 's/^.*$/ &/g')
server_address: \$(dig +short @${MAAS_IP} \$(hostname -f)):8443
cluster_password: ubuntu
EOT
fi
EOF
)"
local CI_USER_DATA="$(cat <<EOF|tee /tmp/${FUNCNAME}.cloud-init.yaml|base64 -w0
#cloud-config
bootcmd:
- set -x
- export DEBIAN_FRONTEND=noninteractive
- cloud-init-per once aupdate apt update -qq
- cloud-init-per once isquashfuse apt install squashfuse -yqq
- cloud-init-per once rlxd apt purge lxd\\* -yqq
- cloud-init-per once aremove apt autoremove -yq
final_message: "LXD-Cluster Install Complete"
timezone: ${CI_TZ}
locale: ${CI_LC}
apt:
primary:
- arches: [amd64]
uri: http://us.archive.ubuntu.com/ubuntu}
security:
- arches: [amd64]
uri: http://us.archive.ubuntu.com/ubuntu}
sources_list: |
deb \$PRIMARY \$RELEASE main universe restricted multiverse
deb \$PRIMARY \$RELEASE-updates main universe restricted multiverse
deb \$SECURITY \$RELEASE-security main universe restricted multiverse
deb \$SECURITY \$RELEASE-backports main universe restricted multiverse
package_update: ${CI_PKG_UPD}
package_upgrade: ${CI_PKG_UPG}
${CI_PACKAGES}
write_files:
- encoding: b64
content: ${LXD_CLUSTER_SCRIPT}
path: /usr/local/bin/lxd-cluster.sh
permissions: '755'
owner: root:root
- encoding: b64
content: ${LXD_IMAGE_SCRIPT}
path: /usr/local/bin/lxc-image-copy.sh
permissions: '755'
owner: root:root
runcmd:
- set -x
- snap install lxd --candidate
- adduser \$(id -un 1000) lxd
- export PATH="/snap/bin:$PATH"
- sed 's|PATH="|PATH="/snap/bin:|g' -i /etc/environment
- if [ ! \$(id -un 1000) = ubuntu -a -n \$(id 2>/dev/null -u ubuntu) ];then adduser ubuntu lxd;fi
- if [ ! -f \$(awk -F":" '/'\$(id -un 0)'/{print \$6}' /etc/passwd)/.ssh/id_rsa ];then printf "y\n"|ssh-keygen -f ~/.ssh/id_rsa -P "";fi
- if [ ! -f \$(awk -F":" '/'\$(id -un 1000)'/{print \$6}' /etc/passwd)/.ssh/id_rsa ];then su - \$(id -un 1000) -c 'printf "y\n"|ssh-keygen -f ~/.ssh/id_rsa -P ""' ;fi
- if [ ! \$(id -un 1000) = ubuntu -a -n \$(id 2>/dev/null -u ubuntu) ];then if [ ! -f \$(awk -F":" '/ubuntu/{print \$6}' /etc/passwd)/.ssh/id_rsa ];then su - ubuntu -c 'printf "y\n"|ssh-keygen -f ~/.ssh/id_rsa -P ""' ;fi;fi
- cp /etc/ssh/ssh_host_rsa_key* \$(awk -F":" '/'\$(id -un 1000)'/{print \$6}' /etc/passwd)/.ssh/
- chown -R \$(id -un 1000):\$(id -un 1000) \$(awk -F":" '/'\$(id -un 1000)'/{print \$6}' /etc/passwd)/.ssh/
- cat /etc/ssh/ssh_host_rsa_key.pub|tee 1>/dev/null -a \$(awk -F":" '/'\$(id -un 0)'/{print \$6}' /etc/passwd)/.ssh/authorized_keys \$(awk -F":" '/'\$(id -un 1000)'/{print \$6}' /etc/passwd)/.ssh/authorized_keys
- printf -- "\nHost ${CLUSTER_HOST_LIST}\n\tAddressFamily inet\n\tCheckHostIP no\n\tForwardX11Trusted yes\n\tForwardX11 yes\n\tIdentityFile /etc/ssh/ssh_host_rsa_key\n LogLevel FATAL\n SendEnv LANG LC_*\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n User ubuntu\n\tXAuthLocation /usr/bin/xauth\n"|tee -a 1>/dev/null /etc/ssh/ssh_config
- printf -- "%s\n" ${CLUSTER_HOST_LIST//\*/}|xargs -I{} -n1 -P0 ssh-keyscan 2>/dev/null -H {}|su - \$(id -un 1000) -c "tee -a ~/.ssh/known_hosts"
- printf -- "%s\n" ${CLUSTER_HOST_LIST//\*/}|xargs -I{} -n1 -P0 ssh-keyscan 2>/dev/null -H {}|tee -a \$(awk -F":" '/'\$(id -un 1000)'/{print \$6}' /etc/passwd)/.ssh/known_hosts
- if [ -f /usr/local/bin/lxd-cluster.sh ];then /usr/local/bin/lxd-cluster.sh;fi
- if [ \$(hostname -s) = ${LXD_PRIMARY} -a -f /usr/local/bin/lxc-image-copy.sh ];then /usr/local/bin/lxc-image-copy.sh;fi
- lxc 2>/dev/null profile device set maas eth0 parent \$(ip route get ${MAAS_IP}|/bin/grep -oP '(?<=dev )[^ ]+')
- lxc 2>/dev/null profile device set maas-privileged eth0 parent \$(ip route get ${MAAS_IP}|/bin/grep -oP '(?<=dev )[^ ]+')
- touch /var/tmp/install-complete
${SSH_HOST_KEYS}
${SSH_PUB_KEYS}
EOF
)"
[[ -n ${MICROCLOUD_TAG} ]] || { local MICROCLOUD_TAG="${BASE_TAG}-$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 6 | head -n 1)"; }
printf "\n\e[2GCreating tag \"${MICROCLOUD_TAG}\" for this microcloud...\n"
maas ${MAAS_PROFILE} tags create name=${MICROCLOUD_TAG} comment="$(echo -n ${MICROCLOUD_TAG^^}|sed 's/-/_/g')_HOSTS=(`printf '%s\n' ${ALLOCATED_MACHINES[@]##*:}|paste -sd" "` ); $(echo -n ${MICROCLOUD_TAG^^}|sed 's/-/_/g')_BUILD_DATE=$(date --iso-8601=seconds)" &>/dev/null
printf "\e[2G- Tagging ${#ALLOCATED_MACHINES[@]} machines with \"${MICROCLOUD_TAG}\"...\n"
ADD=$(printf "add=%s\n" ${ALLOCATED_MACHINES[@]##*:}|paste -sd' ')
local ADDED=$(eval "maas ${MAAS_PROFILE} tag update-nodes ${MICROCLOUD_TAG} "$ADD""|jq -r .added)
[[ ${ADDED} -eq ${#ALLOCATED_MACHINES[@]} ]] && { printf "\e[4G - Successfully tagged ${ADDED}/${#ALLOCATED_MACHINES[@]} machines with the \"${MICROCLOUD_TAG}\" tag ${OK} "; } || { printf "\e[2G - Could only tag ${ADDED}/${#ALLOCATED_MACHINES[@]} machines with ${MICROCLOUD_TAG} ${FAILED} \n"; }
echo
printf "\n\e[2GDeploying the following hosts to ${MICROCLOUD_TAG} :\n\n"
printf -- "\e[2G - %s\n" ${ALLOCATED_MACHINES[@]}|sed 's/:/ \(/g;s/.$/&\)/g';echo
local -a DEPLOYED_MACHINES=($(printf "%s\n" ${ALLOCATED_MACHINES[@]##*:}|xargs -I{} -n1 -P1 maas ${MAAS_PROFILE} machine deploy {} distro_series=${DISTRO} user_data="${CI_USER_DATA}"|jq 2>/dev/null -r '"\(.hostname):\(.system_id)"'))
printf "\n\e[2G - A copy of the cloud-init used for this deployment can be found at /tmp/${FUNCNAME}.cloud-init.yaml\n\n"
printf "\e[0m\n\e[5G\e[38;2;255;255;255mLXD Microcloud Tips:\e[0m\n"
printf "\n\e[4G - To run cluster status on all nodes, type:\n\e[7G\e[38;2;255;255;255;3mmaas ${MAAS_PROFILE} tag nodes ${MICROCLOUD_TAG}|jq -r .[].hostname|sort -V|xargs -rn1 -P1 -I{} ssh {} lxc cluster list\n\e[0m"
printf "\n\e[4G - To release all machines in cluster, type:\n\e[7G\e[38;2;255;255;255;3mmaas ${MAAS_PROFILE} tag nodes ${MICROCLOUD_TAG}|jq -r .[].system_id|xargs -rn1 -P0 maas ${MAAS_PROFILE} machine release;maas ${MAAS_PROFILE} tag delete ${MICROCLOUD_TAG}\n\e[0m"
echo
[[ ${WAIT} = true ]] && { tput civis;while [[ $(maas ${MAAS_PROFILE} tag nodes ${MICROCLOUD_TAG}|jq -r '.[]|select(.status_name=="Deploying").name'|wc -l) -ne 0 ]];do printf "\e[2G - Deploying\e[K\r";sleep .25;printf "\e[2G - Deploying .\e[K\r";sleep .25;printf "\e[2G - Deploying . .\e[K\r";sleep .25;printf "\e[2G - Deploying . . .\e[K\r";sleep .25;done;tput cnorm; }
[[ -n ${FDEBUG} && ${FDEBUG} = true ]] && { set +x &>/dev/null; }
};export -f maas-microcloud-lxd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment