Merge "Move common compute clients to the setting method"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index d5311a9..b04d0bb 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -429,7 +429,7 @@
 
 # Does the test environment support live migration available? (boolean
 # value)
-#live_migration = false
+#live_migration = true
 
 # Does the test environment support pausing? (boolean value)
 #pause = true
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 6c29f51..a494896 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -14,11 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class ServerAddressesTestJSON(base.BaseV2ComputeTest):
 
@@ -31,8 +28,6 @@
 
         resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.skip_because(bug="1210483",
-                       condition=CONF.service_available.neutron)
     @test.attr(type='smoke')
     @test.services('network')
     def test_list_server_addresses(self):
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
index 0590146..7b41d71 100644
--- a/tempest/api/compute/v3/servers/test_server_addresses.py
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -14,11 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class ServerAddressesV3Test(base.BaseV3ComputeTest):
 
@@ -31,8 +28,6 @@
 
         resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.skip_because(bug="1210483",
-                       condition=CONF.service_available.neutron)
     @test.attr(type='smoke')
     def test_list_server_addresses(self):
         # All public and private addresses for
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 2e58dae..5e6d8f3 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -84,6 +84,41 @@
         self.assertEqual(self.network['id'], show_net['id'])
         self.assertFalse(show_net['router:external'])
 
