Merge "Configure stable service clients via the registry"
diff --git a/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml b/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml
new file mode 100644
index 0000000..cfe97c5
--- /dev/null
+++ b/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+
+  - The ``nova_cert`` option default is changed to ``False``. The nova
+    certification management APIs were a hold over from ec2, and are
+    not used by any other parts of nova. They are deprecated for
+    removal in nova after the newton release. This makes false a more
+    sensible default going forward.
\ No newline at end of file
diff --git a/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml b/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
index df7e46d..6a4fc2b 100644
--- a/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
+++ b/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
@@ -10,3 +10,7 @@
       * availability_zone_client(v2)
       * extensions_client(v1)
       * extensions_client(v2)
+      * hosts_client(v1)
+      * hosts_client(v2)
+      * services_client(v1)
+      * services_client(v2)
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 11350e6..ff28b50 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -59,44 +59,6 @@
         backup.update(changes)
         return self._encode_backup(backup)
 
-    @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
-    def test_volume_backup_create_get_detailed_list_restore_delete(self):
-        # Create backup
-        backup_name = data_utils.rand_name('Backup')
-        create_backup = self.admin_backups_client.create_backup
-        backup = create_backup(volume_id=self.volume['id'],
-                               name=backup_name)['backup']
-        self.addCleanup(self.admin_backups_client.delete_backup,
-                        backup['id'])
-        self.assertEqual(backup_name, backup['name'])
-        waiters.wait_for_volume_status(self.admin_volume_client,
-                                       self.volume['id'], 'available')
-        self.admin_backups_client.wait_for_backup_status(backup['id'],
-                                                         'available')
-
-        # Get a given backup
-        backup = self.admin_backups_client.show_backup(backup['id'])['backup']
-        self.assertEqual(backup_name, backup['name'])
-
-        # Get all backups with detail
-        backups = self.admin_backups_client.list_backups(
-            detail=True)['backups']
-        self.assertIn((backup['name'], backup['id']),
-                      [(m['name'], m['id']) for m in backups])
-
-        # Restore backup
-        restore = self.admin_backups_client.restore_backup(
-            backup['id'])['restore']
-
-        # Delete backup
-        self.addCleanup(self.admin_volume_client.delete_volume,
-                        restore['volume_id'])
-        self.assertEqual(backup['id'], restore['backup_id'])
-        self.admin_backups_client.wait_for_backup_status(backup['id'],
-                                                         'available')
-        waiters.wait_for_volume_status(self.admin_volume_client,
-                                       restore['volume_id'], 'available')
-
     @test.idempotent_id('a99c54a1-dd80-4724-8a13-13bf58d4068d')
     def test_volume_backup_export_import(self):
         """Test backup export import functionality.
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 87146db..d83c308 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -36,6 +36,44 @@
 
         cls.volume = cls.create_volume()
 
+    @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
+    def test_volume_backup_create_get_detailed_list_restore_delete(self):
+        # Create backup
+        backup_name = data_utils.rand_name('Backup')
+        create_backup = self.backups_client.create_backup
+        backup = create_backup(volume_id=self.volume['id'],
+                               name=backup_name)['backup']
+        self.addCleanup(self.backups_client.delete_backup,
+                        backup['id'])
+        self.assertEqual(backup_name, backup['name'])
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       self.volume['id'], 'available')
+        self.backups_client.wait_for_backup_status(backup['id'],
+                                                   'available')
+
+        # Get a given backup
+        backup = self.backups_client.show_backup(backup['id'])['backup']
+        self.assertEqual(backup_name, backup['name'])
+
+        # Get all backups with detail
+        backups = self.backups_client.list_backups(
+            detail=True)['backups']
+        self.assertIn((backup['name'], backup['id']),
+                      [(m['name'], m['id']) for m in backups])
+
+        # Restore backup
+        restore = self.backups_client.restore_backup(
+            backup['id'])['restore']
+
+        # Delete backup
+        self.addCleanup(self.volumes_client.delete_volume,
+                        restore['volume_id'])
+        self.assertEqual(backup['id'], restore['backup_id'])
+        self.backups_client.wait_for_backup_status(backup['id'],
+                                                   'available')
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       restore['volume_id'], 'available')
+
     @test.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
     @test.services('compute')
     def test_backup_create_attached_volume(self):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 073481c..9d307ee 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -53,9 +53,7 @@
                     return
                 # NOTE(afazekas): The instance is in "ready for action state"
                 # when no task in progress
-                # NOTE(afazekas): Converted to string because of the XML
-                # responses
-                if str(task_state) == "None":
+                if task_state is None:
                     # without state api extension 3 sec usually enough
                     time.sleep(CONF.compute.ready_wait)
                     return
diff --git a/tempest/config.py b/tempest/config.py
index d67de33..3fd20ab 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -380,8 +380,9 @@
                 help='Does the test environment support creating snapshot '
                      'images of running instances?'),
     cfg.BoolOpt('nova_cert',
-                default=True,
-                help='Does the test environment have the nova cert running?'),
+                default=False,
+                help='Does the test environment have the nova cert running?',
+                deprecated_for_removal=True),
     cfg.BoolOpt('personality',
                 default=False,
                 help='Does the test environment support server personality'),
@@ -502,7 +503,7 @@
                 default=False,
                 help="Whether project networks can be reached directly from "
                      "the test client. This must be set to True when the "
-                     "'fixed' ssh_connect_method is selected."),
+                     "'fixed' connect_method is selected."),
     cfg.StrOpt('public_network_id',
                default="",
                help="Id of the public network that provides external "
@@ -653,7 +654,7 @@
     cfg.StrOpt('network_for_ssh',
                default='public',
                help="Network used for SSH connections. Ignored if "
-                    "connect_method=floating or run_validation=false.",
+                    "connect_method=floating.",
                deprecated_opts=[cfg.DeprecatedOpt('network_for_ssh',
                                                   group='compute')]),
 ]
diff --git a/tempest/lib/services/network/base.py b/tempest/lib/services/network/base.py
index a6ada04..620e0f1 100644
--- a/tempest/lib/services/network/base.py
+++ b/tempest/lib/services/network/base.py
@@ -54,18 +54,26 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def create_resource(self, uri, post_data):
+    def create_resource(self, uri, post_data, expect_empty_body=False):
         req_uri = self.uri_prefix + uri
         req_post_data = json.dumps(post_data)
         resp, body = self.post(req_uri, req_post_data)
-        body = json.loads(body)
+        # NOTE: RFC allows both a valid non-empty body and an empty body for
+        # response of POST API. If a body is expected not empty, we decode the
+        # body. Otherwise we returns the body as it is.
+        if not expect_empty_body:
+            body = json.loads(body)
         self.expected_success(201, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def update_resource(self, uri, post_data):
+    def update_resource(self, uri, post_data, expect_empty_body=False):
         req_uri = self.uri_prefix + uri
         req_post_data = json.dumps(post_data)
         resp, body = self.put(req_uri, req_post_data)
-        body = json.loads(body)
+        # NOTE: RFC allows both a valid non-empty body and an empty body for
+        # response of PUT API. If a body is expected not empty, we decode the
+        # body. Otherwise we returns the body as it is.
+        if not expect_empty_body:
+            body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/network/networks_client.py b/tempest/lib/services/network/networks_client.py
index 7d75bf7..6b601ee 100755
--- a/tempest/lib/services/network/networks_client.py
+++ b/tempest/lib/services/network/networks_client.py
@@ -19,7 +19,7 @@
         """Creates a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#createNetwork
