Disable test_auto_allocated_topology_rbac in patrole
[functest.git] / functest / core / singlevm.py
index ad79a8e..71ed069 100644 (file)
@@ -9,11 +9,12 @@
 
 """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
+import re
 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'
+    image_format = 'qcow2'
+    extra_properties = {}
+    filename_alt = filename
+    image_alt_format = image_format
+    extra_alt_properties = extra_properties
     visibility = 'private'
-    extra_properties = None
     flavor_ram = 512
     flavor_vcpus = 1
     flavor_disk = 1
+    flavor_extra_specs = {}
     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)
-        self.orig_cloud = self.cloud
         self.image = None
         self.flavor = None
 
@@ -67,20 +72,55 @@ class VmReady1(tenantnetwork.TenantNetwork1):
         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),
-            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),
-                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
 
@@ -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)
-        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):
@@ -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)
+        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(
-            flavor.id, getattr(config.CONF, 'flavor_extra_specs', {}))
+            flavor.id, flavor_alt_extra_specs)
         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,
-            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
 
+    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
 
@@ -191,14 +256,14 @@ class VmReady1(tenantnetwork.TenantNetwork1):
             if self.flavor:
                 self.orig_cloud.delete_flavor(self.flavor.id)
         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
-    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).
@@ -227,7 +292,7 @@ class VmReady2(VmReady1):
             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):
@@ -243,8 +308,9 @@ class SingleVm1(VmReady1):
 
     __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:
@@ -293,14 +359,15 @@ class SingleVm1(VmReady1):
         """
         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)
-        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())
         for loop in range(self.ssh_connect_loops):
             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(
@@ -312,11 +379,11 @@ class SingleVm1(VmReady1):
                         '{}_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(
-                    "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)
@@ -330,8 +397,9 @@ class SingleVm1(VmReady1):
 
         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("error:\n%s", stderr.read())
         return stdout.channel.recv_exit_status()
 
     def run(self, **kwargs):
@@ -380,14 +448,14 @@ class SingleVm1(VmReady1):
                 self.cloud.delete_keypair(self.keypair.name)
             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
-    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).
@@ -416,4 +484,4 @@ class SingleVm2(SingleVm1):
             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")