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
This commit is contained in:
parent
87a44986b6
commit
a93a1e6b61
@ -25,6 +25,8 @@
|
|||||||
- name: "Remove testvm hosts from SSH known_hosts file."
|
- name: "Remove testvm hosts from SSH known_hosts file."
|
||||||
command: ssh-keygen -R "{{ ipv4_address }}"
|
command: ssh-keygen -R "{{ ipv4_address }}"
|
||||||
when: ipv4_address is defined
|
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."
|
- name: "Add testvm hosts from SSH known_hosts file."
|
||||||
shell: ssh-keyscan "{{ ipv4_address }}" >> "{{ ansible_env.HOME }}/.ssh/known_hosts"
|
shell: ssh-keyscan "{{ ipv4_address }}" >> "{{ ansible_env.HOME }}/.ssh/known_hosts"
|
||||||
when: ipv4_address is defined
|
when: ipv4_address is defined
|
||||||
|
54
playbooks/roles/bifrost-test-dhcp/README.md
Normal file
54
playbooks/roles/bifrost-test-dhcp/README.md
Normal file
@ -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
|
2
playbooks/roles/bifrost-test-dhcp/defaults/main.yml
Normal file
2
playbooks/roles/bifrost-test-dhcp/defaults/main.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# defaults file for bifrost-test-dhcp
|
97
playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py
Normal file
97
playbooks/roles/bifrost-test-dhcp/files/test-dhcp.py
Normal file
@ -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:])
|
3
playbooks/roles/bifrost-test-dhcp/handlers/main.yml
Normal file
3
playbooks/roles/bifrost-test-dhcp/handlers/main.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
# handlers file for bifrost-test-dhcp
|
||||||
|
|
15
playbooks/roles/bifrost-test-dhcp/meta/main.yml
Normal file
15
playbooks/roles/bifrost-test-dhcp/meta/main.yml
Normal file
@ -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: []
|
17
playbooks/roles/bifrost-test-dhcp/tasks/main.yml
Normal file
17
playbooks/roles/bifrost-test-dhcp/tasks/main.yml
Normal file
@ -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}}"
|
2
playbooks/roles/bifrost-test-dhcp/vars/main.yml
Normal file
2
playbooks/roles/bifrost-test-dhcp/vars/main.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# vars file for bifrost-test-dhcp
|
118
playbooks/test-bifrost-dhcp.yaml
Normal file
118
playbooks/test-bifrost-dhcp.yaml
Normal file
@ -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
|
66
scripts/test-bifrost-inventory-dhcp.sh
Executable file
66
scripts/test-bifrost-inventory-dhcp.sh
Executable file
@ -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
|
Loading…
Reference in New Issue
Block a user