+                              api-ref/networking/v2/index.html#create-network
         """
         uri = '/networks'
         post_data = {'network': kwargs}
@@ -29,7 +29,7 @@
         """Updates a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#updateNetwork
+                              api-ref/networking/v2/index.html#update-network
         """
         uri = '/networks/%s' % network_id
         post_data = {'network': kwargs}
@@ -39,7 +39,7 @@
         """Shows details for a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#showNetwork
+                              api-ref/networking/v2/index.html#show-network-details
         """
         uri = '/networks/%s' % network_id
         return self.show_resource(uri, **fields)
@@ -52,7 +52,7 @@
         """Lists networks to which the tenant has access.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#listNetworks
+                              api-ref/networking/v2/index.html#list-networks
         """
         uri = '/networks'
         return self.list_resources(uri, **filters)
@@ -61,7 +61,7 @@
         """Create multiple networks in a single request.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#bulkCreateNetwork
+                              api-ref/networking/v2/index.html#bulk-create-networks
         """
         uri = '/networks'
         return self.create_resource(uri, kwargs)
diff --git a/tempest/services/volume/v1/json/admin/hosts_client.py b/tempest/lib/services/volume/v1/hosts_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/admin/hosts_client.py
rename to tempest/lib/services/volume/v1/hosts_client.py
diff --git a/tempest/services/volume/v1/json/admin/services_client.py b/tempest/lib/services/volume/v1/services_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/admin/services_client.py
rename to tempest/lib/services/volume/v1/services_client.py
diff --git a/tempest/services/volume/v2/json/admin/hosts_client.py b/tempest/lib/services/volume/v2/hosts_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/admin/hosts_client.py
rename to tempest/lib/services/volume/v2/hosts_client.py
diff --git a/tempest/services/volume/v2/json/admin/services_client.py b/tempest/lib/services/volume/v2/services_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/admin/services_client.py
rename to tempest/lib/services/volume/v2/services_client.py
diff --git a/tempest/manager.py b/tempest/manager.py
index dd16042..e3174d4 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -58,5 +58,5 @@
            "as such it should not imported directly. It will be removed as "
            "the client manager becomes available in tempest.lib.")
     LOG.warning(msg)
-    return clients.get_auth_provider(credentials=credentials,
-                                     pre_auth=pre_auth, scope=scope)
+    return tempest_clients.get_auth_provider(credentials=credentials,
+                                             pre_auth=pre_auth, scope=scope)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 9c48080..e0e1204 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -24,6 +24,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
 
@@ -410,6 +411,7 @@
     @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
     @testtools.skipIf(CONF.baremetal.driver_enabled,
                       'Baremetal relies on a shared physical network.')
+    @decorators.skip_because(bug="1610994")
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
         """Test connectivity between VMs on different networks
