Merge "Introduce bashate"
diff --git a/.zuul.yaml b/.zuul.yaml
index fad4ed0..8fd2594 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -7,12 +7,12 @@
       This Tempest job provides the base for both the single and multi-node
       test setup. To run a multi-node test inherit from devstack-tempest and
       set the nodeset to a multi-node one.
-    required-projects:
+    required-projects: &base_required-projects
       - opendev.org/openstack/tempest
     timeout: 7200
-    roles:
+    roles: &base_roles
       - zuul: opendev.org/openstack/devstack
-    vars:
+    vars: &base_vars
       devstack_services:
         tempest: true
       devstack_local_conf:
@@ -53,37 +53,37 @@
     name: devstack-tempest-ipv6
     parent: devstack-ipv6
     description: |
-      Base Tempest IPv6 job.
-    required-projects:
-      - opendev.org/openstack/tempest
+      Base Tempest IPv6 job. This job is derived from 'devstack-ipv6'
+      which set the IPv6-only setting for OpenStack services. As part of
+      run phase, this job will verify the IPv6 setting and check the services
+      endpoints and listen addresses are IPv6. Basically it will run the script
+      ./tool/verify-ipv6-only-deployments.sh
+
+      Child jobs of this job can run their own set of tests and can
+      add post-run playebooks to extend the IPv6 verification specific
+      to their deployed services.
+      Check the wiki page for more details about project jobs setup
+      - https://wiki.openstack.org/wiki/Goal-IPv6-only-deployments-and-testing
+    required-projects: *base_required-projects
     timeout: 7200
-    roles:
-      - zuul: opendev.org/openstack/devstack
-    vars:
-      devstack_services:
-        tempest: true
-      devstack_local_conf:
-        test-config:
-          $TEMPEST_CONFIG:
-            compute:
-              min_compute_nodes: "{{ groups['compute'] | default(['controller']) | length }}"
-      test_results_stage_name: test_results
-      zuul_copy_output:
-        '{{ devstack_base_dir }}/tempest/etc/tempest.conf': logs
-        '{{ devstack_base_dir }}/tempest/etc/accounts.yaml': logs
-        '{{ devstack_base_dir }}/tempest/tempest.log': logs
-        '{{ stage_dir }}/{{ test_results_stage_name }}.subunit': logs
-        '{{ stage_dir }}/{{ test_results_stage_name }}.html': logs
-        '{{ stage_dir }}/stackviz': logs
-      extensions_to_txt:
-        conf: true
-        log: true
-        yaml: true
-        yml: true
-    run: playbooks/devstack-tempest.yaml
+    roles: *base_roles
+    vars: *base_vars
+    run: playbooks/devstack-tempest-ipv6.yaml
     post-run: playbooks/post-tempest.yaml
 
 - job:
+    name: tempest-ipv6-only
+    parent: devstack-tempest-ipv6
+    # This currently works from stable/pike on.
+    branches: ^(?!stable/ocata).*$
+    description: |
+      Integration test of IPv6-only deployments. This job runs
+      smoke and IPv6 relates tests only. Basic idea is to test
+      whether OpenStack Services listen on IPv6 addrress or not.
+    vars:
+      tox_envlist: ipv6-only
+
+- job:
     name: tempest-full
     parent: devstack-tempest
     # This currently works from stable/pike on.
@@ -454,13 +454,6 @@
       tox_envlist: plugin-sanity-check
     voting: false
     timeout: 5000
-    irrelevant-files:
-      - ^.*\.rst$
-      - ^doc/.*$
-      - ^etc/.*$
-      - ^releasenotes/.*$
-      - ^tempest/hacking/.*$
-      - ^tempest/tests/.*$
     required-projects:
       - opendev.org/airship/tempest-plugin
       - opendev.org/x/almanach
@@ -729,7 +722,7 @@
         - tempest-multinode-full-py3:
             irrelevant-files: *tempest-irrelevant-files
         - tempest-tox-plugin-sanity-check:
-            irrelevant-files:
+            irrelevant-files: &tempest-irrelevant-files-2
               - ^.*\.rst$
               - ^doc/.*$
               - ^etc/.*$
@@ -738,6 +731,8 @@
               - ^tempest/hacking/.*$
               - ^tempest/tests/.*$
               # tools/ is not here since this relies on a script in tools/.
