summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING.rst2
-rw-r--r--README.rst4
-rw-r--r--REVIEWING.rst2
-rw-r--r--doc/source/conf.py3
-rw-r--r--doc/source/microversion_testing.rst24
-rw-r--r--doc/source/test_removal.rst2
-rw-r--r--releasenotes/notes/10/10.0-supported-openstack-releases-b88db468695348f6.yaml (renamed from releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml)0
-rw-r--r--releasenotes/notes/10/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml (renamed from releasenotes/notes/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml)2
-rw-r--r--releasenotes/notes/10/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml (renamed from releasenotes/notes/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml)0
-rw-r--r--releasenotes/notes/11/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml (renamed from releasenotes/notes/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml)0
-rw-r--r--releasenotes/notes/11/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml (renamed from releasenotes/notes/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml)0
-rw-r--r--releasenotes/notes/11/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml (renamed from releasenotes/notes/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml)0
-rw-r--r--releasenotes/notes/12/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml (renamed from releasenotes/notes/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml (renamed from releasenotes/notes/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml (renamed from releasenotes/notes/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml (renamed from releasenotes/notes/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml (renamed from releasenotes/notes/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml (renamed from releasenotes/notes/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-bug-1486834-7ebca15836ae27a9.yaml (renamed from releasenotes/notes/12.1.0-bug-1486834-7ebca15836ae27a9.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml (renamed from releasenotes/notes/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml (renamed from releasenotes/notes/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-new-test-utils-module-adf34468c4d52719.yaml (renamed from releasenotes/notes/12.1.0-new-test-utils-module-adf34468c4d52719.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml (renamed from releasenotes/notes/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml (renamed from releasenotes/notes/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml (renamed from releasenotes/notes/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-remove-trove-tests-666522e9113549f9.yaml (renamed from releasenotes/notes/12.1.0-remove-trove-tests-666522e9113549f9.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-routers-client-as-library-25a363379da351f6.yaml (renamed from releasenotes/notes/12.1.0-routers-client-as-library-25a363379da351f6.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml (renamed from releasenotes/notes/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml)0
-rw-r--r--releasenotes/notes/12/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml (renamed from releasenotes/notes/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml (renamed from releasenotes/notes/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml (renamed from releasenotes/notes/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-clients_module-16f3025f515bf9ec.yaml (renamed from releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml (renamed from releasenotes/notes/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml (renamed from releasenotes/notes/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml (renamed from releasenotes/notes/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml (renamed from releasenotes/notes/12.2.0-service_client_config-8a1d7b4de769c633.yaml)0
-rw-r--r--releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml (renamed from releasenotes/notes/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml (renamed from releasenotes/notes/13.0.0-add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml (renamed from releasenotes/notes/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml (renamed from releasenotes/notes/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml (renamed from releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml (renamed from releasenotes/notes/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml (renamed from releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml)0
-rw-r--r--releasenotes/notes/13/13.0.0-volume-clients-as-library-660811011be29d1a.yaml (renamed from releasenotes/notes/13.0.0-volume-clients-as-library-660811011be29d1a.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml (renamed from releasenotes/notes/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml (renamed from releasenotes/notes/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml (renamed from releasenotes/notes/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml (renamed from releasenotes/notes/14.0.0-add-image-clients-af94564fb34ddca6.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml (renamed from releasenotes/notes/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml (renamed from releasenotes/notes/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml (renamed from releasenotes/notes/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml (renamed from releasenotes/notes/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml (renamed from releasenotes/notes/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml (renamed from releasenotes/notes/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml (renamed from releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml (renamed from releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml (renamed from releasenotes/notes/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml (renamed from releasenotes/notes/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml (renamed from releasenotes/notes/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml)0
-rw-r--r--releasenotes/notes/14/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml (renamed from releasenotes/notes/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml (renamed from releasenotes/notes/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml (renamed from releasenotes/notes/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml (renamed from releasenotes/notes/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml (renamed from releasenotes/notes/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml (renamed from releasenotes/notes/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml (renamed from releasenotes/notes/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml (renamed from releasenotes/notes/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml (renamed from releasenotes/notes/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml (renamed from releasenotes/notes/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml (renamed from releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml (renamed from releasenotes/notes/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml)0
-rw-r--r--releasenotes/notes/15/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml (renamed from releasenotes/notes/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml (renamed from releasenotes/notes/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml (renamed from releasenotes/notes/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml (renamed from releasenotes/notes/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml (renamed from releasenotes/notes/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml (renamed from releasenotes/notes/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml (renamed from releasenotes/notes/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml (renamed from releasenotes/notes/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml (renamed from releasenotes/notes/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml (renamed from releasenotes/notes/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml (renamed from releasenotes/notes/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml (renamed from releasenotes/notes/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml (renamed from releasenotes/notes/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml (renamed from releasenotes/notes/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml (renamed from releasenotes/notes/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml (renamed from releasenotes/notes/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml (renamed from releasenotes/notes/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml (renamed from releasenotes/notes/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml (renamed from releasenotes/notes/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml (renamed from releasenotes/notes/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml (renamed from releasenotes/notes/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml (renamed from releasenotes/notes/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml (renamed from releasenotes/notes/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml (renamed from releasenotes/notes/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml (renamed from releasenotes/notes/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml (renamed from releasenotes/notes/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-mitaka-eol-88ff8355fff81b55.yaml (renamed from releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml (renamed from releasenotes/notes/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml (renamed from releasenotes/notes/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml (renamed from releasenotes/notes/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml (renamed from releasenotes/notes/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml (renamed from releasenotes/notes/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml (renamed from releasenotes/notes/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml (renamed from releasenotes/notes/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml (renamed from releasenotes/notes/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml (renamed from releasenotes/notes/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml)0
-rw-r--r--releasenotes/notes/16/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml (renamed from releasenotes/notes/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml)0
-rw-r--r--releasenotes/notes/add-params-to-v2-list-backups-api-c088d2b4bfe90247.yaml6
-rw-r--r--releasenotes/notes/extra-compute-services-tests-92b6c0618972e02f.yaml6
-rw-r--r--releasenotes/notes/identity_client-635275d43abbb807.yaml5
-rw-r--r--releasenotes/notes/intermediate-pike-release-2ce492432ff8f012.yaml4
-rw-r--r--releasenotes/notes/tempest-identity-catalog-client-f5c8589a9d7c1eb5.yaml5
-rw-r--r--releasenotes/source/index.rst1
-rw-r--r--releasenotes/source/v16.1.0.rst6
-rw-r--r--requirements.txt2
-rw-r--r--setup.cfg2
-rw-r--r--tempest/api/compute/admin/test_live_migration.py49
-rw-r--r--tempest/api/compute/admin/test_live_migration_negative.py (renamed from tempest/api/compute/admin/test_live_block_migration_negative.py)18
-rw-r--r--tempest/api/compute/admin/test_servers_negative.py1
-rw-r--r--tempest/api/compute/base.py18
-rw-r--r--tempest/api/compute/servers/test_create_server.py105
-rw-r--r--tempest/api/compute/servers/test_create_server_multi_nic.py120
-rw-r--r--tempest/api/identity/admin/v3/test_endpoint_groups.py10
-rw-r--r--tempest/api/identity/admin/v3/test_tokens.py3
-rw-r--r--tempest/api/identity/base.py1
-rwxr-xr-xtempest/api/identity/v3/test_catalog.py41
-rw-r--r--tempest/api/network/admin/test_routers.py7
-rw-r--r--tempest/api/volume/admin/test_volume_quotas.py2
-rw-r--r--tempest/api/volume/admin/test_volume_type_access.py2
-rw-r--r--tempest/api/volume/test_volumes_clone.py24
-rw-r--r--tempest/clients.py114
-rwxr-xr-xtempest/cmd/account_generator.py12
-rw-r--r--tempest/cmd/cleanup_service.py4
-rw-r--r--tempest/cmd/verify_tempest_config.py2
-rw-r--r--tempest/common/credentials_factory.py103
-rw-r--r--tempest/common/dynamic_creds.py66
-rw-r--r--tempest/common/preprov_creds.py13
-rw-r--r--tempest/lib/api_schema/response/compute/v2_1/servers.py9
-rw-r--r--tempest/lib/api_schema/response/compute/v2_1/services.py22
-rw-r--r--tempest/lib/api_schema/response/compute/v2_11/__init__.py0
-rw-r--r--tempest/lib/api_schema/response/compute/v2_11/services.py46
-rw-r--r--tempest/lib/common/cred_provider.py8
-rw-r--r--tempest/lib/services/compute/services_client.py37
-rw-r--r--tempest/lib/services/identity/v3/__init__.py17
-rw-r--r--tempest/lib/services/identity/v3/catalog_client.py30
-rw-r--r--tempest/lib/services/identity/v3/endpoint_groups_client.py156
-rw-r--r--tempest/lib/services/identity/v3/identity_client.py7
-rw-r--r--tempest/lib/services/volume/v2/backups_client.py13
-rw-r--r--tempest/scenario/manager.py19
-rw-r--r--tempest/scenario/test_stamp_pattern.py18
-rw-r--r--tempest/scenario/test_volume_boot_pattern.py24
-rw-r--r--tempest/scenario/test_volume_migrate_attached.py1
-rw-r--r--tempest/services/object_storage/bulk_middleware_client.py6
-rw-r--r--tempest/test.py7
-rw-r--r--tempest/tests/cmd/test_account_generator.py16
-rw-r--r--tempest/tests/common/test_dynamic_creds.py6
-rw-r--r--tempest/tests/common/test_preprov_creds.py5
-rw-r--r--tempest/tests/lib/services/compute/test_services_client.py56
-rw-r--r--tempest/tests/lib/services/identity/v3/test_catalog_client.py86
-rw-r--r--tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py324
-rw-r--r--tempest/tests/lib/services/identity/v3/test_identity_client.py8
-rw-r--r--tempest/tests/lib/services/identity/v3/test_oauth_token_client.py6
-rw-r--r--tempest/tests/lib/services/volume/v2/test_backups_client.py117
-rw-r--r--tempest/tests/lib/services/volume/v2/test_snapshot_manage_client.py83
-rw-r--r--tempest/tests/lib/services/volume/v2/test_transfers_client.py123
-rw-r--r--tempest/tests/lib/services/volume/v2/test_volume_manage_client.py111
-rw-r--r--tools/tempest-plugin-sanity.sh122
-rw-r--r--tox.ini8
169 files changed, 1655 insertions, 627 deletions
diff --git a/HACKING.rst b/HACKING.rst
index 999f92e6a..e5f45ac1b 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -2,7 +2,7 @@ Tempest Coding Guide
====================
- Step 1: Read the OpenStack Style Commandments
- http://docs.openstack.org/developer/hacking/
+ https://docs.openstack.org/hacking/latest/
- Step 2: Read on
Tempest Specific Commandments
diff --git a/README.rst b/README.rst
index 1bc213b66..2e13fec5a 100644
--- a/README.rst
+++ b/README.rst
@@ -11,7 +11,7 @@ Tempest - The OpenStack Integration Test Suite
==============================================
The documentation for Tempest is officially hosted at:
-http://docs.openstack.org/developer/tempest/
+https://docs.openstack.org/tempest/latest/
This is a set of integration tests to be run against a live OpenStack
cluster. Tempest has batteries of tests for OpenStack API validation,
@@ -117,7 +117,7 @@ as it is simpler, and quicker to work with.
will run the same set of tests as the default gate jobs.
.. _testr: https://testrepository.readthedocs.org/en/latest/MANUAL.html
-.. _ostestr: http://docs.openstack.org/developer/os-testr/
+.. _ostestr: https://docs.openstack.org/os-testr/latest/
Library
-------
diff --git a/REVIEWING.rst b/REVIEWING.rst
index 9ad9ea0cd..7d28320b4 100644
--- a/REVIEWING.rst
+++ b/REVIEWING.rst
@@ -111,7 +111,7 @@ deprecation), CLI additions or deprecations, major feature additions, and
anything backwards incompatible or would require a user to take note or do
something extra.
-.. _reno: http://docs.openstack.org/developer/reno/
+.. _reno: https://docs.openstack.org/reno/latest/
Deprecated Code
---------------
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 23f732e17..201d3877b 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -36,7 +36,8 @@ def build_plugin_registry(app):
subprocess.call(['tools/generate-tempest-plugins-list.sh'], cwd=root_dir)
def setup(app):
- app.connect('builder-inited', build_plugin_registry)
+ if os.getenv('GENERATE_TEMPEST_PLUGIN_LIST', 'true').lower() == 'true':
+ app.connect('builder-inited', build_plugin_registry)
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index d6d90ba47..60f4f365a 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -111,7 +111,7 @@ For Details, see: `API Microversion testing Framework`_
This document explains how to implement Microversion tests using those
interfaces.
-.. _API Microversion testing Framework: http://docs.openstack.org/developer/tempest/library/api_microversion_testing.html
+.. _API Microversion testing Framework: https://docs.openstack.org/tempest/latest/library/api_microversion_testing.html
Step1: Add skip logic based on configured Microversion range
@@ -296,46 +296,46 @@ Microversion tests implemented in Tempest
* `2.1`_
- .. _2.1: http://docs.openstack.org/developer/nova/api_microversion_history.html#id1
+ .. _2.1: https://docs.openstack.org/nova/latest/api_microversion_history.html#id1
* `2.2`_
- .. _2.2: http://docs.openstack.org/developer/nova/api_microversion_history.html#id2
+ .. _2.2: http://docs.openstack.org/nova/latest/api_microversion_history.html#id2
* `2.10`_
- .. _2.10: http://docs.openstack.org/developer/nova/api_microversion_history.html#id9
+ .. _2.10: http://docs.openstack.org/nova/latest/api_microversion_history.html#id9
* `2.20`_
- .. _2.20: http://docs.openstack.org/developer/nova/api_microversion_history.html#id18
+ .. _2.20: http://docs.openstack.org/nova/latest/api_microversion_history.html#id18
* `2.25`_
- .. _2.25: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-mitaka
+ .. _2.25: http://docs.openstack.org/nova/latest/api_microversion_history.html#maximum-in-mitaka
* `2.32`_
- .. _2.32: http://docs.openstack.org/developer/nova/api_microversion_history.html#id29
+ .. _2.32: http://docs.openstack.org/nova/latest/api_microversion_history.html#id29
* `2.37`_
- .. _2.37: http://docs.openstack.org/developer/nova/api_microversion_history.html#id34
+ .. _2.37: http://docs.openstack.org/nova/latest/api_microversion_history.html#id34
* `2.42`_
- .. _2.42: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-ocata
+ .. _2.42: http://docs.openstack.org/nova/latest/api_microversion_history.html#maximum-in-ocata
* `2.47`_
- .. _2.47: http://docs.openstack.org/developer/nova/api_microversion_history.html#id42
+ .. _2.47: http://docs.openstack.org/nova/latest/api_microversion_history.html#id42
* `2.48`_
- .. _2.48: http://docs.openstack.org/developer/nova/api_microversion_history.html#id43
+ .. _2.48: http://docs.openstack.org/nova/latest/api_microversion_history.html#id43
* Volume
* `3.3`_
- .. _3.3: https://docs.openstack.org/developer/cinder/devref/api_microversion_history.html#id4
+ .. _3.3: https://docs.openstack.org/cinder/latest/devref/api_microversion_history.html#id4
diff --git a/doc/source/test_removal.rst b/doc/source/test_removal.rst
index d06e4ba41..07c3046b0 100644
--- a/doc/source/test_removal.rst
+++ b/doc/source/test_removal.rst
@@ -171,7 +171,7 @@ removed assuming there is equivalent testing elsewhere. Preferably using the
`tempest plugin mechanism`_
to maintain continuity after migrating the tests out of tempest.
-.. _tempest plugin mechanism: http://docs.openstack.org/developer/tempest/plugin.html
+.. _tempest plugin mechanism: https://docs.openstack.org/tempest/latest/plugin.html
API Compatibility
"""""""""""""""""
diff --git a/releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml b/releasenotes/notes/10/10.0-supported-openstack-releases-b88db468695348f6.yaml
index 217c2f6b6..217c2f6b6 100644
--- a/releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml
+++ b/releasenotes/notes/10/10.0-supported-openstack-releases-b88db468695348f6.yaml
diff --git a/releasenotes/notes/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml b/releasenotes/notes/10/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml
index 0ed313012..c1edd6316 100644
--- a/releasenotes/notes/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml
+++ b/releasenotes/notes/10/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml
@@ -5,7 +5,7 @@ prelude: |
it lives directly in the tempest project. For more information refer to
the `library docs`_.
- .. _library docs: http://docs.openstack.org/developer/tempest/library.html#library
+ .. _library docs: https://docs.openstack.org/tempest/latest/library.html#current-library-apis
features:
- Tempest library interface
diff --git a/releasenotes/notes/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml b/releasenotes/notes/10/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml
index 0bc9af58a..0bc9af58a 100644
--- a/releasenotes/notes/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml
+++ b/releasenotes/notes/10/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml
diff --git a/releasenotes/notes/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml b/releasenotes/notes/11/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml
index e98671a52..e98671a52 100644
--- a/releasenotes/notes/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml
+++ b/releasenotes/notes/11/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml
diff --git a/releasenotes/notes/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml b/releasenotes/notes/11/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml
index de1b35ee1..de1b35ee1 100644
--- a/releasenotes/notes/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml
+++ b/releasenotes/notes/11/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml
diff --git a/releasenotes/notes/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml b/releasenotes/notes/11/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml
index 09ff15d14..09ff15d14 100644
--- a/releasenotes/notes/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml
+++ b/releasenotes/notes/11/11.0.0-supported-openstack-releases-1e5d7295d939d439.yaml
diff --git a/releasenotes/notes/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml b/releasenotes/notes/12/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml
index 9baf0352a..9baf0352a 100644
--- a/releasenotes/notes/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml
+++ b/releasenotes/notes/12/12.0.0-supported-openstack-releases-f10aac381d933dd1.yaml
diff --git a/releasenotes/notes/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml b/releasenotes/notes/12/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml
index 07e3151ff..07e3151ff 100644
--- a/releasenotes/notes/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml
+++ b/releasenotes/notes/12/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml
diff --git a/releasenotes/notes/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml b/releasenotes/notes/12/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml
index 297279f99..297279f99 100644
--- a/releasenotes/notes/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml
+++ b/releasenotes/notes/12/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml
diff --git a/releasenotes/notes/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml b/releasenotes/notes/12/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml
index 429bf52a5..429bf52a5 100644
--- a/releasenotes/notes/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml
+++ b/releasenotes/notes/12/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml
diff --git a/releasenotes/notes/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml b/releasenotes/notes/12/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml
index 9a1cef6e1..9a1cef6e1 100644
--- a/releasenotes/notes/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml
+++ b/releasenotes/notes/12/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml
diff --git a/releasenotes/notes/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml b/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
index 092014e61..092014e61 100644
--- a/releasenotes/notes/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
+++ b/releasenotes/notes/12/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
diff --git a/releasenotes/notes/12.1.0-bug-1486834-7ebca15836ae27a9.yaml b/releasenotes/notes/12/12.1.0-bug-1486834-7ebca15836ae27a9.yaml
index b2190f368..b2190f368 100644
--- a/releasenotes/notes/12.1.0-bug-1486834-7ebca15836ae27a9.yaml
+++ b/releasenotes/notes/12/12.1.0-bug-1486834-7ebca15836ae27a9.yaml
diff --git a/releasenotes/notes/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml b/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
index f9173a007..f9173a007 100644
--- a/releasenotes/notes/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
+++ b/releasenotes/notes/12/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
diff --git a/releasenotes/notes/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml b/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
index 1fa4dddc1..1fa4dddc1 100644
--- a/releasenotes/notes/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
+++ b/releasenotes/notes/12/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
diff --git a/releasenotes/notes/12.1.0-new-test-utils-module-adf34468c4d52719.yaml b/releasenotes/notes/12/12.1.0-new-test-utils-module-adf34468c4d52719.yaml
index 55df2b386..55df2b386 100644
--- a/releasenotes/notes/12.1.0-new-test-utils-module-adf34468c4d52719.yaml
+++ b/releasenotes/notes/12/12.1.0-new-test-utils-module-adf34468c4d52719.yaml
diff --git a/releasenotes/notes/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml b/releasenotes/notes/12/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml
index 4ee883f60..4ee883f60 100644
--- a/releasenotes/notes/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml
+++ b/releasenotes/notes/12/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml
diff --git a/releasenotes/notes/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml b/releasenotes/notes/12/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml
index 294f6d9a5..294f6d9a5 100644
--- a/releasenotes/notes/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml
+++ b/releasenotes/notes/12/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml
diff --git a/releasenotes/notes/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml b/releasenotes/notes/12/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
index 89b3f4133..89b3f4133 100644
--- a/releasenotes/notes/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
+++ b/releasenotes/notes/12/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
diff --git a/releasenotes/notes/12.1.0-remove-trove-tests-666522e9113549f9.yaml b/releasenotes/notes/12/12.1.0-remove-trove-tests-666522e9113549f9.yaml
index 7a1fc367f..7a1fc367f 100644
--- a/releasenotes/notes/12.1.0-remove-trove-tests-666522e9113549f9.yaml
+++ b/releasenotes/notes/12/12.1.0-remove-trove-tests-666522e9113549f9.yaml
diff --git a/releasenotes/notes/12.1.0-routers-client-as-library-25a363379da351f6.yaml b/releasenotes/notes/12/12.1.0-routers-client-as-library-25a363379da351f6.yaml
index 35cf2c487..35cf2c487 100644
--- a/releasenotes/notes/12.1.0-routers-client-as-library-25a363379da351f6.yaml
+++ b/releasenotes/notes/12/12.1.0-routers-client-as-library-25a363379da351f6.yaml
diff --git a/releasenotes/notes/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml b/releasenotes/notes/12/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml
index eb45523fe..eb45523fe 100644
--- a/releasenotes/notes/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml
+++ b/releasenotes/notes/12/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml
diff --git a/releasenotes/notes/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml b/releasenotes/notes/12/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
index eeda92169..eeda92169 100644
--- a/releasenotes/notes/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
+++ b/releasenotes/notes/12/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
diff --git a/releasenotes/notes/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml b/releasenotes/notes/12/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
index a360f8ed5..a360f8ed5 100644
--- a/releasenotes/notes/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
+++ b/releasenotes/notes/12/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
diff --git a/releasenotes/notes/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml b/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
index 3ec8b5678..3ec8b5678 100644
--- a/releasenotes/notes/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
+++ b/releasenotes/notes/12/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
diff --git a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml b/releasenotes/notes/12/12.2.0-clients_module-16f3025f515bf9ec.yaml
index d07448aa9..d07448aa9 100644
--- a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
+++ b/releasenotes/notes/12/12.2.0-clients_module-16f3025f515bf9ec.yaml
diff --git a/releasenotes/notes/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml b/releasenotes/notes/12/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml
index cfe97c5de..cfe97c5de 100644
--- a/releasenotes/notes/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml
+++ b/releasenotes/notes/12/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml
diff --git a/releasenotes/notes/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml b/releasenotes/notes/12/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml
index 64f729ac2..64f729ac2 100644
--- a/releasenotes/notes/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml
+++ b/releasenotes/notes/12/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml
diff --git a/releasenotes/notes/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml b/releasenotes/notes/12/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml
index 8e893b8dc..8e893b8dc 100644
--- a/releasenotes/notes/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml
+++ b/releasenotes/notes/12/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml
diff --git a/releasenotes/notes/12.2.0-service_client_config-8a1d7b4de769c633.yaml b/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml
index 3e43f9a88..3e43f9a88 100644
--- a/releasenotes/notes/12.2.0-service_client_config-8a1d7b4de769c633.yaml
+++ b/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml
diff --git a/releasenotes/notes/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml b/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
index cf504ad08..cf504ad08 100644
--- a/releasenotes/notes/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
+++ b/releasenotes/notes/12/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
diff --git a/releasenotes/notes/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 9e828f69b..9e828f69b 100644
--- a/releasenotes/notes/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
diff --git a/releasenotes/notes/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml b/releasenotes/notes/13/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml
index 9cfce0df0..9cfce0df0 100644
--- a/releasenotes/notes/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml
+++ b/releasenotes/notes/13/13.0.0-add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml
diff --git a/releasenotes/notes/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml b/releasenotes/notes/13/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml
index 0884cfa91..0884cfa91 100644
--- a/releasenotes/notes/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml
+++ b/releasenotes/notes/13/13.0.0-deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml
diff --git a/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml b/releasenotes/notes/13/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
index 52c04afc1..52c04afc1 100644
--- a/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
+++ b/releasenotes/notes/13/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
diff --git a/releasenotes/notes/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml b/releasenotes/notes/13/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml
index b9b6fb581..b9b6fb581 100644
--- a/releasenotes/notes/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml
+++ b/releasenotes/notes/13/13.0.0-start-of-newton-support-3ebb274f300f28eb.yaml
diff --git a/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml b/releasenotes/notes/13/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
index 813e47f8a..813e47f8a 100644
--- a/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
+++ b/releasenotes/notes/13/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
diff --git a/releasenotes/notes/13.0.0-volume-clients-as-library-660811011be29d1a.yaml b/releasenotes/notes/13/13.0.0-volume-clients-as-library-660811011be29d1a.yaml
index 9e9eff66d..9e9eff66d 100644
--- a/releasenotes/notes/13.0.0-volume-clients-as-library-660811011be29d1a.yaml
+++ b/releasenotes/notes/13/13.0.0-volume-clients-as-library-660811011be29d1a.yaml
diff --git a/releasenotes/notes/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml b/releasenotes/notes/14/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
index 6f7a41188..6f7a41188 100644
--- a/releasenotes/notes/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
+++ b/releasenotes/notes/14/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
diff --git a/releasenotes/notes/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml b/releasenotes/notes/14/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
index 432a6b155..432a6b155 100644
--- a/releasenotes/notes/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
+++ b/releasenotes/notes/14/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
diff --git a/releasenotes/notes/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml b/releasenotes/notes/14/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
index 57bf47c56..57bf47c56 100644
--- a/releasenotes/notes/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
+++ b/releasenotes/notes/14/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
diff --git a/releasenotes/notes/14.0.0-add-image-clients-af94564fb34ddca6.yaml b/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml
index 7e40fd4d6..7e40fd4d6 100644
--- a/releasenotes/notes/14.0.0-add-image-clients-af94564fb34ddca6.yaml
+++ b/releasenotes/notes/14/14.0.0-add-image-clients-af94564fb34ddca6.yaml
diff --git a/releasenotes/notes/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml b/releasenotes/notes/14/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
index a1edcc5c3..a1edcc5c3 100644
--- a/releasenotes/notes/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
+++ b/releasenotes/notes/14/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
diff --git a/releasenotes/notes/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml b/releasenotes/notes/14/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml
index b504c789a..b504c789a 100644
--- a/releasenotes/notes/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml
+++ b/releasenotes/notes/14/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml
diff --git a/releasenotes/notes/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml b/releasenotes/notes/14/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
index b2ad1995a..b2ad1995a 100644
--- a/releasenotes/notes/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
+++ b/releasenotes/notes/14/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
diff --git a/releasenotes/notes/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml b/releasenotes/notes/14/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml
index c2d9a9bc9..c2d9a9bc9 100644
--- a/releasenotes/notes/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml
+++ b/releasenotes/notes/14/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml
diff --git a/releasenotes/notes/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml b/releasenotes/notes/14/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
index 9223ba566..9223ba566 100644
--- a/releasenotes/notes/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
+++ b/releasenotes/notes/14/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
diff --git a/releasenotes/notes/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml b/releasenotes/notes/14/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml
index 033e14788..033e14788 100644
--- a/releasenotes/notes/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml
+++ b/releasenotes/notes/14/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml
diff --git a/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml b/releasenotes/notes/14/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
index 389b29f76..389b29f76 100644
--- a/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
+++ b/releasenotes/notes/14/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
diff --git a/releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml b/releasenotes/notes/14/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml
index ca2635e16..ca2635e16 100644
--- a/releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml
+++ b/releasenotes/notes/14/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml
diff --git a/releasenotes/notes/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml b/releasenotes/notes/14/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml
index e6e53aff2..e6e53aff2 100644
--- a/releasenotes/notes/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml
+++ b/releasenotes/notes/14/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml
diff --git a/releasenotes/notes/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml b/releasenotes/notes/14/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml
index a734d1555..a734d1555 100644
--- a/releasenotes/notes/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml
+++ b/releasenotes/notes/14/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml
diff --git a/releasenotes/notes/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml b/releasenotes/notes/14/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml
index b541cf902..b541cf902 100644
--- a/releasenotes/notes/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml
+++ b/releasenotes/notes/14/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml
diff --git a/releasenotes/notes/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml b/releasenotes/notes/14/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml
index 6babd93f5..6babd93f5 100644
--- a/releasenotes/notes/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml
+++ b/releasenotes/notes/14/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml
diff --git a/releasenotes/notes/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml b/releasenotes/notes/15/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml
index 1af193948..1af193948 100644
--- a/releasenotes/notes/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml
+++ b/releasenotes/notes/15/15.0.0-add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml
diff --git a/releasenotes/notes/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml b/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
index eaab1f0b8..eaab1f0b8 100644
--- a/releasenotes/notes/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
+++ b/releasenotes/notes/15/15.0.0-add-image-clients-tests-49dbc0a0a4281a77.yaml
diff --git a/releasenotes/notes/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml b/releasenotes/notes/15/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml
index 9116ef8b3..9116ef8b3 100644
--- a/releasenotes/notes/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml
+++ b/releasenotes/notes/15/15.0.0-add-implied-roles-to-roles-client-library-edf96408ad9ba82e.yaml
diff --git a/releasenotes/notes/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml b/releasenotes/notes/15/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml
index 9a4e6b195..9a4e6b195 100644
--- a/releasenotes/notes/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml
+++ b/releasenotes/notes/15/15.0.0-add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml
diff --git a/releasenotes/notes/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml b/releasenotes/notes/15/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml
index 4acdc6d2b..4acdc6d2b 100644
--- a/releasenotes/notes/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml
+++ b/releasenotes/notes/15/15.0.0-deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml
diff --git a/releasenotes/notes/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml b/releasenotes/notes/15/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
index c0a06d16a..c0a06d16a 100644
--- a/releasenotes/notes/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
+++ b/releasenotes/notes/15/15.0.0-deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
diff --git a/releasenotes/notes/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml b/releasenotes/notes/15/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
index c80f159d3..c80f159d3 100644
--- a/releasenotes/notes/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
+++ b/releasenotes/notes/15/15.0.0-deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
diff --git a/releasenotes/notes/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml b/releasenotes/notes/15/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml
index 8817ed438..8817ed438 100644
--- a/releasenotes/notes/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml
+++ b/releasenotes/notes/15/15.0.0-jsonschema-validator-2377ba131e12d3c7.yaml
diff --git a/releasenotes/notes/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml b/releasenotes/notes/15/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml
index b1c0c6230..b1c0c6230 100644
--- a/releasenotes/notes/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml
+++ b/releasenotes/notes/15/15.0.0-remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml
diff --git a/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml b/releasenotes/notes/15/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
index 104bf2792..104bf2792 100644
--- a/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
+++ b/releasenotes/notes/15/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
diff --git a/releasenotes/notes/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml b/releasenotes/notes/15/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml
index 371c0614a..371c0614a 100644
--- a/releasenotes/notes/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml
+++ b/releasenotes/notes/15/15.0.0-remove-deprecated-input-scenario-config-options-414e0c5442e967e9.yaml
diff --git a/releasenotes/notes/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml b/releasenotes/notes/15/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml
index e445fb3ff..e445fb3ff 100644
--- a/releasenotes/notes/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml
+++ b/releasenotes/notes/15/15.0.0-remove-deprecated-network-config-options-f9ce276231578fe6.yaml
diff --git a/releasenotes/notes/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml b/releasenotes/notes/16/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
index 6b4566605..6b4566605 100644
--- a/releasenotes/notes/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
+++ b/releasenotes/notes/16/16.0.0-add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
diff --git a/releasenotes/notes/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml b/releasenotes/notes/16/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
index 01136c6af..01136c6af 100644
--- a/releasenotes/notes/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
+++ b/releasenotes/notes/16/16.0.0-add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
diff --git a/releasenotes/notes/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml b/releasenotes/notes/16/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml
index 6801858f8..6801858f8 100644
--- a/releasenotes/notes/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml
+++ b/releasenotes/notes/16/16.0.0-add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml
diff --git a/releasenotes/notes/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml b/releasenotes/notes/16/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
index 848a21bca..848a21bca 100644
--- a/releasenotes/notes/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
+++ b/releasenotes/notes/16/16.0.0-add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
diff --git a/releasenotes/notes/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml b/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
index 0075a361e..0075a361e 100644
--- a/releasenotes/notes/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
+++ b/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
diff --git a/releasenotes/notes/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml b/releasenotes/notes/16/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml
index 471f8f0c0..471f8f0c0 100644
--- a/releasenotes/notes/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml
+++ b/releasenotes/notes/16/16.0.0-add-list-auth-project-client-5905076d914a3943.yaml
diff --git a/releasenotes/notes/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml b/releasenotes/notes/16/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml
index acc7a4187..acc7a4187 100644
--- a/releasenotes/notes/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml
+++ b/releasenotes/notes/16/16.0.0-add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml
diff --git a/releasenotes/notes/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml b/releasenotes/notes/16/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml
index 67f954107..67f954107 100644
--- a/releasenotes/notes/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml
+++ b/releasenotes/notes/16/16.0.0-add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml
diff --git a/releasenotes/notes/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml b/releasenotes/notes/16/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml
index dd66ff5b6..dd66ff5b6 100644
--- a/releasenotes/notes/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml
+++ b/releasenotes/notes/16/16.0.0-add-list-version-to-identity-client-944cb7396088a575.yaml
diff --git a/releasenotes/notes/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml b/releasenotes/notes/16/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml
index 233cc287e..233cc287e 100644
--- a/releasenotes/notes/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml
+++ b/releasenotes/notes/16/16.0.0-add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml
diff --git a/releasenotes/notes/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml b/releasenotes/notes/16/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
index 06f4fcd05..06f4fcd05 100644
--- a/releasenotes/notes/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
+++ b/releasenotes/notes/16/16.0.0-add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
diff --git a/releasenotes/notes/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml b/releasenotes/notes/16/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
index 1b8cda2b8..1b8cda2b8 100644
--- a/releasenotes/notes/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
+++ b/releasenotes/notes/16/16.0.0-add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
diff --git a/releasenotes/notes/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml b/releasenotes/notes/16/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml
index 73900ca60..73900ca60 100644
--- a/releasenotes/notes/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml
+++ b/releasenotes/notes/16/16.0.0-add-tempest-run-combine-option-e94c1049ba8985d5.yaml
diff --git a/releasenotes/notes/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml b/releasenotes/notes/16/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
index c95e77c90..c95e77c90 100644
--- a/releasenotes/notes/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
+++ b/releasenotes/notes/16/16.0.0-add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
diff --git a/releasenotes/notes/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml b/releasenotes/notes/16/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
index 34530501b..34530501b 100644
--- a/releasenotes/notes/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
+++ b/releasenotes/notes/16/16.0.0-add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
diff --git a/releasenotes/notes/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml b/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
index 992797189..992797189 100644
--- a/releasenotes/notes/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
+++ b/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml b/releasenotes/notes/16/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml
index 69c6bb6b4..69c6bb6b4 100644
--- a/releasenotes/notes/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-deactivate_image-config-7a282c471937bbcb.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml b/releasenotes/notes/16/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
index c3e43ee77..c3e43ee77 100644
--- a/releasenotes/notes/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml b/releasenotes/notes/16/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
index 788bc9590..788bc9590 100644
--- a/releasenotes/notes/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml b/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
index f6792086b..f6792086b 100644
--- a/releasenotes/notes/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml b/releasenotes/notes/16/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml
index 4d8b94157..4d8b94157 100644
--- a/releasenotes/notes/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml
diff --git a/releasenotes/notes/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml b/releasenotes/notes/16/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml
index 6285ea6a2..6285ea6a2 100644
--- a/releasenotes/notes/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml
diff --git a/releasenotes/notes/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml b/releasenotes/notes/16/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml
index 0660d9c1c..0660d9c1c 100644
--- a/releasenotes/notes/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml
diff --git a/releasenotes/notes/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml b/releasenotes/notes/16/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml
index 4081f6a4f..4081f6a4f 100644
--- a/releasenotes/notes/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml
+++ b/releasenotes/notes/16/16.0.0-dreprecate_client_parameters-cb8d069e62957f7e.yaml
diff --git a/releasenotes/notes/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml b/releasenotes/notes/16/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml
index 6d3157648..6d3157648 100644
--- a/releasenotes/notes/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml
+++ b/releasenotes/notes/16/16.0.0-fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml
diff --git a/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml b/releasenotes/notes/16/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
index 24ec51274..24ec51274 100644
--- a/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
+++ b/releasenotes/notes/16/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
diff --git a/releasenotes/notes/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml b/releasenotes/notes/16/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml
index 56708211c..56708211c 100644
--- a/releasenotes/notes/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-call_until_true-of-test-de9c13bc8f969921.yaml
diff --git a/releasenotes/notes/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml b/releasenotes/notes/16/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml
index 710ad9ee3..710ad9ee3 100644
--- a/releasenotes/notes/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-cinder-v1-api-tests-71e266b8d55d475f.yaml
diff --git a/releasenotes/notes/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml b/releasenotes/notes/16/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml
index 9d7102fe0..9d7102fe0 100644
--- a/releasenotes/notes/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml
diff --git a/releasenotes/notes/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml b/releasenotes/notes/16/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
index b4e4dd105..b4e4dd105 100644
--- a/releasenotes/notes/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
diff --git a/releasenotes/notes/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml b/releasenotes/notes/16/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml
index 889e86275..889e86275 100644
--- a/releasenotes/notes/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml
diff --git a/releasenotes/notes/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml b/releasenotes/notes/16/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml
index 8085694f8..8085694f8 100644
--- a/releasenotes/notes/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml
diff --git a/releasenotes/notes/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml b/releasenotes/notes/16/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml
index c0dc7d71a..c0dc7d71a 100644
--- a/releasenotes/notes/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-sahara-service-available-44a642aa9c634ab4.yaml
diff --git a/releasenotes/notes/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml b/releasenotes/notes/16/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml
index fc15995a3..fc15995a3 100644
--- a/releasenotes/notes/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml
+++ b/releasenotes/notes/16/16.0.0-remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml
diff --git a/releasenotes/notes/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml b/releasenotes/notes/16/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml
index dd6e92457..dd6e92457 100644
--- a/releasenotes/notes/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml
+++ b/releasenotes/notes/16/16.0.0-use-keystone-v3-api-935860d30ddbb8e9.yaml
diff --git a/releasenotes/notes/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml b/releasenotes/notes/16/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml
index e5e479bf9..e5e479bf9 100644
--- a/releasenotes/notes/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml
+++ b/releasenotes/notes/16/16.0.0-volume-transfers-client-e5ed3f5464c0cdc0.yaml
diff --git a/releasenotes/notes/add-params-to-v2-list-backups-api-c088d2b4bfe90247.yaml b/releasenotes/notes/add-params-to-v2-list-backups-api-c088d2b4bfe90247.yaml
new file mode 100644
index 000000000..cee2d7663
--- /dev/null
+++ b/releasenotes/notes/add-params-to-v2-list-backups-api-c088d2b4bfe90247.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ The ``list_backups`` method of the v2 ``BackupsClient`` class now has
+ an additional ``**params`` argument that enables passing additional
+ information in the query string of the HTTP request.
diff --git a/releasenotes/notes/extra-compute-services-tests-92b6c0618972e02f.yaml b/releasenotes/notes/extra-compute-services-tests-92b6c0618972e02f.yaml
new file mode 100644
index 000000000..414adf18b
--- /dev/null
+++ b/releasenotes/notes/extra-compute-services-tests-92b6c0618972e02f.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add the ``disable_log_reason`` and the ``update_forced_down`` API endpoints
+ to the compute ``services_client``.
+ Add '2.11' compute validation schema for compute services API.
diff --git a/releasenotes/notes/identity_client-635275d43abbb807.yaml b/releasenotes/notes/identity_client-635275d43abbb807.yaml
new file mode 100644
index 000000000..6f984b74e
--- /dev/null
+++ b/releasenotes/notes/identity_client-635275d43abbb807.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Enhances the v3 identity client with the ``check_token_existence``
+ endpoint, allowing users to check the existence of tokens
diff --git a/releasenotes/notes/intermediate-pike-release-2ce492432ff8f012.yaml b/releasenotes/notes/intermediate-pike-release-2ce492432ff8f012.yaml
new file mode 100644
index 000000000..bfebcd9ed
--- /dev/null
+++ b/releasenotes/notes/intermediate-pike-release-2ce492432ff8f012.yaml
@@ -0,0 +1,4 @@
+---
+prelude: >
+ This is an intermediate release during the Pike development cycle to
+ make new functionality available to plugins and other consumers.
diff --git a/releasenotes/notes/tempest-identity-catalog-client-f5c8589a9d7c1eb5.yaml b/releasenotes/notes/tempest-identity-catalog-client-f5c8589a9d7c1eb5.yaml
new file mode 100644
index 000000000..dcaaceb5f
--- /dev/null
+++ b/releasenotes/notes/tempest-identity-catalog-client-f5c8589a9d7c1eb5.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - Add a new identity catalog client. At this point, the new client
+ contains a single functionality, "show_catalog", which returns a
+ catalog object.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index d2be81435..db01da0a0 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ v16.1.0
v16.0.0
v15.0.0
v14.0.0
diff --git a/releasenotes/source/v16.1.0.rst b/releasenotes/source/v16.1.0.rst
new file mode 100644
index 000000000..e24a70fef
--- /dev/null
+++ b/releasenotes/source/v16.1.0.rst
@@ -0,0 +1,6 @@
+=====================
+v16.1.0 Release Notes
+=====================
+
+.. release-notes:: 16.1.0 Release Notes
+ :version: 16.1.0
diff --git a/requirements.txt b/requirements.txt
index 259a4cffc..b7ebf8ac9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,7 @@ testrepository>=0.0.18 # Apache-2.0/BSD
oslo.concurrency>=3.8.0 # Apache-2.0
oslo.config!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
oslo.log>=3.22.0 # Apache-2.0
-oslo.serialization>=1.10.0 # Apache-2.0
+oslo.serialization!=2.19.1,>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
six>=1.9.0 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD
diff --git a/setup.cfg b/setup.cfg
index b29297058..f52137edf 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,7 @@ description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
-home-page = http://docs.openstack.org/developer/tempest/
+home-page = https://docs.openstack.org/tempest/latest/
classifier =
Intended Audience :: Information Technology
Intended Audience :: System Administrators
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 3859e64b3..3f1bdce00 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -29,13 +29,13 @@ CONF = config.CONF
LOG = logging.getLogger(__name__)
-class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
+class LiveMigrationTest(base.BaseV2ComputeAdminTest):
max_microversion = '2.24'
block_migration = None
@classmethod
def skip_checks(cls):
- super(LiveBlockMigrationTestJSON, cls).skip_checks()
+ super(LiveMigrationTest, cls).skip_checks()
if not CONF.compute_feature_enabled.live_migration:
skip_msg = ("%s skipped as live-migration is "
@@ -47,26 +47,9 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
@classmethod
def setup_clients(cls):
- super(LiveBlockMigrationTestJSON, cls).setup_clients()
- cls.admin_hosts_client = cls.os_admin.hosts_client
+ super(LiveMigrationTest, cls).setup_clients()
cls.admin_migration_client = cls.os_admin.migrations_client
- @classmethod
- def _get_compute_hostnames(cls):
- body = cls.admin_hosts_client.list_hosts()['hosts']
- return [
- host_record['host_name']
- for host_record in body
- if host_record['service'] == 'compute'
- ]
-
- def _get_server_details(self, server_id):
- body = self.admin_servers_client.show_server(server_id)['server']
- return body
-
- def _get_host_for_server(self, server_id):
- return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host']
-
def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
kwargs = dict()
block_migration = getattr(self, 'block_migration', None)
@@ -79,11 +62,6 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
server_id, host=dest_host, block_migration=block_migration,
**kwargs)
- def _get_host_other_than(self, host):
- for target_host in self._get_compute_hostnames():
- if host != target_host:
- return target_host
-
def _live_migrate(self, server_id, target_host, state,
volume_backed=False):
self._migrate_server_to(server_id, target_host, volume_backed)
@@ -97,7 +75,7 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
if (live_migration['instance_uuid'] == server_id):
msg += "\n%s" % live_migration
msg += "]"
- self.assertEqual(target_host, self._get_host_for_server(server_id),
+ self.assertEqual(target_host, self.get_host_for_server(server_id),
msg)
def _test_live_migration(self, state='ACTIVE', volume_backed=False):
@@ -114,8 +92,8 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
# Live migrate an instance to another host
server_id = self.create_test_server(wait_until="ACTIVE",
volume_backed=volume_backed)['id']
- source_host = self._get_host_for_server(server_id)
- destination_host = self._get_host_other_than(source_host)
+ source_host = self.get_host_for_server(server_id)
+ destination_host = self.get_host_other_than(server_id)
if state == 'PAUSED':
self.admin_servers_client.pause_server(server_id)
@@ -158,8 +136,7 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
def test_iscsi_volume(self):
server = self.create_test_server(wait_until="ACTIVE")
server_id = server['id']
- actual_host = self._get_host_for_server(server_id)
- target_host = self._get_host_other_than(actual_host)
+ target_host = self.get_host_other_than(server_id)
volume = self.create_volume()
@@ -174,11 +151,11 @@ class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
server = self.admin_servers_client.show_server(server_id)['server']
volume_id2 = server["os-extended-volumes:volumes_attached"][0]["id"]
- self.assertEqual(target_host, self._get_host_for_server(server_id))
+ self.assertEqual(target_host, self.get_host_for_server(server_id))
self.assertEqual(volume_id1, volume_id2)
-class LiveBlockMigrationRemoteConsolesV26TestJson(LiveBlockMigrationTestJSON):
+class LiveMigrationRemoteConsolesV26Test(LiveMigrationTest):
min_microversion = '2.6'
max_microversion = 'latest'
@@ -201,8 +178,8 @@ class LiveBlockMigrationRemoteConsolesV26TestJson(LiveBlockMigrationTestJSON):
hints = {'different_host': server01_id}
server02_id = self.create_test_server(scheduler_hints=hints,
wait_until='ACTIVE')['id']
- host01_id = self._get_host_for_server(server01_id)
- host02_id = self._get_host_for_server(server02_id)
+ host01_id = self.get_host_for_server(server01_id)
+ host02_id = self.get_host_for_server(server02_id)
self.assertNotEqual(host01_id, host02_id)
# At this step we have 2 instances on different hosts, both with
@@ -216,7 +193,7 @@ class LiveBlockMigrationRemoteConsolesV26TestJson(LiveBlockMigrationTestJSON):
self._migrate_server_to(server01_id, host02_id)
waiters.wait_for_server_status(self.servers_client,
server01_id, 'ACTIVE')
- self.assertEqual(host02_id, self._get_host_for_server(server01_id))
+ self.assertEqual(host02_id, self.get_host_for_server(server01_id))
self._verify_console_interaction(server01_id)
# At this point, both instances have a valid serial console
# connection, which means the ports got updated.
@@ -252,7 +229,7 @@ class LiveBlockMigrationRemoteConsolesV26TestJson(LiveBlockMigrationTestJSON):
self.assertIn(data, console_output)
-class LiveAutoBlockMigrationV225TestJSON(LiveBlockMigrationTestJSON):
+class LiveAutoBlockMigrationV225Test(LiveMigrationTest):
min_microversion = '2.25'
max_microversion = 'latest'
block_migration = 'auto'
diff --git a/tempest/api/compute/admin/test_live_block_migration_negative.py b/tempest/api/compute/admin/test_live_migration_negative.py
index ab6315435..deabbc2d3 100644
--- a/tempest/api/compute/admin/test_live_block_migration_negative.py
+++ b/tempest/api/compute/admin/test_live_migration_negative.py
@@ -23,10 +23,10 @@ from tempest.lib import exceptions as lib_exc
CONF = config.CONF
-class LiveBlockMigrationNegativeTestJSON(base.BaseV2ComputeAdminTest):
+class LiveMigrationNegativeTest(base.BaseV2ComputeAdminTest):
@classmethod
def skip_checks(cls):
- super(LiveBlockMigrationNegativeTestJSON, cls).skip_checks()
+ super(LiveMigrationNegativeTest, cls).skip_checks()
if not CONF.compute_feature_enabled.live_migration:
raise cls.skipException("Live migration is not enabled")
@@ -47,3 +47,17 @@ class LiveBlockMigrationNegativeTestJSON(base.BaseV2ComputeAdminTest):
server['id'], target_host)
waiters.wait_for_server_status(self.servers_client, server['id'],
'ACTIVE')
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('6e2f94f5-2ee8-4830-bef5-5bc95bb0795b')
+ def test_live_block_migration_suspended(self):
+ server = self.create_test_server(wait_until="ACTIVE")
+
+ self.admin_servers_client.suspend_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'SUSPENDED')
+
+ destination_host = self.get_host_other_than(server['id'])
+
+ self.assertRaises(lib_exc.Conflict, self._migrate_server_to,
+ server['id'], destination_host)
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 9023759a4..36567707f 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -32,7 +32,6 @@ class ServersAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
def setup_clients(cls):
super(ServersAdminNegativeTestJSON, cls).setup_clients()
cls.client = cls.os_admin.servers_client
- cls.non_adm_client = cls.servers_client
cls.quotas_client = cls.os_admin.quotas_client
@classmethod
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ddb035dc1..feabe35d1 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -487,3 +487,21 @@ class BaseV2ComputeAdminTest(BaseV2ComputeTest):
self.addCleanup(client.wait_for_resource_deletion, flavor['id'])
self.addCleanup(client.delete_flavor, flavor['id'])
return flavor
+
+ def get_host_for_server(self, server_id):
+ server_details = self.admin_servers_client.show_server(server_id)
+ return server_details['server']['OS-EXT-SRV-ATTR:host']
+
+ def get_host_other_than(self, server_id):
+ source_host = self.get_host_for_server(server_id)
+
+ list_hosts_resp = self.os_admin.hosts_client.list_hosts()['hosts']
+ hosts = [
+ host_record['host_name']
+ for host_record in list_hosts_resp
+ if host_record['service'] == 'compute'
+ ]
+
+ for target_host in hosts:
+ if source_host != target_host:
+ return target_host
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index ffadd96c5..aa5c43d8d 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -28,6 +28,7 @@ CONF = config.CONF
class ServersTestJSON(base.BaseV2ComputeTest):
disk_config = 'AUTO'
+ volume_backed = False
@classmethod
def setup_credentials(cls):
@@ -38,8 +39,6 @@ class ServersTestJSON(base.BaseV2ComputeTest):
def setup_clients(cls):
super(ServersTestJSON, cls).setup_clients()
cls.client = cls.servers_client
- cls.networks_client = cls.os_primary.networks_client
- cls.subnets_client = cls.os_primary.subnets_client
@classmethod
def resource_setup(cls):
@@ -59,24 +58,11 @@ class ServersTestJSON(base.BaseV2ComputeTest):
accessIPv4=cls.accessIPv4,
accessIPv6=cls.accessIPv6,
disk_config=disk_config,
- adminPass=cls.password)
+ adminPass=cls.password,
+ volume_backed=cls.volume_backed)
cls.server = (cls.client.show_server(server_initial['id'])
['server'])
- def _create_net_subnet_ret_net_from_cidr(self, cidr):
- name_net = data_utils.rand_name(self.__class__.__name__)
- net = self.networks_client.create_network(name=name_net)
- self.addCleanup(self.networks_client.delete_network,
- net['network']['id'])
-
- subnet = self.subnets_client.create_subnet(
- network_id=net['network']['id'],
- cidr=cidr,
- ip_version=4)
- self.addCleanup(self.subnets_client.delete_subnet,
- subnet['subnet']['id'])
- return net
-
@decorators.attr(type='smoke')
@decorators.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
def test_verify_server_details(self):
@@ -87,7 +73,11 @@ class ServersTestJSON(base.BaseV2ComputeTest):
self.assertEqual(self.server['accessIPv6'],
str(netaddr.IPAddress(self.accessIPv6)))
self.assertEqual(self.name, self.server['name'])
- self.assertEqual(self.image_ref, self.server['image']['id'])
+ if self.volume_backed:
+ # Image is an empty string as per documentation
+ self.assertEqual("", self.server['image'])
+ else:
+ self.assertEqual(self.image_ref, self.server['image']['id'])
self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
self.assertEqual(self.meta, self.server['metadata'])
@@ -158,73 +148,6 @@ class ServersTestJSON(base.BaseV2ComputeTest):
['server_group'])
self.assertIn(server['id'], server_group['members'])
- @decorators.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
- @testtools.skipUnless(CONF.service_available.neutron,
- 'Neutron service must be available.')
- def test_verify_multiple_nics_order(self):
- # Verify that the networks order given at the server creation is
- # preserved within the server.
- net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24')
- net2 = self._create_net_subnet_ret_net_from_cidr('19.86.0.0/24')
-
- networks = [{'uuid': net1['network']['id']},
- {'uuid': net2['network']['id']}]
-
- server_multi_nics = self.create_test_server(
- networks=networks, wait_until='ACTIVE')
-
- # Cleanup server; this is needed in the test case because with the LIFO
- # nature of the cleanups, if we don't delete the server first, the port
- # will still be part of the subnet and we'll get a 409 from Neutron
- # when trying to delete the subnet. The tear down in the base class
- # will try to delete the server and get a 404 but it's ignored so
- # we're OK.
- self.addCleanup(self.delete_server, server_multi_nics['id'])
-
- addresses = (self.client.list_addresses(server_multi_nics['id'])
- ['addresses'])
-
- # We can't predict the ip addresses assigned to the server on networks.
- # Sometimes the assigned addresses are ['19.80.0.2', '19.86.0.2'], at
- # other times ['19.80.0.3', '19.86.0.3']. So we check if the first
- # address is in first network, similarly second address is in second
- # network.
- addr = [addresses[net1['network']['name']][0]['addr'],
- addresses[net2['network']['name']][0]['addr']]
- networks = [netaddr.IPNetwork('19.80.0.0/24'),
- netaddr.IPNetwork('19.86.0.0/24')]
- for address, network in zip(addr, networks):
- self.assertIn(address, network)
-
- @decorators.idempotent_id('1678d144-ed74-43f8-8e57-ab10dbf9b3c2')
- @testtools.skipUnless(CONF.service_available.neutron,
- 'Neutron service must be available.')
- def test_verify_duplicate_network_nics(self):
- # Verify that server creation does not fail when more than one nic
- # is created on the same network.
- net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24')
- net2 = self._create_net_subnet_ret_net_from_cidr('19.86.0.0/24')
-
- networks = [{'uuid': net1['network']['id']},
- {'uuid': net2['network']['id']},
- {'uuid': net1['network']['id']}]
-
- server_multi_nics = self.create_test_server(
- networks=networks, wait_until='ACTIVE')
- self.addCleanup(self.delete_server, server_multi_nics['id'])
-
- addresses = (self.client.list_addresses(server_multi_nics['id'])
- ['addresses'])
-
- addr = [addresses[net1['network']['name']][0]['addr'],
- addresses[net2['network']['name']][0]['addr'],
- addresses[net1['network']['name']][1]['addr']]
- networks = [netaddr.IPNetwork('19.80.0.0/24'),
- netaddr.IPNetwork('19.86.0.0/24'),
- netaddr.IPNetwork('19.80.0.0/24')]
- for address, network in zip(addr, networks):
- self.assertIn(address, network)
-
class ServersTestManualDisk(ServersTestJSON):
disk_config = 'MANUAL'
@@ -235,3 +158,15 @@ class ServersTestManualDisk(ServersTestJSON):
if not CONF.compute_feature_enabled.disk_config:
msg = "DiskConfig extension not enabled."
raise cls.skipException(msg)
+
+
+class ServersTestBootFromVolume(ServersTestJSON):
+ """Run the `ServersTestJSON` tests with a volume backed VM"""
+ volume_backed = True
+
+ @classmethod
+ def skip_checks(cls):
+ super(ServersTestBootFromVolume, cls).skip_checks()
+ if not test.get_service_list()['volume']:
+ msg = "Volume service not enabled."
+ raise cls.skipException(msg)
diff --git a/tempest/api/compute/servers/test_create_server_multi_nic.py b/tempest/api/compute/servers/test_create_server_multi_nic.py
new file mode 100644
index 000000000..3447d858d
--- /dev/null
+++ b/tempest/api/compute/servers/test_create_server_multi_nic.py
@@ -0,0 +1,120 @@
+# Copyright 2012 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.
+
+import netaddr
+import testtools
+
+from tempest.api.compute import base
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+CONF = config.CONF
+
+
+class ServersTestMultiNic(base.BaseV2ComputeTest):
+
+ @classmethod
+ def setup_credentials(cls):
+ cls.prepare_instance_network()
+ super(ServersTestMultiNic, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(ServersTestMultiNic, cls).setup_clients()
+ cls.client = cls.servers_client
+ cls.networks_client = cls.os_primary.networks_client
+ cls.subnets_client = cls.os_primary.subnets_client
+
+ def _create_net_subnet_ret_net_from_cidr(self, cidr):
+ name_net = data_utils.rand_name(self.__class__.__name__)
+ net = self.networks_client.create_network(name=name_net)
+ self.addCleanup(self.networks_client.delete_network,
+ net['network']['id'])
+
+ subnet = self.subnets_client.create_subnet(
+ network_id=net['network']['id'],
+ cidr=cidr,
+ ip_version=4)
+ self.addCleanup(self.subnets_client.delete_subnet,
+ subnet['subnet']['id'])
+ return net
+
+ @decorators.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
+ @testtools.skipUnless(CONF.service_available.neutron,
+ 'Neutron service must be available.')
+ def test_verify_multiple_nics_order(self):
+ # Verify that the networks order given at the server creation is
+ # preserved within the server.
+ net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24')
+ net2 = self._create_net_subnet_ret_net_from_cidr('19.86.0.0/24')
+
+ networks = [{'uuid': net1['network']['id']},
+ {'uuid': net2['network']['id']}]
+
+ server_multi_nics = self.create_test_server(
+ networks=networks, wait_until='ACTIVE')
+
+ # Cleanup server; this is needed in the test case because with the LIFO
+ # nature of the cleanups, if we don't delete the server first, the port
+ # will still be part of the subnet and we'll get a 409 from Neutron
+ # when trying to delete the subnet. The tear down in the base class
+ # will try to delete the server and get a 404 but it's ignored so
+ # we're OK.
+ self.addCleanup(self.delete_server, server_multi_nics['id'])
+
+ addresses = (self.client.list_addresses(server_multi_nics['id'])
+ ['addresses'])
+
+ # We can't predict the ip addresses assigned to the server on networks.
+ # Sometimes the assigned addresses are ['19.80.0.2', '19.86.0.2'], at
+ # other times ['19.80.0.3', '19.86.0.3']. So we check if the first
+ # address is in first network, similarly second address is in second
+ # network.
+ addr = [addresses[net1['network']['name']][0]['addr'],
+ addresses[net2['network']['name']][0]['addr']]
+ networks = [netaddr.IPNetwork('19.80.0.0/24'),
+ netaddr.IPNetwork('19.86.0.0/24')]
+ for address, network in zip(addr, networks):
+ self.assertIn(address, network)
+
+ @decorators.idempotent_id('1678d144-ed74-43f8-8e57-ab10dbf9b3c2')
+ @testtools.skipUnless(CONF.service_available.neutron,
+ 'Neutron service must be available.')
+ def test_verify_duplicate_network_nics(self):
+ # Verify that server creation does not fail when more than one nic
+ # is created on the same network.
+ net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24')
+ net2 = self._create_net_subnet_ret_net_from_cidr('19.86.0.0/24')
+
+ networks = [{'uuid': net1['network']['id']},
+ {'uuid': net2['network']['id']},
+ {'uuid': net1['network']['id']}]
+
+ server_multi_nics = self.create_test_server(
+ networks=networks, wait_until='ACTIVE')
+ self.addCleanup(self.delete_server, server_multi_nics['id'])
+
+ addresses = (self.client.list_addresses(server_multi_nics['id'])
+ ['addresses'])
+
+ addr = [addresses[net1['network']['name']][0]['addr'],
+ addresses[net2['network']['name']][0]['addr'],
+ addresses[net1['network']['name']][1]['addr']]
+ networks = [netaddr.IPNetwork('19.80.0.0/24'),
+ netaddr.IPNetwork('19.86.0.0/24'),
+ netaddr.IPNetwork('19.80.0.0/24')]
+ for address, network in zip(addr, networks):
+ self.assertIn(address, network)
diff --git a/tempest/api/identity/admin/v3/test_endpoint_groups.py b/tempest/api/identity/admin/v3/test_endpoint_groups.py
index 5cd456c9c..49dbba198 100644
--- a/tempest/api/identity/admin/v3/test_endpoint_groups.py
+++ b/tempest/api/identity/admin/v3/test_endpoint_groups.py
@@ -54,17 +54,17 @@ class EndPointGroupsTest(base.BaseIdentityV3AdminTest):
super(EndPointGroupsTest, cls).resource_cleanup()
@classmethod
- def _create_service(self):
+ def _create_service(cls):
s_name = data_utils.rand_name('service')
s_type = data_utils.rand_name('type')
s_description = data_utils.rand_name('description')
service_data = (
- self.services_client.create_service(name=s_name,
- type=s_type,
- description=s_description))
+ cls.services_client.create_service(name=s_name,
+ type=s_type,
+ description=s_description))
service_id = service_data['service']['id']
- self.service_ids.append(service_id)
+ cls.service_ids.append(service_id)
return service_id
@decorators.idempotent_id('7c69e7a1-f865-402d-a2ea-44493017315a')
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 1acc67df0..5c3cd2667 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -39,6 +39,7 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
resp = self.token.auth(user_id=user['id'],
password=u_password).response
subject_token = resp['x-subject-token']
+ self.client.check_token_existence(subject_token)
# Perform GET Token
token_details = self.client.show_token(subject_token)['token']
self.assertEqual(resp['x-subject-token'], subject_token)
@@ -46,7 +47,7 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
self.assertEqual(token_details['user']['name'], u_name)
# Perform Delete Token
self.client.delete_token(subject_token)
- self.assertRaises(lib_exc.NotFound, self.client.show_token,
+ self.assertRaises(lib_exc.NotFound, self.client.check_token_existence,
subject_token)
@decorators.idempotent_id('565fa210-1da1-4563-999b-f7b5b67cf112')
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 4495cbf75..30d2a366a 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -187,6 +187,7 @@ class BaseIdentityV3Test(BaseIdentityTest):
cls.non_admin_users_client = cls.os_primary.users_v3_client
cls.non_admin_token = cls.os_primary.token_v3_client
cls.non_admin_projects_client = cls.os_primary.projects_client
+ cls.non_admin_catalog_client = cls.os_primary.catalog_client
cls.non_admin_versions_client =\
cls.os_primary.identity_versions_v3_client
diff --git a/tempest/api/identity/v3/test_catalog.py b/tempest/api/identity/v3/test_catalog.py
new file mode 100755
index 000000000..deec2dcf1
--- /dev/null
+++ b/tempest/api/identity/v3/test_catalog.py
@@ -0,0 +1,41 @@
+# 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.identity import base
+from tempest import config
+from tempest.lib import decorators
+
+
+CONF = config.CONF
+
+
+class IdentityCatalogTest(base.BaseIdentityV3Test):
+
+ @decorators.idempotent_id('56b57ced-22b8-4127-9b8a-565dfb0207e2')
+ def test_catalog_standardization(self):
+ # http://git.openstack.org/cgit/openstack/service-types-authority
+ # /tree/service-types.yaml
+ standard_service_values = [{'name': 'keystone', 'type': 'identity'},
+ {'name': 'nova', 'type': 'compute'},
+ {'name': 'glance', 'type': 'image'},
+ {'name': 'swift', 'type': 'object-store'}]
+ # next, we need to GET the catalog using the catalog client
+ catalog = self.non_admin_catalog_client.show_catalog()['catalog']
+ # get list of the service types present in the catalog
+ catalog_services = []
+ for service in catalog:
+ catalog_services.append(service['type'])
+ for service in standard_service_values:
+ # if service enabled, check if it has a standard typevalue
+ if service['name'] == 'keystone' or\
+ getattr(CONF.service_available, service['name']):
+ self.assertIn(service['type'], catalog_services)
diff --git a/tempest/api/network/admin/test_routers.py b/tempest/api/network/admin/test_routers.py
index 07c4157bf..f180cdaea 100644
--- a/tempest/api/network/admin/test_routers.py
+++ b/tempest/api/network/admin/test_routers.py
@@ -61,13 +61,6 @@ class RoutersAdminTest(base.BaseAdminNetworkTest):
msg = "router extension not enabled."
raise cls.skipException(msg)
- @classmethod
- def resource_setup(cls):
- super(RoutersAdminTest, cls).resource_setup()
- cls.tenant_cidr = (CONF.network.project_network_cidr
- if cls._ip_version == 4 else
- CONF.network.project_network_v6_cidr)
-
@decorators.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
def test_create_router_setting_project_id(self):
# Test creating router from admin user setting project_id.
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index f358d7f7d..754104e04 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -36,7 +36,7 @@ class BaseVolumeQuotasAdminTestJSON(base.BaseVolumeAdminTest):
def setup_credentials(cls):
super(BaseVolumeQuotasAdminTestJSON, cls).setup_credentials()
cls.demo_tenant_id = cls.os_primary.credentials.tenant_id
- cls.alt_client = cls.os_alt.volumes_client
+ cls.alt_client = cls.os_alt.volumes_client_latest
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/volume/admin/test_volume_type_access.py b/tempest/api/volume/admin/test_volume_type_access.py
index 297ab6e06..e93bcb5ff 100644
--- a/tempest/api/volume/admin/test_volume_type_access.py
+++ b/tempest/api/volume/admin/test_volume_type_access.py
@@ -30,7 +30,7 @@ class VolumeTypesAccessTest(base.BaseVolumeAdminTest):
@classmethod
def setup_clients(cls):
super(VolumeTypesAccessTest, cls).setup_clients()
- cls.alt_client = cls.os_alt.volumes_client
+ cls.alt_client = cls.os_alt.volumes_client_latest
@decorators.idempotent_id('d4dd0027-835f-4554-a6e5-50903fb79184')
def test_volume_type_access_add(self):
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index 4c1337582..927bfa5a2 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -30,6 +30,18 @@ class VolumesCloneTest(base.BaseVolumeTest):
if not CONF.volume_feature_enabled.clone:
raise cls.skipException("Cinder volume clones are disabled")
+ def _verify_volume_clone(self, source_volume, cloned_volume,
+ bootable='false', extra_size=0):
+
+ cloned_vol_details = self.volumes_client.show_volume(
+ cloned_volume['id'])['volume']
+
+ self.assertEqual(source_volume['id'],
+ cloned_vol_details['source_volid'])
+ self.assertEqual(source_volume['size'] + extra_size,
+ cloned_vol_details['size'])
+ self.assertEqual(bootable, cloned_vol_details['bootable'])
+
@decorators.idempotent_id('9adae371-a257-43a5-9555-dc7c88e66e0e')
def test_create_from_volume(self):
# Creates a volume from another volume passing a size different from
@@ -41,10 +53,7 @@ class VolumesCloneTest(base.BaseVolumeTest):
dst_vol = self.create_volume(source_volid=src_vol['id'],
size=src_size + 1)
- volume = self.volumes_client.show_volume(dst_vol['id'])['volume']
- # Should allow
- self.assertEqual(volume['source_volid'], src_vol['id'])
- self.assertEqual(volume['size'], src_size + 1)
+ self._verify_volume_clone(src_vol, dst_vol, extra_size=1)
@decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
@test.services('image')
@@ -55,10 +64,5 @@ class VolumesCloneTest(base.BaseVolumeTest):
# Create a volume from the bootable volume
cloned_vol = self.create_volume(source_volid=src_vol['id'])
- cloned_vol_details = self.volumes_client.show_volume(
- cloned_vol['id'])['volume']
- # Verify cloned volume creation as expected
- self.assertEqual('true', cloned_vol_details['bootable'])
- self.assertEqual(src_vol['id'], cloned_vol_details['source_volid'])
- self.assertEqual(src_vol['size'], cloned_vol_details['size'])
+ self._verify_volume_clone(src_vol, cloned_vol, bootable='true')
diff --git a/tempest/clients.py b/tempest/clients.py
index 467ef9cd5..85c2242fc 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -13,17 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-from oslo_log import log as logging
-
from tempest import config
from tempest.lib import auth
from tempest.lib import exceptions as lib_exc
from tempest.lib.services import clients
from tempest.services import object_storage
-from tempest.services import orchestration
CONF = config.CONF
-LOG = logging.getLogger(__name__)
class Manager(clients.ServiceClients):
@@ -52,15 +48,6 @@ class Manager(clients.ServiceClients):
self._set_image_clients()
self._set_network_clients()
- self.orchestration_client = orchestration.OrchestrationClient(
- self.auth_provider,
- CONF.orchestration.catalog_type,
- CONF.orchestration.region or CONF.identity.region,
- endpoint_type=CONF.orchestration.endpoint_type,
- build_interval=CONF.orchestration.build_interval,
- build_timeout=CONF.orchestration.build_timeout,
- **self.default_params)
-
def _set_network_clients(self):
self.network_agents_client = self.network.AgentsClient()
self.network_extensions_client = self.network.ExtensionsClient()
@@ -208,6 +195,7 @@ class Manager(clients.ServiceClients):
self.identity_v3.EndPointsFilterClient(**params_v3)
self.endpoint_groups_client = self.identity_v3.EndPointGroupsClient(
**params_v3)
+ self.catalog_client = self.identity_v3.CatalogClient(**params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding
@@ -229,49 +217,63 @@ class Manager(clients.ServiceClients):
def _set_volume_clients(self):
- self.volume_qos_client = self.volume_v1.QosSpecsClient()
- self.volume_qos_v2_client = self.volume_v2.QosSpecsClient()
- self.volume_services_client = self.volume_v1.ServicesClient()
- self.volume_services_v2_client = self.volume_v2.ServicesClient()
- self.backups_client = self.volume_v1.BackupsClient()
- self.backups_v2_client = self.volume_v2.BackupsClient()
- self.backups_v3_client = self.volume_v3.BackupsClient()
- self.encryption_types_client = self.volume_v1.EncryptionTypesClient()
- self.encryption_types_v2_client = \
- self.volume_v2.EncryptionTypesClient()
- self.snapshot_manage_v2_client = self.volume_v2.SnapshotManageClient()
- self.snapshots_client = self.volume_v1.SnapshotsClient()
- self.snapshots_v2_client = self.volume_v2.SnapshotsClient()
- self.volume_manage_v2_client = self.volume_v2.VolumeManageClient()
- self.volumes_client = self.volume_v1.VolumesClient()
- self.volumes_v2_client = self.volume_v2.VolumesClient()
- self.volumes_v3_client = self.volume_v3.VolumesClient()
- self.volume_v3_messages_client = self.volume_v3.MessagesClient()
- self.volume_v3_versions_client = self.volume_v3.VersionsClient()
- self.volume_types_client = self.volume_v1.TypesClient()
- self.volume_types_v2_client = self.volume_v2.TypesClient()
- self.volume_hosts_client = self.volume_v1.HostsClient()
- self.volume_hosts_v2_client = self.volume_v2.HostsClient()
- self.volume_quotas_client = self.volume_v1.QuotasClient()
- self.volume_quotas_v2_client = self.volume_v2.QuotasClient()
- self.volume_quota_classes_v2_client = \
- self.volume_v2.QuotaClassesClient()
- self.volumes_extension_client = self.volume_v1.ExtensionsClient()
- self.volumes_v2_extension_client = self.volume_v2.ExtensionsClient()
- self.groups_v3_client = self.volume_v3.GroupsClient()
- self.group_types_v3_client = self.volume_v3.GroupTypesClient()
- self.volume_availability_zone_client = \
- self.volume_v1.AvailabilityZoneClient()
- self.volume_v2_availability_zone_client = \
- self.volume_v2.AvailabilityZoneClient()
- self.volume_limits_client = self.volume_v1.LimitsClient()
- self.volume_v2_limits_client = self.volume_v2.LimitsClient()
- self.volume_capabilities_v2_client = \
- self.volume_v2.CapabilitiesClient()
- self.volume_scheduler_stats_v2_client = \
- self.volume_v2.SchedulerStatsClient()
- self.volume_transfers_v2_client = \
- self.volume_v2.TransfersClient()
+ if CONF.volume_feature_enabled.api_v1:
+ self.backups_client = self.volume_v1.BackupsClient()
+ self.encryption_types_client = \
+ self.volume_v1.EncryptionTypesClient()
+ self.snapshots_client = self.volume_v1.SnapshotsClient()
+ self.volume_availability_zone_client = \
+ self.volume_v1.AvailabilityZoneClient()
+ self.volume_hosts_client = self.volume_v1.HostsClient()
+ self.volume_limits_client = self.volume_v1.LimitsClient()
+ self.volume_qos_client = self.volume_v1.QosSpecsClient()
+ self.volume_quotas_client = self.volume_v1.QuotasClient()
+ self.volume_services_client = self.volume_v1.ServicesClient()
+ self.volume_types_client = self.volume_v1.TypesClient()
+ self.volumes_client = self.volume_v1.VolumesClient()
+ self.volumes_extension_client = self.volume_v1.ExtensionsClient()
+
+ if CONF.volume_feature_enabled.api_v2:
+ self.backups_v2_client = self.volume_v2.BackupsClient()
+ self.encryption_types_v2_client = \
+ self.volume_v2.EncryptionTypesClient()
+ self.snapshot_manage_v2_client = \
+ self.volume_v2.SnapshotManageClient()
+ self.snapshots_v2_client = self.volume_v2.SnapshotsClient()
+ self.volume_capabilities_v2_client = \
+ self.volume_v2.CapabilitiesClient()
+ self.volume_manage_v2_client = self.volume_v2.VolumeManageClient()
+ self.volume_qos_v2_client = self.volume_v2.QosSpecsClient()
+ self.volume_services_v2_client = self.volume_v2.ServicesClient()
+ self.volume_types_v2_client = self.volume_v2.TypesClient()
+ self.volume_hosts_v2_client = self.volume_v2.HostsClient()
+ self.volume_quotas_v2_client = self.volume_v2.QuotasClient()
+ self.volume_quota_classes_v2_client = \
+ self.volume_v2.QuotaClassesClient()
+ self.volume_scheduler_stats_v2_client = \
+ self.volume_v2.SchedulerStatsClient()
+ self.volume_transfers_v2_client = \
+ self.volume_v2.TransfersClient()
+ self.volume_v2_availability_zone_client = \
+ self.volume_v2.AvailabilityZoneClient()
+ self.volume_v2_limits_client = self.volume_v2.LimitsClient()
+ self.volumes_v2_client = self.volume_v2.VolumesClient()
+ self.volumes_v2_extension_client = \
+ self.volume_v2.ExtensionsClient()
+
+ # Set default client for users that don't need explicit version
+ self.volumes_client_latest = self.volumes_v2_client
+
+ if CONF.volume_feature_enabled.api_v3:
+ self.backups_v3_client = self.volume_v3.BackupsClient()
+ self.group_types_v3_client = self.volume_v3.GroupTypesClient()
+ self.groups_v3_client = self.volume_v3.GroupsClient()
+ self.volume_v3_messages_client = self.volume_v3.MessagesClient()
+ self.volume_v3_versions_client = self.volume_v3.VersionsClient()
+ self.volumes_v3_client = self.volume_v3.VolumesClient()
+
+ # Set default client for users that don't need explicit version
+ self.volumes_client_latest = self.volumes_v3_client
def _set_object_storage_clients(self):
# NOTE(andreaf) Load configuration from config. Once object storage
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 172d9e156..a76123cdc 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -141,18 +141,10 @@ def get_credential_provider(opts):
admin_creds = credentials_factory.get_credentials(
fill_in=False, identity_version=identity_version, **admin_creds_dict)
return dynamic_creds.DynamicCredentialProvider(
- identity_version=identity_version,
name=opts.tag,
network_resources=network_resources,
- neutron_available=CONF.service_available.neutron,
- create_networks=CONF.auth.create_isolated_networks,
- identity_admin_role=CONF.identity.admin_role,
- identity_admin_domain_scope=CONF.identity.admin_domain_scope,
- project_network_cidr=CONF.network.project_network_cidr,
- project_network_mask_bits=CONF.network.project_network_mask_bits,
- public_network_id=CONF.network.public_network_id,
- admin_creds=admin_creds,
- **credentials_factory.get_dynamic_provider_params())
+ **credentials_factory.get_dynamic_provider_params(
+ identity_version, admin_creds=admin_creds))
def generate_resources(cred_provider, admin):
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index f1c0a3eba..11cd4bb6b 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -213,7 +213,9 @@ class ServerGroupService(ServerService):
class StackService(BaseService):
def __init__(self, manager, **kwargs):
super(StackService, self).__init__(kwargs)
- self.client = manager.orchestration_client
+ params = config.service_client_config('orchestration')
+ self.client = manager.orchestration.OrchestrationClient(
+ manager.auth_provider, **params)
def list(self):
client = self.client
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 0972a3c88..2f4d120fc 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -95,7 +95,7 @@ def _get_api_versions(os, service):
client_dict = {
'nova': os.servers_client,
'keystone': os.identity_client,
- 'cinder': os.volumes_client,
+ 'cinder': os.volumes_client_latest,
}
if service != 'keystone' and service != 'cinder':
# Since keystone and cinder may be listening on a path,
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index e6b46ed1b..449c34389 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -39,19 +39,66 @@ to avoid circular dependencies."""
# Subset of the parameters of credential providers that depend on configuration
-def get_common_provider_params():
+def _get_common_provider_params(identity_version):
+ if identity_version == 'v3':
+ identity_uri = CONF.identity.uri_v3
+ elif identity_version == 'v2':
+ identity_uri = CONF.identity.uri
return {
+ 'identity_version': identity_version,
+ 'identity_uri': identity_uri,
'credentials_domain': CONF.auth.default_credentials_domain_name,
'admin_role': CONF.identity.admin_role
}
-def get_dynamic_provider_params():
- return get_common_provider_params()
+def get_dynamic_provider_params(identity_version, admin_creds=None):
+ """Dynamic provider parameters setup from config
+
+ This helper returns a dict of parameter that can be used to initialise
+ a `DynamicCredentialProvider` according to tempest configuration.
+ Parameters that are not configuration specific (name, network_resources)
+ are not returned.
+
+ :param identity_version: 'v2' or 'v3'
+ :param admin_creds: An object of type `auth.Credentials`. If None, it
+ is built from the configuration file as well.
+ :returns A dict with the parameters
+ """
+ _common_params = _get_common_provider_params(identity_version)
+ admin_creds = admin_creds or get_configured_admin_credentials(
+ fill_in=True, identity_version=identity_version)
+ if identity_version == 'v3':
+ endpoint_type = CONF.identity.v3_endpoint_type
+ elif identity_version == 'v2':
+ endpoint_type = CONF.identity.v2_admin_endpoint_type
+ return dict(_common_params, **dict([
+ ('admin_creds', admin_creds),
+ ('identity_admin_domain_scope', CONF.identity.admin_domain_scope),
+ ('identity_admin_role', CONF.identity.admin_role),
+ ('extra_roles', CONF.auth.tempest_roles),
+ ('neutron_available', CONF.service_available.neutron),
+ ('project_network_cidr', CONF.network.project_network_cidr),
+ ('project_network_mask_bits', CONF.network.project_network_mask_bits),
+ ('public_network_id', CONF.network.public_network_id),
+ ('create_networks', (CONF.auth.create_isolated_networks and not
+ CONF.network.shared_physical_network)),
+ ('resource_prefix', CONF.resources_prefix),
+ ('identity_admin_endpoint_type', endpoint_type)
+ ]))
+
+
+def get_preprov_provider_params(identity_version):
+ """Pre-provisioned provider parameters setup from config
+ This helper returns a dict of parameter that can be used to initialise
+ a `PreProvisionedCredentialProvider` according to tempest configuration.
+ Parameters that are not configuration specific (name) are not returned.
-def get_preprov_provider_params():
- _common_params = get_common_provider_params()
+ :param identity_version: 'v2' or 'v3'
+ :returns A dict with the parameters
+ """
+ _common_params = _get_common_provider_params(identity_version)
reseller_admin_role = CONF.object_storage.reseller_admin_role
return dict(_common_params, **dict([
('accounts_lock_dir', lockutils.get_lock_path(CONF)),
@@ -61,42 +108,40 @@ def get_preprov_provider_params():
]))
-# Return the right implementation of CredentialProvider based on config
-# Dropping interface and password, as they are never used anyways
-# TODO(andreaf) Drop them from the CredentialsProvider interface completely
def get_credentials_provider(name, network_resources=None,
force_tenant_isolation=False,
identity_version=None):
+ """Return the right implementation of CredentialProvider based on config
+
+ This helper returns the right implementation of CredentialProvider based on
+ config and on the value of force_tenant_isolation.
+
+ :param name: When provided, it makes it possible to associate credential
+ artifacts back to the owner (test class).
+ :param network_resources: Dictionary of network resources to be allocated
+ for each test account. Only valid for the dynamic
+ credentials provider.
+ :param force_tenant_isolation: Always return a `DynamicCredentialProvider`,
+ regardless of the configuration.
+ :param identity_version: Use the specified identity API version, regardless
+ of the configuration. Valid values are 'v2', 'v3'.
+ """
# If a test requires a new account to work, it can have it via forcing
# dynamic credentials. A new account will be produced only for that test.
# In case admin credentials are not available for the account creation,
# the test should be skipped else it would fail.
identity_version = identity_version or CONF.identity.auth_version
if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
- admin_creds = get_configured_admin_credentials(
- fill_in=True, identity_version=identity_version)
return dynamic_creds.DynamicCredentialProvider(
name=name,
network_resources=network_resources,
- identity_version=identity_version,
- admin_creds=admin_creds,
- identity_admin_domain_scope=CONF.identity.admin_domain_scope,
- identity_admin_role=CONF.identity.admin_role,
- extra_roles=CONF.auth.tempest_roles,
- neutron_available=CONF.service_available.neutron,
- project_network_cidr=CONF.network.project_network_cidr,
- project_network_mask_bits=CONF.network.project_network_mask_bits,
- public_network_id=CONF.network.public_network_id,
- create_networks=(CONF.auth.create_isolated_networks and not
- CONF.network.shared_physical_network),
- resource_prefix=CONF.resources_prefix,
- **get_dynamic_provider_params())
+ **get_dynamic_provider_params(identity_version))
else:
if CONF.auth.test_accounts_file:
# Most params are not relevant for pre-created accounts
return preprov_creds.PreProvisionedCredentialProvider(
- name=name, identity_version=identity_version,
- **get_preprov_provider_params())
+ name=name,
+ **get_preprov_provider_params(identity_version))
else:
raise exceptions.InvalidConfiguration(
'A valid credential provider is needed')
@@ -115,8 +160,8 @@ def is_admin_available(identity_version):
# Check whether test accounts file has the admin specified or not
elif CONF.auth.test_accounts_file:
check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_admin',
- **get_preprov_provider_params())
+ name='check_admin',
+ **get_preprov_provider_params(identity_version))
if not check_accounts.admin_available():
is_admin = False
else:
@@ -140,8 +185,8 @@ def is_alt_available(identity_version):
# Check whether test accounts file has the admin specified or not
if CONF.auth.test_accounts_file:
check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_alt',
- **get_preprov_provider_params())
+ name='check_alt',
+ **get_preprov_provider_params(identity_version))
else:
raise exceptions.InvalidConfiguration(
'A valid credential provider is needed')
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 88fe26c3c..90e67b4d4 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -12,15 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ipaddress
+
import netaddr
from oslo_log import log as logging
import six
-from tempest import clients
from tempest.lib.common import cred_client
from tempest.lib.common import cred_provider
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
+from tempest.lib.services import clients
LOG = logging.getLogger(__name__)
@@ -33,7 +35,8 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
identity_admin_role='admin', extra_roles=None,
neutron_available=False, create_networks=True,
project_network_cidr=None, project_network_mask_bits=None,
- public_network_id=None, resource_prefix=None):
+ public_network_id=None, resource_prefix=None,
+ identity_admin_endpoint_type='public', identity_uri=None):
"""Creates credentials dynamically for tests
A credential provider that, based on an initial set of
@@ -67,10 +70,14 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
:param project_network_mask_bits: The network mask bits to use for
created project networks
:param public_network_id: The id for the public network to use
+ :param identity_admin_endpoint_type: The endpoint type for identity
+ admin clients. Defaults to public.
+ :param identity_uri: Identity URI of the target cloud
"""
super(DynamicCredentialProvider, self).__init__(
- identity_version=identity_version, admin_role=admin_role,
- name=name, credentials_domain=credentials_domain,
+ identity_version=identity_version, identity_uri=identity_uri,
+ admin_role=admin_role, name=name,
+ credentials_domain=credentials_domain,
network_resources=network_resources)
self.network_resources = network_resources
self._creds = {}
@@ -84,6 +91,7 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.default_admin_creds = admin_creds
self.identity_admin_domain_scope = identity_admin_domain_scope
self.identity_admin_role = identity_admin_role or 'admin'
+ self.identity_admin_endpoint_type = identity_admin_endpoint_type
self.extra_roles = extra_roles or []
(self.identity_admin_client,
self.tenants_admin_client,
@@ -94,7 +102,8 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.routers_admin_client,
self.subnets_admin_client,
self.ports_admin_client,
- self.security_groups_admin_client) = self._get_admin_clients()
+ self.security_groups_admin_client) = self._get_admin_clients(
+ identity_admin_endpoint_type)
# Domain where isolated credentials are provisioned (v3 only).
# Use that of the admin account is None is configured.
self.creds_domain_name = None
@@ -110,32 +119,43 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
self.domains_admin_client,
self.creds_domain_name)
- def _get_admin_clients(self):
+ def _get_admin_clients(self, endpoint_type):
"""Returns a tuple with instances of the following admin clients
(in this order):
identity
network
"""
- os = clients.Manager(self.default_admin_creds)
+ os = clients.ServiceClients(self.default_admin_creds,
+ self.identity_uri)
+ params = {'endpoint_type': endpoint_type}
if self.identity_version == 'v2':
- return (os.identity_client, os.tenants_client, os.users_client,
- os.roles_client, None,
- os.networks_client, os.routers_client, os.subnets_client,
- os.ports_client, os.security_groups_client)
+ return (os.identity_v2.IdentityClient(**params),
+ os.identity_v2.TenantsClient(**params),
+ os.identity_v2.UsersClient(**params),
+ os.identity_v2.RolesClient(**params), None,
+ os.network.NetworksClient(),
+ os.network.RoutersClient(),
+ os.network.SubnetsClient(),
+ os.network.PortsClient(),
+ os.network.SecurityGroupsClient())
else:
# We use a dedicated client manager for identity client in case we
# need a different token scope for them.
scope = 'domain' if self.identity_admin_domain_scope else 'project'
- identity_os = clients.Manager(self.default_admin_creds,
- scope=scope)
- return (identity_os.identity_v3_client,
- identity_os.projects_client,
- identity_os.users_v3_client, identity_os.roles_v3_client,
- identity_os.domains_client,
- os.networks_client, os.routers_client,
- os.subnets_client, os.ports_client,
- os.security_groups_client)
+ identity_os = clients.ServiceClients(self.default_admin_creds,
+ self.identity_uri,
+ scope=scope)
+ return (identity_os.identity_v3.IdentityClient(**params),
+ identity_os.identity_v3.ProjectsClient(**params),
+ identity_os.identity_v3.UsersClient(**params),
+ identity_os.identity_v3.RolesClient(**params),
+ identity_os.identity_v3.DomainsClient(**params),
+ os.network.NetworksClient(),
+ os.network.RoutersClient(),
+ os.network.SubnetsClient(),
+ os.network.PortsClient(),
+ os.network.SecurityGroupsClient())
def _create_creds(self, admin=False, roles=None):
"""Create credentials with random name.
@@ -275,14 +295,16 @@ class DynamicCredentialProvider(cred_provider.CredentialProvider):
name=subnet_name,
tenant_id=tenant_id,
enable_dhcp=self.network_resources['dhcp'],
- ip_version=4)
+ ip_version=(ipaddress.ip_network(
+ six.text_type(subnet_cidr)).version))
else:
resp_body = self.subnets_admin_client.\
create_subnet(network_id=network_id,
cidr=str(subnet_cidr),
name=subnet_name,
tenant_id=tenant_id,
- ip_version=4)
+ ip_version=(ipaddress.ip_network(
+ six.text_type(subnet_cidr)).version))
break
except lib_exc.BadRequest as e:
if 'overlaps with another subnet' not in str(e):
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index 8053cacf3..64cabb766 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -20,12 +20,12 @@ from oslo_log import log as logging
import six
import yaml
-from tempest import clients
from tempest.common import fixed_network
from tempest import exceptions
from tempest.lib import auth
from tempest.lib.common import cred_provider
from tempest.lib import exceptions as lib_exc
+from tempest.lib.services import clients
LOG = logging.getLogger(__name__)
@@ -51,7 +51,7 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
def __init__(self, identity_version, test_accounts_file,
accounts_lock_dir, name=None, credentials_domain=None,
admin_role=None, object_storage_operator_role=None,
- object_storage_reseller_admin_role=None):
+ object_storage_reseller_admin_role=None, identity_uri=None):
"""Credentials provider using pre-provisioned accounts
This credentials provider loads the details of pre-provisioned
@@ -79,10 +79,12 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
(if no domain is configured)
:param object_storage_operator_role: name of the role
:param object_storage_reseller_admin_role: name of the role
+ :param identity_uri: Identity URI of the target cloud
"""
super(PreProvisionedCredentialProvider, self).__init__(
identity_version=identity_version, name=name,
- admin_role=admin_role, credentials_domain=credentials_domain)
+ admin_role=admin_role, credentials_domain=credentials_domain,
+ identity_uri=identity_uri)
self.test_accounts_file = test_accounts_file
if test_accounts_file:
accounts = read_accounts_yaml(self.test_accounts_file)
@@ -341,8 +343,9 @@ class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
auth_url=None, fill_in=False,
identity_version=self.identity_version, **creds_dict)
net_creds = cred_provider.TestResources(credential)
- net_clients = clients.Manager(credentials=credential)
- compute_network_client = net_clients.compute_networks_client
+ net_clients = clients.ServiceClients(credentials=credential,
+ identity_uri=self.identity_uri)
+ compute_network_client = net_clients.compute.NetworksClient()
net_name = self.hash_dict['networks'].get(hash, None)
try:
network = fixed_network.get_network_from_name(
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index 73603967a..2954de005 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -420,8 +420,13 @@ instance_action_events = {
'properties': {
'event': {'type': 'string'},
'start_time': parameter_types.date_time,
- 'finish_time': parameter_types.date_time,
- 'result': {'type': 'string'},
+ # The finish_time, result and optionally traceback are all
+ # possibly None (null) until the event is actually finished.
+ # The traceback would only be set if there was an error, but
+ # when the event is complete both finish_time and result will
+ # be set.
+ 'finish_time': parameter_types.date_time_or_null,
+ 'result': {'type': ['string', 'null']},
'traceback': {'type': ['string', 'null']}
},
'additionalProperties': False,
diff --git a/tempest/lib/api_schema/response/compute/v2_1/services.py b/tempest/lib/api_schema/response/compute/v2_1/services.py
index 6949f8626..3b58ece48 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/services.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/services.py
@@ -65,3 +65,25 @@ enable_disable_service = {
'required': ['service']
}
}
+
+disable_log_reason = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'service': {
+ 'type': 'object',
+ 'properties': {
+ 'disabled_reason': {'type': 'string'},
+ 'binary': {'type': 'string'},
+ 'host': {'type': 'string'},
+ 'status': {'type': 'string'}
+ },
+ 'additionalProperties': False,
+ 'required': ['disabled_reason', 'binary', 'host', 'status']
+ }
+ },
+ 'additionalProperties': False,
+ 'required': ['service']
+ }
+}
diff --git a/tempest/lib/api_schema/response/compute/v2_11/__init__.py b/tempest/lib/api_schema/response/compute/v2_11/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_11/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_11/services.py b/tempest/lib/api_schema/response/compute/v2_11/services.py
new file mode 100644
index 000000000..18b833bd2
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_11/services.py
@@ -0,0 +1,46 @@
+# Copyright 2017 AT&T Corporation.
+# 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.
+
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import services
+
+
+list_services = copy.deepcopy(services.list_services)
+list_services['response_body']['properties']['services']['items'][
+ 'properties']['forced_down'] = {'type': 'boolean'}
+list_services['response_body']['properties']['services']['items'][
+ 'required'].append('forced_down')
+
+update_forced_down = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'service': {
+ 'type': 'object',
+ 'properties': {
+ 'binary': {'type': 'string'},
+ 'host': {'type': 'string'},
+ 'forced_down': {'type': 'boolean'}
+ },
+ 'additionalProperties': False,
+ 'required': ['binary', 'host', 'forced_down']
+ }
+ },
+ 'additionalProperties': False,
+ 'required': ['service']
+ }
+}
diff --git a/tempest/lib/common/cred_provider.py b/tempest/lib/common/cred_provider.py
index 1b450ab9f..42ed41b39 100644
--- a/tempest/lib/common/cred_provider.py
+++ b/tempest/lib/common/cred_provider.py
@@ -22,8 +22,9 @@ from tempest.lib import exceptions
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
- def __init__(self, identity_version, name=None, network_resources=None,
- credentials_domain=None, admin_role=None):
+ def __init__(self, identity_version, name=None,
+ network_resources=None, credentials_domain=None,
+ admin_role=None, identity_uri=None):
"""A CredentialProvider supplies credentials to test classes.
:param identity_version: Identity version of the credentials provided
@@ -33,8 +34,11 @@ class CredentialProvider(object):
credentials
:param credentials_domain: Domain credentials belong to
:param admin_role: Name of the role of the admin account
+ :param identity_uri: Identity URI of the target cloud. This *must* be
+ specified for anything to work.
"""
self.identity_version = identity_version
+ self.identity_uri = identity_uri
self.name = name or "test_creds"
self.network_resources = network_resources
self.credentials_domain = credentials_domain or 'Default'
diff --git a/tempest/lib/services/compute/services_client.py b/tempest/lib/services/compute/services_client.py
index 77ac82fee..857c435a6 100644
--- a/tempest/lib/services/compute/services_client.py
+++ b/tempest/lib/services/compute/services_client.py
@@ -18,12 +18,18 @@ from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
from tempest.lib.api_schema.response.compute.v2_1 import services as schema
+from tempest.lib.api_schema.response.compute.v2_11 import services \
+ as schemav211
from tempest.lib.common import rest_client
from tempest.lib.services.compute import base_compute_client
class ServicesClient(base_compute_client.BaseComputeClient):
+ schema_versions_info = [
+ {'min': None, 'max': '2.10', 'schema': schema},
+ {'min': '2.11', 'max': None, 'schema': schemav211}]
+
def list_services(self, **params):
"""Lists all running Compute services for a tenant.
@@ -37,7 +43,8 @@ class ServicesClient(base_compute_client.BaseComputeClient):
resp, body = self.get(url)
body = json.loads(body)
- self.validate_response(schema.list_services, resp, body)
+ _schema = self.get_schema(self.schema_versions_info)
+ self.validate_response(_schema.list_services, resp, body)
return rest_client.ResponseBody(resp, body)
def enable_service(self, **kwargs):
@@ -65,3 +72,31 @@ class ServicesClient(base_compute_client.BaseComputeClient):
body = json.loads(body)
self.validate_response(schema.enable_disable_service, resp, body)
return rest_client.ResponseBody(resp, body)
+
+ def disable_log_reason(self, **kwargs):
+ """Disables scheduling for a Compute service and logs reason.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/compute/#log-disabled-compute-service-information
+ """
+ post_body = json.dumps(kwargs)
+ resp, body = self.put('os-services/disable-log-reason', post_body)
+ body = json.loads(body)
+ self.validate_response(schema.disable_log_reason, resp, body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_forced_down(self, **kwargs):
+ """Set or unset ``forced_down`` flag for the service.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/compute/#update-forced-down
+ """
+ post_body = json.dumps(kwargs)
+ resp, body = self.put('os-services/force-down', post_body)
+ body = json.loads(body)
+ # NOTE: Use schemav211.update_forced_down directly because there is no
+ # update_forced_down schema for <2.11.
+ self.validate_response(schemav211.update_forced_down, resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index e271a58e1..a539d08c0 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations under
# the License.
+from tempest.lib.services.identity.v3.catalog_client import \
+ CatalogClient
from tempest.lib.services.identity.v3.credentials_client import \
CredentialsClient
from tempest.lib.services.identity.v3.domain_configuration_client \
@@ -42,10 +44,11 @@ from tempest.lib.services.identity.v3.trusts_client import TrustsClient
from tempest.lib.services.identity.v3.users_client import UsersClient
from tempest.lib.services.identity.v3.versions_client import VersionsClient
-__all__ = ['CredentialsClient', 'DomainsClient', 'DomainConfigurationClient',
- 'EndPointGroupsClient', 'EndPointsClient', 'EndPointsFilterClient',
- 'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
- 'OAUTHConsumerClient', 'OAUTHTokenClient', 'PoliciesClient',
- 'ProjectsClient', 'RegionsClient', 'RoleAssignmentsClient',
- 'RolesClient', 'ServicesClient', 'V3TokenClient', 'TrustsClient',
- 'UsersClient', 'VersionsClient']
+__all__ = ['CatalogClient', 'CredentialsClient', 'DomainsClient',
+ 'DomainConfigurationClient', 'EndPointGroupsClient',
+ 'EndPointsClient', 'EndPointsFilterClient', 'GroupsClient',
+ 'IdentityClient', 'InheritedRolesClient', 'OAUTHConsumerClient',
+ 'OAUTHTokenClient', 'PoliciesClient', 'ProjectsClient',
+ 'RegionsClient', 'RoleAssignmentsClient', 'RolesClient',
+ 'ServicesClient', 'V3TokenClient', 'TrustsClient', 'UsersClient',
+ 'VersionsClient']
diff --git a/tempest/lib/services/identity/v3/catalog_client.py b/tempest/lib/services/identity/v3/catalog_client.py
new file mode 100644
index 000000000..0f9d48543
--- /dev/null
+++ b/tempest/lib/services/identity/v3/catalog_client.py
@@ -0,0 +1,30 @@
+# 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.
+
+"""
+https://developer.openstack.org/api-ref/identity/v3/index.html#\
+get-service-catalog
+"""
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class CatalogClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def show_catalog(self):
+ resp, body = self.get('auth/catalog')
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/endpoint_groups_client.py b/tempest/lib/services/identity/v3/endpoint_groups_client.py
index 723aeaa09..ce9938953 100644
--- a/tempest/lib/services/identity/v3/endpoint_groups_client.py
+++ b/tempest/lib/services/identity/v3/endpoint_groups_client.py
@@ -1,78 +1,78 @@
-# Copyright 2017 AT&T Corporation.
-# 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 oslo_serialization import jsonutils as json
-
-from tempest.lib.common import rest_client
-
-
-class EndPointGroupsClient(rest_client.RestClient):
- api_version = "v3"
-
- def create_endpoint_group(self, **kwargs):
- """Create endpoint group.
-
- For a full list of available parameters, please refer to the
- official API reference:
- https://developer.openstack.org/api-ref/identity/v3-ext/#create-endpoint-group
- """
- post_body = json.dumps({'endpoint_group': kwargs})
- resp, body = self.post('OS-EP-FILTER/endpoint_groups', post_body)
- self.expected_success(201, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def update_endpoint_group(self, endpoint_group_id, **kwargs):
- """Update endpoint group.
-
- For a full list of available parameters, please refer to the
- official API reference:
- https://developer.openstack.org/api-ref/identity/v3-ext/#update-endpoint-group
- """
- post_body = json.dumps({'endpoint_group': kwargs})
- resp, body = self.patch(
- 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id, post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def delete_endpoint_group(self, endpoint_group_id):
- """Delete endpoint group."""
- resp_header, resp_body = self.delete(
- 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
- self.expected_success(204, resp_header.status)
- return rest_client.ResponseBody(resp_header, resp_body)
-
- def show_endpoint_group(self, endpoint_group_id):
- """Get endpoint group."""
- resp_header, resp_body = self.get(
- 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
- self.expected_success(200, resp_header.status)
- resp_body = json.loads(resp_body)
- return rest_client.ResponseBody(resp_header, resp_body)
-
- def check_endpoint_group(self, endpoint_group_id):
- """Check endpoint group."""
- resp_header, resp_body = self.head(
- 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
- self.expected_success(200, resp_header.status)
- return rest_client.ResponseBody(resp_header, resp_body)
-
- def list_endpoint_groups(self):
- """Get endpoint groups."""
- resp_header, resp_body = self.get('OS-EP-FILTER/endpoint_groups')
- self.expected_success(200, resp_header.status)
- resp_body = json.loads(resp_body)
- return rest_client.ResponseBody(resp_header, resp_body)
+# Copyright 2017 AT&T Corporation.
+# 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 oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class EndPointGroupsClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_endpoint_group(self, **kwargs):
+ """Create endpoint group.
+
+ For a full list of available parameters, please refer to the
+ official API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/#create-endpoint-group
+ """
+ post_body = json.dumps({'endpoint_group': kwargs})
+ resp, body = self.post('OS-EP-FILTER/endpoint_groups', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_endpoint_group(self, endpoint_group_id, **kwargs):
+ """Update endpoint group.
+
+ For a full list of available parameters, please refer to the
+ official API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/#update-endpoint-group
+ """
+ post_body = json.dumps({'endpoint_group': kwargs})
+ resp, body = self.patch(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_endpoint_group(self, endpoint_group_id):
+ """Delete endpoint group."""
+ resp_header, resp_body = self.delete(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(204, resp_header.status)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def show_endpoint_group(self, endpoint_group_id):
+ """Get endpoint group."""
+ resp_header, resp_body = self.get(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(200, resp_header.status)
+ resp_body = json.loads(resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def check_endpoint_group(self, endpoint_group_id):
+ """Check endpoint group."""
+ resp_header, resp_body = self.head(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(200, resp_header.status)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def list_endpoint_groups(self):
+ """Get endpoint groups."""
+ resp_header, resp_body = self.get('OS-EP-FILTER/endpoint_groups')
+ self.expected_success(200, resp_header.status)
+ resp_body = json.loads(resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
diff --git a/tempest/lib/services/identity/v3/identity_client.py b/tempest/lib/services/identity/v3/identity_client.py
index 755c14b2c..2512a3edc 100644
--- a/tempest/lib/services/identity/v3/identity_client.py
+++ b/tempest/lib/services/identity/v3/identity_client.py
@@ -44,6 +44,13 @@ class IdentityClient(rest_client.RestClient):
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
+ def check_token_existence(self, resp_token):
+ """Validates a token."""
+ headers = {'X-Subject-Token': resp_token}
+ resp, body = self.head("auth/tokens", headers=headers)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
def list_auth_projects(self):
"""Get available project scopes."""
resp, body = self.get("auth/projects")
diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py
index a44ed0b74..830fb82fe 100644
--- a/tempest/lib/services/volume/v2/backups_client.py
+++ b/tempest/lib/services/volume/v2/backups_client.py
@@ -14,6 +14,7 @@
# under the License.
from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
@@ -64,11 +65,19 @@ class BackupsClient(base_client.BaseClient):
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
- def list_backups(self, detail=False):
- """Information for all the tenant's backups."""
+ def list_backups(self, detail=False, **params):
+ """List all the tenant's backups.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-backups
+ http://developer.openstack.org/api-ref/block-storage/v2/#list-backups-with-details
+ """
url = "backups"
if detail:
url += "/detail"
+ if params:
+ url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index aecb3741e..9b8c7a01f 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -238,9 +238,26 @@ class ScenarioTest(tempest.test.BaseTestCase):
volume = self.volumes_client.show_volume(volume['id'])['volume']
return volume
+ def create_volume_snapshot(self, volume_id, name=None, description=None,
+ metadata=None, force=False):
+ name = name or data_utils.rand_name(
+ self.__class__.__name__ + '-snapshot')
+ snapshot = self.snapshots_client.create_snapshot(
+ volume_id=volume_id,
+ force=force,
+ display_name=name,
+ description=description,
+ metadata=metadata)['snapshot']
+ self.addCleanup(self.snapshots_client.wait_for_resource_deletion,
+ snapshot['id'])
+ self.addCleanup(self.snapshots_client.delete_snapshot, snapshot['id'])
+ waiters.wait_for_volume_resource_status(self.snapshots_client,
+ snapshot['id'], 'available')
+ return snapshot
+
def create_volume_type(self, client=None, name=None, backend_name=None):
if not client:
- client = self.admin_volume_types_client
+ client = self.os_admin.volume_types_v2_client
if not name:
class_name = self.__class__.__name__
name = data_utils.rand_name(class_name + '-volume-type')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index debd664f8..363264859 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -16,9 +16,7 @@
from oslo_log import log as logging
import testtools
-from tempest.common import waiters
from tempest import config
-from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -57,20 +55,6 @@ class TestStampPattern(manager.ScenarioTest):
if not CONF.volume_feature_enabled.snapshot:
raise cls.skipException("Cinder volume snapshots are disabled")
- def _create_volume_snapshot(self, volume):
- snapshot_name = data_utils.rand_name('scenario-snapshot')
- snapshot = self.snapshots_client.create_snapshot(
- volume_id=volume['id'], display_name=snapshot_name)['snapshot']
- self.addCleanup(self.snapshots_client.wait_for_resource_deletion,
- snapshot['id'])
- self.addCleanup(self.snapshots_client.delete_snapshot, snapshot['id'])
- waiters.wait_for_volume_resource_status(self.volumes_client,
- volume['id'], 'available')
- waiters.wait_for_volume_resource_status(self.snapshots_client,
- snapshot['id'], 'available')
- self.assertEqual(snapshot_name, snapshot['name'])
- return snapshot
-
def _wait_for_volume_available_on_the_system(self, ip_address,
private_key):
ssh = self.get_remote_client(ip_address, private_key=private_key)
@@ -116,7 +100,7 @@ class TestStampPattern(manager.ScenarioTest):
self.nova_volume_detach(server, volume)
# snapshot the volume
- volume_snapshot = self._create_volume_snapshot(volume)
+ volume_snapshot = self.create_volume_snapshot(volume['id'])
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 96d047469..b6f3b38cf 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -69,21 +69,6 @@ class TestVolumeBootPattern(manager.EncryptionScenarioTest):
return self.create_server(image_id='', **create_kwargs)
- def _create_snapshot_from_volume(self, vol_id):
- snap_name = data_utils.rand_name(
- self.__class__.__name__ + '-snapshot')
- snap = self.snapshots_client.create_snapshot(
- volume_id=vol_id,
- force=True,
- display_name=snap_name)['snapshot']
- self.addCleanup(
- self.snapshots_client.wait_for_resource_deletion, snap['id'])
- self.addCleanup(self.snapshots_client.delete_snapshot, snap['id'])
- waiters.wait_for_volume_resource_status(self.snapshots_client,
- snap['id'], 'available')
- self.assertEqual(snap_name, snap['name'])
- return snap
-
def _delete_server(self, server):
self.servers_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client, server['id'])
@@ -147,7 +132,7 @@ class TestVolumeBootPattern(manager.EncryptionScenarioTest):
# snapshot a volume
LOG.info("Creating snapshot from volume: %s", volume_origin['id'])
- snapshot = self._create_snapshot_from_volume(volume_origin['id'])
+ snapshot = self.create_volume_snapshot(volume_origin['id'], force=True)
# create a 3rd instance from snapshot
LOG.info("Creating third instance from snapshot: %s", snapshot['id'])
@@ -177,7 +162,7 @@ class TestVolumeBootPattern(manager.EncryptionScenarioTest):
boot_volume = self._create_volume_from_image()
# Create a snapshot
- boot_snapshot = self._create_snapshot_from_volume(boot_volume['id'])
+ boot_snapshot = self.create_volume_snapshot(boot_volume['id'])
# Create a server from a volume snapshot
server = self._boot_instance_from_resource(
@@ -229,9 +214,8 @@ class TestVolumeBootPattern(manager.EncryptionScenarioTest):
self._delete_server(instance)
@decorators.idempotent_id('cb78919a-e553-4bab-b73b-10cf4d2eb125')
- @testtools.skipIf(CONF.volume.storage_protocol.lower() in ['ceph', 'nfs'],
- 'Currently, {} does not support volume encryption'
- .format(CONF.volume.storage_protocol))
+ @testtools.skipUnless(CONF.compute_feature_enabled.attach_encrypted_volume,
+ 'Encrypted volume attach is not supported')
@test.services('compute', 'volume')
def test_boot_server_from_encrypted_volume_luks(self):
# Create an encrypted volume
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 81b71b19c..5667fbb74 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -40,7 +40,6 @@ class TestVolumeMigrateRetypeAttached(manager.ScenarioTest):
@classmethod
def setup_clients(cls):
super(TestVolumeMigrateRetypeAttached, cls).setup_clients()
- cls.admin_volume_types_client = cls.os_admin.volume_types_v2_client
cls.admin_volumes_client = cls.os_admin.volumes_v2_client
@classmethod
diff --git a/tempest/services/object_storage/bulk_middleware_client.py b/tempest/services/object_storage/bulk_middleware_client.py
index c194ea909..83d2d80eb 100644
--- a/tempest/services/object_storage/bulk_middleware_client.py
+++ b/tempest/services/object_storage/bulk_middleware_client.py
@@ -24,7 +24,7 @@ class BulkMiddlewareClient(rest_client.RestClient):
To extract containers and objects on Swift cluster from
uploaded archived file. For More information please check:
- http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+ https://docs.openstack.org/swift/latest/middleware.html#module-swift.common.middleware.bulk
"""
url = '%s?extract-archive=%s' % (upload_path, archive_file_format)
if headers is None:
@@ -37,7 +37,7 @@ class BulkMiddlewareClient(rest_client.RestClient):
"""Delete multiple objects or containers from their account.
For More information please check:
- http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+ https://docs.openstack.org/swift/latest/middleware.html#module-swift.common.middleware.bulk
"""
url = '?bulk-delete'
@@ -51,7 +51,7 @@ class BulkMiddlewareClient(rest_client.RestClient):
"""Delete multiple objects or containers with POST request.
For More information please check:
- http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+ https://docs.openstack.org/swift/latest/middleware.html#module-swift.common.middleware.bulk
"""
url = '?bulk-delete'
diff --git a/tempest/test.py b/tempest/test.py
index a81b5d7e0..fc846ffab 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -63,7 +63,14 @@ def get_service_list():
'compute': CONF.service_available.nova,
'image': CONF.service_available.glance,
'volume': CONF.service_available.cinder,
+ # NOTE(masayukig): We have two network services which are neutron and
+ # nova-network. And we have no way to know whether nova-network is
+ # available or not. After the pending removal of nova-network from
+ # nova, we can treat the network/neutron case in the same manner as
+ # the other services.
'network': True,
+ # NOTE(masayukig): Tempest tests always require the identity service.
+ # So we should set this True here.
'identity': True,
'object_storage': CONF.service_available.swift,
}
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index 6773b2f39..248cfb0e9 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -20,7 +20,6 @@ from tempest.cmd import account_generator
from tempest import config
from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import fake_identity
class FakeOpts(object):
@@ -85,14 +84,10 @@ class MockHelpersMixin(object):
class TestAccountGeneratorV2(base.TestCase, MockHelpersMixin):
identity_version = 2
- identity_response = fake_identity._fake_v2_response
def setUp(self):
super(TestAccountGeneratorV2, self).setUp()
self.mock_config_and_opts(self.identity_version)
- self.useFixture(fixtures.MockPatch(
- 'tempest.lib.auth.AuthProvider.set_auth',
- return_value=self.identity_response))
def test_get_credential_provider(self):
cp = account_generator.get_credential_provider(self.opts)
@@ -115,7 +110,6 @@ class TestAccountGeneratorV2(base.TestCase, MockHelpersMixin):
class TestAccountGeneratorV3(TestAccountGeneratorV2):
identity_version = 3
- identity_response = fake_identity._fake_v3_response
def setUp(self):
super(TestAccountGeneratorV3, self).setUp()
@@ -145,16 +139,12 @@ class TestAccountGeneratorV3(TestAccountGeneratorV2):
class TestGenerateResourcesV2(base.TestCase, MockHelpersMixin):
identity_version = 2
- identity_response = fake_identity._fake_v2_response
cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
def setUp(self):
super(TestGenerateResourcesV2, self).setUp()
self.mock_config_and_opts(self.identity_version)
- self.useFixture(fixtures.MockPatch(
- 'tempest.lib.auth.AuthProvider.set_auth',
- return_value=self.identity_response))
self.cred_provider = account_generator.get_credential_provider(
self.opts)
self.mock_resource_creation()
@@ -244,7 +234,6 @@ class TestGenerateResourcesV2(base.TestCase, MockHelpersMixin):
class TestGenerateResourcesV3(TestGenerateResourcesV2):
identity_version = 3
- identity_response = fake_identity._fake_v3_response
cred_client = 'tempest.lib.common.cred_client.V3CredsClient'
def setUp(self):
@@ -255,7 +244,6 @@ class TestGenerateResourcesV3(TestGenerateResourcesV2):
class TestDumpAccountsV2(base.TestCase, MockHelpersMixin):
identity_version = 2
- identity_response = fake_identity._fake_v2_response
cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
domain_is_in = False
@@ -263,9 +251,6 @@ class TestDumpAccountsV2(base.TestCase, MockHelpersMixin):
def setUp(self):
super(TestDumpAccountsV2, self).setUp()
self.mock_config_and_opts(self.identity_version)
- self.useFixture(fixtures.MockPatch(
- 'tempest.lib.auth.AuthProvider.set_auth',
- return_value=self.identity_response))
self.cred_provider = account_generator.get_credential_provider(
self.opts)
self.mock_resource_creation()
@@ -337,7 +322,6 @@ class TestDumpAccountsV2(base.TestCase, MockHelpersMixin):
class TestDumpAccountsV3(TestDumpAccountsV2):
identity_version = 3
- identity_response = fake_identity._fake_v3_response
cred_client = 'tempest.lib.common.cred_client.V3CredsClient'
domain_is_in = True
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index c73961930..cf131eb79 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -46,7 +46,8 @@ class TestDynamicCredentialProvider(base.TestCase):
fixed_params = {'name': 'test class',
'identity_version': 'v2',
- 'admin_role': 'admin'}
+ 'admin_role': 'admin',
+ 'identity_uri': 'fake_uri'}
token_client = v2_token_client
iden_client = v2_iden_client
@@ -619,7 +620,8 @@ class TestDynamicCredentialProviderV3(TestDynamicCredentialProvider):
fixed_params = {'name': 'test class',
'identity_version': 'v3',
- 'admin_role': 'admin'}
+ 'admin_role': 'admin',
+ 'identity_uri': 'fake_uri'}
token_client = v3_token_client
iden_client = v3_iden_client
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index 414b1064f..d894c5ed5 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -38,6 +38,7 @@ class TestPreProvisionedCredentials(base.TestCase):
fixed_params = {'name': 'test class',
'identity_version': 'v2',
+ 'identity_uri': 'fake_uri',
'test_accounts_file': 'fake_accounts_file',
'accounts_lock_dir': 'fake_locks_dir',
'admin_role': 'admin',
@@ -91,6 +92,9 @@ class TestPreProvisionedCredentials(base.TestCase):
return_value=self.test_accounts))
self.useFixture(fixtures.MockPatch(
'os.path.isfile', return_value=True))
+ # NOTE(andreaf) Ensure config is loaded so service clients are
+ # registered in the registry before tests
+ config.service_client_config()
def tearDown(self):
super(TestPreProvisionedCredentials, self).tearDown()
@@ -436,6 +440,7 @@ class TestPreProvisionedCredentialsV3(TestPreProvisionedCredentials):
fixed_params = {'name': 'test class',
'identity_version': 'v3',
+ 'identity_uri': 'fake_uri',
'test_accounts_file': 'fake_accounts_file',
'accounts_lock_dir': 'fake_locks_dir_v3',
'admin_role': 'admin',
diff --git a/tempest/tests/lib/services/compute/test_services_client.py b/tempest/tests/lib/services/compute/test_services_client.py
index 41da39ce7..2dd981c00 100644
--- a/tempest/tests/lib/services/compute/test_services_client.py
+++ b/tempest/tests/lib/services/compute/test_services_client.py
@@ -14,6 +14,9 @@
import copy
+import mock
+
+from tempest.lib.services.compute import base_compute_client
from tempest.lib.services.compute import services_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
@@ -44,11 +47,21 @@ class TestServicesClient(base.BaseServiceTest):
}
}
+ FAKE_UPDATE_FORCED_DOWN = {
+ "service":
+ {
+ "forced_down": True,
+ "binary": "nova-conductor",
+ "host": "controller"
+ }
+ }
+
def setUp(self):
super(TestServicesClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = services_client.ServicesClient(
fake_auth, 'compute', 'regionOne')
+ self.addCleanup(mock.patch.stopall)
def test_list_services_with_str_body(self):
self.check_service_client_function(
@@ -68,7 +81,7 @@ class TestServicesClient(base.BaseServiceTest):
'tempest.lib.common.rest_client.RestClient.put',
self.FAKE_SERVICE,
bytes_body,
- host_name="nova-conductor", binary="controller")
+ host="nova-conductor", binary="controller")
def test_enable_service_with_str_body(self):
self._test_enable_service()
@@ -85,10 +98,49 @@ class TestServicesClient(base.BaseServiceTest):
'tempest.lib.common.rest_client.RestClient.put',
fake_service,
bytes_body,
- host_name="nova-conductor", binary="controller")
+ host="nova-conductor", binary="controller")
def test_disable_service_with_str_body(self):
self._test_disable_service()
def test_disable_service_with_bytes_body(self):
self._test_disable_service(bytes_body=True)
+
+ def _test_log_reason_disabled_service(self, bytes_body=False):
+ resp_body = copy.deepcopy(self.FAKE_SERVICE)
+ resp_body['service']['disabled_reason'] = 'test reason'
+
+ self.check_service_client_function(
+ self.client.disable_log_reason,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ resp_body,
+ bytes_body,
+ host="nova-conductor",
+ binary="controller",
+ disabled_reason='test reason')
+
+ def test_log_reason_disabled_service_with_str_body(self):
+ self._test_log_reason_disabled_service()
+
+ def test_log_reason_disabled_service_with_bytes_body(self):
+ self._test_log_reason_disabled_service(bytes_body=True)
+
+ def _test_update_forced_down(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_forced_down,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_UPDATE_FORCED_DOWN,
+ bytes_body,
+ host="nova-conductor",
+ binary="controller",
+ forced_down=True)
+
+ @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+ new_callable=mock.PropertyMock(return_value='2.11'))
+ def test_update_forced_down_with_str_body(self, _):
+ self._test_update_forced_down()
+
+ @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+ new_callable=mock.PropertyMock(return_value='2.11'))
+ def test_update_forced_down_with_bytes_body(self, _):
+ self._test_update_forced_down(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_catalog_client.py b/tempest/tests/lib/services/identity/v3/test_catalog_client.py
new file mode 100644
index 000000000..0ac8fe426
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_catalog_client.py
@@ -0,0 +1,86 @@
+# 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.identity.v3 import catalog_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestCatalogClient(base.BaseServiceTest):
+ FAKE_CATALOG_INFO = {
+ 'catalog': [
+ {
+ 'endpoints': [
+ {
+ 'id': '39dc322ce86c4111b4f06c2eeae0841b',
+ 'interface': 'public',
+ 'region': 'RegionOne',
+ 'url': 'http://localhost:5000'
+ },
+ ],
+ 'id': 'ac58672276f848a7b1727850b3ebe826',
+ 'type': 'compute',
+ 'name': 'nova'
+ },
+ {
+ 'endpoints': [
+ {
+ 'id': '39dc322ce86c4111b4f06c2eeae0841b',
+ 'interface': 'public',
+ 'region': 'RegionOne',
+ 'url': 'http://localhost:5000'
+ },
+ ],
+ 'id': 'b7c5ed2b486a46dbb4c221499d22991c',
+ 'type': 'image',
+ 'name': 'glance'
+ },
+ {
+ 'endpoints': [
+ {
+ 'id': '39dc322ce86c4111b4f06c2eeae0841b',
+ 'interface': 'public',
+ 'region': 'RegionOne',
+ 'url': 'http://localhost:5000'
+ },
+ ],
+ 'id': '4363ae44bdf34a3981fde3b823cb9aa2',
+ 'type': 'identity',
+ 'name': 'keystone'
+ }
+
+ ],
+ 'links': {
+ 'self': 'http://localhost/identity/v3/catalog',
+ 'previous': None,
+ 'next': None
+ }
+ }
+
+ def setUp(self):
+ super(TestCatalogClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = catalog_client.CatalogClient(fake_auth, 'identity',
+ 'RegionOne')
+
+ def test_show_catalog_with_bytes_body(self):
+ self._test_show_catalog(bytes_body=True)
+
+ def test_show_catalog_with_str_body(self):
+ self._test_show_catalog()
+
+ def _test_show_catalog(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_catalog,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_CATALOG_INFO,
+ bytes_body)
diff --git a/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py b/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py
index 8b034e6d0..c724f0a33 100644
--- a/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py
@@ -1,162 +1,162 @@
-# Copyright 2017 AT&T Corporation.
-# 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.lib.services.identity.v3 import endpoint_groups_client
-from tempest.tests.lib import fake_auth_provider
-from tempest.tests.lib.services import base
-
-
-class TestEndPointGroupsClient(base.BaseServiceTest):
- FAKE_CREATE_ENDPOINT_GROUP = {
- "endpoint_group": {
- "id": 1,
- "name": "FAKE_ENDPOINT_GROUP",
- "description": "FAKE SERVICE ENDPOINT GROUP",
- "filters": {
- "service_id": 1
- }
- }
- }
-
- FAKE_ENDPOINT_GROUP_INFO = {
- "endpoint_group": {
- "id": 1,
- "name": "FAKE_ENDPOINT_GROUP",
- "description": "FAKE SERVICE ENDPOINT GROUP",
- "links": {
- "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
- "endpoint_groups/1"
- },
- "filters": {
- "service_id": 1
- }
- }
- }
-
- FAKE_LIST_ENDPOINT_GROUPS = {
- "endpoint_groups": [
- {
- "id": 1,
- "name": "SERVICE_GROUP1",
- "description": "FAKE SERVICE ENDPOINT GROUP",
- "links": {
- "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
- "endpoint_groups/1"
- },
- "filters": {
- "service_id": 1
- }
- },
- {
- "id": 2,
- "name": "SERVICE_GROUP2",
- "description": "FAKE SERVICE ENDPOINT GROUP",
- "links": {
- "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
- "endpoint_groups/2"
- },
- "filters": {
- "service_id": 2
- }
- }
- ]
- }
-
- def setUp(self):
- super(TestEndPointGroupsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = endpoint_groups_client.EndPointGroupsClient(
- fake_auth, 'identity', 'regionOne')
-
- def _test_create_endpoint_group(self, bytes_body=False):
- self.check_service_client_function(
- self.client.create_endpoint_group,
- 'tempest.lib.common.rest_client.RestClient.post',
- self.FAKE_CREATE_ENDPOINT_GROUP,
- bytes_body,
- status=201,
- name="FAKE_ENDPOINT_GROUP",
- filters={'service_id': "1"})
-
- def _test_show_endpoint_group(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_endpoint_group,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_ENDPOINT_GROUP_INFO,
- bytes_body,
- endpoint_group_id="1")
-
- def _test_check_endpoint_group(self, bytes_body=False):
- self.check_service_client_function(
- self.client.check_endpoint_group,
- 'tempest.lib.common.rest_client.RestClient.head',
- {},
- bytes_body,
- status=200,
- endpoint_group_id="1")
-
- def _test_update_endpoint_group(self, bytes_body=False):
- self.check_service_client_function(
- self.client.update_endpoint_group,
- 'tempest.lib.common.rest_client.RestClient.patch',
- self.FAKE_ENDPOINT_GROUP_INFO,
- bytes_body,
- endpoint_group_id="1",
- name="NewName")
-
- def _test_list_endpoint_groups(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_endpoint_groups,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_LIST_ENDPOINT_GROUPS,
- bytes_body)
-
- def test_create_endpoint_group_with_str_body(self):
- self._test_create_endpoint_group()
-
- def test_create_endpoint_group_with_bytes_body(self):
- self._test_create_endpoint_group(bytes_body=True)
-
- def test_show_endpoint_group_with_str_body(self):
- self._test_show_endpoint_group()
-
- def test_show_endpoint_group_with_bytes_body(self):
- self._test_show_endpoint_group(bytes_body=True)
-
- def test_check_endpoint_group_with_str_body(self):
- self._test_check_endpoint_group()
-
- def test_check_endpoint_group_with_bytes_body(self):
- self._test_check_endpoint_group(bytes_body=True)
-
- def test_list_endpoint_groups_with_str_body(self):
- self._test_list_endpoint_groups()
-
- def test_list_endpoint_groups_with_bytes_body(self):
- self._test_list_endpoint_groups(bytes_body=True)
-
- def test_update_endpoint_group_with_str_body(self):
- self._test_update_endpoint_group()
-
- def test_update_endpoint_group_with_bytes_body(self):
- self._test_update_endpoint_group(bytes_body=True)
-
- def test_delete_endpoint_group(self):
- self.check_service_client_function(
- self.client.delete_endpoint_group,
- 'tempest.lib.common.rest_client.RestClient.delete',
- {},
- endpoint_group_id="1",
- status=204)
+# Copyright 2017 AT&T Corporation.
+# 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.lib.services.identity.v3 import endpoint_groups_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestEndPointGroupsClient(base.BaseServiceTest):
+ FAKE_CREATE_ENDPOINT_GROUP = {
+ "endpoint_group": {
+ "id": 1,
+ "name": "FAKE_ENDPOINT_GROUP",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "filters": {
+ "service_id": 1
+ }
+ }
+ }
+
+ FAKE_ENDPOINT_GROUP_INFO = {
+ "endpoint_group": {
+ "id": 1,
+ "name": "FAKE_ENDPOINT_GROUP",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/1"
+ },
+ "filters": {
+ "service_id": 1
+ }
+ }
+ }
+
+ FAKE_LIST_ENDPOINT_GROUPS = {
+ "endpoint_groups": [
+ {
+ "id": 1,
+ "name": "SERVICE_GROUP1",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/1"
+ },
+ "filters": {
+ "service_id": 1
+ }
+ },
+ {
+ "id": 2,
+ "name": "SERVICE_GROUP2",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/2"
+ },
+ "filters": {
+ "service_id": 2
+ }
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestEndPointGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = endpoint_groups_client.EndPointGroupsClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_create_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_ENDPOINT_GROUP,
+ bytes_body,
+ status=201,
+ name="FAKE_ENDPOINT_GROUP",
+ filters={'service_id': "1"})
+
+ def _test_show_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_ENDPOINT_GROUP_INFO,
+ bytes_body,
+ endpoint_group_id="1")
+
+ def _test_check_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.check_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ bytes_body,
+ status=200,
+ endpoint_group_id="1")
+
+ def _test_update_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_ENDPOINT_GROUP_INFO,
+ bytes_body,
+ endpoint_group_id="1",
+ name="NewName")
+
+ def _test_list_endpoint_groups(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_endpoint_groups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ENDPOINT_GROUPS,
+ bytes_body)
+
+ def test_create_endpoint_group_with_str_body(self):
+ self._test_create_endpoint_group()
+
+ def test_create_endpoint_group_with_bytes_body(self):
+ self._test_create_endpoint_group(bytes_body=True)
+
+ def test_show_endpoint_group_with_str_body(self):
+ self._test_show_endpoint_group()
+
+ def test_show_endpoint_group_with_bytes_body(self):
+ self._test_show_endpoint_group(bytes_body=True)
+
+ def test_check_endpoint_group_with_str_body(self):
+ self._test_check_endpoint_group()
+
+ def test_check_endpoint_group_with_bytes_body(self):
+ self._test_check_endpoint_group(bytes_body=True)
+
+ def test_list_endpoint_groups_with_str_body(self):
+ self._test_list_endpoint_groups()
+
+ def test_list_endpoint_groups_with_bytes_body(self):
+ self._test_list_endpoint_groups(bytes_body=True)
+
+ def test_update_endpoint_group_with_str_body(self):
+ self._test_update_endpoint_group()
+
+ def test_update_endpoint_group_with_bytes_body(self):
+ self._test_update_endpoint_group(bytes_body=True)
+
+ def test_delete_endpoint_group(self):
+ self.check_service_client_function(
+ self.client.delete_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ endpoint_group_id="1",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_identity_client.py b/tempest/tests/lib/services/identity/v3/test_identity_client.py
index e435fe294..6572947fe 100644
--- a/tempest/tests/lib/services/identity/v3/test_identity_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_identity_client.py
@@ -109,6 +109,14 @@ class TestIdentityClient(base.BaseServiceTest):
resp_token="cbc36478b0bd8e67e89",
status=204)
+ def test_check_token_existence(self):
+ self.check_service_client_function(
+ self.client.check_token_existence,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ resp_token="cbc36478b0bd8e67e89",
+ status=200)
+
def test_list_auth_projects_with_str_body(self):
self._test_list_auth_projects()
diff --git a/tempest/tests/lib/services/identity/v3/test_oauth_token_client.py b/tempest/tests/lib/services/identity/v3/test_oauth_token_client.py
index b9b9b15f2..420ea5f24 100644
--- a/tempest/tests/lib/services/identity/v3/test_oauth_token_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_oauth_token_client.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from oslotest import mockpatch
+import fixtures
from tempest.lib.services.identity.v3 import oauth_token_client
from tempest.tests.lib import fake_auth_provider
@@ -137,7 +137,7 @@ class TestOAUTHTokenClient(base.BaseServiceTest):
def test_create_request_token(self):
mock_resp = self._mock_token_response(self.FAKE_CREATE_REQUEST_TOKEN)
resp = fake_http.fake_http_response(None, status=201), mock_resp
- self.useFixture(mockpatch.Patch(
+ self.useFixture(fixtures.MockPatch(
'tempest.lib.common.rest_client.RestClient.post',
return_value=resp))
@@ -157,7 +157,7 @@ class TestOAUTHTokenClient(base.BaseServiceTest):
mock_resp = self._mock_token_response(self.FAKE_CREATE_ACCESS_TOKEN)
req_secret = self.FAKE_CREATE_REQUEST_TOKEN['oauth_token_secret']
resp = fake_http.fake_http_response(None, status=201), mock_resp
- self.useFixture(mockpatch.Patch(
+ self.useFixture(fixtures.MockPatch(
'tempest.lib.common.rest_client.RestClient.post',
return_value=resp))
diff --git a/tempest/tests/lib/services/volume/v2/test_backups_client.py b/tempest/tests/lib/services/volume/v2/test_backups_client.py
new file mode 100644
index 000000000..14e5fb0be
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_backups_client.py
@@ -0,0 +1,117 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# 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.lib.services.volume.v2 import backups_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestBackupsClient(base.BaseServiceTest):
+
+ FAKE_BACKUP_LIST = {
+ "backups": [
+ {
+ "id": "2ef47aee-8844-490c-804d-2a8efe561c65",
+ "links": [
+ {
+ "href": "fake-url-1",
+ "rel": "self"
+ },
+ {
+ "href": "fake-url-2",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "backup001"
+ }
+ ]
+ }
+
+ FAKE_BACKUP_LIST_WITH_DETAIL = {
+ "backups": [
+ {
+ "availability_zone": "az1",
+ "container": "volumebackups",
+ "created_at": "2013-04-02T10:35:27.000000",
+ "description": None,
+ "fail_reason": None,
+ "id": "2ef47aee-8844-490c-804d-2a8efe561c65",
+ "links": [
+ {
+ "href": "fake-url-1",
+ "rel": "self"
+ },
+ {
+ "href": "fake-url-2",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "backup001",
+ "object_count": 22,
+ "size": 1,
+ "status": "available",
+ "volume_id": "e5185058-943a-4cb4-96d9-72c184c337d6",
+ "is_incremental": True,
+ "has_dependent_backups": False
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestBackupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = backups_client.BackupsClient(fake_auth,
+ 'volume',
+ 'regionOne')
+
+ def _test_list_backups(self, detail=False, mock_args='backups',
+ bytes_body=False, **params):
+ if detail:
+ resp_body = self.FAKE_BACKUP_LIST_WITH_DETAIL
+ else:
+ resp_body = self.FAKE_BACKUP_LIST
+ self.check_service_client_function(
+ self.client.list_backups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ resp_body,
+ to_utf=bytes_body,
+ mock_args=[mock_args],
+ detail=detail,
+ **params)
+
+ def test_list_backups_with_str_body(self):
+ self._test_list_backups()
+
+ def test_list_backups_with_bytes_body(self):
+ self._test_list_backups(bytes_body=True)
+
+ def test_list_backups_with_detail_with_str_body(self):
+ mock_args = "backups/detail"
+ self._test_list_backups(detail=True, mock_args=mock_args)
+
+ def test_list_backups_with_detail_with_bytes_body(self):
+ mock_args = "backups/detail"
+ self._test_list_backups(detail=True, mock_args=mock_args,
+ bytes_body=True)
+
+ def test_list_backups_with_params(self):
+ # Run the test separately for each param, to avoid assertion error
+ # resulting from randomized params order.
+ mock_args = 'backups?sort_key=name'
+ self._test_list_backups(mock_args=mock_args, sort_key='name')
+
+ mock_args = 'backups/detail?limit=10'
+ self._test_list_backups(detail=True, mock_args=mock_args,
+ bytes_body=True, limit=10)
diff --git a/tempest/tests/lib/services/volume/v2/test_snapshot_manage_client.py b/tempest/tests/lib/services/volume/v2/test_snapshot_manage_client.py
new file mode 100644
index 000000000..3fe8970a8
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_snapshot_manage_client.py
@@ -0,0 +1,83 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# 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.
+
+import mock
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.services.volume.v2 import snapshot_manage_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSnapshotManageClient(base.BaseServiceTest):
+
+ SNAPSHOT_MANAGE_REQUEST = {
+ "snapshot": {
+ "description": "snapshot-manage-description",
+ "metadata": None,
+ "ref": {
+ "source-name": "_snapshot-22b71da0-94f9-4aca-ad45-7522b3fa96bb"
+ },
+ "name": "snapshot-managed",
+ "volume_id": "7c064b34-1e4b-40bd-93ca-4ac5a973661b"
+ }
+ }
+
+ SNAPSHOT_MANAGE_RESPONSE = {
+ "snapshot": {
+ "status": "creating",
+ "description": "snapshot-manage-description",
+ "updated_at": None,
+ "volume_id": "32bafcc8-7109-42cd-8342-70d8de2bedef",
+ "id": "8fd6eb9d-0a82-456d-b1ec-dea4ac7f1ee2",
+ "size": 1,
+ "name": "snapshot-managed",
+ "created_at": "2017-07-11T10:07:58.000000",
+ "metadata": {}
+ }
+ }
+
+ def setUp(self):
+ super(TestSnapshotManageClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = snapshot_manage_client.SnapshotManageClient(fake_auth,
+ 'volume',
+ 'regionOne')
+
+ def _test_manage_snapshot(self, bytes_body=False):
+ payload = json.dumps(self.SNAPSHOT_MANAGE_REQUEST, sort_keys=True)
+ json_dumps = json.dumps
+
+ # NOTE: Use sort_keys for json.dumps so that the expected and actual
+ # payloads are guaranteed to be identical for mock_args assert check.
+ with mock.patch.object(snapshot_manage_client.json,
+ 'dumps') as mock_dumps:
+ mock_dumps.side_effect = lambda d: json_dumps(d, sort_keys=True)
+
+ self.check_service_client_function(
+ self.client.manage_snapshot,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.SNAPSHOT_MANAGE_RESPONSE,
+ to_utf=bytes_body,
+ status=202,
+ mock_args=['os-snapshot-manage', payload],
+ **self.SNAPSHOT_MANAGE_REQUEST['snapshot'])
+
+ def test_manage_snapshot_with_str_body(self):
+ self._test_manage_snapshot()
+
+ def test_manage_snapshot_with_bytes_body(self):
+ self._test_manage_snapshot(bytes_body=True)
diff --git a/tempest/tests/lib/services/volume/v2/test_transfers_client.py b/tempest/tests/lib/services/volume/v2/test_transfers_client.py
index 0c59bf2c6..84f499283 100644
--- a/tempest/tests/lib/services/volume/v2/test_transfers_client.py
+++ b/tempest/tests/lib/services/volume/v2/test_transfers_client.py
@@ -13,6 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+import mock
+from oslo_serialization import jsonutils as json
+
from tempest.lib.services.volume.v2 import transfers_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
@@ -20,11 +25,14 @@ from tempest.tests.lib.services import base
class TestTransfersClient(base.BaseServiceTest):
- FAKE_LIST_VOLUME_TRANSFERS_WITH_DETAIL = {
- "transfers": [{
- "created_at": "2017-04-18T09:10:03.000000",
+ FAKE_VOLUME_TRANSFER_ID = "0e89cdd1-6249-421b-96d8-25fac0623d42"
+
+ FAKE_VOLUME_TRANSFER_INFO = {
+ "transfer": {
+ "id": FAKE_VOLUME_TRANSFER_ID,
+ "name": "fake-volume-transfer",
"volume_id": "47bf04ef-1ea5-4c5f-a375-430a086d6747",
- "id": "0e89cdd1-6249-421b-96d8-25fac0623d42",
+ "created_at": "2017-04-18T09:10:03.000000",
"links": [
{
"href": "fake-url-1",
@@ -34,9 +42,8 @@ class TestTransfersClient(base.BaseServiceTest):
"href": "fake-url-2",
"rel": "bookmark"
}
- ],
- "name": "fake-volume-transfer"
- }]
+ ]
+ }
}
def setUp(self):
@@ -46,16 +53,106 @@ class TestTransfersClient(base.BaseServiceTest):
'volume',
'regionOne')
- def _test_list_volume_transfers_with_detail(self, bytes_body=False):
+ def _test_create_volume_transfer(self, bytes_body=False):
+ resp_body = copy.deepcopy(self.FAKE_VOLUME_TRANSFER_INFO)
+ resp_body['transfer'].update({"auth_key": "fake-auth-key"})
+ kwargs = {"name": "fake-volume-transfer",
+ "volume_id": "47bf04ef-1ea5-4c5f-a375-430a086d6747"}
+ payload = json.dumps({"transfer": kwargs}, sort_keys=True)
+ json_dumps = json.dumps
+
+ # NOTE: Use sort_keys for json.dumps so that the expected and actual
+ # payloads are guaranteed to be identical for mock_args assert check.
+ with mock.patch.object(transfers_client.json, 'dumps') as mock_dumps:
+ mock_dumps.side_effect = lambda d: json_dumps(d, sort_keys=True)
+
+ self.check_service_client_function(
+ self.client.create_volume_transfer,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ resp_body,
+ to_utf=bytes_body,
+ status=202,
+ mock_args=['os-volume-transfer', payload],
+ **kwargs)
+
+ def _test_accept_volume_transfer(self, bytes_body=False):
+ resp_body = copy.deepcopy(self.FAKE_VOLUME_TRANSFER_INFO)
+ resp_body['transfer'].pop('created_at')
+ kwargs = {"auth_key": "fake-auth-key"}
+ payload = json.dumps({"accept": kwargs}, sort_keys=True)
+ json_dumps = json.dumps
+
+ # NOTE: Use sort_keys for json.dumps so that the expected and actual
+ # payloads are guaranteed to be identical for mock_args assert check.
+ with mock.patch.object(transfers_client.json, 'dumps') as mock_dumps:
+ mock_dumps.side_effect = lambda d: json_dumps(d, sort_keys=True)
+
+ self.check_service_client_function(
+ self.client.accept_volume_transfer,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ resp_body,
+ to_utf=bytes_body,
+ status=202,
+ mock_args=['os-volume-transfer/%s/accept' %
+ self.FAKE_VOLUME_TRANSFER_ID, payload],
+ transfer_id=self.FAKE_VOLUME_TRANSFER_ID,
+ **kwargs)
+
+ def _test_show_volume_transfer(self, bytes_body=False):
+ resp_body = self.FAKE_VOLUME_TRANSFER_INFO
+ self.check_service_client_function(
+ self.client.show_volume_transfer,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ resp_body,
+ to_utf=bytes_body,
+ transfer_id="0e89cdd1-6249-421b-96d8-25fac0623d42")
+
+ def _test_list_volume_transfers(self, detail=False, bytes_body=False):
+ resp_body = copy.deepcopy(self.FAKE_VOLUME_TRANSFER_INFO)
+ if not detail:
+ resp_body['transfer'].pop('created_at')
+ resp_body = {"transfers": [resp_body['transfer']]}
self.check_service_client_function(
self.client.list_volume_transfers,
'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_LIST_VOLUME_TRANSFERS_WITH_DETAIL,
- bytes_body,
- detail=True)
+ resp_body,
+ to_utf=bytes_body,
+ detail=detail)
+
+ def test_create_volume_transfer_with_str_body(self):
+ self._test_create_volume_transfer()
+
+ def test_create_volume_transfer_with_bytes_body(self):
+ self._test_create_volume_transfer(bytes_body=True)
+
+ def test_accept_volume_transfer_with_str_body(self):
+ self._test_accept_volume_transfer()
+
+ def test_accept_volume_transfer_with_bytes_body(self):
+ self._test_accept_volume_transfer(bytes_body=True)
+
+ def test_show_volume_transfer_with_str_body(self):
+ self._test_show_volume_transfer()
+
+ def test_show_volume_transfer_with_bytes_body(self):
+ self._test_show_volume_transfer(bytes_body=True)
+
+ def test_list_volume_transfers_with_str_body(self):
+ self._test_list_volume_transfers()
+
+ def test_list_volume_transfers_with_bytes_body(self):
+ self._test_list_volume_transfers(bytes_body=True)
def test_list_volume_transfers_with_detail_with_str_body(self):
- self._test_list_volume_transfers_with_detail()
+ self._test_list_volume_transfers(detail=True)
def test_list_volume_transfers_with_detail_with_bytes_body(self):
- self._test_list_volume_transfers_with_detail(bytes_body=True)
+ self._test_list_volume_transfers(detail=True, bytes_body=True)
+
+ def test_delete_volume_transfer(self):
+ self.check_service_client_function(
+ self.client.delete_volume_transfer,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ status=202,
+ transfer_id="0e89cdd1-6249-421b-96d8-25fac0623d42")
diff --git a/tempest/tests/lib/services/volume/v2/test_volume_manage_client.py b/tempest/tests/lib/services/volume/v2/test_volume_manage_client.py
new file mode 100644
index 000000000..ea4a9f996
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_volume_manage_client.py
@@ -0,0 +1,111 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# 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.
+
+import mock
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.services.volume.v2 import volume_manage_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestVolumeManageClient(base.BaseServiceTest):
+
+ VOLUME_MANAGE_REQUEST = {
+ "volume": {
+ "host": "controller1@rbd#rbd",
+ "name": "volume-managed",
+ "availability_zone": "nova",
+ "bootable": False,
+ "metadata": None,
+ "ref": {
+ "source-name": "volume-2ce6ca46-e6c1-4fe5-8268-3a1c536fcbf3"
+ },
+ "volume_type": None,
+ "description": "volume-manage-description"
+ }
+ }
+
+ VOLUME_MANAGE_RESPONSE = {
+ "volume": {
+ "migration_status": None,
+ "attachments": [],
+ "links": [
+ {
+ "href": "fake-url-1",
+ "rel": "self"
+ },
+ {
+ "href": "fake-url-2",
+ "rel": "bookmark"
+ }
+ ],
+ "availability_zone": "nova",
+ "os-vol-host-attr:host": "controller1@rbd#rbd",
+ "encrypted": False,
+ "updated_at": None,
+ "replication_status": None,
+ "snapshot_id": None,
+ "id": "c07cd4a4-b52b-4511-a176-fbaa2011a227",
+ "size": 0,
+ "user_id": "142d8663efce464c89811c63e45bd82e",
+ "os-vol-tenant-attr:tenant_id": "f21a9c86d7114bf99c711f4874d80474",
+ "os-vol-mig-status-attr:migstat": None,
+ "metadata": {},
+ "status": "creating",
+ "description": "volume-manage-description",
+ "multiattach": False,
+ "source_volid": None,
+ "consistencygroup_id": None,
+ "os-vol-mig-status-attr:name_id": None,
+ "name": "volume-managed",
+ "bootable": "false",
+ "created_at": "2017-07-11T09:14:01.000000",
+ "volume_type": None
+ }
+ }
+
+ def setUp(self):
+ super(TestVolumeManageClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = volume_manage_client.VolumeManageClient(fake_auth,
+ 'volume',
+ 'regionOne')
+
+ def _test_manage_volume(self, bytes_body=False):
+ payload = json.dumps(self.VOLUME_MANAGE_REQUEST, sort_keys=True)
+ json_dumps = json.dumps
+
+ # NOTE: Use sort_keys for json.dumps so that the expected and actual
+ # payloads are guaranteed to be identical for mock_args assert check.
+ with mock.patch.object(volume_manage_client.json,
+ 'dumps') as mock_dumps:
+ mock_dumps.side_effect = lambda d: json_dumps(d, sort_keys=True)
+
+ self.check_service_client_function(
+ self.client.manage_volume,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.VOLUME_MANAGE_RESPONSE,
+ to_utf=bytes_body,
+ status=202,
+ mock_args=['os-volume-manage', payload],
+ **self.VOLUME_MANAGE_REQUEST['volume'])
+
+ def test_manage_volume_with_str_body(self):
+ self._test_manage_volume()
+
+ def test_manage_volume_with_bytes_body(self):
+ self._test_manage_volume(bytes_body=True)
diff --git a/tools/tempest-plugin-sanity.sh b/tools/tempest-plugin-sanity.sh
new file mode 100644
index 000000000..a4f706e01
--- /dev/null
+++ b/tools/tempest-plugin-sanity.sh
@@ -0,0 +1,122 @@
+#!/usr/bin/env bash
+
+# Copyright 2017 Red Hat, Inc.
+# 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.
+
+# This script is intended to check the sanity of tempest plugins against
+# tempest master.
+# What it does:
+# * Creates the virtualenv
+# * Install tempest
+# * Retrive the project lists having tempest plugin if project name is
+# given.
+# * For each project in a list, It does:
+# * Clone the Project
+# * Install the Project and also installs dependencies from
+# test-requirements.txt.
+# * Create Tempest workspace
+# * List tempest plugins
+# * List tempest plugins tests
+# * Uninstall the project and its dependencies
+# * Again Install tempest
+# * Again repeat the step from cloning project
+#
+# If one of the step fails, The script will exit with failure.
+
+if [ "$1" == "-h" ]; then
+ echo -e "This script performs the sanity of tempest plugins to find
+configuration and dependency issues with the tempest.\n
+Usage: sh ./tools/tempest-plugin-sanity.sh [Run sanity on tempest plugins]"
+ exit 0
+fi
+
+set -ex
+
+# retrieve a list of projects having tempest plugins
+PROJECT_LIST="$(python tools/generate-tempest-plugins-list.py)"
+# List of projects having tempest plugin stale or unmaintained from long time
+BLACKLIST="trio2o"
+
+# Function to clone project using zuul-cloner or from git
+function clone_project() {
+ if [ -e /usr/zuul-env/bin/zuul-cloner ]; then
+ /usr/zuul-env/bin/zuul-cloner --cache-dir /opt/git \
+ git://git.openstack.org \
+ openstack/"$1"
+
+ elif [ -e /usr/bin/git ]; then
+ /usr/bin/git clone git://git.openstack.org/openstack/"$1" \
+ openstack/"$1"
+
+ fi
+}
+
+# Create virtualenv to perform sanity operation
+SANITY_DIR=$(pwd)
+virtualenv "$SANITY_DIR"/.venv
+export TVENV="$SANITY_DIR/tools/with_venv.sh"
+cd "$SANITY_DIR"
+
+# Install tempest in a venv
+"$TVENV" pip install .
+
+# Function to install project
+function install_project() {
+ "$TVENV" pip install "$SANITY_DIR"/openstack/"$1"
+ # Check for test-requirements.txt file in a project then install it.
+ if [ -e "$SANITY_DIR"/openstack/"$1"/test-requirements.txt ]; then
+ "$TVENV" pip install -r "$SANITY_DIR"/openstack/"$1"/test-requirements.txt
+ fi
+}
+
+# Function to perform sanity checking on Tempest plugin
+function tempest_sanity() {
+ "$TVENV" tempest init "$SANITY_DIR"/tempest_sanity
+ cd "$SANITY_DIR"/tempest_sanity
+ "$TVENV" tempest list-plugins
+ "$TVENV" tempest run -l
+ # Delete tempest workspace
+ "$TVENV" tempest workspace remove --name tempest_sanity --rmdir
+ cd "$SANITY_DIR"
+}
+
+# Function to uninstall project
+function uninstall_project() {
+ "$TVENV" pip uninstall -y "$SANITY_DIR"/openstack/"$1"
+ # Check for *requirements.txt file in a project then uninstall it.
+ if [ -e "$SANITY_DIR"/openstack/"$1"/*requirements.txt ]; then
+ "$TVENV" pip uninstall -y -r "$SANITY_DIR"/openstack/"$1"/*requirements.txt
+ fi
+ # Remove the project directory after sanity run
+ rm -fr "$SANITY_DIR"/openstack/"$1"
+}
+
+# Function to run sanity check on each project
+function plugin_sanity_check() {
+ clone_project "$1" && install_project "$1" && tempest_sanity "$1" \
+ && uninstall_project "$1" && "$TVENV" pip install .
+}
+
+# Log status
+passed_plugin=''
+failed_plugin=''
+# Perform sanity on all tempest plugin projects
+for project in $PROJECT_LIST; do
+ # Remove blacklisted tempest plugins
+ if ! [[ `echo $BLACKLIST | grep -c $project ` -gt 0 ]]; then
+ plugin_sanity_check $project && passed_plugin+=", $project" || \
+ failed_plugin+=", $project"
+ fi
+done
diff --git a/tox.ini b/tox.ini
index 892f834dc..6f37d00e5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,7 +20,7 @@ setenv =
PYTHONWARNINGS=default::DeprecationWarning
BRANCH_NAME=master
CLIENT_NAME=tempest
-passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY ZUUL_CACHE_DIR REQUIREMENTS_PIP_LOCATION
+passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY ZUUL_CACHE_DIR REQUIREMENTS_PIP_LOCATION GENERATE_TEMPEST_PLUGIN_LIST
usedevelop = True
install_command =
{toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
@@ -185,3 +185,9 @@ commands=
# separately, outside of the requirements files.
deps = bindep
commands = bindep test
+
+[testenv:plugin-sanity-check]
+# perform tempest plugin sanity
+whitelist_externals = bash
+commands =
+ bash tools/tempest-plugin-sanity.sh