Merge "Add device_owner to gateway port search criteria"
diff --git a/.zuul.yaml b/.zuul.yaml
index 9af79a6..93d1db5 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -1,7 +1,6 @@
 - job:
     name: devstack-tempest
     parent: devstack
-    nodeset: openstack-single-node
     description: |
       Base Tempest job.
 
@@ -53,7 +52,6 @@
 - job:
     name: devstack-tempest-ipv6
     parent: devstack-ipv6
-    nodeset: openstack-single-node
     description: |
       Base Tempest IPv6 job.
     required-projects:
@@ -196,7 +194,7 @@
 - job:
     name: tempest-multinode-full
     parent: devstack-tempest
-    nodeset: openstack-two-node
+    nodeset: openstack-two-node-bionic
     # Until the devstack changes are backported, only run this on master
     branches:
       - master
@@ -234,16 +232,6 @@
         nodes:
           - controller
 
-- job:
-    name: tempest-full-py36
-    parent: tempest-full-py3
-    nodeset: openstack-bionic-node
-    branches:
-      - master
-    description: |
-      Base integration test with Neutron networking and py36.
-    voting: false
-
 - nodeset:
     name: openstack-opensuse150-node
     nodes:
@@ -286,26 +274,31 @@
 - job:
     name: tempest-full-rocky
     parent: tempest-full
+    nodeset: openstack-single-node-xenial
     override-checkout: stable/rocky
 
 - job:
     name: tempest-full-rocky-py3
     parent: tempest-full-py3
+    nodeset: openstack-single-node-xenial
     override-checkout: stable/rocky
 
 - job:
     name: tempest-full-queens
     parent: tempest-full
+    nodeset: openstack-single-node-xenial
     override-checkout: stable/queens
 
 - job:
     name: tempest-full-queens-py3
     parent: tempest-full-py3
+    nodeset: openstack-single-node-xenial
     override-checkout: stable/queens
 
 - job:
     name: tempest-full-pike
     parent: tempest-full
+    nodeset: openstack-single-node-xenial
     override-checkout: stable/pike
 
 - job:
@@ -492,8 +485,6 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-full-py3:
             irrelevant-files: *tempest-irrelevant-files
-        - tempest-full-py36:
-            irrelevant-files: *tempest-irrelevant-files
         - tempest-full-py3-ipv6:
             voting: false
             irrelevant-files: *tempest-irrelevant-files
@@ -522,8 +513,6 @@
               # tools/ is not here since this relies on a script in tools/.
         - tempest-slow:
             irrelevant-files: *tempest-irrelevant-files
-        - nova-cells-v1:
-            irrelevant-files: *tempest-irrelevant-files
         - nova-live-migration:
             voting: false
             irrelevant-files: *tempest-irrelevant-files
@@ -531,6 +520,8 @@
             irrelevant-files: *tempest-irrelevant-files
         - neutron-grenade:
             irrelevant-files: *tempest-irrelevant-files
+        - grenade-py3:
+            irrelevant-files: *tempest-irrelevant-files
         - devstack-plugin-ceph-tempest:
             voting: false
             irrelevant-files: *tempest-irrelevant-files
@@ -573,6 +564,8 @@
             irrelevant-files: *tempest-irrelevant-files
         - neutron-grenade:
             irrelevant-files: *tempest-irrelevant-files
+        - grenade-py3:
+            irrelevant-files: *tempest-irrelevant-files
     experimental:
       jobs:
         - tempest-cinder-v2-api:
@@ -583,6 +576,8 @@
             irrelevant-files: *tempest-irrelevant-files
         - neutron-tempest-dvr-ha-multinode-full:
             irrelevant-files: *tempest-irrelevant-files
+        - nova-cells-v1:
+            irrelevant-files: *tempest-irrelevant-files
         - legacy-tempest-dsvm-nova-v20-api:
             irrelevant-files: *tempest-irrelevant-files
         - legacy-tempest-dsvm-lvm-multibackend:
diff --git a/tempest/README.rst b/tempest/README.rst
index a5f4a92..b345032 100644
--- a/tempest/README.rst
+++ b/tempest/README.rst
@@ -9,7 +9,7 @@
 OpenStack clouds.
 
 As such Tempest tests come in many flavors, each with their own rules
-and guidelines. Below is the overview of the Tempest respository structure
+and guidelines. Below is the overview of the Tempest repository structure
 to make this clear.
 
 .. code-block:: console
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index 302a0e5..a79cbc3 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -9,6 +9,8 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import testtools
+
 from tempest.api.identity import base
 from tempest import clients
 from tempest import config
@@ -32,6 +34,10 @@
         self.domains_client.update_domain(domain_id, enabled=False)
         self.domains_client.delete_domain(domain_id)
 