+        - tempest-ipv6-only:
+            irrelevant-files: *tempest-irrelevant-files-2
         - tempest-slow:
             irrelevant-files: *tempest-irrelevant-files
         - tempest-slow-py3:
@@ -791,6 +786,8 @@
             irrelevant-files: *tempest-irrelevant-files
         - grenade-py3:
             irrelevant-files: *tempest-irrelevant-files
+        - tempest-ipv6-only:
+            irrelevant-files: *tempest-irrelevant-files-2
     experimental:
       jobs:
         - tempest-cinder-v2-api:
diff --git a/playbooks/devstack-tempest-ipv6.yaml b/playbooks/devstack-tempest-ipv6.yaml
new file mode 100644
index 0000000..5f72345
--- /dev/null
+++ b/playbooks/devstack-tempest-ipv6.yaml
@@ -0,0 +1,24 @@
+# Changes that run through devstack-tempest-ipv6 are likely to have an impact on
+# the devstack part of the job, so we keep devstack in the main play to
+# avoid zuul retrying on legitimate failures.
+- hosts: all
+  roles:
+    - orchestrate-devstack
+
+# We run tests only on one node, regardless how many nodes are in the system
+- hosts: tempest
+  environment:
+    # This enviroment variable is used by the optional tempest-gabbi
+    # job provided by the gabbi-tempest plugin. It can be safely ignored
+    # if that plugin is not being used.
+    GABBI_TEMPEST_PATH: "{{ gabbi_tempest_path | default('') }}"
+  roles:
+    - setup-tempest-run-dir
+    - setup-tempest-data-dir
+    - acl-devstack-files
+    # Verify the IPv6-only deployments. This role will perform check for
+    # IPv6 only env for example Devstack IPv6 settings and services listen
+    # address is IPv6 etc. This is invoked before tests are run so that we can
+    # fail early if anything missing the IPv6 settings or deployments.
+    - ipv6-only-deployments-verification
+    - run-tempest
diff --git a/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml b/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
index 092014e..8787e0c 100644
--- a/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
+++ b/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
@@ -4,5 +4,5 @@
     Adds subunit-describe-calls. A parser for subunit streams to determine what
     REST API calls are made inside of a test and in what order they are called.
 
-      * Input can be piped in or a file can be specified
-      * Output is shortened for stdout, the output file has more information
+    * Input can be piped in or a file can be specified
+    * Output is shortened for stdout, the output file has more information
diff --git a/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml b/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
index f9173a0..b857db8 100644
--- a/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
+++ b/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
@@ -6,8 +6,8 @@
     so the other projects can use these modules as stable libraries without
     any maintenance changes.
 
-      * endpoints_client(v2)
-      * roles_client(v2)
-      * services_client(v2)
-      * tenants_client(v2)
-      * users_client(v2)
+    * endpoints_client(v2)
+    * roles_client(v2)
+    * services_client(v2)
+    * tenants_client(v2)
+    * users_client(v2)
diff --git a/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml b/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
index 1fa4ddd..492aac8 100644
--- a/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
+++ b/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
@@ -6,10 +6,10 @@
     so the other projects can use these modules as stable libraries
     without any maintenance changes.
 
-      * image_members_client(v1)
-      * images_client(v1)
-      * image_members_client(v2)
-      * images_client(v2)
-      * namespaces_client(v2)
-      * resource_types_client(v2)
-      * schemas_client(v2)
+    * image_members_client(v1)
+    * images_client(v1)
+    * image_members_client(v2)
+    * images_client(v2)
+    * namespaces_client(v2)
+    * resource_types_client(v2)
+    * schemas_client(v2)
diff --git a/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml b/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
index 3ec8b56..6e08743 100644
--- a/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
+++ b/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
@@ -6,8 +6,8 @@
     so the other projects can use these modules as stable libraries without
     any maintenance changes.
 
-     * endpoints_client(v3)
-     * policies_client (v3)
-     * regions_client(v3)
-     * services_client(v3)
-     * projects_client(v3)
+    * endpoints_client(v3)
+    * policies_client (v3)
+    * regions_client(v3)
+    * services_client(v3)
+    * projects_client(v3)
diff --git a/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml b/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
index cf504ad..32cd182 100644
--- a/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
+++ b/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
@@ -6,13 +6,13 @@
     so the other projects can use these modules as stable libraries
     without any maintenance changes.
 
