From baff02fe219aa2fb8b7e075aef960785b57b7bc5 Mon Sep 17 00:00:00 2001 From: Todd Malsbary Date: Thu, 30 Sep 2021 15:44:15 -0700 Subject: [PATCH] Remove unused metal3-vm code Change-Id: Ibc69ef89b832ef24d088fd8b6412f332bbf8cdbb Signed-off-by: Todd Malsbary --- Makefile | 22 +- README.md | 24 ++- ci/jjb/shell/vagrant-verify.sh | 8 +- cmd/bpa-operator/Makefile | 4 - cmd/bpa-operator/e2etest/bpa_vm_verifier.sh | 231 --------------------- deploy/metal3-vm/.gitignore | 11 - deploy/metal3-vm/01_install_requirements.sh | 11 - deploy/metal3-vm/02_configure_host.sh | 223 -------------------- deploy/metal3-vm/03_launch_mgmt_cluster.sh | 180 ---------------- deploy/metal3-vm/04_verify.sh | 70 ------- deploy/metal3-vm/05_host_cleanup.sh | 54 ----- deploy/metal3-vm/Makefile | 20 -- deploy/metal3-vm/config_example.sh | 43 ---- .../metal3-vm/disable_apparmor_driver_libvirtd.sh | 9 - deploy/metal3-vm/lib/common.sh | 127 ----------- deploy/metal3-vm/lib/logging.sh | 12 -- .../ubuntu_bridge_network_configuration.sh | 45 ---- deploy/metal3-vm/ubuntu_install_requirements.sh | 94 --------- deploy/metal3-vm/vm-setup/inventory.ini | 2 - deploy/metal3-vm/vm-setup/library/generate_macs.py | 98 --------- .../vm-setup/roles/common/defaults/main.yml | 45 ---- .../metal3-vm/vm-setup/roles/common/tasks/main.yml | 70 ------- .../vm-setup/roles/libvirt/defaults/main.yml | 63 ------ .../vm-setup/roles/libvirt/files/get-domain-ip.sh | 24 --- .../metal3-vm/vm-setup/roles/libvirt/meta/main.yml | 2 - .../roles/libvirt/tasks/install_setup_tasks.yml | 32 --- .../vm-setup/roles/libvirt/tasks/main.yml | 13 -- .../roles/libvirt/tasks/network_setup_tasks.yml | 128 ------------ .../roles/libvirt/tasks/network_teardown_tasks.yml | 28 --- .../roles/libvirt/tasks/vm_setup_tasks.yml | 122 ----------- .../roles/libvirt/tasks/vm_teardown_tasks.yml | 94 --------- .../roles/libvirt/templates/baremetalvm.xml.j2 | 56 ----- .../roles/libvirt/templates/ironic_nodes.json.j2 | 57 ----- .../roles/libvirt/templates/network.xml.j2 | 59 ------ .../roles/libvirt/templates/volume_pool.xml.j2 | 11 - .../vm-setup/roles/virtbmc/defaults/main.yml | 2 - .../vm-setup/roles/virtbmc/files/vbmc_start.sh | 12 -- .../metal3-vm/vm-setup/roles/virtbmc/meta/main.yml | 3 - .../vm-setup/roles/virtbmc/tasks/main.yml | 4 - .../vm-setup/roles/virtbmc/tasks/setup_tasks.yml | 83 -------- .../roles/virtbmc/tasks/teardown_tasks.yml | 26 --- deploy/metal3-vm/vm-setup/setup-playbook.yml | 13 -- deploy/metal3-vm/vm-setup/teardown-playbook.yml | 17 -- figure-2.odg | Bin 13959 -> 11491 bytes figure-2.png | Bin 54787 -> 38534 bytes 45 files changed, 19 insertions(+), 2233 deletions(-) delete mode 100755 cmd/bpa-operator/e2etest/bpa_vm_verifier.sh delete mode 100644 deploy/metal3-vm/.gitignore delete mode 100755 deploy/metal3-vm/01_install_requirements.sh delete mode 100755 deploy/metal3-vm/02_configure_host.sh delete mode 100755 deploy/metal3-vm/03_launch_mgmt_cluster.sh delete mode 100755 deploy/metal3-vm/04_verify.sh delete mode 100755 deploy/metal3-vm/05_host_cleanup.sh delete mode 100644 deploy/metal3-vm/Makefile delete mode 100644 deploy/metal3-vm/config_example.sh delete mode 100644 deploy/metal3-vm/disable_apparmor_driver_libvirtd.sh delete mode 100644 deploy/metal3-vm/lib/common.sh delete mode 100644 deploy/metal3-vm/lib/logging.sh delete mode 100755 deploy/metal3-vm/ubuntu_bridge_network_configuration.sh delete mode 100755 deploy/metal3-vm/ubuntu_install_requirements.sh delete mode 100644 deploy/metal3-vm/vm-setup/inventory.ini delete mode 100644 deploy/metal3-vm/vm-setup/library/generate_macs.py delete mode 100644 deploy/metal3-vm/vm-setup/roles/common/defaults/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/common/tasks/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/defaults/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/files/get-domain-ip.sh delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/meta/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/install_setup_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_setup_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_teardown_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_setup_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_teardown_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/templates/baremetalvm.xml.j2 delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/templates/ironic_nodes.json.j2 delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/templates/network.xml.j2 delete mode 100644 deploy/metal3-vm/vm-setup/roles/libvirt/templates/volume_pool.xml.j2 delete mode 100644 deploy/metal3-vm/vm-setup/roles/virtbmc/defaults/main.yml delete mode 100755 deploy/metal3-vm/vm-setup/roles/virtbmc/files/vbmc_start.sh delete mode 100644 deploy/metal3-vm/vm-setup/roles/virtbmc/meta/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/main.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/setup_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/teardown_tasks.yml delete mode 100644 deploy/metal3-vm/vm-setup/setup-playbook.yml delete mode 100644 deploy/metal3-vm/vm-setup/teardown-playbook.yml diff --git a/Makefile b/Makefile index 2f21037..84ff14b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ SHELL:=/bin/bash ENV:=$(CURDIR)/env BMDIR:=$(CURDIR)/env/metal3 METAL3DIR:=$(CURDIR)/deploy/metal3/scripts -METAL3VMDIR:=$(CURDIR)/deploy/metal3-vm BPA_OPERATOR:=$(CURDIR)/cmd/bpa-operator/ KUD_PATH:=$(CURDIR)/deploy/kud SDWAN_VERIFIER_PATH:=$(CURDIR)/sdwan/test @@ -74,12 +73,6 @@ kud_vm_deploy: kud_bm_reset: pushd $(KUD_PATH) && ./kud_bm_launch.sh reset v1 && popd -metal3_prerequisite: - pushd $(METAL3VMDIR) && make bmh_install && popd - -metal3_vm: - pushd $(METAL3VMDIR) && make bmh && popd - sdwan_verifier: pushd $(SDWAN_VERIFIER_PATH) && bash sdwan_verifier.sh && popd @@ -92,9 +85,6 @@ bpa_op_install_e2e: bpa_op_delete: pushd $(BPA_OPERATOR) && make delete && popd -bpa_op_e2e_vm: - pushd $(BPA_OPERATOR) && make e2etest_vm && popd - bpa_op_e2e_bmh: pushd $(BPA_OPERATOR) && make e2etest_bmh && popd @@ -104,8 +94,6 @@ bpa_op_e2e_virtletvm: bpa_op_unit: pushd $(BPA_OPERATOR) && make unit_test && popd -bpa_op_vm_verifier: bpa_op_install_e2e bpa_op_e2e_vm - bpa_op_bmh_verifier: bpa_op_install_e2e bpa_op_e2e_bmh bpa_op_virtletvm_verifier: bpa_op_install bpa_op_e2e_virtletvm @@ -142,14 +130,7 @@ bm_verifer: package_prerequisite \ bpa_rest_api_verifier \ clean_all -verify_all: prerequisite \ - metal3_prerequisite \ - kud_bm_deploy_mini \ - metal3_vm \ - bpa_op_vm_verifier \ - bpa_rest_api_verifier - -verifier: verify_all +verifier: bm_verifer verify_nestedk8s: prerequisite \ kud_vm_deploy \ @@ -168,4 +149,3 @@ kud_bm_verifier: prerequisite \ clean_bm_packages .PHONY: all bm_preinstall bm_install bashate - diff --git a/README.md b/README.md index 070bd60..242156b 100644 --- a/README.md +++ b/README.md @@ -381,9 +381,8 @@ The following steps occurs once the `make install` command is given. ![Figure 2](figure-2.png)*Figure 2: Virtual Deployment Architecture* Virtual deployment is used for the development environment using -Metal3 virtual deployment to create VM with PXE boot. VM Ansible -scripts the node inventory file in /opt/ironic. No setting is required -from the user to deploy the virtual deployment. +Vagrant to create VMs with PXE boot. No setting is required from the +user to deploy the virtual deployment. ### Snapshot Deployment Overview No snapshot is implemented in ICN R2. @@ -395,11 +394,20 @@ Jump server is required to be installed with Ubuntu 18.04. This will install all the VMs and install the k8s clusters. #### Verifying the Setup - VMs -`make verify_all` installs two VMs with name master-0 and worker-0 -with 8GB RAM and 8 vCPUs and installs k8s cluster on the VMs using the -ICN BPA operator and install the ICN BPA REST API verifier. BPA -operator installs the multi-cluster KUD to bring up k8s with all -addons and plugins. +To verify the virtual deployment, execute the following commands: +``` shell +$ vagrant up --no-parallel +$ vagrant ssh jump +vagrant@jump:~$ sudo su +root@jump:/home/vagrant# cd /icn +root@jump:/icn# make verifier +``` +`vagrant up --no-parallel` creates three VMs: vm-jump, vm-machine-1, +and vm-machine-2, each with 16GB RAM and 8 vCPUs. `make verifier` +installs the ICN BPA operator and the ICN BPA REST API verifier into +vm-jump, and then installs a k8s cluster on the vm-machine VMs using +the ICN BPA operator. The BPA operator installs the multi-cluster KUD +to bring up k8s with all addons and plugins. # Verifying the Setup ICN blueprint checks all the setup in both bare metal and VM diff --git a/ci/jjb/shell/vagrant-verify.sh b/ci/jjb/shell/vagrant-verify.sh index 65148aa..40aeea1 100644 --- a/ci/jjb/shell/vagrant-verify.sh +++ b/ci/jjb/shell/vagrant-verify.sh @@ -11,13 +11,9 @@ function clean_vm {{ trap clean_vm EXIT vagrant destroy -f -vagrant up +vagrant up --no-parallel vagrant ssh -c " set -exuf -sudo parted -a optimal /dev/sda ---pretend-input-tty resizepart 3 yes 100% -sudo resize2fs /dev/sda3 -sudo apt update -sudo apt install -y make -cd /vagrant +cd /icn sudo su -c 'make {target}' " diff --git a/cmd/bpa-operator/Makefile b/cmd/bpa-operator/Makefile index f075b9a..528f58c 100644 --- a/cmd/bpa-operator/Makefile +++ b/cmd/bpa-operator/Makefile @@ -57,10 +57,6 @@ delete: unit_test: go test ./pkg/controller/provisioning/ -.PHONY: e2etest_vm -e2etest_vm: - ./e2etest/bpa_vm_verifier.sh - .PHONY: e2etest_bmh e2etest_bmh: ./e2etest/bpa_bmh_verifier.sh diff --git a/cmd/bpa-operator/e2etest/bpa_vm_verifier.sh b/cmd/bpa-operator/e2etest/bpa_vm_verifier.sh deleted file mode 100755 index cdb4e5c..0000000 --- a/cmd/bpa-operator/e2etest/bpa_vm_verifier.sh +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -CLUSTER_NAME=cluster-test -ADDONS_NAMESPACE=kud -NUM_MASTERS=${NUM_MASTERS:-"1"} -NUM_WORKERS=${NUM_WORKERS:-"1"} - -# Create provisioning CR file for testing -cat < e2etest/e2e_test_provisioning_cr.yaml -apiVersion: bpa.akraino.org/v1alpha1 -kind: Provisioning -metadata: - name: e2e-test-provisioning - labels: - cluster: ${CLUSTER_NAME} - owner: c1 -spec: - masters: -EOF -for ((master=0;master> e2etest/e2e_test_provisioning_cr.yaml - - master-${master}: - mac-address: ${mac} -EOF -done -cat <> e2etest/e2e_test_provisioning_cr.yaml - workers: -EOF -for ((worker=0;worker> e2etest/e2e_test_provisioning_cr.yaml - - worker-${worker}: - mac-address: ${mac} -EOF -done -cat <> e2etest/e2e_test_provisioning_cr.yaml - KUDPlugins: - - emco -EOF -kubectl apply -f e2etest/e2e_test_provisioning_cr.yaml -sleep 5 - -#Check Status of kud job pod -status="Running" - -while [[ $status == "Running" ]] -do - echo "KUD install job still running" - sleep 2m - stats=$(kubectl get pods |grep -i kud-${CLUSTER_NAME}) - status=$(echo $stats | cut -d " " -f 3) -done - -#Print logs of Job Pod -jobPod=$(kubectl get pods|grep kud-${CLUSTER_NAME}) -podName=$(echo $jobPod | cut -d " " -f 1) -printf "\nNow Printing Job pod logs\n" -kubectl logs $podName - -if [[ $status == "Completed" ]]; -then - printf "KUD Install Job completed\n" - printf "Checking cluster status\n" - - source ../../env/lib/common.sh - CLUSTER_KUBECONFIG=/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/admin.conf - APISERVER=$(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') - TOKEN=$(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl get secret $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode) - if ! call_api $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure; - then - printf "\nKubernetes Cluster Install did not complete successfully\n" - exit 1 - else - printf "\nKubernetes Cluster Install was successful\n" - fi - -else - printf "KUD Install Job failed\n" - exit 1 -fi - -function wait_for { - local -r interval=30 - for ((try=0;try<600;try+=${interval})); do - echo "$(date +%H:%M:%S) - Waiting for $*" - sleep ${interval}s - if $*; then return 0; fi - done - return 1 -} - -function emco_ready { - KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n emco wait pod --all --for=condition=Ready --timeout=0s 1>/dev/null 2>/dev/null -} - -function emcoctl_apply { - [[ $(/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/emcoctl.sh apply -f $@ -v values.yaml | - awk '/Response Code:/ {code=$3} END{print code}') =~ 2.. ]] -} - -function emcoctl_delete { - [[ $(/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/emcoctl.sh delete -f $@ -v values.yaml | - awk '/Response Code:/ {code=$3} END{print code}') =~ 404 ]] -} - -function emcoctl_instantiate { - [[ $(/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/emcoctl.sh apply projects/kud/composite-apps/$@/v1/deployment-intent-groups/deployment/instantiate | - awk '/Response Code:/ {code=$3} END{print code}') =~ 2.. ]] -} - -function emcoctl_terminate { - [[ $(/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/emcoctl.sh apply projects/kud/composite-apps/$@/v1/deployment-intent-groups/deployment/terminate | - awk '/Response Code:/ {code=$3} END{print code}') =~ 2.. ]] -} - -function emcoctl { - local -r op=$1 - shift - - local -r interval=2 - for ((try=0;try<600;try+=${interval})); do - if emco_ready; then break; fi - echo "$(date +%H:%M:%S) - Waiting for emco" - sleep ${interval}s - done - - for ((;try<600;try+=${interval})); do - case ${op} in - "apply") if emcoctl_apply $@; then return 0; fi ;; - "delete") if emcoctl_delete $@; then return 0; fi ;; - "instantiate") if emcoctl_instantiate $@; then return 0; fi ;; - "terminate") if emcoctl_terminate $@; then return 0; fi ;; - esac - echo "$(date +%H:%M:%S) - Waiting for emcoctl ${op} $@" - sleep ${interval}s - done - - return 1 -} - -function addons_instantiated { - KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} wait pod -l app.kubernetes.io/instance=r1 --for=condition=Ready --timeout=0s 1>/dev/null 2>/dev/null -} - -function addons_terminated { - [[ $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get pod -l app.kubernetes.io/instance=r1 --no-headers 2>/dev/null | wc -l) == 0 ]] -} - -function networks_instantiated { - local -r count=$(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get sriovnetworknodestate --no-headers 2>/dev/null | wc -l) - local -r succeeded=$(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get sriovnetworknodestate -o jsonpath='{range .items[*]}{.status.syncStatus}{"\n"}{end}' 2>/dev/null | grep "Succeeded" | wc -l) - [[ $count == $succeeded ]] -} - -function networks_terminated { - # The syncStatus will be the same whether we are instantiating or terminating an SR-IOV network - networks_instantiated -} - -function kubevirt_instantiated { - [[ $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get kubevirt -o jsonpath='{range .items[*]}{.status.phase}{"\n"}{end}' 2>/dev/null | grep "Deployed" | wc -l) == 1 ]] - [[ $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get cdi -o jsonpath='{range .items[*]}{.status.phase}{"\n"}{end}' 2>/dev/null | grep "Deployed" | wc -l) == 1 ]] -} - -function kubevirt_terminated { - [[ $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get kubevirt --no-headers 2>/dev/null | wc -l) == 0 ]] - [[ $(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl -n ${ADDONS_NAMESPACE} get cdi --no-headers 2>/dev/null | wc -l) == 0 ]] -} - -#Apply addons -printf "Applying KUD addons\n" -pushd /opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/addons -emcoctl apply 00-controllers.yaml -emcoctl apply 01-cluster.yaml -emcoctl apply 02-project.yaml -emcoctl apply 03-addons-app.yaml -popd - -#Instantiate addons -emcoctl instantiate addons -wait_for addons_instantiated -emcoctl instantiate networks -wait_for networks_instantiated -emcoctl instantiate kubevirt -wait_for kubevirt_instantiated - -#Test addons -printf "Testing KUD addons\n" -pushd /opt/kud/multi-cluster/addons/tests -failed_kud_tests="" -container_runtime=$(KUBECONFIG=${CLUSTER_KUBECONFIG} kubectl get nodes -o jsonpath='{.items[].status.nodeInfo.containerRuntimeVersion}') -if [[ "${container_runtime}" == "containerd://1.2.13" ]]; then - #With containerd 1.2.13, the qat test container image fails to unpack. - kud_tests="topology-manager-sriov kubevirt multus ovn4nfv nfd sriov-network cmk" -else - kud_tests="topology-manager-sriov kubevirt multus ovn4nfv nfd sriov-network qat cmk" -fi -for test in ${kud_tests}; do - KUBECONFIG=${CLUSTER_KUBECONFIG} bash ${test}.sh || failed_kud_tests="${failed_kud_tests} ${test}" -done -KUBECONFIG=${CLUSTER_KUBECONFIG} DEMO_FOLDER=${PWD} PATH=/opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts:${PATH} bash plugin_fw_v2.sh --external || failed_kud_tests="${failed_kud_tests} plugin_fw_v2" -if [[ ! -z "$failed_kud_tests" ]]; then - printf "Test cases failed:${failed_kud_tests}\n" - exit 1 -fi -popd -printf "All test cases passed\n" - -#Tear down setup -printf "\n\nBeginning BMH E2E Test Teardown\n\n" -emcoctl terminate kubevirt -wait_for kubevirt_terminated -emcoctl terminate networks -wait_for networks_terminated -emcoctl terminate addons -wait_for addons_terminated -pushd /opt/kud/multi-cluster/${CLUSTER_NAME}/artifacts/addons -emcoctl delete 03-addons-app.yaml -emcoctl delete 02-project.yaml -emcoctl delete 01-cluster.yaml -emcoctl delete 00-controllers.yaml -popd -kubectl delete -f e2etest/e2e_test_provisioning_cr.yaml -kubectl delete job kud-${CLUSTER_NAME} -kubectl delete --ignore-not-found=true configmap ${CLUSTER_NAME}-configmap -rm e2etest/e2e_test_provisioning_cr.yaml -rm -rf /opt/kud/multi-cluster/${CLUSTER_NAME} -rm -rf /opt/kud/multi-cluster/addons -make delete diff --git a/deploy/metal3-vm/.gitignore b/deploy/metal3-vm/.gitignore deleted file mode 100644 index 5484a3b..0000000 --- a/deploy/metal3-vm/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -logs -ironic.env -config_*.sh -!config_example.sh -master-*.json -worker-*.json -master-*.yaml -worker-*.yaml -*.bk -*.tmp -*.swp diff --git a/deploy/metal3-vm/01_install_requirements.sh b/deploy/metal3-vm/01_install_requirements.sh deleted file mode 100755 index ca9ce6c..0000000 --- a/deploy/metal3-vm/01_install_requirements.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -OS=$(awk -F= '/^ID=/ { print $2 }' /etc/os-release | tr -d '"') -if [[ $OS == ubuntu ]]; then - # shellcheck disable=SC1091 - source ubuntu_install_requirements.sh -else - # shellcheck disable=SC1091 - source centos_install_requirements.sh -fi diff --git a/deploy/metal3-vm/02_configure_host.sh b/deploy/metal3-vm/02_configure_host.sh deleted file mode 100755 index c316522..0000000 --- a/deploy/metal3-vm/02_configure_host.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# shellcheck disable=SC1091 -source lib/logging.sh -# shellcheck disable=SC1091 -source lib/common.sh - -# Generate user ssh key -if [ ! -f "$HOME/.ssh/id_rsa.pub" ]; then - ssh-keygen -f ~/.ssh/id_rsa -P "" -fi - -# root needs a private key to talk to libvirt -# See tripleo-quickstart-config/roles/virtbmc/tasks/configure-vbmc.yml -if sudo [ ! -f /root/.ssh/id_rsa_virt_power ]; then - sudo ssh-keygen -f /root/.ssh/id_rsa_virt_power -P "" - sudo cat /root/.ssh/id_rsa_virt_power.pub | sudo tee -a /root/.ssh/authorized_keys -fi - -ANSIBLE_FORCE_COLOR=true ansible-playbook \ - -e "working_dir=$WORKING_DIR" \ - -e "num_masters=$NUM_MASTERS" \ - -e "num_workers=$NUM_WORKERS" \ - -e "extradisks=$VM_EXTRADISKS" \ - -e "virthost=$HOSTNAME" \ - -e "platform=$NODES_PLATFORM" \ - -e "manage_baremetal=$MANAGE_BR_BRIDGE" \ - -i vm-setup/inventory.ini \ - -b -vvv vm-setup/setup-playbook.yml - -# Allow local non-root-user access to libvirt -# Restart libvirtd service to get the new group membership loaded -if ! id "$USER" | grep -q libvirt; then - sudo usermod -a -G "libvirt" "$USER" - sudo systemctl restart libvirtd -fi -# Usually virt-manager/virt-install creates this: https://www.redhat.com/archives/libvir-list/2008-August/msg00179.html -if ! virsh pool-uuid default > /dev/null 2>&1 ; then - virsh pool-define /dev/stdin < - default - - /var/lib/libvirt/images - - -EOF - virsh pool-start default - virsh pool-autostart default -fi - -if [[ $OS == ubuntu ]]; then - # source ubuntu_bridge_network_configuration.sh - # shellcheck disable=SC1091 - source ubuntu_bridge_network_configuration.sh - # shellcheck disable=SC1091 - source disable_apparmor_driver_libvirtd.sh -else - if [ "$MANAGE_PRO_BRIDGE" == "y" ]; then - # Adding an IP address in the libvirt definition for this network results in - # dnsmasq being run, we don't want that as we have our own dnsmasq, so set - # the IP address here - if [ ! -e /etc/sysconfig/network-scripts/ifcfg-provisioning ] ; then - echo -e "DEVICE=provisioning\nTYPE=Bridge\nONBOOT=yes\nNM_CONTROLLED=no\nBOOTPROTO=static\nIPADDR=172.22.0.1\nNETMASK=255.255.255.0" | sudo dd of=/etc/sysconfig/network-scripts/ifcfg-provisioning - fi - sudo ip link set dev provisioning down || true - sudo ip link set dev provisioning up - - # Need to pass the provision interface for bare metal - if [ "$PRO_IF" ]; then - echo -e "DEVICE=$PRO_IF\nTYPE=Ethernet\nONBOOT=yes\nNM_CONTROLLED=no\nBRIDGE=provisioning" | sudo dd of="/etc/sysconfig/network-scripts/ifcfg-$PRO_IF" - sudo ip link set dev "$PRO_IF" down || true - sudo ip link set dev "$PRO_IF" up - fi - fi - - if [ "$MANAGE_INT_BRIDGE" == "y" ]; then - # Create the baremetal bridge - if [ ! -e /etc/sysconfig/network-scripts/ifcfg-baremetal ] ; then - echo -e "DEVICE=baremetal\nTYPE=Bridge\nONBOOT=yes\nNM_CONTROLLED=no" | sudo dd of=/etc/sysconfig/network-scripts/ifcfg-baremetal - fi - sudo ip link set dev baremetal down || true - sudo ip link set dev baremetal up - - # Add the internal interface to it if requests, this may also be the interface providing - # external access so we need to make sure we maintain dhcp config if its available - if [ "$INT_IF" ]; then - echo -e "DEVICE=$INT_IF\nTYPE=Ethernet\nONBOOT=yes\nNM_CONTROLLED=no\nBRIDGE=baremetal" | sudo dd of="/etc/sysconfig/network-scripts/ifcfg-$INT_IF" - if sudo nmap --script broadcast-dhcp-discover -e "$INT_IF" | grep "IP Offered" ; then - echo -e "\nBOOTPROTO=dhcp\n" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-baremetal - sudo systemctl restart network - else - sudo systemctl restart network - fi - fi - fi - - # restart the libvirt network so it applies an ip to the bridge - if [ "$MANAGE_BR_BRIDGE" == "y" ] ; then - sudo virsh net-destroy baremetal - sudo virsh net-start baremetal - if [ "$INT_IF" ]; then #Need to bring UP the NIC after destroying the libvirt network - sudo ip link set dev "$INT_IF" up - fi - fi -fi - -# Add firewall rules to ensure the IPA ramdisk can reach httpd, Ironic and the Inspector API on the host -for port in 80 5050 6385 ; do - if ! sudo iptables -C INPUT -i provisioning -p tcp -m tcp --dport $port -j ACCEPT > /dev/null 2>&1; then - sudo iptables -I INPUT -i provisioning -p tcp -m tcp --dport $port -j ACCEPT - fi -done - -# Allow ipmi to the virtual bmc processes that we just started -if ! sudo iptables -C INPUT -i baremetal -p udp -m udp --dport 6230:6235 -j ACCEPT 2>/dev/null ; then - sudo iptables -I INPUT -i baremetal -p udp -m udp --dport 6230:6235 -j ACCEPT -fi - -#Allow access to dhcp and tftp server for pxeboot -for port in 67 69 ; do - if ! sudo iptables -C INPUT -i provisioning -p udp --dport $port -j ACCEPT 2>/dev/null ; then - sudo iptables -I INPUT -i provisioning -p udp --dport $port -j ACCEPT - fi -done - -# Need to route traffic from the provisioning host. -if [ "$EXT_IF" ]; then - sudo iptables -t nat -A POSTROUTING --out-interface "$EXT_IF" -j MASQUERADE - sudo iptables -A FORWARD --in-interface baremetal -j ACCEPT -fi - -# Switch NetworkManager to internal DNS - -if [[ "$MANAGE_BR_BRIDGE" == "y" && $OS == "centos" ]] ; then - sudo mkdir -p /etc/NetworkManager/conf.d/ - sudo crudini --set /etc/NetworkManager/conf.d/dnsmasq.conf main dns dnsmasq - if [ "$ADDN_DNS" ] ; then - echo "server=$ADDN_DNS" | sudo tee /etc/NetworkManager/dnsmasq.d/upstream.conf - fi - if systemctl is-active --quiet NetworkManager; then - sudo systemctl reload NetworkManager - else - sudo systemctl restart NetworkManager - fi -fi - -for name in ironic ironic-inspector dnsmasq httpd mariadb ipa-downloader; do - sudo "${CONTAINER_RUNTIME}" ps | grep -w "$name$" && sudo "${CONTAINER_RUNTIME}" kill $name - sudo "${CONTAINER_RUNTIME}" ps --all | grep -w "$name$" && sudo "${CONTAINER_RUNTIME}" rm $name -f -done -rm -rf "$IRONIC_DATA_DIR" - -mkdir -p "$IRONIC_DATA_DIR/html/images" -pushd "$IRONIC_DATA_DIR/html/images" -BM_IMAGE=${BM_IMAGE:-"bionic-server-cloudimg-amd64.img"} -BM_IMAGE_URL=${BM_IMAGE_URL:-"https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img"} -if [ ! -f ${BM_IMAGE} ] ; then - curl -o ${BM_IMAGE} --insecure --compressed -O -L ${BM_IMAGE_URL} - md5sum ${BM_IMAGE} | awk '{print $1}' > ${BM_IMAGE}.md5sum -fi -popd - -for IMAGE_VAR in IRONIC_IMAGE IRONIC_INSPECTOR_IMAGE IPA_DOWNLOADER_IMAGE; do - IMAGE=${!IMAGE_VAR} - sudo "${CONTAINER_RUNTIME}" pull "$IMAGE" -done - -# set password for mariadb -mariadb_password="$(echo "$(date;hostname)"|sha256sum |cut -c-20)" - -cat < ${PWD}/ironic.env -PROVISIONING_INTERFACE=provisioning -DHCP_RANGE=172.22.0.10,172.22.0.100 -IPA_BASEURI=https://images.rdoproject.org/train/rdo_trunk/current-tripleo -DEPLOY_KERNEL_URL=http://172.22.0.1/images/ironic-python-agent.kernel -DEPLOY_RAMDISK_URL=http://172.22.0.1/images/ironic-python-agent.initramfs -IRONIC_ENDPOINT=http://172.22.0.1:6385/v1/ -IRONIC_INSPECTOR_ENDPOINT=http://172.22.0.1:5050/v1/ -CACHEURL=http://172.22.0.1/images -IRONIC_FAST_TRACK=false -EOF - -# Start image downloader container -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name ipa-downloader \ - --env-file "${PWD}/ironic.env" \ - -v "$IRONIC_DATA_DIR:/shared" "${IPA_DOWNLOADER_IMAGE}" /usr/local/bin/get-resource.sh - -sudo "${CONTAINER_RUNTIME}" wait ipa-downloader - -if [ ! -e "$IRONIC_DATA_DIR/html/images/ironic-python-agent.kernel" ] || - [ ! -e "$IRONIC_DATA_DIR/html/images/ironic-python-agent.initramfs" ]; then - echo "Failed to get ironic-python-agent" - exit 1 -fi - -# Start dnsmasq, http, mariadb, and ironic containers using same image -# See this file for env vars you can set, like IP, DHCP_RANGE, INTERFACE -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name dnsmasq \ - --env-file "${PWD}/ironic.env" \ - -v "$IRONIC_DATA_DIR:/shared" --entrypoint /bin/rundnsmasq "${IRONIC_IMAGE}" - -# For available env vars, see: -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name httpd \ - --env-file "${PWD}/ironic.env" \ - -v "$IRONIC_DATA_DIR:/shared" --entrypoint /bin/runhttpd "${IRONIC_IMAGE}" - -# https://github.com/metal3-io/ironic/blob/master/runmariadb.sh -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name mariadb \ - --env-file "${PWD}/ironic.env" \ - -v "$IRONIC_DATA_DIR:/shared" --entrypoint /bin/runmariadb \ - --env "MARIADB_PASSWORD=$mariadb_password" "${IRONIC_IMAGE}" - -# See this file for additional env vars you may want to pass, like IP and INTERFACE -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name ironic \ - --env-file "${PWD}/ironic.env" \ - --env "MARIADB_PASSWORD=$mariadb_password" \ - -v "$IRONIC_DATA_DIR:/shared" "${IRONIC_IMAGE}" - -# Start Ironic Inspector -sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name ironic-inspector \ - --env-file "${PWD}/ironic.env" \ - -v "$IRONIC_DATA_DIR:/shared" "${IRONIC_INSPECTOR_IMAGE}" diff --git a/deploy/metal3-vm/03_launch_mgmt_cluster.sh b/deploy/metal3-vm/03_launch_mgmt_cluster.sh deleted file mode 100755 index b72a30b..0000000 --- a/deploy/metal3-vm/03_launch_mgmt_cluster.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# shellcheck disable=SC1091 -source lib/logging.sh -# shellcheck disable=SC1091 -source lib/common.sh - -eval "$(go env)" -export GOPATH -DEPLOYDIR="$(dirname "$PWD")" -BMODIR=$DEPLOYDIR/metal3/scripts/bmo - -# Environment variables -# M3PATH : Path to clone the metal3 dev env repo -# BMOPATH : Path to clone the baremetal operator repo -# -# BMOREPO : Baremetal operator repository URL -# BMOBRANCH : Baremetal operator repository branch to checkout -# FORCE_REPO_UPDATE : discard existing directories -# -# BMO_RUN_LOCAL : run the baremetal operator locally (not in Kubernetes cluster) - -M3PATH="${GOPATH}/src/github.com/metal3-io" -BMOPATH="${M3PATH}/baremetal-operator" - -BMOREPO="${BMOREPO:-https://github.com/metal3-io/baremetal-operator.git}" -BMOBRANCH="${BMOBRANCH:-10eb5aa3e614d0fdc6315026ebab061cbae6b929}" -FORCE_REPO_UPDATE="${FORCE_REPO_UPDATE:-true}" - -BMO_RUN_LOCAL="${BMO_RUN_LOCAL:-false}" -COMPUTE_NODE_PASSWORD="${COMPUTE_NODE_PASSWORD:-mypasswd}" -BM_IMAGE=${BM_IMAGE:-"bionic-server-cloudimg-amd64.img"} -IMAGE_URL=http://172.22.0.1/images/${BM_IMAGE} -IMAGE_CHECKSUM=http://172.22.0.1/images/${BM_IMAGE}.md5sum - -function clone_repos { - mkdir -p "${M3PATH}" - if [[ -d ${BMOPATH} && "${FORCE_REPO_UPDATE}" == "true" ]]; then - rm -rf "${BMOPATH}" - fi - if [ ! -d "${BMOPATH}" ] ; then - pushd "${M3PATH}" - git clone "${BMOREPO}" - popd - fi - pushd "${BMOPATH}" - git checkout "${BMOBRANCH}" - git pull -r || true - popd -} - -function launch_baremetal_operator { - docker pull $IRONIC_BAREMETAL_IMAGE - kubectl apply -f $BMODIR/namespace/namespace.yaml - kubectl apply -f $BMODIR/rbac/service_account.yaml -n metal3 - kubectl apply -f $BMODIR/rbac/role.yaml -n metal3 - kubectl apply -f $BMODIR/rbac/role_binding.yaml - kubectl apply -f $BMODIR/crds/metal3.io_baremetalhosts_crd.yaml - kubectl apply -f $BMODIR/operator/no_ironic/operator.yaml -n metal3 -} - -# documentation for the values below may be found at -# https://cloudinit.readthedocs.io/en/latest/topics/modules.html -function create_userdata { - name="$1" - COMPUTE_NODE_FQDN="$name.akraino.icn.org" - printf "#cloud-config\n" > $name-userdata.yaml - if [ -n "$COMPUTE_NODE_PASSWORD" ]; then - printf "password: ""%s" "$COMPUTE_NODE_PASSWORD" >> $name-userdata.yaml - printf "\nchpasswd: {expire: False}\n" >> $name-userdata.yaml - printf "ssh_pwauth: True\n" >> $name-userdata.yaml - fi - - if [ -n "$COMPUTE_NODE_FQDN" ]; then - printf "fqdn: ""%s" "$COMPUTE_NODE_FQDN" >> $name-userdata.yaml - printf "\n" >> $name-userdata.yaml - fi - printf "disable_root: false\n" >> $name-userdata.yaml - printf "ssh_authorized_keys:\n - " >> $name-userdata.yaml - - if [ ! -f $HOME/.ssh/id_rsa.pub ]; then - yes y | ssh-keygen -t rsa -N "" -f $HOME/.ssh/id_rsa - fi - - cat $HOME/.ssh/id_rsa.pub >> $name-userdata.yaml - cloud_init_scripts >> $name-userdata.yaml - printf "\n" >> $name-userdata.yaml -} - -function cloud_init_scripts { - # set_dhcp_indentifier.sh: - # The IP address assigned to the provisioning NIC will change - # due to IPA using the MAC address as the client ID and systemd - # using a different ID. Tell systemd to use the MAC as the - # client ID. We can't do this in the network data as only the - # JSON format is supported by metal3, and the JSON format does - # not support the dhcp-identifier field. - cat << 'EOF' -write_files: -- path: /var/lib/cloud/scripts/per-instance/set_dhcp_identifier.sh - owner: root:root - permissions: '0777' - content: | - #!/usr/bin/env bash - set -eux -o pipefail - sed -i -e '/dhcp4: true$/!b' -e 'h;s/\S.*/dhcp-identifier: mac/;H;g' /etc/netplan/50-cloud-init.yaml - netplan apply -EOF -} - -function apply_userdata_credential { - name="$1" - cat < ./$name-user-data-credential.yaml -apiVersion: v1 -data: - userData: $(base64 -w 0 $name-userdata.yaml) -kind: Secret -metadata: - name: $name-user-data - namespace: metal3 -type: Opaque -EOF - kubectl apply -n metal3 -f $name-user-data-credential.yaml -} - -function create_networkdata { - name="$1" - node_networkdata $name > $name-networkdata.json -} - -function apply_networkdata_credential { - name="$1" - cat < ./$name-network-data-credential.yaml -apiVersion: v1 -data: - networkData: $(base64 -w 0 $name-networkdata.json) -kind: Secret -metadata: - name: $name-network-data - namespace: metal3 -type: Opaque -EOF - kubectl apply -n metal3 -f $name-network-data-credential.yaml -} - -function make_bm_hosts { - while IFS=',' read -r name address user password mac; do - create_userdata $name - apply_userdata_credential $name - create_networkdata $name - apply_networkdata_credential $name - GO111MODULE=auto go run "${BMOPATH}"/cmd/make-bm-worker/main.go \ - -address "$address" \ - -password "$password" \ - -user "$user" \ - -boot-mac "$mac" \ - "$name" > $name-bm-node.yaml - printf " image:" >> $name-bm-node.yaml - printf "\n url: ""%s" "${IMAGE_URL}" >> $name-bm-node.yaml - printf "\n checksum: ""%s" "${IMAGE_CHECKSUM}" >> $name-bm-node.yaml - printf "\n userData:" >> $name-bm-node.yaml - printf "\n name: ""%s" "$name""-user-data" >> $name-bm-node.yaml - printf "\n namespace: metal3" >> $name-bm-node.yaml - printf "\n networkData:" >> $name-bm-node.yaml - printf "\n name: ""%s" "$name""-network-data" >> $name-bm-node.yaml - printf "\n namespace: metal3" >> $name-bm-node.yaml - printf "\n rootDeviceHints:" >> $name-bm-node.yaml - printf "\n minSizeGigabytes: 48\n" >> $name-bm-node.yaml - kubectl apply -f $name-bm-node.yaml -n metal3 - done -} - -function apply_bm_hosts { - list_nodes | make_bm_hosts -} - -clone_repos -launch_baremetal_operator -apply_bm_hosts diff --git a/deploy/metal3-vm/04_verify.sh b/deploy/metal3-vm/04_verify.sh deleted file mode 100755 index 70fbf22..0000000 --- a/deploy/metal3-vm/04_verify.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -# shellcheck disable=SC1091 -source lib/common.sh - -declare -i timeout=30 -declare -i interval=60 - -function check_provisioned { - declare -i prev_host_state=0 - declare -i j=0 - echo "VM state: 1 means provisioned & 0 means not yet provisioned" - while IFS=',' read -r name address user password mac; do - declare -i current_host_state=0 - state=$(kubectl get baremetalhosts $name -n metal3 -o json | jq -r '.status.provisioning.state') - echo "VM host metal3 state - "$name" : "$state - - if [ $state == "provisioned" ];then - current_host_state=1 - fi - - echo "VM $name current_host_state : "$current_host_state - echo "VMs prev_host_state : "$prev_host_state - - if [ $j -eq 0 ]; then - prev_host_state=$current_host_state - ((j+=1)) - continue - fi - - if [ $current_host_state -eq 1 ] && [ $prev_host_state -eq 1 ]; then - prev_host_state=1 - else - prev_host_state=0 - fi - - echo "All VM hosts aggregated state - prev_host_state:"$prev_host_state - ((j+=1)) - done - return $prev_host_state -} - -function warm_up_time { - echo "Wait for 75s for all VM to reboot and network is up" - sleep 75 -} - -function wait_for_provisioned { - declare -i k=1 - declare -i t=$timeout - while ((t > 0)); do - echo "Try $k/$timeout iteration : Wait for $interval seconds to check all bmh state" - sleep $interval - if ! list_nodes | check_provisioned; then - echo "All the VMs are provisioned - success" - warm_up_time - exit 0 - fi - ((t-=1)) - ((k+=1)) - done - exit 1 -} - -function verify_bm_hosts { - wait_for_provisioned -} - -verify_bm_hosts diff --git a/deploy/metal3-vm/05_host_cleanup.sh b/deploy/metal3-vm/05_host_cleanup.sh deleted file mode 100755 index 1e69d12..0000000 --- a/deploy/metal3-vm/05_host_cleanup.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# shellcheck disable=SC1091 -source lib/logging.sh -# shellcheck disable=SC1091 -source lib/common.sh - -BMO_RUN_LOCAL="${BMO_RUN_LOCAL:-false}" -CAPBM_RUN_LOCAL="${CAPBM_RUN_LOCAL:-false}" - -# Kill and remove the running ironic containers -for name in ironic ironic-inspector dnsmasq httpd mariadb ipa-downloader; do - sudo "${CONTAINER_RUNTIME}" ps | grep -w "$name$" && sudo "${CONTAINER_RUNTIME}" kill $name - sudo "${CONTAINER_RUNTIME}" ps --all | grep -w "$name$" && sudo "${CONTAINER_RUNTIME}" rm $name -f -done - -# Kill the locally running operators -if [ "${BMO_RUN_LOCAL}" = true ]; then - kill "$(pgrep "operator-sdk")" 2> /dev/null || true -fi -if [ "${CAPBM_RUN_LOCAL}" = true ]; then - CAPBM_PARENT_PID="$(pgrep -f "go run ./cmd/manager/main.go")" - if [[ "${CAPBM_PARENT_PID}" != "" ]]; then - CAPBM_GO_PID="$(pgrep -P "${CAPBM_PARENT_PID}" )" - kill "${CAPBM_GO_PID}" 2> /dev/null || true - fi -fi - - -ANSIBLE_FORCE_COLOR=true ansible-playbook \ - -e "working_dir=$WORKING_DIR" \ - -e "num_masters=$NUM_MASTERS" \ - -e "num_workers=$NUM_WORKERS" \ - -e "extradisks=$VM_EXTRADISKS" \ - -e "virthost=$HOSTNAME" \ - -e "manage_baremetal=$MANAGE_BR_BRIDGE" \ - -i vm-setup/inventory.ini \ - -b -vvv vm-setup/teardown-playbook.yml - -sudo rm -rf /etc/NetworkManager/conf.d/dnsmasq.conf -# There was a bug in this file, it may need to be recreated. -if [ "$MANAGE_PRO_BRIDGE" == "y" ]; then - sudo ip link set dev provisioning down || true - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-provisioning || true -fi -# Leaving this around causes issues when the host is rebooted -if [ "$MANAGE_BR_BRIDGE" == "y" ]; then - sudo ip link set dev baremetal down || true - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-baremetal || true -fi - -rm -rf $WORKING_DIR -rm -rf $IRONIC_DATA_DIR diff --git a/deploy/metal3-vm/Makefile b/deploy/metal3-vm/Makefile deleted file mode 100644 index 29a4ab3..0000000 --- a/deploy/metal3-vm/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -all: bmh_install bmh_configure bmh_launch bmh_verify - -bmh: bmh_configure bmh_launch bmh_verify - -bmh_install: - ./01_install_requirements.sh - -bmh_configure: - ./02_configure_host.sh - -bmh_launch: - ./03_launch_mgmt_cluster.sh - -bmh_verify: - ./04_verify.sh - -bmh_clean: - ./05_host_cleanup.sh - -.PHONY: all bmh bmh_install bmh_configure bmh_launch bmh_verify bmh_clean diff --git a/deploy/metal3-vm/config_example.sh b/deploy/metal3-vm/config_example.sh deleted file mode 100644 index 9f53d24..0000000 --- a/deploy/metal3-vm/config_example.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# -# This is the subnet used on the "baremetal" libvirt network, created as the -# primary network interface for the virtual bare metalhosts. -# -# Default of 192.168.111.0/24 set in lib/common.sh -# -#export EXTERNAL_SUBNET="192.168.111.0/24" - -# -# This SSH key will be automatically injected into the provisioned host -# by the provision_host.sh script. -# -# Default of ~/.ssh/id_rsa.pub is set in lib/common.sh -# -#export SSH_PUB_KEY=~/.ssh/id_rsa.pub - -# -# Select the Container Runtime, can be "docker" or "containerd" -# Defaults to "docker" -# -#export CONTAINER_RUNTIME="docker" - -# -# Set the Baremetal Operator repository to clone -# -#export BMOREPO="${BMOREPO:-https://github.com/metal3-io/baremetal-operator.git}" - -# -# Set the Baremetal Operator branch to checkout -# -#export BMOBRANCH="${BMOBRANCH:-master}" - -# -# Force deletion of the BMO and CAPBM repositories before cloning them again -# -#export FORCE_REPO_UPDATE="${FORCE_REPO_UPDATE:-false}" - -# -# Run a local baremetal operator instead of deploying in Kubernetes -# -#export BMO_RUN_LOCAL=true diff --git a/deploy/metal3-vm/disable_apparmor_driver_libvirtd.sh b/deploy/metal3-vm/disable_apparmor_driver_libvirtd.sh deleted file mode 100644 index 5aca6d6..0000000 --- a/deploy/metal3-vm/disable_apparmor_driver_libvirtd.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -selinux="#security_driver = \"selinux\"" -apparmor="security_driver = \"apparmor\"" -none="security_driver = \"none\"" -sudo sed -i "s/$selinux/$none/g" /etc/libvirt/qemu.conf -sudo sed -i "s/$apparmor/$none/g" /etc/libvirt/qemu.conf -sudo systemctl restart libvirtd diff --git a/deploy/metal3-vm/lib/common.sh b/deploy/metal3-vm/lib/common.sh deleted file mode 100644 index cc48dd6..0000000 --- a/deploy/metal3-vm/lib/common.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -eval "$(go env)" - -SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -USER=`whoami` - -# Get variables from the config file -if [ -z "${CONFIG:-}" ]; then - # See if there's a config_$USER.sh in the SCRIPTDIR - if [ ! -f ${SCRIPTDIR}/../config_${USER}.sh ]; then - cp ${SCRIPTDIR}/../config_example.sh ${SCRIPTDIR}/../config_${USER}.sh - echo "Automatically created config_${USER}.sh with default contents." - fi - CONFIG="${SCRIPTDIR}/../config_${USER}.sh" -fi -source $CONFIG - -# Set variables -# Additional DNS -ADDN_DNS=${ADDN_DNS:-} -# External interface for routing traffic through the host -EXT_IF=${EXT_IF:-} -# Provisioning interface -PRO_IF=${PRO_IF:-} -# Does libvirt manage the baremetal bridge (including DNS and DHCP) -MANAGE_BR_BRIDGE=${MANAGE_BR_BRIDGE:-y} -# Only manage bridges if is set -MANAGE_PRO_BRIDGE=${MANAGE_PRO_BRIDGE:-y} -MANAGE_INT_BRIDGE=${MANAGE_INT_BRIDGE:-y} -# Internal interface, to bridge virbr0 -INT_IF=${INT_IF:-} -#Container runtime -CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-"docker"} - -export EXTERNAL_SUBNET="192.168.111.0/24" -#Ironic data directory -IRONIC_DATA_DIR=${IRONIC_DATA_DIR:-"/opt/ironic"} -export SSH_PUB_KEY=~/.ssh/id_rsa.pub - -FILESYSTEM=${FILESYSTEM:="/"} - -WORKING_DIR=${WORKING_DIR:-"/opt/metal3-vm"} -NODES_FILE=${NODES_FILE:-"${WORKING_DIR}/ironic_nodes.json"} -NODES_PLATFORM=${NODES_PLATFORM:-"libvirt"} - -export NUM_MASTERS=${NUM_MASTERS:-"1"} -export NUM_WORKERS=${NUM_WORKERS:-"1"} -export VM_EXTRADISKS=${VM_EXTRADISKS:-"false"} - -# Ironic vars -export IRONIC_IMAGE=${IRONIC_IMAGE:-"integratedcloudnative/ironic:v1.0-icn"} -export IRONIC_INSPECTOR_IMAGE=${IRONIC_INSPECTOR_IMAGE:-"integratedcloudnative/ironic-inspector:v1.0-icn"} -export IRONIC_BAREMETAL_IMAGE=${IRONIC_BAREMETAL_IMAGE:-"integratedcloudnative/baremetal-operator:v2.0-icn"} -export IPA_DOWNLOADER_IMAGE=${IPA_DOWNLOADER_IMAGE:-"integratedcloudnative/ironic-ipa-downloader:v1.0-icn"} - -# Verify requisites/permissions -# Connect to system libvirt -export LIBVIRT_DEFAULT_URI=qemu:///system -if [ "$USER" != "root" -a "${XDG_RUNTIME_DIR:-}" == "/run/user/0" ] ; then - echo "Please use a non-root user, WITH a login shell (e.g. su - USER)" - exit 1 -fi - -# Check if sudo privileges without password -if ! sudo -n uptime &> /dev/null ; then - echo "sudo without password is required" - exit 1 -fi - -# Check OS -OS=$(awk -F= '/^ID=/ { print $2 }' /etc/os-release | tr -d '"') -if [[ ! $OS =~ ^(centos|rhel|ubuntu)$ ]]; then - echo "Unsupported OS" - exit 1 -fi - -# Check CentOS version -os_version=$(awk -F= '/^VERSION_ID=/ { print $2 }' /etc/os-release | tr -d '"' | cut -f1 -d'.') -if [[ ${os_version} -ne 7 ]] && [[ ${os_version} -ne 18 ]]; then - echo "Required CentOS 7 or RHEL 7 or Ubuntu 18.04" - exit 1 -fi - -# Check d_type support -FSTYPE=$(df ${FILESYSTEM} --output=fstype | grep -v Type) - -case ${FSTYPE} in - 'ext4'|'btrfs') - ;; - 'xfs') - if [[ $(xfs_info ${FILESYSTEM} | grep -q "ftype=1") ]]; then - echo "Filesystem not supported" - exit 1 - fi - ;; - *) - echo "Filesystem not supported" - exit 1 - ;; -esac - -if [ ! -d "$WORKING_DIR" ]; then - echo "Creating Working Dir" - sudo mkdir "$WORKING_DIR" - sudo chown "${USER}:${USER}" "$WORKING_DIR" - chmod 755 "$WORKING_DIR" -fi - -function list_nodes { - # Includes -machine and -machine-namespace - cat $NODES_FILE | \ - jq -r '.nodes[] | [ - .name, - .driver + "://" + .driver_info.ipmi_address + (if .driver_info.ipmi_port then ":" + .driver_info.ipmi_port else "" end), - .driver_info.ipmi_username, - .driver_info.ipmi_password, - .ports[0].address - ] | @csv' | \ - sed 's/"//g' -} - -function node_networkdata { - name=$1 - cat $NODES_FILE | jq -r --arg name "$name" '.nodes[] | select(.name==$name) | .net' -} diff --git a/deploy/metal3-vm/lib/logging.sh b/deploy/metal3-vm/lib/logging.sh deleted file mode 100644 index e936439..0000000 --- a/deploy/metal3-vm/lib/logging.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -# Log output automatically -LOGDIR="$(dirname $0)/logs" -if [ ! -d "$LOGDIR" ]; then - mkdir -p "$LOGDIR" -fi -LOGFILE="$LOGDIR/$(basename $0 .sh)-$(date +%F-%H%M%S).log" -echo "Logging to $LOGFILE" -# Set fd 1 and 2 to write to the log file -exec 1> >( tee "${LOGFILE}" ) 2>&1 diff --git a/deploy/metal3-vm/ubuntu_bridge_network_configuration.sh b/deploy/metal3-vm/ubuntu_bridge_network_configuration.sh deleted file mode 100755 index 60875cb..0000000 --- a/deploy/metal3-vm/ubuntu_bridge_network_configuration.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# shellcheck disable=SC1091 -source lib/logging.sh -# shellcheck disable=SC1091 -source lib/common.sh - -if [ "$MANAGE_PRO_BRIDGE" == "y" ]; then - # Adding an IP address in the libvirt definition for this network results in - # dnsmasq being run, we don't want that as we have our own dnsmasq, so set - # the IP address here - sudo ip link add dev provisioning type bridge - sudo ip addr add dev provisioning 172.22.0.1/24 - sudo ip link set provisioning up - - # Need to pass the provision interface for bare metal - if [ "$PRO_IF" ]; then - sudo ip link set dev "$PRO_IF" master provisioning - fi - fi - - if [ "$MANAGE_INT_BRIDGE" == "y" ]; then - # Create the baremetal bridge - if ! [[ $(ip a show baremetal) ]]; then - sudo ip link add dev baremetal type bridge - sudo ip addr add dev baremetal 192.168.111.1/24 - sudo ip link set baremetal up - fi - - # Add the internal interface to it if requests, this may also be the interface providing - # external access so we need to make sure we maintain dhcp config if its available - if [ "$INT_IF" ]; then - sudo ip link set dev "$INT_IF" master baremetal - fi - fi - - # restart the libvirt network so it applies an ip to the bridge - if [ "$MANAGE_BR_BRIDGE" == "y" ] ; then - sudo virsh net-destroy baremetal - sudo virsh net-start baremetal - if [ "$INT_IF" ]; then #Need to bring UP the NIC after destroying the libvirt network - sudo ip link set dev "$INT_IF" up - fi - fi diff --git a/deploy/metal3-vm/ubuntu_install_requirements.sh b/deploy/metal3-vm/ubuntu_install_requirements.sh deleted file mode 100755 index c39e1d1..0000000 --- a/deploy/metal3-vm/ubuntu_install_requirements.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# shellcheck disable=SC1091 -source lib/logging.sh -# shellcheck disable=SC1091 -source lib/common.sh - -# Update to latest packages first -sudo apt -y update - -# Install required packages - -sudo apt -y install \ - crudini \ - curl \ - dnsmasq \ - figlet \ - golang \ - zlib1g-dev \ - libssl1.0-dev \ - nmap \ - patch \ - psmisc \ - python3-pip \ - wget - -sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 -sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 - -# Install pyenv - -if [[ $(cat ~/.bashrc) != *PYENV_ROOT* ]]; then - if ! [ -d "$HOME/.pyenv" ] ; then - git clone git://github.com/yyuu/pyenv.git ~/.pyenv - fi - # shellcheck disable=SC2016 - # shellcheck disable=SC2129 - echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc - # shellcheck disable=SC2016 - echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc - # shellcheck disable=SC2016 - echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc -fi - -if [[ $PATH != *pyenv* ]]; then - export PYENV_ROOT="$HOME/.pyenv" - export PATH="$PYENV_ROOT/bin:$PATH" - if command -v pyenv 1>/dev/null 2>&1; then - eval "$(pyenv init -)" - fi -fi - -# There are some packages which are newer in the tripleo repos - -# Setup yarn and nodejs repositories -#sudo curl -sL https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo -curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - -#curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash - -echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list - -# Add this repository to install Golang 1.12 -sudo add-apt-repository -y ppa:longsleep/golang-backports - -# Update some packages from new repos -sudo apt -y update - -# make sure additional requirments are installed - -##No bind-utils. It is for host, nslookop,..., no need in ubuntu -sudo apt -y install \ - jq \ - libguestfs-tools \ - nodejs \ - qemu-kvm \ - libvirt-bin libvirt-clients libvirt-dev \ - golang-go \ - unzip \ - yarn \ - genisoimage - -# Install python packages not included as rpms -sudo pip install \ - ansible==2.8.2 \ - lolcat \ - yq \ - virtualbmc==1.6.0 \ - python-ironicclient \ - python-ironic-inspector-client \ - lxml \ - netaddr \ - requests \ - setuptools \ - libvirt-python==5.7.0 \ diff --git a/deploy/metal3-vm/vm-setup/inventory.ini b/deploy/metal3-vm/vm-setup/inventory.ini deleted file mode 100644 index d6d53d4..0000000 --- a/deploy/metal3-vm/vm-setup/inventory.ini +++ /dev/null @@ -1,2 +0,0 @@ -[virthost] -localhost diff --git a/deploy/metal3-vm/vm-setup/library/generate_macs.py b/deploy/metal3-vm/vm-setup/library/generate_macs.py deleted file mode 100644 index d4f09fb..0000000 --- a/deploy/metal3-vm/vm-setup/library/generate_macs.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/python -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generate_baremetal_macs method ripped from -# openstack/tripleo-incubator/scripts/configure-vm - -import marshal -import math -import random - -DOCUMENTATION = ''' ---- -module: generate_macs -version_added: "2.0" -short_description: Generate a list of Ethernet MAC addresses -description: - - Generate a list of Ethernet MAC addresses suitable for baremetal testing. -''' - -MAX_NUM_MACS = math.trunc(0xff / 2) - - -def generate_baremetal_macs(nodes, networks): - """Generate an Ethernet MAC address suitable for baremetal testing.""" - # NOTE(dprince): We generate our own bare metal MAC address's here - # instead of relying on libvirt so that we can ensure the - # locally administered bit is set low. (The libvirt default is - # to set the 2nd MSB high.) This effectively allows our - # fake baremetal VMs to more accurately behave like real hardware - # and fixes issues with bridge/DHCP configurations which rely - # on the fact that bridges assume the MAC address of the lowest - # attached NIC. - # MACs generated for a given machine will also be in sequential - # order, which matches how most BM machines are laid out as well. - # Additionally we increment each MAC by two places. - macs = [] - count = len(nodes) * len(networks) - - if count > MAX_NUM_MACS: - raise ValueError("The MAX num of MACS supported is %i " - "(you specified %i)." % (MAX_NUM_MACS, count)) - - # See the random number generator with the input so that MAC - # generation is idempotent. - random.seed(marshal.dumps(nodes + networks)) - - base_nums = [0x00, - random.randint(0x00, 0xff), - random.randint(0x00, 0xff), - random.randint(0x00, 0xff), - random.randint(0x00, 0xff)] - base_mac = ':'.join(map(lambda x: "%02x" % x, base_nums)) - - start = random.randint(0x00, 0xff) - if (start + (count * 2)) > 0xff: - # leave room to generate macs in sequence - start = 0xff - count * 2 - for num in range(0, count * 2, 2): - mac = start + num - macs.append(base_mac + ":" + ("%02x" % mac)) - - result = {} - for node in nodes: - result[node['name']] = {} - for network in networks: - result[node['name']][network['name']] = macs.pop(0) - - return result - - -def main(): - module = AnsibleModule( - argument_spec=dict( - nodes=dict(required=True, type='list'), - networks=dict(required=True, type='list') - ) - ) - result = generate_baremetal_macs(module.params["nodes"], - module.params["networks"]) - module.exit_json(**result) - -# see http://docs.ansible.com/developing_modules.html#common-module-boilerplate -from ansible.module_utils.basic import AnsibleModule # noqa - - -if __name__ == '__main__': - main() diff --git a/deploy/metal3-vm/vm-setup/roles/common/defaults/main.yml b/deploy/metal3-vm/vm-setup/roles/common/defaults/main.yml deleted file mode 100644 index 40751bc..0000000 --- a/deploy/metal3-vm/vm-setup/roles/common/defaults/main.yml +++ /dev/null @@ -1,45 +0,0 @@ -non_root_user: "{{ lookup('env', 'USER') }}" - -# base domain to use -cluster_domain: "{{ lookup('env', 'CLUSTER_DOMAIN') | default('ostest.test.metalkube.org', true) }}" - -# allow the nic model to be overridden -libvirt_nic_model: virtio - -# These defaults are used if there are no flavor-specific -# overrides configured. -default_disk: 50 -default_memory: 16384 -default_vcpu: 8 -num_masters: 1 -num_workers: 1 -extradisks: false -virtualbmc_base_port: 6230 -flavors: - master: - memory: '{{master_memory|default(default_memory)}}' - disk: '{{master_disk|default(default_disk)}}' - vcpu: '{{master_vcpu|default(default_vcpu)}}' - extradisks: '{{extradisks|bool}}' - - worker: - memory: '{{worker_memory|default(default_memory)}}' - disk: '{{worker_disk|default(default_disk)}}' - vcpu: '{{worker_vcpu|default(default_vcpu)}}' - extradisks: '{{extradisks|bool}}' - -# An optional prefix for node names -ironic_prefix: "" - -baremetal_network_cidr: "{{ lookup('env', 'EXTERNAL_SUBNET') | default('192.168.111.0/24', true) }}" - -# Set this to `false` if you don't want your vms -# to have a VNC console available. -enable_vnc_console: true - -# Path for volume storage -libvirt_volume_path: "{{ working_dir }}/pool" - -# These ensure we're using privileged virt, so VMs persist over reboot -libvirt_uri: qemu:///system -ssh_user: root diff --git a/deploy/metal3-vm/vm-setup/roles/common/tasks/main.yml b/deploy/metal3-vm/vm-setup/roles/common/tasks/main.yml deleted file mode 100644 index 05c4dca..0000000 --- a/deploy/metal3-vm/vm-setup/roles/common/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ ---- - -- set_fact: - generate_vm_nodes: "{{vm_nodes is not defined}}" - -- name: Define vm_nodes if not already defined - when: generate_vm_nodes - block: - - name: Generate vm_nodes for "{{num_masters}}" masters - set_fact: - vm_nodes: "{{vm_nodes|default([]) + [ - {'name': ironic_prefix + 'master_%s'|format(item), - 'flavor': 'master', - 'virtualbmc_port': virtualbmc_base_port+item}]}}" - loop: "{{ range(0, num_masters|int)|list }}" - - - name: Generate vm_nodes for "{{num_workers}}" workers - set_fact: - vm_nodes: "{{vm_nodes|default([]) + [ - {'name': ironic_prefix + 'worker_%s'|format(item), - 'flavor': 'worker', - 'virtualbmc_port': virtualbmc_base_port+num_masters|int+item} ]}}" - loop: "{{ range(0, num_workers|int)|list }}" - -# Describe our virtual networks. These networks will be attached to -# the vm nodes in the order in which they are defined with the following caveats: -# * The first bridge network defined will be used for pxe booting -- set_fact: - generate_networks: "{{networks is not defined}}" -- name: Define networks when not already defined - when: generate_networks - block: - - name: Generate dhcp entries on baremetal network for "{{num_masters}}" masters - set_fact: - dhcp_hosts: "{{dhcp_hosts|default([]) + [ - {'name': 'master-%s'|format(item), - 'ip': baremetal_network_cidr|nthhost(20+item)|string}]}}" - loop: "{{ range(0, num_masters|int)|list }}" - - - name: Generate dhcp entries on baremetal network for "{{num_workers}}" workers - set_fact: - dhcp_hosts: "{{dhcp_hosts|default([]) + [ - {'name': 'worker-%s'|format(item), - 'ip': baremetal_network_cidr|nthhost(20+num_masters|int+item)|string} ]}}" - loop: "{{ range(0, num_workers|int)|list }}" - - - name: Set fact for networks - set_fact: - networks: - - name: provisioning - bridge: provisioning - forward_mode: bridge - - name: baremetal - bridge: baremetal - forward_mode: "{% if manage_baremetal == 'y' %}nat{% else %}bridge{% endif %}" - address: "{{ baremetal_network_cidr|nthhost(1) }}" - netmask: "{{ baremetal_network_cidr|ipaddr('netmask') }}" - dhcp_range: - - "{{ baremetal_network_cidr|nthhost(20) }}" - - "{{ baremetal_network_cidr|nthhost(60) }}" - dhcp_hosts: "{{dhcp_hosts}}" - nat_port_range: - - 1024 - - 65535 - domain: "{{ cluster_domain }}" - dns: - hosts: "{{dns_extrahosts | default([])}}" - forwarders: - - domain: "apps.{{ cluster_domain }}" - addr: "127.0.0.1" diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/defaults/main.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/defaults/main.yml deleted file mode 100644 index 3e477b0..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/defaults/main.yml +++ /dev/null @@ -1,63 +0,0 @@ -# When libvirt_action==teardown we destroy the existing configuration -libvirt_action: setup - -# For some baremetal testing we set this to "baremetal" so that only the -# libvirt networking is configured, not the nodes -vm_platform: libvirt - -# Which libvirt session should we use? Using `qemu://session` does -# not require privileged access (but does require the setup performed by the -# `environment/setup` role). -libvirt_volume_pool: oooq_pool -libvirt_domain_type: kvm -libvirt_diskdev: sda -libvirt_diskbus: scsi -libvirt_arch: x86_64 -libvirt_cpu_mode: host-model - -# how many disks should be created when using extradisks -extradisks_list: - - vdb - -# size of the disks to create when using extradisks -extradisks_size: 8G - -# The packages required to set up our desired libvirt environment. -# (Tested on Centos 7) -libvirt_packages: - - qemu-kvm - - libvirt - - libvirt-python - - libguestfs-tools - - python-lxml - - polkit-pkla-compat - - python-netaddr - - python2-virtualbmc - -# We expect virtualbmc to already be installed on rhel8 as a pre-req to running this, -# as there's no rhel package available yet. -libvirt_packages_rhel8: - - qemu-kvm - - libvirt - - python3-libvirt - - libguestfs-tools - - python3-lxml - - polkit-pkla-compat - - python3-netaddr - -ubuntu_libvirt_packages: - - qemu-kvm - - libvirt-bin - - libvirt-clients - - libvirt-dev - - python3-libvirt - - libguestfs-tools - - python3-lxml - - gir1.2-polkit-1.0 - - libpolkit-agent-1-0 - - libpolkit-backend-1-0 - - libpolkit-gobject-1-0 - - -# The name of the libvirt service. -libvirtd_service: libvirtd diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/files/get-domain-ip.sh b/deploy/metal3-vm/vm-setup/roles/libvirt/files/get-domain-ip.sh deleted file mode 100644 index ad0fd61..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/files/get-domain-ip.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -eu -o pipefail - -# This script will attempt to get the ip address of the a given libvirt guest. - -PATH=$PATH:/usr/sbin:/sbin - -VMNAME=$1 - -# Get the MAC address of the first interface by looking for looking for the -# `&2 - exit 1 -fi - -echo $ip diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/meta/main.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/meta/main.yml deleted file mode 100644 index 9711b33..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - role: common diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/install_setup_tasks.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/install_setup_tasks.yml deleted file mode 100644 index 8e89b42..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/install_setup_tasks.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Install the packages required for our desired libvirt environment. -# We store the list of packages in `libvirt_packages` so that in -# theory we can support multiple distributions simply by passing in a -# different list of packages. -- name: Install packages for libvirt - package: - name: "{{ libvirt_packages }}" - state: present - become: true - when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int == 7 - -- name: Install packages for libvirt - package: - name: "{{ libvirt_packages_rhel8 }}" - state: present - become: true - when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int == 8 - -- name: Install packages for libvirt on Ubuntu - when: - - ansible_facts['distribution'] == "Ubuntu" - package: - name: "{{ ubuntu_libvirt_packages }}" - state: present - become: true - -- name: Start libvirtd - service: - name: "{{ libvirtd_service }}" - state: started - enabled: true - become: true diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/main.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/main.yml deleted file mode 100644 index 2a7f2d7..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/main.yml +++ /dev/null @@ -1,13 +0,0 @@ -- name: libvirt role setup tasks - block: - - include_tasks: install_setup_tasks.yml - - include_tasks: network_setup_tasks.yml - - include_tasks: vm_setup_tasks.yml - when: vm_platform == "libvirt" - when: libvirt_action == "setup" - -- name: libvirt role teardown tasks - block: - - include_tasks: network_teardown_tasks.yml - - include_tasks: vm_teardown_tasks.yml - when: libvirt_action == "teardown" diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_setup_tasks.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_setup_tasks.yml deleted file mode 100644 index e527b70..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_setup_tasks.yml +++ /dev/null @@ -1,128 +0,0 @@ -# If virtualport_type is defined for any networks, include OVS dependencies -- when: networks|selectattr('virtualport_type', 'defined')|map(attribute='name')|list|length > 0 - block: - - # Install OVS dependencies - - name: Install OVS dependencies - include_role: - name: 'parts/ovs' - - # Create any OVS Bridges that have been defined - - name: Create OVS Bridges - openvswitch_bridge: - bridge: "{{ item.bridge }}" - state: present - when: item.virtualport_type is defined and item.virtualport_type == "openvswitch" - with_items: "{{ networks }}" - become: true - -# TODO(apuimedo) drop this back to vm tasks once we have proper DNS -- name: get a list of MACs to use - generate_macs: - nodes: "{{ vm_nodes }}" - networks: "{{ networks }}" - register: node_mac_map - when: vm_nodes - - -# Create the global, root-managed libvirt networks to which we will -# attach the undercoud and vm virtual machines. -- name: Create libvirt networks - virt_net: - command: define - state: present - name: "{{ item.name }}" - xml: '{{ lookup("template", "network.xml.j2") }}' - with_items: "{{ networks }}" - become: true - -- name: Start libvirt networks - virt_net: - command: start - name: "{{ item.name }}" - state: active - with_items: "{{ networks }}" - become: true - -- name: Mark libvirt networks as autostarted - virt_net: - name: "{{ item.name }}" - autostart: "yes" - with_items: "{{ networks }}" - become: true - register: net_autostart - ignore_errors: true - -# https://bugs.launchpad.net/tripleo-quickstart/+bug/1581676 -# There is a bug w/ virt_net and RHEL where the network xml -# file is not written to /etc/libvirt/qemu/networks/ This causes -# network to be considered transient. -- when: not net_autostart.changed - block: - - - name: Check if "virsh net-autostart" was successful - debug: msg="Some libvirt networks were not set to autostart. Please see - https://bugs.launchpad.net/tripleo-quickstart/+bug/1581676" - - # get the network xml from the running network - - name: Get libvirt networks xml - virt_net: - command: get_xml - name: "{{ item.name }}" - with_items: "{{ networks }}" - register: net_xml - become: true - - # copy the xml to a file - - name: copy network-xml to file - copy: content={{ item.get_xml }} dest=/tmp/network-{{ item.item.name }}.xml - with_items: "{{ net_xml.results }}" - become: true - - # redefine the network w/ virsh, this will write the xml file to - # /etc/libvirt/qemu/networks/ and it will no longer be transient - - name: redefine the libvirt networks so the config is written to /etc/libvirt - command: virsh net-define /tmp/network-{{ item.name }}.xml - with_items: "{{ networks }}" - become: true - - # Now we're ready to mark the network autostart - - name: Mark libvirt networks as autostarted - virt_net: - name: "{{ item.name }}" - autostart: "yes" - with_items: "{{ networks }}" - become: true - -# Whitelist the bridges associated with these networks for -# access using qemu [helper networking][helper]. Later on we -# create virtual machines use an unprivileged `qemu://session` -# connection, and we connect to the networks using the bridge names. -# -# [helper]: http://wiki.qemu.org/Features-Done/HelperNetworking -- name: Whitelist bridges for unprivileged access on CentOS - lineinfile: - dest: '/etc/qemu-kvm/bridge.conf' # Needs to be /etc/qemu/bridge.conf if supporting Fedora - line: "allow {{ item.bridge }}" - with_items: "{{ networks }}" - when: - - ansible_os_family == "RedHat" - become: true - -- name: Whitelist bridges for unprivileged access on Ubuntu or Fedora - lineinfile: - dest: '/etc/qemu/bridge.conf' - line: "allow {{ item.bridge }}" - create: yes - with_items: "{{ networks }}" - when: - - ansible_facts['distribution'] == "Ubuntu" - become: true - -# We're going to want to store things in `working_dir` so ensure it -# exists first. `working_dir` is a directory on the target host. -- name: Ensure remote working dir exists - file: - path: "{{ working_dir }}" - state: directory - become: true diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_teardown_tasks.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_teardown_tasks.yml deleted file mode 100644 index ab77e35..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/network_teardown_tasks.yml +++ /dev/null @@ -1,28 +0,0 @@ -- name: Stop libvirt networks - virt_net: - command: destroy - name: "{{ item.name }}" - state: inactive - with_items: "{{ networks }}" - become: true - -- name: Delete libvirt networks - virt_net: - command: undefine - state: absent - name: "{{ item.name }}" - with_items: "{{ networks }}" - become: true - -- name: Delete bridges on Ubuntu - shell: | - sudo ip link set baremetal down - sudo ip link set provisioning down - ip link del baremetal type bridge | true - ip link del provisioning type bridge | true - - when: - - ansible_distribution == 'Ubuntu' - - become: yes - diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_setup_tasks.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_setup_tasks.yml deleted file mode 100644 index 323aa3c..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_setup_tasks.yml +++ /dev/null @@ -1,122 +0,0 @@ -# Create a libvirt volume pool. This is where we'll be creating -# images for the VMs -# Note: the virt_pool module is not working properly on rhel-7.2 -# https://bugs.launchpad.net/tripleo-quickstart/+bug/1597905 -- name: ensure libvirt volume path exists - become: true - file: - path: "{{ libvirt_volume_path }}" - state: directory - mode: 0755 - -- name: Check volume pool - command: > - virsh pool-uuid "{{ libvirt_volume_pool }}" - register: pool_check - ignore_errors: true - changed_when: false - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - -- name: create the volume pool xml file - template: - src: volume_pool.xml.j2 - dest: "{{ working_dir }}/volume_pool.xml" - when: pool_check is failed - -- name: Define volume pool - command: "virsh pool-define {{ working_dir }}/volume_pool.xml" - when: pool_check is failed - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - -- name: Start volume pool - virt_pool: - command: start - state: active - name: "{{ libvirt_volume_pool }}" - uri: "{{ libvirt_uri }}" - -# In some cases the pool_check can pass and the pool xml config is absent -# In this case it is required to dump the xml and redefine the pool. -- name: ensure tripleo-quickstart volume pool is defined - shell: > - virsh pool-dumpxml {{ libvirt_volume_pool }} | - virsh pool-define /dev/stdin - changed_when: true - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - -- name: Mark volume pool for autostart - virt_pool: - name: "{{ libvirt_volume_pool }}" - autostart: "yes" - uri: "{{ libvirt_uri }}" - -- when: vm_nodes - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - block: - - # Create libvirt volumes for the vm hosts. - - name: Check if vm volumes exist - command: > - virsh vol-info --pool '{{ libvirt_volume_pool }}' '{{ item.name }}.qcow2' - register: vm_vol_check - ignore_errors: true - with_items: "{{ vm_nodes }}" - - - name: Create vm vm storage - command: > - virsh vol-create-as '{{ libvirt_volume_pool }}' - '{{ item.item.name }}'.qcow2 '{{ flavors[item.item.flavor].disk }}'G - --format qcow2 - when: - - item is failed - with_items: "{{ vm_vol_check.results }}" - - # Define (but do not start) the vm nodes. These will be - # booted later by ironic during the provisioning process. - - name: Define vm vms - virt: - name: "{{ item.name }}" - command: define - xml: "{{ lookup('template', 'baremetalvm.xml.j2') }}" - uri: "{{ libvirt_uri }}" - with_items: "{{ vm_nodes }}" - - # Create additional blockdevices for each objectstorage flavor node - # These are sparse files, not using space if unused - - name: Create additional blockdevice for objectstorage nodes - command: > - dd if=/dev/zero of={{ libvirt_volume_path }}/{{ item[0].name }}_{{ item[1] }}.img bs=1 count=0 seek={{ extradisks_size }} - when: flavors[item[0].flavor].extradisks|default(false) - with_nested: - - "{{ vm_nodes }}" - - "{{ extradisks_list }}" - - - name: Check if additional blockdevices are attached - command: > - virsh domblkinfo {{ item[0].name }} {{ libvirt_volume_path }}/{{ item[0].name }}_{{ item[1] }}.img - when: flavors[item[0].flavor].extradisks|default(false) - changed_when: false - ignore_errors: true - register: vm_extradisks_check - with_nested: - - "{{ vm_nodes }}" - - "{{ extradisks_list }}" - - - name: Attach additional blockdevices to vm objectstorage VMs - command: > - virsh attach-disk --config {{ item.item[0].name }} {{ libvirt_volume_path }}/{{ item.item[0].name }}_{{ item.item[1] }}.img {{ item.item[1] }} - when: item is failed - with_items: "{{ vm_extradisks_check.results }}" - -# Generate the ironic node inventory files. Note that this -# task *must* occur after the above vm tasks, because if -# `vm_nodes` is defined the template depends on the -# `node_mac_map` variable. -- name: Write ironic node json files - template: - src: ../templates/ironic_nodes.json.j2 - dest: "{{ working_dir }}/ironic_nodes.json" diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_teardown_tasks.yml b/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_teardown_tasks.yml deleted file mode 100644 index d4745e7..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/tasks/vm_teardown_tasks.yml +++ /dev/null @@ -1,94 +0,0 @@ -# NB: We use `virsh` here instead of the `virt` module because -# these tasks may be called before the dependencies of the `virt` -# module are satisfied. - -- name: Check if libvirt is available - command: > - virsh uri - ignore_errors: true - changed_when: false - register: libvirt_check - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - -# If libvirt isn't available we can skip everything else. -- when: libvirt_check is success - environment: - LIBVIRT_DEFAULT_URI: "{{ libvirt_uri }}" - block: - - - when: vm_nodes - block: - - # Check if the vm nodes exist. - - name: Check vm vms - command: > - virsh domid "{{ item.name }}" - with_items: "{{ vm_nodes }}" - ignore_errors: true - register: vm_check - - # Destroy and undefine the vm nodes. - - name: Destroy vm vms - command: - virsh destroy "{{ item.item.name }}" - when: item is success - with_items: "{{ vm_check.results }}" - ignore_errors: true - - - name: Undefine vm vms - command: - virsh undefine "{{ item.item.name }}" - when: item is success - with_items: "{{ vm_check.results }}" - - # The `virsh vol-dumpxml ... > /dev/null` is here (and elsewhere) due to - # [1293804]. - # - # [1293804]: https://bugzilla.redhat.com/show_bug.cgi?id=1293804 - - name: Delete baremetal vm storage - shell: | - virsh vol-dumpxml --pool '{{ libvirt_volume_pool }}' \ - '{{ item.name }}'.qcow2 2>&1 > /dev/null - virsh vol-delete --pool '{{ libvirt_volume_pool }}' \ - '{{ item.name }}'.qcow2 - with_items: "{{ vm_nodes }}" - ignore_errors: true - - - name: Check volume pool - command: > - virsh pool-uuid "{{ libvirt_volume_pool }}" - register: pool_check - ignore_errors: true - - # See https://www.redhat.com/archives/libvirt-users/2016-March/msg00123.html - # TL;DR: ensure that the pool really exists if the previous - # task says it does. - - name: Work around libvirt bug - shell: | - virsh pool-dumpxml "{{ libvirt_volume_pool }}" | - virsh pool-define /dev/stdin - when: pool_check is success - - - name: Destroy volume pool - command: > - virsh pool-destroy "{{ libvirt_volume_pool }}" - when: pool_check is success - ignore_errors: true - - - name: Undefine volume pool - command: > - virsh pool-undefine "{{ libvirt_volume_pool }}" - when: pool_check is success - - - name: Get UID of pool user - command: id -u "{{ ansible_user_id }}" - register: pool_uid - changed_when: false - when: pool_check is success - - - name: Destroy pool definition file - file: - path: "/run/user/{{ pool_uid.stdout }}/libvirt/storage/run/{{ libvirt_volume_pool }}.xml" - state: absent - when: pool_check is success diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/baremetalvm.xml.j2 b/deploy/metal3-vm/vm-setup/roles/libvirt/templates/baremetalvm.xml.j2 deleted file mode 100644 index 0841885..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/baremetalvm.xml.j2 +++ /dev/null @@ -1,56 +0,0 @@ - - {{ item.name }} - {{ flavors[item.flavor].memory }} - {{ flavors[item.flavor].vcpu }} - - {{baremetal_vm_xml|default('')}} - - - hvm - - - - - - - - - - - destroy - restart - restart - - - - - - -{% if libvirt_diskbus == 'scsi' %} - -{% endif %} -{% for network in networks %} - - - - -{% if network.virtualport_type is defined %} - -{% endif %} - -{% endfor %} - - - -{% if enable_vnc_console|bool %} - - - -{% endif %} - - {{baremetal_vm_device_xml|default('')}} - - - diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/ironic_nodes.json.j2 b/deploy/metal3-vm/vm-setup/roles/libvirt/templates/ironic_nodes.json.j2 deleted file mode 100644 index 021f0cd..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/ironic_nodes.json.j2 +++ /dev/null @@ -1,57 +0,0 @@ -{% set lvars = { 'host_ip' : '192.168.122.1', 'pxe_network' : False} %} -{% for network in networks %} -{% if (not (network.forward_mode is defined and network.forward_mode == 'nat') and lvars['pxe_network'] == False) %} -{% if lvars.update({'pxe_network' : network.name}) %}{% endif %} -{% endif %} -{% if network.address is defined and lvars['host_ip'] == '192.168.122.1' %} -{% if lvars.update({'host_ip' : network.address}) %}{% endif %} -{% endif %} -{% endfor %} -{ - "nodes": [ - {% for node in vm_nodes %} - { - "name": "{{ node.name|replace('_', '-') }}", - "driver": "ipmi", - "resource_class": "baremetal", - "driver_info": { - "ipmi_username": "admin", - "ipmi_password": "password", - "ipmi_address": "{{ lvars['host_ip'] }}", - "ipmi_port": "{{ node.virtualbmc_port }}", - "deploy_kernel": "http://172.22.0.1/images/ironic-python-agent.kernel", - "deploy_ramdisk": "http://172.22.0.1/images/ironic-python-agent.initramfs" - }, - "ports": [{ - "address": "{{ node_mac_map.get(node.name).get(lvars['pxe_network']) }}", - "pxe_enabled": true - }], - "properties": { - "local_gb": "{{ flavors[node.flavor].disk }}", - "cpu_arch": "{{ libvirt_arch }}" - }, - "net": { - "links": [ - {% for network in networks %} - { - "id": "{{ network.name }}_nic", - "ethernet_mac_address": "{{ node_mac_map.get(node.name).get(network.name) }}", - "type": "phy" - }{% if not loop.last %},{% endif %} - {% endfor %} - ], - "networks": [ - {% for network in networks %} - { - "id": "{{ network.name }}", - "link": "{{ network.name }}_nic", - "type": "ipv4_dhcp" - }{% if not loop.last %},{% endif %} - {% endfor %} - ], - "services": [] - } - }{% if not loop.last %},{% endif %} - {% endfor %} - ] -} diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/network.xml.j2 b/deploy/metal3-vm/vm-setup/roles/libvirt/templates/network.xml.j2 deleted file mode 100644 index 7ec1dc4..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/network.xml.j2 +++ /dev/null @@ -1,59 +0,0 @@ -{% set nat_port_range = item.nat_port_range|default([1024, 65535]) %} -{% set netmask = item.netmask|default('255.255.255.0') %} -{% if item.dhcp_hosts is defined %} -{% set dhcp_hosts_names = item.dhcp_hosts | map(attribute='name') | map('replace', '-', '_') | list %} -{% endif %} - - {{ item.name }} - -{% if item.forward_mode is defined %} - -{% if item.forward_mode == 'nat' %} - - - -{% endif %} - -{% endif %} -{% if item.virtualport_type is defined %} - -{% endif %} -{% if item.address is defined and item.forward_mode != 'bridge' %} - -{% if item.dhcp_range is defined %} - - - {% if item.dhcp_hosts is defined %} - {% for host in item.dhcp_hosts %} - - {% endfor %} - {% endif %} - -{% endif %} - -{% if item.domain is defined %} - -{% endif %} -{% if item.dns is defined %} - - {% for host in item.dns.hosts %} - - {% for name in host.hostnames %} - {{ name }} - {% endfor %} - - {% endfor %} - {% if item.dns.srvs is defined %} - {% for srv in item.dns.srvs %} - - {% endfor %} - {% endif %} - {% if item.dns.forwarders is defined %} - {% for forwarder in item.dns.forwarders %} - - {% endfor %} - {% endif %} - -{% endif %} -{% endif %} - diff --git a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/volume_pool.xml.j2 b/deploy/metal3-vm/vm-setup/roles/libvirt/templates/volume_pool.xml.j2 deleted file mode 100644 index eb19810..0000000 --- a/deploy/metal3-vm/vm-setup/roles/libvirt/templates/volume_pool.xml.j2 +++ /dev/null @@ -1,11 +0,0 @@ - - {{ libvirt_volume_pool }} - - {{ libvirt_volume_path }} - - 0755 - -1 - -1 - - - diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/defaults/main.yml b/deploy/metal3-vm/vm-setup/roles/virtbmc/defaults/main.yml deleted file mode 100644 index 75ce168..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -# Can be set to "teardown" to destroy a previous configuration -virtbmc_action: setup diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/files/vbmc_start.sh b/deploy/metal3-vm/vm-setup/roles/virtbmc/files/vbmc_start.sh deleted file mode 100755 index 651a9b0..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/files/vbmc_start.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -name="$1" - -status=$(vbmc show -f value $name | grep status | cut -f2 -d' ') - -export PATH=$PATH:/usr/local/bin - -if [[ $status != "running" ]]; then - vbmc start $name -fi diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/meta/main.yml b/deploy/metal3-vm/vm-setup/roles/virtbmc/meta/main.yml deleted file mode 100644 index 2083f0e..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - common diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/main.yml b/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/main.yml deleted file mode 100644 index 3e35782..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/main.yml +++ /dev/null @@ -1,4 +0,0 @@ -- include_tasks: setup_tasks.yml - when: virtbmc_action == "setup" -- include_tasks: teardown_tasks.yml - when: virtbmc_action == "teardown" diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/setup_tasks.yml b/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/setup_tasks.yml deleted file mode 100644 index 31d18f7..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/setup_tasks.yml +++ /dev/null @@ -1,83 +0,0 @@ ---- - -- name: Create VirtualBMC directories - file: - path: "{{ item }}" - state: directory - mode: 0750 - owner: root - group: root - with_items: - - "/etc/virtualbmc" - - "/var/log/virtualbmc" - become: true - -- name: Create VirtualBMC configuration file - copy: - mode: 0750 - dest: "/etc/virtualbmc/virtualbmc.conf" - content: | - [default] - config_dir=/root/.vbmc - [log] - logfile=/var/log/virtualbmc/virtualbmc.log - debug=True - [ipmi] - session_timout=20 - become: true - -- name: get virthost non_root_user userid - command: id -u {{ non_root_user }} - register: non_root_user_uid - -- name: set fact on non_root_user_uid - set_fact: - non_root_user_uid: "{{ non_root_user_uid.stdout }}" - -# The first network defined with an address will be used for vbmc access. -- name: set vbmc address if there is a (nat) network defined with an address - set_fact: - vbmc_address: "{{ networks|selectattr('address', 'defined')|map(attribute='address')|list|first }}" - when: networks|selectattr('address', 'defined')|map(attribute='name')|list|length > 0 - -# The connection uri is slightly different when using qemu:///system -# and requires the root user. -- name: set qemu uri for qemu:///system usage - set_fact: - vbmc_libvirt_uri: "qemu+ssh://root@{{ vbmc_address }}/system?&keyfile=/root/.ssh/id_rsa_virt_power&no_verify=1&no_tty=1" - when: libvirt_uri == "qemu:///system" - -- name: set qemu uri for qemu:///session usage - set_fact: - vbmc_libvirt_uri: "qemu+ssh://{{ non_root_user }}@{{ vbmc_address }}/session?socket=/run/user/{{ non_root_user_uid }}/libvirt/libvirt-sock&keyfile=/root/.ssh/id_rsa_virt_power&no_verify=1&no_tty=1" - when: vbmc_libvirt_uri is not defined - -- name: Start the Virtual BMCs (virtualbmc >= 1.4.0+) on Redhat-family OSes - service: - name: "virtualbmc" - state: started - enabled: true - when: - - ansible_os_family == "RedHat" - become: true - -- name: Start the Virtual BMCs (virtualbmc >= 1.4.0+) on ubuntu - shell: vbmcd || true - when: - - ansible_facts['distribution'] == "Ubuntu" - become: true - - -- name: Create the Virtual BMCs - command: "vbmc add {{ item.name }} --port {{ item.virtualbmc_port }} --libvirt-uri {{ vbmc_libvirt_uri }}" - args: - creates: /root/.vbmc/{{ item.name }}/config - with_items: "{{ vm_nodes }}" - become: true - environment: - PATH: "{{ ansible_env.PATH }}:/usr/local/bin" - -- name: Start the Virtual BMCs - script: vbmc_start.sh {{ item.name }} - with_items: "{{ vm_nodes }}" - become: true diff --git a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/teardown_tasks.yml b/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/teardown_tasks.yml deleted file mode 100644 index 64068e9..0000000 --- a/deploy/metal3-vm/vm-setup/roles/virtbmc/tasks/teardown_tasks.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- - -- name: Remove virtualbmc directories - file: - path: "{{ item }}" - state: absent - with_items: - - "/etc/virtualbmc" - - "/var/log/virtualbmc" - - "/root/.vbmc/" - become: true - -- name: Stop/disable the Virtual BMCs (virtualbmc >= 1.4.0+) on CentOS - when: - - ansible_os_family == "RedHat" - service: - name: "virtualbmc" - state: "stopped" - enabled: false - become: true - -- name: Stop/disable the Virtual BMCs (virtualbmc >= 1.4.0+) on Ubuntu - when: - - ansible_distribution == 'Ubuntu' - shell: pkill vbmcd || true - become: true diff --git a/deploy/metal3-vm/vm-setup/setup-playbook.yml b/deploy/metal3-vm/vm-setup/setup-playbook.yml deleted file mode 100644 index fa942f2..0000000 --- a/deploy/metal3-vm/vm-setup/setup-playbook.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Setup dummy baremetal VMs - hosts: virthost - connection: local - gather_facts: true - tasks: - - import_role: - name: common - - import_role: - name: libvirt - - import_role: - name: virtbmc - when: vm_platform|default("libvirt") == "libvirt" diff --git a/deploy/metal3-vm/vm-setup/teardown-playbook.yml b/deploy/metal3-vm/vm-setup/teardown-playbook.yml deleted file mode 100644 index 571df12..0000000 --- a/deploy/metal3-vm/vm-setup/teardown-playbook.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: Teardown previous libvirt setup - hosts: virthost - connection: local - gather_facts: true - tasks: - - import_role: - name: common - - import_role: - name: libvirt - vars: - libvirt_action: "teardown" - - import_role: - name: virtbmc - vars: - virtbmc_action: "teardown" - diff --git a/figure-2.odg b/figure-2.odg index 990f17433f36a3e5c9203e24b5607e6f42d1349f..ac4b9b6353dec3791f510a29f53c3355ef194ea0 100644 GIT binary patch delta 9951 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 Bsm}la delta 12454 zcmZ{~1yo$kwk_PVridEDMM>vC`%xtx!2IoSwO%h@yGH&m03 zGnhZJD!_+n-<;?HU{ijpE5;eGN^^4%)mo0JTHv+*?k=(kp5uzmZd6F2BSU-o{Wwaj zjfIqSj#)^MDwJ_FB{VncDHgm9F5I1Clg9wYX0Esm?yK8IHPl>pG}c z$2DGw%9A<1xVy3;f|e@wneXxpVeQ$(Pq6a7wNZvETNz4@yOP1s8<_+q7~D5_C;oNX zj?VP!#-|&q7DIZZ5!g&PpViJ@?Fv*yogRI$WN=4E?GXMFayF7rsD0~9(Xk-O+KZs) zliM@<2f6NL7g6}29zxjNutatl2?3~@RkU141Q7r+ zM?7RFvoHv!&eA>wt+NSG#(`PGV#V+Zj0Np1GB*Qg;=}CGPM%b)UW2_Ny2$xB1FapW z%H`!>JP(qx%%!8g%q)|fQcyjVoGJn|kIo~1Gcl&hRdXS@gqi-}h?pqoKBr~shxKo^ z@Cr4H7w0E&#AG*6{o%--|8Ne8A3HUW)6Kc!f%)h|1{e>&uW!Dz69Nx9xGY5Vw_yeK zvSzNaFR@c9?tY`|I7S#r3}d`yiAWso#p{TR(Aej(kDgMDv6*3#!iMeUyli;lX9HdA zr|90`X;$7NC7Xy0$Z2=_m3i1^3f&-Y8OAw9utz7)w@I~ph?j(AuQVeFY$tuez-f3M z#m%)N_KnF8S~uP@*Z||ST6@G?!peyGP^M=1_ecD)WH;b?w__IX(0z~H+fkTxYd_{D z7|K_3A#)v9ZcH9-4UzqAK78>Qbu6P3;$L$iH1bpZ`k-kYcRNYeTY-r-BT#B2zoV=3 zDA_sf#sU-8@Lk37Y}8Xl8v5;4C{B?iHKvL%1AbRLbKik1_W{_Oxc1Sc-y!n@O@BeU zS^^mSVTeo#Gjbji^I>KmO2Nbkll2-sbQ7sWLjdNtLi&p!vS(jb9d=#k2K=pfb5vhj zZav~rCj&zivd|-I)ZWycL`QT<)K`?l2MbJN#jbb1c#*f;(JDsS0mr`uThbdKFV3||hG~*KuA4aj?k{eLnB5>lZt3(Hdn!JOo zzD;V9BXmqfNt_94o|w^H@L)QAArsqXL={;EDopItB@BYqTHIs;SaMR5Rt9vu%}|=7 zO1!Ib3ivui5OPG$>=r%p+oPd1?|x3YbcT$7&!yOh$Pj1Bh>8ZR}<^Eo5p(r1u&(;skbHxq|Njhcj)p0q=I5FhSOd%isK#9C--9J zF%wJhc}!L5lM5l_b$QLAx{+0N{jjq1DY!K4-#z-kb;l5UI7clrFqPF;B4g!h?qS_f zB5_YgU`R1d2X!ut5GkHPlV$wJDRr)%0tQ0NTC{D&^yje_R91M7Wbx;m8lh;Mhb=rCtp|&oX?~i0|;wPkhfvO)Hy@c zKY!o{^9veeIZ*z{Cn!sE%QStw`i$j5lsF<9PVXGq_rovmvZ*E&X6B+&86CwhI6upr zxU~mhFXQdqLfq&P#yr)(oPkFT0|G{NU+W|%OkyJfDI12>`9=oIcPuXGg_=Yek}m=< zOv&Z3RYdW_*-Nq{v|3_PH(}BMO$gDi!_4k zhvq|ZBo?3E7(+yQoh@*9uv(VRF8I?}`tJBN#$MYoYZO;BByG}|K7G`rCX+XrFMNA` zGM+rDnGqBc$`8x2&WY_!DzmxlN+~6&Tib>))Nfo<4@uWQ_DKbNIHA7g z5$DY?l&se}(ado4N-D^-6f+Ig0&As%v8vSFB~yv9kBqWMB(OFn81xG(Nkchn6SVJ) z-7?HO9(0!DRbQi5#F47_A}qY!QRP05=tOIerqon?up45fef{8Y;qi-g#|XSE)VbDk zn93xTU!7RW^Qp2-rk-I%%m9J&ofe*(r&-vt&2q+tN4qKO?O5l6_+DM&FTM45;NOXJ zh0P?-84vqZ?>R;1d$RK9^^WNgq;x!Oi|0!7d2TjJOT+VZ$?e|ruJ%}bi4zp7g4@>& z|GlprVR@h$S>(-B^hwH()CiC1tAP*Q5Bv#uqlRXt4(F>m9@uP}L&;<8iCgTk{bwrW z`>^wrAv)EEgYv8|TP$X`gvDK2FJSoAk_RPaC{K=b#Mg0#XB5ufF0+tU4E8S%8J2$B z(QxKI?{D(H)3x@#tt!h52{*8pMsH|NSoE2Ag3-MM)Ew)IDi`>`OBxG(mnHr!OS&*w z{*)&VZ#(mnVP)4P7n@dTRtqI(#Q{%vo*jZ>m-wehA=dcM9nw?RUc(zCpTH{D?}zf? zwus`;dhVE{Rhv&FN_9KwqA$eodlLMV==W7ZPv2+_de>YKx`=c#jEIR?N#GruKZ@Y9 zZ5Q?yjfQX-TO7fkhFkDA%kc3R5PN-GeWaDN}zt7X+N8_LIe@>a->MPt| z&V97`&Hu7;Ai$zn2(!5}R2bT4+>h^kBHGH7EM+DZy2|-08qlzw6t$HtMR#S8ww_`N zE_Lxb=7!?1R5!eATRP$%x@LHFp_9*kSYXd&JadAv+Ty|~mT`d*=A`ey=u5-=23m_l z{3@3iVTb3$>8_L+kH!H@2t@rL#b_Ax$JxCD!R^Mt%(XHd>QMcvSp`O zZx*r9kqA{r%dfAYDCaNlB>GoD0uik!uRJUTjzq!0jW8x;lN<0h&*=yI*hCctShD>? z!?H(W3(*DG?BbaaZpIem_`yeaAs}MLMtWzUS67p2=?O1^z_s2Qh2WuL`LUH!e`nCo z%5d`-HQk*7ua95!#3v^B3t zfA_`Ld2XO%#6PeHS?b>#<9{QdBw;l2Bw19a}3r2H*SkM=*Mh0$2y|3ANf3pS&oga5q)2mFU1{Rx{pJ9$_-d9eC8I-D3T zJ8kn}2CUbhb1e*T;kK%J`w9?@DVnoGc@V~&9GiS&1G4;V;;*BZbt9fsIo^I<4;)VX zHIQhj+dw4{yX-5wWRbu;SH`G~Lv!~;ma~_C9+Jq_{WAvMLJN$ox??I5QOvv5bqY=( zz6f9LY9CCJ+sIFd>lh%G`m(c0PX&hI;Fp*2W&3e2on@&jsE$osNbj8D%Av)j<(cwa z{~N90_#N!k4-e9ib}UuB-YY@c`e+Hw zTv}ySdHBWa_8IW(;IF+5+D;4jgK?bB^M=dfK>!~(8QKlR2Y%hpB8DRVX~a=fPO<<|@`pM2KdbLPiSVPU9A zW&6pYTd(-MJ8ZQ%m~Jm*a13DnnXMZhP4YX|qt4iytRfps<1*ZaTSU{OZakslkqd4< zogcK?|DrFO++>Qr$SApjS=^68k&k?dTHJ6`+s3lK@a-ABhWCpiQ!YnO)X=07qcM@t zAU%Q&9x@UhXZiTl!sAS`|F+5ustSaz-F*Xrpd=FIY)~ZC@oWB4yLs-6YQ_fYEgcY1 zp`(I*fl(eDUF0h-C>4fD9A{T}G$Rx)cD-=&#m0G+C-*_SI2QPnG(NzKJa<P2?x@%PdhqG)o$m%Z1w0jw+KxJjl{%mb5E*QlplOAgRq8c^oTKK3>{oj7#IK`RgXJ9H~kj* z)ezY97CH%nptETmqxgPvD+V(sxJ8ApuZ>1qEh{)1ZJ+5mpf)p~5Cu-*fN^~4S?YdM zHy(j(3M+aeIr`v-^QUv_m4Ke85Uv+Q_fXux*I&cNnI7z@DXf_+OPiE^Tmk3QJSvuB z$KK{5fym_ph^JBa%AYqIXk%}uY^MqNl}x~bNbPm+!w|-^7T_4jBqcn_Xgfbl=p!eX zx$zWGBdLz;e6d0Zl-yZCd-oorQ)4lXUUhA#ha^mEGUNqY=$enhUfeb;X+uS^qYS#w zL_TYMUMd47X_j^q%Wy_N$&!y%wiLO@HaKk>8D@syVhanuxc|G#xeckLRt4=c>iI5M z>xtvs_85g(_xo{yP?)e1ThY4-jtmLF;xFWB9l11FL=HKwo$l8CNU6bzT9q9P zM%7Q2c+yL*>}HfBVyzfd#1yVX4ulPw^Hn|4w1cJ_cc4h~eHemG?Uy5ysR^jW@&cis zG;lR@usTVzSUn|YXk?^dDWfLjIszlGg=T+NllHMvidg4w79V9=ZqBT}9Sj-^TTGK` zxT9hzxOoQI{icpC87fVj*47Cm`|+^|jQW5D?eG`JBcz|y=E&tHg>=JO`NvC8Lfe&7 z_8+!!I*hKz<~_2r=++3{%P%i(G007r3Y55}%;8jjcduTwM(5{w-elU$8=+kQ+wr8j zQc`DeikfYZzlu^5dn*t-4;5cMs@CdT|CQP>}HD zS-8G?_yyDLEy}$eaefeHDZY(J#`_UYlM@yBr+)lO1Pa4^=>#pUj%7;ddQF;m5ELS= z4g}(mUV8gy5;z^vT1s* zex!S2VzawrFI$Rai!Ykg@k0g02RoWio~f5`v~3NhM4fGxKK%g=bp=%5&pc-qeHomN z=|GXYs$^3UY*b%L6Q8ePcnVCaWQxoK1BVpi8`fPogPq07xNr=AjL6R{b2gc|T%0Ky zKxOkG-%33$-Pb?EumXBJLZ><%eGHLD-4oMZvc>vH$*Vozp6{M}OTWGe3RZ7B&)XPF z{9gD}WqVFX;k6Yl)nN|a7fKZM6`L*;C)WiPa!n!-qK!?vVk$!6;}r5f?JrYP_)YlV zp^ryNWXC4Ih4=-;26s5OAdEEogp?k4T4uE~o%lbleIJYPE($=4d`i{6tZB$~ZgU=J z2w>_cZmRW$=_6-3go(-i2yK>4E~!G#Jc76_g0&I%SY;h~Axv#KqkF=gUTIV$$utR-LdJeK9W{mllsF$3+{5R3uVL*_F&?+WJ|D zv1A#uXNA zSt?^`Ff5q4@!pUUlNv$UPN!g&+p43j9p2H)sv@2J3pv}TpAD^eRSOY|yo)Oc9-DCk z(bKYsu1m@ zr#^z6c3a_cGSctX!*df6H}^J6UQVu7o!2Yz4mt5FW=vMZlvxsYN^dkqlRafg2&=Gn}_i84oNZ= z82*d4RHxEz52Zdox@6aPM_MHM^~`Ml8-h++@$7;K};XKJ{%eEq~kSX}88nRT_l z5$_j9lgVX=E_-i+52?s|XGp&GSy~NRz2_v&QwJlH`voiVSAwAl_?IqCmThXIMrm??0Lrx%6xRn9whXUtcB6-z z8Gg;6h5`94lGUXu5YG5;qo>BV-;E2kH4~zD1JwInJ!^ix#h6XeO9VS3VRP*QoR9JX z0eIuZK1c?M?jK^2BTTxdtbgjlAmlwsry^0#uVB(Th<{yP3smdPLAS+=RlCFC0^><9 zQ?{&XTa1{%M>r_Wap`t=U>$az?*tF(J#9IC@aS)p!g&3ciOPAv=Z;LpZrcQ4kW>N)EwaEP z%I_eo^xm8`UcTRqdNbpie03Ig^>Ds6#6H0I+XFEIH>sQ}^T;SSTP-g1%%JsRAG;tL z8&wM%VyHMP;i@7IDed6&L5pshZzrY4kjivhwD87at!Tw!#f?2!q1`3nV{yYpcnnc; z^}K@iTipjrm8YS_$2!`!;ZhVPVN+~je-*3w*4+8%Z&R)5#6c8SoS9-R*R$ls92z4= zMn;BvM%&MrUPwYi*&BE|cxjP82k}Q9Snr=_fA6tHZW6&y?g|V{R>Zk72hKqS;%Y?T z!aKR=yWCkx*(Yy<&wszeEc}M>y&pS~No6Rx!Pua`UNYN!0o&f+p+_JZ1KOsT+82`8 zt)KPN5liHg2!PV8fOh}_0uOPG9$2pDdG{bU0&`6nr>TB|_0tPFu<6)mvad*5rne5w z4w(&$PxC#J4-!SW0HM$bNg*Z=sdu!LQI%T1O?Xtj2^YJ-LKi}L(%-@v;!8(|I5_kb z4C9N7mvK^Ag$ZS3iX0t{+>2_Zj$UknibnjG??v-ebS!D0jjiNk&Ua}^Wpt#35vHwd z-`!#Kd}nZTmhenx&}#OYX7>r#!Z)pvQasIifsp5z1y0r8Xcvv2^z&F7wD>8CkdYTq zq6ZT`f9+NRW3-58_Fyai#MZ*4r_zDnutz^r%8;|63?3n#A~>wq3JCDa0QR6q zvTg<7p00gL_bh1|iA9MJHy?9+c}p7(O&;BW9+^mF=|SNW$O*8z16Fk4#WJqJ|=Khzoce+63K>HF&;ovjHNWH)*=61iMb z(CtDB!C7b#>QFDfx`B7Xs-VCRNby+eO0dK^NW1+>@;J1_rH3&(=_UG*R#zTP%It>t zsFB~lxV*O!v|!9~G8Ea1759PAl8m*mZr--oBB67FaAF!JqHwH(oec{?+cv>hjm1AF zB&R3?3O+3$6!<`|sZ;Fm;vdCIo9>0Q9-qbPfujZR#U*pko_0E>Q~8&m1ttQIGU0zV zi&0HI`>URajS&*Lc)~f%``Z7adPKD3>eKW_HK+PTFW4+>3krzpngI4AGB+;pMt$c* zAz!@)T?#r4`$X}@6j<@*RU@P3tS8;*dPY@^EflKLdIod2kj>b5weRrV<5RwiWSpM1 z1&hh-%CiXHKQC^v?RYxuK|9)))|h1?oMXE_XJ@kkdIr6L!nj>1&t&90y2I6+a15eB0^eej(RdzClw;vj1!;3){Elr4>{FM)c0JCi zvZgIK02w>Jw_XDbn>;nU)y0T?q}tIWzBDJA zB22tAxxW2XYuhxwF?d#NtK@j|_VeJ&Za33L;3~%{+-`yRsQg{r507c)>#IT&e(=NY zI@_qwJQc7qE)}OH?}yA`nP?y?bLeqqZ#Uvm+7Hy z@A&ffi3L67E9&&Qs;e3`;5O22~8qB{ypDNA==Q{%3QJ9{nC1G_e^a z7XDd&0U)8v0R9yh$*U`q6^hk-U$DLYZ#_2SsX8Mm{+s8u7ko?s6=9|DK!5%N`&GsI z6)u12eDir`f3s^DFGtguDsgL@>nghs)je{$7ZU=?ohqlDPpf6#WLLgB0KxoC0~j7e zcDc>`m|(K1HLcb{oL))7FHRff9x2Kq+`+;tsIhPkPpVqp{NIoh_L87d)&v8$&rYaz zjXKa$m+yX<92oyyv*7Zu3qxT60C)O-uUY>-KKl{K8A^)^0Q`ON0ZA^*gh`a-nBYHm z+W;T{9_o*>ul%410DxFk6*Z-Bad8O=30YWJNW^W(WZkG_oyg@pDHQ!!HT;CNodxwj zYHMrj>;IYaT-D^9wJg2#?R@RTZ7eMd?=}EB&~Klqkbao z+f+`|RB_u}S?6p;_gr=FLTArF-N0hg&`QhbYS-jOe|7atd;8m`Pj4|XZ^_ATnVD~e zg>MxVZw(D^?d|>j{R2Z|e`I26dS+&3d3m{iW@~6}XKZnIav8iovvx4IakR8^vc7lz z*5Cg&Hug3%^R~Ray}iBl`(R`L?D+V2WAA+X@Z#X~`sCvFZF~Fe;Na@&>hk8{?eg;V z_4QBJd3$@ye<;KQ0FdhCB*ip+mQJ!`+=&JVe$1q*Bfco=A+2B~MKobcehc#AfYqBN zQILKK1IdYC>VYxKR(KkUT0))91nXk5p$BcTMirYztG5$Hw~mhQkB(pNTD=o2vLh`7 zQZ-gjJE!IN{RO`~9r&&Vtar4H3+MYDa{`b7P~8Cb|5C4AYQdZKd2EmXxE%!o;16~z zWb+NI+ygj3tL4TWc|&fp#&7I-Fe(7O*EQdtTsDXUA}WHkp9Ree_!X+c1-$_Uot=mh z`Ei8z1;CChuS^h3nhB*k%?{_1%aMlhIiR1Rh!%km01E+{{25RGFEvF2Fu*&zM@Rup zU39$zB*Fl`zs_b(HbvCf6hLIEaKWy*z`RzNRAD{bD6#e)~cD$x5}2nHFU~3XEly^tyn#cDY$qqhp89z!Ef%@?z|XN_AjK}x4R8v8ROeu1 zbfrMOzRu-3ldWR`FW%9Z>L|WLgHLjNS27Ik67C6b1EM^c5G`qvOXoc&@B?Ton*e@i zNhDC8;_u@rBj{o9LAfALW_Bm;rA>q5soZasor>X%Jx0_2f(1F-dC8$=Yr2HQ2A4AA;3={)V(+RV&%nR=n08}|?L_!?z4ffCO zXpy99D1q0vuk5&N?L<)$Mks|JsypZ=KuU7o*fNK2OX?RL9#wZ;c$V2j94vzrQAAx` z?E+t)3-DjSai0sjc>s#p0{UOl5rwme=drt2wjRn_9^zO(w={<6Z9K&_MX)&`iC!Y* z3p^7cm^dDqU8z`b7#K|>c2D2;-yF1*MQP07?JQsKHzMIx(@cTd04}C}Zgw7l*S+^Q z71m69lS(Qvh8l7}AA2N4<1YU1J^`nFmJb{vZ=18=1IsGr_-ms)cR;Y{uo}Rb2=MKO z7?!B#%Py{J1A1>O)Iuug`30Fm9TD9XiiKsP&}|qt7I2XuN`~a}*&v*Jf`o2r8dQvq zSPE6fL_X(#_rUk~0jopOxzy{JACJ0mF9K~L!?wzw5Gdk3WU?<4BX1o>_( z3jW089CSN4Saylq?fB*mubliHVua}8sRLLm1Az*xFg`d`Q5od1XQ6vN2c)SG-1x~f_T|`E;`jJ|L9!VLAt? zSMYC)D*;l)VbEiniCoguPbq`mQAFy9mT8fE%ZGFZg@M>_2yV*+-IPC)%~)C4jllz< zrO?MQWC36DsX`4{=l6n~{r*T+EzuUbR48;va1i_VVdC?1)pZT1mL3Bmy^UIyu%4R~ z=QrCTC1Qa&PXI_iaJe_XmVm-4+!lrVH$>mw=32OE)bxDe;-fW1CX;!MQ=R#Z>D80L^%Xn}n2p6%Ge zYoWLh15$_g)c}w<2hGxjRVflqcj5Nez)Dn?6Uq7{^qJUhztTRe!a4brqm#Js;)!=m zN+QC4vo|*;hgE8Ks-T?O$-lOT%GQ;NXXR# zB6ow~KhFZOLyEphP{JVNhF$ix^bYyxVe&OwVq;kcajX~+KQ{YH%Qp4B$hf^flC=qX zd-Xpdvp0nvwI5eoH&o7oDLsMhh2d#=$;vxiHF>ExwY3YA1h>hlX&pgIZ#uF;ulFq< zO8LmpVHJXK5#x7Jn^$%e?irXvYZDPgz4r+7tH*({0p8V^M@BGTxwJ&LulbO!HAS~q zHVj+kEA4S0BEynwNL*2rQ$Ilf_6{7AJ5?c^sb>iGV+~OdxUQxVWWl*_XNb_+RPEV);*{yW%5#TGRs4~mee}>5c zu;U#74Tc08<=Sv7Cp27`@90Xk7#wJ&yvqSvlSmH6K+QX1Q4cbhXb=|}jHVEq$ss@k z!LA%IgOo0>dc|+DR|q-vgoLGR?3v$9tdXt0>#YT=1Vd!s-z$EDFbE;8V0GEkD+bGg zx}&McVBirRiW@*%08&Jj4b`+|Y=H$+_=oPslu=-ijR9waSB+)S%t3UD92y=q1YGs( z?pbv4!BEE?n;t0RvT>dPl9pzCKRHTz%X~zXncDAjP#Uch=hV*@=-crA_1up+)<`}K zWB?w-V23wB>E8dAc5x{of!Qt5mHRNRsFB4_vE7J8bg^xmYZI$uvS&emHjE?eGXMy6>-JpEXh|^1&DQamAIpuda5mh8nB$y3S8Tbw9 z?WYcbjeKeo{kL>I`go#|#u*c;J>yEC6`f zzX0YgjK~?@12#Fz^+g?F8t`G@MMILEzkeP}Bt?uUur<*d6*9(vR$w$Pl8G(VdV-K1&J*nSy%`#`v(>H zrItjtt^yP|hWRxLyjZxrZuTpL1mePbe1~Wwc1r^VG$D3!->!5b=tU6sjo|)tv^yiw zaB3Syu~ilm?7Ro|{qJp_3j+oZUiZp*3`GDa6E@A6MgTdjKp-C@5S_YbLV_MfH0Hl| z&&U9!ZE(fY_cARSf`X)Xbh!T_XVfdunFIf!Y1GkkApGUI|BE1t&^|MD|b6@VaY!2h!5lQNkIfwoDm3|L9#jQ>LoIbt9L=Ke{- zP6DH%p#GPA&Y#T1f7y>Q5dBjl6edCtE^1OZ3TaY21L8kve|&(HQInog$p72HU+W0e zq%~C1|IYbamF^@LCc1xI{E32YQIizWi2vL0uM1|hq)kR@s(({b{`1KAFD2!F#UkmM ziBRuv8~rCl|8u(hAM%6fPa9c!c-T5w|6g0_{}18+qaYxZ@(-Y={inhi%!Hs#_M|3e LI#_9rzefKDNrD;* diff --git a/figure-2.png b/figure-2.png index a252874bdd17b054a5f34e725cff0e40b3b86c9d..695258311633b3c3e0ad1f5b55536f3594f9802c 100644 GIT binary patch literal 38534 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

)naol53af!lv9# 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