Merge "Stop passing around dicts in validation resources"
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index 5d62f67..ae9d584 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -19,15 +19,15 @@
 LOG = logging.getLogger(__name__)
 
 
-def _network_service(os, use_neutron):
+def _network_service(clients, use_neutron):
     # Internal helper to select the right network clients
     if use_neutron:
-        return os.network
+        return clients.network
     else:
-        return os.compute
+        return clients.compute
 
 
-def create_ssh_security_group(os, add_rule=False, ethertype='IPv4',
+def create_ssh_security_group(clients, add_rule=False, ethertype='IPv4',
                               use_neutron=True):
     """Create a security group for ping/ssh testing
 
@@ -35,8 +35,9 @@
     clients. If rules are added, the group can be attached to a VM to enable
     connectivity validation over ICMP and further testing over SSH.
 
-    :param os: An instance of `tempest.lib.services.clients.ServiceClients` or
-        of a subclass of it. Resources are provisioned using clients from `os`.
+    :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+        or of a subclass of it. Resources are provisioned using clients from
+        `clients`.
     :param add_rule: Whether security group rules are provisioned or not.
         Defaults to `False`.
     :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
@@ -53,13 +54,14 @@
         creds = auth.get_credentials('http://mycloud/identity/v3',
                                      username='me', project_name='me',
                                      password='secret', domain_name='Default')
-        os = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+        osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
         # Security group for IPv4 tests
-        sg4 = vr.create_ssh_security_group(os, add_rule=True)
+        sg4 = vr.create_ssh_security_group(osclients, add_rule=True)
         # Security group for IPv6 tests
-        sg6 = vr.create_ssh_security_group(os, ethertype='IPv6', add_rule=True)
+        sg6 = vr.create_ssh_security_group(osclients, ethertype='IPv6',
+                                           add_rule=True)
     """
-    network_service = _network_service(os, use_neutron)
+    network_service = _network_service(clients, use_neutron)
     security_groups_client = network_service.SecurityGroupsClient()
     security_group_rules_client = network_service.SecurityGroupRulesClient()
     # Security Group clients for nova and neutron behave the same
@@ -95,7 +97,9 @@
     return security_group
 
 
-def create_validation_resources(os, validation_resources=None,
+def create_validation_resources(clients, keypair=False, floating_ip=False,
+                                security_group=False,
+                                security_group_rules=False,
                                 ethertype='IPv4', use_neutron=True,
                                 floating_network_id=None,
                                 floating_network_name=None):
@@ -104,16 +108,20 @@
     Create resources required to be able to ping / ssh a virtual machine:
     keypair, security group, security group rules and a floating IP.
     Which of those resources are required may depend on the cloud setup and on
-    the specific test and it can be controlled via the validation_resources
-    dictionary.
+    the specific test and it can be controlled via the corresponding
+    arguments.
 
     Provisioned resources are returned in a dictionary.
 
-    :param os: An instance of `tempest.lib.services.clients.ServiceClients` or
-        of a subclass of it. Resources are provisioned using clients from `os`.
-    :param validation_resources: A dictionary that specifies which resources to
-        provision. Required keys are: 'keypair', 'security_group',
-        'security_group_rules' and 'floating_ip'.
+    :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+        or of a subclass of it. Resources are provisioned using clients from
+        `clients`.
+    :param keypair: Whether to provision a keypair. Defaults to False.
+    :param floating_ip: Whether to provision a floating IP. Defaults to False.
+    :param security_group: Whether to provision a security group. Defaults to
+        False.
+    :param security_group_rules: Whether to provision security group rules.
+        Defaults to False.
     :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
     :param use_neutron: When True resources are provisioned via neutron, when
         False resources are provisioned via nova.
@@ -135,55 +143,54 @@
         creds = auth.get_credentials('http://mycloud/identity/v3',
                                      username='me', project_name='me',
                                      password='secret', domain_name='Default')
-        os = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+        osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
         # Request keypair and floating IP
         resources = dict(keypair=True, security_group=False,
                          security_group_rules=False, floating_ip=True)
         resources = vr.create_validation_resources(
-            os, validation_resources=resources, use_neutron=True,
-            floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C')
+            osclients, use_neutron=True,
+            floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C',
+            **resources)
 
         # The floating IP to be attached to the VM
         floating_ip = resources['floating_ip']['ip']
     """
     # Create and Return the validation resources required to validate a VM
     validation_data = {}
-    if validation_resources:
-        if validation_resources['keypair']:
-            keypair_name = data_utils.rand_name('keypair')
-            validation_data.update(os.compute.KeyPairsClient().create_keypair(
+    if keypair:
+        keypair_name = data_utils.rand_name('keypair')
+        validation_data.update(
+            clients.compute.KeyPairsClient().create_keypair(
                 name=keypair_name))
-            LOG.debug("Validation resource key %s created", keypair_name)
-        add_rule = False
-        if validation_resources['security_group']:
-            if validation_resources['security_group_rules']:
-                add_rule = True
-            validation_data['security_group'] = \
-                create_ssh_security_group(
-                    os, add_rule, use_neutron=use_neutron, ethertype=ethertype)
-        if validation_resources['floating_ip']:
-            floating_ip_client = _network_service(
-                os, use_neutron).FloatingIPsClient()
-            if use_neutron:
-                floatingip = floating_ip_client.create_floatingip(
-                    floating_network_id=floating_network_id)
-                # validation_resources['floating_ip'] has historically looked
-                # like a compute API POST /os-floating-ips response, so we need
-                # to mangle it a bit for a Neutron response with different
-                # fields.
-                validation_data['floating_ip'] = floatingip['floatingip']
-                validation_data['floating_ip']['ip'] = (
-                    floatingip['floatingip']['floating_ip_address'])
-            else:
-                # NOTE(mriedem): The os-floating-ips compute API was deprecated
-                # in the 2.36 microversion. Any tests for CRUD operations on
-                # floating IPs using the compute API should be capped at 2.35.
-                validation_data.update(floating_ip_client.create_floating_ip(
-                    pool=floating_network_name))
+        LOG.debug("Validation resource key %s created", keypair_name)
+    if security_group:
+        validation_data['security_group'] = create_ssh_security_group(
+            clients, add_rule=security_group_rules,
+            use_neutron=use_neutron, ethertype=ethertype)
+    if floating_ip:
+        floating_ip_client = _network_service(
+            clients, use_neutron).FloatingIPsClient()
+        if use_neutron:
+            floatingip = floating_ip_client.create_floatingip(
+                floating_network_id=floating_network_id)
+            # validation_resources['floating_ip'] has historically looked
+            # like a compute API POST /os-floating-ips response, so we need
+            # to mangle it a bit for a Neutron response with different
+            # fields.
+            validation_data['floating_ip'] = floatingip['floatingip']
+            validation_data['floating_ip']['ip'] = (
+                floatingip['floatingip']['floating_ip_address'])
+        else:
+            # NOTE(mriedem): The os-floating-ips compute API was deprecated
+            # in the 2.36 microversion. Any tests for CRUD operations on
+            # floating IPs using the compute API should be capped at 2.35.
+            validation_data.update(floating_ip_client.create_floating_ip(
+                pool=floating_network_name))
     return validation_data
 
 
-def clear_validation_resources(os, validation_data=None, use_neutron=True):
+def clear_validation_resources(clients, keypair=None, floating_ip=None,
+                               security_group=None, use_neutron=True):
     """Cleanup resources for VM ping/ssh testing
 
     Cleanup a set of resources provisioned via `create_validation_resources`.
@@ -191,12 +198,15 @@
     process is continued. The first exception that was raised is re-raised
     after the cleanup is complete.
 
-    :param os: An instance of `tempest.lib.services.clients.ServiceClients` or
-        of a subclass of it. Resources are provisioned using clients from `os`.
-    :param validation_data: A dictionary that specifies resources to be
-        cleaned up in the format returned by `create_validation_resources`.
-        Required keys are: 'keypair', 'security_group', 'security_group_rules'
-        and 'floating_ip'.
+    :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+        or of a subclass of it. Resources are provisioned using clients from
+        `clients`.
+    :param keypair: A dictionary with the keypair to be deleted. Defaults to
+        None.
+    :param floating_ip: A dictionary with the floating_ip to be deleted.
+        Defaults to None.
+    :param security_group: A dictionary with the security_group to be deleted.
+        Defaults to None.
     :param use_neutron: When True resources are provisioned via neutron, when
         False resources are provisioned via nova.
     :returns: A dictionary with the same keys as the input
@@ -212,71 +222,71 @@
         creds = auth.get_credentials('http://mycloud/identity/v3',
                                      username='me', project_name='me',
                                      password='secret', domain_name='Default')
-        os = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+        osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
         # Request keypair and floating IP
         resources = dict(keypair=True, security_group=False,
                          security_group_rules=False, floating_ip=True)
         resources = vr.create_validation_resources(
-            os, validation_resources=resources, use_neutron=True,
+            osclients, validation_resources=resources, use_neutron=True,
             floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C')
 
         # Now cleanup the resources
         try:
-            vr.clear_validation_resources(os, resources)
+            vr.clear_validation_resources(osclients, use_neutron=True,
+                                          **resources)
         except Exception as e:
             LOG.exception('Something went wrong during cleanup, ignoring')
     """
     has_exception = None
-    if validation_data:
-        if 'keypair' in validation_data:
-            keypair_client = os.compute.KeyPairsClient()
-            keypair_name = validation_data['keypair']['name']
-            try:
-                keypair_client.delete_keypair(keypair_name)
-            except lib_exc.NotFound:
-                LOG.warning(
-                    "Keypair %s is not found when attempting to delete",
-                    keypair_name
-                )
-            except Exception as exc:
-                LOG.exception('Exception raised while deleting key %s',
-                              keypair_name)
-                if not has_exception:
-                    has_exception = exc
-        network_service = _network_service(os, use_neutron)
-        if 'security_group' in validation_data:
-            security_group_client = network_service.SecurityGroupsClient()
-            sec_id = validation_data['security_group']['id']
-            try:
-                security_group_client.delete_security_group(sec_id)
-                security_group_client.wait_for_resource_deletion(sec_id)
-            except lib_exc.NotFound:
-                LOG.warning("Security group %s is not found when attempting "
-                            "to delete", sec_id)
-            except lib_exc.Conflict as exc:
-                LOG.exception('Conflict while deleting security '
-                              'group %s VM might not be deleted', sec_id)
-                if not has_exception:
-                    has_exception = exc
-            except Exception as exc:
-                LOG.exception('Exception raised while deleting security '
-                              'group %s', sec_id)
-                if not has_exception:
-                    has_exception = exc
-        if 'floating_ip' in validation_data:
-            floating_ip_client = network_service.FloatingIPsClient()
-            fip_id = validation_data['floating_ip']['id']
-            try:
-                if use_neutron:
-                    floating_ip_client.delete_floatingip(fip_id)
-                else:
-                    floating_ip_client.delete_floating_ip(fip_id)
-            except lib_exc.NotFound:
-                LOG.warning('Floating ip %s not found while attempting to '
-                            'delete', fip_id)
-            except Exception as exc:
-                LOG.exception('Exception raised while deleting ip %s', fip_id)
-                if not has_exception:
-                    has_exception = exc
+    if keypair:
+        keypair_client = clients.compute.KeyPairsClient()
+        keypair_name = keypair['name']
+        try:
+            keypair_client.delete_keypair(keypair_name)
+        except lib_exc.NotFound:
+            LOG.warning(
+                "Keypair %s is not found when attempting to delete",
+                keypair_name
+            )
+        except Exception as exc:
+            LOG.exception('Exception raised while deleting key %s',
+                          keypair_name)
+            if not has_exception:
+                has_exception = exc
+    network_service = _network_service(clients, use_neutron)
+    if security_group:
+        security_group_client = network_service.SecurityGroupsClient()
+        sec_id = security_group['id']
+        try:
+            security_group_client.delete_security_group(sec_id)
+            security_group_client.wait_for_resource_deletion(sec_id)
+        except lib_exc.NotFound:
+            LOG.warning("Security group %s is not found when attempting "
+                        "to delete", sec_id)
+        except lib_exc.Conflict as exc:
+            LOG.exception('Conflict while deleting security '
+                          'group %s VM might not be deleted', sec_id)
+            if not has_exception:
+                has_exception = exc
+        except Exception as exc:
+            LOG.exception('Exception raised while deleting security '
+                          'group %s', sec_id)
+            if not has_exception:
+                has_exception = exc
+    if floating_ip:
+        floating_ip_client = network_service.FloatingIPsClient()
+        fip_id = floating_ip['id']
+        try:
+            if use_neutron:
+                floating_ip_client.delete_floatingip(fip_id)
+            else:
+                floating_ip_client.delete_floating_ip(fip_id)
+        except lib_exc.NotFound:
+            LOG.warning('Floating ip %s not found while attempting to '
+                        'delete', fip_id)
+        except Exception as exc:
+            LOG.exception('Exception raised while deleting ip %s', fip_id)
+            if not has_exception:
+                has_exception = exc
     if has_exception:
         raise has_exception
diff --git a/tempest/test.py b/tempest/test.py
index 5937a9b..78db8e1 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -379,12 +379,14 @@
             raise lib_exc.InvalidConfiguration(
                 msg % CONF.validation.ip_version_for_ssh)
         if hasattr(cls, "os_primary"):
+            vr = cls.validation_resources
             cls.validation_resources = vresources.create_validation_resources(
-                cls.os_primary, cls.validation_resources,
+                cls.os_primary,
                 use_neutron=CONF.service_available.neutron,
                 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
                 floating_network_id=CONF.network.public_network_id,
-                floating_network_name=CONF.network.floating_network_name)
+                floating_network_name=CONF.network.floating_network_name,
+                **vr)
         else:
             LOG.warning("Client manager not found, validation resources not"
                         " created")
@@ -398,9 +400,10 @@
         """
         if cls.validation_resources:
             if hasattr(cls, "os_primary"):
+                vr = cls.validation_resources
                 vresources.clear_validation_resources(
-                    cls.os_primary, cls.validation_resources,
-                    use_neutron=CONF.service_available.neutron)
+                    cls.os_primary,
+                    use_neutron=CONF.service_available.neutron, **vr)
                 cls.validation_resources = {}
             else:
                 LOG.warning("Client manager not found, validation resources "