-      * availability_zone_client(v1)
-      * availability_zone_client(v2)
-      * extensions_client(v1)
-      * extensions_client(v2)
-      * hosts_client(v1)
-      * hosts_client(v2)
-      * quotas_client(v1)
-      * quotas_client(v2)
-      * services_client(v1)
-      * services_client(v2)
+    * availability_zone_client(v1)
+    * availability_zone_client(v2)
+    * extensions_client(v1)
+    * extensions_client(v2)
+    * hosts_client(v1)
+    * hosts_client(v2)
+    * quotas_client(v1)
+    * quotas_client(v2)
+    * services_client(v1)
+    * services_client(v2)
diff --git a/releasenotes/notes/13/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml b/releasenotes/notes/13/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
index 9e828f6..a0de2c3 100644
--- a/releasenotes/notes/13/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
+++ b/releasenotes/notes/13/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
@@ -5,11 +5,11 @@
     Add new service clients to the library interface so the other projects can use these modules as stable libraries without
     any maintenance changes.
 
-      * identity_client(v2)
-      * groups_client(v3)
-      * trusts_client(v3)
-      * users_client(v3)
-      * identity_client(v3)
-      * roles_client(v3)
-      * inherited_roles_client(v3)
-      * credentials_client(v3)
+    * identity_client(v2)
+    * groups_client(v3)
+    * trusts_client(v3)
+    * users_client(v3)
+    * identity_client(v3)
+    * roles_client(v3)
+    * inherited_roles_client(v3)
+    * credentials_client(v3)
diff --git a/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml b/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml
index 7e40fd4..6346156 100644
--- a/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml
+++ b/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml
@@ -5,5 +5,5 @@
     http://developer.openstack.org/api-ref/image/v2/metadefs-index.html,
     there are some apis are not included, add them.
 
-      * namespace_properties_client(v2)
+    * namespace_properties_client(v2)
 
diff --git a/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml b/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
index eaab1f0..a4e5791 100644
--- a/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
+++ b/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
@@ -5,6 +5,6 @@
     http://developer.openstack.org/api-ref/image/v2/metadefs-index.html,
     there are some apis are not included, add them.
 
-      * namespace_objects_client(v2)
-      * namespace_tags_client(v2)
+    * namespace_objects_client(v2)
+    * namespace_tags_client(v2)
 
diff --git a/releasenotes/notes/add-domain-param-in-cliclient-a270fcf35c8f09e6.yaml b/releasenotes/notes/add-domain-param-in-cliclient-a270fcf35c8f09e6.yaml
index 87a6af9..85e5f5f 100644
--- a/releasenotes/notes/add-domain-param-in-cliclient-a270fcf35c8f09e6.yaml
+++ b/releasenotes/notes/add-domain-param-in-cliclient-a270fcf35c8f09e6.yaml
@@ -3,10 +3,10 @@
   - |
     Allow to specify new domain parameters:
 
-    * `user_domain_name`
-    * `user_domain_id`
-    * `project_domain_name`
-    * `project_domain_id`
+    * ``user_domain_name``
+    * ``user_domain_id``
+    * ``project_domain_name``
+    * ``project_domain_id``
 
     for CLIClient class, whose values will be substituted to
     ``--os-user-domain-name``, ``--os-user-domain-id``,
diff --git a/releasenotes/notes/intermediate-train-release-0146c624cff9a57f.yaml b/releasenotes/notes/intermediate-train-release-0146c624cff9a57f.yaml
index 6977e12..7940846 100644
--- a/releasenotes/notes/intermediate-train-release-0146c624cff9a57f.yaml
+++ b/releasenotes/notes/intermediate-train-release-0146c624cff9a57f.yaml
@@ -1,12 +1,12 @@
 ---
-prelude: >
+prelude: |
     This is an intermediate release during the Train development cycle to
     mark the end of support for Pike in Tempest.
     After this release, Tempest will support below OpenStack Releases:
 
-      * Stein
-      * Rocky
-      * Queens
+    * Stein
+    * Rocky
+    * Queens
 
     Current development of Tempest is for OpenStack Train development
     cycle.
