Initial robot smoke suite which creates two vms and tries to ping them directly from... 67/16167/1
authorJuraj Linkes <jlinkes@cisco.com>
Thu, 30 Jun 2016 09:30:27 +0000 (11:30 +0200)
committerJuraj Linkes <jlinkes@cisco.com>
Thu, 30 Jun 2016 10:43:41 +0000 (12:43 +0200)
Change-Id: Ib1057d5cb3942bf1eafa2288bc9d40391a35a662
Signed-off-by: Juraj Linkes <jlinkes@cisco.com>
.gitignore [new file with mode: 0644]
testing/robot/data/test_data.py [new file with mode: 0644]
testing/robot/lib/FDSLibrary.py [new file with mode: 0644]
testing/robot/requirements.txt [new file with mode: 0644]
testing/robot/smoke.robot [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..3b854ca
--- /dev/null
@@ -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 (file)
index 0000000..cd3b170
--- /dev/null
@@ -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 (file)
index 0000000..2e29d6c
--- /dev/null
@@ -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 (file)
index 0000000..87f9867
--- /dev/null
@@ -0,0 +1,2 @@
+python-openstackclient
+python-neutronclient
diff --git a/testing/robot/smoke.robot b/testing/robot/smoke.robot
new file mode 100644 (file)
index 0000000..17b19bf
--- /dev/null
@@ -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}