+    def test_delete_external_networks_with_floating_ip(self):
+        """Verifies external network can be deleted while still holding
+        (unassociated) floating IPs
+
+        """
+        # Set cls.client to admin to use base.create_subnet()
+        client = self.admin_client
+        _, body = client.create_network(**{'router:external': True})
+        external_network = body['network']
+        self.addCleanup(self._try_delete_resource,
+                        client.delete_network,
+                        external_network['id'])
+        subnet = self.create_subnet(external_network, client=client)
+        _, body = client.create_floatingip(
+            floating_network_id=external_network['id'])
+        created_floating_ip = body['floatingip']
+        self.addCleanup(self._try_delete_resource,
+                        client.delete_floatingip,
+                        created_floating_ip['id'])
+        _, floatingip_list = client.list_floatingips(
+            network=external_network['id'])
+        self.assertIn(created_floating_ip['id'],
+                      (f['id'] for f in floatingip_list['floatingips']))
+        client.delete_network(external_network['id'])
+        # Verifies floating ip is deleted
+        _, floatingip_list = client.list_floatingips()
+        self.assertNotIn(created_floating_ip['id'],
+                         (f['id'] for f in floatingip_list['floatingips']))
+        # Verifies subnet is deleted
+        _, subnet_list = client.list_subnets()
+        self.assertNotIn(subnet['id'],
+                         (s['id'] for s in subnet_list))
+        # Removes subnet from the cleanup list
+        self.subnets.remove(subnet)
+
 
 class ExternalNetworksTestXML(ExternalNetworksTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 7ba68f7..cd04ef7 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -93,58 +93,95 @@
         if CONF.service_available.neutron:
             # Clean up ipsec policies
             for ipsecpolicy in cls.ipsecpolicies:
-                cls.client.delete_ipsecpolicy(ipsecpolicy['id'])
+                cls._try_delete_resource(cls.client.delete_ipsecpolicy,
+                                         ipsecpolicy['id'])
             # Clean up firewall policies
             for fw_policy in cls.fw_policies:
-                cls.client.delete_firewall_policy(fw_policy['id'])
+                cls._try_delete_resource(cls.client.delete_firewall_policy,
+                                         fw_policy['id'])
             # Clean up firewall rules
             for fw_rule in cls.fw_rules:
-                cls.client.delete_firewall_rule(fw_rule['id'])
+                cls._try_delete_resource(cls.client.delete_firewall_rule,
+                                         fw_rule['id'])
             # Clean up ike policies
             for ikepolicy in cls.ikepolicies:
-                cls.client.delete_ikepolicy(ikepolicy['id'])
+                cls._try_delete_resource(cls.client.delete_ikepolicy,
+                                         ikepolicy['id'])
             # Clean up vpn services
             for vpnservice in cls.vpnservices:
-                cls.client.delete_vpnservice(vpnservice['id'])
+                cls._try_delete_resource(cls.client.delete_vpnservice,
+                                         vpnservice['id'])
             # Clean up floating IPs
             for floating_ip in cls.floating_ips:
-                cls.client.delete_floatingip(floating_ip['id'])
+                cls._try_delete_resource(cls.client.delete_floatingip,
+                                         floating_ip['id'])
             # Clean up routers
             for router in cls.routers:
-                cls.delete_router(router)
+                cls._try_delete_resource(cls.delete_router,
+                                         router)
 
             # Clean up health monitors
             for health_monitor in cls.health_monitors:
-                cls.client.delete_health_monitor(health_monitor['id'])
+                cls._try_delete_resource(cls.client.delete_health_monitor,
+                                         health_monitor['id'])
             # Clean up members
             for member in cls.members:
-                cls.client.delete_member(member['id'])
+                cls._try_delete_resource(cls.client.delete_member,
+                                         member['id'])
             # Clean up vips
             for vip in cls.vips:
-                cls.client.delete_vip(vip['id'])
+                cls._try_delete_resource(cls.client.delete_vip,
+                                         vip['id'])
             # Clean up pools
             for pool in cls.pools:
-                cls.client.delete_pool(pool['id'])
+                cls._try_delete_resource(cls.client.delete_pool,
+                                         pool['id'])
             # Clean up metering label rules
             for metering_label_rule in cls.metering_label_rules:
-                cls.admin_client.delete_metering_label_rule(
+                cls._try_delete_resource(
+                    cls.admin_client.delete_metering_label_rule,
                     metering_label_rule['id'])
             # Clean up metering labels
             for metering_label in cls.metering_labels:
-                cls.admin_client.delete_metering_label(metering_label['id'])
+                cls._try_delete_resource(
+                    cls.admin_client.delete_metering_label,
+                    metering_label['id'])
             # Clean up ports
             for port in cls.ports:
-                cls.client.delete_port(port['id'])
+                cls._try_delete_resource(cls.client.delete_port,
+                                         port['id'])
             # Clean up subnets
             for subnet in cls.subnets:
-                cls.client.delete_subnet(subnet['id'])
+                cls._try_delete_resource(cls.client.delete_subnet,
+                                         subnet['id'])
             # Clean up networks
             for network in cls.networks:
-                cls.client.delete_network(network['id'])
+                cls._try_delete_resource(cls.client.delete_network,
+                                         network['id'])
             cls.clear_isolated_creds()
         super(BaseNetworkTest, cls).resource_cleanup()
 
     @classmethod
+    def _try_delete_resource(self, delete_callable, *args, **kwargs):
+        """Cleanup resources in case of test-failure
+
+        Some resources are explicitly deleted by the test.
+        If the test failed to delete a resource, this method will execute
+        the appropriate delete methods. Otherwise, the method ignores NotFound
+        exceptions thrown for resources that were correctly deleted by the
+        test.
+
+        :param delete_callable: delete method
+        :param args: arguments for delete method
+        :param kwargs: keyword arguments for delete method
+        """
+        try:
+            delete_callable(*args, **kwargs)
+        # if resource is not found, this means it was deleted in the test
+        except exceptions.NotFound:
+            pass
+
+    @classmethod
     def create_network(cls, network_name=None):
         """Wrapper utility that returns a test network."""
         network_name = network_name or data_utils.rand_name('test-network-')
@@ -156,8 +193,13 @@
 
     @classmethod
     def create_subnet(cls, network, gateway='', cidr=None, mask_bits=None,
-                      ip_version=None, **kwargs):
+                      ip_version=None, client=None, **kwargs):
         """Wrapper utility that returns a test subnet."""
+
+        # allow tests to use admin client
+        if not client:
+            client = cls.client
+
         # The cidr and mask_bits depend on the ip version.
         ip_version = ip_version if ip_version is not None else cls._ip_version
         gateway_not_set = gateway == ''
@@ -175,7 +217,7 @@
             else:
                 gateway_ip = gateway
             try:
-                resp, body = cls.client.create_subnet(
+                resp, body = client.create_subnet(
                     network_id=network['id'],
                     cidr=str(subnet_cidr),
                     ip_version=ip_version,
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 1189c8f..6e45b0f 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -71,7 +71,7 @@
     @test.attr(type='gate')
     def test_show_quota_usage(self):
         _, quota_usage = self.quotas_client.get_quota_usage(
-            self.os_adm.credentials.tenant_name)
+            self.os_adm.credentials.tenant_id)
         for key in QUOTA_KEYS:
             self.assertIn(key, quota_usage)
             for usage_key in QUOTA_USAGE_KEYS:
diff --git a/tempest/cli/simple_read_only/volume/test_cinder.py b/tempest/cli/simple_read_only/volume/test_cinder.py
index 102f199..c2e0a42 100644
--- a/tempest/cli/simple_read_only/volume/test_cinder.py
+++ b/tempest/cli/simple_read_only/volume/test_cinder.py
@@ -20,6 +20,7 @@
 import testtools
 
 from tempest import cli
+from tempest import clients
 from tempest import config
 
 
@@ -41,6 +42,9 @@
             msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(msg)
         super(SimpleReadOnlyCinderClientTest, cls).resource_setup()
+        id_cl = clients.AdminManager().identity_client
+        tenant = id_cl.get_tenant_by_name(CONF.identity.admin_tenant_name)
+        cls.admin_tenant_id = tenant['id']
 
     def cinder(self, *args, **kwargs):
         return self.clients.cinder(*args,
@@ -87,15 +91,13 @@
     def test_cinder_quota_defaults(self):
         """This CLI can accept and string as param."""
         roles = self.parser.listing(self.cinder('quota-defaults',
-                                                params=CONF.identity.
-                                                admin_tenant_name))
+                                                params=self.admin_tenant_id))
         self.assertTableStruct(roles, ['Property', 'Value'])
 
     def test_cinder_quota_show(self):
         """This CLI can accept and string as param."""
         roles = self.parser.listing(self.cinder('quota-show',
-                                                params=CONF.identity.
-                                                admin_tenant_name))
+                                                params=self.admin_tenant_id))
         self.assertTableStruct(roles, ['Property', 'Value'])
 
     def test_cinder_rate_limits(self):
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index c290dad..6f2e1bd 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -42,7 +42,7 @@
 
 
 # convert a structure into a string safely