diff --git a/releasenotes/notes/make-object-storage-client-as-stable-interface-d1b07c7e8f17bef6.yaml b/releasenotes/notes/make-object-storage-client-as-stable-interface-d1b07c7e8f17bef6.yaml
index 2bba952..37eeec5 100644
--- a/releasenotes/notes/make-object-storage-client-as-stable-interface-d1b07c7e8f17bef6.yaml
+++ b/releasenotes/notes/make-object-storage-client-as-stable-interface-d1b07c7e8f17bef6.yaml
@@ -6,6 +6,6 @@
     other projects can use these modules as stable libraries
     without any maintenance changes.
 
-      * account_client
-      * container_client
-      * object_client
+    * account_client
+    * container_client
+    * object_client
diff --git a/releasenotes/notes/migrate-object-storage-as-stable-interface-42014c7b43ecb254.yaml b/releasenotes/notes/migrate-object-storage-as-stable-interface-42014c7b43ecb254.yaml
index 72b8e26..00829b9 100644
--- a/releasenotes/notes/migrate-object-storage-as-stable-interface-42014c7b43ecb254.yaml
+++ b/releasenotes/notes/migrate-object-storage-as-stable-interface-42014c7b43ecb254.yaml
@@ -6,5 +6,5 @@
     other projects can use these modules as stable libraries
     without any maintenance changes.
 
-      * bulk_middleware_client
-      * capabilities_client
+    * bulk_middleware_client
+    * capabilities_client
diff --git a/releasenotes/notes/segments-client-866f02948f40d4ff.yaml b/releasenotes/notes/segments-client-866f02948f40d4ff.yaml
new file mode 100644
index 0000000..90ac3e8
--- /dev/null
+++ b/releasenotes/notes/segments-client-866f02948f40d4ff.yaml
@@ -0,0 +1,12 @@
+---
+features:
+  - |
+    Add ``segments`` client to Tempest to make possible the testing of the
+    Routed Provider Networks feature.
+    The following API calls are available for tempest from now:
+
+    * POST /segments
+    * PUT /segments/{segment_id}
+    * GET /segment/{segment_id}
+    * DELETE /segments/{segment_id}
+    * GET /segments
diff --git a/releasenotes/notes/tempest-rocky-release-0fc3312053923380.yaml b/releasenotes/notes/tempest-rocky-release-0fc3312053923380.yaml
index e9c77a6..8406be6 100644
--- a/releasenotes/notes/tempest-rocky-release-0fc3312053923380.yaml
+++ b/releasenotes/notes/tempest-rocky-release-0fc3312053923380.yaml
@@ -1,12 +1,12 @@
 ---
-prelude: >
+prelude: |
     This release is to tag the Tempest for OpenStack Rocky release.
     After this release, Tempest will support below OpenStack Releases:
 
-      * Rocky
-      * Queens
-      * Pike
-      * Ocata
+    * Rocky
+    * Queens
+    * Pike
+    * Ocata
 
     Current development of Tempest is for OpenStack Stein development
     cycle. Every Tempest commit is also tested against master during
diff --git a/releasenotes/notes/tempest-stein-release-18bad34136a2e6ef.yaml b/releasenotes/notes/tempest-stein-release-18bad34136a2e6ef.yaml
index 212cf7d..c3537fc 100644
--- a/releasenotes/notes/tempest-stein-release-18bad34136a2e6ef.yaml
+++ b/releasenotes/notes/tempest-stein-release-18bad34136a2e6ef.yaml
@@ -1,14 +1,14 @@
 ---
-prelude: >
+prelude: |
     This release is to tag the Tempest for OpenStack Stein release.
     This release marks the start of Stein release support in Tempest and
     the end of support for Ocata in Tempest.
     After this release, Tempest will support below OpenStack Releases:
 
-      * Stein
-      * Rocky
-      * Queens
-      * Pike
+    * Stein
+    * Rocky
+    * Queens
+    * Pike
 
     Current development of Tempest is for OpenStack Train development
     cycle. Every Tempest commit is also tested against master during
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index e5d5bfe..1d0d914 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
    :maxdepth: 1
 
    unreleased
+   v21.0.0
    v20.0.0
    v19.0.0
    v18.0.0
diff --git a/releasenotes/source/v21.0.0.rst b/releasenotes/source/v21.0.0.rst
new file mode 100644
index 0000000..9ea8120
--- /dev/null
+++ b/releasenotes/source/v21.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v21.0.0 Release Notes
+=====================
+
+.. release-notes:: 21.0.0 Release Notes
+   :version: 21.0.0
diff --git a/roles/ipv6-only-deployments-verification/README.rst b/roles/ipv6-only-deployments-verification/README.rst
new file mode 100644
index 0000000..400a8da
--- /dev/null
+++ b/roles/ipv6-only-deployments-verification/README.rst
@@ -0,0 +1,16 @@
+Verify the IPv6-only deployments
+
+This role needs to be invoked from a playbook that
+run tests. This role verifies the IPv6 setting on
+devstack side and devstack deploy services on IPv6.
+This role is invoked before tests are run so that
+if any missing IPv6 setting or deployments can fail
+the job early.
+
+
+**Role Variables**
+
+.. zuul:rolevar:: devstack_base_dir
+   :default: /opt/stack
+
+   The devstack base directory.
diff --git a/roles/ipv6-only-deployments-verification/defaults/main.yaml b/roles/ipv6-only-deployments-verification/defaults/main.yaml
new file mode 100644
index 0000000..fea05c8
--- /dev/null
+++ b/roles/ipv6-only-deployments-verification/defaults/main.yaml
@@ -0,0 +1 @@
+devstack_base_dir: /opt/stack
diff --git a/roles/ipv6-only-deployments-verification/tasks/main.yaml b/roles/ipv6-only-deployments-verification/tasks/main.yaml
new file mode 100644
index 0000000..d73c79c
--- /dev/null
+++ b/roles/ipv6-only-deployments-verification/tasks/main.yaml
@@ -0,0 +1,4 @@
+- name: Verify the ipv6-only deployments
+  become: true
+  become_user: stack
+  shell: "{{ devstack_base_dir }}/tempest/tools/verify-ipv6-only-deployments.sh"
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index c69e4c8..5aec931 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -34,6 +34,14 @@
                          map(lambda x: x[key], body))
 
     @classmethod
+    def skip_checks(cls):
+        super(UsersV3TestJSON, cls).skip_checks()
+        if CONF.identity_feature_enabled.immutable_user_source:
+            raise cls.skipException('Skipped because environment has an '
+                                    'immutable user source and solely '
+                                    'provides read-only access to users.')
+
+    @classmethod
     def resource_setup(cls):
         super(UsersV3TestJSON, cls).resource_setup()
         alt_user = data_utils.rand_name('test_user')
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 54a5ab7..78e3cce 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -33,6 +33,10 @@
         super(TrustsV3TestJSON, cls).skip_checks()
         if not CONF.identity_feature_enabled.trust:
             raise cls.skipException("Trusts aren't enabled")
+        if CONF.identity_feature_enabled.immutable_user_source:
+            raise cls.skipException('Skipped because environment has an '
+                                    'immutable user source and solely '
+                                    'provides read-only access to users.')
 
     def setUp(self):
         super(TrustsV3TestJSON, self).setUp()
diff --git a/tempest/clients.py b/tempest/clients.py
index f7a83be..6aed92e 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -71,6 +71,7 @@
         self.tags_client = self.network.TagsClient()
         self.qos_client = self.network.QosClient()
         self.qos_min_bw_client = self.network.QosMinimumBandwidthRulesClient()
+        self.segments_client = self.network.SegmentsClient()
 
     def _set_image_clients(self):
         if CONF.service_available.glance:
diff --git a/tempest/lib/services/network/__init__.py b/tempest/lib/services/network/__init__.py
index 69f178e..f7ac046 100644
--- a/tempest/lib/services/network/__init__.py
+++ b/tempest/lib/services/network/__init__.py
@@ -30,6 +30,7 @@
     SecurityGroupRulesClient
 from tempest.lib.services.network.security_groups_client import \
     SecurityGroupsClient
+from tempest.lib.services.network.segments_client import SegmentsClient
 from tempest.lib.services.network.service_providers_client import \
     ServiceProvidersClient
 from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
@@ -42,5 +43,5 @@
            'NetworksClient', 'NetworkVersionsClient', 'PortsClient',
            'QosClient', 'QosMinimumBandwidthRulesClient', 'QuotasClient',
            'RoutersClient', 'SecurityGroupRulesClient', 'SecurityGroupsClient',
-           'ServiceProvidersClient', 'SubnetpoolsClient', 'SubnetsClient',
-           'TagsClient']
+           'SegmentsClient', 'ServiceProvidersClient', 'SubnetpoolsClient',
+           'SubnetsClient', 'TagsClient']
diff --git a/tempest/lib/services/network/segments_client.py b/tempest/lib/services/network/segments_client.py
new file mode 100644
index 0000000..dfdc418
--- /dev/null
+++ b/tempest/lib/services/network/segments_client.py
@@ -0,0 +1,63 @@
+#    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.lib.services.network import base
+
+
+class SegmentsClient(base.BaseNetworkClient):
+
+    def create_segment(self, **kwargs):
+        """Creates a segment.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/networking/v2/index.html#create-segment
+        """
+        uri = '/segments'
+        post_data = {'segment': kwargs}
+        return self.create_resource(uri, post_data)
+
+    def update_segment(self, segment_id, **kwargs):
+        """Updates a segment.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/networking/v2/index.html#update-segment
+        """
+        uri = '/segments/%s' % segment_id
+        post_data = {'segment': kwargs}
+        return self.update_resource(uri, post_data)
+
+    def show_segment(self, segment_id, **fields):
+        """Shows details of a segment.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/networking/v2/index.html#show-segment
+        """
+        uri = '/segments/%s' % segment_id
+        return self.show_resource(uri, **fields)
+
+    def delete_segment(self, segment_id):
+        """Deletes a segment"""
+        uri = '/segments/%s' % segment_id
+        return self.delete_resource(uri)
+
+    def list_segments(self, **filters):
+        """Lists segments.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/networking/v2/index.html#list-segments
+        """
+        uri = '/segments'
+        return self.list_resources(uri, **filters)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 2782119..af79ea0 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -70,7 +70,6 @@
             raise lib_exc.TimeoutException
 
     @decorators.attr(type='slow')
-    @decorators.skip_because(bug="1664793")
     @decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
@@ -91,6 +90,11 @@
         # create and add floating IP to server1
         ip_for_server = self.get_server_ip(server)
 
+        # Make sure the machine ssh-able before attaching the volume
+        self.get_remote_client(ip_for_server,
+                               private_key=keypair['private_key'],
+                               server=server)
+
         self.nova_volume_attach(server, volume)
         self._wait_for_volume_available_on_the_system(ip_for_server,
                                                       keypair['private_key'])
@@ -119,6 +123,13 @@
         # create and add floating IP to server_from_snapshot
         ip_for_snapshot = self.get_server_ip(server_from_snapshot)
 
