#!/bin/bash xe_min() { local cmd="$1" shift xe "$cmd" --minimal "$@" } function die_with_error { local err_msg err_msg="$1" echo "$err_msg" >&2 exit 1 } function get_local_sr { xe pool-list params=default-SR minimal=true } function find_ip_by_name { local guest_name="$1" local interface="$2" local period=10 local max_tries=10 local i=0 while true; do if [ $i -ge $max_tries ]; then echo "Timeout: ip address for interface $interface of $guest_name" exit 11 fi ipaddress=$(xe vm-list --minimal \ name-label=$guest_name \ params=networks | sed -ne "s,^.*${interface}/ip: \([0-9.]*\).*\$,\1,p") if [ -z "$ipaddress" ]; then sleep $period i=$((i+1)) else echo $ipaddress break fi done } function _vm_uuid { local vm_name_label vm_name_label="$1" xe vm-list name-label="$vm_name_label" --minimal } function _create_new_network { local name_label name_label=$1 uuid=$(xe network-create name-label="$name_label") xe network-param-add uuid=$uuid param-name=other-config assume_network_is_shared='true' } function _multiple_networks_with_name { local name_label name_label=$1 # A comma indicates multiple matches xe network-list name-label="$name_label" --minimal | grep -q "," } function _network_exists { local name_label name_label=$1 ! [ -z "$(xe network-list name-label="$name_label" --minimal)" ] } function _bridge_exists { local bridge bridge=$1 ! [ -z "$(xe network-list bridge="$bridge" --minimal)" ] } function _network_uuid { local bridge_or_net_name bridge_or_net_name=$1 if _bridge_exists "$bridge_or_net_name"; then xe network-list bridge="$bridge_or_net_name" --minimal else xe network-list name-label="$bridge_or_net_name" --minimal fi } function add_interface { local vm_name_label local bridge_or_network_name vm_name_label="$1" bridge_or_network_name="$2" device_number="$3" local vm local net vm=$(_vm_uuid "$vm_name_label") net=$(_network_uuid "$bridge_or_network_name") xe vif-create network-uuid=$net vm-uuid=$vm device=$device_number } function setup_network { local bridge_or_net_name bridge_or_net_name=$1 if ! _bridge_exists "$bridge_or_net_name"; then if _network_exists "$bridge_or_net_name"; then if _multiple_networks_with_name "$bridge_or_net_name"; then cat >&2 << EOF ERROR: Multiple networks found matching name-label to "$bridge_or_net_name" please review your XenServer network configuration / localrc file. EOF exit 1 fi else _create_new_network "$bridge_or_net_name" fi fi } function bridge_for { local bridge_or_net_name bridge_or_net_name=$1 if _bridge_exists "$bridge_or_net_name"; then echo "$bridge_or_net_name" else xe network-list name-label="$bridge_or_net_name" params=bridge --minimal fi } function xenapi_ip_on { local bridge_or_net_name bridge_or_net_name=$1 ip -4 addr show $(bridge_for "$bridge_or_net_name") |\ awk '/inet/{split($2, ip, "/"); print ip[1];}' } function xenapi_is_listening_on { local bridge_or_net_name bridge_or_net_name=$1 ! [ -z $(xenapi_ip_on "$bridge_or_net_name") ] } function parameter_is_specified { local parameter_name parameter_name=$1 compgen -v | grep "$parameter_name" } function append_kernel_cmdline { local vm_name_label local kernel_args vm_name_label="$1" kernel_args="$2" local vm local pv_args vm=$(_vm_uuid "$vm_name_label") pv_args=$(xe vm-param-get param-name=PV-args uuid=$vm) xe vm-param-set PV-args="$pv_args $kernel_args" uuid=$vm } function destroy_all_vifs_of { local vm_name_label vm_name_label="$1" local vm vm=$(_vm_uuid "$vm_name_label") IFS=, for vif in $(xe vif-list vm-uuid=$vm --minimal); do xe vif-destroy uuid="$vif" done unset IFS } function have_multiple_hosts { xe host-list --minimal | grep -q "," } function get_current_host_uuid { source /etc/xensource-inventory; echo $INSTALLATION_UUID } function get_current_dom0_uuid { source /etc/xensource-inventory; echo $CONTROL_DOMAIN_UUID } function attach_network { local bridge_or_net_name bridge_or_net_name="$1" local net local host net=$(_network_uuid "$bridge_or_net_name") host=$(get_current_host_uuid) xe network-attach uuid=$net host-uuid=$host } function set_vm_memory { local vm_name_label local memory vm_name_label="$1" memory="$2" local vm vm=$(_vm_uuid "$vm_name_label") xe vm-memory-limits-set \ static-min=${memory}MiB \ static-max=${memory}MiB \ dynamic-min=${memory}MiB \ dynamic-max=${memory}MiB \ uuid=$vm } function set_vm_disk { local vm_name_label local vm_disk_size vm_name_label="$1" vm_disk_size="$2" local vm_uuid local vm_vbd local vm_vdi vm_uuid=$(xe vm-list name-label=$vm_name_label --minimal) vm_vbd=$(xe vbd-list vm-uuid=$vm_uuid device=xvda --minimal) vm_vdi=$(xe vdi-list vbd-uuids=$vm_vbd --minimal) xe vdi-resize uuid=$vm_vdi disk-size=$((vm_disk_size * 1024 * 1024 * 1024)) } function max_vcpus { local vm_name_label vm_name_label="$1" local vm local host local cpu_count host=$(get_current_host_uuid) vm=$(_vm_uuid "$vm_name_label") cpu_count=$(xe host-param-get \ param-name=cpu_info \ uuid=$host | sed -e 's/^.*cpu_count: \([0-9]*\);.*$/\1/g') if [ -z "$cpu_count" ]; then # get dom0's vcpu count cpu_count=$(cat /proc/cpuinfo | grep processor | wc -l) fi # Assert cpu_count is not empty [ -n "$cpu_count" ] # Assert ithas a numeric nonzero value expr "$cpu_count" + 0 # 8 VCPUs should be enough for devstack VM; avoid using too # many VCPUs: # 1. too many VCPUs may trigger a kernel bug which result VM # not able to boot: # https://kernel.googlesource.com/pub/scm/linux/kernel/git/wsa/linux/+/e2e004acc7cbe3c531e752a270a74e95cde3ea48 # 2. The remaining CPUs can be used for other purpose: # e.g. boot test VMs. MAX_VCPUS=8 if [ $cpu_count -ge $MAX_VCPUS ]; then cpu_count=$MAX_VCPUS fi xe vm-param-set uuid=$vm VCPUs-max=$cpu_count xe vm-param-set uuid=$vm VCPUs-at-startup=$cpu_count } function get_template { local tmp_name="$1" local host="$2" tmp=$(xe template-list name-label="$tmp_name" --minimal) if [[ $tmp == *","* ]]; then tmp_group=tmp tmp=$(xe template-list name-label="$tmp_name" \ possible-hosts=$host --minimal) # Current host have no template if [[ -z $tmp ]]; then tmp=${tmp_group##*,} fi fi echo $tmp } function clean_template_other_conf { local tmp_name="$1" tmp=$(xe template-list name-label="$tmp_name" --minimal) if [ -n "\$tmp" ]; then echo " $tmp clean other configure" IFS=',' for i in "\${tmp[@]}"; do xe template-param-clear param-name=other-config uuid=$i > /dev/null done fi } function uninstall_template { local tmp_name="$1" tmp=$(xe template-list name-label="$tmp_name" --minimal) if [ -n "\$tmp" ]; then echo " $tmp already exist, uninstalling" IFS=',' for i in "\${tmp[@]}"; do xe template-uninstall template-uuid="\$i" force=true > /dev/null done fi } function get_domid { local vm_name_label vm_name_label="$1" xe vm-list name-label="$vm_name_label" params=dom-id minimal=true } function install_conntrack_tools { local xs_host local xs_ver_major local centos_ver local conntrack_conf xs_host=$(get_current_host_uuid) xs_ver_major=$(xe host-param-get uuid=$xs_host param-name=software-version param-key=product_version_text_short | cut -d'.' -f 1) if [ $xs_ver_major -gt 6 ]; then # Only support conntrack-tools in Dom0 with XS7.0 and above if [ ! -f /usr/sbin/conntrackd ]; then sed -i s/#baseurl=/baseurl=/g /etc/yum.repos.d/CentOS-Base.repo centos_ver=$(yum version nogroups |grep Installed | cut -d' ' -f 2 | cut -d'/' -f 1 | cut -d'-' -f 1) yum install -y --enablerepo=base --releasever=$centos_ver conntrack-tools # Backup conntrackd.conf after install conntrack-tools, use the one with statistic mode mv /etc/conntrackd/conntrackd.conf /etc/conntrackd/conntrackd.conf.back conntrack_conf=$(find /usr/share/doc -name conntrackd.conf |grep stats) cp $conntrack_conf /etc/conntrackd/conntrackd.conf fi service conntrackd restart fi } # # Wait for VM to halt # function wait_for_VM_to_halt { #mgmt_ip="$1" GUEST_VM_NAME="$1" set +x echo "Waiting for the VM to halt. Progress in-VM can be checked with XenCenter or xl console:" domid=$(get_domid "$GUEST_VM_NAME") echo "ssh root@host \"xl console $domid\"" while true; do state=$(xe_min vm-list name-label="$GUEST_VM_NAME" power-state=halted) if [ -n "$state" ]; then break else echo -n "." sleep 20 fi done set -x }