-def safe_body(body, maxlen=2048):
+def safe_body(body, maxlen=4096):
     try:
         text = six.text_type(body)
     except UnicodeDecodeError:
diff --git a/tempest/config.py b/tempest/config.py
index 163817c..495de62 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -312,7 +312,7 @@
                 default=True,
                 help="Does the test environment support suspend/resume?"),
     cfg.BoolOpt('live_migration',
-                default=False,
+                default=True,
                 help="Does the test environment support live migration "
                      "available?"),
     cfg.BoolOpt('block_migration_for_live_migration',
diff --git a/tempest/scenario/orchestration/test_server_cfn_init.py b/tempest/scenario/orchestration/test_server_cfn_init.py
index 791c564..ddfabe4 100644
--- a/tempest/scenario/orchestration/test_server_cfn_init.py
+++ b/tempest/scenario/orchestration/test_server_cfn_init.py
@@ -129,6 +129,7 @@
                 raise e
 
     @test.attr(type='slow')
+    @test.skip_because(bug='1374175')
     @test.services('orchestration', 'compute')
     def test_server_cfn_init(self):
         self.assign_keypair()
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 78ed56f..46475f0 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -85,8 +85,14 @@
         update_body['admin_state_up'] = kwargs.get(
             'admin_state_up', body['router']['admin_state_up'])
         cur_gw_info = body['router']['external_gateway_info']
-        if cur_gw_info and not set_enable_snat:
-            cur_gw_info.pop('enable_snat', None)
+        if cur_gw_info:
+            # TODO(kevinbenton): setting the external gateway info is not
+            # allowed for a regular tenant. If the ability to update is also
+            # merged, a test case for this will need to be added similar to
+            # the SNAT case.
+            cur_gw_info.pop('external_fixed_ips', None)
+            if not set_enable_snat:
+                cur_gw_info.pop('enable_snat', None)
         update_body['external_gateway_info'] = kwargs.get(
             'external_gateway_info', body['router']['external_gateway_info'])
         update_body = dict(router=update_body)
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index a23e173..4417e3b 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -230,7 +230,7 @@
 
         url = '?format=%s' % self.format
         if params:
-            url += '&%s' + urllib.urlencode(params)
+            url += '&%s' % urllib.urlencode(params)
 
         headers = {}
         if metadata: