Disable test_auto_allocated_topology_rbac in patrole
[functest.git] / functest / core / singlevm.py
index 88e5155..71ed069 100644 (file)
@@ -9,11 +9,12 @@
 
 """Ease deploying a single VM reachable via ssh
 
 
 """Ease deploying a single VM reachable via ssh
 
-It offers a simple way to create all tenant network ressources + a VM for
+It offers a simple way to create all tenant network resources + a VM for
 advanced testcases (e.g. deploying an orchestrator).
 """
 
 import logging
 advanced testcases (e.g. deploying an orchestrator).
 """
 
 import logging
+import re
 import tempfile
 import time
 
 import tempfile
 import time
 
@@ -37,22 +38,26 @@ class VmReady1(tenantnetwork.TenantNetwork1):
 
     __logger = logging.getLogger(__name__)
     filename = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img'
 
     __logger = logging.getLogger(__name__)
     filename = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img'
+    image_format = 'qcow2'
+    extra_properties = {}
+    filename_alt = filename
+    image_alt_format = image_format
+    extra_alt_properties = extra_properties
     visibility = 'private'
     visibility = 'private'
-    extra_properties = None
     flavor_ram = 512
     flavor_vcpus = 1
     flavor_disk = 1
     flavor_ram = 512
     flavor_vcpus = 1
     flavor_disk = 1
+    flavor_extra_specs = {}
     flavor_alt_ram = 1024
     flavor_alt_vcpus = 1
     flavor_alt_disk = 1
     flavor_alt_ram = 1024
     flavor_alt_vcpus = 1
     flavor_alt_disk = 1
-
-    image_format = 'qcow2'
+    flavor_alt_extra_specs = flavor_extra_specs
+    create_server_timeout = 180
 
     def __init__(self, **kwargs):
         if "case_name" not in kwargs:
             kwargs["case_name"] = 'vmready1'
         super(VmReady1, self).__init__(**kwargs)
 
     def __init__(self, **kwargs):
         if "case_name" not in kwargs:
             kwargs["case_name"] = 'vmready1'
         super(VmReady1, self).__init__(**kwargs)
-        self.orig_cloud = self.cloud
         self.image = None
         self.flavor = None
 
         self.image = None
         self.flavor = None
 
@@ -67,20 +72,55 @@ class VmReady1(tenantnetwork.TenantNetwork1):
         Raises: expection on error
         """
         assert self.cloud
         Raises: expection on error
         """
         assert self.cloud
+        extra_properties = self.extra_properties.copy()
+        extra_properties.update(
+            getattr(config.CONF, '{}_extra_properties'.format(
+                self.case_name), {}))
         image = self.cloud.create_image(
             name if name else '{}-img_{}'.format(self.case_name, self.guid),
             filename=getattr(
                 config.CONF, '{}_image'.format(self.case_name),
                 self.filename),
         image = self.cloud.create_image(
             name if name else '{}-img_{}'.format(self.case_name, self.guid),
             filename=getattr(
                 config.CONF, '{}_image'.format(self.case_name),
                 self.filename),
-            meta=getattr(
-                config.CONF, '{}_extra_properties'.format(self.case_name),
-                self.extra_properties),
+            meta=extra_properties,
             disk_format=getattr(
                 config.CONF, '{}_image_format'.format(self.case_name),
                 self.image_format),
             visibility=getattr(
                 config.CONF, '{}_visibility'.format(self.case_name),
             disk_format=getattr(
                 config.CONF, '{}_image_format'.format(self.case_name),
                 self.image_format),
             visibility=getattr(
                 config.CONF, '{}_visibility'.format(self.case_name),
-                self.visibility))
+                self.visibility),
+            wait=True)
+        self.__logger.debug("image: %s", image)
+        return image
+
+    def publish_image_alt(self, name=None):
+        """Publish alternative image
+
+        It allows publishing multiple images for the child testcases. It forces
+        the same configuration for all subtestcases.
+
+        Returns: image
+
+        Raises: expection on error
+        """
+        assert self.cloud
+        extra_alt_properties = self.extra_alt_properties.copy()
+        extra_alt_properties.update(
+            getattr(config.CONF, '{}_extra_alt_properties'.format(
+                self.case_name), {}))
+        image = self.cloud.create_image(
+            name if name else '{}-img_alt_{}'.format(
+                self.case_name, self.guid),
+            filename=getattr(
+                config.CONF, '{}_image_alt'.format(self.case_name),
+                self.filename_alt),
+            meta=extra_alt_properties,
+            disk_format=getattr(
+                config.CONF, '{}_image_alt_format'.format(self.case_name),
+                self.image_format),
+            visibility=getattr(
+                config.CONF, '{}_visibility'.format(self.case_name),
+                self.visibility),
+            wait=True)
         self.__logger.debug("image: %s", image)
         return image
 
         self.__logger.debug("image: %s", image)
         return image
 