+        # Make sure the machine ssh-able before attaching the volume
+        # Just a live machine is responding
+        # for device attache/detach as expected
+        self.get_remote_client(ip_for_snapshot,
+                               private_key=keypair['private_key'],
+                               server=server_from_snapshot)
+
         # attach volume2 to instance2
         self.nova_volume_attach(server_from_snapshot, volume_from_snapshot)
         self._wait_for_volume_available_on_the_system(ip_for_snapshot,
diff --git a/tempest/tests/lib/services/network/test_segments_client.py b/tempest/tests/lib/services/network/test_segments_client.py
new file mode 100644
index 0000000..579c78f
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_segments_client.py
@@ -0,0 +1,140 @@
+#    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.
+
+import copy
+
+from tempest.lib.services.network import segments_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSegmentsClient(base.BaseServiceTest):
+
+    FAKE_SEGMENT_ID = '83a59912-a473-11e9-a012-af494c35c9c2'
+    FAKE_NETWORK_ID = '913ab0e4-a473-11e9-84a3-af1c16fc05de'
+
+    FAKE_SEGMENT_REQUEST = {
+        'segment': {
+            'network_id': FAKE_NETWORK_ID,
+            'segmentation_id': 2000,
+            'network_type': 'vlan',
+            'physical_network': 'segment-1'
+        }
+    }
+
+    FAKE_SEGMENT_RESPONSE = {
+        'segment': {
+            'name': 'foo',
+            'network_id': FAKE_NETWORK_ID,
+            'segmentation_id': 2000,
+            'network_type': 'vlan',
+            'physical_network': 'segment-1',
+            'revision_number': 1,
+            'id': FAKE_SEGMENT_ID,
+            'created_at': '2019-07-12T09:13:56Z',
+            'updated_at': '2019-07-12T09:13:56Z',
+            'description': 'bar'
+        }
+    }
+
+    FAKE_SEGMENTS = {
+        'segments': [
+            FAKE_SEGMENT_RESPONSE['segment']
+        ]
+    }
+
+    def setUp(self):
+        super(TestSegmentsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.segments_client = segments_client.SegmentsClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def _test_create_segment(self, bytes_body=False):
+        self.check_service_client_function(
+            self.segments_client.create_segment,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_SEGMENT_RESPONSE,
+            bytes_body,
+            201,
+            **self.FAKE_SEGMENT_REQUEST['segment']
+        )
+
+    def _test_list_segments(self, bytes_body=False):
+        self.check_service_client_function(
+            self.segments_client.list_segments,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_SEGMENTS,
+            bytes_body,
+            200
+        )
+
+    def _test_show_segment(self, bytes_body=False):
+        self.check_service_client_function(
+            self.segments_client.show_segment,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_SEGMENT_RESPONSE,
+            bytes_body,
+            200,
+            segment_id=self.FAKE_SEGMENT_ID
+        )
+
+    def _test_update_segment(self, bytes_body=False):
+        update_kwargs = {
+            'name': 'notfoo'
+        }
+
+        resp_body = {
+            'segment': copy.deepcopy(self.FAKE_SEGMENT_RESPONSE['segment'])
+        }
+        resp_body['segment'].update(update_kwargs)
+
+        self.check_service_client_function(
+            self.segments_client.update_segment,
+            'tempest.lib.common.rest_client.RestClient.put',
+            resp_body,
+            bytes_body,
+            200,
+            segment_id=self.FAKE_SEGMENT_ID,
+            **update_kwargs
+        )
+
+    def test_create_segment_with_str_body(self):
+        self._test_create_segment()
+
+    def test_create_segment_with_bytes_body(self):
+        self._test_create_segment(bytes_body=True)
+
+    def test_update_segment_with_str_body(self):
+        self._test_update_segment()
+
+    def test_update_segment_with_bytes_body(self):
+        self._test_update_segment(bytes_body=True)
+
+    def test_show_segment_with_str_body(self):
+        self._test_show_segment()
+
+    def test_show_segment_with_bytes_body(self):
+        self._test_show_segment(bytes_body=True)
+
+    def test_delete_segment(self):
+        self.check_service_client_function(
+            self.segments_client.delete_segment,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            status=204,
+            segment_id=self.FAKE_SEGMENT_ID)
+
+    def test_list_segment_with_str_body(self):
+        self._test_list_segments()
+
+    def test_list_segment_with_bytes_body(self):
+        self._test_list_segments(bytes_body=True)
diff --git a/tools/verify-ipv6-only-deployments.sh b/tools/verify-ipv6-only-deployments.sh
new file mode 100755
index 0000000..90807a3
--- /dev/null
+++ b/tools/verify-ipv6-only-deployments.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+#
+# NOTE(gmann): This script is used in 'devstack-tempest-ipv6' zuul job to verify that
+# services are deployed on IPv6 properly or not. This will capture if any devstck or devstack
+# plugins are missing the required setting to listen on IPv6 address. This is run as part of
+# run phase of zuul job and before test run. Child job of 'devstack-tempest-ipv6'
+# can expand the IPv6 verification specific to project by defining the new post-run script which
+# will run along with this base script.
+# If there are more common verification for IPv6 then we can always extent this script.
+
+# Keep track of the DevStack directory
+TOP_DIR=$(cd $(dirname "$0")/../../devstack && pwd)
+source $TOP_DIR/stackrc
+source $TOP_DIR/openrc admin admin
+
+function verify_devstack_ipv6_setting {
+    local _service_host=$(echo $SERVICE_HOST | tr -d [])
+    local _host_ipv6=$(echo $HOST_IPV6 | tr -d [])
+    local _service_listen_address=$(echo $SERVICE_LISTEN_ADDRESS | tr -d [])
+    local _service_local_host=$(echo $SERVICE_LOCAL_HOST | tr -d [])
+    if [[ "$SERVICE_IP_VERSION" != 6 ]]; then
+        echo $SERVICE_IP_VERSION "SERVICE_IP_VERSION is not set to 6 which is must for devstack to deploy services with IPv6 address."
+        exit 1
+    fi
+    is_service_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_host'"))')
+    if [[ "$is_service_host_ipv6" != "True" ]]; then
+        echo $SERVICE_HOST "SERVICE_HOST is not ipv6 which means devstack cannot deploy services on IPv6 address."
+        exit 1
+    fi
+    is_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_host_ipv6'"))')
+    if [[ "$is_host_ipv6" != "True" ]]; then
+        echo $HOST_IPV6 "HOST_IPV6 is not ipv6 which means devstack cannot deploy services on IPv6 address."
+        exit 1
+    fi
+    is_service_listen_address=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_listen_address'"))')
+    if [[ "$is_service_listen_address" != "True" ]]; then
+        echo $SERVICE_LISTEN_ADDRESS "SERVICE_LISTEN_ADDRESS is not ipv6 which means devstack cannot deploy services on IPv6 address."
+        exit 1
+    fi
+    is_service_local_host=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_local_host'"))')
+    if [[ "$is_service_local_host" != "True" ]]; then
+        echo $SERVICE_LOCAL_HOST "SERVICE_LOCAL_HOST is not ipv6 which means devstack cannot deploy services on IPv6 address."
+        exit 1
+    fi
+    echo "Devstack is properly configured with IPv6"
+    echo "SERVICE_IP_VERSION: " $SERVICE_IP_VERSION "HOST_IPV6: " $HOST_IPV6 "SERVICE_HOST: " $SERVICE_HOST "SERVICE_LISTEN_ADDRESS: " $SERVICE_LISTEN_ADDRESS "SERVICE_LOCAL_HOST: " $SERVICE_LOCAL_HOST
+}
+
+function sanity_check_system_ipv6_enabled {
+    system_ipv6_enabled=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_ipv6_enabled())')
+    if [[ $system_ipv6_enabled != "True" ]]; then
+        echo "IPv6 is disabled in system"
+        exit 1
+    fi
+    echo "IPv6 is enabled in system"
+}
+
+function verify_service_listen_address_is_ipv6 {
+    local endpoints_verified=False
+    local all_ipv6=True
+    endpoints=$(openstack endpoint list -f value -c URL)
+    for endpoint in ${endpoints}; do
+        local endpoint_address=$(echo "$endpoint" | awk -F/ '{print $3}' | awk -F] '{print $1}')
+        endpoint_address=$(echo $endpoint_address | tr -d [])
+        local is_endpoint_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$endpoint_address'"))')
+        if [[ "$is_endpoint_ipv6" != "True" ]]; then
+            all_ipv6=False
+            echo $endpoint ": This is not ipv6 endpoint which means corresponding service is not listening on IPv6 address."
+            continue
+        fi
+        endpoints_verified=True
+    done
+    if [[ "$all_ipv6" == "False"  ]] || [[ "$endpoints_verified" == "False" ]]; then
+        exit 1
+    fi
+    echo "All services deployed by devstack is on IPv6 endpoints"
+    echo $endpoints
+}
+
+#First thing to verify if system has IPv6 enabled or not
+sanity_check_system_ipv6_enabled
+#Verify whether devstack is configured properly with IPv6 setting
+verify_devstack_ipv6_setting
+#Get all registrfed endpoints by devstack in keystone and verify that each endpoints address is IPv6.
+verify_service_listen_address_is_ipv6
diff --git a/tox.ini b/tox.ini
index 21182d8..b6ea143 100644
--- a/tox.ini
+++ b/tox.ini
@@ -231,6 +231,18 @@
     find . -type f -name "*.pyc" -delete
     tempest run --serial --regex '\[.*\bslow\b.*\]' {posargs}
 
+[testenv:ipv6-only]
+envdir = .tox/tempest
+sitepackages = {[tempestenv]sitepackages}
+setenv = {[tempestenv]setenv}
+deps = {[tempestenv]deps}
+# Run only smoke and ipv6 tests. This env is used to tests
+# the ipv6 deployments and basic tests run fine so that we can
+# verify that services listen on IPv6 address.
+commands =
+    find . -type f -name "*.pyc" -delete
+    tempest run --regex '\[.*\bsmoke|ipv6|test_network_v6\b.*\]' {posargs}
+
 [testenv:venv]
 deps =
   -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}