#!/bin/bash export TEMP_DIR=${TEMP_DIR:-$(mktemp -d -p /var/tmp)} export NAMEKEY_FILE=${NAMEKEY_FILE:-"$HOME/.airship_key"} export DEFINITION_DEPOT="${TEMP_DIR}/site_yaml/" export RENDERED_DEPOT="${TEMP_DIR}/rendered_yaml/" export CERT_DEPOT="${TEMP_DIR}/cert_yaml/" export GATE_DEPOT="${TEMP_DIR}/gate_yaml/" export SCRIPT_DEPOT="${TEMP_DIR}/scripts/" export BUILD_WORK_DIR=${BUILD_WORK_DIR:-/work} export BASE_IMAGE_SIZE=${BASE_IMAGE_SIZE:-68719476736} export BASE_IMAGE_URL=${BASE_IMAGE_URL:-https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img} export IMAGE_PROMENADE_CLI=${IMAGE_PROMENADE_CLI:-quay.io/airshipit/promenade:cfb8aa498c294c2adbc369ba5aaee19b49550d22} export IMAGE_PEGLEG_CLI=${IMAGE_PEGLEG_CLI:-quay.io/airshipit/pegleg:50ce7a02e08a0a5277c2fbda96ece6eb5782407a} export IMAGE_SHIPYARD_CLI=${IMAGE_SHIPYARD_CLI:-quay.io/airshipit/shipyard:4dd6b484d11e86ad51da733841b9ef137421d461} export IMAGE_COREDNS=${IMAGE_COREDNS:-docker.io/coredns/coredns:1.2.2} export IMAGE_QUAGGA=${IMAGE_QUAGGA:-docker.io/cumulusnetworks/quagga:CL3.3.2} export IMAGE_DRYDOCK_CLI=${IMAGE_DRYDOCK_CLI:-quay.io/airshipit/drydock:d93d6d5a0a370ced536180612d1ade708e29cd47} export IMAGE_DOCKER_REGISTRY=${IMAGE_DOCKER_REGISTRY:-"docker.io/registry:2"} export IMAGE_HYPERKUBE=${IMAGE_HYPERKUBE:-gcr.io/google_containers/hyperkube-amd64:v1.12.9} export PROMENADE_DEBUG=${PROMENADE_DEBUG:-0} export PROMENADE_TMP_LOCAL=${PROMENADE_TMP_LOCAL:-cache} export REGISTRY_DATA_DIR=${REGISTRY_DATA_DIR:-/mnt/registry} export VIRSH_POOL=${VIRSH_POOL:-airship} export VIRSH_POOL_PATH=${VIRSH_POOL_PATH:-/var/lib/libvirt/airship} export VIRSH_CPU_OPTS=${VIRSH_CPU_OPTS:-host} export UPSTREAM_DNS=${UPSTREAM_DNS:-"8.8.8.8 8.8.4.4"} export NTP_POOLS=${NTP_POOLS:-"0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org"} export NTP_SERVERS=${NTP_SERVERS:-""} export PROMENADE_ENCRYPTION_KEY=${PROMENADE_ENCRYPTION_KEY:-MjI1N2ZiMjMzYjI0ZmVkZDU4} export PEGLEG_PASSPHRASE=${PEGLEG_PASSPHRASE:-ewd?egnPWL0Q?hzzGwEBmII5} export PEGLEG_SALT=${PEGLEG_SALT:-9EX&uapdz1ka17WOQMG-FjTA} # key-pair used for drydock/maas auth towards libvirt and access to # the virtual nodes; auto-generated if no value provided export GATE_SSH_KEY=${GATE_SSH_KEY:-""} # skip generation of certificates, and other security manifests # auto-generated by default export USE_EXISTING_SECRETS=${USE_EXISTING_SECRETS:-""} export SHIPYARD_PASSWORD=${SHIPYARD_OS_PASSWORD:-'password18'} export AIRSHIP_KEYSTONE_URL=${AIRSHIP_KEYSTONE_URL:-'http://keystone.gate.local:80/v3'} config_vm_memory() { nodename=${1} mem=$(jq -cr ".vm.${nodename}.memory" < "${GATE_MANIFEST}") mem_backing=$(jq -cr ".vm.${nodename}.memorybacking" < "${GATE_MANIFEST}") if [[ "${mem_backing}" != "null" ]] then echo "memory=${mem},${mem_backing}=yes" else echo "${mem}" fi } config_vm_names() { jq -cr '.vm | keys | join(" ")' < "${GATE_MANIFEST}" } config_vm_iface_list() { nodename="$1" jq -cr ".vm.${nodename}.networking | del(.addresses) | keys | .[]" < "${GATE_MANIFEST}" } config_vm_iface_model() { nodename="$1" interface="$2" iface_model=$(jq -cr ".vm.${nodename}.networking.${interface}.model" < "${GATE_MANIFEST}") if [[ "${iface_model}" != "null" ]] then echo "${iface_model}" else echo "virtio" fi } config_vm_iface_mac() { nodename="$1" interface="$2" jq -cr ".vm.${nodename}.networking.${interface}.mac" < "${GATE_MANIFEST}" } # What network this VM interface should be attached to config_vm_iface_network() { nodename="$1" interface="$2" jq -cr ".vm.${nodename}.networking.${interface}.attachment.network" < "${GATE_MANIFEST}" } # What VLANs on a network should be attached to this node config_vm_iface_vlans() { nodename="$1" interface="$2" jq -cr ".vm.${nodename}.networking.${interface}.attachment.vlans | select(.!=null)" < "${GATE_MANIFEST}" } # PCI slot for this VM interface config_vm_iface_slot() { nodename="$1" interface="$2" jq -cr ".vm.${nodename}.networking.${interface}.pci.slot" < "${GATE_MANIFEST}" } # PCI card port for this VM interface config_vm_iface_port() { nodename="$1" interface="$2" jq -cr ".vm.${nodename}.networking.${interface}.pci.port" < "${GATE_MANIFEST}" } # The IP address for the VM for a network. If vlan is also specified, the VLAN # on the network config_vm_net_ip() { nodename="$1" network="$2" vlan="$3" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".vm.${nodename}.networking.addresses.${network}.ip" else query=".vm.${nodename}.networking.addresses.${network}.vlans.${vlan}.ip" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_vm_cpu() { nodename=${1} cpu_mode=$(jq -cr ".vm.${nodename}.cpu_mode" < "${GATE_MANIFEST}") cpu_cells=$(jq -cr ".vm.${nodename}.cpu_cells" < "${GATE_MANIFEST}") if [[ "${cpu_mode}" != "null" ]] then config_string="mode=${cpu_mode}" if [[ "${cpu_cells}" != "null" ]] then cpu_cells_to_s=$(echo "${cpu_cells}" | jq -cr "[to_entries[] | [.key + \".cpus=\" + .value.cpus, .key + \".memory=\" + .value.memory]] | add | join (\",\")") config_string="${config_string},${cpu_cells_to_s}" fi else config_string=${VIRSH_CPU_OPTS} fi echo -n "$config_string" } config_vm_vcpus() { nodename=${1} vcpus=$(jq -cr ".vm.${nodename}.vcpus" < "${GATE_MANIFEST}") sockets=$(jq -cr ".vm.${nodename}.sockets" < "${GATE_MANIFEST}") threads=$(jq -cr ".vm.${nodename}.threads" < "${GATE_MANIFEST}") if [[ "${sockets}" != "null" ]] then config_string="vcpus=${vcpus},sockets=${sockets}" if [[ "${threads}" != "null" ]] then config_string="${config_string},threads=${threads}" fi echo -n "$config_string" else echo "${vcpus}" fi } config_vm_bootstrap() { nodename=${1} val=$(jq -cr ".vm.${nodename}.bootstrap" < "${GATE_MANIFEST}") if [[ "${val}" == "true" ]] then echo "true" else echo "false" fi } config_disk_list() { layout_name="${1}" jq -cr ".disk_layouts.${layout_name} | keys | join(\" \")" < "${GATE_MANIFEST}" } config_disk_details() { layout_name="${1}" disk_device="${2}" jq -cr ".disk_layouts.${layout_name}.${disk_device}" < "${GATE_MANIFEST}" } config_disk_size() { layout_name="$1" disk_device="$2" jq -cr ".disk_layouts.${layout_name}.${disk_device}.size" < "${GATE_MANIFEST}" } config_disk_format() { layout_name="$1" disk_device="$2" do_format=$(jq -cr ".disk_layouts.${layout_name}.${disk_device} | has(\"format\")") if [[ "$do_format" == "true" && "$disk_device" != "$(config_layout_bootstrap "$layout_name")" ]] then jq -cr ".disk_layouts.${layout_name}.${disk_device}.format" < "${GATE_MANIFEST}" else echo "" fi } config_format_type() { JSON="$1" echo "$JSON" | jq -cr '.type' } config_format_mount() { JSON="$1" echo "$JSON" | jq -cr '.mountpoint' } config_disk_ioprofile() { layout_name="$1" disk_device="$2" jq -cr ".disk_layouts.${layout_name}.${disk_device}.io_profile" < "${GATE_MANIFEST}" } # Find which disk in a layout should # get the bootstrap image config_layout_bootstrap() { layout_name="${1}" jq -cr ".disk_layouts.${layout_name} | keys[] as \$k | {device: (\$k)} + (.[\$k]) | select(.bootstrap) | .device " < "${GATE_MANIFEST}" } config_vm_disk_layout() { nodename=${1} jq -cr ".vm.${nodename}.disk_layout" < "${GATE_MANIFEST}" } config_vm_userdata() { nodename=${1} val=$(jq -cr ".vm.${nodename}.userdata" < "${GATE_MANIFEST}") if [[ "${val}" != "null" ]] then echo "${val}" fi } config_bgp_as() { as_number=${1} jq -cr ".bgp.${as_number}" < "${GATE_MANIFEST}" } config_net_list() { jq -cr '.networking | keys | .[]' < "${GATE_MANIFEST}" } config_net_vlan_list() { network="$1" jq -cr ".networking.${network}.layer2.vlans // {} | keys | .[]" < "${GATE_MANIFEST}" } config_net_cidr() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network}.layer3.cidr" else query=".networking.${network}.vlans.${vlan}.layer3.cidr" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_net_is_layer3() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network} | has(\"layer3\")" else query=".network.${network}.vlans.${vlan} | has(\"layer3\")" fi jq -cr "$query" < "${GATE_MANIFEST}" } # Find the layer 3 network tagged for a particular # role - this can be either a native or vlan network # If multiple networks have a role, the results is # undefined config_netspec_for_role() { role="$1" set -e for net in $(config_net_list) do if config_net_has_role "$net" "$role" then netspec="$net" fi for vlan in $(config_net_vlan_list "$net") do if config_vlan_has_role "$net" "$vlan" "$role" then netspec="${vlan}@${net}" fi done done echo -n "$netspec" } config_net_has_role() { netname="$1" role="$2" value="$(jq -cr ".networking.${netname}.roles | contains([\"${role}\"])" < "$GATE_MANIFEST")" if [ "$value" == "true" ] then return 0 else return 1 fi } config_vlan_has_role() { netname="$1" vlan="$2" role="$3" value="$(jq -cr " .networking.${netname}.vlans.${vlan}.roles | contains([\"${role}\"])" < "$GATE_MANIFEST")" if [ "$value" == "true" ] then return 0 else return 1 fi } config_net_selfip() { network="$1" vlan="$2" if [[ -z "$vlan" ]] then query=".networking.${network}.layer3.address" else query=".networking.${network}.vlans.${vlan}.layer3.address" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_net_selfip_cidr() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi selfip=$(config_net_selfip "$network" "$vlan") netcidr=$(config_net_cidr "$network" "$vlan") netbits=$(echo "$netcidr" | awk -F '/' '{print $2}') printf "%s/%s" "$selfip" "$netbits" } config_net_gateway() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network}.layer3.gateway" else query=".networking.${network}.vlans.${vlan}.layer3.gateway" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_net_routemode() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network}.layer3.routing.mode" else query=".networking.${network}.vlans.${vlan}.layer3.routing.mode" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_net_mtu() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network}.layer2.mtu // 1500" else query=".networking.${network}.vlans.${vlan}.layer2.mtu // 1500" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_net_mac() { network="$1" vlan="$2" if is_netspec "$network" then vlan=$(netspec_vlan "$network") network=$(netspec_netname "$network") fi if [[ -z "$vlan" ]] then query=".networking.${network}.layer2.address" else query=".networking.${network}.vlans.${vlan}.layer2.address" fi jq -cr "$query" < "${GATE_MANIFEST}" } config_ingress_domain() { jq -cr '.ingress.domain' < "${GATE_MANIFEST}" } config_ingress_ca() { if [[ ! -z "$GATE_MANIFEST" ]] then jq -cr '.ingress.ca' < "${GATE_MANIFEST}" fi } config_ingress_ips() { jq -cr '.ingress | keys | map(select(test("([0-9]{1,3}.?){4}"))) | join(" ")' < "${GATE_MANIFEST}" } config_ingress_entries() { IP=$1 jq -cr ".ingress[\"${IP}\"] | join(\" \")" < "${GATE_MANIFEST}" } config_pegleg_primary_repo() { jq -cr ".configuration.primary_repo" < "${GATE_MANIFEST}" } config_pegleg_sitename() { jq -cr ".configuration.site" < "${GATE_MANIFEST}" } config_pegleg_aux_repos() { jq -cr '.configuration.aux_repos | join(" ")' < "${GATE_MANIFEST}" } join_array() { local IFS=$1 shift echo "$*" } besteffort() { set +e "$@" set -e } get_namekey() { if [[ -r "$NAMEKEY_FILE" ]] then key=$(cat "$NAMEKEY_FILE") else key=$(openssl rand -hex 4) echo -n "$key" > "$NAMEKEY_FILE" fi echo -n "$key" } is_netspec(){ value="$1" if echo -n "$value" | grep -q "[0-9]+@.+" then return 0 else return 1 fi } netspec_netname(){ netspec="$1" echo -n "$netspec" | awk -F'@' '{print $2}' } netspec_vlan(){ netspec="$1" echo -n "$netspec" | awk -F'@' '{print $1}' } # We'll just add the conversions as needed cidr_to_netmask() { cidr="$1" netbits="$(echo "$cidr" | awk -F'/' '{print $2}')" case "$netbits" in 32) netmask="255.255.255.255" ;; 24) netmask="255.255.255.0" ;; esac echo "$netmask" }