diff --git a/tempest/services/volume/v1/__init__.py b/tempest/services/volume/v1/__init__.py
index c56d42c..52d2942 100644
--- a/tempest/services/volume/v1/__init__.py
+++ b/tempest/services/volume/v1/__init__.py
@@ -15,10 +15,9 @@
 from tempest.lib.services.volume.v1.availability_zone_client import \
     AvailabilityZoneClient
 from tempest.lib.services.volume.v1.extensions_client import ExtensionsClient
-from tempest.services.volume.v1.json.admin.hosts_client import HostsClient
+from tempest.lib.services.volume.v1.hosts_client import HostsClient
+from tempest.lib.services.volume.v1.services_client import ServicesClient
 from tempest.services.volume.v1.json.admin.quotas_client import QuotasClient
-from tempest.services.volume.v1.json.admin.services_client import \
-    ServicesClient
 from tempest.services.volume.v1.json.admin.types_client import TypesClient
 from tempest.services.volume.v1.json.backups_client import BackupsClient
 from tempest.services.volume.v1.json.qos_client import QosSpecsClient
diff --git a/tempest/services/volume/v2/__init__.py b/tempest/services/volume/v2/__init__.py
index df6bd3e..26fbc2b 100644
--- a/tempest/services/volume/v2/__init__.py
+++ b/tempest/services/volume/v2/__init__.py
@@ -15,10 +15,9 @@
 from tempest.lib.services.volume.v2.availability_zone_client import \
     AvailabilityZoneClient
 from tempest.lib.services.volume.v2.extensions_client import ExtensionsClient
-from tempest.services.volume.v2.json.admin.hosts_client import HostsClient
+from tempest.lib.services.volume.v2.hosts_client import HostsClient
+from tempest.lib.services.volume.v2.services_client import ServicesClient
 from tempest.services.volume.v2.json.admin.quotas_client import QuotasClient
-from tempest.services.volume.v2.json.admin.services_client import \
-    ServicesClient
 from tempest.services.volume.v2.json.admin.types_client import TypesClient
 from tempest.services.volume.v2.json.backups_client import BackupsClient
 from tempest.services.volume.v2.json.qos_client import QosSpecsClient