@@ -104,8 +144,11 @@ class VmReady1(tenantnetwork.TenantNetwork1):
             getattr(config.CONF, '{}_flavor_disk'.format(self.case_name),
                     self.flavor_disk))
         self.__logger.debug("flavor: %s", flavor)
             getattr(config.CONF, '{}_flavor_disk'.format(self.case_name),
                     self.flavor_disk))
         self.__logger.debug("flavor: %s", flavor)
-        self.orig_cloud.set_flavor_specs(
-            flavor.id, getattr(config.CONF, 'flavor_extra_specs', {}))
+        flavor_extra_specs = self.flavor_extra_specs.copy()
+        flavor_extra_specs.update(
+            getattr(config.CONF,
+                    '{}_flavor_extra_specs'.format(self.case_name), {}))
+        self.orig_cloud.set_flavor_specs(flavor.id, flavor_extra_specs)
         return flavor
 
     def create_flavor_alt(self, name=None):
         return flavor
 
     def create_flavor_alt(self, name=None):
@@ -129,8 +172,12 @@ class VmReady1(tenantnetwork.TenantNetwork1):
             getattr(config.CONF, '{}_flavor_alt_disk'.format(self.case_name),
                     self.flavor_alt_disk))
         self.__logger.debug("flavor: %s", flavor)
             getattr(config.CONF, '{}_flavor_alt_disk'.format(self.case_name),
                     self.flavor_alt_disk))
         self.__logger.debug("flavor: %s", flavor)
+        flavor_alt_extra_specs = self.flavor_alt_extra_specs.copy()
+        flavor_alt_extra_specs.update(
+            getattr(config.CONF,
+                    '{}_flavor_alt_extra_specs'.format(self.case_name), {}))
         self.orig_cloud.set_flavor_specs(
         self.orig_cloud.set_flavor_specs(
-            flavor.id, getattr(config.CONF, 'flavor_extra_specs', {}))
+            flavor.id, flavor_alt_extra_specs)
         return flavor
 
     def boot_vm(self, name=None, **kwargs):
         return flavor
 
     def boot_vm(self, name=None, **kwargs):
@@ -147,13 +194,31 @@ class VmReady1(tenantnetwork.TenantNetwork1):
         vm1 = self.cloud.create_server(
             name if name else '{}-vm_{}'.format(self.case_name, self.guid),
             image=self.image.id, flavor=self.flavor.id,
         vm1 = self.cloud.create_server(
             name if name else '{}-vm_{}'.format(self.case_name, self.guid),
             image=self.image.id, flavor=self.flavor.id,
-            auto_ip=False, wait=True,
-            network=self.network.id,
-            **kwargs)
-        vm1 = self.cloud.wait_for_server(vm1, auto_ip=False)
+            auto_ip=False, network=self.network.id,
+            timeout=self.create_server_timeout, wait=True, **kwargs)
         self.__logger.debug("vm: %s", vm1)
         return vm1
 
         self.__logger.debug("vm: %s", vm1)
         return vm1
 
+    def check_regex_in_console(self, name, regex=' login: ', loop=1):
+        """Wait for specific message in console
+
+        Returns: True or False on errors
+        """
+        assert self.cloud
+        for iloop in range(loop):
+            console = self.cloud.get_server_console(name)
+            self.__logger.debug("console: \n%s", console)
+            if re.search(regex, console):
+                self.__logger.debug("regex found: ''%s' in console", regex)
+                return True
+            else:
+                self.__logger.debug(
+                    "try %s: cannot find regex '%s' in console",
+                    iloop + 1, regex)
+                time.sleep(10)
+        self.__logger.error("cannot find regex '%s' in console", regex)
+        return False
+
     def run(self, **kwargs):
         """Boot the new VM
 
     def run(self, **kwargs):
         """Boot the new VM
 
@@ -168,13 +233,15 @@ class VmReady1(tenantnetwork.TenantNetwork1):
         status = testcase.TestCase.EX_RUN_ERROR
         try:
             assert self.cloud
         status = testcase.TestCase.EX_RUN_ERROR
         try:
             assert self.cloud
-            super(VmReady1, self).run(**kwargs)
+            assert super(VmReady1, self).run(
+                **kwargs) == testcase.TestCase.EX_OK
             self.image = self.publish_image()
             self.flavor = self.create_flavor()
             self.result = 100
             status = testcase.TestCase.EX_OK
         except Exception:  # pylint: disable=broad-except
             self.__logger.exception('Cannot run %s', self.case_name)
             self.image = self.publish_image()
             self.flavor = self.create_flavor()
             self.result = 100
             status = testcase.TestCase.EX_OK
         except Exception:  # pylint: disable=broad-except
             self.__logger.exception('Cannot run %s', self.case_name)
+            self.result = 0
         finally:
             self.stop_time = time.time()
         return status
         finally:
             self.stop_time = time.time()
         return status
@@ -184,17 +251,19 @@ class VmReady1(tenantnetwork.TenantNetwork1):
             assert self.orig_cloud
             assert self.cloud
             super(VmReady1, self).clean()
             assert self.orig_cloud
             assert self.cloud
             super(VmReady1, self).clean()
-            self.cloud.delete_image(self.image.id)
-            self.orig_cloud.delete_flavor(self.flavor.id)
+            if self.image:
+                self.cloud.delete_image(self.image.id)
+            if self.flavor:
+                self.orig_cloud.delete_flavor(self.flavor.id)
         except Exception:  # pylint: disable=broad-except
         except Exception:  # pylint: disable=broad-except
-            self.__logger.exception("Cannot clean all ressources")
+            self.__logger.exception("Cannot clean all resources")
 
 
 class VmReady2(VmReady1):
     """Deploy a single VM reachable via ssh (scenario2)
 
     It creates new user/project before creating and configuring all tenant
 
 
 class VmReady2(VmReady1):
     """Deploy a single VM reachable via ssh (scenario2)
 
     It creates new user/project before creating and configuring all tenant
-    network ressources, flavors, images, etc. required by advanced testcases.
+    network resources, flavors, images, etc. required by advanced testcases.
 
     It ensures that all testcases inheriting from SingleVm2 could work
     without specific configurations (or at least read the same config data).
 
     It ensures that all testcases inheriting from SingleVm2 could work
     without specific configurations (or at least read the same config data).
@@ -223,7 +292,7 @@ class VmReady2(VmReady1):
             assert self.project
             self.project.clean()
         except Exception:  # pylint: disable=broad-except
             assert self.project
             self.project.clean()
         except Exception:  # pylint: disable=broad-except
-            self.__logger.exception("Cannot clean all ressources")
+            self.__logger.exception("Cannot clean all resources")
 
 
 class SingleVm1(VmReady1):
 
 
 class SingleVm1(VmReady1):
@@ -239,7 +308,9 @@ class SingleVm1(VmReady1):
 
     __logger = logging.getLogger(__name__)
     username = 'cirros'
 
     __logger = logging.getLogger(__name__)
     username = 'cirros'
-    ssh_connect_timeout = 60
+    ssh_connect_timeout = 1
+    ssh_connect_loops = 6
+    create_floating_ip_timeout = 120
 
     def __init__(self, **kwargs):
         if "case_name" not in kwargs:
 
     def __init__(self, **kwargs):
         if "case_name" not in kwargs:
@@ -288,14 +359,15 @@ class SingleVm1(VmReady1):
         """
         assert vm1
         fip = self.cloud.create_floating_ip(
         """
         assert vm1
         fip = self.cloud.create_floating_ip(
-            network=self.ext_net.id, server=vm1)
+            network=self.ext_net.id, server=vm1, wait=True,
+            timeout=self.create_floating_ip_timeout)
         self.__logger.debug("floating_ip: %s", fip)
         self.__logger.debug("floating_ip: %s", fip)
-        p_console = self.cloud.get_server_console(vm1)
-        self.__logger.debug("vm console: \n%s", p_console)
         ssh = paramiko.SSHClient()
         ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
         ssh = paramiko.SSHClient()
         ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
-        for loop in range(6):
+        for loop in range(self.ssh_connect_loops):
             try:
             try:
+                p_console = self.cloud.get_server_console(vm1)
+                self.__logger.debug("vm console: \n%s", p_console)
                 ssh.connect(
                     fip.floating_ip_address,
                     username=getattr(
                 ssh.connect(
                     fip.floating_ip_address,
                     username=getattr(
@@ -307,11 +379,11 @@ class SingleVm1(VmReady1):
                         '{}_vm_ssh_connect_timeout'.format(self.case_name),
                         self.ssh_connect_timeout))
                 break
                         '{}_vm_ssh_connect_timeout'.format(self.case_name),
                         self.ssh_connect_timeout))
                 break
-            except Exception:  # pylint: disable=broad-except
+            except Exception as exc:  # pylint: disable=broad-except
                 self.__logger.debug(
                 self.__logger.debug(
-                    "try %s: cannot connect to %s", loop + 1,
-                    fip.floating_ip_address)
-                time.sleep(10)
+                    "try %s: cannot connect to %s: %s", loop + 1,
+                    fip.floating_ip_address, exc)
+                time.sleep(9)
         else:
             self.__logger.error(
                 "cannot connect to %s", fip.floating_ip_address)
         else:
             self.__logger.error(
                 "cannot connect to %s", fip.floating_ip_address)
@@ -325,8 +397,9 @@ class SingleVm1(VmReady1):
 
         Returns: echo exit codes
         """
 
         Returns: echo exit codes
         """
-        (_, stdout, _) = self.ssh.exec_command('echo Hello World')
+        (_, stdout, stderr) = self.ssh.exec_command('echo Hello World')
         self.__logger.debug("output:\n%s", stdout.read())
         self.__logger.debug("output:\n%s", stdout.read())
+        self.__logger.debug("error:\n%s", stderr.read())
         return stdout.channel.recv_exit_status()
 
     def run(self, **kwargs):
         return stdout.channel.recv_exit_status()
 
     def run(self, **kwargs):
@@ -345,7 +418,8 @@ class SingleVm1(VmReady1):
         status = testcase.TestCase.EX_RUN_ERROR
         try:
             assert self.cloud
         status = testcase.TestCase.EX_RUN_ERROR
         try:
             assert self.cloud
-            super(SingleVm1, self).run(**kwargs)
+            assert super(SingleVm1, self).run(
+                **kwargs) == testcase.TestCase.EX_OK
             self.result = 0
             self.prepare()
             self.sshvm = self.boot_vm(
             self.result = 0
             self.prepare()
             self.sshvm = self.boot_vm(
@@ -364,20 +438,24 @@ class SingleVm1(VmReady1):
         try:
             assert self.orig_cloud
             assert self.cloud
         try:
             assert self.orig_cloud
             assert self.cloud
-            self.cloud.delete_floating_ip(self.fip.id)
-            self.cloud.delete_server(self.sshvm, wait=True)
-            self.cloud.delete_security_group(self.sec.id)
-            self.cloud.delete_keypair(self.keypair.id)
+            if self.fip:
+                self.cloud.delete_floating_ip(self.fip.id)
+            if self.sshvm:
+                self.cloud.delete_server(self.sshvm, wait=True)
+            if self.sec:
+                self.cloud.delete_security_group(self.sec.id)
+            if self.keypair:
+                self.cloud.delete_keypair(self.keypair.name)
             super(SingleVm1, self).clean()
         except Exception:  # pylint: disable=broad-except
             super(SingleVm1, self).clean()
         except Exception:  # pylint: disable=broad-except
-            self.__logger.exception("Cannot clean all ressources")
+            self.__logger.exception("Cannot clean all resources")
 
 
 class SingleVm2(SingleVm1):
     """Deploy a single VM reachable via ssh (scenario2)
 
     It creates new user/project before creating and configuring all tenant
 
 
 class SingleVm2(SingleVm1):
     """Deploy a single VM reachable via ssh (scenario2)
 
     It creates new user/project before creating and configuring all tenant
-    network ressources and vms required by advanced testcases.
+    network resources and vms required by advanced testcases.
 
     It ensures that all testcases inheriting from SingleVm2 could work
     without specific configurations (or at least read the same config data).
 
     It ensures that all testcases inheriting from SingleVm2 could work
     without specific configurations (or at least read the same config data).
@@ -406,4 +484,4 @@ class SingleVm2(SingleVm1):
             assert self.project
             self.project.clean()
         except Exception:  # pylint: disable=broad-except
             assert self.project
             self.project.clean()
         except Exception:  # pylint: disable=broad-except
-            self.__logger.exception("Cannot clean all ressources")
+            self.__logger.exception("Cannot clean all resources")