From 14c94e8cd0da0dd859d5b66e32b6540be5ff457e Mon Sep 17 00:00:00 2001 From: Juraj Linkes Date: Thu, 30 Jun 2016 11:30:27 +0200 Subject: Initial robot smoke suite which creates two vms and tries to ping them directly from where the tests are run Change-Id: Ib1057d5cb3942bf1eafa2288bc9d40391a35a662 Signed-off-by: Juraj Linkes --- .gitignore | 5 ++ testing/robot/data/test_data.py | 14 ++++++ testing/robot/lib/FDSLibrary.py | 108 +++++++++++++++++++++++++++++++++++++++ testing/robot/requirements.txt | 2 + testing/robot/smoke.robot | 109 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 238 insertions(+) create mode 100644 .gitignore create mode 100644 testing/robot/data/test_data.py create mode 100644 testing/robot/lib/FDSLibrary.py create mode 100644 testing/robot/requirements.txt create mode 100644 testing/robot/smoke.robot diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b854ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +*.pyc +testing/robot/log.html +testing/robot/output.xml +testing/robot/report.html diff --git a/testing/robot/data/test_data.py b/testing/robot/data/test_data.py new file mode 100644 index 0000000..cd3b170 --- /dev/null +++ b/testing/robot/data/test_data.py @@ -0,0 +1,14 @@ +import uuid + +run_uuid = str(uuid.uuid4()) +network_name = 'fds_smoke_network_' + run_uuid +subnet_name = 'fds_smoke_subnet_' + run_uuid +vm1_name = 'fds_smoke_vm1_' + run_uuid +vm1_address = '192.168.10.5' +vm2_name = 'fds_smoke_vm2_' + run_uuid +vm2_address = '192.168.10.6' +port1_name = 'fds_smoke_port1_' + run_uuid +port2_name = 'fds_smoke_port2_' + run_uuid +subnet_cidr = '192.168.10.0/24' +vm_flavor = 'm1.small' +vm_image = 'cirros-0.3.3' diff --git a/testing/robot/lib/FDSLibrary.py b/testing/robot/lib/FDSLibrary.py new file mode 100644 index 0000000..2e29d6c --- /dev/null +++ b/testing/robot/lib/FDSLibrary.py @@ -0,0 +1,108 @@ +from neutronclient.v2_0 import client as neutron +from novaclient import client as nova +from novaclient.exceptions import NotFound +import time +import datetime +import os +import subprocess + +class FDSLibrary(): + def __init__(self): + self.neutron_client = neutron.Client(username=os.getenv('OS_USERNAME'), + password=os.getenv('OS_PASSWORD'), + tenant_name=os.getenv('OS_TENANT_NAME'), + auth_url=os.getenv('OS_AUTH_URL')) + + self.nova_client = nova.Client('2', + os.getenv('OS_USERNAME'), + os.getenv('OS_PASSWORD'), + os.getenv('OS_TENANT_NAME'), + os.getenv('OS_AUTH_URL')) + + def create_network(self, name): + body = {'network': {'name': name}} + response = self.neutron_client.create_network(body=body) + return response + + def create_subnet(self, name, network_id, cidr, dhcp=True, ip_version=4): + body = {'subnet': { + 'name': name, + 'enable_dhcp': dhcp, + 'network_id': network_id, + 'ip_version': ip_version, + 'cidr': cidr + }} + response = self.neutron_client.create_subnet(body=body) + return response + + def create_port(self, name, net_id, subnet_id, ip_address, security_groups=None): + body = {'port': { + 'name': name, + 'network_id': net_id, + 'fixed_ips': [ + { + 'subnet_id': subnet_id, + 'ip_address': ip_address + } + ] + }} + if security_groups is not None: + # this is a list + body['port']['security_groups'] = security_groups + response = self.neutron_client.create_port(body=body) + return response + + def create_server(self, name, image, flavor, port_ids, security_groups=None): + image = self.nova_client.images.find(name=image) + flavor = self.nova_client.flavors.find(name=flavor) + nics = [{'port-id': port_id} for port_id in port_ids] + response = self.nova_client.servers.create(name=name, image=image.id, flavor=flavor.id, + security_groups=security_groups, nics=nics) + for key in dir(response): + print key, getattr(response, key) + return response + + def poll_server(self, vm_id, status, timeout=300): + try: + start = datetime.datetime.now() + delta = datetime.timedelta(seconds=timeout) + vm_obj = self.nova_client.servers.get(vm_id) + current_state = getattr(vm_obj, 'OS-EXT-STS:vm_state', None) + print "Found state '{}' while looking for state '{}'".format(current_state, status) + while datetime.datetime.now() - start < delta and self._states_are_not_equal(current_state, status): + time.sleep(1) + vm_obj = self.nova_client.servers.get(vm_id) + current_state = getattr(vm_obj, 'OS-EXT-STS:vm_state', None) + print "Found state '{}' while looking for state '{}'".format(current_state, status) + + if self._states_are_not_equal(current_state, status): + raise Exception("Vm with id '{}' is in state '{}' after timeout of {} seconds" + "".format(vm_id, getattr(vm_obj, 'OS-EXT-STS:vm_state'), timeout)) + except NotFound as e: + if status is not None: + raise e + else: + print "VM not found, which means it's been deleted" + + def _states_are_not_equal(self, current_state, expected_state): + return current_state.lower() != expected_state + + def delete_server(self, vm_id): + response = self.nova_client.servers.delete(vm_id) + return response + + def delete_port(self, port_id): + response = self.neutron_client.delete_port(port_id) + return response + + def delete_net(self, net_id): + response = self.neutron_client.delete_network(net_id) + return response + + def ping_vm(self, ip_address): + try: + output = subprocess.check_output(['ping', '-c', '4', ip_address]) + print output + except subprocess.CalledProcessError as e: + print e.output + raise Exception('Ping on ip {} failed'.format(ip_address)) diff --git a/testing/robot/requirements.txt b/testing/robot/requirements.txt new file mode 100644 index 0000000..87f9867 --- /dev/null +++ b/testing/robot/requirements.txt @@ -0,0 +1,2 @@ +python-openstackclient +python-neutronclient diff --git a/testing/robot/smoke.robot b/testing/robot/smoke.robot new file mode 100644 index 0000000..17b19bf --- /dev/null +++ b/testing/robot/smoke.robot @@ -0,0 +1,109 @@ +*** Settings *** +Library OperatingSystem +Library lib/FDSLibrary.py +Variables data/test_data.py +Suite Setup Setup Suite +Suite Teardown Teardown Suite + +*** Variables *** + +*** Test Cases *** +Create network for VMs + Create tenant network + +Create subnet without dhcp for VMs + Create subnet without dhcp + +Create port for VM1 + ${result} = Create port with ip ${port1_name} ${vm1_address} + Set Suite Variable ${port1_id} ${result} + +Create port for VM2 + ${result} = Create port with ip ${port2_name} ${vm2_address} + Set Suite Variable ${port2_id} ${result} + +Create VM1 + ${port_ids} = Create List ${port1_id} + ${result} = Create vm ${vm1_name} ${port_ids} + Set Suite Variable ${vm1_id} ${result} + +Create VM2 + ${port_ids} = Create List ${port2_id} + ${result} = Create vm ${vm2_name} ${port_ids} + Set Suite Variable ${vm2_id} ${result} + +Wait for VM1 to be active + Should Be True $vm1_id is not $None + Poll vm ${vm1_id} active + +Wait for VM2 to be active + Should Be True $vm2_id is not $None + Poll vm ${vm2_id} active + +Ping VM1 + Ping vm ${vm1_address} + +Ping VM2 + Ping vm ${vm2_address} + +*** Keywords *** +Setup Suite + Set Suite Variable ${network_id} ${None} + Set Suite Variable ${subnet_id} ${None} + Set Suite Variable ${port1_id} ${None} + Set Suite Variable ${port2_id} ${None} + Set Suite Variable ${vm1_id} ${None} + Set Suite Variable ${vm2_id} ${None} + +Teardown Suite + Run Keyword If $vm1_id is not $None Delete vm ${vm1_id} + Run Keyword If $vm2_id is not $None Delete vm ${vm2_id} + Run Keyword If $port1_id is not $None Delete ports ${port1_id} + Run Keyword If $port2_id is not $None Delete ports ${port2_id} + Run Keyword If $network_id is not $None Delete network ${network_id} + +Create tenant network + &{response} = create network ${network_name} + log many &{response} + Set Suite Variable ${network_id} ${response.network['id']} + log ${network_id} + +Create subnet without dhcp + &{response} = create subnet ${subnet_name} ${network_id} ${subnet_cidr} dhcp=False + log many &{response} + Set Suite Variable ${subnet_id} ${response.subnet['id']} + log ${subnet_id} + +Create port with ip + [Arguments] ${port_name} ${ip_address} + &{response} = create port ${port_name} ${network_id} ${subnet_id} ${ip_address} + log many &{response} + log ${response.port['id']} + [Return] ${response.port['id']} + +Create vm + [Arguments] ${vm_name} ${port_ids} + ${response} = create server ${vm_name} ${vm_image} ${vm_flavor} ${port_ids} + log many ${response} + log ${response.id} + [Return] ${response.id} + +Poll vm + [Arguments] ${id} ${state} + poll server ${id} ${state} + +Delete vm + [Arguments] ${id} + ${response} = delete server ${id} + log ${response} + Poll vm ${id} ${None} + +Delete ports + [Arguments] ${id} + ${response} = delete port ${id} + log ${response} + +Delete network + [Arguments] ${id} + ${response} = delete net ${id} + log ${response} -- cgit 1.2.3-korg