+    @testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source,
+                      'Skipped because environment has an '
+                      'immutable user source and solely '
+                      'provides read-only access to users.')
     @decorators.idempotent_id('d6110661-6a71-49a7-a453-b5e26640ff6d')
     def test_default_project_id(self):
         # create a domain
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index 30ed176..eaf477c 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -48,11 +48,6 @@
             agent.pop('configurations', None)
         self.assertIn(self.agent, agents)
 
-    @decorators.idempotent_id('e335be47-b9a1-46fd-be30-0874c0b751e6')
-    def test_list_agents_non_admin(self):
-        body = self.agents_client.list_agents()
-        self.assertEmpty(body["agents"])
-
     @decorators.idempotent_id('869bc8e8-0fda-4a30-9b71-f8a7cf58ca9f')
     def test_show_agent(self):
         body = self.admin_agents_client.show_agent(self.agent['id'])
@@ -95,4 +90,4 @@
         non_existent_id = data_utils.rand_uuid()
         self.assertRaises(
             lib_exc.NotFound,
-            self.agents_client.delete_agent, non_existent_id)
+            self.admin_agents_client.delete_agent, non_existent_id)
diff --git a/tempest/api/network/test_agent_management_negative.py b/tempest/api/network/test_agent_management_negative.py
new file mode 100644
index 0000000..d1c02ce
--- /dev/null
+++ b/tempest/api/network/test_agent_management_negative.py
@@ -0,0 +1,28 @@
+# Copyright 2018 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.network import base
+from tempest.lib import decorators
+
+
+class AgentManagementNegativeTest(base.BaseNetworkTest):
+
+    @decorators.idempotent_id('e335be47-b9a1-46fd-be30-0874c0b751e6')
+    @decorators.attr(type=['negative'])
+    def test_list_agents_non_admin(self):
+        """Validate that non-admin user cannot list agents."""
+        # Listing agents requires admin_only permissions.
+        body = self.agents_client.list_agents()
+        self.assertEmpty(body["agents"])
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 915aeec..5c7ab15 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -45,13 +45,6 @@
         cls.addClassResourceCleanup(cls.admin_quotas_client.update_quota_set,
                                     cls.demo_tenant_id, **cleanup_quota_set)
 
-        cls.shared_quota_set = {'gigabytes': 2 * CONF.volume.volume_size,
-                                'volumes': 1}
-
-        cls.admin_quotas_client.update_quota_set(
-            cls.demo_tenant_id,
-            **cls.shared_quota_set)
-
         # NOTE(gfidente): no need to delete in tearDown as
         # they are created using utility wrapper methods.
         cls.volume = cls.create_volume()
@@ -59,6 +52,8 @@
     @decorators.attr(type='negative')
     @decorators.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
     def test_quota_volumes(self):
+        self.admin_quotas_client.update_quota_set(self.demo_tenant_id,
+                                                  volumes=1, gigabytes=-1)
         self.assertRaises(lib_exc.OverLimit,
                           self.volumes_client.create_volume,
                           size=CONF.volume.volume_size)
@@ -66,17 +61,18 @@
     @decorators.attr(type='negative')
     @decorators.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
     def test_quota_volume_gigabytes(self):
-        # NOTE(gfidente): quota set needs to be changed for this test
-        # or we may be limited by the volumes or snaps quota number, not by
-        # actual gigs usage; next line ensures shared set is restored.
-        self.addCleanup(self.admin_quotas_client.update_quota_set,
-                        self.demo_tenant_id,
-                        **self.shared_quota_set)
-        new_quota_set = {'gigabytes': CONF.volume.volume_size,
-                         'volumes': 2, 'snapshots': 1}
         self.admin_quotas_client.update_quota_set(
-            self.demo_tenant_id,
-            **new_quota_set)
+            self.demo_tenant_id, gigabytes=CONF.volume.volume_size, volumes=-1)
         self.assertRaises(lib_exc.OverLimit,
                           self.volumes_client.create_volume,
-                          size=CONF.volume.volume_size)
+                          size=CONF.volume.volume_size * 2)
+
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('d321dc21-d8c6-401f-95fe-49f4845f1a6d')
+    def test_volume_extend_gigabytes_quota_deviation(self):
+        self.admin_quotas_client.update_quota_set(
+            self.demo_tenant_id, gigabytes=CONF.volume.volume_size)
+        self.assertRaises(lib_exc.OverLimit,
+                          self.volumes_client.extend_volume,
+                          self.volume['id'],
+                          new_size=CONF.volume.volume_size * 2)
diff --git a/tox.ini b/tox.ini
index 4d3c622..4068054 100644
--- a/tox.ini
+++ b/tox.ini
@@ -48,6 +48,10 @@
   coverage xml -o cover/coverage.xml
   coverage report
 
+[testenv:debug]
+basepython = python3
+commands = oslo_debug_helper -t tempest/tests {posargs}
+
 [testenv:all]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}