From a93a1e6b612fee360323c8a2f5efb2a51cfd1185 Mon Sep 17 00:00:00 2001 From: Yolanda Robla Date: Thu, 4 Feb 2016 12:35:03 +0100 Subject: [PATCH] Add script and playbook to test dhcp It will run a play where it will spin up five vms, and will truncate inventory to consider only three. The play will configure dns using dynamic inventory, and will take an extra parameter to specify if we want static ips or not. It will perform a test on dnsmasq leases file, to ensure that the dhcp behaviour is working as expected, depending on the settings. Change-Id: If56488f78524ceba201b50f76df306620744cda5 --- .../tasks/main.yml | 2 + playbooks/roles/bifrost-test-dhcp/README.md | 54 ++++++++ .../roles/bifrost-test-dhcp/defaults/main.yml | 2 + .../bifrost-test-dhcp/files/test-dhcp.py | 97 ++++++++++++++ .../roles/bifrost-test-dhcp/handlers/main.yml | 3 + .../roles/bifrost-test-dhcp/meta/main.yml | 15 +++ .../roles/bifrost-test-dhcp/tasks/main.yml | 17 +++ .../roles/bifrost-test-dhcp/vars/main.yml | 2 + playbooks/test-bifrost-dhcp.yaml | 118 ++++++++++++++++++ scripts/test-bifrost-inventory-dhcp.sh | 66 ++++++++++ 10 files changed, 376 insertions(+) create mode 100644 playbooks/roles/bifrost-test-dhcp/README.md create mode 100644 playbooks/roles/bifrost-test-dhcp/defaults/main.yml create mode 100644 playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py create mode 100644 playbooks/roles/bifrost-test-dhcp/handlers/main.yml create mode 100644 playbooks/roles/bifrost-test-dhcp/meta/main.yml create mode 100644 playbooks/roles/bifrost-test-dhcp/tasks/main.yml create mode 100644 playbooks/roles/bifrost-test-dhcp/vars/main.yml create mode 100644 playbooks/test-bifrost-dhcp.yaml create mode 100755 scripts/test-bifrost-inventory-dhcp.sh diff --git a/playbooks/roles/bifrost-prepare-for-test-dynamic/tasks/main.yml b/playbooks/roles/bifrost-prepare-for-test-dynamic/tasks/main.yml index 30bb17c06..61423cd11 100644 --- a/playbooks/roles/bifrost-prepare-for-test-dynamic/tasks/main.yml +++ b/playbooks/roles/bifrost-prepare-for-test-dynamic/tasks/main.yml @@ -25,6 +25,8 @@ - name: "Remove testvm hosts from SSH known_hosts file." command: ssh-keygen -R "{{ ipv4_address }}" when: ipv4_address is defined +- name: "Pause before asking for keyscan, to avoid races" + pause: minutes=2 - name: "Add testvm hosts from SSH known_hosts file." shell: ssh-keyscan "{{ ipv4_address }}" >> "{{ ansible_env.HOME }}/.ssh/known_hosts" when: ipv4_address is defined diff --git a/playbooks/roles/bifrost-test-dhcp/README.md b/playbooks/roles/bifrost-test-dhcp/README.md new file mode 100644 index 000000000..99f620d1c --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/README.md @@ -0,0 +1,54 @@ +bifrost-test-dhcp +================= + +Perform checks on dnsmasq generated files to ensure that it +behaves as expected on bifrost. + +Requirements +------------ + +None at this time. See Dependencies. + +Role Variables +-------------- + +None at this time. See Dependencies. + +Dependencies +------------ + +This role is intended to be executed as part of bifrost, as part +of bifrost-test-dhcp scripts. + +Example Playbook +---------------- + +hosts: localhost + name: "Tests DCHP settings" + become: no + gather_facts: yes + remote_user: root + roles: + - role: bifrost-test-dhcp + +License +------- + +Copyright (c) 2016 Hewlett-Packard Enterprise Development Company LP + +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. + +Author Information +------------------ + +Infra-cloud Developers diff --git a/playbooks/roles/bifrost-test-dhcp/defaults/main.yml b/playbooks/roles/bifrost-test-dhcp/defaults/main.yml new file mode 100644 index 000000000..c3f6ea4c7 --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for bifrost-test-dhcp diff --git a/playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py b/playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py new file mode 100644 index 000000000..b14887b1f --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# +# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company LP +# +# 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. + +from __future__ import print_function +import csv +import os +import sys + + +def main(argv): + # first item is the inventory_dhcp setting + # second item is the inventory_dhcp_static_ip setting + inventory_dhcp = (argv[0] == 'True' or argv[0] == 'true') + inventory_dhcp_static_ip = (argv[1] == 'True' or argv[1] == 'true') + + if not inventory_dhcp: + # nothing to validate + sys.exit(0) + + # extract data from csv file + inventory = [] + if not os.path.exists('/tmp/baremetal.csv'): + print('ERROR: Inventory file has not been generated') + sys.exit(1) + + with open('/tmp/baremetal.csv') as csvfile: + inventory_reader = csv.reader(csvfile) + for row in inventory_reader: + inventory.append(row) + + # now check that we only have these entries in leases file + leases = [] + if not os.path.exists('/var/lib/misc/dnsmasq.leases'): + print('ERROR: dnsmasq leases file has not been generated') + sys.exit(1) + + with open('/var/lib/misc/dnsmasq.leases') as csvfile: + leases_reader = csv.reader(csvfile, delimiter=' ') + for row in leases_reader: + leases.append(row) + + # first we test number of entries + if len(leases) != len(inventory): + print('ERROR: Number of entries do not match with inventory') + sys.exit(1) + + # then we check that all macs and hostnames are present + for entry in inventory: + mac = entry[0] + hostname = entry[10] + ip = entry[11] + + # mac check + found = False + for lease_entry in leases: + if lease_entry[1] == mac: + found = True + break + if not found: + print('ERROR: No mac found in leases') + sys.exit(1) + + # hostname check + found = False + for lease_entry in leases: + if lease_entry[3] == hostname: + found = True + + # if we use static ip, we need to check that ip matches + # with hostname in leases + if inventory_dhcp_static_ip: + if lease_entry[2] != ip: + print('ERROR: IP does not match with inventory') + sys.exit(1) + break + if not found: + print('ERROR: No hostname found in leases') + sys.exit(1) + + sys.exit(0) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/playbooks/roles/bifrost-test-dhcp/handlers/main.yml b/playbooks/roles/bifrost-test-dhcp/handlers/main.yml new file mode 100644 index 000000000..abff1504e --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/handlers/main.yml @@ -0,0 +1,3 @@ +--- +# handlers file for bifrost-test-dhcp + diff --git a/playbooks/roles/bifrost-test-dhcp/meta/main.yml b/playbooks/roles/bifrost-test-dhcp/meta/main.yml new file mode 100644 index 000000000..2a3fbb62c --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + author: Infra-cloud Developers + description: Basic dnsmasq checks created by Bifrost. + company: OpenStack + license: Apache + min_ansible_version: 1.9 + platforms: + - name: Ubuntu + versions: + - trusty + categories: + - cloud + - cloud:openstack +dependencies: [] diff --git a/playbooks/roles/bifrost-test-dhcp/tasks/main.yml b/playbooks/roles/bifrost-test-dhcp/tasks/main.yml new file mode 100644 index 000000000..870513973 --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/tasks/main.yml @@ -0,0 +1,17 @@ +# Copyright (c) 2016 Hewlett-Packard Development Company, L.P. +# +# 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. +--- +- name: Execute python dhcp check file + become: true + script: test-dhcp.py "{{inventory_dhcp}}" "{{inventory_dhcp_static_ip}}" diff --git a/playbooks/roles/bifrost-test-dhcp/vars/main.yml b/playbooks/roles/bifrost-test-dhcp/vars/main.yml new file mode 100644 index 000000000..53e3d999a --- /dev/null +++ b/playbooks/roles/bifrost-test-dhcp/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for bifrost-test-dhcp diff --git a/playbooks/test-bifrost-dhcp.yaml b/playbooks/test-bifrost-dhcp.yaml new file mode 100644 index 000000000..dacb26632 --- /dev/null +++ b/playbooks/test-bifrost-dhcp.yaml @@ -0,0 +1,118 @@ +# Example command line to use: +# Create a VM: +# ansible-playbook -vvvv -i inventory/localhost test-bifrost-dhcp.yaml +# Set BIFROST_INVENTORY_SOURCE +# export BIFROST_INVENTORY_SOURCE=/tmp/baremetal.csv +# Execute the installation and VM startup test. +# ansible-playbook -vvvv -i inventory/bifrost_inventory.py test-bifrost-dhcp.yaml -e use_cirros=true -e testing_user=cirros +--- +- hosts: localhost + connection: local + name: "Remove existing leases file" + become: yes + ignore_errors: yes + tasks: + - command: rm /var/lib/misc/dnsmasq.leases +- hosts: localhost + connection: local + name: "Executes install, enrollment, and testing in one playbook" + become: no + gather_facts: yes + pre_tasks: + - name: "Set ci_testing_zuul if it appears we are running in upstream OpenStack CI" + set_fact: + ci_testing: true + ci_testing_zuul: true + ironic_git_url: "{{ lookup('env', 'WORKSPACE') }}/openstack/ironic" + ironicclient_git_url: "{{ lookup('env', 'WORKSPACE') }}/openstack/python-ironicclient" + shade_git_url: "{{ lookup('env', 'WORKSPACE') }}/openstack-infra/shade" + dib_git_url: "/opt/git/openstack/diskimage-builder" + # TODO(TheJulia) Fix the above paths to be consistent, because the NV job gets the dib + # folder cloned, while the gate job does not. Likely need to work out a semi-hybrid + # solution. + when: lookup('env', 'ZUUL_BRANCH') | length > 0 + - name: "Set ci_testing_zuul_changes if ZUUL_CHANGES is set" + set_fact: + ci_testing_zuul_changes: true + when: lookup('env', 'ZUUL_CHANGES') | length > 0 + - name: "Override the ipv4_gateway setting" + set_fact: + ipv4_gateway: "192.168.122.1" + roles: + - { role: bifrost-prep-for-install, when: skip_install is not defined } + - { role: bifrost-openstack-ci-prep, when: ci_testing_zuul is defined } + environment: + http_proxy: "{{ lookup('env','http_proxy') }}" + https_proxy: "{{ lookup('env','https_proxy') }}" +- hosts: localhost + connection: local + name: "Executes install, enrollment, and testing in one playbook" + become: yes + gather_facts: yes + vars: + inventory_dhcp: "{{ inventory_dhcp | bool }}" + roles: + - role: bifrost-ironic-install + cleaning: false + testing: true + # NOTE(TheJulia): While the next step creates a ramdisk, some elements + # do not support ramdisk-image-create as they invoke steps to cleanup + # the ramdisk which causes ramdisk-image-create to believe it failed. + - { role: bifrost-create-dib-image, dib_imagename: "{{ http_boot_folder }}/ipa", build_ramdisk: false, dib_os_element: "{{ ipa_dib_os_element|default('debian') }}", dib_os_release: "jessie", dib_elements: "ironic-agent {{ ipa_extra_dib_elements | default('') }}", when: create_ipa_image | bool == true } + - { role: bifrost-create-dib-image, dib_imagetype: "qcow2", dib_imagename: "{{deploy_image}}", dib_os_element: "debian", dib_os_release: "jessie", dib_elements: "vm serial-console simple-init {{ extra_dib_elements|default('') }}", when: create_image_via_dib == true and transform_boot_image == false } + environment: + http_proxy: "{{ lookup('env','http_proxy') }}" + https_proxy: "{{ lookup('env','https_proxy') }}" +- hosts: baremetal + name: "Enroll node with Ironic" + become: no + connection: local + roles: + - role: ironic-enroll-dynamic + - { role: ironic-inspect-node, when: inspect_nodes | default('false') | bool } +- hosts: baremetal + vars: + inventory_dhcp_static_ip: "{{ inventory_dhcp_static_ip | bool }}" + name: "Creat configuration drive files and deploy machines." + become: no + connection: local + roles: + - role: bifrost-configdrives-dynamic + - role: bifrost-deploy-nodes-dynamic + - role: bifrost-prepare-for-test-dynamic + serial: 1 +# The testvm Host group is added by bifrost-prepare-for-test based +# on the contents of the CSV file. +- hosts: test + name: "Tests connectivity to the VM" + become: no + gather_facts: no + remote_user: "{{ testing_user }}" + serial: 1 + any_errors_fatal: yes + max_fail_percentage: 0 + roles: + - role: bifrost-test-vm +- hosts: localhost + connection: local + name: "Executes test script" + become: yes + gather_facts: yes + vars: + inventory_dhcp: "{{ inventory_dhcp | bool }}" + inventory_dhcp_static_ip: "{{ inventory_dhcp_static_ip | bool }}" + roles: + - role: bifrost-test-dhcp + cleaning: false + testing: true + environment: + http_proxy: "{{ lookup('env','http_proxy') }}" + https_proxy: "{{ lookup('env','https_proxy') }}" +- hosts: baremetal + connection: local + name: "Unprovisions the test node" + become: no + gather_facts: no + roles: + - role: bifrost-unprovision-node-dynamic + - role: ironic-delete-dynamic diff --git a/scripts/test-bifrost-inventory-dhcp.sh b/scripts/test-bifrost-inventory-dhcp.sh new file mode 100755 index 000000000..1644a0519 --- /dev/null +++ b/scripts/test-bifrost-inventory-dhcp.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Note(TheJulia): If there is a workspace variable, we want to utilize that as +# the preference of where to put logs +LOG_LOCATION="${WORKSPACE:-..}/logs" + +set -eux +set -o pipefail +export PYTHONUNBUFFERED=1 + +SCRIPT_HOME="$(cd "$(dirname "$0")" && pwd)" +BIFROST_HOME=$SCRIPT_HOME/.. +# Install Ansible +$SCRIPT_HOME/env-setup.sh + +# Source Ansible +# NOTE(TheJulia): Ansible stable-1.9 source method tosses an error deep +# under the hood which -x will detect, so for this step, we need to suspend +# and then re-enable the feature. +set +x +source /opt/stack/ansible/hacking/env-setup +set -x + +# Change working directory +cd $BIFROST_HOME/playbooks + +# Syntax check of dynamic inventory test path +ansible-playbook -vvvv -i inventory/localhost test-bifrost-create-vm.yaml --syntax-check --list-tasks +ansible-playbook -vvvv -i inventory/localhost test-bifrost-dynamic.yaml --syntax-check --list-tasks + +# Create the test VMS +ansible-playbook -vvvv -i inventory/localhost test-bifrost-create-vm.yaml -e test_vm_num_nodes="5" -e test_vm_memory_size="512" + +# cut file +head -n -2 /tmp/baremetal.csv > /tmp/baremetal.csv.new && mv /tmp/baremetal.csv.new /tmp/baremetal.csv + +set +e + +# Set BIFROST_INVENTORY_SOURCE +export BIFROST_INVENTORY_SOURCE=/tmp/baremetal.csv + +# Execute the installation and VM startup test. +# NOTE(TheJulia): The variables defined on the command line are to +# drive the use of Cirros as the deployed operating system, and +# as such sets the test user to cirros, and writes a debian style +# interfaces file out to the configuration drive as cirros does +# not support the network_info.json format file placed in the +# configuration drive. +ansible-playbook -vvvv \ + -i inventory/bifrost_inventory.py \ + test-bifrost-dhcp.yaml \ + -e use_cirros=true \ + -e testing_user=cirros \ + -e inventory_dhcp=true \ + -e inventory_dhcp_static_ip=true +EXITCODE=$? + +if [ $EXITCODE != 0 ]; then + echo "****************************" + echo "Test failed. See logs folder" + echo "****************************" +fi + +$SCRIPT_HOME/collect-test-info.sh + +exit $EXITCODE