From 8beea33471ca95bd5413211938a4dce101ce3a4e Mon Sep 17 00:00:00 2001 From: Zhijiang Hu Date: Wed, 9 Aug 2017 13:43:55 +0800 Subject: [PATCH] Delete tempest code in repo and use python-tempest instead Change-Id: Id6834d1d87543d94bd4b8e7fd0acec69a5354cb9 Signed-off-by: Zhijiang Hu --- .../{tempest => daisy_tempest}/__init__.py | 0 .../api/daisy => daisy_tempest}/base.py | 14 +- .../api => daisy_tempest/v1}/__init__.py | 0 .../v1/fake}/__init__.py | 0 .../v1/fake/logical_network_fake.py | 0 .../daisy => daisy_tempest}/v1/getnodeinfo.sh | 0 .../daisy => daisy_tempest}/v1/mergeLog.py | 0 .../v1/test_cinder_volume.py | 5 +- .../v1/test_cluster.py | 4 +- .../v1/test_component.py | 4 +- .../v1/test_config_file.py | 4 +- .../v1/test_discover_host.py | 6 +- .../v1/test_logical_network.py | 5 +- .../v1/test_service.py | 4 +- test/tempest/etc/tempest.conf | 1234 -------------- test/tempest/openstack-common.conf | 8 - test/tempest/requirements.txt | 26 - test/tempest/run_tempest.sh | 146 -- test/tempest/run_tests.sh | 150 -- test/tempest/setup.cfg | 36 - test/tempest/setup.py | 30 - test/tempest/tempest/api/README.rst | 52 - test/tempest/tempest/api/daisy/v1/__init__.py | 0 .../tempest/api/daisy/v1/fake/__init__.py | 0 test/tempest/tempest/api_schema/__init__.py | 0 .../tempest/api_schema/request/__init__.py | 0 .../api_schema/request/compute/__init__.py | 0 .../api_schema/request/compute/flavors.py | 58 - .../api_schema/request/compute/v2/__init__.py | 0 .../api_schema/request/compute/v2/flavors.py | 39 - .../tempest/api_schema/response/__init__.py | 0 .../api_schema/response/compute/__init__.py | 0 .../response/compute/baremetal_nodes.py | 60 - .../response/compute/flavors_access.py | 34 - .../response/compute/flavors_extra_specs.py | 39 - .../api_schema/response/compute/migrations.py | 50 - .../response/compute/parameter_types.py | 81 - .../api_schema/response/compute/services.py | 61 - .../response/compute/v2_1/__init__.py | 0 .../response/compute/v2_1/agents.py | 57 - .../response/compute/v2_1/aggregates.py | 88 - .../compute/v2_1/availability_zone.py | 74 - .../response/compute/v2_1/certificates.py | 39 - .../response/compute/v2_1/extensions.py | 45 - .../response/compute/v2_1/fixed_ips.py | 41 - .../response/compute/v2_1/flavors.py | 98 -- .../response/compute/v2_1/floating_ips.py | 148 -- .../api_schema/response/compute/v2_1/hosts.py | 109 -- .../response/compute/v2_1/hypervisors.py | 185 --- .../response/compute/v2_1/images.py | 146 -- .../compute/v2_1/instance_usage_audit_logs.py | 59 - .../response/compute/v2_1/interfaces.py | 72 - .../response/compute/v2_1/keypairs.py | 100 -- .../response/compute/v2_1/limits.py | 101 -- .../response/compute/v2_1/quota_classes.py | 31 - .../response/compute/v2_1/quotas.py | 63 - .../v2_1/security_group_default_rule.py | 61 - .../response/compute/v2_1/security_groups.py | 105 -- .../response/compute/v2_1/servers.py | 520 ------ .../response/compute/v2_1/tenant_networks.py | 50 - .../response/compute/v2_1/tenant_usages.py | 92 -- .../response/compute/v2_1/volumes.py | 114 -- .../api_schema/response/compute/version.py | 59 - .../api_schema/response/messaging/__init__.py | 0 .../response/messaging/v1/__init__.py | 0 .../response/messaging/v1/queues.py | 239 --- test/tempest/tempest/auth.py | 659 -------- test/tempest/tempest/clients.py | 418 ----- test/tempest/tempest/common/__init__.py | 0 test/tempest/tempest/common/accounts.py | 349 ---- test/tempest/tempest/common/commands.py | 39 - test/tempest/tempest/common/cred_provider.py | 173 -- test/tempest/tempest/common/credentials.py | 93 -- .../tempest/tempest/common/custom_matchers.py | 226 --- test/tempest/tempest/common/fixed_network.py | 130 -- .../tempest/common/generator/__init__.py | 0 .../common/generator/base_generator.py | 182 --- .../common/generator/negative_generator.py | 79 - .../common/generator/valid_generator.py | 82 - test/tempest/tempest/common/glance_http.py | 376 ----- test/tempest/tempest/common/isolated_creds.py | 438 ----- .../tempest/common/negative_rest_client.py | 85 - test/tempest/tempest/common/service_client.py | 85 - test/tempest/tempest/common/ssh.py | 151 -- .../tempest/common/tempest_fixtures.py | 21 - test/tempest/tempest/common/utils/__init__.py | 3 - .../tempest/common/utils/file_utils.py | 23 - .../tempest/common/utils/linux/__init__.py | 0 .../common/utils/linux/remote_client.py | 179 -- test/tempest/tempest/common/waiters.py | 161 -- test/tempest/tempest/config.py | 1436 ----------------- test/tempest/tempest/exceptions.py | 246 --- test/tempest/tempest/manager.py | 80 - test/tempest/tempest/services/__init__.py | 0 .../tempest/services/baremetal/__init__.py | 0 .../tempest/services/baremetal/base.py | 219 --- .../tempest/services/baremetal/v1/__init__.py | 0 .../services/baremetal/v1/json/__init__.py | 0 .../baremetal/v1/json/baremetal_client.py | 373 ----- test/tempest/tempest/services/botoclients.py | 216 --- .../tempest/services/compute/__init__.py | 0 .../tempest/services/compute/json/__init__.py | 0 .../services/compute/json/agents_client.py | 55 - .../compute/json/aggregates_client.py | 114 -- .../compute/json/availability_zone_client.py | 36 - .../compute/json/baremetal_nodes_client.py | 43 - .../compute/json/certificates_client.py | 37 - .../compute/json/extensions_client.py | 39 - .../services/compute/json/fixed_ips_client.py | 36 - .../services/compute/json/flavors_client.py | 176 -- .../compute/json/floating_ips_client.py | 142 -- .../services/compute/json/hosts_client.py | 81 - .../compute/json/hypervisor_client.py | 71 - .../services/compute/json/images_client.py | 142 -- .../json/instance_usage_audit_log_client.py | 40 - .../compute/json/interfaces_client.py | 109 -- .../services/compute/json/keypairs_client.py | 54 - .../services/compute/json/limits_client.py | 37 - .../compute/json/migrations_client.py | 34 - .../services/compute/json/networks_client.py | 37 - .../services/compute/json/quotas_client.py | 141 -- .../security_group_default_rules_client.py | 75 - .../compute/json/security_groups_client.py | 144 -- .../services/compute/json/servers_client.py | 601 ------- .../services/compute/json/services_client.py | 57 - .../compute/json/tenant_networks_client.py | 33 - .../compute/json/tenant_usages_client.py | 43 - .../compute/json/volumes_extensions_client.py | 122 -- .../tempest/services/daisy/__init__.py | 0 .../tempest/services/daisy/v1/__init__.py | 0 .../services/daisy/v1/json/__init__.py | 0 .../services/daisy/v1/json/daisy_client.py | 257 --- .../services/daisy/v1/json/image_client.py | 324 ---- .../services/data_processing/__init__.py | 0 .../services/data_processing/v1_1/__init__.py | 0 .../v1_1/data_processing_client.py | 317 ---- .../tempest/services/database/__init__.py | 0 .../services/database/json/__init__.py | 0 .../services/database/json/flavors_client.py | 35 - .../services/database/json/limits_client.py | 30 - .../services/database/json/versions_client.py | 46 - .../tempest/services/identity/__init__.py | 0 .../tempest/services/identity/v2/__init__.py | 0 .../services/identity/v2/json/__init__.py | 0 .../identity/v2/json/identity_client.py | 283 ---- .../services/identity/v2/json/token_client.py | 110 -- .../tempest/services/identity/v3/__init__.py | 0 .../services/identity/v3/json/__init__.py | 0 .../identity/v3/json/credentials_client.py | 83 - .../identity/v3/json/endpoints_client.py | 87 - .../identity/v3/json/identity_client.py | 526 ------ .../identity/v3/json/policy_client.py | 69 - .../identity/v3/json/region_client.py | 77 - .../identity/v3/json/service_client.py | 73 - .../services/identity/v3/json/token_client.py | 172 -- .../tempest/services/image/__init__.py | 0 .../tempest/services/image/v1/__init__.py | 0 .../services/image/v1/json/__init__.py | 0 .../services/image/v1/json/image_client.py | 324 ---- .../tempest/services/image/v2/__init__.py | 0 .../services/image/v2/json/__init__.py | 0 .../services/image/v2/json/image_client.py | 203 --- .../tempest/services/messaging/__init__.py | 0 .../services/messaging/json/__init__.py | 0 .../messaging/json/messaging_client.py | 175 -- .../tempest/services/network/__init__.py | 0 .../tempest/services/network/json/__init__.py | 0 .../services/network/json/network_client.py | 581 ------- .../tempest/services/network/resources.py | 189 --- .../services/object_storage/__init__.py | 0 .../services/object_storage/account_client.py | 159 -- .../object_storage/container_client.py | 186 --- .../services/object_storage/object_client.py | 261 --- .../services/orchestration/__init__.py | 0 .../services/orchestration/json/__init__.py | 0 .../json/orchestration_client.py | 449 ------ .../tempest/services/telemetry/__init__.py | 0 .../services/telemetry/json/__init__.py | 0 .../telemetry/json/telemetry_client.py | 139 -- .../tempest/services/volume/__init__.py | 0 .../tempest/services/volume/json/__init__.py | 0 .../services/volume/json/admin/__init__.py | 0 .../volume/json/admin/volume_hosts_client.py | 43 - .../volume/json/admin/volume_quotas_client.py | 82 - .../json/admin/volume_services_client.py | 36 - .../volume/json/admin/volume_types_client.py | 192 --- .../volume/json/availability_zone_client.py | 33 - .../services/volume/json/backups_client.py | 99 -- .../services/volume/json/extensions_client.py | 34 - .../services/volume/json/qos_client.py | 161 -- .../services/volume/json/snapshots_client.py | 202 --- .../services/volume/json/volumes_client.py | 342 ---- .../tempest/services/volume/v2/__init__.py | 0 .../services/volume/v2/json/__init__.py | 0 .../services/volume/v2/json/admin/__init__.py | 0 .../v2/json/admin/volume_hosts_client.py | 24 - .../v2/json/admin/volume_quotas_client.py | 23 - .../v2/json/admin/volume_services_client.py | 23 - .../v2/json/admin/volume_types_client.py | 24 - .../v2/json/availability_zone_client.py | 21 - .../services/volume/v2/json/backups_client.py | 23 - .../volume/v2/json/extensions_client.py | 20 - .../services/volume/v2/json/qos_client.py | 19 - .../volume/v2/json/snapshots_client.py | 19 - .../services/volume/v2/json/volumes_client.py | 24 - test/tempest/tempest/test.py | 767 --------- test/tempest/tempest_envir_conf_install.sh | 208 --- test/tempest/test-requirements.txt | 13 - test/tempest/tox.ini | 125 -- 209 files changed, 18 insertions(+), 21561 deletions(-) rename test/tempest/{tempest => daisy_tempest}/__init__.py (100%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/base.py (97%) rename test/tempest/{tempest/api => daisy_tempest/v1}/__init__.py (100%) rename test/tempest/{tempest/api/daisy => daisy_tempest/v1/fake}/__init__.py (100%) mode change 100644 => 100755 rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/fake/logical_network_fake.py (100%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/getnodeinfo.sh (100%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/mergeLog.py (100%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_cinder_volume.py (99%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_cluster.py (99%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_component.py (98%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_config_file.py (97%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_discover_host.py (97%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_logical_network.py (99%) rename test/tempest/{tempest/api/daisy => daisy_tempest}/v1/test_service.py (98%) delete mode 100755 test/tempest/etc/tempest.conf delete mode 100644 test/tempest/openstack-common.conf delete mode 100644 test/tempest/requirements.txt delete mode 100644 test/tempest/run_tempest.sh delete mode 100644 test/tempest/run_tests.sh delete mode 100644 test/tempest/setup.cfg delete mode 100644 test/tempest/setup.py delete mode 100644 test/tempest/tempest/api/README.rst delete mode 100644 test/tempest/tempest/api/daisy/v1/__init__.py delete mode 100755 test/tempest/tempest/api/daisy/v1/fake/__init__.py delete mode 100644 test/tempest/tempest/api_schema/__init__.py delete mode 100644 test/tempest/tempest/api_schema/request/__init__.py delete mode 100644 test/tempest/tempest/api_schema/request/compute/__init__.py delete mode 100644 test/tempest/tempest/api_schema/request/compute/flavors.py delete mode 100644 test/tempest/tempest/api_schema/request/compute/v2/__init__.py delete mode 100644 test/tempest/tempest/api_schema/request/compute/v2/flavors.py delete mode 100644 test/tempest/tempest/api_schema/response/__init__.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/__init__.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/baremetal_nodes.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/flavors_access.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/flavors_extra_specs.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/migrations.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/parameter_types.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/services.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/__init__.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/agents.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/aggregates.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/availability_zone.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/certificates.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/extensions.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/fixed_ips.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/flavors.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/floating_ips.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/hosts.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/hypervisors.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/images.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/interfaces.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/keypairs.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/limits.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/quota_classes.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/quotas.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/security_groups.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/servers.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/tenant_networks.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/tenant_usages.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/v2_1/volumes.py delete mode 100644 test/tempest/tempest/api_schema/response/compute/version.py delete mode 100644 test/tempest/tempest/api_schema/response/messaging/__init__.py delete mode 100644 test/tempest/tempest/api_schema/response/messaging/v1/__init__.py delete mode 100644 test/tempest/tempest/api_schema/response/messaging/v1/queues.py delete mode 100644 test/tempest/tempest/auth.py delete mode 100644 test/tempest/tempest/clients.py delete mode 100644 test/tempest/tempest/common/__init__.py delete mode 100644 test/tempest/tempest/common/accounts.py delete mode 100644 test/tempest/tempest/common/commands.py delete mode 100644 test/tempest/tempest/common/cred_provider.py delete mode 100644 test/tempest/tempest/common/credentials.py delete mode 100644 test/tempest/tempest/common/custom_matchers.py delete mode 100644 test/tempest/tempest/common/fixed_network.py delete mode 100644 test/tempest/tempest/common/generator/__init__.py delete mode 100644 test/tempest/tempest/common/generator/base_generator.py delete mode 100644 test/tempest/tempest/common/generator/negative_generator.py delete mode 100644 test/tempest/tempest/common/generator/valid_generator.py delete mode 100644 test/tempest/tempest/common/glance_http.py delete mode 100644 test/tempest/tempest/common/isolated_creds.py delete mode 100644 test/tempest/tempest/common/negative_rest_client.py delete mode 100644 test/tempest/tempest/common/service_client.py delete mode 100644 test/tempest/tempest/common/ssh.py delete mode 100644 test/tempest/tempest/common/tempest_fixtures.py delete mode 100644 test/tempest/tempest/common/utils/__init__.py delete mode 100644 test/tempest/tempest/common/utils/file_utils.py delete mode 100644 test/tempest/tempest/common/utils/linux/__init__.py delete mode 100644 test/tempest/tempest/common/utils/linux/remote_client.py delete mode 100644 test/tempest/tempest/common/waiters.py delete mode 100755 test/tempest/tempest/config.py delete mode 100644 test/tempest/tempest/exceptions.py delete mode 100644 test/tempest/tempest/manager.py delete mode 100644 test/tempest/tempest/services/__init__.py delete mode 100644 test/tempest/tempest/services/baremetal/__init__.py delete mode 100644 test/tempest/tempest/services/baremetal/base.py delete mode 100644 test/tempest/tempest/services/baremetal/v1/__init__.py delete mode 100644 test/tempest/tempest/services/baremetal/v1/json/__init__.py delete mode 100644 test/tempest/tempest/services/baremetal/v1/json/baremetal_client.py delete mode 100644 test/tempest/tempest/services/botoclients.py delete mode 100644 test/tempest/tempest/services/compute/__init__.py delete mode 100644 test/tempest/tempest/services/compute/json/__init__.py delete mode 100644 test/tempest/tempest/services/compute/json/agents_client.py delete mode 100644 test/tempest/tempest/services/compute/json/aggregates_client.py delete mode 100644 test/tempest/tempest/services/compute/json/availability_zone_client.py delete mode 100644 test/tempest/tempest/services/compute/json/baremetal_nodes_client.py delete mode 100644 test/tempest/tempest/services/compute/json/certificates_client.py delete mode 100644 test/tempest/tempest/services/compute/json/extensions_client.py delete mode 100644 test/tempest/tempest/services/compute/json/fixed_ips_client.py delete mode 100644 test/tempest/tempest/services/compute/json/flavors_client.py delete mode 100644 test/tempest/tempest/services/compute/json/floating_ips_client.py delete mode 100644 test/tempest/tempest/services/compute/json/hosts_client.py delete mode 100644 test/tempest/tempest/services/compute/json/hypervisor_client.py delete mode 100644 test/tempest/tempest/services/compute/json/images_client.py delete mode 100644 test/tempest/tempest/services/compute/json/instance_usage_audit_log_client.py delete mode 100644 test/tempest/tempest/services/compute/json/interfaces_client.py delete mode 100644 test/tempest/tempest/services/compute/json/keypairs_client.py delete mode 100644 test/tempest/tempest/services/compute/json/limits_client.py delete mode 100644 test/tempest/tempest/services/compute/json/migrations_client.py delete mode 100644 test/tempest/tempest/services/compute/json/networks_client.py delete mode 100644 test/tempest/tempest/services/compute/json/quotas_client.py delete mode 100644 test/tempest/tempest/services/compute/json/security_group_default_rules_client.py delete mode 100644 test/tempest/tempest/services/compute/json/security_groups_client.py delete mode 100644 test/tempest/tempest/services/compute/json/servers_client.py delete mode 100644 test/tempest/tempest/services/compute/json/services_client.py delete mode 100644 test/tempest/tempest/services/compute/json/tenant_networks_client.py delete mode 100644 test/tempest/tempest/services/compute/json/tenant_usages_client.py delete mode 100644 test/tempest/tempest/services/compute/json/volumes_extensions_client.py delete mode 100644 test/tempest/tempest/services/daisy/__init__.py delete mode 100644 test/tempest/tempest/services/daisy/v1/__init__.py delete mode 100644 test/tempest/tempest/services/daisy/v1/json/__init__.py delete mode 100644 test/tempest/tempest/services/daisy/v1/json/daisy_client.py delete mode 100644 test/tempest/tempest/services/daisy/v1/json/image_client.py delete mode 100644 test/tempest/tempest/services/data_processing/__init__.py delete mode 100644 test/tempest/tempest/services/data_processing/v1_1/__init__.py delete mode 100644 test/tempest/tempest/services/data_processing/v1_1/data_processing_client.py delete mode 100644 test/tempest/tempest/services/database/__init__.py delete mode 100644 test/tempest/tempest/services/database/json/__init__.py delete mode 100644 test/tempest/tempest/services/database/json/flavors_client.py delete mode 100644 test/tempest/tempest/services/database/json/limits_client.py delete mode 100644 test/tempest/tempest/services/database/json/versions_client.py delete mode 100644 test/tempest/tempest/services/identity/__init__.py delete mode 100644 test/tempest/tempest/services/identity/v2/__init__.py delete mode 100644 test/tempest/tempest/services/identity/v2/json/__init__.py delete mode 100644 test/tempest/tempest/services/identity/v2/json/identity_client.py delete mode 100644 test/tempest/tempest/services/identity/v2/json/token_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/__init__.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/__init__.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/credentials_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/endpoints_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/identity_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/policy_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/region_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/service_client.py delete mode 100644 test/tempest/tempest/services/identity/v3/json/token_client.py delete mode 100644 test/tempest/tempest/services/image/__init__.py delete mode 100644 test/tempest/tempest/services/image/v1/__init__.py delete mode 100644 test/tempest/tempest/services/image/v1/json/__init__.py delete mode 100644 test/tempest/tempest/services/image/v1/json/image_client.py delete mode 100644 test/tempest/tempest/services/image/v2/__init__.py delete mode 100644 test/tempest/tempest/services/image/v2/json/__init__.py delete mode 100644 test/tempest/tempest/services/image/v2/json/image_client.py delete mode 100644 test/tempest/tempest/services/messaging/__init__.py delete mode 100644 test/tempest/tempest/services/messaging/json/__init__.py delete mode 100644 test/tempest/tempest/services/messaging/json/messaging_client.py delete mode 100644 test/tempest/tempest/services/network/__init__.py delete mode 100644 test/tempest/tempest/services/network/json/__init__.py delete mode 100644 test/tempest/tempest/services/network/json/network_client.py delete mode 100644 test/tempest/tempest/services/network/resources.py delete mode 100644 test/tempest/tempest/services/object_storage/__init__.py delete mode 100644 test/tempest/tempest/services/object_storage/account_client.py delete mode 100644 test/tempest/tempest/services/object_storage/container_client.py delete mode 100644 test/tempest/tempest/services/object_storage/object_client.py delete mode 100644 test/tempest/tempest/services/orchestration/__init__.py delete mode 100644 test/tempest/tempest/services/orchestration/json/__init__.py delete mode 100644 test/tempest/tempest/services/orchestration/json/orchestration_client.py delete mode 100644 test/tempest/tempest/services/telemetry/__init__.py delete mode 100644 test/tempest/tempest/services/telemetry/json/__init__.py delete mode 100644 test/tempest/tempest/services/telemetry/json/telemetry_client.py delete mode 100644 test/tempest/tempest/services/volume/__init__.py delete mode 100644 test/tempest/tempest/services/volume/json/__init__.py delete mode 100644 test/tempest/tempest/services/volume/json/admin/__init__.py delete mode 100644 test/tempest/tempest/services/volume/json/admin/volume_hosts_client.py delete mode 100644 test/tempest/tempest/services/volume/json/admin/volume_quotas_client.py delete mode 100644 test/tempest/tempest/services/volume/json/admin/volume_services_client.py delete mode 100644 test/tempest/tempest/services/volume/json/admin/volume_types_client.py delete mode 100644 test/tempest/tempest/services/volume/json/availability_zone_client.py delete mode 100644 test/tempest/tempest/services/volume/json/backups_client.py delete mode 100644 test/tempest/tempest/services/volume/json/extensions_client.py delete mode 100644 test/tempest/tempest/services/volume/json/qos_client.py delete mode 100644 test/tempest/tempest/services/volume/json/snapshots_client.py delete mode 100644 test/tempest/tempest/services/volume/json/volumes_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/__init__.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/__init__.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/admin/__init__.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/admin/volume_hosts_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/admin/volume_quotas_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/admin/volume_services_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/admin/volume_types_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/availability_zone_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/backups_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/extensions_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/qos_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/snapshots_client.py delete mode 100644 test/tempest/tempest/services/volume/v2/json/volumes_client.py delete mode 100755 test/tempest/tempest/test.py delete mode 100755 test/tempest/tempest_envir_conf_install.sh delete mode 100644 test/tempest/test-requirements.txt diff --git a/test/tempest/tempest/__init__.py b/test/tempest/daisy_tempest/__init__.py similarity index 100% rename from test/tempest/tempest/__init__.py rename to test/tempest/daisy_tempest/__init__.py diff --git a/test/tempest/tempest/api/daisy/base.py b/test/tempest/daisy_tempest/base.py similarity index 97% rename from test/tempest/tempest/api/daisy/base.py rename to test/tempest/daisy_tempest/base.py index f8d65873..a7c00df7 100644 --- a/test/tempest/tempest/api/daisy/base.py +++ b/test/tempest/daisy_tempest/base.py @@ -16,9 +16,7 @@ from oslo_log import log as logging from tempest import config import tempest.test from daisyclient.v1 import client as daisy_client -from tempest.api.daisy.v1.fake.logical_network_fake import FakeDiscoverHosts - -CONF = config.CONF +from daisy_tempest.v1.fake.logical_network_fake import FakeDiscoverHosts LOG = logging.getLogger(__name__) @@ -33,7 +31,7 @@ class BaseDaisyTest(tempest.test.BaseTestCase): def resource_setup(cls): super(BaseDaisyTest, cls).resource_setup() cls.daisy_version = 1.0 - cls.daisy_endpoint = CONF.daisy.daisy_endpoint + cls.daisy_endpoint = "http://127.0.0.1:19292" cls.daisy_client = daisy_client.Client(version=cls.daisy_version, endpoint=cls.daisy_endpoint) @@ -533,3 +531,11 @@ class BaseDaisyTest(tempest.test.BaseTestCase): @classmethod def add_fake_node(cls, num): return cls.daisy_client.hosts.add(**FakeDiscoverHosts.daisy_data[num]) + + def assertRaisesMessage(self, exc, msg, func, *args, **kwargs): + try: + func(*args, **kwargs) + except Exception as e: + self.assertEqual(msg, str(e)) + self.assertTrue(isinstance(e, exc), + "Expected %s, got %s" % (exc, type(e))) diff --git a/test/tempest/tempest/api/__init__.py b/test/tempest/daisy_tempest/v1/__init__.py similarity index 100% rename from test/tempest/tempest/api/__init__.py rename to test/tempest/daisy_tempest/v1/__init__.py diff --git a/test/tempest/tempest/api/daisy/__init__.py b/test/tempest/daisy_tempest/v1/fake/__init__.py old mode 100644 new mode 100755 similarity index 100% rename from test/tempest/tempest/api/daisy/__init__.py rename to test/tempest/daisy_tempest/v1/fake/__init__.py diff --git a/test/tempest/tempest/api/daisy/v1/fake/logical_network_fake.py b/test/tempest/daisy_tempest/v1/fake/logical_network_fake.py similarity index 100% rename from test/tempest/tempest/api/daisy/v1/fake/logical_network_fake.py rename to test/tempest/daisy_tempest/v1/fake/logical_network_fake.py diff --git a/test/tempest/tempest/api/daisy/v1/getnodeinfo.sh b/test/tempest/daisy_tempest/v1/getnodeinfo.sh similarity index 100% rename from test/tempest/tempest/api/daisy/v1/getnodeinfo.sh rename to test/tempest/daisy_tempest/v1/getnodeinfo.sh diff --git a/test/tempest/tempest/api/daisy/v1/mergeLog.py b/test/tempest/daisy_tempest/v1/mergeLog.py similarity index 100% rename from test/tempest/tempest/api/daisy/v1/mergeLog.py rename to test/tempest/daisy_tempest/v1/mergeLog.py diff --git a/test/tempest/tempest/api/daisy/v1/test_cinder_volume.py b/test/tempest/daisy_tempest/v1/test_cinder_volume.py similarity index 99% rename from test/tempest/tempest/api/daisy/v1/test_cinder_volume.py rename to test/tempest/daisy_tempest/v1/test_cinder_volume.py index 57899589..577fb1e2 100755 --- a/test/tempest/tempest/api/daisy/v1/test_cinder_volume.py +++ b/test/tempest/daisy_tempest/v1/test_cinder_volume.py @@ -1,12 +1,9 @@ -from tempest.api.daisy import base -from tempest import config +from daisy_tempest import base from nose.tools import set_trace from daisyclient import exc as client_exc import copy from fake.logical_network_fake import FakeLogicNetwork as logical_fake -CONF = config.CONF - class DaisyCinderVolumeTest(base.BaseDaisyTest): diff --git a/test/tempest/tempest/api/daisy/v1/test_cluster.py b/test/tempest/daisy_tempest/v1/test_cluster.py similarity index 99% rename from test/tempest/tempest/api/daisy/v1/test_cluster.py rename to test/tempest/daisy_tempest/v1/test_cluster.py index bd7b28fa..02af16c1 100755 --- a/test/tempest/tempest/api/daisy/v1/test_cluster.py +++ b/test/tempest/daisy_tempest/v1/test_cluster.py @@ -16,12 +16,10 @@ import logging -from tempest.api.daisy import base -from tempest import config +from daisy_tempest import base from fake.logical_network_fake import FakeLogicNetwork as logical_fake import copy -CONF = config.CONF LOG = logging.getLogger(__name__) diff --git a/test/tempest/tempest/api/daisy/v1/test_component.py b/test/tempest/daisy_tempest/v1/test_component.py similarity index 98% rename from test/tempest/tempest/api/daisy/v1/test_component.py rename to test/tempest/daisy_tempest/v1/test_component.py index e1290c29..76c1f99b 100755 --- a/test/tempest/tempest/api/daisy/v1/test_component.py +++ b/test/tempest/daisy_tempest/v1/test_component.py @@ -1,8 +1,6 @@ -from tempest.api.daisy import base -from tempest import config -CONF = config.CONF +from daisy_tempest import base class DaisyComponentTest(base.BaseDaisyTest): diff --git a/test/tempest/tempest/api/daisy/v1/test_config_file.py b/test/tempest/daisy_tempest/v1/test_config_file.py similarity index 97% rename from test/tempest/tempest/api/daisy/v1/test_config_file.py rename to test/tempest/daisy_tempest/v1/test_config_file.py index 886a3c09..3eae890a 100755 --- a/test/tempest/tempest/api/daisy/v1/test_config_file.py +++ b/test/tempest/daisy_tempest/v1/test_config_file.py @@ -13,9 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.daisy import base -from tempest import config -CONF = config.CONF +from daisy_tempest import base class DaisyConfigFileTest(base.BaseDaisyTest): diff --git a/test/tempest/tempest/api/daisy/v1/test_discover_host.py b/test/tempest/daisy_tempest/v1/test_discover_host.py similarity index 97% rename from test/tempest/tempest/api/daisy/v1/test_discover_host.py rename to test/tempest/daisy_tempest/v1/test_discover_host.py index 6f1914a5..6e59fb58 100755 --- a/test/tempest/tempest/api/daisy/v1/test_discover_host.py +++ b/test/tempest/daisy_tempest/v1/test_discover_host.py @@ -13,12 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.api.daisy import base -from tempest import config +from daisy_tempest import base import time from daisyclient import exc as client_exc from fake.logical_network_fake import FakeLogicNetwork as logical_fake -CONF = config.CONF class DaisyDiscoverHostTest(base.BaseDaisyTest): @@ -102,7 +100,7 @@ class DaisyDiscoverHostTest(base.BaseDaisyTest): pass def test_discover_host(self): - daisy_endpoint = CONF.daisy.daisy_endpoint + daisy_endpoint = "http://127.0.0.1:19292" def GetMiddleStr(content, startStr, endStr): startIndex = content.index(startStr) diff --git a/test/tempest/tempest/api/daisy/v1/test_logical_network.py b/test/tempest/daisy_tempest/v1/test_logical_network.py similarity index 99% rename from test/tempest/tempest/api/daisy/v1/test_logical_network.py rename to test/tempest/daisy_tempest/v1/test_logical_network.py index 5742a33c..57584ea2 100755 --- a/test/tempest/tempest/api/daisy/v1/test_logical_network.py +++ b/test/tempest/daisy_tempest/v1/test_logical_network.py @@ -2,12 +2,9 @@ import copy from daisyclient import exc as client_exc -from tempest.api.daisy import base -from tempest import config +from daisy_tempest import base from fake.logical_network_fake import FakeLogicNetwork as logical_fake -CONF = config.CONF - class TecsLogicalNetworkTest(base.BaseDaisyTest): LOGICAL_FILTER = ['name', 'physnet_name', 'segmentation_id', diff --git a/test/tempest/tempest/api/daisy/v1/test_service.py b/test/tempest/daisy_tempest/v1/test_service.py similarity index 98% rename from test/tempest/tempest/api/daisy/v1/test_service.py rename to test/tempest/daisy_tempest/v1/test_service.py index 11a16200..21ada6e3 100755 --- a/test/tempest/tempest/api/daisy/v1/test_service.py +++ b/test/tempest/daisy_tempest/v1/test_service.py @@ -1,8 +1,6 @@ -from tempest.api.daisy import base -from tempest import config -CONF = config.CONF +from daisy_tempest import base class DaisyServiceTest(base.BaseDaisyTest): diff --git a/test/tempest/etc/tempest.conf b/test/tempest/etc/tempest.conf deleted file mode 100755 index ec565da4..00000000 --- a/test/tempest/etc/tempest.conf +++ /dev/null @@ -1,1234 +0,0 @@ -[oslo_concurrency] -lock_path = /tmp - -[DEFAULT] -#lock_path = /tmp -log_file = tempest.log -lock_path = /tmp - -# -# From tempest.config -# - -# Whether to disable inter-process locks (boolean value) -#disable_process_locking = false - -# Directory to use for lock files. (string value) -#lock_path = - -# -# From tempest.config -# - -# Print debugging output (set logging level to DEBUG instead of -# default WARNING level). (boolean value) -#debug = false - -# Print more verbose output (set logging level to INFO instead of -# default WARNING level). (boolean value) -#verbose = false - -# -# From tempest.config -# - -# The name of a logging configuration file. This file is appended to -# any existing logging configuration files. For details about logging -# configuration files, see the Python logging module documentation. -# (string value) -# Deprecated group/name - [DEFAULT]/log_config -#log_config_append = - -# Format string for %%(asctime)s in log records. Default: %(default)s -# . (string value) -#log_date_format = %Y-%m-%d %H:%M:%S - -# (Optional) The base directory used for relative --log-file paths. -# (string value) -# Deprecated group/name - [DEFAULT]/logdir -#log_dir = - -# (Optional) Name of log file to output to. If no default is set, -# logging will go to stdout. (string value) -# Deprecated group/name - [DEFAULT]/logfile -#log_file = - -# DEPRECATED. A logging.Formatter log message format string which may -# use any of the available logging.LogRecord attributes. This option -# is deprecated. Please use logging_context_format_string and -# logging_default_format_string instead. (string value) -#log_format = - -# Syslog facility to receive log lines. (string value) -#syslog_log_facility = LOG_USER - -# Use syslog for logging. Existing syslog format is DEPRECATED during -# I, and will change in J to honor RFC5424. (boolean value) -#use_syslog = false - -# (Optional) Enables or disables syslog rfc5424 format for logging. If -# enabled, prefixes the MSG part of the syslog message with APP-NAME -# (RFC5424). The format without the APP-NAME is deprecated in I, and -# will be removed in J. (boolean value) -#use_syslog_rfc_format = false - -# -# From tempest.config -# - -# Log output to standard error. (boolean value) -#use_stderr = true - -# -# From tempest.config -# - -# List of logger=LEVEL pairs. (list value) -#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN - -# Enables or disables fatal status of deprecations. (boolean value) -#fatal_deprecations = false - -# The format for an instance that is passed with the log message. -# (string value) -#instance_format = "[instance: %(uuid)s] " - -# The format for an instance UUID that is passed with the log message. -# (string value) -#instance_uuid_format = "[instance: %(uuid)s] " - -# Format string to use for log messages with context. (string value) -#logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s - -# Data to append to log format when level is DEBUG. (string value) -#logging_debug_format_suffix = %(funcName)s %(pathname)s:%(lineno)d - -# Format string to use for log messages without context. (string -# value) -#logging_default_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s - -# Prefix each line of exception output with this format. (string -# value) -#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s - -# Enables or disables publication of error events. (boolean value) -#publish_errors = false - - -[auth] - -# -# From tempest.config -# - -# Allows test cases to create/destroy tenants and users. This option -# requires that OpenStack Identity API admin credentials are known. If -# false, isolated test cases and parallel execution, can still be -# achieved configuring a list of test accounts (boolean value) -# Deprecated group/name - [compute]/allow_tenant_isolation -# Deprecated group/name - [orchestration]/allow_tenant_isolation -#allow_tenant_isolation = false - -# If set to True it enables the Accounts provider, which locks -# credentials to allow for parallel execution with pre-provisioned -# accounts. It can only be used to run tests that ensure credentials -# cleanup happens. It requires at least `2 * CONC` distinct accounts -# configured in `test_accounts_file`, with CONC == the number of -# concurrent test processes. (boolean value) -#locking_credentials_provider = false - -# Path to the yaml file that contains the list of credentials to use -# for running tests (string value) -#test_accounts_file = etc/accounts.yaml - - -[baremetal] - -# -# From tempest.config -# - -# Timeout for Ironic node to completely provision (integer value) -#active_timeout = 300 - -# Timeout for association of Nova instance and Ironic node (integer -# value) -#association_timeout = 30 - -# Catalog type of the baremetal provisioning service (string value) -#catalog_type = baremetal - -# Driver name which Ironic uses (string value) -#driver = fake - -# Whether the Ironic nova-compute driver is enabled (boolean value) -#driver_enabled = false - -# The endpoint type to use for the baremetal provisioning service -# (string value) -#endpoint_type = publicURL - -# Timeout for Ironic power transitions. (integer value) -#power_timeout = 60 - -# Timeout for unprovisioning an Ironic node. (integer value) -#unprovision_timeout = 60 - - -[boto] - -# -# From tempest.config -# - -# AKI Kernel Image manifest (string value) -#aki_manifest = cirros-0.3.0-x86_64-vmlinuz.manifest.xml - -# AMI Machine Image manifest (string value) -#ami_manifest = cirros-0.3.0-x86_64-blank.img.manifest.xml - -# ARI Ramdisk Image manifest (string value) -#ari_manifest = cirros-0.3.0-x86_64-initrd.manifest.xml - -# AWS Access Key (string value) -#aws_access = - -# AWS Secret Key (string value) -#aws_secret = - -# AWS Zone for EC2 tests (string value) -#aws_zone = nova - -# Status Change Test Interval (integer value) -#build_interval = 1 - -# Status Change Timeout (integer value) -#build_timeout = 60 - -# EC2 URL (string value) -#ec2_url = http://localhost:8773/services/Cloud - -# boto Http socket timeout (integer value) -#http_socket_timeout = 3 - -# Instance type (string value) -#instance_type = m1.tiny - -# boto num_retries on error (integer value) -#num_retries = 1 - -# S3 Materials Path (string value) -#s3_materials_path = /opt/stack/devstack/files/images/s3-materials/cirros-0.3.0 - -# S3 URL (string value) -#s3_url = http://localhost:8080 - - -[cli] -cli_dir = /usr/bin - -# -# From tempest.config -# - -# directory where python client binaries are located (string value) -#cli_dir = /usr/local/bin - -# enable cli tests (boolean value) -#enabled = true - -# Whether the tempest run location has access to the *-manage -# commands. In a pure blackbox environment it will not. (boolean -# value) -#has_manage = true - -# Number of seconds to wait on a CLI timeout (integer value) -#timeout = 15 - - -[compute] -build_timeout = 300 -run_ssh = true -ssh_auth_method = adminpass -ssh_user = cirros -image_ssh_user = cirros -image_ssh_password = cubswin:) -image_ref = -image_ref_alt = -flavor_ref = -flavor_ref_alt = -use_floatingip_for_ssh = true -fixed_network_name = net1 -fixed_network_name_external = big-net - -#VMB_V05.01.10_1128Patch_MGW_20150309_serial -image_ref_vmb = fc9e4f80-6133-4b25-b81b-3eafcea621fc -image_ssh_vmb_user = zte -image_ssh_vmb_pwd = zte - -#winxp -image_ref_xp = 1e48ce15-f4db-46bf-9a30-01074a81f666 -image_ssh_xp_user = openstack -image_ssh_xp_pwd = 1234 - -#linux-cgslv5 cgslv5_x86_64 -image_ref_linux = 9c6e73d5-99ed-4b19-a9f3-f79f6272d2b9 -image_ssh_linux_user = root -image_ssh_linux_pwd = ossdbg1 - -#suse -image_ref_suse = e9f6f3e7-cca5-4cb7-b955-4eb49cf147cf -image_ssh_suse_user = root -image_ssh_suse_pwd = it@123456 - -#centos7 -image_ref_centos7 = 64fe48eb-5179-4dcf-a08a-797370f130d7 -image_ssh_centos7_user = root -image_ssh_centos7_pwd = ossdbg1 - -#is sdn , default is False -use_sdn = False - -# -# From tempest.config -# - -# Time in seconds between build status checks. (integer value) -#build_interval = 1 - -# Timeout in seconds to wait for an instance to build. Other services -# that do not define build_timeout will inherit this value, for -# example the image service. (integer value) -#build_timeout = 300 - -# Catalog type of the Compute service. (string value) -#catalog_type = compute - -# The endpoint type to use for the compute service. (string value) -#endpoint_type = publicURL - -# Name of the fixed network that is visible to all test tenants. -# (string value) -#fixed_network_name = private - -# Valid primary flavor to use in tests. (string value) -#flavor_ref = 1 - -# Valid secondary flavor to be used in tests. (string value) -#flavor_ref_alt = 2 - -# Unallocated floating IP range, which will be used to test the -# floating IP bulk feature for CRUD operation. This block must not -# overlap an existing floating IP pool. (string value) -#floating_ip_range = 10.0.0.0/29 - -# Password used to authenticate to an instance using the alternate -# image. (string value) -#image_alt_ssh_password = password - -# User name used to authenticate to an instance using the alternate -# image. (string value) -#image_alt_ssh_user = root - -# Valid primary image reference to be used in tests. This is a -# required option (string value) -#image_ref = - -# Valid secondary image reference to be used in tests. This is a -# required option, but if only one image is available duplicate the -# value of image_ref above (string value) -#image_ref_alt = - -# Password used to authenticate to an instance. (string value) -#image_ssh_password = password - -# User name used to authenticate to an instance. (string value) -#image_ssh_user = root - -# IP version used for SSH connections. (integer value) -#ip_version_for_ssh = 4 - -# Network used for SSH connections. Ignored if -# use_floatingip_for_ssh=true or run_ssh=false. (string value) -#network_for_ssh = public - -# Path to a private key file for SSH access to remote hosts (string -# value) -#path_to_private_key = - -# Timeout in seconds to wait for ping to succeed. (integer value) -#ping_timeout = 120 - -# Additional wait time for clean state, when there is no OS-EXT-STS -# extension available (integer value) -#ready_wait = 0 - -# The compute region name to use. If empty, the value of -# identity.region is used instead. If no such region is found in the -# service catalog, the first found one is used. (string value) -#region = - -# Should the tests ssh to instances? (boolean value) -#run_ssh = false - -# Time in seconds before a shelved instance is eligible for removing -# from a host. -1 never offload, 0 offload when shelved. This time -# should be the same as the time of nova.conf, and some tests will run -# for as long as the time. (integer value) -#shelved_offload_time = 0 - -# Auth method used for authenticate to the instance. Valid choices -# are: keypair, configured, adminpass. keypair: start the servers with -# an ssh keypair. configured: use the configured user and password. -# adminpass: use the injected adminPass. disabled: avoid using ssh -# when it is an option. (string value) -#ssh_auth_method = keypair - -# Timeout in seconds to wait for output from ssh channel. (integer -# value) -#ssh_channel_timeout = 60 - -# How to connect to the instance? fixed: using the first ip belongs -# the fixed network floating: creating and using a floating ip (string -# value) -#ssh_connect_method = fixed - -# Timeout in seconds to wait for authentication to succeed. (integer -# value) -#ssh_timeout = 300 - -# User name used to authenticate to an instance. (string value) -#ssh_user = root - -# Does SSH use Floating IPs? (boolean value) -#use_floatingip_for_ssh = true - -# Expected device name when a volume is attached to an instance -# (string value) -#volume_device_name = vdb - - -[compute-feature-enabled] -resize = true -live_migration = false -vnc_console = true -api_v3 = false -interface_attach = false - -# -# From tempest.config -# - -# A list of enabled compute extensions with a special entry all which -# indicates every extension is enabled. Each extension should be -# specified with alias name. Empty list indicates all extensions are -# disabled (list value) -#api_extensions = all - -# Does the test environment block migration support cinder iSCSI -# volumes (boolean value) -#block_migrate_cinder_iscsi = false - -# Does the test environment use block devices for live migration -# (boolean value) -#block_migration_for_live_migration = false - -# Does the test environment support changing the admin password? -# (boolean value) -#change_password = false - -# Does the test environment support obtaining instance serial console -# output? (boolean value) -#console_output = true - -# If false, skip disk config tests (boolean value) -#disk_config = true - -# Enables returning of the instance password by the relevant server -# API calls such as create, rebuild or rescue. (boolean value) -#enable_instance_password = true - -# Does the test environment support dynamic network interface -# attachment? (boolean value) -#interface_attach = true - -# Does the test environment support live migration available? (boolean -# value) -#live_migration = true - -# Does the test environment support pausing? (boolean value) -#pause = true - -# Enable RDP console. This configuration value should be same as -# [nova.rdp]->enabled in nova.conf (boolean value) -#rdp_console = false - -# Does the test environment support instance rescue mode? (boolean -# value) -#rescue = true - -# Does the test environment support resizing? (boolean value) -#resize = false - -# Does the test environment support shelving/unshelving? (boolean -# value) -#shelve = true - -# Does the test environment support creating snapshot images of -# running instances? (boolean value) -#snapshot = true - -# Enable Spice console. This configuration value should be same as -# [nova.spice]->enabled in nova.conf (boolean value) -#spice_console = false - -# Does the test environment support suspend/resume? (boolean value) -#suspend = true - -# Enable VNC console. This configuration value should be same as -# [nova.vnc]->vnc_enabled in nova.conf (boolean value) -#vnc_console = false - - -[dashboard] -dashboard_url = http://localhost/dashboard/ -login_url = http://localhost/dashboard/auth/login/ - -# -# From tempest.config -# - -# Where the dashboard can be found (string value) -#dashboard_url = http://localhost/ - -# Login page for the dashboard (string value) -#login_url = http://localhost/auth/login/ - - -[data_processing] - -# -# From tempest.config -# - -# Catalog type of the data processing service. (string value) -#catalog_type = data_processing - -# The endpoint type to use for the data processing service. (string -# value) -#endpoint_type = publicURL - - -[database] - -# -# From tempest.config -# - -# Catalog type of the Database service. (string value) -#catalog_type = database - -# Current database version to use in database tests. (string value) -#db_current_version = v1.0 - -# Valid primary flavor to use in database tests. (string value) -#db_flavor_ref = 1 - - -[debug] - -# -# From tempest.config -# - -# A regex to determine which requests should be traced. This is a -# regex to match the caller for rest client requests to be able to -# selectively trace calls out of specific classes and methods. It -# largely exists for test development, and is not expected to be used -# in a real deploy of tempest. This will be matched against the -# discovered ClassName:method in the test environment. Expected -# values for this field are: * ClassName:test_method_name - traces -# one test_method * ClassName:setUp(Class) - traces specific setup -# functions * ClassName:tearDown(Class) - traces specific teardown -# functions * ClassName:_run_cleanups - traces the cleanup functions -# If nothing is specified, this feature is not enabled. To trace -# everything specify .* as the regex. (string value) -#trace_requests = - - -[identity] -admin_username = admin -admin_role = admin -admin_tenant_name = admin -admin_password = keystone -alt_tenant_name = alt_demo -alt_username = alt_demo -alt_password = secret -tenant_name = demo -username = demo -password = secret -auth_version = v2 -catalog_type = identity -endpoint_type = publicURL -region = RegionOne -uri = http://127.0.0.1:5000/v2.0/ -uri_v3 = http://127.0.0.1:5000/v3/ - -# -# From tempest.config -# - -# Admin domain name for authentication (Keystone V3).The same domain -# applies to user and project (string value) -#admin_domain_name = - -# API key to use when authenticating as admin. (string value) -#admin_password = - -# Role required to administrate keystone. (string value) -#admin_role = admin - -# Administrative Tenant name to use for Keystone API requests. (string -# value) -#admin_tenant_name = - -# Administrative Username to use for Keystone API requests. (string -# value) -#admin_username = - -# Alternate domain name for authentication (Keystone V3).The same -# domain applies to user and project (string value) -#alt_domain_name = - -# API key to use when authenticating as alternate user. (string value) -#alt_password = - -# Alternate user's Tenant name to use for Nova API requests. (string -# value) -#alt_tenant_name = - -# Username of alternate user to use for Nova API requests. (string -# value) -#alt_username = - -# Identity API version to be used for authentication for API tests. -# (string value) -#auth_version = v2 - -# Specify a CA bundle file to use in verifying a TLS (https) server -# certificate. (string value) -#ca_certificates_file = - -# Catalog type of the Identity service. (string value) -#catalog_type = identity - -# Set to True if using self-signed SSL certificates. (boolean value) -#disable_ssl_certificate_validation = false - -# Domain name for authentication (Keystone V3).The same domain applies -# to user and project (string value) -#domain_name = - -# The endpoint type to use for the identity service. (string value) -#endpoint_type = publicURL - -# API key to use when authenticating. (string value) -#password = - -# The identity region name to use. Also used as the other services' -# region name unless they are set explicitly. If no such region is -# found in the service catalog, the first found one is used. (string -# value) -#region = RegionOne - -# Tenant name to use for Nova API requests. (string value) -#tenant_name = - -# Full URI of the OpenStack Identity API (Keystone), v2 (string value) -#uri = - -# Full URI of the OpenStack Identity API (Keystone), v3 (string value) -#uri_v3 = - -# Username to use for Nova API requests. (string value) -#username = - - -[identity-feature-enabled] - -# -# From tempest.config -# - -# Is the v2 identity API enabled (boolean value) -#api_v2 = true - -# Is the v3 identity API enabled (boolean value) -#api_v3 = true - -# Does the identity service have delegation and impersonation enabled -# (boolean value) -#trust = true - - -[image] -http_image = http://10.43.211.171/images/cirros-0.3.1-x86_64-disk.img -build_interval = 1 -build_timeout = 180 - -# -# From tempest.config -# - -# Catalog type of the Image service. (string value) -#catalog_type = image - -# The endpoint type to use for the image service. (string value) -#endpoint_type = publicURL - -# http accessible image (string value) -#http_image = http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz - -# The image region name to use. If empty, the value of identity.region -# is used instead. If no such region is found in the service catalog, -# the first found one is used. (string value) -#region = - - -[image-feature-enabled] - -# -# From tempest.config -# - -# Is the v1 image API enabled (boolean value) -#api_v1 = true - -# Is the v2 image API enabled (boolean value) -#api_v2 = true - - -[input-scenario] - -# -# From tempest.config -# - -# Matching flavors become parameters for scenario tests (string value) -#flavor_regex = ^m1.nano$ - -# Matching images become parameters for scenario tests (string value) -#image_regex = ^cirros-0.3.1-x86_64-uec$ - -# SSH verification in tests is skippedfor matching images (string -# value) -#non_ssh_image_regex = ^.*[Ww]in.*$ - -# List of user mapped to regex to matching image names. (string value) -#ssh_user_regex = [["^.*[Cc]irros.*$", "root"]] - - -[messaging] - -# -# From tempest.config -# - -# Catalog type of the Messaging service. (string value) -#catalog_type = messaging - -# The maximum grace period for a claim (integer value) -#max_claim_grace = 43200 - -# The maximum ttl for a claim (integer value) -#max_claim_ttl = 43200 - -# The maximum size of a message body (integer value) -#max_message_size = 262144 - -# The maximum ttl for a message (integer value) -#max_message_ttl = 1209600 - -# The maximum number of messages per claim (integer value) -#max_messages_per_claim = 20 - -# The maximum number of queue message per page when listing (or) -# posting messages (integer value) -#max_messages_per_page = 20 - -# The maximum metadata size for a queue (integer value) -#max_queue_metadata = 65536 - -# The maximum number of queue records per page when listing queues -# (integer value) -#max_queues_per_page = 20 - - -[negative] - -# -# From tempest.config -# - -# Test generator class for all negative tests (string value) -#test_generator = tempest.common.generator.negative_generator.NegativeTestGenerator - - -[network] -internal_network_id = 84b96c34-de5f-462e-96cb-ab36a07a3d18 -public_network_id = f968caee-ba4d-44ab-a9b3-2de9496ca98d -tenant_network_cidr = 192.168.0.0/24 -tenant_network_mask_bits = 28 -tenant_network_v6_cidr = 2003::/48 -tenant_network_v6_mask_bits = 50 -tenant_networks_reachable = false -public_router_id = 0cb7dad9-5db3-47ea-8d7e-f165332b5309 - -# -# From tempest.config -# - -# Time in seconds between network operation status checks. (integer -# value) -#build_interval = 1 - -# Timeout in seconds to wait for network operation to complete. -# (integer value) -#build_timeout = 300 - -# Catalog type of the Neutron service. (string value) -#catalog_type = network - -# List of dns servers which should be used for subnet creation (list -# value) -#dns_servers = 8.8.8.8,8.8.4.4 - -# The endpoint type to use for the network service. (string value) -#endpoint_type = publicURL - -# Id of the public network that provides external connectivity (string -# value) -#public_network_id = - -# Id of the public router that provides external connectivity. This -# should only be used when Neutron's 'allow_overlapping_ips' is set to -# 'False' in neutron.conf. usually not needed past 'Grizzly' release -# (string value) -#public_router_id = - -# The network region name to use. If empty, the value of -# identity.region is used instead. If no such region is found in the -# service catalog, the first found one is used. (string value) -#region = - -# The cidr block to allocate tenant ipv4 subnets from (string value) -#tenant_network_cidr = 10.100.0.0/16 - -# The mask bits for tenant ipv4 subnets (integer value) -#tenant_network_mask_bits = 28 - -# The cidr block to allocate tenant ipv6 subnets from (string value) -#tenant_network_v6_cidr = 2003::/48 - -# The mask bits for tenant ipv6 subnets (integer value) -#tenant_network_v6_mask_bits = 64 - -# Whether tenant network connectivity should be evaluated directly -# (boolean value) -#tenant_networks_reachable = false - - -[network-feature-enabled] -ipv6 = false -ipv6_subnet_attributes = false - -# -# From tempest.config -# - -# A list of enabled network extensions with a special entry all which -# indicates every extension is enabled. Empty list indicates all -# extensions are disabled (list value) -#api_extensions = all - -# Allow the execution of IPv6 tests (boolean value) -#ipv6 = true - -# Allow the execution of IPv6 subnet tests that use the extended IPv6 -# attributes ipv6_ra_mode and ipv6_address_mode (boolean value) -#ipv6_subnet_attributes = false - - -[object-storage] - -# -# From tempest.config -# - -# Catalog type of the Object-Storage service. (string value) -#catalog_type = object-store - -# Number of seconds to wait while looping to check the status of a -# container to container synchronization (integer value) -#container_sync_interval = 5 - -# Number of seconds to time on waiting for a container to container -# synchronization complete. (integer value) -#container_sync_timeout = 120 - -# The endpoint type to use for the object-store service. (string -# value) -#endpoint_type = publicURL - -# Role to add to users created for swift tests to enable creating -# containers (string value) -#operator_role = Member - -# The object-storage region name to use. If empty, the value of -# identity.region is used instead. If no such region is found in the -# service catalog, the first found one is used. (string value) -#region = - -# User role that has reseller admin (string value) -#reseller_admin_role = ResellerAdmin - - -[object-storage-feature-enabled] - -# -# From tempest.config -# - -# Execute (old style) container-sync tests (boolean value) -#container_sync = true - -# Execute discoverability tests (boolean value) -#discoverability = true - -# A list of the enabled optional discoverable apis. A single entry, -# all, indicates that all of these features are expected to be enabled -# (list value) -#discoverable_apis = all - -# Execute object-versioning tests (boolean value) -#object_versioning = true - - -[orchestration] - -# -# From tempest.config -# - -# Time in seconds between build status checks. (integer value) -#build_interval = 1 - -# Timeout in seconds to wait for a stack to build. (integer value) -#build_timeout = 1200 - -# Catalog type of the Orchestration service. (string value) -#catalog_type = orchestration - -# The endpoint type to use for the orchestration service. (string -# value) -#endpoint_type = publicURL - -# Name of heat-cfntools enabled image to use when launching test -# instances. (string value) -#image_ref = - -# Instance type for tests. Needs to be big enough for a full OS plus -# the test workload (string value) -#instance_type = m1.micro - -# Name of existing keypair to launch servers with. (string value) -#keypair_name = - -# Value must match heat configuration of the same name. (integer -# value) -#max_resources_per_stack = 1000 - -# Value must match heat configuration of the same name. (integer -# value) -#max_template_size = 524288 - -# The orchestration region name to use. If empty, the value of -# identity.region is used instead. If no such region is found in the -# service catalog, the first found one is used. (string value) -#region = - - -[scenario] -img_dir = /home/image -img_file = cirros-0.3.1-x86_64-disk.img -qcow2_img_file = cirros-0.3.1-x86_64-disk.img -qcow2_img_file_2 = xp-ssh.img -large_ops_number = 1 -ssh_user = cirros - -# -# From tempest.config -# - -# AKI image file name (string value) -#aki_img_file = cirros-0.3.1-x86_64-vmlinuz - -# AMI image file name (string value) -#ami_img_file = cirros-0.3.1-x86_64-blank.img - -# ARI image file name (string value) -#ari_img_file = cirros-0.3.1-x86_64-initrd - -# Image container format (string value) -#img_container_format = bare - -# Directory containing image files (string value) -#img_dir = /opt/stack/new/devstack/files/images/cirros-0.3.1-x86_64-uec - -# Image disk format (string value) -#img_disk_format = qcow2 - -# Image file name (string value) -# Deprecated group/name - [DEFAULT]/qcow2_img_file -#img_file = cirros-0.3.1-x86_64-disk.img - -# specifies how many resources to request at once. Used for large -# operations testing. (integer value) -#large_ops_number = 0 - -# ssh username for the image file (string value) -#ssh_user = cirros - - -[service_available] -ceilometer = false -cinder = true -glance = true -heat = false -horizon = true -ironic = false -neutron = true -nova = true -sahara = false -swift = false -trove = false -zaqar = false - -# -# From tempest.config -# - -# Whether or not Ceilometer is expected to be available (boolean -# value) -#ceilometer = true - -# Whether or not cinder is expected to be available (boolean value) -#cinder = true - -# Whether or not glance is expected to be available (boolean value) -#glance = true - -# Whether or not Heat is expected to be available (boolean value) -#heat = false - -# Whether or not Horizon is expected to be available (boolean value) -#horizon = true - -# Whether or not Ironic is expected to be available (boolean value) -#ironic = false - -# Whether or not neutron is expected to be available (boolean value) -#neutron = false - -# Whether or not nova is expected to be available (boolean value) -#nova = true - -# Whether or not Sahara is expected to be available (boolean value) -#sahara = false - -# Whether or not swift is expected to be available (boolean value) -#swift = true - -# Whether or not Trove is expected to be available (boolean value) -#trove = false - -# Whether or not Zaqar is expected to be available (boolean value) -#zaqar = false - - -[stress] - -# -# From tempest.config -# - -# Controller host. (string value) -#controller = - -# The number of threads created while stress test. (integer value) -#default_thread_number_per_action = 4 - -# Allows a full cleaning process after a stress test. Caution : this -# cleanup will remove every objects of every tenant. (boolean value) -#full_clean_stack = false - -# Prevent the cleaning (tearDownClass()) between each stress test run -# if an exception occurs during this run. (boolean value) -#leave_dirty_stack = false - -# time (in seconds) between log file error checks. (integer value) -#log_check_interval = 60 - -# Maximum number of instances to create during test. (integer value) -#max_instances = 16 - -# Directory containing log files on the compute nodes (string value) -#nova_logdir = - -# Controller host. (string value) -#target_controller = - -# regexp for list of log files. (string value) -#target_logfiles = - -# Path to private key. (string value) -#target_private_key_path = - -# ssh user. (string value) -#target_ssh_user = - - -[telemetry] - -# -# From tempest.config -# - -# Catalog type of the Telemetry service. (string value) -#catalog_type = metering - -# The endpoint type to use for the telemetry service. (string value) -#endpoint_type = publicURL - -# This variable is used as flag to enable notification tests (boolean -# value) -#too_slow_to_test = true - - -[volume] -build_timeout = 300 - -# -# From tempest.config -# - -# Name of the backend1 (must be declared in cinder.conf) (string -# value) -#backend1_name = BACKEND_1 - -# Name of the backend2 (must be declared in cinder.conf) (string -# value) -#backend2_name = BACKEND_2 - -# Time in seconds between volume availability checks. (integer value) -#build_interval = 1 - -# Timeout in seconds to wait for a volume to become available. -# (integer value) -#build_timeout = 300 - -# Catalog type of the Volume Service (string value) -#catalog_type = volume - -# Disk format to use when copying a volume to image (string value) -#disk_format = raw - -# The endpoint type to use for the volume service. (string value) -#endpoint_type = publicURL - -# The volume region name to use. If empty, the value of -# identity.region is used instead. If no such region is found in the -# service catalog, the first found one is used. (string value) -#region = - -# Backend protocol to target when creating volume types (string value) -#storage_protocol = iSCSI - -# Backend vendor to target when creating volume types (string value) -#vendor_name = Open Source - -# Default size in GB for volumes created by volumes tests (integer -# value) -#volume_size = 1 - - -[volume-feature-enabled] - -# -# From tempest.config -# - -# A list of enabled volume extensions with a special entry all which -# indicates every extension is enabled. Empty list indicates all -# extensions are disabled (list value) -#api_extensions = all - -# Is the v1 volume API enabled (boolean value) -#api_v1 = true - -# Is the v2 volume API enabled (boolean value) -#api_v2 = true - -# Runs Cinder volumes backup test (boolean value) -#backup = true - -# Runs Cinder multi-backend test (requires 2 backends) (boolean value) -#multi_backend = false - -# Runs Cinder volume snapshot test (boolean value) -#snapshot = true - - -[tecs] -host_ip = 10.43.211.177 -host_username = root -host_password = ossdbg1 - - -v4_flavor_id = 51a6f3f3-816d-4bc6-a762-797fd4e78a2a -v4_omcnet_id = 3d409993-f4cb-4acd-8ab9-5258feab0f01 -v4_basenet_id = 974588bb-b552-46d0-ae83-ffe5ac7e4205 -v4_fabricnet_id = -v4_outnet_id = - -#added for network test -network_image_id = be99d4c9-5c01-47ba-a075-9c0102b6fb44 -network_flavor_id = c79328e9-71dc-4870-bafe-a77f484d5d0e -network_ssh_user = root -network_ssh_pwd = ossdbg1 -network_server_ipaddr = 10.43.20.231 -network_server_ssh_user = root -network_server_ssh_pwd = q1w2e3 -network_server_ftp_user = vr -network_server_ftp_pwd = vr -network_lb_provider= haproxy - -[daisy] -#°Ñip»»³É°²×°daisyµÄʵ¼Êip -daisy_endpoint=http://127.0.0.1:19292 - -#жÔصļ¯Èºid£¬Èç¹û²»Ìîд¾Í´ÓÊý¾Ý¿âÖжÁÈ¡×îºóÒ»¸ö -cluster_id= - -#°²×°tecs(Ò»¶ÔhaµÄÁ½¸ö¿ØÖƽڵã)µÄÄ¿±ê»úµÄÍø¿Ú£¬ÒÔ¼°¸ÃÍø¿ÚÉϵÄip£¬macµØÖ·£¬¸¡¶¯ip -#ha°²×°Ê±Á½¸ö¿ØÖƽڵãµÄÍø¿ÚÃû±ØÐëÒ»Ñù£¬¸¡¶¯ip£¨vip£©±ØÐ뱣֤û±»Õ¼Óà -#Ò»¶Ô¿ØÖƽڵãµÄÁ½¸öipºÍmacµØÖ·£¬Ê¹ÓöººÅ·Ö¿ª¡£¸ñʽÀýÈç(10.43.177.127,10.43.177.128) -install_ha_eth_name=eth1 -install_ha_ip=192.0.1.149,192.0.2.19 -install_ha_netmask=255.0.0.0,255.0.0.0 -install_ha_mac=fa:16:3e:3a:51:4e,fa:16:3e:fc:05:3d -install_ha_vip=192.0.1.254 - -#°²×°tecsµÄ³¬Ê±Ê±¼ä(Ãë) -time_out=10800 - diff --git a/test/tempest/openstack-common.conf b/test/tempest/openstack-common.conf deleted file mode 100644 index 19202957..00000000 --- a/test/tempest/openstack-common.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -module=install_venv_common -module=versionutils - -# The base module to hold the copy of openstack.common -base=tempest diff --git a/test/tempest/requirements.txt b/test/tempest/requirements.txt deleted file mode 100644 index 0d7fc0dc..00000000 --- a/test/tempest/requirements.txt +++ /dev/null @@ -1,26 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -pbr>=0.6,!=0.7,<1.0 -anyjson>=0.3.3 -httplib2>=0.7.5 -jsonschema>=2.0.0,<3.0.0 -testtools>=0.9.36,!=1.2.0 -boto>=2.32.1 -paramiko>=1.13.0 -netaddr>=0.7.12 -python-glanceclient>=0.15.0 -python-cinderclient>=1.1.0 -python-heatclient>=0.3.0 -testrepository>=0.0.18 -oslo.concurrency>=1.8.0,<1.9.0 # Apache-2.0 -oslo.config>=1.9.3,<1.10.0 # Apache-2.0 -oslo.i18n>=1.5.0,<1.6.0 # Apache-2.0 -oslo.log>=1.0.0,<1.1.0 # Apache-2.0 -oslo.serialization>=1.4.0,<1.5.0 # Apache-2.0 -oslo.utils>=1.4.0,<1.5.0 # Apache-2.0 -six>=1.9.0 -iso8601>=0.1.9 -fixtures>=0.3.14 -testscenarios>=0.4 -tempest-lib>=0.4.0 diff --git a/test/tempest/run_tempest.sh b/test/tempest/run_tempest.sh deleted file mode 100644 index 5a9b7425..00000000 --- a/test/tempest/run_tempest.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env bash - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run Tempest test suite" - echo "" - echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" - echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" - echo " -n, --no-site-packages Isolate the virtualenv from the global Python environment" - echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." - echo " -u, --update Update the virtual environment with any newer package versions" - echo " -s, --smoke Only run smoke tests" - echo " -t, --serial Run testr serially" - echo " -C, --config Config file location" - echo " -h, --help Print this usage message" - echo " -d, --debug Run tests with testtools instead of testr. This allows you to use PDB" - echo " -l, --logging Enable logging" - echo " -L, --logging-config Logging config file location. Default is etc/logging.conf" - echo " -- [TESTROPTIONS] After the first '--' you can pass arbitrary arguments to testr " -} - -testrargs="" -venv=.venv -with_venv=tools/with_venv.sh -serial=0 -always_venv=0 -never_venv=0 -no_site_packages=0 -debug=0 -force=0 -wrapper="" -config_file="" -update=0 -logging=0 -logging_config=etc/logging.conf - -if ! options=$(getopt -o VNnfusthdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,help,debug,config:,logging,logging-config: -- "$@") -then - # parse error - usage - exit 1 -fi - -eval set -- $options -first_uu=yes -while [ $# -gt 0 ]; do - case "$1" in - -h|--help) usage; exit;; - -V|--virtual-env) always_venv=1; never_venv=0;; - -N|--no-virtual-env) always_venv=0; never_venv=1;; - -n|--no-site-packages) no_site_packages=1;; - -f|--force) force=1;; - -u|--update) update=1;; - -d|--debug) debug=1;; - -C|--config) config_file=$2; shift;; - -s|--smoke) testrargs+="smoke";; - -t|--serial) serial=1;; - -l|--logging) logging=1;; - -L|--logging-config) logging_config=$2; shift;; - --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no ;; - *) testrargs="$testrargs $1";; - esac - shift -done - -if [ -n "$config_file" ]; then - config_file=`readlink -f "$config_file"` - export TEMPEST_CONFIG_DIR=`dirname "$config_file"` - export TEMPEST_CONFIG=`basename "$config_file"` -fi - -if [ $logging -eq 1 ]; then - if [ ! -f "$logging_config" ]; then - echo "No such logging config file: $logging_config" - exit 1 - fi - logging_config=`readlink -f "$logging_config"` - export TEMPEST_LOG_CONFIG_DIR=`dirname "$logging_config"` - export TEMPEST_LOG_CONFIG=`basename "$logging_config"` -fi - -cd `dirname "$0"` - -if [ $no_site_packages -eq 1 ]; then - installvenvopts="--no-site-packages" -fi - -function testr_init { - if [ ! -d .testrepository ]; then - ${wrapper} testr init - fi -} - -function run_tests { - testr_init - ${wrapper} find . -type f -name "*.pyc" -delete - export OS_TEST_PATH=./tempest/test_discover - if [ $debug -eq 1 ]; then - if [ "$testrargs" = "" ]; then - testrargs="discover ./tempest/test_discover" - fi - ${wrapper} python -m testtools.run $testrargs - return $? - fi - - if [ $serial -eq 1 ]; then - ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py - else - ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py - fi -} - -if [ $never_venv -eq 0 ] -then - # Remove the virtual environment if --force used - if [ $force -eq 1 ]; then - echo "Cleaning virtualenv..." - rm -rf ${venv} - fi - if [ $update -eq 1 ]; then - echo "Updating virtualenv..." - python tools/install_venv.py $installvenvopts - fi - if [ -e ${venv} ]; then - wrapper="${with_venv}" - else - if [ $always_venv -eq 1 ]; then - # Automatically install the virtualenv - python tools/install_venv.py $installvenvopts - wrapper="${with_venv}" - else - echo -e "No virtual environment found...create one? (Y/n) \c" - read use_ve - if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then - # Install the virtualenv and run the test suite in it - python tools/install_venv.py $installvenvopts - wrapper=${with_venv} - fi - fi - fi -fi - -run_tests -retval=$? - -exit $retval diff --git a/test/tempest/run_tests.sh b/test/tempest/run_tests.sh deleted file mode 100644 index 971f89bd..00000000 --- a/test/tempest/run_tests.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env bash - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run Tempest unit tests" - echo "" - echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" - echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" - echo " -n, --no-site-packages Isolate the virtualenv from the global Python environment" - echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." - echo " -u, --update Update the virtual environment with any newer package versions" - echo " -t, --serial Run testr serially" - echo " -p, --pep8 Just run pep8" - echo " -c, --coverage Generate coverage report" - echo " -h, --help Print this usage message" - echo " -d, --debug Run tests with testtools instead of testr. This allows you to use PDB" - echo " -- [TESTROPTIONS] After the first '--' you can pass arbitrary arguments to testr " -} - -testrargs="" -just_pep8=0 -venv=.venv -with_venv=tools/with_venv.sh -serial=0 -always_venv=0 -never_venv=0 -no_site_packages=0 -debug=0 -force=0 -coverage=0 -wrapper="" -config_file="" -update=0 - -if ! options=$(getopt -o VNnfuctphd -l virtual-env,no-virtual-env,no-site-packages,force,update,serial,coverage,pep8,help,debug -- "$@") -then - # parse error - usage - exit 1 -fi - -eval set -- $options -first_uu=yes -while [ $# -gt 0 ]; do - case "$1" in - -h|--help) usage; exit;; - -V|--virtual-env) always_venv=1; never_venv=0;; - -N|--no-virtual-env) always_venv=0; never_venv=1;; - -n|--no-site-packages) no_site_packages=1;; - -f|--force) force=1;; - -u|--update) update=1;; - -d|--debug) debug=1;; - -p|--pep8) let just_pep8=1;; - -c|--coverage) coverage=1;; - -t|--serial) serial=1;; - --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no ;; - *) testrargs="$testrargs $1";; - esac - shift -done - - -cd `dirname "$0"` - -if [ $no_site_packages -eq 1 ]; then - installvenvopts="--no-site-packages" -fi - -function testr_init { - if [ ! -d .testrepository ]; then - ${wrapper} testr init - fi -} - -function run_tests { - testr_init - ${wrapper} find . -type f -name "*.pyc" -delete - export OS_TEST_PATH=./tempest/tests - if [ $debug -eq 1 ]; then - if [ "$testrargs" = "" ]; then - testrargs="discover ./tempest/tests" - fi - ${wrapper} python -m testtools.run $testrargs - return $? - fi - - if [ $coverage -eq 1 ]; then - ${wrapper} python setup.py test --coverage - return $? - fi - - if [ $serial -eq 1 ]; then - ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py - else - ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py - fi -} - -function run_pep8 { - echo "Running flake8 ..." - if [ $never_venv -eq 1 ]; then - echo "**WARNING**:" >&2 - echo "Running flake8 without virtual env may miss OpenStack HACKING detection" >&2 - fi - ${wrapper} flake8 -} - -if [ $never_venv -eq 0 ] -then - # Remove the virtual environment if --force used - if [ $force -eq 1 ]; then - echo "Cleaning virtualenv..." - rm -rf ${venv} - fi - if [ $update -eq 1 ]; then - echo "Updating virtualenv..." - python tools/install_venv.py $installvenvopts - fi - if [ -e ${venv} ]; then - wrapper="${with_venv}" - else - if [ $always_venv -eq 1 ]; then - # Automatically install the virtualenv - python tools/install_venv.py $installvenvopts - wrapper="${with_venv}" - else - echo -e "No virtual environment found...create one? (Y/n) \c" - read use_ve - if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then - # Install the virtualenv and run the test suite in it - python tools/install_venv.py $installvenvopts - wrapper=${with_venv} - fi - fi - fi -fi - -if [ $just_pep8 -eq 1 ]; then - run_pep8 - exit -fi - -run_tests -retval=$? - -if [ -z "$testrargs" ]; then - run_pep8 -fi - -exit $retval diff --git a/test/tempest/setup.cfg b/test/tempest/setup.cfg deleted file mode 100644 index 1e7cc2be..00000000 --- a/test/tempest/setup.cfg +++ /dev/null @@ -1,36 +0,0 @@ -[metadata] -name = tempest -version = 4 -summary = OpenStack Integration Testing -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://www.openstack.org/ -classifier = - Intended Audience :: Information Technology - Intended Audience :: System Administrators - Intended Audience :: Developers - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - -[entry_points] -console_scripts = - verify-tempest-config = tempest.cmd.verify_tempest_config:main - javelin2 = tempest.cmd.javelin:main - run-tempest-stress = tempest.cmd.run_stress:main - tempest-cleanup = tempest.cmd.cleanup:main - -oslo.config.opts = - tempest.config = tempest.config:list_opts - -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source - -[wheel] -universal = 1 diff --git a/test/tempest/setup.py b/test/tempest/setup.py deleted file mode 100644 index 73637574..00000000 --- a/test/tempest/setup.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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 FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr'], - pbr=True) diff --git a/test/tempest/tempest/api/README.rst b/test/tempest/tempest/api/README.rst deleted file mode 100644 index 91e6ad6b..00000000 --- a/test/tempest/tempest/api/README.rst +++ /dev/null @@ -1,52 +0,0 @@ -.. _api_field_guide: - -Tempest Field Guide to API tests -================================ - - -What are these tests? ---------------------- - -One of Tempest's prime function is to ensure that your OpenStack cloud -works with the OpenStack API as documented. The current largest -portion of Tempest code is devoted to test cases that do exactly this. - -It's also important to test not only the expected positive path on -APIs, but also to provide them with invalid data to ensure they fail -in expected and documented ways. Over the course of the OpenStack -project Tempest has discovered many fundamental bugs by doing just -this. - -In order for some APIs to return meaningful results, there must be -enough data in the system. This means these tests might start by -spinning up a server, image, etc, then operating on it. - - -Why are these tests in tempest? -------------------------------- - -This is one of the core missions for the Tempest project, and where it -started. Many people use this bit of function in Tempest to ensure -their clouds haven't broken the OpenStack API. - -It could be argued that some of the negative testing could be done -back in the projects themselves, and we might evolve there over time, -but currently in the OpenStack gate this is a fundamentally important -place to keep things. - - -Scope of these tests --------------------- - -API tests should always use the Tempest implementation of the -OpenStack API, as we want to ensure that bugs aren't hidden by the -official clients. - -They should test specific API calls, and can build up complex state if -it's needed for the API call to be meaningful. - -They should send not only good data, but bad data at the API and look -for error codes. - -They should all be able to be run on their own, not depending on the -state created by a previous test. diff --git a/test/tempest/tempest/api/daisy/v1/__init__.py b/test/tempest/tempest/api/daisy/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api/daisy/v1/fake/__init__.py b/test/tempest/tempest/api/daisy/v1/fake/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/__init__.py b/test/tempest/tempest/api_schema/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/request/__init__.py b/test/tempest/tempest/api_schema/request/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/request/compute/__init__.py b/test/tempest/tempest/api_schema/request/compute/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/request/compute/flavors.py b/test/tempest/tempest/api_schema/request/compute/flavors.py deleted file mode 100644 index adaaf270..00000000 --- a/test/tempest/tempest/api_schema/request/compute/flavors.py +++ /dev/null @@ -1,58 +0,0 @@ -# (c) 2014 Deutsche Telekom AG -# 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. - -common_flavor_details = { - "name": "get-flavor-details", - "http-method": "GET", - "url": "flavors/%s", - "resources": [ - {"name": "flavor", "expected_result": 404} - ] -} - -common_flavor_list = { - "name": "list-flavors-with-detail", - "http-method": "GET", - "url": "flavors/detail", - "json-schema": { - "type": "object", - "properties": { - } - } -} - -common_admin_flavor_create = { - "name": "flavor-create", - "http-method": "POST", - "admin_client": True, - "url": "flavors", - "default_result_code": 400, - "json-schema": { - "type": "object", - "properties": { - "flavor": { - "type": "object", - "properties": { - "name": {"type": "string", - "exclude_tests": ["gen_str_min_length"]}, - "ram": {"type": "integer", "minimum": 1}, - "vcpus": {"type": "integer", "minimum": 1}, - "disk": {"type": "integer"}, - "id": {"type": "integer", - "exclude_tests": ["gen_none", "gen_string"] - }, - } - } - } - } -} diff --git a/test/tempest/tempest/api_schema/request/compute/v2/__init__.py b/test/tempest/tempest/api_schema/request/compute/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/request/compute/v2/flavors.py b/test/tempest/tempest/api_schema/request/compute/v2/flavors.py deleted file mode 100644 index bc459ad4..00000000 --- a/test/tempest/tempest/api_schema/request/compute/v2/flavors.py +++ /dev/null @@ -1,39 +0,0 @@ -# (c) 2014 Deutsche Telekom AG -# 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.api_schema.request.compute import flavors - -flavors_details = copy.deepcopy(flavors.common_flavor_details) - -flavor_list = copy.deepcopy(flavors.common_flavor_list) - -flavor_create = copy.deepcopy(flavors.common_admin_flavor_create) - -flavor_list["json-schema"]["properties"] = { - "minRam": { - "type": "integer", - "results": { - "gen_none": 400, - "gen_string": 400 - } - }, - "minDisk": { - "type": "integer", - "results": { - "gen_none": 400, - "gen_string": 400 - } - } -} diff --git a/test/tempest/tempest/api_schema/response/__init__.py b/test/tempest/tempest/api_schema/response/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/response/compute/__init__.py b/test/tempest/tempest/api_schema/response/compute/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/response/compute/baremetal_nodes.py b/test/tempest/tempest/api_schema/response/compute/baremetal_nodes.py deleted file mode 100644 index 82506e77..00000000 --- a/test/tempest/tempest/api_schema/response/compute/baremetal_nodes.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2015 NEC 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 - -node = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'interfaces': {'type': 'array'}, - 'host': {'type': 'string'}, - 'task_state': {'type': ['string', 'null']}, - 'cpus': {'type': ['integer', 'string']}, - 'memory_mb': {'type': ['integer', 'string']}, - 'disk_gb': {'type': ['integer', 'string']}, - }, - 'required': ['id', 'interfaces', 'host', 'task_state', 'cpus', 'memory_mb', - 'disk_gb'] -} - -list_baremetal_nodes = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'nodes': { - 'type': 'array', - 'items': node - } - }, - 'required': ['nodes'] - } -} - -baremetal_node = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'node': node - }, - 'required': ['node'] - } -} -get_baremetal_node = copy.deepcopy(baremetal_node) -get_baremetal_node['response_body']['properties']['node'][ - 'properties'].update({'instance_uuid': {'type': ['string', 'null']}}) -get_baremetal_node['response_body']['properties']['node'][ - 'required'].append('instance_uuid') diff --git a/test/tempest/tempest/api_schema/response/compute/flavors_access.py b/test/tempest/tempest/api_schema/response/compute/flavors_access.py deleted file mode 100644 index cd31b0a9..00000000 --- a/test/tempest/tempest/api_schema/response/compute/flavors_access.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2014 NEC 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. - -add_remove_list_flavor_access = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'flavor_access': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'flavor_id': {'type': 'string'}, - 'tenant_id': {'type': 'string'}, - }, - 'required': ['flavor_id', 'tenant_id'], - } - } - }, - 'required': ['flavor_access'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/flavors_extra_specs.py b/test/tempest/tempest/api_schema/response/compute/flavors_extra_specs.py deleted file mode 100644 index 4003d367..00000000 --- a/test/tempest/tempest/api_schema/response/compute/flavors_extra_specs.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2014 NEC 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. - -flavor_extra_specs = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'extra_specs': { - 'type': 'object', - 'patternProperties': { - '^[a-zA-Z0-9_\-\. :]+$': {'type': 'string'} - } - } - }, - 'required': ['extra_specs'] - } -} - -flavor_extra_specs_key = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'patternProperties': { - '^[a-zA-Z0-9_\-\. :]+$': {'type': 'string'} - } - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/migrations.py b/test/tempest/tempest/api_schema/response/compute/migrations.py deleted file mode 100644 index c38492ad..00000000 --- a/test/tempest/tempest/api_schema/response/compute/migrations.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2014 NEC 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. - -list_migrations = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'migrations': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'integer'}, - 'status': {'type': 'string'}, - 'instance_uuid': {'type': 'string'}, - 'source_node': {'type': 'string'}, - 'source_compute': {'type': 'string'}, - 'dest_node': {'type': 'string'}, - 'dest_compute': {'type': 'string'}, - 'dest_host': {'type': 'string'}, - # zfl : tecs 1.0 old_instance_type_id is None - # 'old_instance_type_id': {'type': 'integer'}, - 'new_instance_type_id': {'type': 'integer'}, - 'created_at': {'type': 'string'}, - 'updated_at': {'type': ['string', 'null']} - }, - 'required': [ - 'id', 'status', 'instance_uuid', 'source_node', - 'source_compute', 'dest_node', 'dest_compute', - 'dest_host', 'old_instance_type_id', - 'new_instance_type_id', 'created_at', 'updated_at' - ] - } - } - }, - 'required': ['migrations'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/parameter_types.py b/test/tempest/tempest/api_schema/response/compute/parameter_types.py deleted file mode 100644 index 90d4c8f7..00000000 --- a/test/tempest/tempest/api_schema/response/compute/parameter_types.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2014 NEC 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. - -links = { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'href': { - 'type': 'string', - 'format': 'uri' - }, - 'rel': {'type': 'string'} - }, - 'required': ['href', 'rel'] - } -} - -mac_address = { - 'type': 'string', - 'pattern': '(?:[a-f0-9]{2}:){5}[a-f0-9]{2}' -} - -access_ip_v4 = { - 'type': 'string', - 'anyOf': [{'format': 'ipv4'}, {'enum': ['']}] -} - -access_ip_v6 = { - 'type': 'string', - 'anyOf': [{'format': 'ipv6'}, {'enum': ['']}] -} - -addresses = { - 'type': 'object', - 'patternProperties': { - # NOTE: Here is for 'private' or something. - '^[a-zA-Z0-9-_.]+$': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'version': {'type': 'integer'}, - 'addr': { - 'type': 'string', - 'anyOf': [ - {'format': 'ipv4'}, - {'format': 'ipv6'} - ] - } - }, - 'required': ['version', 'addr'] - } - } - } -} - -response_header = { - 'connection': {'type': 'string'}, - 'content-length': {'type': 'string'}, - 'content-type': {'type': 'string'}, - 'status': {'type': 'string'}, - 'x-compute-request-id': {'type': 'string'}, - 'vary': {'type': 'string'}, - 'x-openstack-nova-api-version': {'type': 'string'}, - 'date': { - 'type': 'string', - 'format': 'data-time' - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/services.py b/test/tempest/tempest/api_schema/response/compute/services.py deleted file mode 100644 index 6f361ef8..00000000 --- a/test/tempest/tempest/api_schema/response/compute/services.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2014 NEC 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. - -list_services = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'services': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': ['integer', 'string'], - 'pattern': '^[a-zA-Z!]*@[0-9]+$'}, - 'zone': {'type': 'string'}, - 'host': {'type': 'string'}, - 'state': {'type': 'string'}, - 'binary': {'type': 'string'}, - 'status': {'type': 'string'}, - 'updated_at': {'type': ['string', 'null']}, - 'disabled_reason': {'type': ['string', 'null']} - }, - 'required': ['id', 'zone', 'host', 'state', 'binary', - 'status', 'updated_at', 'disabled_reason'] - } - } - }, - 'required': ['services'] - } -} - -enable_service = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'service': { - 'type': 'object', - 'properties': { - 'status': {'type': 'string'}, - 'binary': {'type': 'string'}, - 'host': {'type': 'string'} - }, - 'required': ['status', 'binary', 'host'] - } - }, - 'required': ['service'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/__init__.py b/test/tempest/tempest/api_schema/response/compute/v2_1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/agents.py b/test/tempest/tempest/api_schema/response/compute/v2_1/agents.py deleted file mode 100644 index 84c5fd31..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/agents.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2014 NEC 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. - -common_agent_info = { - 'type': 'object', - 'properties': { - 'agent_id': {'type': ['integer', 'string']}, - 'hypervisor': {'type': 'string'}, - 'os': {'type': 'string'}, - 'architecture': {'type': 'string'}, - 'version': {'type': 'string'}, - 'url': {'type': 'string', 'format': 'uri'}, - 'md5hash': {'type': 'string'} - }, - 'required': ['agent_id', 'hypervisor', 'os', 'architecture', - 'version', 'url', 'md5hash'] -} - -list_agents = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'agents': { - 'type': 'array', - 'items': common_agent_info - } - }, - 'required': ['agents'] - } -} - -create_agent = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'agent': common_agent_info - }, - 'required': ['agent'] - } -} - -delete_agent = { - 'status_code': [200] -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/aggregates.py b/test/tempest/tempest/api_schema/response/compute/v2_1/aggregates.py deleted file mode 100644 index c935592e..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/aggregates.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2014 NEC 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 - -# create-aggregate api doesn't have 'hosts' and 'metadata' attributes. -aggregate_for_create = { - 'type': 'object', - 'properties': { - 'availability_zone': {'type': ['string', 'null']}, - 'created_at': {'type': 'string'}, - 'deleted': {'type': 'boolean'}, - 'deleted_at': {'type': ['string', 'null']}, - 'id': {'type': 'integer'}, - 'name': {'type': 'string'}, - 'updated_at': {'type': ['string', 'null']} - }, - 'required': ['availability_zone', 'created_at', 'deleted', - 'deleted_at', 'id', 'name', 'updated_at'], -} - -common_aggregate_info = copy.deepcopy(aggregate_for_create) -common_aggregate_info['properties'].update({ - 'hosts': {'type': 'array'}, - 'metadata': {'type': 'object'} -}) -common_aggregate_info['required'].extend(['hosts', 'metadata']) - -list_aggregates = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'aggregates': { - 'type': 'array', - 'items': common_aggregate_info - } - }, - 'required': ['aggregates'], - } -} - -get_aggregate = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'aggregate': common_aggregate_info - }, - 'required': ['aggregate'], - } -} - -aggregate_set_metadata = get_aggregate -# The 'updated_at' attribute of 'update_aggregate' can't be null. -update_aggregate = copy.deepcopy(get_aggregate) -update_aggregate['response_body']['properties']['aggregate']['properties'][ - 'updated_at'] = { - 'type': 'string' - } - -delete_aggregate = { - 'status_code': [200] -} - -create_aggregate = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'aggregate': aggregate_for_create - }, - 'required': ['aggregate'], - } -} - -aggregate_add_remove_host = get_aggregate diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/availability_zone.py b/test/tempest/tempest/api_schema/response/compute/v2_1/availability_zone.py deleted file mode 100644 index 5c1224e2..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/availability_zone.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2014 NEC 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 - - -base = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'availabilityZoneInfo': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'zoneName': {'type': 'string'}, - 'zoneState': { - 'type': 'object', - 'properties': { - 'available': {'type': 'boolean'} - }, - 'required': ['available'] - }, - # NOTE: Here is the difference between detail and - # non-detail. - 'hosts': {'type': 'null'} - }, - 'required': ['zoneName', 'zoneState', 'hosts'] - } - } - }, - 'required': ['availabilityZoneInfo'] - } -} - -detail = { - 'type': 'object', - 'patternProperties': { - # NOTE: Here is for a hostname - '^[a-zA-Z0-9-_.]+$': { - 'type': 'object', - 'patternProperties': { - # NOTE: Here is for a service name - '^.*$': { - 'type': 'object', - 'properties': { - 'available': {'type': 'boolean'}, - 'active': {'type': 'boolean'}, - 'updated_at': {'type': ['string', 'null']} - }, - 'required': ['available', 'active', 'updated_at'] - } - } - } - } -} - -list_availability_zone_list = copy.deepcopy(base) - -list_availability_zone_list_detail = copy.deepcopy(base) -list_availability_zone_list_detail['response_body']['properties'][ - 'availabilityZoneInfo']['items']['properties']['hosts'] = detail diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/certificates.py b/test/tempest/tempest/api_schema/response/compute/v2_1/certificates.py deleted file mode 100644 index 35445d81..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/certificates.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2014 NEC 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 - -_common_schema = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'certificate': { - 'type': 'object', - 'properties': { - 'data': {'type': 'string'}, - 'private_key': {'type': 'string'}, - }, - 'required': ['data', 'private_key'] - } - }, - 'required': ['certificate'] - } -} - -get_certificate = copy.deepcopy(_common_schema) -get_certificate['response_body']['properties']['certificate'][ - 'properties']['private_key'].update({'type': 'null'}) - -create_certificate = copy.deepcopy(_common_schema) diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/extensions.py b/test/tempest/tempest/api_schema/response/compute/v2_1/extensions.py deleted file mode 100644 index 570cd030..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/extensions.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2014 NEC 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. - -list_extensions = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'extensions': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'updated': { - 'type': 'string', - 'format': 'data-time' - }, - 'name': {'type': 'string'}, - 'links': {'type': 'array'}, - 'namespace': { - 'type': 'string', - 'format': 'uri' - }, - 'alias': {'type': 'string'}, - 'description': {'type': 'string'} - }, - 'required': ['updated', 'name', 'links', 'namespace', - 'alias', 'description'] - } - } - }, - 'required': ['extensions'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/fixed_ips.py b/test/tempest/tempest/api_schema/response/compute/v2_1/fixed_ips.py deleted file mode 100644 index 13e70bfb..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/fixed_ips.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2014 NEC 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. - -get_fixed_ip = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'fixed_ip': { - 'type': 'object', - 'properties': { - 'address': { - 'type': 'string', - 'format': 'ip-address' - }, - 'cidr': {'type': 'string'}, - 'host': {'type': 'string'}, - 'hostname': {'type': 'string'} - }, - 'required': ['address', 'cidr', 'host', 'hostname'] - } - }, - 'required': ['fixed_ip'] - } -} - -reserve_fixed_ip = { - 'status_code': [202], - 'response_body': {'type': 'string'} -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/flavors.py b/test/tempest/tempest/api_schema/response/compute/v2_1/flavors.py deleted file mode 100644 index 725d17a0..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/flavors.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright 2014 NEC 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.api_schema.response.compute import parameter_types - -list_flavors = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'flavors': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'name': {'type': 'string'}, - 'links': parameter_types.links, - 'id': {'type': 'string'} - }, - 'required': ['name', 'links', 'id'] - } - }, - 'flavors_links': parameter_types.links - }, - # NOTE(gmann): flavors_links attribute is not necessary - # to be present always So it is not 'required'. - 'required': ['flavors'] - } -} - -common_flavor_info = { - 'type': 'object', - 'properties': { - 'name': {'type': 'string'}, - 'links': parameter_types.links, - 'ram': {'type': 'integer'}, - 'vcpus': {'type': 'integer'}, - # 'swap' attributes comes as integer value but if it is empty - # it comes as "". So defining type of as string and integer. - 'swap': {'type': ['integer', 'string']}, - 'disk': {'type': 'integer'}, - 'id': {'type': 'string'}, - 'OS-FLV-DISABLED:disabled': {'type': 'boolean'}, - 'os-flavor-access:is_public': {'type': 'boolean'}, - 'rxtx_factor': {'type': 'number'}, - 'OS-FLV-EXT-DATA:ephemeral': {'type': 'integer'} - }, - # 'OS-FLV-DISABLED', 'os-flavor-access', 'rxtx_factor' and - # 'OS-FLV-EXT-DATA' are API extensions. So they are not 'required'. - 'required': ['name', 'links', 'ram', 'vcpus', 'swap', 'disk', 'id'] -} - -list_flavors_details = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'flavors': { - 'type': 'array', - 'items': common_flavor_info - }, - # NOTE(gmann): flavors_links attribute is not necessary - # to be present always So it is not 'required'. - 'flavors_links': parameter_types.links - }, - 'required': ['flavors'] - } -} - -unset_flavor_extra_specs = { - 'status_code': [200] -} - -create_get_flavor_details = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'flavor': common_flavor_info - }, - 'required': ['flavor'] - } -} - -delete_flavor = { - 'status_code': [202] -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/floating_ips.py b/test/tempest/tempest/api_schema/response/compute/v2_1/floating_ips.py deleted file mode 100644 index 7369becb..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/floating_ips.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright 2014 NEC 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. - -common_floating_ip_info = { - 'type': 'object', - 'properties': { - # NOTE: Now the type of 'id' is integer, but - # here allows 'string' also because we will be - # able to change it to 'uuid' in the future. - 'id': {'type': ['integer', 'string']}, - 'pool': {'type': ['string', 'null']}, - 'instance_id': {'type': ['string', 'null']}, - 'ip': { - 'type': 'string', - 'format': 'ip-address' - }, - 'fixed_ip': { - 'type': ['string', 'null'], - 'format': 'ip-address' - } - }, - 'required': ['id', 'pool', 'instance_id', - 'ip', 'fixed_ip'], - -} -list_floating_ips = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ips': { - 'type': 'array', - 'items': common_floating_ip_info - }, - }, - 'required': ['floating_ips'], - } -} - -floating_ip = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ip': common_floating_ip_info - }, - 'required': ['floating_ip'], - } -} - -floating_ip_pools = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ip_pools': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'name': {'type': 'string'} - }, - 'required': ['name'], - } - } - }, - 'required': ['floating_ip_pools'], - } -} - -add_remove_floating_ip = { - 'status_code': [202] -} - -create_floating_ips_bulk = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ips_bulk_create': { - 'type': 'object', - 'properties': { - 'interface': {'type': ['string', 'null']}, - 'ip_range': {'type': 'string'}, - 'pool': {'type': ['string', 'null']}, - }, - 'required': ['interface', 'ip_range', 'pool'], - } - }, - 'required': ['floating_ips_bulk_create'], - } -} - -delete_floating_ips_bulk = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ips_bulk_delete': {'type': 'string'} - }, - 'required': ['floating_ips_bulk_delete'], - } -} - -list_floating_ips_bulk = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'floating_ip_info': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'address': { - 'type': 'string', - 'format': 'ip-address' - }, - 'instance_uuid': {'type': ['string', 'null']}, - 'interface': {'type': ['string', 'null']}, - 'pool': {'type': ['string', 'null']}, - 'project_id': {'type': ['string', 'null']}, - 'fixed_ip': { - 'type': ['string', 'null'], - 'format': 'ip-address' - } - }, - # NOTE: fixed_ip is introduced after JUNO release, - # So it is not defined as 'required'. - 'required': ['address', 'instance_uuid', 'interface', - 'pool', 'project_id'], - } - } - }, - 'required': ['floating_ip_info'], - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/hosts.py b/test/tempest/tempest/api_schema/response/compute/v2_1/hosts.py deleted file mode 100644 index 72d5a07c..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/hosts.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2014 NEC 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 - - -list_hosts = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hosts': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'host_name': {'type': 'string'}, - 'service': {'type': 'string'}, - 'zone': {'type': 'string'} - }, - 'required': ['host_name', 'service', 'zone'] - } - } - }, - 'required': ['hosts'] - } -} - -get_host_detail = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'host': { - 'type': 'array', - 'item': { - 'type': 'object', - 'properties': { - 'resource': { - 'type': 'object', - 'properties': { - 'cpu': {'type': 'integer'}, - 'disk_gb': {'type': 'integer'}, - 'host': {'type': 'string'}, - 'memory_mb': {'type': 'integer'}, - 'project': {'type': 'string'} - }, - 'required': ['cpu', 'disk_gb', 'host', - 'memory_mb', 'project'] - } - }, - 'required': ['resource'] - } - } - }, - 'required': ['host'] - } -} - -startup_host = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'host': {'type': 'string'}, - 'power_action': {'enum': ['startup']} - }, - 'required': ['host', 'power_action'] - } -} - -# The 'power_action' attribute of 'shutdown_host' API is 'shutdown' -shutdown_host = copy.deepcopy(startup_host) - -shutdown_host['response_body']['properties']['power_action'] = { - 'enum': ['shutdown'] -} - -# The 'power_action' attribute of 'reboot_host' API is 'reboot' -reboot_host = copy.deepcopy(startup_host) - -reboot_host['response_body']['properties']['power_action'] = { - 'enum': ['reboot'] -} - -update_host = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'host': {'type': 'string'}, - 'maintenance_mode': {'enum': ['on_maintenance', - 'off_maintenance']}, - 'status': {'enum': ['enabled', 'disabled']} - }, - 'required': ['host', 'maintenance_mode', 'status'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/hypervisors.py b/test/tempest/tempest/api_schema/response/compute/v2_1/hypervisors.py deleted file mode 100644 index 3efa46b4..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/hypervisors.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2014 NEC 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 - -get_hypervisor_statistics = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hypervisor_statistics': { - 'type': 'object', - 'properties': { - 'count': {'type': 'integer'}, - 'current_workload': {'type': 'integer'}, - 'disk_available_least': {'type': ['integer', 'null']}, - 'free_disk_gb': {'type': 'integer'}, - 'free_ram_mb': {'type': 'integer'}, - 'local_gb': {'type': 'integer'}, - 'local_gb_used': {'type': 'integer'}, - 'memory_mb': {'type': 'integer'}, - 'memory_mb_used': {'type': 'integer'}, - 'running_vms': {'type': 'integer'}, - 'vcpus': {'type': 'integer'}, - 'vcpus_used': {'type': 'integer'} - }, - 'required': ['count', 'current_workload', - 'disk_available_least', 'free_disk_gb', - 'free_ram_mb', 'local_gb', 'local_gb_used', - 'memory_mb', 'memory_mb_used', 'running_vms', - 'vcpus', 'vcpus_used'] - } - }, - 'required': ['hypervisor_statistics'] - } -} - - -hypervisor_detail = { - 'type': 'object', - 'properties': { - 'status': {'type': 'string'}, - 'state': {'type': 'string'}, - 'cpu_info': {'type': 'string'}, - 'current_workload': {'type': 'integer'}, - 'disk_available_least': {'type': ['integer', 'null']}, - 'host_ip': { - 'type': 'string', - 'format': 'ip-address' - }, - 'free_disk_gb': {'type': 'integer'}, - 'free_ram_mb': {'type': 'integer'}, - 'hypervisor_hostname': {'type': 'string'}, - 'hypervisor_type': {'type': 'string'}, - 'hypervisor_version': {'type': 'integer'}, - 'id': {'type': ['integer', 'string']}, - 'local_gb': {'type': 'integer'}, - 'local_gb_used': {'type': 'integer'}, - 'memory_mb': {'type': 'integer'}, - 'memory_mb_used': {'type': 'integer'}, - 'running_vms': {'type': 'integer'}, - 'service': { - 'type': 'object', - 'properties': { - 'host': {'type': 'string'}, - 'id': {'type': ['integer', 'string']}, - 'disabled_reason': {'type': ['string', 'null']} - }, - 'required': ['host', 'id'] - }, - 'vcpus': {'type': 'integer'}, - 'vcpus_used': {'type': 'integer'} - }, - # NOTE: When loading os-hypervisor-status extension, - # a response contains status and state. So these params - # should not be required. - 'required': ['cpu_info', 'current_workload', - 'disk_available_least', 'host_ip', - 'free_disk_gb', 'free_ram_mb', - 'hypervisor_hostname', 'hypervisor_type', - 'hypervisor_version', 'id', 'local_gb', - 'local_gb_used', 'memory_mb', 'memory_mb_used', - 'running_vms', 'service', 'vcpus', 'vcpus_used'] -} - -list_hypervisors_detail = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hypervisors': { - 'type': 'array', - 'items': hypervisor_detail - } - }, - 'required': ['hypervisors'] - } -} - -get_hypervisor = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hypervisor': hypervisor_detail - }, - 'required': ['hypervisor'] - } -} - -list_search_hypervisors = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hypervisors': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'status': {'type': 'string'}, - 'state': {'type': 'string'}, - 'id': {'type': ['integer', 'string']}, - 'hypervisor_hostname': {'type': 'string'} - }, - # NOTE: When loading os-hypervisor-status extension, - # a response contains status and state. So these params - # should not be required. - 'required': ['id', 'hypervisor_hostname'] - } - } - }, - 'required': ['hypervisors'] - } -} - -get_hypervisor_uptime = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'hypervisor': { - 'type': 'object', - 'properties': { - 'status': {'type': 'string'}, - 'state': {'type': 'string'}, - 'id': {'type': ['integer', 'string']}, - 'hypervisor_hostname': {'type': 'string'}, - 'uptime': {'type': 'string'} - }, - # NOTE: When loading os-hypervisor-status extension, - # a response contains status and state. So these params - # should not be required. - 'required': ['id', 'hypervisor_hostname', 'uptime'] - } - }, - 'required': ['hypervisor'] - } -} - -get_hypervisors_servers = copy.deepcopy(list_search_hypervisors) -get_hypervisors_servers['response_body']['properties']['hypervisors']['items'][ - 'properties']['servers'] = { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'uuid': {'type': 'string'}, - 'name': {'type': 'string'} - } - } - } -# In V2 API, if there is no servers (VM) on the Hypervisor host then 'servers' -# attribute will not be present in response body So it is not 'required'. diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/images.py b/test/tempest/tempest/api_schema/response/compute/v2_1/images.py deleted file mode 100644 index 3c0b80e7..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/images.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright 2014 NEC 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.api_schema.response.compute import parameter_types - -image_links = copy.deepcopy(parameter_types.links) -image_links['items']['properties'].update({'type': {'type': 'string'}}) - -common_image_schema = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'status': {'type': 'string'}, - 'updated': {'type': 'string'}, - 'links': image_links, - 'name': {'type': 'string'}, - 'created': {'type': 'string'}, - 'minDisk': {'type': 'integer'}, - 'minRam': {'type': 'integer'}, - 'progress': {'type': 'integer'}, - 'metadata': {'type': 'object'}, - 'server': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': parameter_types.links - }, - 'required': ['id', 'links'] - }, - 'OS-EXT-IMG-SIZE:size': {'type': 'integer'}, - 'OS-DCF:diskConfig': {'type': 'string'} - }, - # 'server' attributes only comes in response body if image is - # associated with any server. 'OS-EXT-IMG-SIZE:size' & 'OS-DCF:diskConfig' - # are API extension, So those are not defined as 'required'. - 'required': ['id', 'status', 'updated', 'links', 'name', - 'created', 'minDisk', 'minRam', 'progress', - 'metadata'] -} - -get_image = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'image': common_image_schema - }, - 'required': ['image'] - } -} - -list_images = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'images': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': image_links, - 'name': {'type': 'string'} - }, - 'required': ['id', 'links', 'name'] - } - }, - 'images_links': parameter_types.links - }, - # NOTE(gmann): images_links attribute is not necessary to be - # present always So it is not 'required'. - 'required': ['images'] - } -} - -create_image = { - 'status_code': [202], - 'response_header': { - 'type': 'object', - 'properties': parameter_types.response_header - } -} -create_image['response_header']['properties'].update( - {'location': { - 'type': 'string', - 'format': 'uri'} - } -) -create_image['response_header']['required'] = ['location'] - -delete = { - 'status_code': [204] -} - -image_metadata = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'metadata': {'type': 'object'} - }, - 'required': ['metadata'] - } -} - -image_meta_item = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'meta': {'type': 'object'} - }, - 'required': ['meta'] - } -} - -list_images_details = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'images': { - 'type': 'array', - 'items': common_image_schema - }, - 'images_links': parameter_types.links - }, - # NOTE(gmann): images_links attribute is not necessary to be - # present always So it is not 'required'. - 'required': ['images'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py b/test/tempest/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py deleted file mode 100644 index 658f5746..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2014 NEC 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. - -common_instance_usage_audit_log = { - 'type': 'object', - 'properties': { - 'hosts_not_run': { - 'type': 'array', - 'items': {'type': 'string'} - }, - 'log': {'type': 'object'}, - 'num_hosts': {'type': 'integer'}, - 'num_hosts_done': {'type': 'integer'}, - 'num_hosts_not_run': {'type': 'integer'}, - 'num_hosts_running': {'type': 'integer'}, - 'overall_status': {'type': 'string'}, - 'period_beginning': {'type': 'string'}, - 'period_ending': {'type': 'string'}, - 'total_errors': {'type': 'integer'}, - 'total_instances': {'type': 'integer'} - }, - 'required': ['hosts_not_run', 'log', 'num_hosts', 'num_hosts_done', - 'num_hosts_not_run', 'num_hosts_running', 'overall_status', - 'period_beginning', 'period_ending', 'total_errors', - 'total_instances'] -} - -get_instance_usage_audit_log = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'instance_usage_audit_log': common_instance_usage_audit_log - }, - 'required': ['instance_usage_audit_log'] - } -} - -list_instance_usage_audit_log = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'instance_usage_audit_logs': common_instance_usage_audit_log - }, - 'required': ['instance_usage_audit_logs'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/interfaces.py b/test/tempest/tempest/api_schema/response/compute/v2_1/interfaces.py deleted file mode 100644 index 4de33098..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/interfaces.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2014 NEC 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.api_schema.response.compute import parameter_types - -interface_common_info = { - 'type': 'object', - 'properties': { - 'port_state': {'type': 'string'}, - 'fixed_ips': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'subnet_id': { - 'type': 'string', - 'format': 'uuid' - }, - 'ip_address': { - 'type': 'string', - 'format': 'ipv4' - } - }, - 'required': ['subnet_id', 'ip_address'] - } - }, - 'port_id': {'type': 'string', 'format': 'uuid'}, - 'net_id': {'type': 'string', 'format': 'uuid'}, - 'mac_addr': parameter_types.mac_address - }, - 'required': ['port_state', 'fixed_ips', 'port_id', 'net_id', 'mac_addr'] -} - -get_create_interfaces = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'interfaceAttachment': interface_common_info - }, - 'required': ['interfaceAttachment'] - } -} - -list_interfaces = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'interfaceAttachments': { - 'type': 'array', - 'items': interface_common_info - } - }, - 'required': ['interfaceAttachments'] - } -} - -delete_interface = { - 'status_code': [202] -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/keypairs.py b/test/tempest/tempest/api_schema/response/compute/v2_1/keypairs.py deleted file mode 100644 index ceae6cf9..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/keypairs.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2014 NEC 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. - -get_keypair = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'keypair': { - 'type': 'object', - 'properties': { - 'public_key': {'type': 'string'}, - 'name': {'type': 'string'}, - 'fingerprint': {'type': 'string'}, - 'user_id': {'type': 'string'}, - 'deleted': {'type': 'boolean'}, - 'created_at': {'type': 'string'}, - 'updated_at': {'type': ['string', 'null']}, - 'deleted_at': {'type': ['string', 'null']}, - 'id': {'type': 'integer'} - - }, - # When we run the get keypair API, response body includes - # all the above mentioned attributes. - # But in Nova API sample file, response body includes only - # 'public_key', 'name' & 'fingerprint'. So only 'public_key', - # 'name' & 'fingerprint' are defined as 'required'. - 'required': ['public_key', 'name', 'fingerprint'] - } - }, - 'required': ['keypair'] - } -} - -create_keypair = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'keypair': { - 'type': 'object', - 'properties': { - 'fingerprint': {'type': 'string'}, - 'name': {'type': 'string'}, - 'public_key': {'type': 'string'}, - 'user_id': {'type': 'string'}, - 'private_key': {'type': 'string'} - }, - # When create keypair API is being called with 'Public key' - # (Importing keypair) then, response body does not contain - # 'private_key' So it is not defined as 'required' - 'required': ['fingerprint', 'name', 'public_key', 'user_id'] - } - }, - 'required': ['keypair'] - } -} - -delete_keypair = { - 'status_code': [202], -} - -list_keypairs = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'keypairs': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'keypair': { - 'type': 'object', - 'properties': { - 'public_key': {'type': 'string'}, - 'name': {'type': 'string'}, - 'fingerprint': {'type': 'string'} - }, - 'required': ['public_key', 'name', 'fingerprint'] - } - }, - 'required': ['keypair'] - } - } - }, - 'required': ['keypairs'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/limits.py b/test/tempest/tempest/api_schema/response/compute/v2_1/limits.py deleted file mode 100644 index a7decb7b..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/limits.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2014 NEC 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. - -get_limit = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'limits': { - 'type': 'object', - 'properties': { - 'absolute': { - 'type': 'object', - 'properties': { - 'maxTotalRAMSize': {'type': 'integer'}, - 'totalCoresUsed': {'type': 'integer'}, - 'maxTotalInstances': {'type': 'integer'}, - 'maxTotalFloatingIps': {'type': 'integer'}, - 'totalSecurityGroupsUsed': {'type': 'integer'}, - 'maxTotalCores': {'type': 'integer'}, - 'totalFloatingIpsUsed': {'type': 'integer'}, - 'maxSecurityGroups': {'type': 'integer'}, - 'maxServerMeta': {'type': 'integer'}, - 'maxPersonality': {'type': 'integer'}, - 'maxImageMeta': {'type': 'integer'}, - 'maxPersonalitySize': {'type': 'integer'}, - 'maxSecurityGroupRules': {'type': 'integer'}, - 'maxTotalKeypairs': {'type': 'integer'}, - 'totalRAMUsed': {'type': 'integer'}, - 'totalInstancesUsed': {'type': 'integer'}, - 'maxServerGroupMembers': {'type': 'integer'}, - 'maxServerGroups': {'type': 'integer'}, - 'totalServerGroupsUsed': {'type': 'integer'} - }, - # NOTE(gmann): maxServerGroupMembers, maxServerGroups - # and totalServerGroupsUsed are API extension, - # and some environments return a response without these - # attributes.So they are not 'required'. - 'required': ['maxImageMeta', - 'maxPersonality', - 'maxPersonalitySize', - 'maxSecurityGroupRules', - 'maxSecurityGroups', - 'maxServerMeta', - 'maxTotalCores', - 'maxTotalFloatingIps', - 'maxTotalInstances', - 'maxTotalKeypairs', - 'maxTotalRAMSize', - 'totalCoresUsed', - 'totalFloatingIpsUsed', - 'totalInstancesUsed', - 'totalRAMUsed', - 'totalSecurityGroupsUsed'] - }, - 'rate': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'limit': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'next-available': - {'type': 'string'}, - 'remaining': - {'type': 'integer'}, - 'unit': - {'type': 'string'}, - 'value': - {'type': 'integer'}, - 'verb': - {'type': 'string'} - } - } - }, - 'regex': {'type': 'string'}, - 'uri': {'type': 'string'} - } - } - } - }, - 'required': ['absolute', 'rate'] - } - }, - 'required': ['limits'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/quota_classes.py b/test/tempest/tempest/api_schema/response/compute/v2_1/quota_classes.py deleted file mode 100644 index a0cdaf56..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/quota_classes.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2014 IBM 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.api_schema.response.compute.v2_1 import quotas - -# NOTE(mriedem): os-quota-class-sets responses are the same as os-quota-sets -# except for the key in the response body is quota_class_set instead of -# quota_set, so update this copy of the schema from os-quota-sets. -get_quota_class_set = copy.deepcopy(quotas.get_quota_set) -get_quota_class_set['response_body']['properties']['quota_class_set'] = ( - get_quota_class_set['response_body']['properties'].pop('quota_set')) -get_quota_class_set['response_body']['required'] = ['quota_class_set'] - -update_quota_class_set = copy.deepcopy(quotas.update_quota_set) -update_quota_class_set['response_body']['properties']['quota_class_set'] = ( - update_quota_class_set['response_body']['properties'].pop('quota_set')) -update_quota_class_set['response_body']['required'] = ['quota_class_set'] diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/quotas.py b/test/tempest/tempest/api_schema/response/compute/v2_1/quotas.py deleted file mode 100644 index 9141f7e5..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/quotas.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2014 NEC 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 - -update_quota_set = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'quota_set': { - 'type': 'object', - 'properties': { - 'instances': {'type': 'integer'}, - 'cores': {'type': 'integer'}, - 'ram': {'type': 'integer'}, - 'floating_ips': {'type': 'integer'}, - 'fixed_ips': {'type': 'integer'}, - 'metadata_items': {'type': 'integer'}, - 'key_pairs': {'type': 'integer'}, - 'security_groups': {'type': 'integer'}, - 'security_group_rules': {'type': 'integer'}, - 'server_group_members': {'type': 'integer'}, - 'server_groups': {'type': 'integer'}, - 'injected_files': {'type': 'integer'}, - 'injected_file_content_bytes': {'type': 'integer'}, - 'injected_file_path_bytes': {'type': 'integer'} - }, - # NOTE: server_group_members and server_groups are represented - # when enabling quota_server_group extension. So they should - # not be required. - 'required': ['instances', 'cores', 'ram', - 'floating_ips', 'fixed_ips', - 'metadata_items', 'key_pairs', - 'security_groups', 'security_group_rules', - 'injected_files', 'injected_file_content_bytes', - 'injected_file_path_bytes'] - } - }, - 'required': ['quota_set'] - } -} - -get_quota_set = copy.deepcopy(update_quota_set) -get_quota_set['response_body']['properties']['quota_set']['properties'][ - 'id'] = {'type': 'string'} -get_quota_set['response_body']['properties']['quota_set']['required'].extend([ - 'id']) - -delete_quota = { - 'status_code': [202] -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py b/test/tempest/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py deleted file mode 100644 index 9246ab87..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2014 NEC 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. - -common_security_group_default_rule_info = { - 'type': 'object', - 'properties': { - 'from_port': {'type': 'integer'}, - 'id': {'type': 'integer'}, - 'ip_protocol': {'type': 'string'}, - 'ip_range': { - 'type': 'object', - 'properties': { - 'cidr': {'type': 'string'} - }, - 'required': ['cidr'], - }, - 'to_port': {'type': 'integer'}, - }, - 'required': ['from_port', 'id', 'ip_protocol', 'ip_range', 'to_port'], -} - -create_get_security_group_default_rule = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'security_group_default_rule': - common_security_group_default_rule_info - }, - 'required': ['security_group_default_rule'] - } -} - -delete_security_group_default_rule = { - 'status_code': [204] -} - -list_security_group_default_rules = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'security_group_default_rules': { - 'type': 'array', - 'items': common_security_group_default_rule_info - } - }, - 'required': ['security_group_default_rules'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/security_groups.py b/test/tempest/tempest/api_schema/response/compute/v2_1/security_groups.py deleted file mode 100644 index 9a852e52..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/security_groups.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2014 NEC 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. - -common_security_group_rule = { - 'from_port': {'type': ['integer', 'null']}, - 'to_port': {'type': ['integer', 'null']}, - 'group': { - 'type': 'object', - 'properties': { - 'tenant_id': {'type': 'string'}, - 'name': {'type': 'string'} - } - }, - 'ip_protocol': {'type': ['string', 'null']}, - # 'parent_group_id' can be UUID so defining it as 'string' also. - 'parent_group_id': {'type': ['string', 'integer', 'null']}, - 'ip_range': { - 'type': 'object', - 'properties': { - 'cidr': {'type': 'string'} - } - # When optional argument is provided in request body - # like 'group_id' then, attribute 'cidr' does not - # comes in response body. So it is not 'required'. - }, - 'id': {'type': ['string', 'integer']} -} - -common_security_group = { - 'type': 'object', - 'properties': { - 'id': {'type': ['integer', 'string']}, - 'name': {'type': 'string'}, - 'tenant_id': {'type': 'string'}, - 'rules': { - 'type': 'array', - 'items': { - 'type': ['object', 'null'], - 'properties': common_security_group_rule - } - }, - 'description': {'type': 'string'}, - }, - 'required': ['id', 'name', 'tenant_id', 'rules', 'description'], -} - -list_security_groups = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'security_groups': { - 'type': 'array', - 'items': common_security_group - } - }, - 'required': ['security_groups'] - } -} - -get_security_group = create_security_group = update_security_group = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'security_group': common_security_group - }, - 'required': ['security_group'] - } -} - -delete_security_group = { - 'status_code': [202] -} - -create_security_group_rule = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'security_group_rule': { - 'type': 'object', - 'properties': common_security_group_rule, - 'required': ['from_port', 'to_port', 'group', 'ip_protocol', - 'parent_group_id', 'id', 'ip_range'] - } - }, - 'required': ['security_group_rule'] - } -} - -delete_security_group_rule = { - 'status_code': [202] -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/servers.py b/test/tempest/tempest/api_schema/response/compute/v2_1/servers.py deleted file mode 100644 index 2ecf5262..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/servers.py +++ /dev/null @@ -1,520 +0,0 @@ -# Copyright 2014 NEC 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.api_schema.response.compute import parameter_types - -create_server = { - 'status_code': [202], - 'response_body': { - 'type': 'object', - 'properties': { - 'server': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'security_groups': {'type': 'array'}, - 'links': parameter_types.links, - 'OS-DCF:diskConfig': {'type': 'string'} - }, - # NOTE: OS-DCF:diskConfig & security_groups are API extension, - # and some environments return a response without these - # attributes.So they are not 'required'. - 'required': ['id', 'links'] - } - }, - 'required': ['server'] - } -} - -create_server_with_admin_pass = copy.deepcopy(create_server) -create_server_with_admin_pass['response_body']['properties']['server'][ - 'properties'].update({'adminPass': {'type': 'string'}}) -create_server_with_admin_pass['response_body']['properties']['server'][ - 'required'].append('adminPass') - -list_servers = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'servers': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': parameter_types.links, - 'name': {'type': 'string'} - }, - 'required': ['id', 'links', 'name'] - } - }, - 'servers_links': parameter_types.links - }, - # NOTE(gmann): servers_links attribute is not necessary to be - # present always So it is not 'required'. - 'required': ['servers'] - } -} - -delete_server = { - 'status_code': [204], -} - -common_show_server = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'name': {'type': 'string'}, - 'status': {'type': 'string'}, - 'image': {'oneOf': [ - {'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': parameter_types.links - }, - 'required': ['id', 'links']}, - {'type': ['string', 'null']} - ]}, - 'flavor': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': parameter_types.links - }, - 'required': ['id', 'links'] - }, - 'fault': { - 'type': 'object', - 'properties': { - 'code': {'type': 'integer'}, - 'created': {'type': 'string'}, - 'message': {'type': 'string'}, - 'details': {'type': 'string'}, - }, - # NOTE(gmann): 'details' is not necessary to be present - # in the 'fault'. So it is not defined as 'required'. - 'required': ['code', 'created', 'message'] - }, - 'user_id': {'type': 'string'}, - 'tenant_id': {'type': 'string'}, - 'created': {'type': 'string'}, - 'updated': {'type': 'string'}, - 'progress': {'type': 'integer'}, - 'metadata': {'type': 'object'}, - 'links': parameter_types.links, - 'addresses': parameter_types.addresses, - 'hostId': {'type': 'string'}, - 'OS-DCF:diskConfig': {'type': 'string'}, - 'accessIPv4': parameter_types.access_ip_v4, - 'accessIPv6': parameter_types.access_ip_v6 - }, - # NOTE(GMann): 'progress' attribute is present in the response - # only when server's status is one of the progress statuses - # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE") - # 'fault' attribute is present in the response - # only when server's status is one of the "ERROR", "DELETED". - # OS-DCF:diskConfig and accessIPv4/v6 are API - # extensions, and some environments return a response - # without these attributes.So these are not defined as 'required'. - 'required': ['id', 'name', 'status', 'image', 'flavor', - 'user_id', 'tenant_id', 'created', 'updated', - 'metadata', 'links', 'addresses', 'hostId'] -} - -update_server = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'server': common_show_server - }, - 'required': ['server'] - } -} - -server_detail = copy.deepcopy(common_show_server) -server_detail['properties'].update({ - 'key_name': {'type': ['string', 'null']}, - 'security_groups': {'type': 'array'}, - - # NOTE: Non-admin users also can see "OS-SRV-USG" and "OS-EXT-AZ" - # attributes. - 'OS-SRV-USG:launched_at': {'type': ['string', 'null']}, - 'OS-SRV-USG:terminated_at': {'type': ['string', 'null']}, - 'OS-EXT-AZ:availability_zone': {'type': 'string'}, - - # NOTE: Admin users only can see "OS-EXT-STS" and "OS-EXT-SRV-ATTR" - # attributes. - 'OS-EXT-STS:task_state': {'type': ['string', 'null']}, - 'OS-EXT-STS:vm_state': {'type': 'string'}, - 'OS-EXT-STS:power_state': {'type': 'integer'}, - 'OS-EXT-SRV-ATTR:host': {'type': ['string', 'null']}, - 'OS-EXT-SRV-ATTR:instance_name': {'type': 'string'}, - 'OS-EXT-SRV-ATTR:hypervisor_hostname': {'type': ['string', 'null']}, - 'os-extended-volumes:volumes_attached': {'type': 'array'}, - 'config_drive': {'type': 'string'} -}) -server_detail['properties']['addresses']['patternProperties'][ - '^[a-zA-Z0-9-_.]+$']['items']['properties'].update({ - 'OS-EXT-IPS:type': {'type': 'string'}, - 'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address}) -# NOTE(gmann): Update OS-EXT-IPS:type and OS-EXT-IPS-MAC:mac_addr -# attributes in server address. Those are API extension, -# and some environments return a response without -# these attributes. So they are not 'required'. - -get_server = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'server': server_detail - }, - 'required': ['server'] - } -} - -list_servers_detail = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'servers': { - 'type': 'array', - 'items': server_detail - }, - 'servers_links': parameter_types.links - }, - # NOTE(gmann): servers_links attribute is not necessary to be - # present always So it is not 'required'. - 'required': ['servers'] - } -} - -rebuild_server = copy.deepcopy(update_server) -rebuild_server['status_code'] = [202] - -rebuild_server_with_admin_pass = copy.deepcopy(rebuild_server) -rebuild_server_with_admin_pass['response_body']['properties']['server'][ - 'properties'].update({'adminPass': {'type': 'string'}}) -rebuild_server_with_admin_pass['response_body']['properties']['server'][ - 'required'].append('adminPass') - -rescue_server = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'adminPass': {'type': 'string'} - }, - 'required': ['adminPass'] - } -} - -evacuate_server = copy.deepcopy(rescue_server) - -list_virtual_interfaces = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'virtual_interfaces': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'mac_address': parameter_types.mac_address, - 'OS-EXT-VIF-NET:net_id': {'type': 'string'} - }, - # 'OS-EXT-VIF-NET:net_id' is API extension So it is - # not defined as 'required' - 'required': ['id', 'mac_address'] - } - } - }, - 'required': ['virtual_interfaces'] - } -} - -common_attach_volume_info = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'device': {'type': 'string'}, - 'volumeId': {'type': 'string'}, - 'serverId': {'type': ['integer', 'string']} - }, - 'required': ['id', 'device', 'volumeId', 'serverId'] -} - -attach_volume = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'volumeAttachment': common_attach_volume_info - }, - 'required': ['volumeAttachment'] - } -} - -detach_volume = { - 'status_code': [202] -} - -get_volume_attachment = copy.deepcopy(attach_volume) -get_volume_attachment['response_body']['properties'][ - 'volumeAttachment']['properties'].update({'serverId': {'type': 'string'}}) - -list_volume_attachments = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'volumeAttachments': { - 'type': 'array', - 'items': common_attach_volume_info - } - }, - 'required': ['volumeAttachments'] - } -} -list_volume_attachments['response_body']['properties'][ - 'volumeAttachments']['items']['properties'].update( - {'serverId': {'type': 'string'}}) - -list_addresses_by_network = { - 'status_code': [200], - 'response_body': parameter_types.addresses -} - -list_addresses = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'addresses': parameter_types.addresses - }, - 'required': ['addresses'] - } -} - -common_server_group = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'name': {'type': 'string'}, - 'policies': { - 'type': 'array', - 'items': {'type': 'string'} - }, - # 'members' attribute contains the array of instance's UUID of - # instances present in server group - 'members': { - 'type': 'array', - 'items': {'type': 'string'} - }, - 'metadata': {'type': 'object'} - }, - 'required': ['id', 'name', 'policies', 'members', 'metadata'] -} - -create_get_server_group = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'server_group': common_server_group - }, - 'required': ['server_group'] - } -} - -delete_server_group = { - 'status_code': [204] -} - -list_server_groups = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'server_groups': { - 'type': 'array', - 'items': common_server_group - } - }, - 'required': ['server_groups'] - } -} - -instance_actions = { - 'type': 'object', - 'properties': { - 'action': {'type': 'string'}, - 'request_id': {'type': 'string'}, - 'user_id': {'type': 'string'}, - 'project_id': {'type': 'string'}, - 'start_time': {'type': 'string'}, - 'message': {'type': ['string', 'null']}, - 'instance_uuid': {'type': 'string'} - }, - 'required': ['action', 'request_id', 'user_id', 'project_id', - 'start_time', 'message', 'instance_uuid'] -} - -instance_action_events = { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'event': {'type': 'string'}, - 'start_time': {'type': 'string'}, - 'finish_time': {'type': 'string'}, - 'result': {'type': 'string'}, - 'traceback': {'type': ['string', 'null']} - }, - 'required': ['event', 'start_time', 'finish_time', 'result', - 'traceback'] - } -} - -list_instance_actions = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'instanceActions': { - 'type': 'array', - 'items': instance_actions - } - }, - 'required': ['instanceActions'] - } -} - -instance_actions_with_events = copy.deepcopy(instance_actions) -instance_actions_with_events['properties'].update({ - 'events': instance_action_events}) -# 'events' does not come in response body always so it is not -# defined as 'required' - -get_instance_action = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'instanceAction': instance_actions_with_events - }, - 'required': ['instanceAction'] - } -} - -get_password = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'password': {'type': 'string'} - }, - 'required': ['password'] - } -} - -get_vnc_console = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'console': { - 'type': 'object', - 'properties': { - 'type': {'type': 'string'}, - 'url': { - 'type': 'string', - 'format': 'uri' - } - }, - 'required': ['type', 'url'] - } - }, - 'required': ['console'] - } -} - -get_console_output = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'output': {'type': 'string'} - }, - 'required': ['output'] - } -} - -set_server_metadata = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'metadata': { - 'type': 'object', - 'patternProperties': { - '^.+$': {'type': 'string'} - } - } - }, - 'required': ['metadata'] - } -} - -list_server_metadata = copy.deepcopy(set_server_metadata) - -update_server_metadata = copy.deepcopy(set_server_metadata) - -delete_server_metadata_item = { - 'status_code': [204] -} - -set_get_server_metadata_item = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'meta': { - 'type': 'object', - 'patternProperties': { - '^.+$': {'type': 'string'} - } - } - }, - 'required': ['meta'] - } -} - -server_actions_common_schema = { - 'status_code': [202] -} - -server_actions_delete_password = { - 'status_code': [204] -} - -server_actions_confirm_resize = copy.deepcopy( - server_actions_delete_password) diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_networks.py b/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_networks.py deleted file mode 100644 index 0b2868a7..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_networks.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2015 NEC 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. - -param_network = { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'cidr': {'type': ['string', 'null']}, - 'label': {'type': 'string'} - }, - 'required': ['id', 'cidr', 'label'] -} - - -list_tenant_networks = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'networks': { - 'type': 'array', - 'items': param_network - } - }, - 'required': ['networks'] - } -} - - -get_tenant_network = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'network': param_network - }, - 'required': ['network'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_usages.py b/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_usages.py deleted file mode 100644 index 0b824a1c..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/tenant_usages.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2014 NEC 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 - -_server_usages = { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'ended_at': { - 'oneOf': [ - {'type': 'string'}, - {'type': 'null'} - ] - }, - 'flavor': {'type': 'string'}, - 'hours': {'type': 'number'}, - 'instance_id': {'type': 'string'}, - 'local_gb': {'type': 'integer'}, - 'memory_mb': {'type': 'integer'}, - 'name': {'type': 'string'}, - 'started_at': {'type': 'string'}, - 'state': {'type': 'string'}, - 'tenant_id': {'type': 'string'}, - 'uptime': {'type': 'integer'}, - 'vcpus': {'type': 'integer'}, - }, - 'required': ['ended_at', 'flavor', 'hours', 'instance_id', 'local_gb', - 'memory_mb', 'name', 'started_at', 'state', 'tenant_id', - 'uptime', 'vcpus'] - } -} - -_tenant_usage_list = { - 'type': 'object', - 'properties': { - 'server_usages': _server_usages, - 'start': {'type': 'string'}, - 'stop': {'type': 'string'}, - 'tenant_id': {'type': 'string'}, - 'total_hours': {'type': 'number'}, - 'total_local_gb_usage': {'type': 'number'}, - 'total_memory_mb_usage': {'type': 'number'}, - 'total_vcpus_usage': {'type': 'number'}, - }, - 'required': ['start', 'stop', 'tenant_id', - 'total_hours', 'total_local_gb_usage', - 'total_memory_mb_usage', 'total_vcpus_usage'] -} - -# 'required' of get_tenant is different from list_tenant's. -_tenant_usage_get = copy.deepcopy(_tenant_usage_list) -_tenant_usage_get['required'] = ['server_usages', 'start', 'stop', 'tenant_id', - 'total_hours', 'total_local_gb_usage', - 'total_memory_mb_usage', 'total_vcpus_usage'] - -list_tenant = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'tenant_usages': { - 'type': 'array', - 'items': _tenant_usage_list - } - }, - 'required': ['tenant_usages'] - } -} - -get_tenant = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'tenant_usage': _tenant_usage_get - }, - 'required': ['tenant_usage'] - } -} diff --git a/test/tempest/tempest/api_schema/response/compute/v2_1/volumes.py b/test/tempest/tempest/api_schema/response/compute/v2_1/volumes.py deleted file mode 100644 index 541d3ff2..00000000 --- a/test/tempest/tempest/api_schema/response/compute/v2_1/volumes.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2014 NEC 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. - -create_get_volume = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'volume': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'status': {'type': 'string'}, - 'displayName': {'type': ['string', 'null']}, - 'availabilityZone': {'type': 'string'}, - 'createdAt': {'type': 'string'}, - 'displayDescription': {'type': ['string', 'null']}, - 'volumeType': {'type': ['string', 'null']}, - 'snapshotId': {'type': ['string', 'null']}, - 'metadata': {'type': 'object'}, - 'size': {'type': 'integer'}, - 'attachments': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'device': {'type': 'string'}, - 'volumeId': {'type': 'string'}, - 'serverId': {'type': 'string'} - } - # NOTE- If volume is not attached to any server - # then, 'attachments' attributes comes as array - # with empty objects "[{}]" due to that elements - # of 'attachments' cannot defined as 'required'. - # If it would come as empty array "[]" then, - # those elements can be defined as 'required'. - } - } - }, - 'required': ['id', 'status', 'displayName', 'availabilityZone', - 'createdAt', 'displayDescription', 'volumeType', - 'snapshotId', 'metadata', 'size', 'attachments'] - } - }, - 'required': ['volume'] - } -} - -list_volumes = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'volumes': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'status': {'type': 'string'}, - 'displayName': {'type': ['string', 'null']}, - 'availabilityZone': {'type': 'string'}, - 'createdAt': {'type': 'string'}, - 'displayDescription': {'type': ['string', 'null']}, - 'volumeType': {'type': ['string', 'null']}, - 'snapshotId': {'type': ['string', 'null']}, - 'metadata': {'type': 'object'}, - 'size': {'type': 'integer'}, - 'attachments': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'device': {'type': 'string'}, - 'volumeId': {'type': 'string'}, - 'serverId': {'type': 'string'} - } - # NOTE- If volume is not attached to any server - # then, 'attachments' attributes comes as array - # with empty object "[{}]" due to that elements - # of 'attachments' cannot defined as 'required' - # If it would come as empty array "[]" then, - # those elements can be defined as 'required'. - } - } - }, - 'required': ['id', 'status', 'displayName', - 'availabilityZone', 'createdAt', - 'displayDescription', 'volumeType', - 'snapshotId', 'metadata', 'size', - 'attachments'] - } - } - }, - 'required': ['volumes'] - } -} - -delete_volume = { - 'status_code': [202] -} diff --git a/test/tempest/tempest/api_schema/response/compute/version.py b/test/tempest/tempest/api_schema/response/compute/version.py deleted file mode 100644 index 6579c63d..00000000 --- a/test/tempest/tempest/api_schema/response/compute/version.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2014 NEC 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. - -version = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'version': { - 'type': 'object', - 'properties': { - 'id': {'type': 'string'}, - 'links': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'href': {'type': 'string', 'format': 'uri'}, - 'rel': {'type': 'string'}, - 'type': {'type': 'string'} - }, - 'required': ['href', 'rel'] - } - }, - 'media-types': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'base': {'type': 'string'}, - 'type': {'type': 'string'} - }, - 'required': ['base', 'type'] - } - }, - 'status': {'type': 'string'}, - 'updated': {'type': 'string', 'format': 'date-time'}, - 'version': {'type': 'string'}, - 'min_version': {'type': 'string'} - }, - # NOTE: version and min_version have been added since Kilo, - # so they should not be required. - 'required': ['id', 'links', 'media-types', 'status', 'updated'] - } - }, - 'required': ['version'] - } -} diff --git a/test/tempest/tempest/api_schema/response/messaging/__init__.py b/test/tempest/tempest/api_schema/response/messaging/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/response/messaging/v1/__init__.py b/test/tempest/tempest/api_schema/response/messaging/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/api_schema/response/messaging/v1/queues.py b/test/tempest/tempest/api_schema/response/messaging/v1/queues.py deleted file mode 100644 index 09e01477..00000000 --- a/test/tempest/tempest/api_schema/response/messaging/v1/queues.py +++ /dev/null @@ -1,239 +0,0 @@ - -# Copyright (c) 2014 Rackspace, Inc. -# -# 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. - - -list_link = { - 'type': 'object', - 'properties': { - 'rel': {'type': 'string'}, - 'href': { - 'type': 'string', - 'format': 'uri' - } - }, - 'required': ['href', 'rel'] -} - -list_queue = { - 'type': 'object', - 'properties': { - 'name': {'type': 'string'}, - 'href': { - 'type': 'string', - 'format': 'uri' - }, - 'metadata': {'type': 'object'} - }, - 'required': ['name', 'href'] -} - -list_queues = { - 'status_code': [200, 204], - 'response_body': { - 'type': 'object', - 'properties': { - 'links': { - 'type': 'array', - 'items': list_link, - 'maxItems': 1 - }, - 'queues': { - 'type': 'array', - 'items': list_queue - } - }, - 'required': ['links', 'queues'] - } -} - -age = { - 'type': 'number', - 'minimum': 0 -} - -message_link = { - 'type': 'object', - 'properties': { - 'href': { - 'type': 'string', - 'format': 'uri' - }, - 'age': age, - 'created': { - 'type': 'string', - 'format': 'date-time' - } - }, - 'required': ['href', 'age', 'created'] -} - -messages = { - 'type': 'object', - 'properties': { - 'free': {'type': 'number'}, - 'claimed': {'type': 'number'}, - 'total': {'type': 'number'}, - 'oldest': message_link, - 'newest': message_link - }, - 'required': ['free', 'claimed', 'total'] -} - -queue_stats = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'messages': messages - }, - 'required': ['messages'] - } -} - -resource_schema = { - 'type': 'array', - 'items': { - 'type': 'string' - }, - 'minItems': 1 -} - -post_messages = { - 'status_code': [201], - 'response_body': { - 'type': 'object', - 'properties': { - 'resources': resource_schema, - 'partial': {'type': 'boolean'} - } - }, - 'required': ['resources', 'partial'] -} - -message_ttl = { - 'type': 'number', - 'minimum': 1 -} - -list_messages_links = { - 'type': 'array', - 'maxItems': 1, - 'minItems': 1, - 'items': { - 'type': 'object', - 'properties': { - 'rel': {'type': 'string'}, - 'href': {'type': 'string'} - }, - 'required': ['rel', 'href'] - } -} - -list_messages_response = { - 'type': 'array', - 'minItems': 1, - 'items': { - 'type': 'object', - 'properties': { - 'href': {'type': 'string'}, - 'ttl': message_ttl, - 'age': age, - 'body': {'type': 'object'} - }, - 'required': ['href', 'ttl', 'age', 'body'] - } -} - -list_messages = { - 'status_code': [200, 204], - 'response_body': { - 'type': 'object', - 'properties': { - 'links': list_messages_links, - 'messages': list_messages_response - } - }, - 'required': ['links', 'messages'] -} - -single_message = { - 'type': 'object', - 'properties': { - 'href': {'type': 'string'}, - 'ttl': message_ttl, - 'age': age, - 'body': {'type': 'object'} - }, - 'required': ['href', 'ttl', 'age', 'body'] -} - -get_single_message = { - 'status_code': [200], - 'response_body': single_message -} - -get_multiple_messages = { - 'status_code': [200], - 'response_body': { - 'type': 'array', - 'items': single_message, - 'minItems': 1 - } -} - -messages_claimed = { - 'type': 'object', - 'properties': { - 'href': { - 'type': 'string', - 'format': 'uri' - }, - 'ttl': message_ttl, - 'age': {'type': 'number'}, - 'body': {'type': 'object'} - }, - 'required': ['href', 'ttl', 'age', 'body'] -} - -claim_messages = { - 'status_code': [201, 204], - 'response_body': { - 'type': 'array', - 'items': messages_claimed, - 'minItems': 1 - } -} - -claim_ttl = { - 'type': 'number', - 'minimum': 1 -} - -query_claim = { - 'status_code': [200], - 'response_body': { - 'type': 'object', - 'properties': { - 'age': {'type': 'number'}, - 'ttl': claim_ttl, - 'messages': { - 'type': 'array', - 'minItems': 1 - } - }, - 'required': ['ttl', 'age', 'messages'] - } -} diff --git a/test/tempest/tempest/auth.py b/test/tempest/tempest/auth.py deleted file mode 100644 index 113ad696..00000000 --- a/test/tempest/tempest/auth.py +++ /dev/null @@ -1,659 +0,0 @@ -# Copyright 2014 Hewlett-Packard Development Company, L.P. -# 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 abc -import copy -import datetime -import exceptions -import re -import urlparse - -from oslo_log import log as logging -import six - -from tempest.services.identity.v2.json import token_client as json_v2id -from tempest.services.identity.v3.json import token_client as json_v3id - - -LOG = logging.getLogger(__name__) - - -@six.add_metaclass(abc.ABCMeta) -class AuthProvider(object): - """ - Provide authentication - """ - - def __init__(self, credentials): - """ - :param credentials: credentials for authentication - """ - if self.check_credentials(credentials): - self.credentials = credentials - else: - raise TypeError("Invalid credentials") - self.cache = None - self.alt_auth_data = None - self.alt_part = None - - def __str__(self): - return "Creds :{creds}, cached auth data: {cache}".format( - creds=self.credentials, cache=self.cache) - - @abc.abstractmethod - def _decorate_request(self, filters, method, url, headers=None, body=None, - auth_data=None): - """ - Decorate request with authentication data - """ - return - - @abc.abstractmethod - def _get_auth(self): - return - - @abc.abstractmethod - def _fill_credentials(self, auth_data_body): - return - - def fill_credentials(self): - """ - Fill credentials object with data from auth - """ - auth_data = self.get_auth() - self._fill_credentials(auth_data[1]) - return self.credentials - - @classmethod - def check_credentials(cls, credentials): - """ - Verify credentials are valid. - """ - return isinstance(credentials, Credentials) and credentials.is_valid() - - @property - def auth_data(self): - return self.get_auth() - - @auth_data.deleter - def auth_data(self): - self.clear_auth() - - def get_auth(self): - """ - Returns auth from cache if available, else auth first - """ - if self.cache is None or self.is_expired(self.cache): - self.set_auth() - return self.cache - - def set_auth(self): - """ - Forces setting auth, ignores cache if it exists. - Refills credentials - """ - self.cache = self._get_auth() - self._fill_credentials(self.cache[1]) - - def clear_auth(self): - """ - Can be called to clear the access cache so that next request - will fetch a new token and base_url. - """ - self.cache = None - self.credentials.reset() - - @abc.abstractmethod - def is_expired(self, auth_data): - return - - def auth_request(self, method, url, headers=None, body=None, filters=None): - """ - Obtains auth data and decorates a request with that. - :param method: HTTP method of the request - :param url: relative URL of the request (path) - :param headers: HTTP headers of the request - :param body: HTTP body in case of POST / PUT - :param filters: select a base URL out of the catalog - :returns a Tuple (url, headers, body) - """ - orig_req = dict(url=url, headers=headers, body=body) - - auth_url, auth_headers, auth_body = self._decorate_request( - filters, method, url, headers, body) - auth_req = dict(url=auth_url, headers=auth_headers, body=auth_body) - - # Overwrite part if the request if it has been requested - if self.alt_part is not None: - if self.alt_auth_data is not None: - alt_url, alt_headers, alt_body = self._decorate_request( - filters, method, url, headers, body, - auth_data=self.alt_auth_data) - alt_auth_req = dict(url=alt_url, headers=alt_headers, - body=alt_body) - auth_req[self.alt_part] = alt_auth_req[self.alt_part] - - else: - # If alt auth data is None, skip auth in the requested part - auth_req[self.alt_part] = orig_req[self.alt_part] - - # Next auth request will be normal, unless otherwise requested - self.reset_alt_auth_data() - - return auth_req['url'], auth_req['headers'], auth_req['body'] - - def reset_alt_auth_data(self): - """ - Configure auth provider to provide valid authentication data - """ - self.alt_part = None - self.alt_auth_data = None - - def set_alt_auth_data(self, request_part, auth_data): - """ - Configure auth provider to provide alt authentication data - on a part of the *next* auth_request. If credentials are None, - set invalid data. - :param request_part: request part to contain invalid auth: url, - headers, body - :param auth_data: alternative auth_data from which to get the - invalid data to be injected - """ - self.alt_part = request_part - self.alt_auth_data = auth_data - - @abc.abstractmethod - def base_url(self, filters, auth_data=None): - """ - Extracts the base_url based on provided filters - """ - return - - -class KeystoneAuthProvider(AuthProvider): - - token_expiry_threshold = datetime.timedelta(seconds=60) - - def __init__(self, credentials, auth_url, - disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - super(KeystoneAuthProvider, self).__init__(credentials) - self.dsvm = disable_ssl_certificate_validation - self.ca_certs = ca_certs - self.trace_requests = trace_requests - self.auth_client = self._auth_client(auth_url) - - def _decorate_request(self, filters, method, url, headers=None, body=None, - auth_data=None): - if auth_data is None: - auth_data = self.auth_data - token, _ = auth_data - base_url = self.base_url(filters=filters, auth_data=auth_data) - # build authenticated request - # returns new request, it does not touch the original values - _headers = copy.deepcopy(headers) if headers is not None else {} - _headers['X-Auth-Token'] = str(token) - if url is None or url == "": - _url = base_url - else: - # Join base URL and url, and remove multiple contiguous slashes - _url = "/".join([base_url, url]) - parts = [x for x in urlparse.urlparse(_url)] - parts[2] = re.sub("/{2,}", "/", parts[2]) - _url = urlparse.urlunparse(parts) - # no change to method or body - return str(_url), _headers, body - - @abc.abstractmethod - def _auth_client(self): - return - - @abc.abstractmethod - def _auth_params(self): - return - - def _get_auth(self): - # Bypasses the cache - auth_func = getattr(self.auth_client, 'get_token') - auth_params = self._auth_params() - - # returns token, auth_data - token, auth_data = auth_func(**auth_params) - return token, auth_data - - def get_token(self): - return self.auth_data[0] - - -class KeystoneV2AuthProvider(KeystoneAuthProvider): - - EXPIRY_DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' - - def _auth_client(self, auth_url): - return json_v2id.TokenClientJSON( - auth_url, disable_ssl_certificate_validation=self.dsvm, - ca_certs=self.ca_certs, trace_requests=self.trace_requests) - - def _auth_params(self): - return dict( - user=self.credentials.username, - password=self.credentials.password, - tenant=self.credentials.tenant_name, - auth_data=True) - - def _fill_credentials(self, auth_data_body): - tenant = auth_data_body['token']['tenant'] - user = auth_data_body['user'] - if self.credentials.tenant_name is None: - self.credentials.tenant_name = tenant['name'] - if self.credentials.tenant_id is None: - self.credentials.tenant_id = tenant['id'] - if self.credentials.username is None: - self.credentials.username = user['name'] - if self.credentials.user_id is None: - self.credentials.user_id = user['id'] - - def base_url(self, filters, auth_data=None): - """ - Filters can be: - - service: compute, image, etc - - region: the service region - - endpoint_type: adminURL, publicURL, internalURL - - api_version: replace catalog version with this - - skip_path: take just the base URL - """ - if auth_data is None: - auth_data = self.auth_data - token, _auth_data = auth_data - service = filters.get('service') - region = filters.get('region') - endpoint_type = filters.get('endpoint_type', 'publicURL') - - if service is None: - raise exceptions.EndpointNotFound("No service provided") - - _base_url = None - for ep in _auth_data['serviceCatalog']: - if ep["type"] == service: - for _ep in ep['endpoints']: - if region is not None and _ep['region'] == region: - _base_url = _ep.get(endpoint_type) - if not _base_url: - # No region matching, use the first - _base_url = ep['endpoints'][0].get(endpoint_type) - break - if _base_url is None: - raise exceptions.EndpointNotFound(service) - - parts = urlparse.urlparse(_base_url) - if filters.get('api_version', None) is not None: - path = "/" + filters['api_version'] - noversion_path = "/".join(parts.path.split("/")[2:]) - if noversion_path != "": - path += "/" + noversion_path - _base_url = _base_url.replace(parts.path, path) - if filters.get('skip_path', None) is not None and parts.path != '': - _base_url = _base_url.replace(parts.path, "/") - - return _base_url - - def is_expired(self, auth_data): - _, access = auth_data - expiry = datetime.datetime.strptime(access['token']['expires'], - self.EXPIRY_DATE_FORMAT) - return expiry - self.token_expiry_threshold <= \ - datetime.datetime.utcnow() - - -class KeystoneV3AuthProvider(KeystoneAuthProvider): - - EXPIRY_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' - - def _auth_client(self, auth_url): - return json_v3id.V3TokenClientJSON( - auth_url, disable_ssl_certificate_validation=self.dsvm, - ca_certs=self.ca_certs, trace_requests=self.trace_requests) - - def _auth_params(self): - return dict( - user_id=self.credentials.user_id, - username=self.credentials.username, - password=self.credentials.password, - project_id=self.credentials.project_id, - project_name=self.credentials.project_name, - user_domain_id=self.credentials.user_domain_id, - user_domain_name=self.credentials.user_domain_name, - project_domain_id=self.credentials.project_domain_id, - project_domain_name=self.credentials.project_domain_name, - domain_id=self.credentials.domain_id, - domain_name=self.credentials.domain_name, - auth_data=True) - - def _fill_credentials(self, auth_data_body): - # project or domain, depending on the scope - project = auth_data_body.get('project', None) - domain = auth_data_body.get('domain', None) - # user is always there - user = auth_data_body['user'] - # Set project fields - if project is not None: - if self.credentials.project_name is None: - self.credentials.project_name = project['name'] - if self.credentials.project_id is None: - self.credentials.project_id = project['id'] - if self.credentials.project_domain_id is None: - self.credentials.project_domain_id = project['domain']['id'] - if self.credentials.project_domain_name is None: - self.credentials.project_domain_name = \ - project['domain']['name'] - # Set domain fields - if domain is not None: - if self.credentials.domain_id is None: - self.credentials.domain_id = domain['id'] - if self.credentials.domain_name is None: - self.credentials.domain_name = domain['name'] - # Set user fields - if self.credentials.username is None: - self.credentials.username = user['name'] - if self.credentials.user_id is None: - self.credentials.user_id = user['id'] - if self.credentials.user_domain_id is None: - self.credentials.user_domain_id = user['domain']['id'] - if self.credentials.user_domain_name is None: - self.credentials.user_domain_name = user['domain']['name'] - - def base_url(self, filters, auth_data=None): - """ - Filters can be: - - service: compute, image, etc - - region: the service region - - endpoint_type: adminURL, publicURL, internalURL - - api_version: replace catalog version with this - - skip_path: take just the base URL - """ - if auth_data is None: - auth_data = self.auth_data - token, _auth_data = auth_data - service = filters.get('service') - region = filters.get('region') - endpoint_type = filters.get('endpoint_type', 'public') - - if service is None: - raise exceptions.EndpointNotFound("No service provided") - - if 'URL' in endpoint_type: - endpoint_type = endpoint_type.replace('URL', '') - _base_url = None - catalog = _auth_data['catalog'] - # Select entries with matching service type - service_catalog = [ep for ep in catalog if ep['type'] == service] - if len(service_catalog) > 0: - service_catalog = service_catalog[0]['endpoints'] - else: - # No matching service - raise exceptions.EndpointNotFound(service) - # Filter by endpoint type (interface) - filtered_catalog = [ep for ep in service_catalog if - ep['interface'] == endpoint_type] - if len(filtered_catalog) == 0: - # No matching type, keep all and try matching by region at least - filtered_catalog = service_catalog - # Filter by region - filtered_catalog = [ep for ep in filtered_catalog if - ep['region'] == region] - if len(filtered_catalog) == 0: - # No matching region, take the first endpoint - filtered_catalog = [service_catalog[0]] - # There should be only one match. If not take the first. - _base_url = filtered_catalog[0].get('url', None) - if _base_url is None: - raise exceptions.EndpointNotFound(service) - - parts = urlparse.urlparse(_base_url) - if filters.get('api_version', None) is not None: - path = "/" + filters['api_version'] - noversion_path = "/".join(parts.path.split("/")[2:]) - if noversion_path != "": - path += "/" + noversion_path - _base_url = _base_url.replace(parts.path, path) - if filters.get('skip_path', None) is not None: - _base_url = _base_url.replace(parts.path, "/") - - return _base_url - - def is_expired(self, auth_data): - _, access = auth_data - expiry = datetime.datetime.strptime(access['expires_at'], - self.EXPIRY_DATE_FORMAT) - return expiry - self.token_expiry_threshold <= \ - datetime.datetime.utcnow() - - -def is_identity_version_supported(identity_version): - return identity_version in IDENTITY_VERSION - - -def get_credentials(auth_url, fill_in=True, identity_version='v2', - disable_ssl_certificate_validation=None, ca_certs=None, - trace_requests=None, **kwargs): - """ - Builds a credentials object based on the configured auth_version - - :param auth_url (string): Full URI of the OpenStack Identity API(Keystone) - which is used to fetch the token from Identity service. - :param fill_in (boolean): obtain a token and fill in all credential - details provided by the identity service. When fill_in is not - specified, credentials are not validated. Validation can be invoked - by invoking ``is_valid()`` - :param identity_version (string): identity API version is used to - select the matching auth provider and credentials class - :param disable_ssl_certificate_validation: whether to enforce SSL - certificate validation in SSL API requests to the auth system - :param ca_certs: CA certificate bundle for validation of certificates - in SSL API requests to the auth system - :param trace_requests: trace in log API requests to the auth system - :param kwargs (dict): Dict of credential key/value pairs - - Examples: - - Returns credentials from the provided parameters: - >>> get_credentials(username='foo', password='bar') - - Returns credentials including IDs: - >>> get_credentials(username='foo', password='bar', fill_in=True) - """ - if not is_identity_version_supported(identity_version): - raise exceptions.InvalidIdentityVersion( - identity_version=identity_version) - - credential_class, auth_provider_class = IDENTITY_VERSION.get( - identity_version) - - creds = credential_class(**kwargs) - # Fill in the credentials fields that were not specified - if fill_in: - dsvm = disable_ssl_certificate_validation - auth_provider = auth_provider_class( - creds, auth_url, disable_ssl_certificate_validation=dsvm, - ca_certs=ca_certs, trace_requests=trace_requests) - creds = auth_provider.fill_credentials() - return creds - - -class Credentials(object): - """ - Set of credentials for accessing OpenStack services - - ATTRIBUTES: list of valid class attributes representing credentials. - """ - - ATTRIBUTES = [] - - def __init__(self, **kwargs): - """ - Enforce the available attributes at init time (only). - Additional attributes can still be set afterwards if tests need - to do so. - """ - self._initial = kwargs - self._apply_credentials(kwargs) - - def _apply_credentials(self, attr): - for key in attr.keys(): - if key in self.ATTRIBUTES: - setattr(self, key, attr[key]) - else: - raise exceptions.InvalidCredentials - - def __str__(self): - """ - Represent only attributes included in self.ATTRIBUTES - """ - _repr = dict((k, getattr(self, k)) for k in self.ATTRIBUTES) - return str(_repr) - - def __eq__(self, other): - """ - Credentials are equal if attributes in self.ATTRIBUTES are equal - """ - return str(self) == str(other) - - def __getattr__(self, key): - # If an attribute is set, __getattr__ is not invoked - # If an attribute is not set, and it is a known one, return None - if key in self.ATTRIBUTES: - return None - else: - raise AttributeError - - def __delitem__(self, key): - # For backwards compatibility, support dict behaviour - if key in self.ATTRIBUTES: - delattr(self, key) - else: - raise AttributeError - - def get(self, item, default): - # In this patch act as dict for backward compatibility - try: - return getattr(self, item) - except AttributeError: - return default - - def get_init_attributes(self): - return self._initial.keys() - - def is_valid(self): - raise NotImplementedError - - def reset(self): - # First delete all known attributes - for key in self.ATTRIBUTES: - if getattr(self, key) is not None: - delattr(self, key) - # Then re-apply initial setup - self._apply_credentials(self._initial) - - -class KeystoneV2Credentials(Credentials): - - ATTRIBUTES = ['username', 'password', 'tenant_name', 'user_id', - 'tenant_id'] - - def is_valid(self): - """ - Minimum set of valid credentials, are username and password. - Tenant is optional. - """ - return None not in (self.username, self.password) - - -class KeystoneV3Credentials(Credentials): - """ - Credentials suitable for the Keystone Identity V3 API - """ - - ATTRIBUTES = ['domain_id', 'domain_name', 'password', 'username', - 'project_domain_id', 'project_domain_name', 'project_id', - 'project_name', 'tenant_id', 'tenant_name', 'user_domain_id', - 'user_domain_name', 'user_id'] - - def __setattr__(self, key, value): - parent = super(KeystoneV3Credentials, self) - # for tenant_* set both project and tenant - if key == 'tenant_id': - parent.__setattr__('project_id', value) - elif key == 'tenant_name': - parent.__setattr__('project_name', value) - # for project_* set both project and tenant - if key == 'project_id': - parent.__setattr__('tenant_id', value) - elif key == 'project_name': - parent.__setattr__('tenant_name', value) - # for *_domain_* set both user and project if not set yet - if key == 'user_domain_id': - if self.project_domain_id is None: - parent.__setattr__('project_domain_id', value) - if key == 'project_domain_id': - if self.user_domain_id is None: - parent.__setattr__('user_domain_id', value) - if key == 'user_domain_name': - if self.project_domain_name is None: - parent.__setattr__('project_domain_name', value) - if key == 'project_domain_name': - if self.user_domain_name is None: - parent.__setattr__('user_domain_name', value) - # support domain_name coming from config - if key == 'domain_name': - parent.__setattr__('user_domain_name', value) - parent.__setattr__('project_domain_name', value) - # finally trigger default behaviour for all attributes - parent.__setattr__(key, value) - - def is_valid(self): - """ - Valid combinations of v3 credentials (excluding token, scope) - - User id, password (optional domain) - - User name, password and its domain id/name - For the scope, valid combinations are: - - None - - Project id (optional domain) - - Project name and its domain id/name - - Domain id - - Domain name - """ - valid_user_domain = any( - [self.user_domain_id is not None, - self.user_domain_name is not None]) - valid_project_domain = any( - [self.project_domain_id is not None, - self.project_domain_name is not None]) - valid_user = any( - [self.user_id is not None, - self.username is not None and valid_user_domain]) - valid_project_scope = any( - [self.project_name is None and self.project_id is None, - self.project_id is not None, - self.project_name is not None and valid_project_domain]) - valid_domain_scope = any( - [self.domain_id is None and self.domain_name is None, - self.domain_id or self.domain_name]) - return all([self.password is not None, - valid_user, - valid_project_scope and valid_domain_scope]) - - -IDENTITY_VERSION = {'v2': (KeystoneV2Credentials, KeystoneV2AuthProvider), - 'v3': (KeystoneV3Credentials, KeystoneV3AuthProvider)} diff --git a/test/tempest/tempest/clients.py b/test/tempest/tempest/clients.py deleted file mode 100644 index 8197db5a..00000000 --- a/test/tempest/tempest/clients.py +++ /dev/null @@ -1,418 +0,0 @@ -# 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 copy - -from oslo_log import log as logging - -from tempest.common import cred_provider -from tempest.common import negative_rest_client -from tempest import config -from tempest import manager -from tempest.services.baremetal.v1.json.baremetal_client import \ - BaremetalClientJSON -from tempest.services import botoclients -from tempest.services.compute.json.agents_client import \ - AgentsClientJSON -from tempest.services.compute.json.aggregates_client import \ - AggregatesClientJSON -from tempest.services.compute.json.availability_zone_client import \ - AvailabilityZoneClientJSON -from tempest.services.compute.json.baremetal_nodes_client import \ - BaremetalNodesClientJSON -from tempest.services.compute.json.certificates_client import \ - CertificatesClientJSON -from tempest.services.compute.json.extensions_client import \ - ExtensionsClientJSON -from tempest.services.compute.json.fixed_ips_client import FixedIPsClientJSON -from tempest.services.compute.json.flavors_client import FlavorsClientJSON -from tempest.services.compute.json.floating_ips_client import \ - FloatingIPsClientJSON -from tempest.services.compute.json.hosts_client import HostsClientJSON -from tempest.services.compute.json.hypervisor_client import \ - HypervisorClientJSON -from tempest.services.compute.json.images_client import ImagesClientJSON -from tempest.services.compute.json.instance_usage_audit_log_client import \ - InstanceUsagesAuditLogClientJSON -from tempest.services.compute.json.interfaces_client import \ - InterfacesClientJSON -from tempest.services.compute.json.keypairs_client import KeyPairsClientJSON -from tempest.services.compute.json.limits_client import LimitsClientJSON -from tempest.services.compute.json.migrations_client import \ - MigrationsClientJSON -from tempest.services.compute.json.networks_client import NetworksClientJSON -from tempest.services.compute.json.quotas_client import QuotaClassesClientJSON -from tempest.services.compute.json.quotas_client import QuotasClientJSON -from tempest.services.compute.json.security_group_default_rules_client import \ - SecurityGroupDefaultRulesClientJSON -from tempest.services.compute.json.security_groups_client import \ - SecurityGroupsClientJSON -from tempest.services.compute.json.servers_client import ServersClientJSON -from tempest.services.compute.json.services_client import ServicesClientJSON -from tempest.services.compute.json.tenant_networks_client import \ - TenantNetworksClientJSON -from tempest.services.compute.json.tenant_usages_client import \ - TenantUsagesClientJSON -from tempest.services.compute.json.volumes_extensions_client import \ - VolumesExtensionsClientJSON -from tempest.services.data_processing.v1_1.data_processing_client import \ - DataProcessingClient -from tempest.services.database.json.flavors_client import \ - DatabaseFlavorsClientJSON -from tempest.services.database.json.limits_client import \ - DatabaseLimitsClientJSON -from tempest.services.database.json.versions_client import \ - DatabaseVersionsClientJSON -from tempest.services.identity.v2.json.identity_client import \ - IdentityClientJSON -from tempest.services.identity.v2.json.token_client import TokenClientJSON -from tempest.services.identity.v3.json.credentials_client import \ - CredentialsClientJSON -from tempest.services.identity.v3.json.endpoints_client import \ - EndPointClientJSON -from tempest.services.identity.v3.json.identity_client import \ - IdentityV3ClientJSON -from tempest.services.identity.v3.json.policy_client import PolicyClientJSON -from tempest.services.identity.v3.json.region_client import RegionClientJSON -from tempest.services.identity.v3.json.service_client import \ - ServiceClientJSON -from tempest.services.identity.v3.json.token_client import V3TokenClientJSON -from tempest.services.image.v1.json.image_client import ImageClientJSON -from tempest.services.image.v2.json.image_client import ImageClientV2JSON -from tempest.services.messaging.json.messaging_client import \ - MessagingClientJSON -from tempest.services.network.json.network_client import NetworkClientJSON -from tempest.services.object_storage.account_client import AccountClient -from tempest.services.object_storage.container_client import ContainerClient -from tempest.services.object_storage.object_client import ObjectClient -from tempest.services.telemetry.json.telemetry_client import \ - TelemetryClientJSON -from tempest.services.volume.json.admin.volume_hosts_client import \ - VolumeHostsClientJSON -from tempest.services.volume.json.admin.volume_quotas_client import \ - VolumeQuotasClientJSON -from tempest.services.volume.json.admin.volume_services_client import \ - VolumesServicesClientJSON -from tempest.services.volume.json.admin.volume_types_client import \ - VolumeTypesClientJSON -from tempest.services.volume.json.availability_zone_client import \ - VolumeAvailabilityZoneClientJSON -from tempest.services.volume.json.backups_client import BackupsClientJSON -from tempest.services.volume.json.extensions_client import \ - ExtensionsClientJSON as VolumeExtensionClientJSON -from tempest.services.volume.json.qos_client import QosSpecsClientJSON -from tempest.services.volume.json.snapshots_client import SnapshotsClientJSON -from tempest.services.volume.json.volumes_client import VolumesClientJSON -from tempest.services.volume.v2.json.admin.volume_hosts_client import \ - VolumeHostsV2ClientJSON -from tempest.services.volume.v2.json.admin.volume_quotas_client import \ - VolumeQuotasV2Client -from tempest.services.volume.v2.json.admin.volume_services_client import \ - VolumesServicesV2ClientJSON -from tempest.services.volume.v2.json.admin.volume_types_client import \ - VolumeTypesV2ClientJSON -from tempest.services.volume.v2.json.availability_zone_client import \ - VolumeV2AvailabilityZoneClientJSON -from tempest.services.volume.v2.json.backups_client import BackupsClientV2JSON -from tempest.services.volume.v2.json.extensions_client import \ - ExtensionsV2ClientJSON as VolumeV2ExtensionClientJSON -from tempest.services.volume.v2.json.qos_client import QosSpecsV2ClientJSON -from tempest.services.volume.v2.json.snapshots_client import \ - SnapshotsV2ClientJSON -from tempest.services.volume.v2.json.volumes_client import VolumesV2ClientJSON - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -class Manager(manager.Manager): - - """ - Top level manager for OpenStack tempest clients - """ - - default_params = { - 'disable_ssl_certificate_validation': - CONF.identity.disable_ssl_certificate_validation, - 'ca_certs': CONF.identity.ca_certificates_file, - 'trace_requests': CONF.debug.trace_requests - } - - # NOTE: Tempest uses timeout values of compute API if project specific - # timeout values don't exist. - default_params_with_timeout_values = { - 'build_interval': CONF.compute.build_interval, - 'build_timeout': CONF.compute.build_timeout - } - default_params_with_timeout_values.update(default_params) - - def __init__(self, credentials=None, service=None): - super(Manager, self).__init__(credentials=credentials) - - self._set_compute_clients() - self._set_database_clients() - self._set_identity_clients() - self._set_volume_clients() - self._set_object_storage_clients() - - self.baremetal_client = BaremetalClientJSON( - self.auth_provider, - CONF.baremetal.catalog_type, - CONF.identity.region, - endpoint_type=CONF.baremetal.endpoint_type, - **self.default_params_with_timeout_values) - self.network_client = NetworkClientJSON( - self.auth_provider, - CONF.network.catalog_type, - CONF.network.region or CONF.identity.region, - endpoint_type=CONF.network.endpoint_type, - build_interval=CONF.network.build_interval, - build_timeout=CONF.network.build_timeout, - **self.default_params) - self.messaging_client = MessagingClientJSON( - self.auth_provider, - CONF.messaging.catalog_type, - CONF.identity.region, - **self.default_params_with_timeout_values) - if CONF.service_available.ceilometer: - self.telemetry_client = TelemetryClientJSON( - self.auth_provider, - CONF.telemetry.catalog_type, - CONF.identity.region, - endpoint_type=CONF.telemetry.endpoint_type, - **self.default_params_with_timeout_values) - if CONF.service_available.glance: - self.image_client = ImageClientJSON( - self.auth_provider, - CONF.image.catalog_type, - CONF.image.region or CONF.identity.region, - endpoint_type=CONF.image.endpoint_type, - build_interval=CONF.image.build_interval, - build_timeout=CONF.image.build_timeout, - **self.default_params) - self.image_client_v2 = ImageClientV2JSON( - self.auth_provider, - CONF.image.catalog_type, - CONF.image.region or CONF.identity.region, - endpoint_type=CONF.image.endpoint_type, - build_interval=CONF.image.build_interval, - build_timeout=CONF.image.build_timeout, - **self.default_params) - self.data_processing_client = DataProcessingClient( - self.auth_provider, - CONF.data_processing.catalog_type, - CONF.identity.region, - endpoint_type=CONF.data_processing.endpoint_type, - **self.default_params_with_timeout_values) - self.negative_client = negative_rest_client.NegativeRestClient( - self.auth_provider, service, **self.default_params) - - # Generating EC2 credentials in tempest is only supported - # with identity v2 - if CONF.identity_feature_enabled.api_v2 and \ - CONF.identity.auth_version == 'v2': - # EC2 and S3 clients, if used, will check onfigured AWS credentials - # and generate new ones if needed - self.ec2api_client = botoclients.APIClientEC2(self.identity_client) - self.s3_client = botoclients.ObjectClientS3(self.identity_client) - - def _set_compute_clients(self): - params = { - 'service': CONF.compute.catalog_type, - 'region': CONF.compute.region or CONF.identity.region, - 'endpoint_type': CONF.compute.endpoint_type, - 'build_interval': CONF.compute.build_interval, - 'build_timeout': CONF.compute.build_timeout - } - params.update(self.default_params) - - self.agents_client = AgentsClientJSON(self.auth_provider, **params) - self.networks_client = NetworksClientJSON(self.auth_provider, **params) - self.migrations_client = MigrationsClientJSON(self.auth_provider, - **params) - self.security_group_default_rules_client = ( - SecurityGroupDefaultRulesClientJSON(self.auth_provider, **params)) - self.certificates_client = CertificatesClientJSON(self.auth_provider, - **params) - self.servers_client = ServersClientJSON( - self.auth_provider, - enable_instance_password=CONF.compute_feature_enabled - .enable_instance_password, - **params) - self.limits_client = LimitsClientJSON(self.auth_provider, **params) - self.images_client = ImagesClientJSON(self.auth_provider, **params) - self.keypairs_client = KeyPairsClientJSON(self.auth_provider, **params) - self.quotas_client = QuotasClientJSON(self.auth_provider, **params) - self.quota_classes_client = QuotaClassesClientJSON(self.auth_provider, - **params) - self.flavors_client = FlavorsClientJSON(self.auth_provider, **params) - self.extensions_client = ExtensionsClientJSON(self.auth_provider, - **params) - self.floating_ips_client = FloatingIPsClientJSON(self.auth_provider, - **params) - self.security_groups_client = SecurityGroupsClientJSON( - self.auth_provider, **params) - self.interfaces_client = InterfacesClientJSON(self.auth_provider, - **params) - self.fixed_ips_client = FixedIPsClientJSON(self.auth_provider, - **params) - self.availability_zone_client = AvailabilityZoneClientJSON( - self.auth_provider, **params) - self.aggregates_client = AggregatesClientJSON(self.auth_provider, - **params) - self.services_client = ServicesClientJSON(self.auth_provider, **params) - self.tenant_usages_client = TenantUsagesClientJSON(self.auth_provider, - **params) - self.hosts_client = HostsClientJSON(self.auth_provider, **params) - self.hypervisor_client = HypervisorClientJSON(self.auth_provider, - **params) - self.instance_usages_audit_log_client = \ - InstanceUsagesAuditLogClientJSON(self.auth_provider, **params) - self.tenant_networks_client = \ - TenantNetworksClientJSON(self.auth_provider, **params) - self.baremetal_nodes_client = BaremetalNodesClientJSON( - self.auth_provider, **params) - - # NOTE: The following client needs special timeout values because - # the API is a proxy for the other component. - params_volume = copy.deepcopy(params) - params_volume.update({ - 'build_interval': CONF.volume.build_interval, - 'build_timeout': CONF.volume.build_timeout - }) - self.volumes_extensions_client = VolumesExtensionsClientJSON( - self.auth_provider, default_volume_size=CONF.volume.volume_size, - **params_volume) - - def _set_database_clients(self): - self.database_flavors_client = DatabaseFlavorsClientJSON( - self.auth_provider, - CONF.database.catalog_type, - CONF.identity.region, - **self.default_params_with_timeout_values) - self.database_limits_client = DatabaseLimitsClientJSON( - self.auth_provider, - CONF.database.catalog_type, - CONF.identity.region, - **self.default_params_with_timeout_values) - self.database_versions_client = DatabaseVersionsClientJSON( - self.auth_provider, - CONF.database.catalog_type, - CONF.identity.region, - **self.default_params_with_timeout_values) - - def _set_identity_clients(self): - params = { - 'service': CONF.identity.catalog_type, - 'region': CONF.identity.region, - 'endpoint_type': 'adminURL' - } - params.update(self.default_params_with_timeout_values) - - self.identity_client = IdentityClientJSON(self.auth_provider, - **params) - self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider, - **params) - self.endpoints_client = EndPointClientJSON(self.auth_provider, - **params) - self.service_client = ServiceClientJSON(self.auth_provider, **params) - self.policy_client = PolicyClientJSON(self.auth_provider, **params) - self.region_client = RegionClientJSON(self.auth_provider, **params) - self.credentials_client = CredentialsClientJSON(self.auth_provider, - **params) - # Token clients do not use the catalog. They only need default_params. - self.token_client = TokenClientJSON(CONF.identity.uri, - **self.default_params) - if CONF.identity_feature_enabled.api_v3: - self.token_v3_client = V3TokenClientJSON(CONF.identity.uri_v3, - **self.default_params) - - def _set_volume_clients(self): - params = { - 'service': CONF.volume.catalog_type, - 'region': CONF.volume.region or CONF.identity.region, - 'endpoint_type': CONF.volume.endpoint_type, - 'build_interval': CONF.volume.build_interval, - 'build_timeout': CONF.volume.build_timeout - } - params.update(self.default_params) - - self.volume_qos_client = QosSpecsClientJSON(self.auth_provider, - **params) - self.volume_qos_v2_client = QosSpecsV2ClientJSON( - self.auth_provider, **params) - self.volume_services_v2_client = VolumesServicesV2ClientJSON( - self.auth_provider, **params) - self.backups_client = BackupsClientJSON(self.auth_provider, **params) - self.backups_v2_client = BackupsClientV2JSON(self.auth_provider, - **params) - self.snapshots_client = SnapshotsClientJSON(self.auth_provider, - **params) - self.snapshots_v2_client = SnapshotsV2ClientJSON(self.auth_provider, - **params) - self.volumes_client = VolumesClientJSON( - self.auth_provider, default_volume_size=CONF.volume.volume_size, - **params) - self.volumes_v2_client = VolumesV2ClientJSON( - self.auth_provider, default_volume_size=CONF.volume.volume_size, - **params) - self.volume_types_client = VolumeTypesClientJSON(self.auth_provider, - **params) - self.volume_services_client = VolumesServicesClientJSON( - self.auth_provider, **params) - self.volume_hosts_client = VolumeHostsClientJSON(self.auth_provider, - **params) - self.volume_hosts_v2_client = VolumeHostsV2ClientJSON( - self.auth_provider, **params) - self.volume_quotas_client = VolumeQuotasClientJSON(self.auth_provider, - **params) - self.volume_quotas_v2_client = VolumeQuotasV2Client(self.auth_provider, - **params) - self.volumes_extension_client = VolumeExtensionClientJSON( - self.auth_provider, **params) - self.volumes_v2_extension_client = VolumeV2ExtensionClientJSON( - self.auth_provider, **params) - self.volume_availability_zone_client = \ - VolumeAvailabilityZoneClientJSON(self.auth_provider, **params) - self.volume_v2_availability_zone_client = \ - VolumeV2AvailabilityZoneClientJSON(self.auth_provider, **params) - self.volume_types_v2_client = VolumeTypesV2ClientJSON( - self.auth_provider, **params) - - def _set_object_storage_clients(self): - params = { - 'service': CONF.object_storage.catalog_type, - 'region': CONF.object_storage.region or CONF.identity.region, - 'endpoint_type': CONF.object_storage.endpoint_type - } - params.update(self.default_params_with_timeout_values) - - self.account_client = AccountClient(self.auth_provider, **params) - self.container_client = ContainerClient(self.auth_provider, **params) - self.object_client = ObjectClient(self.auth_provider, **params) - - -class AdminManager(Manager): - - """ - Manager object that uses the admin credentials for its - managed client objects - """ - - def __init__(self, service=None): - super(AdminManager, self).__init__( - credentials=cred_provider.get_configured_credentials( - 'identity_admin'), - service=service) diff --git a/test/tempest/tempest/common/__init__.py b/test/tempest/tempest/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/common/accounts.py b/test/tempest/tempest/common/accounts.py deleted file mode 100644 index 93c8bcf7..00000000 --- a/test/tempest/tempest/common/accounts.py +++ /dev/null @@ -1,349 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# 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 hashlib -import os - -from oslo_concurrency import lockutils -from oslo_log import log as logging -import yaml - -from tempest import clients -from tempest.common import cred_provider -from tempest.common import fixed_network -from tempest import config -from tempest import exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -def read_accounts_yaml(path): - yaml_file = open(path, 'r') - accounts = yaml.load(yaml_file) - return accounts - - -class Accounts(cred_provider.CredentialProvider): - - def __init__(self, identity_version=None, name=None): - super(Accounts, self).__init__(identity_version=identity_version, - name=name) - if (CONF.auth.test_accounts_file and - os.path.isfile(CONF.auth.test_accounts_file)): - accounts = read_accounts_yaml(CONF.auth.test_accounts_file) - self.use_default_creds = False - else: - accounts = {} - self.use_default_creds = True - self.hash_dict = self.get_hash_dict(accounts) - self.accounts_dir = os.path.join(lockutils.get_lock_path(CONF), - 'test_accounts') - self.isolated_creds = {} - - @classmethod - def _append_role(cls, role, account_hash, hash_dict): - if role in hash_dict['roles']: - hash_dict['roles'][role].append(account_hash) - else: - hash_dict['roles'][role] = [account_hash] - return hash_dict - - @classmethod - def get_hash_dict(cls, accounts): - hash_dict = {'roles': {}, 'creds': {}, 'networks': {}} - # Loop over the accounts read from the yaml file - for account in accounts: - roles = [] - types = [] - resources = [] - if 'roles' in account: - roles = account.pop('roles') - if 'types' in account: - types = account.pop('types') - if 'resources' in account: - resources = account.pop('resources') - temp_hash = hashlib.md5() - temp_hash.update(str(account)) - temp_hash_key = temp_hash.hexdigest() - hash_dict['creds'][temp_hash_key] = account - for role in roles: - hash_dict = cls._append_role(role, temp_hash_key, - hash_dict) - # If types are set for the account append the matching role - # subdict with the hash - for type in types: - if type == 'admin': - hash_dict = cls._append_role(CONF.identity.admin_role, - temp_hash_key, hash_dict) - elif type == 'operator': - hash_dict = cls._append_role( - CONF.object_storage.operator_role, temp_hash_key, - hash_dict) - elif type == 'reseller_admin': - hash_dict = cls._append_role( - CONF.object_storage.reseller_admin_role, - temp_hash_key, - hash_dict) - # Populate the network subdict - for resource in resources: - if resource == 'network': - hash_dict['networks'][temp_hash_key] = resources[resource] - else: - LOG.warning('Unkown resource type %s, ignoring this field' - % resource) - return hash_dict - - def is_multi_user(self): - # Default credentials is not a valid option with locking Account - if self.use_default_creds: - raise exceptions.InvalidConfiguration( - "Account file %s doesn't exist" % CONF.auth.test_accounts_file) - else: - return len(self.hash_dict['creds']) > 1 - - def is_multi_tenant(self): - return self.is_multi_user() - - def _create_hash_file(self, hash_string): - path = os.path.join(os.path.join(self.accounts_dir, hash_string)) - if not os.path.isfile(path): - with open(path, 'w') as fd: - fd.write(self.name) - return True - return False - - @lockutils.synchronized('test_accounts_io', external=True) - def _get_free_hash(self, hashes): - # Cast as a list because in some edge cases a set will be passed in - hashes = list(hashes) - if not os.path.isdir(self.accounts_dir): - os.mkdir(self.accounts_dir) - # Create File from first hash (since none are in use) - self._create_hash_file(hashes[0]) - return hashes[0] - names = [] - for _hash in hashes: - res = self._create_hash_file(_hash) - if res: - return _hash - else: - path = os.path.join(os.path.join(self.accounts_dir, - _hash)) - with open(path, 'r') as fd: - names.append(fd.read()) - msg = ('Insufficient number of users provided. %s have allocated all ' - 'the credentials for this allocation request' % ','.join(names)) - raise exceptions.InvalidConfiguration(msg) - - def _get_match_hash_list(self, roles=None): - hashes = [] - if roles: - # Loop over all the creds for each role in the subdict and generate - # a list of cred lists for each role - for role in roles: - temp_hashes = self.hash_dict['roles'].get(role, None) - if not temp_hashes: - raise exceptions.InvalidConfiguration( - "No credentials with role: %s specified in the " - "accounts ""file" % role) - hashes.append(temp_hashes) - # Take the list of lists and do a boolean and between each list to - # find the creds which fall under all the specified roles - temp_list = set(hashes[0]) - for hash_list in hashes[1:]: - temp_list = temp_list & set(hash_list) - hashes = temp_list - else: - hashes = self.hash_dict['creds'].keys() - # NOTE(mtreinish): admin is a special case because of the increased - # privlege set which could potentially cause issues on tests where that - # is not expected. So unless the admin role isn't specified do not - # allocate admin. - admin_hashes = self.hash_dict['roles'].get(CONF.identity.admin_role, - None) - if ((not roles or CONF.identity.admin_role not in roles) and - admin_hashes): - useable_hashes = [x for x in hashes if x not in admin_hashes] - else: - useable_hashes = hashes - return useable_hashes - - def _sanitize_creds(self, creds): - temp_creds = creds.copy() - temp_creds.pop('password') - return temp_creds - - def _get_creds(self, roles=None): - if self.use_default_creds: - raise exceptions.InvalidConfiguration( - "Account file %s doesn't exist" % CONF.auth.test_accounts_file) - useable_hashes = self._get_match_hash_list(roles) - free_hash = self._get_free_hash(useable_hashes) - clean_creds = self._sanitize_creds( - self.hash_dict['creds'][free_hash]) - LOG.info('%s allocated creds:\n%s' % (self.name, clean_creds)) - return self._wrap_creds_with_network(free_hash) - - @lockutils.synchronized('test_accounts_io', external=True) - def remove_hash(self, hash_string): - hash_path = os.path.join(self.accounts_dir, hash_string) - if not os.path.isfile(hash_path): - LOG.warning('Expected an account lock file %s to remove, but ' - 'one did not exist' % hash_path) - else: - os.remove(hash_path) - if not os.listdir(self.accounts_dir): - os.rmdir(self.accounts_dir) - - def get_hash(self, creds): - for _hash in self.hash_dict['creds']: - # Comparing on the attributes that are expected in the YAML - init_attributes = creds.get_init_attributes() - hash_attributes = self.hash_dict['creds'][_hash].copy() - if ('user_domain_name' in init_attributes and 'user_domain_name' - not in hash_attributes): - # Allow for the case of domain_name populated from config - domain_name = CONF.identity.admin_domain_name - hash_attributes['user_domain_name'] = domain_name - if all([getattr(creds, k) == hash_attributes[k] for - k in init_attributes]): - return _hash - raise AttributeError('Invalid credentials %s' % creds) - - def remove_credentials(self, creds): - _hash = self.get_hash(creds) - clean_creds = self._sanitize_creds(self.hash_dict['creds'][_hash]) - self.remove_hash(_hash) - LOG.info("%s returned allocated creds:\n%s" % (self.name, clean_creds)) - - def get_primary_creds(self): - if self.isolated_creds.get('primary'): - return self.isolated_creds.get('primary') - net_creds = self._get_creds() - self.isolated_creds['primary'] = net_creds - return net_creds - - def get_alt_creds(self): - if self.isolated_creds.get('alt'): - return self.isolated_creds.get('alt') - net_creds = self._get_creds() - self.isolated_creds['alt'] = net_creds - return net_creds - - def get_creds_by_roles(self, roles, force_new=False): - roles = list(set(roles)) - exist_creds = self.isolated_creds.get(str(roles), None) - # The force kwarg is used to allocate an additional set of creds with - # the same role list. The index used for the previously allocation - # in the isolated_creds dict will be moved. - if exist_creds and not force_new: - return exist_creds - elif exist_creds and force_new: - new_index = str(roles) + '-' + str(len(self.isolated_creds)) - self.isolated_creds[new_index] = exist_creds - net_creds = self._get_creds(roles=roles) - self.isolated_creds[str(roles)] = net_creds - return net_creds - - def clear_isolated_creds(self): - for creds in self.isolated_creds.values(): - self.remove_credentials(creds) - - def get_admin_creds(self): - return self.get_creds_by_roles([CONF.identity.admin_role]) - - def is_role_available(self, role): - if self.use_default_creds: - return False - else: - if self.hash_dict['roles'].get(role): - return True - return False - - def admin_available(self): - return self.is_role_available(CONF.identity.admin_role) - - def _wrap_creds_with_network(self, hash): - creds_dict = self.hash_dict['creds'][hash] - credential = cred_provider.get_credentials( - identity_version=self.identity_version, **creds_dict) - net_creds = cred_provider.TestResources(credential) - net_clients = clients.Manager(credentials=credential) - compute_network_client = net_clients.networks_client - net_name = self.hash_dict['networks'].get(hash, None) - network = fixed_network.get_network_from_name( - net_name, compute_network_client) - net_creds.set_resources(network=network) - return net_creds - - -class NotLockingAccounts(Accounts): - """Credentials provider which always returns the first and second - configured accounts as primary and alt users. - This credential provider can be used in case of serial test execution - to preserve the current behaviour of the serial tempest run. - """ - - def _unique_creds(self, cred_arg=None): - """Verify that the configured credentials are valid and distinct """ - try: - user = self.get_primary_creds() - alt_user = self.get_alt_creds() - return getattr(user, cred_arg) != getattr(alt_user, cred_arg) - except exceptions.InvalidCredentials as ic: - msg = "At least one of the configured credentials is " \ - "not valid: %s" % ic.message - raise exceptions.InvalidConfiguration(msg) - - def is_multi_user(self): - return self._unique_creds('username') - - def is_multi_tenant(self): - return self._unique_creds('tenant_id') - - def get_primary_creds(self): - if self.isolated_creds.get('primary'): - return self.isolated_creds.get('primary') - primary_credential = cred_provider.get_configured_credentials( - credential_type='user', identity_version=self.identity_version) - self.isolated_creds['primary'] = cred_provider.TestResources( - primary_credential) - return self.isolated_creds['primary'] - - def get_alt_creds(self): - if self.isolated_creds.get('alt'): - return self.isolated_creds.get('alt') - alt_credential = cred_provider.get_configured_credentials( - credential_type='alt_user', - identity_version=self.identity_version) - self.isolated_creds['alt'] = cred_provider.TestResources( - alt_credential) - return self.isolated_creds['alt'] - - def clear_isolated_creds(self): - self.isolated_creds = {} - - def get_admin_creds(self): - creds = cred_provider.get_configured_credentials( - "identity_admin", fill_in=False) - self.isolated_creds['admin'] = cred_provider.TestResources(creds) - return self.isolated_creds['admin'] - - def get_creds_by_roles(self, roles, force_new=False): - msg = "Credentials being specified through the config file can not be"\ - " used with tests that specify using credentials by roles. "\ - "Either exclude/skip the tests doing this or use either an "\ - "test_accounts_file or tenant isolation." - raise exceptions.InvalidConfiguration(msg) diff --git a/test/tempest/tempest/common/commands.py b/test/tempest/tempest/common/commands.py deleted file mode 100644 index 392c9d06..00000000 --- a/test/tempest/tempest/common/commands.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 shlex -import subprocess - -from oslo_log import log as logging - -LOG = logging.getLogger(__name__) - - -def copy_file_to_host(file_from, dest, host, username, pkey): - dest = "%s@%s:%s" % (username, host, dest) - cmd = "scp -v -o UserKnownHostsFile=/dev/null " \ - "-o StrictHostKeyChecking=no " \ - "-i %(pkey)s %(file1)s %(dest)s" % {'pkey': pkey, - 'file1': file_from, - 'dest': dest} - args = shlex.split(cmd.encode('utf-8')) - subprocess_args = {'stdout': subprocess.PIPE, - 'stderr': subprocess.STDOUT} - proc = subprocess.Popen(args, **subprocess_args) - stdout, stderr = proc.communicate() - if proc.returncode != 0: - LOG.error(("Command {0} returned with exit status {1}," - "output {2}, error {3}").format(cmd, proc.returncode, - stdout, stderr)) - return stdout diff --git a/test/tempest/tempest/common/cred_provider.py b/test/tempest/tempest/common/cred_provider.py deleted file mode 100644 index 32230276..00000000 --- a/test/tempest/tempest/common/cred_provider.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright (c) 2014 Deutsche Telekom AG -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# 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 abc - -from oslo_log import log as logging -import six - -from tempest import auth -from tempest import config -from tempest import exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - -# Type of credentials available from configuration -CREDENTIAL_TYPES = { - 'identity_admin': ('identity', 'admin'), - 'user': ('identity', None), - 'alt_user': ('identity', 'alt') -} - -DEFAULT_PARAMS = { - 'disable_ssl_certificate_validation': - CONF.identity.disable_ssl_certificate_validation, - 'ca_certs': CONF.identity.ca_certificates_file, - 'trace_requests': CONF.debug.trace_requests -} - - -# Read credentials from configuration, builds a Credentials object -# based on the specified or configured version -def get_configured_credentials(credential_type, fill_in=True, - identity_version=None): - identity_version = identity_version or CONF.identity.auth_version - if identity_version not in ('v2', 'v3'): - raise exceptions.InvalidConfiguration( - 'Unsupported auth version: %s' % identity_version) - if credential_type not in CREDENTIAL_TYPES: - raise exceptions.InvalidCredentials() - conf_attributes = ['username', 'password', 'tenant_name'] - if identity_version == 'v3': - conf_attributes.append('domain_name') - # Read the parts of credentials from config - params = DEFAULT_PARAMS.copy() - section, prefix = CREDENTIAL_TYPES[credential_type] - for attr in conf_attributes: - _section = getattr(CONF, section) - if prefix is None: - params[attr] = getattr(_section, attr) - else: - params[attr] = getattr(_section, prefix + "_" + attr) - # Build and validate credentials. We are reading configured credentials, - # so validate them even if fill_in is False - credentials = get_credentials(fill_in=fill_in, - identity_version=identity_version, **params) - if not fill_in: - if not credentials.is_valid(): - msg = ("The %s credentials are incorrectly set in the config file." - " Double check that all required values are assigned" % - credential_type) - raise exceptions.InvalidConfiguration(msg) - return credentials - - -# Wrapper around auth.get_credentials to use the configured identity version -# is none is specified -def get_credentials(fill_in=True, identity_version=None, **kwargs): - params = dict(DEFAULT_PARAMS, **kwargs) - identity_version = identity_version or CONF.identity.auth_version - # In case of "v3" add the domain from config if not specified - if identity_version == 'v3': - domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES - if 'domain' in x) - if not domain_fields.intersection(kwargs.keys()): - # TODO(andreaf) It might be better here to use a dedicated config - # option such as CONF.auth.tenant_isolation_domain_name - params['user_domain_name'] = CONF.identity.admin_domain_name - auth_url = CONF.identity.uri_v3 - else: - auth_url = CONF.identity.uri - return auth.get_credentials(auth_url, - fill_in=fill_in, - identity_version=identity_version, - **params) - - -@six.add_metaclass(abc.ABCMeta) -class CredentialProvider(object): - def __init__(self, identity_version=None, name=None, password='pass', - network_resources=None): - """A CredentialProvider supplies credentials to test classes. - :param identity_version If specified it will return credentials of the - corresponding identity version, otherwise it - uses auth_version from configuration - :param name Name of the calling test. Included in provisioned - credentials when credentials are provisioned on the fly - :param password Used for provisioned credentials when credentials are - provisioned on the fly - :param network_resources Network resources required for the credentials - """ - # TODO(andreaf) name and password are tenant isolation specific, and - # could be removed from this abstract class - self.name = name or "test_creds" - self.identity_version = identity_version or CONF.identity.auth_version - if not auth.is_identity_version_supported(self.identity_version): - raise exceptions.InvalidIdentityVersion( - identity_version=self.identity_version) - - @abc.abstractmethod - def get_primary_creds(self): - return - - @abc.abstractmethod - def get_admin_creds(self): - return - - @abc.abstractmethod - def get_alt_creds(self): - return - - @abc.abstractmethod - def clear_isolated_creds(self): - return - - @abc.abstractmethod - def is_multi_user(self): - return - - @abc.abstractmethod - def is_multi_tenant(self): - return - - @abc.abstractmethod - def get_creds_by_roles(self, roles, force_new=False): - return - - @abc.abstractmethod - def is_role_available(self, role): - return - - -class TestResources(object): - """Readonly Credentials, with network resources added.""" - - def __init__(self, credentials): - self._credentials = credentials - self.network = None - self.subnet = None - self.router = None - - def __getattr__(self, item): - return getattr(self._credentials, item) - - def set_resources(self, **kwargs): - for key in kwargs.keys(): - if hasattr(self, key): - setattr(self, key, kwargs[key]) - - @property - def credentials(self): - return self._credentials diff --git a/test/tempest/tempest/common/credentials.py b/test/tempest/tempest/common/credentials.py deleted file mode 100644 index 71d905f8..00000000 --- a/test/tempest/tempest/common/credentials.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# 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 os - -from tempest.common import accounts -from tempest.common import cred_provider -from tempest.common import isolated_creds -from tempest import config -from tempest import exceptions - -CONF = config.CONF - - -# 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_isolated_credentials(name, network_resources=None, - force_tenant_isolation=False, - identity_version=None): - # If a test requires a new account to work, it can have it via forcing - # tenant isolation. 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. - if CONF.auth.allow_tenant_isolation or force_tenant_isolation: - return isolated_creds.IsolatedCreds( - name=name, - network_resources=network_resources, - identity_version=identity_version) - else: - if (CONF.auth.test_accounts_file and - os.path.isfile(CONF.auth.test_accounts_file)): - # Most params are not relevant for pre-created accounts - return accounts.Accounts(name=name, - identity_version=identity_version) - else: - return accounts.NotLockingAccounts( - name=name, identity_version=identity_version) - - -# We want a helper function here to check and see if admin credentials -# are available so we can do a single call from skip_checks if admin -# creds area vailable. -def is_admin_available(): - is_admin = True - # If tenant isolation is enabled admin will be available - if CONF.auth.allow_tenant_isolation: - return is_admin - # Check whether test accounts file has the admin specified or not - elif (CONF.auth.test_accounts_file and - os.path.isfile(CONF.auth.test_accounts_file)): - check_accounts = accounts.Accounts(name='check_admin') - if not check_accounts.admin_available(): - is_admin = False - else: - try: - cred_provider.get_configured_credentials('identity_admin', - fill_in=False) - except exceptions.InvalidConfiguration: - is_admin = False - return is_admin - - -# We want a helper function here to check and see if alt credentials -# are available so we can do a single call from skip_checks if alt -# creds area vailable. -def is_alt_available(): - # If tenant isolation is enabled admin will be available - if CONF.auth.allow_tenant_isolation: - return True - # Check whether test accounts file has the admin specified or not - if (CONF.auth.test_accounts_file and - os.path.isfile(CONF.auth.test_accounts_file)): - check_accounts = accounts.Accounts(name='check_alt') - else: - check_accounts = accounts.NotLockingAccounts(name='check_alt') - try: - if not check_accounts.is_multi_user(): - return False - else: - return True - except exceptions.InvalidConfiguration: - return False diff --git a/test/tempest/tempest/common/custom_matchers.py b/test/tempest/tempest/common/custom_matchers.py deleted file mode 100644 index 298a94ec..00000000 --- a/test/tempest/tempest/common/custom_matchers.py +++ /dev/null @@ -1,226 +0,0 @@ -# Copyright 2013 NTT Corporation -# -# 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 re - -from testtools import helpers - - -class ExistsAllResponseHeaders(object): - """ - Specific matcher to check the existence of Swift's response headers - - This matcher checks the existence of common headers for each HTTP method - or the target, which means account, container or object. - When checking the existence of 'specific' headers such as - X-Account-Meta-* or X-Object-Manifest for example, those headers must be - checked in each test code. - """ - - def __init__(self, target, method): - """ - param: target Account/Container/Object - param: method PUT/GET/HEAD/DELETE/COPY/POST - """ - self.target = target - self.method = method - - def match(self, actual): - """ - param: actual HTTP response headers - """ - # Check common headers for all HTTP methods - if 'content-length' not in actual: - return NonExistentHeader('content-length') - if 'content-type' not in actual: - return NonExistentHeader('content-type') - if 'x-trans-id' not in actual: - return NonExistentHeader('x-trans-id') - if 'date' not in actual: - return NonExistentHeader('date') - - # Check headers for a specific method or target - if self.method == 'GET' or self.method == 'HEAD': - if 'x-timestamp' not in actual: - return NonExistentHeader('x-timestamp') - if 'accept-ranges' not in actual: - return NonExistentHeader('accept-ranges') - if self.target == 'Account': - if 'x-account-bytes-used' not in actual: - return NonExistentHeader('x-account-bytes-used') - if 'x-account-container-count' not in actual: - return NonExistentHeader('x-account-container-count') - if 'x-account-object-count' not in actual: - return NonExistentHeader('x-account-object-count') - elif self.target == 'Container': - if 'x-container-bytes-used' not in actual: - return NonExistentHeader('x-container-bytes-used') - if 'x-container-object-count' not in actual: - return NonExistentHeader('x-container-object-count') - elif self.target == 'Object': - if 'etag' not in actual: - return NonExistentHeader('etag') - if 'last-modified' not in actual: - return NonExistentHeader('last-modified') - elif self.method == 'PUT': - if self.target == 'Object': - if 'etag' not in actual: - return NonExistentHeader('etag') - if 'last-modified' not in actual: - return NonExistentHeader('last-modified') - elif self.method == 'COPY': - if self.target == 'Object': - if 'etag' not in actual: - return NonExistentHeader('etag') - if 'last-modified' not in actual: - return NonExistentHeader('last-modified') - if 'x-copied-from' not in actual: - return NonExistentHeader('x-copied-from') - if 'x-copied-from-last-modified' not in actual: - return NonExistentHeader('x-copied-from-last-modified') - - return None - - -class NonExistentHeader(object): - """ - Informs an error message for end users in the case of missing a - certain header in Swift's responses - """ - - def __init__(self, header): - self.header = header - - def describe(self): - return "%s header does not exist" % self.header - - def get_details(self): - return {} - - -class AreAllWellFormatted(object): - """ - Specific matcher to check the correctness of formats of values of Swift's - response headers - - This matcher checks the format of values of response headers. - When checking the format of values of 'specific' headers such as - X-Account-Meta-* or X-Object-Manifest for example, those values must be - checked in each test code. - """ - - def match(self, actual): - for key, value in actual.iteritems(): - if key in ('content-length', 'x-account-bytes-used', - 'x-account-container-count', 'x-account-object-count', - 'x-container-bytes-used', 'x-container-object-count')\ - and not value.isdigit(): - return InvalidFormat(key, value) - elif key in ('content-type', 'date', 'last-modified', - 'x-copied-from-last-modified') and not value: - return InvalidFormat(key, value) - elif key == 'x-timestamp' and not re.match("^\d+\.?\d*\Z", value): - return InvalidFormat(key, value) - elif key == 'x-copied-from' and not re.match("\S+/\S+", value): - return InvalidFormat(key, value) - elif key == 'x-trans-id' and \ - not re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*", value): - return InvalidFormat(key, value) - elif key == 'accept-ranges' and not value == 'bytes': - return InvalidFormat(key, value) - elif key == 'etag' and not value.isalnum(): - return InvalidFormat(key, value) - elif key == 'transfer-encoding' and not value == 'chunked': - return InvalidFormat(key, value) - - return None - - -class InvalidFormat(object): - """ - Informs an error message for end users if a format of a certain header - is invalid - """ - - def __init__(self, key, value): - self.key = key - self.value = value - - def describe(self): - return "InvalidFormat (%s, %s)" % (self.key, self.value) - - def get_details(self): - return {} - - -class MatchesDictExceptForKeys(object): - """Matches two dictionaries. Verifies all items are equals except for those - identified by a list of keys. - """ - - def __init__(self, expected, excluded_keys=None): - self.expected = expected - self.excluded_keys = excluded_keys if excluded_keys is not None else [] - - def match(self, actual): - filtered_expected = helpers.dict_subtract(self.expected, - self.excluded_keys) - filtered_actual = helpers.dict_subtract(actual, - self.excluded_keys) - if filtered_actual != filtered_expected: - return DictMismatch(filtered_expected, filtered_actual) - - -class DictMismatch(object): - """Mismatch between two dicts describes deltas""" - - def __init__(self, expected, actual): - self.expected = expected - self.actual = actual - self.intersect = set(self.expected) & set(self.actual) - self.symmetric_diff = set(self.expected) ^ set(self.actual) - - def _format_dict(self, dict_to_format): - # Ensure the error string dict is printed in a set order - # NOTE(mtreinish): needed to ensure a deterministic error msg for - # testing. Otherwise the error message will be dependent on the - # dict ordering. - dict_string = "{" - for key in sorted(dict_to_format): - dict_string += "'%s': %s, " % (key, dict_to_format[key]) - dict_string = dict_string[:-2] + '}' - return dict_string - - def describe(self): - msg = "" - if self.symmetric_diff: - only_expected = helpers.dict_subtract(self.expected, self.actual) - only_actual = helpers.dict_subtract(self.actual, self.expected) - if only_expected: - msg += "Only in expected:\n %s\n" % self._format_dict( - only_expected) - if only_actual: - msg += "Only in actual:\n %s\n" % self._format_dict( - only_actual) - diff_set = set(o for o in self.intersect if - self.expected[o] != self.actual[o]) - if diff_set: - msg += "Differences:\n" - for o in diff_set: - msg += " %s: expected %s, actual %s\n" % ( - o, self.expected[o], self.actual[o]) - return msg - - def get_details(self): - return {} diff --git a/test/tempest/tempest/common/fixed_network.py b/test/tempest/tempest/common/fixed_network.py deleted file mode 100644 index a1e99bdc..00000000 --- a/test/tempest/tempest/common/fixed_network.py +++ /dev/null @@ -1,130 +0,0 @@ -# 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 oslo_log import log as logging - -from tempest_lib.common.utils import misc as misc_utils -from tempest_lib import exceptions as lib_exc - -from tempest import config - -CONF = config.CONF - -LOG = logging.getLogger(__name__) - - -def get_network_from_name(name, compute_networks_client): - """Get a full network dict from just a network name - - :param str name: the name of the network to use - :param NetworksClientJSON compute_networks_client: The network client - object to use for making the network lists api request - :return: The full dictionary for the network in question, unless the - network for the supplied name can not be found. In which case a dict - with just the name will be returned. - :rtype: dict - """ - caller = misc_utils.find_test_caller() - if not name: - network = {'name': name} - else: - try: - resp = compute_networks_client.list_networks(name=name) - if isinstance(resp, list): - networks = resp - elif isinstance(resp, dict): - networks = resp['networks'] - else: - raise lib_exc.NotFound() - if len(networks) > 0: - network = networks[0] - else: - msg = "Network with name: %s not found" % name - if caller: - LOG.warning('(%s) %s' % (caller, msg)) - else: - LOG.warning(msg) - raise lib_exc.NotFound() - # To be consistent with network isolation, add name is only - # label is available - name = network.get('name', network.get('label')) - if name: - network['name'] = name - else: - raise lib_exc.NotFound() - except lib_exc.NotFound: - # In case of nova network, if the fixed_network_name is not - # owned by the tenant, and the network client is not an admin - # one, list_networks will not find it - msg = ('Unable to find network %s. ' - 'Starting instance without specifying a network.' % - name) - if caller: - LOG.info('(%s) %s' % (caller, msg)) - else: - LOG.info(msg) - network = {'name': name} - return network - - -def get_tenant_network(creds_provider, compute_networks_client): - """Get a network usable by the primary tenant - - :param creds_provider: instance of credential provider - :param compute_networks_client: compute network client. We want to have the - compute network client so we can have use a common approach for both - neutron and nova-network cases. If this is not an admin network - client, set_network_kwargs might fail in case fixed_network_name - is the network to be used, and it's not visible to the tenant - :return a dict with 'id' and 'name' of the network - """ - caller = misc_utils.find_test_caller() - fixed_network_name = CONF.compute.fixed_network_name - net_creds = creds_provider.get_primary_creds() - network = getattr(net_creds, 'network', None) - if not network or not network.get('name'): - if fixed_network_name: - msg = ('No valid network provided or created, defaulting to ' - 'fixed_network_name') - if caller: - LOG.debug('(%s) %s' % (caller, msg)) - else: - LOG.debug(msg) - network = get_network_from_name(fixed_network_name, - compute_networks_client) - msg = ('Found network %s available for tenant' % network) - if caller: - LOG.info('(%s) %s' % (caller, msg)) - else: - LOG.info(msg) - return network - - -def set_networks_kwarg(network, kwargs=None): - """Set 'networks' kwargs for a server create if missing - - :param network: dict of network to be used with 'id' and 'name' - :param kwargs: server create kwargs to be enhanced - :return: new dict of kwargs updated to include networks - """ - params = copy.copy(kwargs) or {} - if kwargs and 'networks' in kwargs: - return params - - if network: - if 'id' in network.keys(): - params.update({"networks": [{'uuid': network['id']}]}) - else: - LOG.warning('provided network dict: %s was invalid, did not ' - ' contain an id' % network) - return params diff --git a/test/tempest/tempest/common/generator/__init__.py b/test/tempest/tempest/common/generator/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/common/generator/base_generator.py b/test/tempest/tempest/common/generator/base_generator.py deleted file mode 100644 index f81f4055..00000000 --- a/test/tempest/tempest/common/generator/base_generator.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2014 Deutsche Telekom AG -# 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 -import functools - -import jsonschema - -from oslo_log import log as logging - -LOG = logging.getLogger(__name__) - - -def _check_for_expected_result(name, schema): - expected_result = None - if "results" in schema: - if name in schema["results"]: - expected_result = schema["results"][name] - return expected_result - - -def generator_type(*args, **kwargs): - def wrapper(func): - func.types = args - for key in kwargs: - setattr(func, key, kwargs[key]) - return func - return wrapper - - -def simple_generator(fn): - """ - Decorator for simple generators that return one value - """ - @functools.wraps(fn) - def wrapped(self, schema): - result = fn(self, schema) - if result is not None: - expected_result = _check_for_expected_result(fn.__name__, schema) - return (fn.__name__, result, expected_result) - return - return wrapped - - -class BasicGeneratorSet(object): - _instance = None - - schema = { - "type": "object", - "properties": { - "name": {"type": "string"}, - "http-method": { - "enum": ["GET", "PUT", "HEAD", - "POST", "PATCH", "DELETE", 'COPY'] - }, - "admin_client": {"type": "boolean"}, - "url": {"type": "string"}, - "default_result_code": {"type": "integer"}, - "json-schema": {}, - "resources": { - "type": "array", - "items": { - "oneOf": [ - {"type": "string"}, - { - "type": "object", - "properties": { - "name": {"type": "string"}, - "expected_result": {"type": "integer"} - } - } - ] - } - }, - "results": { - "type": "object", - "properties": {} - } - }, - "required": ["name", "http-method", "url"], - "additionalProperties": False, - } - - def __init__(self): - self.types_dict = {} - for m in dir(self): - if callable(getattr(self, m)) and not'__' in m: - method = getattr(self, m) - if hasattr(method, "types"): - for type in method.types: - if type not in self.types_dict: - self.types_dict[type] = [] - self.types_dict[type].append(method) - - def validate_schema(self, schema): - if "json-schema" in schema: - jsonschema.Draft4Validator.check_schema(schema['json-schema']) - jsonschema.validate(schema, self.schema) - - def generate_scenarios(self, schema, path=None): - """ - Generates the scenario (all possible test cases) out of the given - schema. - - :param schema: a dict style schema (see ``BasicGeneratorSet.schema``) - :param path: the schema path if the given schema is a subschema - """ - schema_type = schema['type'] - scenarios = [] - - if schema_type == 'object': - properties = schema["properties"] - for attribute, definition in properties.iteritems(): - current_path = copy.copy(path) - if path is not None: - current_path.append(attribute) - else: - current_path = [attribute] - scenarios.extend( - self.generate_scenarios(definition, current_path)) - elif isinstance(schema_type, list): - if "integer" in schema_type: - schema_type = "integer" - else: - raise Exception("non-integer list types not supported") - for generator in self.types_dict[schema_type]: - if hasattr(generator, "needed_property"): - prop = generator.needed_property - if (prop not in schema or - schema[prop] is None or - schema[prop] is False): - continue - - name = generator.__name__ - if ("exclude_tests" in schema and - name in schema["exclude_tests"]): - continue - if path is not None: - name = "%s_%s" % ("_".join(path), name) - scenarios.append({ - "_negtest_name": name, - "_negtest_generator": generator, - "_negtest_schema": schema, - "_negtest_path": path}) - return scenarios - - def generate_payload(self, test, schema): - """ - Generates one jsonschema out of the given test. It's mandatory to use - generate_scenarios before to register all needed variables to the test. - - :param test: A test object (scenario) with all _negtest variables on it - :param schema: schema for the test - """ - generator = test._negtest_generator - ret = generator(test._negtest_schema) - path = copy.copy(test._negtest_path) - expected_result = None - - if ret is not None: - generator_result = generator(test._negtest_schema) - invalid_snippet = generator_result[1] - expected_result = generator_result[2] - element = path.pop() - if len(path) > 0: - schema_snip = reduce(dict.get, path, schema) - schema_snip[element] = invalid_snippet - else: - schema[element] = invalid_snippet - return expected_result diff --git a/test/tempest/tempest/common/generator/negative_generator.py b/test/tempest/tempest/common/generator/negative_generator.py deleted file mode 100644 index 17997a52..00000000 --- a/test/tempest/tempest/common/generator/negative_generator.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2014 Deutsche Telekom AG -# 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 oslo_log import log as logging - -import tempest.common.generator.base_generator as base -import tempest.common.generator.valid_generator as valid - -LOG = logging.getLogger(__name__) - - -class NegativeTestGenerator(base.BasicGeneratorSet): - @base.generator_type("string") - @base.simple_generator - def gen_int(self, _): - return 4 - - @base.generator_type("integer") - @base.simple_generator - def gen_string(self, _): - return "XXXXXX" - - @base.generator_type("integer", "string") - def gen_none(self, schema): - # Note(mkoderer): it's not using the decorator otherwise it'd be - # filtered - expected_result = base._check_for_expected_result('gen_none', schema) - return ('gen_none', None, expected_result) - - @base.generator_type("string") - @base.simple_generator - def gen_str_min_length(self, schema): - min_length = schema.get("minLength", 0) - if min_length > 0: - return "x" * (min_length - 1) - - @base.generator_type("string", needed_property="maxLength") - @base.simple_generator - def gen_str_max_length(self, schema): - max_length = schema.get("maxLength", -1) - return "x" * (max_length + 1) - - @base.generator_type("integer", needed_property="minimum") - @base.simple_generator - def gen_int_min(self, schema): - minimum = schema["minimum"] - if "exclusiveMinimum" not in schema: - minimum -= 1 - return minimum - - @base.generator_type("integer", needed_property="maximum") - @base.simple_generator - def gen_int_max(self, schema): - maximum = schema["maximum"] - if "exclusiveMaximum" not in schema: - maximum += 1 - return maximum - - @base.generator_type("object", needed_property="additionalProperties") - @base.simple_generator - def gen_obj_add_attr(self, schema): - valid_schema = valid.ValidTestGenerator().generate_valid(schema) - new_valid = copy.deepcopy(valid_schema) - new_valid["$$$$$$$$$$"] = "xxx" - return new_valid diff --git a/test/tempest/tempest/common/generator/valid_generator.py b/test/tempest/tempest/common/generator/valid_generator.py deleted file mode 100644 index 0c63bf51..00000000 --- a/test/tempest/tempest/common/generator/valid_generator.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2014 Deutsche Telekom AG -# 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_log import log as logging - -import tempest.common.generator.base_generator as base - - -LOG = logging.getLogger(__name__) - - -class ValidTestGenerator(base.BasicGeneratorSet): - @base.generator_type("string") - @base.simple_generator - def generate_valid_string(self, schema): - size = schema.get("minLength", 1) - # TODO(dkr mko): handle format and pattern - return "x" * size - - @base.generator_type("integer") - @base.simple_generator - def generate_valid_integer(self, schema): - # TODO(dkr mko): handle multipleOf - if "minimum" in schema: - minimum = schema["minimum"] - if "exclusiveMinimum" not in schema: - return minimum - else: - return minimum + 1 - if "maximum" in schema: - maximum = schema["maximum"] - if "exclusiveMaximum" not in schema: - return maximum - else: - return maximum - 1 - return 0 - - @base.generator_type("object") - @base.simple_generator - def generate_valid_object(self, schema): - obj = {} - for k, v in schema["properties"].iteritems(): - obj[k] = self.generate_valid(v) - return obj - - def generate(self, schema): - schema_type = schema["type"] - if isinstance(schema_type, list): - if "integer" in schema_type: - schema_type = "integer" - else: - raise Exception("non-integer list types not supported") - result = [] - if schema_type not in self.types_dict: - raise TypeError("generator (%s) doesn't support type: %s" - % (self.__class__.__name__, schema_type)) - for generator in self.types_dict[schema_type]: - ret = generator(schema) - if ret is not None: - if isinstance(ret, list): - result.extend(ret) - elif isinstance(ret, tuple): - result.append(ret) - else: - raise Exception("generator (%s) returns invalid result: %s" - % (generator, ret)) - return result - - def generate_valid(self, schema): - return self.generate(schema)[0][1] diff --git a/test/tempest/tempest/common/glance_http.py b/test/tempest/tempest/common/glance_http.py deleted file mode 100644 index 5cd844cb..00000000 --- a/test/tempest/tempest/common/glance_http.py +++ /dev/null @@ -1,376 +0,0 @@ -# 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. - -# Originally copied from python-glanceclient - -import copy -import hashlib -import json -import posixpath -import re -import socket -import struct - -import OpenSSL -from oslo_log import log as logging -import six -from six import moves -from six.moves import http_client as httplib -from six.moves.urllib import parse as urlparse -from tempest_lib import exceptions as lib_exc - -from tempest import exceptions as exc - -LOG = logging.getLogger(__name__) -USER_AGENT = 'tempest' -CHUNKSIZE = 1024 * 64 # 64kB -TOKEN_CHARS_RE = re.compile('^[-A-Za-z0-9+/=]*$') - - -class HTTPClient(object): - - def __init__(self, auth_provider, filters, **kwargs): - self.auth_provider = auth_provider - self.filters = filters - self.endpoint = auth_provider.base_url(filters) - endpoint_parts = urlparse.urlparse(self.endpoint) - self.endpoint_scheme = endpoint_parts.scheme - self.endpoint_hostname = endpoint_parts.hostname - self.endpoint_port = endpoint_parts.port - self.endpoint_path = endpoint_parts.path - - self.connection_class = self.get_connection_class(self.endpoint_scheme) - self.connection_kwargs = self.get_connection_kwargs( - self.endpoint_scheme, **kwargs) - - @staticmethod - def get_connection_class(scheme): - if scheme == 'https': - return VerifiedHTTPSConnection - else: - return httplib.HTTPConnection - - @staticmethod - def get_connection_kwargs(scheme, **kwargs): - _kwargs = {'timeout': float(kwargs.get('timeout', 600))} - - if scheme == 'https': - _kwargs['ca_certs'] = kwargs.get('ca_certs', None) - _kwargs['cert_file'] = kwargs.get('cert_file', None) - _kwargs['key_file'] = kwargs.get('key_file', None) - _kwargs['insecure'] = kwargs.get('insecure', False) - _kwargs['ssl_compression'] = kwargs.get('ssl_compression', True) - - return _kwargs - - def get_connection(self): - _class = self.connection_class - try: - return _class(self.endpoint_hostname, self.endpoint_port, - **self.connection_kwargs) - except httplib.InvalidURL: - raise exc.EndpointNotFound - - def _http_request(self, url, method, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around httplib.HTTP(S)Connection.request to handle tasks such - as setting headers and error handling. - """ - # Copy the kwargs so we can reuse the original in case of redirects - kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) - kwargs['headers'].setdefault('User-Agent', USER_AGENT) - - self._log_request(method, url, kwargs['headers']) - - conn = self.get_connection() - - try: - url_parts = urlparse.urlparse(url) - conn_url = posixpath.normpath(url_parts.path) - LOG.debug('Actual Path: {path}'.format(path=conn_url)) - if kwargs['headers'].get('Transfer-Encoding') == 'chunked': - conn.putrequest(method, conn_url) - for header, value in kwargs['headers'].items(): - conn.putheader(header, value) - conn.endheaders() - chunk = kwargs['body'].read(CHUNKSIZE) - # Chunk it, baby... - while chunk: - conn.send('%x\r\n%s\r\n' % (len(chunk), chunk)) - chunk = kwargs['body'].read(CHUNKSIZE) - conn.send('0\r\n\r\n') - else: - conn.request(method, conn_url, **kwargs) - resp = conn.getresponse() - except socket.gaierror as e: - message = ("Error finding address for %(url)s: %(e)s" % - {'url': url, 'e': e}) - raise exc.EndpointNotFound(message) - except (socket.error, socket.timeout) as e: - message = ("Error communicating with %(endpoint)s %(e)s" % - {'endpoint': self.endpoint, 'e': e}) - raise exc.TimeoutException(message) - - body_iter = ResponseBodyIterator(resp) - # Read body into string if it isn't obviously image data - if resp.getheader('content-type', None) != 'application/octet-stream': - body_str = ''.join([body_chunk for body_chunk in body_iter]) - body_iter = six.StringIO(body_str) - self._log_response(resp, None) - else: - self._log_response(resp, body_iter) - - return resp, body_iter - - def _log_request(self, method, url, headers): - LOG.info('Request: ' + method + ' ' + url) - if headers: - headers_out = headers - if 'X-Auth-Token' in headers and headers['X-Auth-Token']: - token = headers['X-Auth-Token'] - if len(token) > 64 and TOKEN_CHARS_RE.match(token): - headers_out = headers.copy() - headers_out['X-Auth-Token'] = "" - LOG.info('Request Headers: ' + str(headers_out)) - - def _log_response(self, resp, body): - status = str(resp.status) - LOG.info("Response Status: " + status) - if resp.getheaders(): - LOG.info('Response Headers: ' + str(resp.getheaders())) - if body: - str_body = str(body) - length = len(body) - LOG.info('Response Body: ' + str_body[:2048]) - if length >= 2048: - self.LOG.debug("Large body (%d) md5 summary: %s", length, - hashlib.md5(str_body).hexdigest()) - - def json_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', 'application/json') - if kwargs['headers']['Content-Type'] != 'application/json': - msg = "Only application/json content-type is supported." - raise lib_exc.InvalidContentType(msg) - - if 'body' in kwargs: - kwargs['body'] = json.dumps(kwargs['body']) - - resp, body_iter = self._http_request(url, method, **kwargs) - - if 'application/json' in resp.getheader('content-type', ''): - body = ''.join([chunk for chunk in body_iter]) - try: - body = json.loads(body) - except ValueError: - LOG.error('Could not decode response body as JSON') - else: - msg = "Only json/application content-type is supported." - raise lib_exc.InvalidContentType(msg) - - return resp, body - - def raw_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', - 'application/octet-stream') - if 'body' in kwargs: - if (hasattr(kwargs['body'], 'read') - and method.lower() in ('post', 'put')): - # We use 'Transfer-Encoding: chunked' because - # body size may not always be known in advance. - kwargs['headers']['Transfer-Encoding'] = 'chunked' - - # Decorate the request with auth - req_url, kwargs['headers'], kwargs['body'] = \ - self.auth_provider.auth_request( - method=method, url=url, headers=kwargs['headers'], - body=kwargs.get('body', None), filters=self.filters) - return self._http_request(req_url, method, **kwargs) - - -class OpenSSLConnectionDelegator(object): - """ - An OpenSSL.SSL.Connection delegator. - - Supplies an additional 'makefile' method which httplib requires - and is not present in OpenSSL.SSL.Connection. - - Note: Since it is not possible to inherit from OpenSSL.SSL.Connection - a delegator must be used. - """ - def __init__(self, *args, **kwargs): - self.connection = OpenSSL.SSL.Connection(*args, **kwargs) - - def __getattr__(self, name): - return getattr(self.connection, name) - - def makefile(self, *args, **kwargs): - # Ensure the socket is closed when this file is closed - kwargs['close'] = True - return socket._fileobject(self.connection, *args, **kwargs) - - -class VerifiedHTTPSConnection(httplib.HTTPSConnection): - """ - Extended HTTPSConnection which uses the OpenSSL library - for enhanced SSL support. - Note: Much of this functionality can eventually be replaced - with native Python 3.3 code. - """ - def __init__(self, host, port=None, key_file=None, cert_file=None, - ca_certs=None, timeout=None, insecure=False, - ssl_compression=True): - httplib.HTTPSConnection.__init__(self, host, port, - key_file=key_file, - cert_file=cert_file) - self.key_file = key_file - self.cert_file = cert_file - self.timeout = timeout - self.insecure = insecure - self.ssl_compression = ssl_compression - self.ca_certs = ca_certs - self.setcontext() - - @staticmethod - def host_matches_cert(host, x509): - """ - Verify that the the x509 certificate we have received - from 'host' correctly identifies the server we are - connecting to, ie that the certificate's Common Name - or a Subject Alternative Name matches 'host'. - """ - # First see if we can match the CN - if x509.get_subject().commonName == host: - return True - - # Also try Subject Alternative Names for a match - san_list = None - for i in moves.xrange(x509.get_extension_count()): - ext = x509.get_extension(i) - if ext.get_short_name() == 'subjectAltName': - san_list = str(ext) - for san in ''.join(san_list.split()).split(','): - if san == "DNS:%s" % host: - return True - - # Server certificate does not match host - msg = ('Host "%s" does not match x509 certificate contents: ' - 'CommonName "%s"' % (host, x509.get_subject().commonName)) - if san_list is not None: - msg = msg + ', subjectAltName "%s"' % san_list - raise exc.SSLCertificateError(msg) - - def verify_callback(self, connection, x509, errnum, - depth, preverify_ok): - if x509.has_expired(): - msg = "SSL Certificate expired on '%s'" % x509.get_notAfter() - raise exc.SSLCertificateError(msg) - - if depth == 0 and preverify_ok is True: - # We verify that the host matches against the last - # certificate in the chain - return self.host_matches_cert(self.host, x509) - else: - # Pass through OpenSSL's default result - return preverify_ok - - def setcontext(self): - """ - Set up the OpenSSL context. - """ - self.context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) - - if self.ssl_compression is False: - self.context.set_options(0x20000) # SSL_OP_NO_COMPRESSION - - if self.insecure is not True: - self.context.set_verify(OpenSSL.SSL.VERIFY_PEER, - self.verify_callback) - else: - self.context.set_verify(OpenSSL.SSL.VERIFY_NONE, - self.verify_callback) - - if self.cert_file: - try: - self.context.use_certificate_file(self.cert_file) - except Exception as e: - msg = 'Unable to load cert from "%s" %s' % (self.cert_file, e) - raise exc.SSLConfigurationError(msg) - if self.key_file is None: - # We support having key and cert in same file - try: - self.context.use_privatekey_file(self.cert_file) - except Exception as e: - msg = ('No key file specified and unable to load key ' - 'from "%s" %s' % (self.cert_file, e)) - raise exc.SSLConfigurationError(msg) - - if self.key_file: - try: - self.context.use_privatekey_file(self.key_file) - except Exception as e: - msg = 'Unable to load key from "%s" %s' % (self.key_file, e) - raise exc.SSLConfigurationError(msg) - - if self.ca_certs: - try: - self.context.load_verify_locations(self.ca_certs) - except Exception as e: - msg = 'Unable to load CA from "%s"' % (self.ca_certs, e) - raise exc.SSLConfigurationError(msg) - else: - self.context.set_default_verify_paths() - - def connect(self): - """ - Connect to an SSL port using the OpenSSL library and apply - per-connection parameters. - """ - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if self.timeout is not None: - # '0' microseconds - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, - struct.pack('LL', self.timeout, 0)) - self.sock = OpenSSLConnectionDelegator(self.context, sock) - self.sock.connect((self.host, self.port)) - - def close(self): - if self.sock: - # Remove the reference to the socket but don't close it yet. - # Response close will close both socket and associated - # file. Closing socket too soon will cause response - # reads to fail with socket IO error 'Bad file descriptor'. - self.sock = None - httplib.HTTPSConnection.close(self) - - -class ResponseBodyIterator(object): - """A class that acts as an iterator over an HTTP response.""" - - def __init__(self, resp): - self.resp = resp - - def __iter__(self): - while True: - yield self.next() - - def next(self): - chunk = self.resp.read(CHUNKSIZE) - if chunk: - return chunk - else: - raise StopIteration() diff --git a/test/tempest/tempest/common/isolated_creds.py b/test/tempest/tempest/common/isolated_creds.py deleted file mode 100644 index 1221901a..00000000 --- a/test/tempest/tempest/common/isolated_creds.py +++ /dev/null @@ -1,438 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# 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 abc -import netaddr -from oslo_log import log as logging -import six -from tempest_lib.common.utils import data_utils -from tempest_lib import exceptions as lib_exc - -from tempest import clients -from tempest.common import cred_provider -from tempest import config -from tempest import exceptions -from tempest.services.identity.v2.json import identity_client as v2_identity - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -@six.add_metaclass(abc.ABCMeta) -class CredsClient(object): - """This class is a wrapper around the identity clients, to provide a - single interface for managing credentials in both v2 and v3 cases. - It's not bound to created credentials, only to a specific set of admin - credentials used for generating credentials. - """ - - def __init__(self, identity_client): - # The client implies version and credentials - self.identity_client = identity_client - self.credentials = self.identity_client.auth_provider.credentials - - def create_user(self, username, password, project, email): - user = self.identity_client.create_user( - username, password, project['id'], email) - return user - - @abc.abstractmethod - def create_project(self, name, description): - pass - - def assign_user_role(self, user, project, role_name): - try: - roles = self._list_roles() - role = next(r for r in roles if r['name'] == role_name) - except StopIteration: - msg = 'No "%s" role found' % role_name - raise lib_exc.NotFound(msg) - try: - self.identity_client.assign_user_role(project['id'], user['id'], - role['id']) - except lib_exc.Conflict: - LOG.debug("Role %s already assigned on project %s for user %s" % ( - role['id'], project['id'], user['id'])) - - @abc.abstractmethod - def get_credentials(self, user, project, password): - pass - - def delete_user(self, user_id): - self.identity_client.delete_user(user_id) - - def _list_roles(self): - roles = self.identity_client.list_roles() - return roles - - -class V2CredsClient(CredsClient): - - def create_project(self, name, description): - tenant = self.identity_client.create_tenant( - name=name, description=description) - return tenant - - def get_credentials(self, user, project, password): - return cred_provider.get_credentials( - identity_version='v2', - username=user['name'], user_id=user['id'], - tenant_name=project['name'], tenant_id=project['id'], - password=password) - - def delete_project(self, project_id): - self.identity_client.delete_tenant(project_id) - - -class V3CredsClient(CredsClient): - - def __init__(self, identity_client, domain_name): - super(V3CredsClient, self).__init__(identity_client) - try: - # Domain names must be unique, in any case a list is returned, - # selecting the first (and only) element - self.creds_domain = self.identity_client.list_domains( - params={'name': domain_name})[0] - except lib_exc.NotFound: - # TODO(andrea) we could probably create the domain on the fly - msg = "Configured domain %s could not be found" % domain_name - raise exceptions.InvalidConfiguration(msg) - - def create_project(self, name, description): - project = self.identity_client.create_project( - name=name, description=description, - domain_id=self.creds_domain['id']) - return project - - def get_credentials(self, user, project, password): - return cred_provider.get_credentials( - identity_version='v3', - username=user['name'], user_id=user['id'], - project_name=project['name'], project_id=project['id'], - password=password, - project_domain_name=self.creds_domain['name']) - - def delete_project(self, project_id): - self.identity_client.delete_project(project_id) - - -def get_creds_client(identity_client, project_domain_name=None): - if isinstance(identity_client, v2_identity.IdentityClientJSON): - return V2CredsClient(identity_client) - else: - return V3CredsClient(identity_client, project_domain_name) - - -class IsolatedCreds(cred_provider.CredentialProvider): - - def __init__(self, identity_version=None, name=None, password='pass', - network_resources=None): - super(IsolatedCreds, self).__init__(identity_version, name, password, - network_resources) - self.network_resources = network_resources - self.isolated_creds = {} - self.ports = [] - self.password = password - self.default_admin_creds = cred_provider.get_configured_credentials( - 'identity_admin', fill_in=True, - identity_version=self.identity_version) - self.identity_admin_client, self.network_admin_client = ( - self._get_admin_clients()) - # Domain where isolated credentials are provisioned (v3 only). - # Use that of the admin account is None is configured. - self.creds_domain_name = None - if self.identity_version == 'v3': - self.creds_domain_name = ( - CONF.auth.tenant_isolation_domain_name or - self.default_admin_creds.project_domain_name) - self.creds_client = get_creds_client( - self.identity_admin_client, self.creds_domain_name) - - def _get_admin_clients(self): - """ - Returns a tuple with instances of the following admin clients (in this - order): - identity - network - """ - os = clients.Manager(self.default_admin_creds) - if self.identity_version == 'v2': - return os.identity_client, os.network_client - else: - return os.identity_v3_client, os.network_client - - def _create_creds(self, suffix="", admin=False, roles=None): - """Create random credentials under the following schema. - - If the name contains a '.' is the full class path of something, and - we don't really care. If it isn't, it's probably a meaningful name, - so use it. - - For logging purposes, -user and -tenant are long and redundant, - don't use them. The user# will be sufficient to figure it out. - """ - if '.' in self.name: - root = "" - else: - root = self.name - - project_name = data_utils.rand_name(root) + suffix - project_desc = project_name + "-desc" - project = self.creds_client.create_project( - name=project_name, description=project_desc) - - username = data_utils.rand_name(root) + suffix - email = data_utils.rand_name(root) + suffix + "@example.com" - user = self.creds_client.create_user( - username, self.password, project, email) - if admin: - self.creds_client.assign_user_role(user, project, - CONF.identity.admin_role) - # Add roles specified in config file - for conf_role in CONF.auth.tempest_roles: - self.creds_client.assign_user_role(user, project, conf_role) - # Add roles requested by caller - if roles: - for role in roles: - self.creds_client.assign_user_role(user, project, role) - creds = self.creds_client.get_credentials(user, project, self.password) - return cred_provider.TestResources(creds) - - def _create_network_resources(self, tenant_id): - network = None - subnet = None - router = None - # Make sure settings - if self.network_resources: - if self.network_resources['router']: - if (not self.network_resources['subnet'] or - not self.network_resources['network']): - raise exceptions.InvalidConfiguration( - 'A router requires a subnet and network') - elif self.network_resources['subnet']: - if not self.network_resources['network']: - raise exceptions.InvalidConfiguration( - 'A subnet requires a network') - elif self.network_resources['dhcp']: - raise exceptions.InvalidConfiguration('DHCP requires a subnet') - - data_utils.rand_name_root = data_utils.rand_name(self.name) - if not self.network_resources or self.network_resources['network']: - network_name = data_utils.rand_name_root + "-network" - network = self._create_network(network_name, tenant_id) - try: - if not self.network_resources or self.network_resources['subnet']: - subnet_name = data_utils.rand_name_root + "-subnet" - subnet = self._create_subnet(subnet_name, tenant_id, - network['id']) - if not self.network_resources or self.network_resources['router']: - router_name = data_utils.rand_name_root + "-router" - router = self._create_router(router_name, tenant_id) - self._add_router_interface(router['id'], subnet['id']) - except Exception: - if router: - self._clear_isolated_router(router['id'], router['name']) - if subnet: - self._clear_isolated_subnet(subnet['id'], subnet['name']) - if network: - self._clear_isolated_network(network['id'], network['name']) - raise - return network, subnet, router - - def _create_network(self, name, tenant_id): - resp_body = self.network_admin_client.create_network( - name=name, tenant_id=tenant_id) - return resp_body['network'] - - def _create_subnet(self, subnet_name, tenant_id, network_id): - base_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr) - mask_bits = CONF.network.tenant_network_mask_bits - for subnet_cidr in base_cidr.subnet(mask_bits): - try: - if self.network_resources: - resp_body = self.network_admin_client.\ - create_subnet( - network_id=network_id, cidr=str(subnet_cidr), - name=subnet_name, - tenant_id=tenant_id, - enable_dhcp=self.network_resources['dhcp'], - ip_version=4) - else: - resp_body = self.network_admin_client.\ - create_subnet(network_id=network_id, - cidr=str(subnet_cidr), - name=subnet_name, - tenant_id=tenant_id, - ip_version=4) - break - except lib_exc.BadRequest as e: - if 'overlaps with another subnet' not in str(e): - raise - else: - message = 'Available CIDR for subnet creation could not be found' - raise Exception(message) - return resp_body['subnet'] - - def _create_router(self, router_name, tenant_id): - external_net_id = dict( - network_id=CONF.network.public_network_id) - resp_body = self.network_admin_client.create_router( - router_name, - external_gateway_info=external_net_id, - tenant_id=tenant_id) - return resp_body['router'] - - def _add_router_interface(self, router_id, subnet_id): - self.network_admin_client.add_router_interface_with_subnet_id( - router_id, subnet_id) - - def get_credentials(self, credential_type): - if self.isolated_creds.get(str(credential_type)): - credentials = self.isolated_creds[str(credential_type)] - else: - if credential_type in ['primary', 'alt', 'admin']: - is_admin = (credential_type == 'admin') - credentials = self._create_creds(admin=is_admin) - else: - credentials = self._create_creds(roles=credential_type) - self.isolated_creds[str(credential_type)] = credentials - # Maintained until tests are ported - LOG.info("Acquired isolated creds:\n credentials: %s" - % credentials) - if (CONF.service_available.neutron and - not CONF.baremetal.driver_enabled): - network, subnet, router = self._create_network_resources( - credentials.tenant_id) - credentials.set_resources(network=network, subnet=subnet, - router=router) - LOG.info("Created isolated network resources for : \n" - + " credentials: %s" % credentials) - return credentials - - def get_primary_creds(self): - return self.get_credentials('primary') - - def get_admin_creds(self): - return self.get_credentials('admin') - - def get_alt_creds(self): - return self.get_credentials('alt') - - def get_creds_by_roles(self, roles, force_new=False): - roles = list(set(roles)) - # The roles list as a str will become the index as the dict key for - # the created credentials set in the isolated_creds dict. - exist_creds = self.isolated_creds.get(str(roles)) - # If force_new flag is True 2 cred sets with the same roles are needed - # handle this by creating a separate index for old one to store it - # separately for cleanup - if exist_creds and force_new: - new_index = str(roles) + '-' + str(len(self.isolated_creds)) - self.isolated_creds[new_index] = exist_creds - del self.isolated_creds[str(roles)] - return self.get_credentials(roles) - - def _clear_isolated_router(self, router_id, router_name): - net_client = self.network_admin_client - try: - net_client.delete_router(router_id) - except lib_exc.NotFound: - LOG.warning('router with name: %s not found for delete' % - router_name) - - def _clear_isolated_subnet(self, subnet_id, subnet_name): - net_client = self.network_admin_client - try: - net_client.delete_subnet(subnet_id) - except lib_exc.NotFound: - LOG.warning('subnet with name: %s not found for delete' % - subnet_name) - - def _clear_isolated_network(self, network_id, network_name): - net_client = self.network_admin_client - try: - net_client.delete_network(network_id) - except lib_exc.NotFound: - LOG.warning('network with name: %s not found for delete' % - network_name) - - def _cleanup_default_secgroup(self, tenant): - net_client = self.network_admin_client - resp_body = net_client.list_security_groups(tenant_id=tenant, - name="default") - secgroups_to_delete = resp_body['security_groups'] - for secgroup in secgroups_to_delete: - try: - net_client.delete_security_group(secgroup['id']) - except lib_exc.NotFound: - LOG.warning('Security group %s, id %s not found for clean-up' % - (secgroup['name'], secgroup['id'])) - - def _clear_isolated_net_resources(self): - net_client = self.network_admin_client - for cred in self.isolated_creds: - creds = self.isolated_creds.get(cred) - if (not creds or not any([creds.router, creds.network, - creds.subnet])): - continue - LOG.debug("Clearing network: %(network)s, " - "subnet: %(subnet)s, router: %(router)s", - {'network': creds.network, 'subnet': creds.subnet, - 'router': creds.router}) - if (not self.network_resources or - (self.network_resources.get('router') and creds.subnet)): - try: - net_client.remove_router_interface_with_subnet_id( - creds.router['id'], creds.subnet['id']) - except lib_exc.NotFound: - LOG.warning('router with name: %s not found for delete' % - creds.router['name']) - self._clear_isolated_router(creds.router['id'], - creds.router['name']) - if (not self.network_resources or - self.network_resources.get('subnet')): - self._clear_isolated_subnet(creds.subnet['id'], - creds.subnet['name']) - if (not self.network_resources or - self.network_resources.get('network')): - self._clear_isolated_network(creds.network['id'], - creds.network['name']) - - def clear_isolated_creds(self): - if not self.isolated_creds: - return - self._clear_isolated_net_resources() - for creds in self.isolated_creds.itervalues(): - try: - self.creds_client.delete_user(creds.user_id) - except lib_exc.NotFound: - LOG.warning("user with name: %s not found for delete" % - creds.username) - try: - if CONF.service_available.neutron: - self._cleanup_default_secgroup(creds.tenant_id) - self.creds_client.delete_project(creds.tenant_id) - except lib_exc.NotFound: - LOG.warning("tenant with name: %s not found for delete" % - creds.tenant_name) - self.isolated_creds = {} - - def is_multi_user(self): - return True - - def is_multi_tenant(self): - return True - - def is_role_available(self, role): - return True diff --git a/test/tempest/tempest/common/negative_rest_client.py b/test/tempest/tempest/common/negative_rest_client.py deleted file mode 100644 index abd8b31e..00000000 --- a/test/tempest/tempest/common/negative_rest_client.py +++ /dev/null @@ -1,85 +0,0 @@ -# (c) 2014 Deutsche Telekom AG -# Copyright 2014 Red Hat, Inc. -# Copyright 2014 NEC 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.common import service_client -from tempest import config - -CONF = config.CONF - - -class NegativeRestClient(service_client.ServiceClient): - """ - Version of RestClient that does not raise exceptions. - """ - def __init__(self, auth_provider, service, - build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - region, endpoint_type = self._get_region_and_endpoint_type(service) - super(NegativeRestClient, self).__init__( - auth_provider, - service, - region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=( - disable_ssl_certificate_validation), - ca_certs=ca_certs, - trace_requests=trace_requests) - - def _get_region_and_endpoint_type(self, service): - """ - Returns the region for a specific service - """ - service_region = None - service_endpoint_type = None - for cfgname in dir(CONF._config): - # Find all config.FOO.catalog_type and assume FOO is a service. - cfg = getattr(CONF, cfgname) - catalog_type = getattr(cfg, 'catalog_type', None) - if catalog_type == service: - service_region = getattr(cfg, 'region', None) - service_endpoint_type = getattr(cfg, 'endpoint_type', None) - if not service_region: - service_region = CONF.identity.region - return service_region, service_endpoint_type - - def _error_checker(self, method, url, - headers, body, resp, resp_body): - pass - - def send_request(self, method, url_template, resources, body=None): - url = url_template % tuple(resources) - if method == "GET": - resp, body = self.get(url) - elif method == "POST": - resp, body = self.post(url, body) - elif method == "PUT": - resp, body = self.put(url, body) - elif method == "PATCH": - resp, body = self.patch(url, body) - elif method == "HEAD": - resp, body = self.head(url) - elif method == "DELETE": - resp, body = self.delete(url) - elif method == "COPY": - resp, body = self.copy(url) - else: - assert False - - return resp, body diff --git a/test/tempest/tempest/common/service_client.py b/test/tempest/tempest/common/service_client.py deleted file mode 100644 index 87e925db..00000000 --- a/test/tempest/tempest/common/service_client.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2015 NEC 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.common import rest_client - - -class ServiceClient(rest_client.RestClient): - - def __init__(self, auth_provider, service, region, - endpoint_type=None, build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, ca_certs=None, - trace_requests=None): - - dscv = disable_ssl_certificate_validation - params = { - 'disable_ssl_certificate_validation': dscv, - 'ca_certs': ca_certs, - 'trace_requests': trace_requests - } - - if endpoint_type is not None: - params.update({'endpoint_type': endpoint_type}) - if build_interval is not None: - params.update({'build_interval': build_interval}) - if build_timeout is not None: - params.update({'build_timeout': build_timeout}) - super(ServiceClient, self).__init__(auth_provider, service, region, - **params) - - -class ResponseBody(dict): - """Class that wraps an http response and dict body into a single value. - - Callers that receive this object will normally use it as a dict but - can extract the response if needed. - """ - - def __init__(self, response, body=None): - body_data = body or {} - self.update(body_data) - self.response = response - - def __str__(self): - body = super(ResponseBody, self).__str__() - return "response: %s\nBody: %s" % (self.response, body) - - -class ResponseBodyData(object): - """Class that wraps an http response and string data into a single value. - """ - - def __init__(self, response, data): - self.response = response - self.data = data - - def __str__(self): - return "response: %s\nBody: %s" % (self.response, self.data) - - -class ResponseBodyList(list): - """Class that wraps an http response and list body into a single value. - - Callers that receive this object will normally use it as a list but - can extract the response if needed. - """ - - def __init__(self, response, body=None): - body_data = body or [] - self.extend(body_data) - self.response = response - - def __str__(self): - body = super(ResponseBodyList, self).__str__() - return "response: %s\nBody: %s" % (self.response, body) diff --git a/test/tempest/tempest/common/ssh.py b/test/tempest/tempest/common/ssh.py deleted file mode 100644 index d0e484cd..00000000 --- a/test/tempest/tempest/common/ssh.py +++ /dev/null @@ -1,151 +0,0 @@ -# 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 select -import socket -import time -import warnings - -from oslo_log import log as logging -import six -from six import moves - -from tempest import exceptions - - -with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import paramiko - - -LOG = logging.getLogger(__name__) - - -class Client(object): - - def __init__(self, host, username, password=None, timeout=300, pkey=None, - channel_timeout=10, look_for_keys=False, key_filename=None): - self.host = host - self.username = username - self.password = password - if isinstance(pkey, six.string_types): - pkey = paramiko.RSAKey.from_private_key( - moves.cStringIO(str(pkey))) - self.pkey = pkey - self.look_for_keys = look_for_keys - self.key_filename = key_filename - self.timeout = int(timeout) - self.channel_timeout = float(channel_timeout) - self.buf_size = 1024 - - def _get_ssh_connection(self, sleep=1.5, backoff=1): - """Returns an ssh connection to the specified host.""" - bsleep = sleep - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy( - paramiko.AutoAddPolicy()) - _start_time = time.time() - if self.pkey is not None: - LOG.info("Creating ssh connection to '%s' as '%s'" - " with public key authentication", - self.host, self.username) - else: - LOG.info("Creating ssh connection to '%s' as '%s'" - " with password %s", - self.host, self.username, str(self.password)) - attempts = 0 - while True: - try: - ssh.connect(self.host, username=self.username, - password=self.password, - look_for_keys=self.look_for_keys, - key_filename=self.key_filename, - timeout=self.channel_timeout, pkey=self.pkey) - LOG.info("ssh connection to %s@%s successfuly created", - self.username, self.host) - return ssh - except (socket.error, - paramiko.SSHException) as e: - if self._is_timed_out(_start_time): - LOG.exception("Failed to establish authenticated ssh" - " connection to %s@%s after %d attempts", - self.username, self.host, attempts) - raise exceptions.SSHTimeout(host=self.host, - user=self.username, - password=self.password) - bsleep += backoff - attempts += 1 - LOG.warning("Failed to establish authenticated ssh" - " connection to %s@%s (%s). Number attempts: %s." - " Retry after %d seconds.", - self.username, self.host, e, attempts, bsleep) - time.sleep(bsleep) - - def _is_timed_out(self, start_time): - return (time.time() - self.timeout) > start_time - - def exec_command(self, cmd): - """ - Execute the specified command on the server. - - Note that this method is reading whole command outputs to memory, thus - shouldn't be used for large outputs. - - :returns: data read from standard output of the command. - :raises: SSHExecCommandFailed if command returns nonzero - status. The exception contains command status stderr content. - """ - ssh = self._get_ssh_connection() - transport = ssh.get_transport() - channel = transport.open_session() - channel.fileno() # Register event pipe - channel.exec_command(cmd) - channel.shutdown_write() - out_data = [] - err_data = [] - poll = select.poll() - poll.register(channel, select.POLLIN) - start_time = time.time() - - while True: - ready = poll.poll(self.channel_timeout) - if not any(ready): - if not self._is_timed_out(start_time): - continue - raise exceptions.TimeoutException( - "Command: '{0}' executed on host '{1}'.".format( - cmd, self.host)) - if not ready[0]: # If there is nothing to read. - continue - out_chunk = err_chunk = None - if channel.recv_ready(): - out_chunk = channel.recv(self.buf_size) - out_data += out_chunk, - if channel.recv_stderr_ready(): - err_chunk = channel.recv_stderr(self.buf_size) - err_data += err_chunk, - if channel.closed and not err_chunk and not out_chunk: - break - exit_status = channel.recv_exit_status() - if 0 != exit_status: - raise exceptions.SSHExecCommandFailed( - command=cmd, exit_status=exit_status, - strerror=''.join(err_data)) - return ''.join(out_data) - - def test_connection_auth(self): - """Raises an exception when we can not connect to server via ssh.""" - connection = self._get_ssh_connection() - connection.close() diff --git a/test/tempest/tempest/common/tempest_fixtures.py b/test/tempest/tempest/common/tempest_fixtures.py deleted file mode 100644 index d416857a..00000000 --- a/test/tempest/tempest/common/tempest_fixtures.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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_concurrency.fixture import lockutils - - -class LockFixture(lockutils.LockFixture): - def __init__(self, name): - super(LockFixture, self).__init__(name, 'tempest-') diff --git a/test/tempest/tempest/common/utils/__init__.py b/test/tempest/tempest/common/utils/__init__.py deleted file mode 100644 index 04d898df..00000000 --- a/test/tempest/tempest/common/utils/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -PING_IPV4_COMMAND = 'ping -c 3 ' -PING_IPV6_COMMAND = 'ping6 -c 3 ' -PING_PACKET_LOSS_REGEX = '(\d{1,3})\.?\d*\% packet loss' diff --git a/test/tempest/tempest/common/utils/file_utils.py b/test/tempest/tempest/common/utils/file_utils.py deleted file mode 100644 index 43083f46..00000000 --- a/test/tempest/tempest/common/utils/file_utils.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - - -def have_effective_read_access(path): - try: - fh = open(path, "rb") - except IOError: - return False - fh.close() - return True diff --git a/test/tempest/tempest/common/utils/linux/__init__.py b/test/tempest/tempest/common/utils/linux/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/common/utils/linux/remote_client.py b/test/tempest/tempest/common/utils/linux/remote_client.py deleted file mode 100644 index 30a2132a..00000000 --- a/test/tempest/tempest/common/utils/linux/remote_client.py +++ /dev/null @@ -1,179 +0,0 @@ -# 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 re -import time - -import six - -from tempest.common import ssh -from tempest import config -from tempest import exceptions - -CONF = config.CONF - - -class RemoteClient(object): - - # NOTE(afazekas): It should always get an address instead of server - def __init__(self, server, username, password=None, pkey=None): - # zfl: use server's generated adminpass can't ssh,so - # if password is a generated one, - # use CONF.compute.image_ssh_password instead; - # if password is specified by use, just use it - if password is not None and password.startswith('opencos'): - self.password = password[len('opencos'):] - else: - self.password = CONF.compute.image_ssh_password - - self.ssh_timeout = CONF.compute.ssh_timeout - # network = CONF.compute.network_for_ssh - network = CONF.compute.fixed_network_name - self.ip_version = CONF.compute.ip_version_for_ssh - self.ssh_channel_timeout = CONF.compute.ssh_channel_timeout - if isinstance(server, six.string_types): - self.ip_address = server - else: - self.addresses = server['addresses'][network] - # zfl look for network backwards (first floating ip,then internal - # ip) - for address in self.addresses[::-1]: - if address['version'] == self.ip_version: - self.ip_address = address['addr'] - break - else: - raise exceptions.ServerUnreachable() - self.ssh_client = ssh.Client(self.ip_address, username, self.password, - self.ssh_timeout, pkey=pkey, - channel_timeout=self.ssh_channel_timeout) - - def exec_command(self, cmd): - return self.ssh_client.exec_command(cmd) - - def validate_authentication(self): - """Validate ssh connection and authentication - This method raises an Exception when the validation fails. - """ - self.ssh_client.test_connection_auth() - - def hostname_equals_servername(self, expected_hostname): - # Get host name using command "hostname" - actual_hostname = self.exec_command("hostname").rstrip() - return expected_hostname == actual_hostname - - def get_ram_size_in_mb(self): - output = self.exec_command('free -m | grep Mem') - if output: - return output.split()[1] - - def get_number_of_vcpus(self): - command = 'cat /proc/cpuinfo | grep processor | wc -l' - output = self.exec_command(command) - return int(output) - - def get_partitions(self): - # Return the contents of /proc/partitions - command = 'cat /proc/partitions' - output = self.exec_command(command) - return output - - def get_boot_time(self): - cmd = 'cut -f1 -d. /proc/uptime' - boot_secs = self.exec_command(cmd) - boot_time = time.time() - int(boot_secs) - return time.localtime(boot_time) - - def write_to_console(self, message): - message = re.sub("([$\\`])", "\\\\\\\\\\1", message) - # usually to /dev/ttyS0 - cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message - return self.exec_command(cmd) - - def ping_host(self, host, count=CONF.compute.ping_count, - size=CONF.compute.ping_size): - addr = netaddr.IPAddress(host) - cmd = 'ping6' if addr.version == 6 else 'ping' - cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host) - return self.exec_command(cmd) - - def get_mac_address(self): - cmd = "/bin/ip addr | awk '/ether/ {print $2}'" - return self.exec_command(cmd) - - def get_nic_name(self, address): - cmd = "/bin/ip -o addr | awk '/%s/ {print $2}'" % address - return self.exec_command(cmd) - - def get_ip_list(self): - cmd = "/bin/ip address" - return self.exec_command(cmd) - - def assign_static_ip(self, nic, addr): - cmd = "sudo /bin/ip addr add {ip}/{mask} dev {nic}".format( - ip=addr, mask=CONF.network.tenant_network_mask_bits, - nic=nic - ) - return self.exec_command(cmd) - - def turn_nic_on(self, nic): - cmd = "sudo /bin/ip link set {nic} up".format(nic=nic) - return self.exec_command(cmd) - - def get_pids(self, pr_name): - # Get pid(s) of a process/program - cmd = "ps -ef | grep %s | grep -v 'grep' | awk {'print $1'}" % pr_name - return self.exec_command(cmd).split('\n') - - def get_dns_servers(self): - cmd = 'cat /etc/resolv.conf' - resolve_file = self.exec_command(cmd).strip().split('\n') - entries = (l.split() for l in resolve_file) - dns_servers = [l[1] for l in entries - if len(l) and l[0] == 'nameserver'] - return dns_servers - - def send_signal(self, pid, signum): - cmd = 'sudo /bin/kill -{sig} {pid}'.format(pid=pid, sig=signum) - return self.exec_command(cmd) - - def _renew_lease_udhcpc(self, fixed_ip=None): - """Renews DHCP lease via udhcpc client. """ - file_path = '/var/run/udhcpc.' - nic_name = self.get_nic_name(fixed_ip) - nic_name = nic_name.strip().lower() - pid = self.exec_command('cat {path}{nic}.pid'. - format(path=file_path, nic=nic_name)) - pid = pid.strip() - self.send_signal(pid, 'USR1') - - def _renew_lease_dhclient(self, fixed_ip=None): - """Renews DHCP lease via dhclient client. """ - cmd = "sudo /sbin/dhclient -r && sudo /sbin/dhclient" - self.exec_command(cmd) - - def renew_lease(self, fixed_ip=None): - """Wrapper method for renewing DHCP lease via given client - - Supporting: - * udhcpc - * dhclient - """ - # TODO(yfried): add support for dhcpcd - suported_clients = ['udhcpc', 'dhclient'] - dhcp_client = CONF.scenario.dhcp_client - if dhcp_client not in suported_clients: - raise exceptions.InvalidConfiguration('%s DHCP client unsupported' - % dhcp_client) - if dhcp_client == 'udhcpc' and not fixed_ip: - raise ValueError("need to set 'fixed_ip' for udhcpc client") - return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip) diff --git a/test/tempest/tempest/common/waiters.py b/test/tempest/tempest/common/waiters.py deleted file mode 100644 index 64ff7f2c..00000000 --- a/test/tempest/tempest/common/waiters.py +++ /dev/null @@ -1,161 +0,0 @@ -# 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 time - -from oslo_log import log as logging -from tempest_lib.common.utils import misc as misc_utils - -from tempest import config -from tempest import exceptions - -CONF = config.CONF -LOG = logging.getLogger(__name__) - - -# NOTE(afazekas): This function needs to know a token and a subject. -def wait_for_server_status(client, server_id, status, ready_wait=True, - extra_timeout=0, raise_on_error=True): - """Waits for a server to reach a given status.""" - - def _get_task_state(body): - return body.get('OS-EXT-STS:task_state', None) - - # NOTE(afazekas): UNKNOWN status possible on ERROR - # or in a very early stage. - body = client.get_server(server_id) - old_status = server_status = body['status'] - old_task_state = task_state = _get_task_state(body) - start_time = int(time.time()) - timeout = client.build_timeout + extra_timeout - while True: - # NOTE(afazekas): Now the BUILD status only reached - # between the UNKNOWN->ACTIVE transition. - # TODO(afazekas): enumerate and validate the stable status set - if status == 'BUILD' and server_status != 'UNKNOWN': - return - if server_status == status: - if ready_wait: - if status == 'BUILD': - return - # NOTE(afazekas): The instance is in "ready for action state" - # when no task in progress - # NOTE(afazekas): Converted to string bacuse of the XML - # responses - if str(task_state) == "None": - # without state api extension 3 sec usually enough - time.sleep(CONF.compute.ready_wait) - return - else: - return - - time.sleep(client.build_interval) - body = client.get_server(server_id) - server_status = body['status'] - task_state = _get_task_state(body) - if (server_status != old_status) or (task_state != old_task_state): - LOG.info('State transition "%s" ==> "%s" after %d second wait', - '/'.join((old_status, str(old_task_state))), - '/'.join((server_status, str(task_state))), - time.time() - start_time) - if (server_status == 'ERROR') and raise_on_error: - if 'fault' in body: - raise exceptions.BuildErrorException(body['fault'], - server_id=server_id) - else: - raise exceptions.BuildErrorException(server_id=server_id) - - timed_out = int(time.time()) - start_time >= timeout - - if timed_out: - expected_task_state = 'None' if ready_wait else 'n/a' - message = ('Server %(server_id)s failed to reach %(status)s ' - 'status and task state "%(expected_task_state)s" ' - 'within the required time (%(timeout)s s).' % - {'server_id': server_id, - 'status': status, - 'expected_task_state': expected_task_state, - 'timeout': timeout}) - message += ' Current status: %s.' % server_status - message += ' Current task state: %s.' % task_state - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - old_status = server_status - old_task_state = task_state - - -def wait_for_image_status(client, image_id, status): - """Waits for an image to reach a given status. - - The client should have a get_image(image_id) method to get the image. - The client should also have build_interval and build_timeout attributes. - """ - image = client.get_image(image_id) - start = int(time.time()) - - while image['status'] != status: - time.sleep(client.build_interval) - image = client.get_image(image_id) - status_curr = image['status'] - if status_curr == 'ERROR': - raise exceptions.AddImageException(image_id=image_id) - - # check the status again to avoid a false negative where we hit - # the timeout at the same time that the image reached the expected - # status - if status_curr == status: - return - - if int(time.time()) - start >= client.build_timeout: - message = ('Image %(image_id)s failed to reach %(status)s state' - '(current state %(status_curr)s) ' - 'within the required time (%(timeout)s s).' % - {'image_id': image_id, - 'status': status, - 'status_curr': status_curr, - 'timeout': client.build_timeout}) - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - - -def wait_for_bm_node_status(client, node_id, attr, status): - """Waits for a baremetal node attribute to reach given status. - - The client should have a show_node(node_uuid) method to get the node. - """ - _, node = client.show_node(node_id) - start = int(time.time()) - - while node[attr] != status: - time.sleep(client.build_interval) - _, node = client.show_node(node_id) - status_curr = node[attr] - if status_curr == status: - return - - if int(time.time()) - start >= client.build_timeout: - message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s ' - 'within the required time (%(timeout)s s).' % - {'node_id': node_id, - 'attr': attr, - 'status': status, - 'timeout': client.build_timeout}) - message += ' Current state of %s: %s.' % (attr, status_curr) - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) diff --git a/test/tempest/tempest/config.py b/test/tempest/tempest/config.py deleted file mode 100755 index 469a96f7..00000000 --- a/test/tempest/tempest/config.py +++ /dev/null @@ -1,1436 +0,0 @@ -# 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. - -from __future__ import print_function - -import logging as std_logging -import os - -from oslo_config import cfg - -from oslo_log import log as logging - - -# TODO(marun) Replace use of oslo_config's global ConfigOpts -# (cfg.CONF) instance with a local instance (cfg.ConfigOpts()) once -# the cli tests move to the clients. The cli tests rely on oslo -# incubator modules that use the global cfg.CONF. -_CONF = cfg.CONF - - -def register_opt_group(conf, opt_group, options): - conf.register_group(opt_group) - for opt in options: - conf.register_opt(opt, group=opt_group.name) - - -auth_group = cfg.OptGroup(name='auth', - title="Options for authentication and credentials") - - -AuthGroup = [ - cfg.StrOpt('test_accounts_file', - help="Path to the yaml file that contains the list of " - "credentials to use for running tests. If used when " - "running in parallel you have to make sure sufficient " - "credentials are provided in the accounts file. For " - "example if no tests with roles are being run it requires " - "at least `2 * CONC` distinct accounts configured in " - " the `test_accounts_file`, with CONC == the " - "number of concurrent test processes."), - cfg.BoolOpt('allow_tenant_isolation', - default=False, - help="Allows test cases to create/destroy tenants and " - "users. This option requires that OpenStack Identity " - "API admin credentials are known. If false, isolated " - "test cases and parallel execution, can still be " - "achieved configuring a list of test accounts", - deprecated_opts=[cfg.DeprecatedOpt('allow_tenant_isolation', - group='compute'), - cfg.DeprecatedOpt('allow_tenant_isolation', - group='orchestration')]), - cfg.ListOpt('tempest_roles', - help="Roles to assign to all users created by tempest", - default=[]), - cfg.StrOpt('tenant_isolation_domain_name', - default=None, - help="Only applicable when identity.auth_version is v3." - "Domain within which isolated credentials are provisioned." - "The default \"None\" means that the domain from the" - "admin user is used instead.") -] - -identity_group = cfg.OptGroup(name='identity', - title="Keystone Configuration Options") - -IdentityGroup = [ - cfg.StrOpt('catalog_type', - default='identity', - help="Catalog type of the Identity service."), - cfg.BoolOpt('disable_ssl_certificate_validation', - default=False, - help="Set to True if using self-signed SSL certificates."), - cfg.StrOpt('ca_certificates_file', - default=None, - help='Specify a CA bundle file to use in verifying a ' - 'TLS (https) server certificate.'), - cfg.StrOpt('uri', - help="Full URI of the OpenStack Identity API (Keystone), v2"), - cfg.StrOpt('uri_v3', - help='Full URI of the OpenStack Identity API (Keystone), v3'), - cfg.StrOpt('auth_version', - default='v2', - help="Identity API version to be used for authentication " - "for API tests."), - cfg.StrOpt('region', - default='RegionOne', - help="The identity region name to use. Also used as the other " - "services' region name unless they are set explicitly. " - "If no such region is found in the service catalog, the " - "first found one is used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the identity service."), - cfg.StrOpt('username', - help="Username to use for Nova API requests."), - cfg.StrOpt('tenant_name', - help="Tenant name to use for Nova API requests."), - cfg.StrOpt('admin_role', - default='admin', - help="Role required to administrate keystone."), - cfg.StrOpt('password', - help="API key to use when authenticating.", - secret=True), - cfg.StrOpt('domain_name', - help="Domain name for authentication (Keystone V3)." - "The same domain applies to user and project"), - cfg.StrOpt('alt_username', - help="Username of alternate user to use for Nova API " - "requests."), - cfg.StrOpt('alt_tenant_name', - help="Alternate user's Tenant name to use for Nova API " - "requests."), - cfg.StrOpt('alt_password', - help="API key to use when authenticating as alternate user.", - secret=True), - cfg.StrOpt('alt_domain_name', - help="Alternate domain name for authentication (Keystone V3)." - "The same domain applies to user and project"), - cfg.StrOpt('admin_username', - help="Administrative Username to use for " - "Keystone API requests."), - cfg.StrOpt('admin_tenant_name', - help="Administrative Tenant name to use for Keystone API " - "requests."), - cfg.StrOpt('admin_password', - help="API key to use when authenticating as admin.", - secret=True), - cfg.StrOpt('admin_domain_name', - help="Admin domain name for authentication (Keystone V3)." - "The same domain applies to user and project"), -] - -identity_feature_group = cfg.OptGroup(name='identity-feature-enabled', - title='Enabled Identity Features') - -IdentityFeatureGroup = [ - cfg.BoolOpt('trust', - default=True, - help='Does the identity service have delegation and ' - 'impersonation enabled'), - cfg.BoolOpt('api_v2', - default=True, - help='Is the v2 identity API enabled'), - cfg.BoolOpt('api_v3', - default=True, - help='Is the v3 identity API enabled'), -] - -compute_group = cfg.OptGroup(name='compute', - title='Compute Service Options') - -ComputeGroup = [ - cfg.StrOpt('image_ref', - help="Valid primary image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ref_alt', - help="Valid secondary image reference to be used in tests. " - "This is a required option, but if only one image is " - "available duplicate the value of image_ref above"), - cfg.StrOpt('image_ref_xp', - help="Valid XP image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ssh_xp_user', - default="administrator", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ssh_xp_pwd', - default="null", - help="Password used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ref_vmb', - help="Valid VMB image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ssh_vmb_user', - default="zte", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ssh_vmb_pwd', - default="zte", - help="Password used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ref_linux', - help="Valid Linux-CGSLV5 image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ssh_linux_user', - default="root", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ssh_linux_pwd', - default="ossdbg1", - help="Password used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ref_suse', - help="Valid SUSE image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ssh_suse_user', - default="root", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ssh_suse_pwd', - default="it@123456", - help="Password used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ref_centos7', - help="Valid CENTOS7 image reference to be used in tests. " - "This is a required option"), - cfg.StrOpt('image_ssh_centos7_user', - default="root", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.StrOpt('image_ssh_centos7_pwd', - default="ossdbg1", - help="Password used to authenticate to an instance using " - "the alternate image."), - cfg.BoolOpt('use_sdn', - default=False, - help="whether use SDN."), - cfg.StrOpt('flavor_ref', - default="1", - help="Valid primary flavor to use in tests."), - cfg.StrOpt('flavor_ref_alt', - default="2", - help='Valid secondary flavor to be used in tests.'), - cfg.StrOpt('image_ssh_user', - default="root", - help="User name used to authenticate to an instance."), - cfg.StrOpt('image_ssh_password', - default="password", - help="Password used to authenticate to an instance."), - cfg.StrOpt('image_alt_ssh_user', - default="root", - help="User name used to authenticate to an instance using " - "the alternate image."), - cfg.IntOpt('build_interval', - default=1, - help="Time in seconds between build status checks."), - cfg.IntOpt('build_timeout', - default=300, - help="Timeout in seconds to wait for an instance to build. " - "Other services that do not define build_timeout will " - "inherit this value."), - cfg.BoolOpt('run_ssh', - default=False, - help="Should the tests ssh to instances?"), - cfg.StrOpt('ssh_auth_method', - default='keypair', - help="Auth method used for authenticate to the instance. " - "Valid choices are: keypair, configured, adminpass " - "and disabled. " - "Keypair: start the servers with a ssh keypair. " - "Configured: use the configured user and password. " - "Adminpass: use the injected adminPass. " - "Disabled: avoid using ssh when it is an option."), - cfg.StrOpt('ssh_connect_method', - default='floating', - help="How to connect to the instance? " - "fixed: using the first ip belongs the fixed network " - "floating: creating and using a floating ip."), - cfg.StrOpt('ssh_user', - default='root', - help="User name used to authenticate to an instance."), - cfg.IntOpt('ping_timeout', - default=120, - help="Timeout in seconds to wait for ping to " - "succeed."), - cfg.IntOpt('ping_size', - default=56, - help="The packet size for ping packets originating " - "from remote linux hosts"), - cfg.IntOpt('ping_count', - default=1, - help="The number of ping packets originating from remote " - "linux hosts"), - cfg.IntOpt('ssh_timeout', - default=300, - help="Timeout in seconds to wait for authentication to " - "succeed."), - cfg.IntOpt('ready_wait', - default=0, - help="Additional wait time for clean state, when there is " - "no OS-EXT-STS extension available"), - cfg.IntOpt('ssh_channel_timeout', - default=60, - help="Timeout in seconds to wait for output from ssh " - "channel."), - cfg.StrOpt('fixed_network_name', - help="Name of the fixed network that is visible to all test " - "tenants. If multiple networks are available for a tenant" - " this is the network which will be used for creating " - "servers if tempest does not create a network or a " - "network is not specified elsewhere. It may be used for " - "ssh validation only if floating IPs are disabled."), - cfg.StrOpt('fixed_network_name_external', - default='private', - help="Visible fixed network name external "), - cfg.StrOpt('multi_create_flavor_id', - default='3', - help="Valid flavor reference to be used in multiple create " - "servers. This is a required option"), - cfg.IntOpt('multi_create_max_count', - default=5, - help="Max count of multiple creating servers."), - cfg.StrOpt('v4_image_file', - default='', - help="V4 image file where stored."), - cfg.StrOpt('network_for_ssh', - default='public', - help="Network used for SSH connections. Ignored if " - "use_floatingip_for_ssh=true or run_ssh=false."), - cfg.IntOpt('ip_version_for_ssh', - default=4, - help="IP version used for SSH connections."), - cfg.BoolOpt('use_floatingip_for_ssh', - default=True, - help="Does SSH use Floating IPs?"), - cfg.StrOpt('catalog_type', - default='compute', - help="Catalog type of the Compute service."), - cfg.StrOpt('region', - default='', - help="The compute region name to use. If empty, the value " - "of identity.region is used instead. If no such region " - "is found in the service catalog, the first found one is " - "used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the compute service."), - cfg.StrOpt('volume_device_name', - default='vdb', - help="Expected device name when a volume is attached to " - "an instance"), - cfg.IntOpt('shelved_offload_time', - default=0, - help='Time in seconds before a shelved instance is eligible ' - 'for removing from a host. -1 never offload, 0 offload ' - 'when shelved. This time should be the same as the time ' - 'of nova.conf, and some tests will run for as long as the ' - 'time.'), - cfg.StrOpt('floating_ip_range', - default='10.0.0.0/29', - help='Unallocated floating IP range, which will be used to ' - 'test the floating IP bulk feature for CRUD operation. ' - 'This block must not overlap an existing floating IP ' - 'pool.') -] - -compute_features_group = cfg.OptGroup(name='compute-feature-enabled', - title="Enabled Compute Service Features") - -ComputeFeaturesGroup = [ - cfg.BoolOpt('disk_config', - default=True, - help="If false, skip disk config tests"), - cfg.ListOpt('api_extensions', - default=['all'], - help='A list of enabled compute extensions with a special ' - 'entry all which indicates every extension is enabled. ' - 'Each extension should be specified with alias name. ' - 'Empty list indicates all extensions are disabled'), - cfg.BoolOpt('change_password', - default=False, - help="Does the test environment support changing the admin " - "password?"), - cfg.BoolOpt('console_output', - default=True, - help="Does the test environment support obtaining instance " - "serial console output?"), - cfg.BoolOpt('resize', - default=False, - help="Does the test environment support resizing?"), - cfg.BoolOpt('pause', - default=True, - help="Does the test environment support pausing?"), - cfg.BoolOpt('shelve', - default=True, - help="Does the test environment support shelving/unshelving?"), - cfg.BoolOpt('suspend', - default=True, - help="Does the test environment support suspend/resume?"), - cfg.BoolOpt('live_migration', - default=True, - help="Does the test environment support live migration " - "available?"), - cfg.BoolOpt('block_migration_for_live_migration', - default=True, - help="Does the test environment use block devices for live " - "migration"), - cfg.BoolOpt('block_migrate_cinder_iscsi', - default=False, - help="Does the test environment block migration support " - "cinder iSCSI volumes. Note, libvirt doesn't support this, " - "see https://bugs.launchpad.net/nova/+bug/1398999"), - cfg.BoolOpt('vnc_console', - default=False, - help='Enable VNC console. This configuration value should ' - 'be same as [nova.vnc]->vnc_enabled in nova.conf'), - cfg.BoolOpt('spice_console', - default=False, - help='Enable Spice console. This configuration value should ' - 'be same as [nova.spice]->enabled in nova.conf'), - cfg.BoolOpt('rdp_console', - default=False, - help='Enable RDP console. This configuration value should ' - 'be same as [nova.rdp]->enabled in nova.conf'), - cfg.BoolOpt('rescue', - default=True, - help='Does the test environment support instance rescue ' - 'mode?'), - cfg.BoolOpt('enable_instance_password', - default=True, - help='Enables returning of the instance password by the ' - 'relevant server API calls such as create, rebuild ' - 'or rescue.'), - cfg.BoolOpt('interface_attach', - default=False, - help='Does the test environment support dynamic network ' - 'interface attachment?'), - cfg.BoolOpt('snapshot', - default=True, - help='Does the test environment support creating snapshot ' - 'images of running instances?'), - cfg.BoolOpt('ec2_api', - default=True, - help='Does the test environment have the ec2 api running?'), - # TODO(mriedem): Remove preserve_ports once juno-eol happens. - cfg.BoolOpt('preserve_ports', - default=False, - help='Does Nova preserve preexisting ports from Neutron ' - 'when deleting an instance? This should be set to True ' - 'if testing Kilo+ Nova.') -] - - -image_group = cfg.OptGroup(name='image', - title="Image Service Options") - -ImageGroup = [ - cfg.StrOpt('catalog_type', - default='image', - help='Catalog type of the Image service.'), - cfg.StrOpt('region', - default='', - help="The image region name to use. If empty, the value " - "of identity.region is used instead. If no such region " - "is found in the service catalog, the first found one is " - "used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the image service."), - cfg.StrOpt('http_image', - default='http://download.cirros-cloud.net/0.3.1/' - 'cirros-0.3.1-x86_64-uec.tar.gz', - help='http accessible image'), - cfg.IntOpt('build_timeout', - default=300, - help="Timeout in seconds to wait for an image to " - "become available."), - cfg.IntOpt('build_interval', - default=1, - help="Time in seconds between image operation status " - "checks.") -] - -image_feature_group = cfg.OptGroup(name='image-feature-enabled', - title='Enabled image service features') - -ImageFeaturesGroup = [ - cfg.BoolOpt('api_v2', - default=True, - help="Is the v2 image API enabled"), - cfg.BoolOpt('api_v1', - default=True, - help="Is the v1 image API enabled"), -] - -network_group = cfg.OptGroup(name='network', - title='Network Service Options') - -NetworkGroup = [ - cfg.StrOpt('internal_network_id', - default='private', - help="internal network id "), - cfg.StrOpt('catalog_type', - default='network', - help='Catalog type of the Neutron service.'), - cfg.StrOpt('region', - default='', - help="The network region name to use. If empty, the value " - "of identity.region is used instead. If no such region " - "is found in the service catalog, the first found one is " - "used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the network service."), - cfg.StrOpt('tenant_network_cidr', - default="10.100.0.0/16", - help="The cidr block to allocate tenant ipv4 subnets from"), - cfg.IntOpt('tenant_network_mask_bits', - default=28, - help="The mask bits for tenant ipv4 subnets"), - cfg.StrOpt('tenant_network_v6_cidr', - default="2003::/48", - help="The cidr block to allocate tenant ipv6 subnets from"), - cfg.IntOpt('tenant_network_v6_mask_bits', - default=64, - help="The mask bits for tenant ipv6 subnets"), - cfg.BoolOpt('tenant_networks_reachable', - default=False, - help="Whether tenant networks can be reached directly from " - "the test client. This must be set to True when the " - "'fixed' ssh_connect_method is selected."), - cfg.StrOpt('public_network_id', - default="", - help="Id of the public network that provides external " - "connectivity"), - cfg.StrOpt('floating_network_name', - help="Default floating network name. Used to allocate floating " - "IPs when neutron is enabled."), - cfg.StrOpt('public_router_id', - default="", - help="Id of the public router that provides external " - "connectivity. This should only be used when Neutron's " - "'allow_overlapping_ips' is set to 'False' in " - "neutron.conf. usually not needed past 'Grizzly' release"), - cfg.IntOpt('build_timeout', - default=300, - help="Timeout in seconds to wait for network operation to " - "complete."), - cfg.IntOpt('build_interval', - default=1, - help="Time in seconds between network operation status " - "checks."), - cfg.ListOpt('dns_servers', - default=["8.8.8.8", "8.8.4.4"], - help="List of dns servers which should be used" - " for subnet creation"), - cfg.StrOpt('port_vnic_type', - choices=[None, 'normal', 'direct', 'macvtap'], - help="vnic_type to use when Launching instances" - " with pre-configured ports." - " Supported ports are:" - " ['normal','direct','macvtap']"), -] - -network_feature_group = cfg.OptGroup(name='network-feature-enabled', - title='Enabled network service features') - -NetworkFeaturesGroup = [ - cfg.BoolOpt('ipv6', - default=True, - help="Allow the execution of IPv6 tests"), - cfg.ListOpt('api_extensions', - default=['all'], - help='A list of enabled network extensions with a special ' - 'entry all which indicates every extension is enabled. ' - 'Empty list indicates all extensions are disabled'), - cfg.BoolOpt('ipv6_subnet_attributes', - default=False, - help="Allow the execution of IPv6 subnet tests that use " - "the extended IPv6 attributes ipv6_ra_mode " - "and ipv6_address_mode" - ), - cfg.BoolOpt('port_admin_state_change', - default=True, - help="Does the test environment support changing" - " port admin state"), -] - -messaging_group = cfg.OptGroup(name='messaging', - title='Messaging Service') - -MessagingGroup = [ - cfg.StrOpt('catalog_type', - default='messaging', - help='Catalog type of the Messaging service.'), - cfg.IntOpt('max_queues_per_page', - default=20, - help='The maximum number of queue records per page when ' - 'listing queues'), - cfg.IntOpt('max_queue_metadata', - default=65536, - help='The maximum metadata size for a queue'), - cfg.IntOpt('max_messages_per_page', - default=20, - help='The maximum number of queue message per page when ' - 'listing (or) posting messages'), - cfg.IntOpt('max_message_size', - default=262144, - help='The maximum size of a message body'), - cfg.IntOpt('max_messages_per_claim', - default=20, - help='The maximum number of messages per claim'), - cfg.IntOpt('max_message_ttl', - default=1209600, - help='The maximum ttl for a message'), - cfg.IntOpt('max_claim_ttl', - default=43200, - help='The maximum ttl for a claim'), - cfg.IntOpt('max_claim_grace', - default=43200, - help='The maximum grace period for a claim'), -] - -validation_group = cfg.OptGroup(name='validation', - title='SSH Validation options') - -ValidationGroup = [ - cfg.StrOpt('connect_method', - default='floating', - choices=['fixed', 'floating'], - help='Default IP type used for validation: ' - '-fixed: uses the first IP belonging to the fixed network ' - '-floating: creates and uses a floating IP'), - cfg.StrOpt('auth_method', - default='keypair', - choices=['keypair'], - help='Default authentication method to the instance. ' - 'Only ssh via keypair is supported for now. ' - 'Additional methods will be handled in a separate spec.'), - cfg.IntOpt('ip_version_for_ssh', - default=4, - help='Default IP version for ssh connections.'), - cfg.IntOpt('ping_timeout', - default=120, - help='Timeout in seconds to wait for ping to succeed.'), - cfg.IntOpt('connect_timeout', - default=60, - help='Timeout in seconds to wait for the TCP connection to be ' - 'successful.'), - cfg.IntOpt('ssh_timeout', - default=300, - help='Timeout in seconds to wait for the ssh banner.'), -] - -volume_group = cfg.OptGroup(name='volume', - title='Block Storage Options') - -VolumeGroup = [ - cfg.IntOpt('build_interval', - default=1, - help='Time in seconds between volume availability checks.'), - cfg.IntOpt('build_timeout', - default=300, - help='Timeout in seconds to wait for a volume to become ' - 'available.'), - cfg.StrOpt('catalog_type', - default='volume', - help="Catalog type of the Volume Service"), - cfg.StrOpt('region', - default='', - help="The volume region name to use. If empty, the value " - "of identity.region is used instead. If no such region " - "is found in the service catalog, the first found one is " - "used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the volume service."), - cfg.StrOpt('backend1_name', - default='BACKEND_1', - help="Name of the backend1 (must be declared in cinder.conf)"), - cfg.StrOpt('backend2_name', - default='BACKEND_2', - help="Name of the backend2 (must be declared in cinder.conf)"), - cfg.StrOpt('storage_protocol', - default='iSCSI', - help='Backend protocol to target when creating volume types'), - cfg.StrOpt('vendor_name', - default='Open Source', - help='Backend vendor to target when creating volume types'), - cfg.StrOpt('disk_format', - default='raw', - help='Disk format to use when copying a volume to image'), - cfg.IntOpt('volume_size', - default=1, - help='Default size in GB for volumes created by volumes tests'), -] - -volume_feature_group = cfg.OptGroup(name='volume-feature-enabled', - title='Enabled Cinder Features') - -VolumeFeaturesGroup = [ - cfg.BoolOpt('multi_backend', - default=False, - help="Runs Cinder multi-backend test (requires 2 backends)"), - cfg.BoolOpt('backup', - default=False, - help='Runs Cinder volumes backup test'), - cfg.BoolOpt('snapshot', - default=False, - help='Runs Cinder volume snapshot test'), - cfg.ListOpt('api_extensions', - default=['all'], - help='A list of enabled volume extensions with a special ' - 'entry all which indicates every extension is enabled. ' - 'Empty list indicates all extensions are disabled'), - cfg.BoolOpt('api_v1', - default=True, - help="Is the v1 volume API enabled"), - cfg.BoolOpt('api_v2', - default=True, - help="Is the v2 volume API enabled"), -] - - -object_storage_group = cfg.OptGroup(name='object-storage', - title='Object Storage Service Options') - -ObjectStoreGroup = [ - cfg.StrOpt('catalog_type', - default='object-store', - help="Catalog type of the Object-Storage service."), - cfg.StrOpt('region', - default='', - help="The object-storage region name to use. If empty, the " - "value of identity.region is used instead. If no such " - "region is found in the service catalog, the first found " - "one is used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the object-store service."), - cfg.IntOpt('container_sync_timeout', - default=600, - help="Number of seconds to time on waiting for a container " - "to container synchronization complete."), - cfg.IntOpt('container_sync_interval', - default=5, - help="Number of seconds to wait while looping to check the " - "status of a container to container synchronization"), - cfg.StrOpt('operator_role', - default='Member', - help="Role to add to users created for swift tests to " - "enable creating containers"), - cfg.StrOpt('reseller_admin_role', - default='ResellerAdmin', - help="User role that has reseller admin"), - cfg.StrOpt('realm_name', - default='realm1', - help="Name of sync realm. A sync realm is a set of clusters " - "that have agreed to allow container syncing with each " - "other. Set the same realm name as Swift's " - "container-sync-realms.conf"), - cfg.StrOpt('cluster_name', - default='name1', - help="One name of cluster which is set in the realm whose name " - "is set in 'realm_name' item in this file. Set the " - "same cluster name as Swift's container-sync-realms.conf"), -] - -object_storage_feature_group = cfg.OptGroup( - name='object-storage-feature-enabled', - title='Enabled object-storage features') - -ObjectStoreFeaturesGroup = [ - cfg.ListOpt('discoverable_apis', - default=['all'], - help="A list of the enabled optional discoverable apis. " - "A single entry, all, indicates that all of these " - "features are expected to be enabled"), - cfg.BoolOpt('container_sync', - default=True, - help="Execute (old style) container-sync tests"), - cfg.BoolOpt('object_versioning', - default=True, - help="Execute object-versioning tests"), - cfg.BoolOpt('discoverability', - default=True, - help="Execute discoverability tests"), -] - -database_group = cfg.OptGroup(name='database', - title='Database Service Options') - -DatabaseGroup = [ - cfg.StrOpt('catalog_type', - default='database', - help="Catalog type of the Database service."), - cfg.StrOpt('db_flavor_ref', - default="1", - help="Valid primary flavor to use in database tests."), - cfg.StrOpt('db_current_version', - default="v1.0", - help="Current database version to use in database tests."), -] - -orchestration_group = cfg.OptGroup(name='orchestration', - title='Orchestration Service Options') - -OrchestrationGroup = [ - cfg.StrOpt('catalog_type', - default='orchestration', - help="Catalog type of the Orchestration service."), - cfg.StrOpt('region', - default='', - help="The orchestration region name to use. If empty, the " - "value of identity.region is used instead. If no such " - "region is found in the service catalog, the first found " - "one is used."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the orchestration service."), - cfg.StrOpt('stack_owner_role', default='heat_stack_owner', - help='Role required for users to be able to manage stacks'), - cfg.IntOpt('build_interval', - default=1, - help="Time in seconds between build status checks."), - cfg.IntOpt('build_timeout', - default=1200, - help="Timeout in seconds to wait for a stack to build."), - cfg.StrOpt('instance_type', - default='m1.micro', - help="Instance type for tests. Needs to be big enough for a " - "full OS plus the test workload"), - cfg.StrOpt('keypair_name', - help="Name of existing keypair to launch servers with."), - cfg.IntOpt('max_template_size', - default=524288, - help="Value must match heat configuration of the same name."), - cfg.IntOpt('max_resources_per_stack', - default=1000, - help="Value must match heat configuration of the same name."), -] - - -telemetry_group = cfg.OptGroup(name='telemetry', - title='Telemetry Service Options') - -TelemetryGroup = [ - cfg.StrOpt('catalog_type', - default='metering', - help="Catalog type of the Telemetry service."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the telemetry service."), - cfg.BoolOpt('too_slow_to_test', - default=True, - help="This variable is used as flag to enable " - "notification tests") -] - - -dashboard_group = cfg.OptGroup(name="dashboard", - title="Dashboard options") - -DashboardGroup = [ - cfg.StrOpt('dashboard_url', - default='http://localhost/', - help="Where the dashboard can be found"), - cfg.StrOpt('login_url', - default='http://localhost/auth/login/', - help="Login page for the dashboard"), -] - - -data_processing_group = cfg.OptGroup(name="data_processing", - title="Data Processing options") - -DataProcessingGroup = [ - cfg.StrOpt('catalog_type', - default='data_processing', - help="Catalog type of the data processing service."), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the data processing " - "service."), -] - - -data_processing_feature_group = cfg.OptGroup( - name="data_processing-feature-enabled", - title="Enabled Data Processing features") - -DataProcessingFeaturesGroup = [ - cfg.ListOpt('plugins', - default=["vanilla", "hdp"], - help="List of enabled data processing plugins") -] - - -boto_group = cfg.OptGroup(name='boto', - title='EC2/S3 options') -BotoGroup = [ - cfg.StrOpt('ec2_url', - default="http://localhost:8773/services/Cloud", - help="EC2 URL"), - cfg.StrOpt('s3_url', - default="http://localhost:8080", - help="S3 URL"), - cfg.StrOpt('aws_secret', - help="AWS Secret Key", - secret=True), - cfg.StrOpt('aws_access', - help="AWS Access Key"), - cfg.StrOpt('aws_zone', - default="nova", - help="AWS Zone for EC2 tests"), - cfg.StrOpt('s3_materials_path', - default="/opt/stack/devstack/files/images/" - "s3-materials/cirros-0.3.0", - help="S3 Materials Path"), - cfg.StrOpt('ari_manifest', - default="cirros-0.3.0-x86_64-initrd.manifest.xml", - help="ARI Ramdisk Image manifest"), - cfg.StrOpt('ami_manifest', - default="cirros-0.3.0-x86_64-blank.img.manifest.xml", - help="AMI Machine Image manifest"), - cfg.StrOpt('aki_manifest', - default="cirros-0.3.0-x86_64-vmlinuz.manifest.xml", - help="AKI Kernel Image manifest"), - cfg.StrOpt('instance_type', - default="m1.tiny", - help="Instance type"), - cfg.IntOpt('http_socket_timeout', - default=3, - help="boto Http socket timeout"), - cfg.IntOpt('num_retries', - default=1, - help="boto num_retries on error"), - cfg.IntOpt('build_timeout', - default=60, - help="Status Change Timeout"), - cfg.IntOpt('build_interval', - default=1, - help="Status Change Test Interval"), -] - -stress_group = cfg.OptGroup(name='stress', title='Stress Test Options') - -StressGroup = [ - cfg.StrOpt('nova_logdir', - help='Directory containing log files on the compute nodes'), - cfg.IntOpt('max_instances', - default=16, - help='Maximum number of instances to create during test.'), - cfg.StrOpt('controller', - help='Controller host.'), - # new stress options - cfg.StrOpt('target_controller', - help='Controller host.'), - cfg.StrOpt('target_ssh_user', - help='ssh user.'), - cfg.StrOpt('target_private_key_path', - help='Path to private key.'), - cfg.StrOpt('target_logfiles', - help='regexp for list of log files.'), - cfg.IntOpt('log_check_interval', - default=60, - help='time (in seconds) between log file error checks.'), - cfg.IntOpt('default_thread_number_per_action', - default=4, - help='The number of threads created while stress test.'), - cfg.BoolOpt('leave_dirty_stack', - default=False, - help='Prevent the cleaning (tearDownClass()) between' - ' each stress test run if an exception occurs' - ' during this run.'), - cfg.BoolOpt('full_clean_stack', - default=False, - help='Allows a full cleaning process after a stress test.' - ' Caution : this cleanup will remove every objects of' - ' every tenant.') -] - - -scenario_group = cfg.OptGroup(name='scenario', title='Scenario Test Options') - -ScenarioGroup = [ - cfg.StrOpt('img_dir', - default='/opt/stack/new/devstack/files/images/' - 'cirros-0.3.1-x86_64-uec', - help='Directory containing image files'), - cfg.StrOpt('img_file', deprecated_name='qcow2_img_file', - default='cirros-0.3.1-x86_64-disk.img', - help='Image file name'), - cfg.StrOpt('img_file_2', deprecated_name='qcow2_img_file_2', - default='winxp.img', - help='Image file name 2'), - cfg.StrOpt('img_disk_format', - default='qcow2', - help='Image disk format'), - cfg.StrOpt('img_container_format', - default='bare', - help='Image container format'), - cfg.StrOpt('ami_img_file', - default='cirros-0.3.1-x86_64-blank.img', - help='AMI image file name'), - cfg.StrOpt('ari_img_file', - default='cirros-0.3.1-x86_64-initrd', - help='ARI image file name'), - cfg.StrOpt('aki_img_file', - default='cirros-0.3.1-x86_64-vmlinuz', - help='AKI image file name'), - cfg.StrOpt('ssh_user', - default='cirros', - help='ssh username for the image file'), - cfg.IntOpt( - 'large_ops_number', - default=0, - help="specifies how many resources to request at once. Used " - "for large operations testing."), - # TODO(yfried): add support for dhcpcd - cfg.StrOpt('dhcp_client', - default='udhcpc', - choices=["udhcpc", "dhclient"], - help='DHCP client used by images to renew DCHP lease. ' - 'If left empty, update operation will be skipped. ' - 'Supported clients: "udhcpc", "dhclient"') -] - - -service_available_group = cfg.OptGroup(name="service_available", - title="Available OpenStack Services") - -ServiceAvailableGroup = [ - cfg.BoolOpt('cinder', - default=True, - help="Whether or not cinder is expected to be available"), - cfg.BoolOpt('neutron', - default=False, - help="Whether or not neutron is expected to be available"), - cfg.BoolOpt('glance', - default=True, - help="Whether or not glance is expected to be available"), - cfg.BoolOpt('swift', - default=True, - help="Whether or not swift is expected to be available"), - cfg.BoolOpt('nova', - default=True, - help="Whether or not nova is expected to be available"), - cfg.BoolOpt('heat', - default=False, - help="Whether or not Heat is expected to be available"), - cfg.BoolOpt('ceilometer', - default=True, - help="Whether or not Ceilometer is expected to be available"), - cfg.BoolOpt('horizon', - default=True, - help="Whether or not Horizon is expected to be available"), - cfg.BoolOpt('sahara', - default=False, - help="Whether or not Sahara is expected to be available"), - cfg.BoolOpt('ironic', - default=False, - help="Whether or not Ironic is expected to be available"), - cfg.BoolOpt('trove', - default=False, - help="Whether or not Trove is expected to be available"), - cfg.BoolOpt('zaqar', - default=False, - help="Whether or not Zaqar is expected to be available"), -] - -debug_group = cfg.OptGroup(name="debug", - title="Debug System") - -DebugGroup = [ - cfg.StrOpt('trace_requests', - default='', - help="""A regex to determine which requests should be traced. - -This is a regex to match the caller for rest client requests to be able to -selectively trace calls out of specific classes and methods. It largely -exists for test development, and is not expected to be used in a real deploy -of tempest. This will be matched against the discovered ClassName:method -in the test environment. - -Expected values for this field are: - - * ClassName:test_method_name - traces one test_method - * ClassName:setUp(Class) - traces specific setup functions - * ClassName:tearDown(Class) - traces specific teardown functions - * ClassName:_run_cleanups - traces the cleanup functions - -If nothing is specified, this feature is not enabled. To trace everything -specify .* as the regex. -""") -] - -input_scenario_group = cfg.OptGroup(name="input-scenario", - title="Filters and values for" - " input scenarios") - -InputScenarioGroup = [ - cfg.StrOpt('image_regex', - default='^cirros-0.3.1-x86_64-uec$', - help="Matching images become parameters for scenario tests"), - cfg.StrOpt('flavor_regex', - default='^m1.nano$', - help="Matching flavors become parameters for scenario tests"), - cfg.StrOpt('non_ssh_image_regex', - default='^.*[Ww]in.*$', - help="SSH verification in tests is skipped" - "for matching images"), - cfg.StrOpt('ssh_user_regex', - default="[[\"^.*[Cc]irros.*$\", \"cirros\"]]", - help="List of user mapped to regex " - "to matching image names."), -] - - -baremetal_group = cfg.OptGroup(name='baremetal', - title='Baremetal provisioning service options', - help='When enabling baremetal tests, Nova ' - 'must be configured to use the Ironic ' - 'driver. The following paremeters for the ' - '[compute] section must be disabled: ' - 'console_output, interface_attach, ' - 'live_migration, pause, rescue, resize ' - 'shelve, snapshot, and suspend') - -BaremetalGroup = [ - cfg.StrOpt('catalog_type', - default='baremetal', - help="Catalog type of the baremetal provisioning service"), - cfg.BoolOpt('driver_enabled', - default=False, - help="Whether the Ironic nova-compute driver is enabled"), - cfg.StrOpt('driver', - default='fake', - help="Driver name which Ironic uses"), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the baremetal provisioning " - "service"), - cfg.IntOpt('active_timeout', - default=300, - help="Timeout for Ironic node to completely provision"), - cfg.IntOpt('association_timeout', - default=30, - help="Timeout for association of Nova instance and Ironic " - "node"), - cfg.IntOpt('power_timeout', - default=60, - help="Timeout for Ironic power transitions."), - cfg.IntOpt('unprovision_timeout', - default=60, - help="Timeout for unprovisioning an Ironic node.") -] - -cli_group = cfg.OptGroup(name='cli', title="cli Configuration Options") - -CLIGroup = [ - cfg.BoolOpt('enabled', - default=True, - help="enable cli tests"), - cfg.StrOpt('cli_dir', - default='/usr/local/bin', - help="directory where python client binaries are located"), - cfg.BoolOpt('has_manage', - default=True, - help=("Whether the tempest run location has access to the " - "*-manage commands. In a pure blackbox environment " - "it will not.")), - cfg.IntOpt('timeout', - default=15, - help="Number of seconds to wait on a CLI timeout"), -] - -negative_group = cfg.OptGroup(name='negative', title="Negative Test Options") - -NegativeGroup = [ - cfg.StrOpt('test_generator', - default='tempest.common.' + - 'generator.negative_generator.NegativeTestGenerator', - help="Test generator class for all negative tests"), -] - -tecs_group = cfg.OptGroup(name='tecs', title="TECS Test Options") - -TecsGroup = [ - cfg.StrOpt('host_ip', - default='', - help="host ip"), - cfg.StrOpt('host_username', - help="host username"), - cfg.StrOpt('host_password', - help="host password"), - cfg.StrOpt('v4_flavor_id', - help="V4 flavor for V4 image tests"), - cfg.StrOpt('v4_omcnet_id', - help="V4 omcnet - flat for V4 VM tests"), - cfg.StrOpt('v4_basenet_id', - help="V4 basenet - vlan for V4 VM tests"), - cfg.StrOpt('v4_fabricnet_id', - help="V4 fabricnet for V4 VM tests"), - cfg.StrOpt('v4_outnet_id', - help="V4 outnet for V4 VM tests"), - cfg.StrOpt('network_image_id', - help="Network image for network tests"), - cfg.StrOpt('network_flavor_id', - help="Network flavor for network tests"), - cfg.StrOpt('network_ssh_user', - help="Network SSH user for network tests"), - cfg.StrOpt('network_ssh_pwd', - help="Network SSH password for network tests"), - cfg.StrOpt('network_server_ipaddr', - help="Network outside server ip address for network tests"), - cfg.StrOpt('network_server_ssh_user', - help="Network outside server SSH user for network tests"), - cfg.StrOpt('network_server_ssh_pwd', - help="Network outside server SSH password for network tests"), - cfg.StrOpt('network_server_ftp_user', - help="Network outside server FTP user for network tests"), - cfg.StrOpt('network_server_ftp_pwd', - help="Network outside server FTP password for network tests"), - cfg.StrOpt('network_lb_provider', - help="Network lbaas provider"), -] - -daisy_group = cfg.OptGroup(name='daisy', title="Daisy Test Tecs") -DaisyGroup = [ - cfg.StrOpt('daisy_endpoint', - default='', - help="daisy_endpoint"), - cfg.StrOpt('cluster_id', - default='', - help="cluster_id"), - cfg.StrOpt('install_ha_ip', - default='', - help="install_ha_ip"), - cfg.StrOpt('install_ha_netmask', - default='', - help="install_ha_netmask"), - cfg.StrOpt('install_ha_vip', - default='', - help="install_ha_vip"), - cfg.StrOpt('time_out', - default=1080, - help="time_out"), - cfg.StrOpt('install_ha_eth_name', - default='', - help="install_ha_eth_name"), - cfg.StrOpt('install_ha_mac', - default='', - help="install_ha_mac") -] - -_opts = [ - (auth_group, AuthGroup), - (compute_group, ComputeGroup), - (compute_features_group, ComputeFeaturesGroup), - (identity_group, IdentityGroup), - (identity_feature_group, IdentityFeatureGroup), - (image_group, ImageGroup), - (image_feature_group, ImageFeaturesGroup), - (network_group, NetworkGroup), - (network_feature_group, NetworkFeaturesGroup), - (messaging_group, MessagingGroup), - (validation_group, ValidationGroup), - (volume_group, VolumeGroup), - (volume_feature_group, VolumeFeaturesGroup), - (object_storage_group, ObjectStoreGroup), - (object_storage_feature_group, ObjectStoreFeaturesGroup), - (database_group, DatabaseGroup), - (orchestration_group, OrchestrationGroup), - (telemetry_group, TelemetryGroup), - (dashboard_group, DashboardGroup), - (data_processing_group, DataProcessingGroup), - (data_processing_feature_group, DataProcessingFeaturesGroup), - (boto_group, BotoGroup), - (stress_group, StressGroup), - (scenario_group, ScenarioGroup), - (service_available_group, ServiceAvailableGroup), - (debug_group, DebugGroup), - (baremetal_group, BaremetalGroup), - (input_scenario_group, InputScenarioGroup), - (cli_group, CLIGroup), - (negative_group, NegativeGroup), - (tecs_group, TecsGroup), - (daisy_group, DaisyGroup) -] - - -def register_opts(): - for g, o in _opts: - register_opt_group(_CONF, g, o) - - -def list_opts(): - """Return a list of oslo.config options available. - - The purpose of this is to allow tools like the Oslo sample config file - generator to discover the options exposed to users. - """ - return [(g.name, o) for g, o in _opts] - - -# this should never be called outside of this class -class TempestConfigPrivate(object): - """Provides OpenStack configuration information.""" - - DEFAULT_CONFIG_DIR = os.path.join( - os.path.abspath(os.path.dirname(os.path.dirname(__file__))), - "etc") - - DEFAULT_CONFIG_FILE = "tempest.conf" - - def __getattr__(self, attr): - # Handles config options from the default group - return getattr(_CONF, attr) - - def _set_attrs(self): - self.auth = _CONF.auth - self.compute = _CONF.compute - self.compute_feature_enabled = _CONF['compute-feature-enabled'] - self.identity = _CONF.identity - self.identity_feature_enabled = _CONF['identity-feature-enabled'] - self.image = _CONF.image - self.image_feature_enabled = _CONF['image-feature-enabled'] - self.network = _CONF.network - self.network_feature_enabled = _CONF['network-feature-enabled'] - self.validation = _CONF.validation - self.volume = _CONF.volume - self.volume_feature_enabled = _CONF['volume-feature-enabled'] - self.object_storage = _CONF['object-storage'] - self.object_storage_feature_enabled = _CONF[ - 'object-storage-feature-enabled'] - self.database = _CONF.database - self.orchestration = _CONF.orchestration - self.messaging = _CONF.messaging - self.telemetry = _CONF.telemetry - self.dashboard = _CONF.dashboard - self.data_processing = _CONF.data_processing - self.data_processing_feature_enabled = _CONF[ - 'data_processing-feature-enabled'] - self.boto = _CONF.boto - self.stress = _CONF.stress - self.scenario = _CONF.scenario - self.service_available = _CONF.service_available - self.debug = _CONF.debug - self.baremetal = _CONF.baremetal - self.input_scenario = _CONF['input-scenario'] - self.cli = _CONF.cli - self.negative = _CONF.negative - _CONF.set_default('domain_name', self.identity.admin_domain_name, - group='identity') - _CONF.set_default('alt_domain_name', self.identity.admin_domain_name, - group='identity') - self.tecs = cfg.CONF.tecs - self.daisy = cfg.CONF.daisy - - def __init__(self, parse_conf=True, config_path=None): - """Initialize a configuration from a conf directory and conf file.""" - super(TempestConfigPrivate, self).__init__() - config_files = [] - failsafe_path = "/etc/tempest/" + self.DEFAULT_CONFIG_FILE - - if config_path: - path = config_path - else: - # Environment variables override defaults... - conf_dir = os.environ.get('TEMPEST_CONFIG_DIR', - self.DEFAULT_CONFIG_DIR) - conf_file = os.environ.get('TEMPEST_CONFIG', - self.DEFAULT_CONFIG_FILE) - - path = os.path.join(conf_dir, conf_file) - - if not os.path.isfile(path): - path = failsafe_path - - # only parse the config file if we expect one to exist. This is needed - # to remove an issue with the config file up to date checker. - if parse_conf: - config_files.append(path) - logging.register_options(_CONF) - if os.path.isfile(path): - _CONF([], project='tempest', default_config_files=config_files) - else: - _CONF([], project='tempest') - logging.setup(_CONF, 'tempest') - LOG = logging.getLogger('tempest') - LOG.info("Using tempest config file %s" % path) - register_opts() - self._set_attrs() - if parse_conf: - _CONF.log_opt_values(LOG, std_logging.DEBUG) - - -class TempestConfigProxy(object): - _config = None - _path = None - - _extra_log_defaults = [ - ('paramiko.transport', std_logging.INFO), - ('requests.packages.urllib3.connectionpool', std_logging.WARN), - ] - - def _fix_log_levels(self): - """Tweak the oslo log defaults.""" - for name, level in self._extra_log_defaults: - std_logging.getLogger(name).setLevel(level) - - def __getattr__(self, attr): - if not self._config: - self._fix_log_levels() - self._config = TempestConfigPrivate(config_path=self._path) - - return getattr(self._config, attr) - - def set_config_path(self, path): - self._path = path - - -CONF = TempestConfigProxy() diff --git a/test/tempest/tempest/exceptions.py b/test/tempest/tempest/exceptions.py deleted file mode 100644 index f52744d2..00000000 --- a/test/tempest/tempest/exceptions.py +++ /dev/null @@ -1,246 +0,0 @@ -# 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 testtools - -# zfl add : get related opencos log -import re -import traceback -import time -from tempest_lib.common.utils import misc - - -# zfl add a decorator to show func's exec time -def exectime(func): - def newfunc(*args, **args2): - t0 = time.time() - f = func(*args, **args2) - print "\n\n@====exectime====%.3fs taken for {%s}\n\n" \ - % (time.time() - t0, func.__name__) - return f - return newfunc -# zfl add end - - -class TempestException(Exception): - """ - Base Tempest Exception - - To correctly use this class, inherit from it and define - a 'message' property. That message will get printf'd - with the keyword arguments provided to the constructor. - """ - message = "An unknown exception occurred" - - def __init__(self, *args, **kwargs): - super(TempestException, self).__init__() - try: - self._error_string = self.message % kwargs - except Exception: - # at least get the core message out if something happened - self._error_string = self.message - if len(args) > 0: - # If there is a non-kwarg parameter, assume it's the error - # message or reason description and tack it on to the end - # of the exception message - # Convert all arguments into their string representations... - args = ["%s" % arg for arg in args] - self._error_string = (self._error_string + - "\nDetails: %s" % '\n'.join(args)) - - def __str__(self): - # zfl add : get related opencos log - try: - # zfl for debug only: stop and reserve - # if issubclass(type(self),SSHTimeout): - # import time - # time.sleep(999999999) - # zfl for debug only: stop and reserve end - - self.get_log = True - log_obj = misc.GetOpenCosLog() - pattern1 = re.compile(r'\w+-\w+-\w+-\w+-\w+') - sresult = pattern1.findall(self._error_string) - obj_type = "" - if 'server' in self._error_string.lower(): - obj_type = "server" - if sresult: - log_result = log_obj.get_opencos_log(sresult, - obj_type=obj_type) - else: - log_result = log_obj.get_opencos_log([], - obj_type=obj_type) - log_result = "\n--------- \n" + log_result - self._error_string = self._error_string + \ - "\n\n\n===possible log ===" + \ - log_result + \ - "\n\n===possiblelog end===\n\n\n" - except Exception as e: - print "ZTE ===zfl : error ==", e - traceback.print_exc() -# else: -# print "\n========zfl,exception call __str__ again" - - # zfl add end: get related opencos log - return self._error_string - - -class RestClientException(TempestException, - testtools.TestCase.failureException): - pass - - -class InvalidConfiguration(TempestException): - message = "Invalid Configuration" - - -class InvalidCredentials(TempestException): - message = "Invalid Credentials" - - -class InvalidServiceTag(TempestException): - message = "Invalid service tag" - - -class InvalidIdentityVersion(TempestException): - message = "Invalid version %(identity_version) of the identity service" - - -class TimeoutException(TempestException): - message = "Request timed out" - - -class BuildErrorException(TempestException): - message = "Server %(server_id)s failed to build and is in ERROR status" - - -class ImageKilledException(TempestException): - message = "Image %(image_id)s 'killed' while waiting for '%(status)s'" - - -class AddImageException(TempestException): - message = "Image %(image_id)s failed to become ACTIVE in the allotted time" - - -class EC2RegisterImageException(TempestException): - message = ("Image %(image_id)s failed to become 'available' " - "in the allotted time") - - -class VolumeBuildErrorException(TempestException): - message = "Volume %(volume_id)s failed to build and is in ERROR status" - - -class SnapshotBuildErrorException(TempestException): - message = "Snapshot %(snapshot_id)s failed to build and is in ERROR status" - - -class VolumeBackupException(TempestException): - message = "Volume backup %(backup_id)s failed and is in ERROR status" - - -class StackBuildErrorException(TempestException): - message = ("Stack %(stack_identifier)s is in %(stack_status)s status " - "due to '%(stack_status_reason)s'") - - -class StackResourceBuildErrorException(TempestException): - message = ("Resource %(resource_name)s in stack %(stack_identifier)s is " - "in %(resource_status)s status due to " - "'%(resource_status_reason)s'") - - -class AuthenticationFailure(TempestException): - message = ("Authentication with user %(user)s and password " - "%(password)s failed auth using tenant %(tenant)s.") - - -class EndpointNotFound(TempestException): - message = "Endpoint not found" - - -class ImageFault(TempestException): - message = "Got image fault" - - -class IdentityError(TempestException): - message = "Got identity error" - - -class SSHTimeout(TempestException): - message = ("Connection to the %(host)s via SSH timed out.\n" - "User: %(user)s, Password: %(password)s") - - -class SSHExecCommandFailed(TempestException): - """Raised when remotely executed command returns nonzero status.""" - message = ("Command '%(command)s', exit status: %(exit_status)d, " - "Error:\n%(strerror)s") - - -class ServerUnreachable(TempestException): - message = "The server is not reachable via the configured network" - - -class TearDownException(TempestException): - message = "%(num)d cleanUp operation failed" - - -class RFCViolation(RestClientException): - message = "RFC Violation" - - -class InvalidHttpSuccessCode(RestClientException): - message = "The success code is different than the expected one" - - -class BadRequest(RestClientException): - message = "Bad request" - - -class ResponseWithNonEmptyBody(RFCViolation): - message = ("RFC Violation! Response with %(status)d HTTP Status Code " - "MUST NOT have a body") - - -class ResponseWithEntity(RFCViolation): - message = ("RFC Violation! Response with 205 HTTP Status Code " - "MUST NOT have an entity") - - -class InvalidHTTPResponseHeader(RestClientException): - message = "HTTP response header is invalid" - - -class InvalidStructure(TempestException): - message = "Invalid structure of table with details" - - -class CommandFailed(Exception): - - def __init__(self, returncode, cmd, output, stderr): - super(CommandFailed, self).__init__() - self.returncode = returncode - self.cmd = cmd - self.stdout = output - self.stderr = stderr - - def __str__(self): - return ("Command '%s' returned non-zero exit status %d.\n" - "stdout:\n%s\n" - "stderr:\n%s" % (self.cmd, - self.returncode, - self.stdout, - self.stderr)) diff --git a/test/tempest/tempest/manager.py b/test/tempest/tempest/manager.py deleted file mode 100644 index 025ce65d..00000000 --- a/test/tempest/tempest/manager.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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. - -from tempest import auth -from tempest.common import cred_provider -from tempest import config -from tempest import exceptions - -CONF = config.CONF - - -class Manager(object): - - """ - Base manager class - - Manager objects are responsible for providing a configuration object - and a client object for a test case to use in performing actions. - """ - - def __init__(self, credentials=None): - """ - We allow overriding of the credentials used within the various - client classes managed by the Manager object. Left as None, the - standard username/password/tenant_name[/domain_name] is used. - - :param credentials: Override of the credentials - """ - self.auth_version = CONF.identity.auth_version - if credentials is None: - self.credentials = cred_provider.get_configured_credentials('user') - else: - self.credentials = credentials - # Check if passed or default credentials are valid - if not self.credentials.is_valid(): - raise exceptions.InvalidCredentials() - # Tenant isolation creates TestResources, but Accounts and some tests - # creates Credentials - if isinstance(credentials, cred_provider.TestResources): - creds = self.credentials.credentials - else: - creds = self.credentials - # Creates an auth provider for the credentials - self.auth_provider = get_auth_provider(creds) - # FIXME(andreaf) unused - self.client_attr_names = [] - - -def get_auth_provider_class(credentials): - if isinstance(credentials, auth.KeystoneV3Credentials): - return auth.KeystoneV3AuthProvider, CONF.identity.uri_v3 - else: - return auth.KeystoneV2AuthProvider, CONF.identity.uri - - -def get_auth_provider(credentials): - default_params = { - 'disable_ssl_certificate_validation': - CONF.identity.disable_ssl_certificate_validation, - 'ca_certs': CONF.identity.ca_certificates_file, - 'trace_requests': CONF.debug.trace_requests - } - if credentials is None: - raise exceptions.InvalidCredentials( - 'Credentials must be specified') - auth_provider_class, auth_url = get_auth_provider_class( - credentials) - return auth_provider_class(credentials, auth_url, **default_params) diff --git a/test/tempest/tempest/services/__init__.py b/test/tempest/tempest/services/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/baremetal/__init__.py b/test/tempest/tempest/services/baremetal/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/baremetal/base.py b/test/tempest/tempest/services/baremetal/base.py deleted file mode 100644 index 4c6a5bf0..00000000 --- a/test/tempest/tempest/services/baremetal/base.py +++ /dev/null @@ -1,219 +0,0 @@ -# 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 functools -import json -import urllib - -import six - -from tempest.common import service_client - - -def handle_errors(f): - """A decorator that allows to ignore certain types of errors.""" - - @functools.wraps(f) - def wrapper(*args, **kwargs): - param_name = 'ignore_errors' - ignored_errors = kwargs.get(param_name, tuple()) - - if param_name in kwargs: - del kwargs[param_name] - - try: - return f(*args, **kwargs) - except ignored_errors: - # Silently ignore errors - pass - - return wrapper - - -class BaremetalClient(service_client.ServiceClient): - """ - Base Tempest REST client for Ironic API. - - """ - - uri_prefix = '' - - def serialize(self, object_dict): - """Serialize an Ironic object.""" - - return json.dumps(object_dict) - - def deserialize(self, object_str): - """Deserialize an Ironic object.""" - - return json.loads(object_str) - - def _get_uri(self, resource_name, uuid=None, permanent=False): - """ - Get URI for a specific resource or object. - - :param resource_name: The name of the REST resource, e.g., 'nodes'. - :param uuid: The unique identifier of an object in UUID format. - :return: Relative URI for the resource or object. - - """ - prefix = self.uri_prefix if not permanent else '' - - return '{pref}/{res}{uuid}'.format(pref=prefix, - res=resource_name, - uuid='/%s' % uuid if uuid else '') - - def _make_patch(self, allowed_attributes, **kw): - """ - Create a JSON patch according to RFC 6902. - - :param allowed_attributes: An iterable object that contains a set of - allowed attributes for an object. - :param **kw: Attributes and new values for them. - :return: A JSON path that sets values of the specified attributes to - the new ones. - - """ - def get_change(kw, path='/'): - for name, value in six.iteritems(kw): - if isinstance(value, dict): - for ch in get_change(value, path + '%s/' % name): - yield ch - else: - if value is None: - yield {'path': path + name, - 'op': 'remove'} - else: - yield {'path': path + name, - 'value': value, - 'op': 'replace'} - - patch = [ch for ch in get_change(kw) - if ch['path'].lstrip('/') in allowed_attributes] - - return patch - - def _list_request(self, resource, permanent=False, **kwargs): - """ - Get the list of objects of the specified type. - - :param resource: The name of the REST resource, e.g., 'nodes'. - "param **kw: Parameters for the request. - :return: A tuple with the server response and deserialized JSON list - of objects - - """ - uri = self._get_uri(resource, permanent=permanent) - if kwargs: - uri += "?%s" % urllib.urlencode(kwargs) - - resp, body = self.get(uri) - self.expected_success(200, resp['status']) - - return resp, self.deserialize(body) - - def _show_request(self, resource, uuid, permanent=False, **kwargs): - """ - Gets a specific object of the specified type. - - :param uuid: Unique identifier of the object in UUID format. - :return: Serialized object as a dictionary. - - """ - if 'uri' in kwargs: - uri = kwargs['uri'] - else: - uri = self._get_uri(resource, uuid=uuid, permanent=permanent) - resp, body = self.get(uri) - self.expected_success(200, resp['status']) - - return resp, self.deserialize(body) - - def _create_request(self, resource, object_dict): - """ - Create an object of the specified type. - - :param resource: The name of the REST resource, e.g., 'nodes'. - :param object_dict: A Python dict that represents an object of the - specified type. - :return: A tuple with the server response and the deserialized created - object. - - """ - body = self.serialize(object_dict) - uri = self._get_uri(resource) - - resp, body = self.post(uri, body=body) - self.expected_success(201, resp['status']) - - return resp, self.deserialize(body) - - def _delete_request(self, resource, uuid): - """ - Delete specified object. - - :param resource: The name of the REST resource, e.g., 'nodes'. - :param uuid: The unique identifier of an object in UUID format. - :return: A tuple with the server response and the response body. - - """ - uri = self._get_uri(resource, uuid) - - resp, body = self.delete(uri) - self.expected_success(204, resp['status']) - return resp, body - - def _patch_request(self, resource, uuid, patch_object): - """ - Update specified object with JSON-patch. - - :param resource: The name of the REST resource, e.g., 'nodes'. - :param uuid: The unique identifier of an object in UUID format. - :return: A tuple with the server response and the serialized patched - object. - - """ - uri = self._get_uri(resource, uuid) - patch_body = json.dumps(patch_object) - - resp, body = self.patch(uri, body=patch_body) - self.expected_success(200, resp['status']) - return resp, self.deserialize(body) - - @handle_errors - def get_api_description(self): - """Retrieves all versions of the Ironic API.""" - - return self._list_request('', permanent=True) - - @handle_errors - def get_version_description(self, version='v1'): - """ - Retrieves the desctription of the API. - - :param version: The version of the API. Default: 'v1'. - :return: Serialized description of API resources. - - """ - return self._list_request(version, permanent=True) - - def _put_request(self, resource, put_object): - """ - Update specified object with JSON-patch. - - """ - uri = self._get_uri(resource) - put_body = json.dumps(put_object) - - resp, body = self.put(uri, body=put_body) - self.expected_success(202, resp['status']) - return resp, body diff --git a/test/tempest/tempest/services/baremetal/v1/__init__.py b/test/tempest/tempest/services/baremetal/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/baremetal/v1/json/__init__.py b/test/tempest/tempest/services/baremetal/v1/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/baremetal/v1/json/baremetal_client.py b/test/tempest/tempest/services/baremetal/v1/json/baremetal_client.py deleted file mode 100644 index 0c319f65..00000000 --- a/test/tempest/tempest/services/baremetal/v1/json/baremetal_client.py +++ /dev/null @@ -1,373 +0,0 @@ -# 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.services.baremetal import base - - -class BaremetalClientJSON(base.BaremetalClient): - """ - Base Tempest REST client for Ironic API v1. - """ - version = '1' - uri_prefix = 'v1' - - @base.handle_errors - def list_nodes(self, **kwargs): - """List all existing nodes.""" - return self._list_request('nodes', **kwargs) - - @base.handle_errors - def list_chassis(self): - """List all existing chassis.""" - return self._list_request('chassis') - - @base.handle_errors - def list_chassis_nodes(self, chassis_uuid): - """List all nodes associated with a chassis.""" - return self._list_request('/chassis/%s/nodes' % chassis_uuid) - - @base.handle_errors - def list_ports(self, **kwargs): - """List all existing ports.""" - return self._list_request('ports', **kwargs) - - @base.handle_errors - def list_node_ports(self, uuid): - """List all ports associated with the node.""" - return self._list_request('/nodes/%s/ports' % uuid) - - @base.handle_errors - def list_nodestates(self, uuid): - """List all existing states.""" - return self._list_request('/nodes/%s/states' % uuid) - - @base.handle_errors - def list_ports_detail(self, **kwargs): - """Details list all existing ports.""" - return self._list_request('/ports/detail', **kwargs) - - @base.handle_errors - def list_drivers(self): - """List all existing drivers.""" - return self._list_request('drivers') - - @base.handle_errors - def show_node(self, uuid): - """ - Gets a specific node. - - :param uuid: Unique identifier of the node in UUID format. - :return: Serialized node as a dictionary. - - """ - return self._show_request('nodes', uuid) - - @base.handle_errors - def show_node_by_instance_uuid(self, instance_uuid): - """ - Gets a node associated with given instance uuid. - - :param uuid: Unique identifier of the node in UUID format. - :return: Serialized node as a dictionary. - - """ - uri = '/nodes/detail?instance_uuid=%s' % instance_uuid - - return self._show_request('nodes', - uuid=None, - uri=uri) - - @base.handle_errors - def show_chassis(self, uuid): - """ - Gets a specific chassis. - - :param uuid: Unique identifier of the chassis in UUID format. - :return: Serialized chassis as a dictionary. - - """ - return self._show_request('chassis', uuid) - - @base.handle_errors - def show_port(self, uuid): - """ - Gets a specific port. - - :param uuid: Unique identifier of the port in UUID format. - :return: Serialized port as a dictionary. - - """ - return self._show_request('ports', uuid) - - @base.handle_errors - def show_port_by_address(self, address): - """ - Gets a specific port by address. - - :param address: MAC address of the port. - :return: Serialized port as a dictionary. - - """ - uri = '/ports/detail?address=%s' % address - - return self._show_request('ports', uuid=None, uri=uri) - - def show_driver(self, driver_name): - """ - Gets a specific driver. - - :param driver_name: Name of driver. - :return: Serialized driver as a dictionary. - """ - return self._show_request('drivers', driver_name) - - @base.handle_errors - def create_node(self, chassis_id=None, **kwargs): - """ - Create a baremetal node with the specified parameters. - - :param cpu_arch: CPU architecture of the node. Default: x86_64. - :param cpus: Number of CPUs. Default: 8. - :param local_gb: Disk size. Default: 1024. - :param memory_mb: Available RAM. Default: 4096. - :param driver: Driver name. Default: "fake" - :return: A tuple with the server response and the created node. - - """ - node = {'chassis_uuid': chassis_id, - 'properties': {'cpu_arch': kwargs.get('cpu_arch', 'x86_64'), - 'cpus': kwargs.get('cpus', 8), - 'local_gb': kwargs.get('local_gb', 1024), - 'memory_mb': kwargs.get('memory_mb', 4096)}, - 'driver': kwargs.get('driver', 'fake')} - - return self._create_request('nodes', node) - - @base.handle_errors - def create_chassis(self, **kwargs): - """ - Create a chassis with the specified parameters. - - :param description: The description of the chassis. - Default: test-chassis - :return: A tuple with the server response and the created chassis. - - """ - chassis = {'description': kwargs.get('description', 'test-chassis')} - - return self._create_request('chassis', chassis) - - @base.handle_errors - def create_port(self, node_id, **kwargs): - """ - Create a port with the specified parameters. - - :param node_id: The ID of the node which owns the port. - :param address: MAC address of the port. - :param extra: Meta data of the port. Default: {'foo': 'bar'}. - :param uuid: UUID of the port. - :return: A tuple with the server response and the created port. - - """ - port = {'extra': kwargs.get('extra', {'foo': 'bar'}), - 'uuid': kwargs['uuid']} - - if node_id is not None: - port['node_uuid'] = node_id - - if kwargs['address'] is not None: - port['address'] = kwargs['address'] - - return self._create_request('ports', port) - - @base.handle_errors - def delete_node(self, uuid): - """ - Deletes a node having the specified UUID. - - :param uuid: The unique identifier of the node. - :return: A tuple with the server response and the response body. - - """ - return self._delete_request('nodes', uuid) - - @base.handle_errors - def delete_chassis(self, uuid): - """ - Deletes a chassis having the specified UUID. - - :param uuid: The unique identifier of the chassis. - :return: A tuple with the server response and the response body. - - """ - return self._delete_request('chassis', uuid) - - @base.handle_errors - def delete_port(self, uuid): - """ - Deletes a port having the specified UUID. - - :param uuid: The unique identifier of the port. - :return: A tuple with the server response and the response body. - - """ - return self._delete_request('ports', uuid) - - @base.handle_errors - def update_node(self, uuid, **kwargs): - """ - Update the specified node. - - :param uuid: The unique identifier of the node. - :return: A tuple with the server response and the updated node. - - """ - node_attributes = ('properties/cpu_arch', - 'properties/cpus', - 'properties/local_gb', - 'properties/memory_mb', - 'driver', - 'instance_uuid') - - patch = self._make_patch(node_attributes, **kwargs) - - return self._patch_request('nodes', uuid, patch) - - @base.handle_errors - def update_chassis(self, uuid, **kwargs): - """ - Update the specified chassis. - - :param uuid: The unique identifier of the chassis. - :return: A tuple with the server response and the updated chassis. - - """ - chassis_attributes = ('description',) - patch = self._make_patch(chassis_attributes, **kwargs) - - return self._patch_request('chassis', uuid, patch) - - @base.handle_errors - def update_port(self, uuid, patch): - """ - Update the specified port. - - :param uuid: The unique identifier of the port. - :param patch: List of dicts representing json patches. - :return: A tuple with the server response and the updated port. - - """ - - return self._patch_request('ports', uuid, patch) - - @base.handle_errors - def set_node_power_state(self, node_uuid, state): - """ - Set power state of the specified node. - - :param node_uuid: The unique identifier of the node. - :state: desired state to set (on/off/reboot). - - """ - target = {'target': state} - return self._put_request('nodes/%s/states/power' % node_uuid, - target) - - @base.handle_errors - def validate_driver_interface(self, node_uuid): - """ - Get all driver interfaces of a specific node. - - :param uuid: Unique identifier of the node in UUID format. - - """ - - uri = '{pref}/{res}/{uuid}/{postf}'.format(pref=self.uri_prefix, - res='nodes', - uuid=node_uuid, - postf='validate') - - return self._show_request('nodes', node_uuid, uri=uri) - - @base.handle_errors - def set_node_boot_device(self, node_uuid, boot_device, persistent=False): - """ - Set the boot device of the specified node. - - :param node_uuid: The unique identifier of the node. - :param boot_device: The boot device name. - :param persistent: Boolean value. True if the boot device will - persist to all future boots, False if not. - Default: False. - - """ - request = {'boot_device': boot_device, 'persistent': persistent} - resp, body = self._put_request('nodes/%s/management/boot_device' % - node_uuid, request) - self.expected_success(204, resp.status) - return body - - @base.handle_errors - def get_node_boot_device(self, node_uuid): - """ - Get the current boot device of the specified node. - - :param node_uuid: The unique identifier of the node. - - """ - path = 'nodes/%s/management/boot_device' % node_uuid - resp, body = self._list_request(path) - self.expected_success(200, resp.status) - return body - - @base.handle_errors - def get_node_supported_boot_devices(self, node_uuid): - """ - Get the supported boot devices of the specified node. - - :param node_uuid: The unique identifier of the node. - - """ - path = 'nodes/%s/management/boot_device/supported' % node_uuid - resp, body = self._list_request(path) - self.expected_success(200, resp.status) - return body - - @base.handle_errors - def get_console(self, node_uuid): - """ - Get connection information about the console. - - :param node_uuid: Unique identifier of the node in UUID format. - - """ - - resp, body = self._show_request('nodes/states/console', node_uuid) - self.expected_success(200, resp.status) - return resp, body - - @base.handle_errors - def set_console_mode(self, node_uuid, enabled): - """ - Start and stop the node console. - - :param node_uuid: Unique identifier of the node in UUID format. - :param enabled: Boolean value; whether to enable or disable the - console. - - """ - - enabled = {'enabled': enabled} - resp, body = self._put_request('nodes/%s/states/console' % node_uuid, - enabled) - self.expected_success(202, resp.status) - return resp, body diff --git a/test/tempest/tempest/services/botoclients.py b/test/tempest/tempest/services/botoclients.py deleted file mode 100644 index ede464f8..00000000 --- a/test/tempest/tempest/services/botoclients.py +++ /dev/null @@ -1,216 +0,0 @@ -# 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 contextlib -import types - -import boto -import boto.ec2 -import boto.s3.connection -from six.moves import configparser as ConfigParser -from six.moves.urllib import parse as urlparse -from tempest_lib import exceptions as lib_exc - -from tempest import config - -CONF = config.CONF - - -class BotoClientBase(object): - - ALLOWED_METHODS = set() - - def __init__(self, identity_client): - self.identity_client = identity_client - - self.ca_cert = CONF.identity.ca_certificates_file - self.connection_timeout = str(CONF.boto.http_socket_timeout) - self.num_retries = str(CONF.boto.num_retries) - self.build_timeout = CONF.boto.build_timeout - - self.connection_data = {} - - def _config_boto_timeout(self, timeout, retries): - try: - boto.config.add_section("Boto") - except ConfigParser.DuplicateSectionError: - pass - boto.config.set("Boto", "http_socket_timeout", timeout) - boto.config.set("Boto", "num_retries", retries) - - def _config_boto_ca_certificates_file(self, ca_cert): - if ca_cert is None: - return - - try: - boto.config.add_section("Boto") - except ConfigParser.DuplicateSectionError: - pass - boto.config.set("Boto", "ca_certificates_file", ca_cert) - - def __getattr__(self, name): - """Automatically creates methods for the allowed methods set.""" - if name in self.ALLOWED_METHODS: - def func(self, *args, **kwargs): - with contextlib.closing(self.get_connection()) as conn: - return getattr(conn, name)(*args, **kwargs) - - func.__name__ = name - setattr(self, name, types.MethodType(func, self, self.__class__)) - setattr(self.__class__, name, - types.MethodType(func, None, self.__class__)) - return getattr(self, name) - else: - raise AttributeError(name) - - def get_connection(self): - self._config_boto_timeout(self.connection_timeout, self.num_retries) - self._config_boto_ca_certificates_file(self.ca_cert) - - ec2_client_args = {'aws_access_key_id': CONF.boto.aws_access, - 'aws_secret_access_key': CONF.boto.aws_secret} - if not all(ec2_client_args.values()): - ec2_client_args = self.get_aws_credentials(self.identity_client) - - self.connection_data.update(ec2_client_args) - return self.connect_method(**self.connection_data) - - def get_aws_credentials(self, identity_client): - """ - Obtain existing, or create new AWS credentials - :param identity_client: identity client with embedded credentials - :return: EC2 credentials - """ - ec2_cred_list = identity_client.list_user_ec2_credentials( - identity_client.user_id) - for cred in ec2_cred_list: - if cred['tenant_id'] == identity_client.tenant_id: - ec2_cred = cred - break - else: - ec2_cred = identity_client.create_user_ec2_credentials( - identity_client.user_id, identity_client.tenant_id) - if not all((ec2_cred, ec2_cred['access'], ec2_cred['secret'])): - raise lib_exc.NotFound("Unable to get access and secret keys") - else: - ec2_cred_aws = {} - ec2_cred_aws['aws_access_key_id'] = ec2_cred['access'] - ec2_cred_aws['aws_secret_access_key'] = ec2_cred['secret'] - return ec2_cred_aws - - -class APIClientEC2(BotoClientBase): - - def connect_method(self, *args, **kwargs): - return boto.connect_ec2(*args, **kwargs) - - def __init__(self, identity_client): - super(APIClientEC2, self).__init__(identity_client) - insecure_ssl = CONF.identity.disable_ssl_certificate_validation - purl = urlparse.urlparse(CONF.boto.ec2_url) - - region_name = CONF.compute.region - if not region_name: - region_name = CONF.identity.region - region = boto.ec2.regioninfo.RegionInfo(name=region_name, - endpoint=purl.hostname) - port = purl.port - if port is None: - if purl.scheme is not "https": - port = 80 - else: - port = 443 - else: - port = int(port) - self.connection_data.update({"is_secure": purl.scheme == "https", - "validate_certs": not insecure_ssl, - "region": region, - "host": purl.hostname, - "port": port, - "path": purl.path}) - - ALLOWED_METHODS = set(('create_key_pair', 'get_key_pair', - 'delete_key_pair', 'import_key_pair', - 'get_all_key_pairs', - 'get_all_tags', - 'create_image', 'get_image', - 'register_image', 'deregister_image', - 'get_all_images', 'get_image_attribute', - 'modify_image_attribute', 'reset_image_attribute', - 'get_all_kernels', - 'create_volume', 'delete_volume', - 'get_all_volume_status', 'get_all_volumes', - 'get_volume_attribute', 'modify_volume_attribute' - 'bundle_instance', 'cancel_spot_instance_requests', - 'confirm_product_instanc', - 'get_all_instance_status', 'get_all_instances', - 'get_all_reserved_instances', - 'get_all_spot_instance_requests', - 'get_instance_attribute', 'monitor_instance', - 'monitor_instances', 'unmonitor_instance', - 'unmonitor_instances', - 'purchase_reserved_instance_offering', - 'reboot_instances', 'request_spot_instances', - 'reset_instance_attribute', 'run_instances', - 'start_instances', 'stop_instances', - 'terminate_instances', - 'attach_network_interface', 'attach_volume', - 'detach_network_interface', 'detach_volume', - 'get_console_output', - 'delete_network_interface', 'create_subnet', - 'create_network_interface', 'delete_subnet', - 'get_all_network_interfaces', - 'allocate_address', 'associate_address', - 'disassociate_address', 'get_all_addresses', - 'release_address', - 'create_snapshot', 'delete_snapshot', - 'get_all_snapshots', 'get_snapshot_attribute', - 'modify_snapshot_attribute', - 'reset_snapshot_attribute', 'trim_snapshots', - 'get_all_regions', 'get_all_zones', - 'get_all_security_groups', 'create_security_group', - 'delete_security_group', 'authorize_security_group', - 'authorize_security_group_egress', - 'revoke_security_group', - 'revoke_security_group_egress')) - - -class ObjectClientS3(BotoClientBase): - - def connect_method(self, *args, **kwargs): - return boto.connect_s3(*args, **kwargs) - - def __init__(self, identity_client): - super(ObjectClientS3, self).__init__(identity_client) - insecure_ssl = CONF.identity.disable_ssl_certificate_validation - purl = urlparse.urlparse(CONF.boto.s3_url) - port = purl.port - if port is None: - if purl.scheme is not "https": - port = 80 - else: - port = 443 - else: - port = int(port) - self.connection_data.update({"is_secure": purl.scheme == "https", - "validate_certs": not insecure_ssl, - "host": purl.hostname, - "port": port, - "calling_format": boto.s3.connection. - OrdinaryCallingFormat()}) - - ALLOWED_METHODS = set(('create_bucket', 'delete_bucket', 'generate_url', - 'get_all_buckets', 'get_bucket', 'delete_key', - 'lookup')) diff --git a/test/tempest/tempest/services/compute/__init__.py b/test/tempest/tempest/services/compute/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/compute/json/__init__.py b/test/tempest/tempest/services/compute/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/compute/json/agents_client.py b/test/tempest/tempest/services/compute/json/agents_client.py deleted file mode 100644 index 403437dd..00000000 --- a/test/tempest/tempest/services/compute/json/agents_client.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2014 NEC 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 json -import urllib - -from tempest.api_schema.response.compute.v2_1 import agents as schema -from tempest.common import service_client - - -class AgentsClientJSON(service_client.ServiceClient): - """ - Tests Agents API - """ - - def list_agents(self, params=None): - """List all agent builds.""" - url = 'os-agents' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_agents, resp, body) - return service_client.ResponseBodyList(resp, body['agents']) - - def create_agent(self, **kwargs): - """Create an agent build.""" - post_body = json.dumps({'agent': kwargs}) - resp, body = self.post('os-agents', post_body) - body = json.loads(body) - self.validate_response(schema.create_agent, resp, body) - return service_client.ResponseBody(resp, body['agent']) - - def delete_agent(self, agent_id): - """Delete an existing agent build.""" - resp, body = self.delete("os-agents/%s" % str(agent_id)) - self.validate_response(schema.delete_agent, resp, body) - return service_client.ResponseBody(resp, body) - - def update_agent(self, agent_id, **kwargs): - """Update an agent build.""" - put_body = json.dumps({'para': kwargs}) - resp, body = self.put('os-agents/%s' % str(agent_id), put_body) - return service_client.ResponseBody(resp, self._parse_resp(body)) diff --git a/test/tempest/tempest/services/compute/json/aggregates_client.py b/test/tempest/tempest/services/compute/json/aggregates_client.py deleted file mode 100644 index 6c02b633..00000000 --- a/test/tempest/tempest/services/compute/json/aggregates_client.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2013 NEC 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 json - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import aggregates as schema -from tempest.common import service_client - - -class AggregatesClientJSON(service_client.ServiceClient): - - def list_aggregates(self): - """Get aggregate list.""" - resp, body = self.get("os-aggregates") - body = json.loads(body) - self.validate_response(schema.list_aggregates, resp, body) - return service_client.ResponseBodyList(resp, body['aggregates']) - - def show_aggregate(self, aggregate_id): - """Get details of the given aggregate.""" - resp, body = self.get("os-aggregates/%s" % str(aggregate_id)) - body = json.loads(body) - self.validate_response(schema.get_aggregate, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) - - def create_aggregate(self, **kwargs): - """Creates a new aggregate.""" - post_body = json.dumps({'aggregate': kwargs}) - resp, body = self.post('os-aggregates', post_body) - - body = json.loads(body) - self.validate_response(schema.create_aggregate, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) - - def update_aggregate(self, aggregate_id, name, availability_zone=None): - """Update a aggregate.""" - put_body = { - 'name': name, - 'availability_zone': availability_zone - } - put_body = json.dumps({'aggregate': put_body}) - resp, body = self.put('os-aggregates/%s' % str(aggregate_id), put_body) - - body = json.loads(body) - self.validate_response(schema.update_aggregate, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) - - def delete_aggregate(self, aggregate_id): - """Deletes the given aggregate.""" - resp, body = self.delete("os-aggregates/%s" % str(aggregate_id)) - self.validate_response(schema.delete_aggregate, resp, body) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - try: - self.show_aggregate(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'aggregate' - - def add_host(self, aggregate_id, host): - """Adds a host to the given aggregate.""" - post_body = { - 'host': host, - } - post_body = json.dumps({'add_host': post_body}) - resp, body = self.post('os-aggregates/%s/action' % aggregate_id, - post_body) - body = json.loads(body) - self.validate_response(schema.aggregate_add_remove_host, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) - - def remove_host(self, aggregate_id, host): - """Removes a host from the given aggregate.""" - post_body = { - 'host': host, - } - post_body = json.dumps({'remove_host': post_body}) - resp, body = self.post('os-aggregates/%s/action' % aggregate_id, - post_body) - body = json.loads(body) - self.validate_response(schema.aggregate_add_remove_host, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) - - def set_metadata(self, aggregate_id, meta): - """Replaces the aggregate's existing metadata with new metadata.""" - post_body = { - 'metadata': meta, - } - post_body = json.dumps({'set_metadata': post_body}) - resp, body = self.post('os-aggregates/%s/action' % aggregate_id, - post_body) - body = json.loads(body) - self.validate_response(schema.aggregate_set_metadata, resp, body) - return service_client.ResponseBody(resp, body['aggregate']) diff --git a/test/tempest/tempest/services/compute/json/availability_zone_client.py b/test/tempest/tempest/services/compute/json/availability_zone_client.py deleted file mode 100644 index 925d79f5..00000000 --- a/test/tempest/tempest/services/compute/json/availability_zone_client.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2013 NEC 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 json - -from tempest.api_schema.response.compute.v2_1 import availability_zone \ - as schema -from tempest.common import service_client - - -class AvailabilityZoneClientJSON(service_client.ServiceClient): - - def list_availability_zones(self, detail=False): - url = 'os-availability-zone' - schema_list = schema.list_availability_zone_list - if detail: - url += '/detail' - schema_list = schema.list_availability_zone_list_detail - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema_list, resp, body) - return service_client.ResponseBodyList(resp, - body['availabilityZoneInfo']) diff --git a/test/tempest/tempest/services/compute/json/baremetal_nodes_client.py b/test/tempest/tempest/services/compute/json/baremetal_nodes_client.py deleted file mode 100644 index e4a4e884..00000000 --- a/test/tempest/tempest/services/compute/json/baremetal_nodes_client.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2015 NEC 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 json -import urllib - -from tempest.api_schema.response.compute import baremetal_nodes as schema -from tempest.common import service_client - - -class BaremetalNodesClientJSON(service_client.ServiceClient): - """ - Tests Baremetal API - """ - - def list_baremetal_nodes(self, params=None): - """List all baremetal nodes.""" - url = 'os-baremetal-nodes' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_baremetal_nodes, resp, body) - return service_client.ResponseBodyList(resp, body['nodes']) - - def show_baremetal_node(self, baremetal_node_id): - """Returns the details of a single baremetal node.""" - url = 'os-baremetal-nodes/%s' % baremetal_node_id - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_baremetal_node, resp, body) - return service_client.ResponseBody(resp, body['node']) diff --git a/test/tempest/tempest/services/compute/json/certificates_client.py b/test/tempest/tempest/services/compute/json/certificates_client.py deleted file mode 100644 index 752a48e7..00000000 --- a/test/tempest/tempest/services/compute/json/certificates_client.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2013 IBM Corp -# 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 json - -from tempest.api_schema.response.compute.v2_1 import certificates as schema -from tempest.common import service_client - - -class CertificatesClientJSON(service_client.ServiceClient): - - def show_certificate(self, id): - url = "os-certificates/%s" % (id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_certificate, resp, body) - return service_client.ResponseBody(resp, body['certificate']) - - def create_certificate(self): - """create certificates.""" - url = "os-certificates" - resp, body = self.post(url, None) - body = json.loads(body) - self.validate_response(schema.create_certificate, resp, body) - return service_client.ResponseBody(resp, body['certificate']) diff --git a/test/tempest/tempest/services/compute/json/extensions_client.py b/test/tempest/tempest/services/compute/json/extensions_client.py deleted file mode 100644 index 265b381e..00000000 --- a/test/tempest/tempest/services/compute/json/extensions_client.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 json - -from tempest.api_schema.response.compute.v2_1 import extensions as schema -from tempest.common import service_client - - -class ExtensionsClientJSON(service_client.ServiceClient): - - def list_extensions(self): - url = 'extensions' - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_extensions, resp, body) - return service_client.ResponseBodyList(resp, body['extensions']) - - def is_enabled(self, extension): - extensions = self.list_extensions() - exts = extensions['extensions'] - return any([e for e in exts if e['name'] == extension]) - - def show_extension(self, extension_alias): - resp, body = self.get('extensions/%s' % extension_alias) - body = json.loads(body) - return service_client.ResponseBody(resp, body['extension']) diff --git a/test/tempest/tempest/services/compute/json/fixed_ips_client.py b/test/tempest/tempest/services/compute/json/fixed_ips_client.py deleted file mode 100644 index 7ba424f1..00000000 --- a/test/tempest/tempest/services/compute/json/fixed_ips_client.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2013 IBM Corp -# 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 json - -from tempest.api_schema.response.compute.v2_1 import fixed_ips as schema -from tempest.common import service_client - - -class FixedIPsClientJSON(service_client.ServiceClient): - - def get_fixed_ip_details(self, fixed_ip): - url = "os-fixed-ips/%s" % (fixed_ip) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_fixed_ip, resp, body) - return service_client.ResponseBody(resp, body['fixed_ip']) - - def reserve_fixed_ip(self, ip, body): - """This reserves and unreserves fixed ips.""" - url = "os-fixed-ips/%s/action" % (ip) - resp, body = self.post(url, json.dumps(body)) - self.validate_response(schema.reserve_fixed_ip, resp, body) - return service_client.ResponseBody(resp) diff --git a/test/tempest/tempest/services/compute/json/flavors_client.py b/test/tempest/tempest/services/compute/json/flavors_client.py deleted file mode 100644 index 2de43cf2..00000000 --- a/test/tempest/tempest/services/compute/json/flavors_client.py +++ /dev/null @@ -1,176 +0,0 @@ -# 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 json -import urllib - -from tempest.api_schema.response.compute import flavors_access as schema_access -from tempest.api_schema.response.compute import flavors_extra_specs \ - as schema_extra_specs -from tempest.api_schema.response.compute.v2_1 import flavors as schema -from tempest.common import service_client - - -class FlavorsClientJSON(service_client.ServiceClient): - - def list_flavors(self, params=None): - url = 'flavors' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_flavors, resp, body) - return service_client.ResponseBodyList(resp, body['flavors']) - - def list_flavors_with_detail(self, params=None): - url = 'flavors/detail' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_flavors_details, resp, body) - return service_client.ResponseBodyList(resp, body['flavors']) - - def get_flavor_details(self, flavor_id): - resp, body = self.get("flavors/%s" % str(flavor_id)) - body = json.loads(body) - self.validate_response(schema.create_get_flavor_details, resp, body) - return service_client.ResponseBody(resp, body['flavor']) - - def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs): - """Creates a new flavor or instance type.""" - post_body = { - 'name': name, - 'ram': ram, - 'vcpus': vcpus, - 'disk': disk, - 'id': flavor_id, - } - if kwargs.get('ephemeral'): - post_body['OS-FLV-EXT-DATA:ephemeral'] = kwargs.get('ephemeral') - if kwargs.get('swap'): - post_body['swap'] = kwargs.get('swap') - if kwargs.get('rxtx'): - post_body['rxtx_factor'] = kwargs.get('rxtx') - if kwargs.get('is_public'): - post_body['os-flavor-access:is_public'] = kwargs.get('is_public') - post_body = json.dumps({'flavor': post_body}) - resp, body = self.post('flavors', post_body) - - body = json.loads(body) - self.validate_response(schema.create_get_flavor_details, resp, body) - return service_client.ResponseBody(resp, body['flavor']) - - def delete_flavor(self, flavor_id): - """Deletes the given flavor.""" - resp, body = self.delete("flavors/{0}".format(flavor_id)) - self.validate_response(schema.delete_flavor, resp, body) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - # Did not use get_flavor_details(id) for verification as it gives - # 200 ok even for deleted id. LP #981263 - # we can remove the loop here and use get by ID when bug gets sortedout - flavors = self.list_flavors_with_detail() - for flavor in flavors: - if flavor['id'] == id: - return False - return True - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'flavor' - - def set_flavor_extra_spec(self, flavor_id, specs): - """Sets extra Specs to the mentioned flavor.""" - post_body = json.dumps({'extra_specs': specs}) - resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id, - post_body) - body = json.loads(body) - self.validate_response(schema_extra_specs.flavor_extra_specs, - resp, body) - return service_client.ResponseBody(resp, body['extra_specs']) - - def get_flavor_extra_spec(self, flavor_id): - """Gets extra Specs details of the mentioned flavor.""" - resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id) - body = json.loads(body) - self.validate_response(schema_extra_specs.flavor_extra_specs, - resp, body) - return service_client.ResponseBody(resp, body['extra_specs']) - - def get_flavor_extra_spec_with_key(self, flavor_id, key): - """Gets extra Specs key-value of the mentioned flavor and key.""" - resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id), - key)) - body = json.loads(body) - self.validate_response(schema_extra_specs.flavor_extra_specs_key, - resp, body) - return service_client.ResponseBody(resp, body) - - def update_flavor_extra_spec(self, flavor_id, key, **kwargs): - """Update specified extra Specs of the mentioned flavor and key.""" - resp, body = self.put('flavors/%s/os-extra_specs/%s' % - (flavor_id, key), json.dumps(kwargs)) - body = json.loads(body) - self.validate_response(schema_extra_specs.flavor_extra_specs_key, - resp, body) - return service_client.ResponseBody(resp, body) - - def unset_flavor_extra_spec(self, flavor_id, key): - """Unsets extra Specs from the mentioned flavor.""" - resp, body = self.delete('flavors/%s/os-extra_specs/%s' % - (str(flavor_id), key)) - self.validate_response(schema.unset_flavor_extra_specs, resp, body) - return service_client.ResponseBody(resp, body) - - def list_flavor_access(self, flavor_id): - """Gets flavor access information given the flavor id.""" - resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id) - body = json.loads(body) - self.validate_response(schema_access.add_remove_list_flavor_access, - resp, body) - return service_client.ResponseBodyList(resp, body['flavor_access']) - - def add_flavor_access(self, flavor_id, tenant_id): - """Add flavor access for the specified tenant.""" - post_body = { - 'addTenantAccess': { - 'tenant': tenant_id - } - } - post_body = json.dumps(post_body) - resp, body = self.post('flavors/%s/action' % flavor_id, post_body) - body = json.loads(body) - self.validate_response(schema_access.add_remove_list_flavor_access, - resp, body) - return service_client.ResponseBodyList(resp, body['flavor_access']) - - def remove_flavor_access(self, flavor_id, tenant_id): - """Remove flavor access from the specified tenant.""" - post_body = { - 'removeTenantAccess': { - 'tenant': tenant_id - } - } - post_body = json.dumps(post_body) - resp, body = self.post('flavors/%s/action' % flavor_id, post_body) - body = json.loads(body) - self.validate_response(schema_access.add_remove_list_flavor_access, - resp, body) - return service_client.ResponseBody(resp, body['flavor_access']) diff --git a/test/tempest/tempest/services/compute/json/floating_ips_client.py b/test/tempest/tempest/services/compute/json/floating_ips_client.py deleted file mode 100644 index 5bad527b..00000000 --- a/test/tempest/tempest/services/compute/json/floating_ips_client.py +++ /dev/null @@ -1,142 +0,0 @@ -# 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 json -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import floating_ips as schema -from tempest.common import service_client - - -class FloatingIPsClientJSON(service_client.ServiceClient): - - def list_floating_ips(self, params=None): - """Returns a list of all floating IPs filtered by any parameters.""" - url = 'os-floating-ips' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_floating_ips, resp, body) - return service_client.ResponseBodyList(resp, body['floating_ips']) - - def get_floating_ip_details(self, floating_ip_id): - """Get the details of a floating IP.""" - url = "os-floating-ips/%s" % str(floating_ip_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.floating_ip, resp, body) - return service_client.ResponseBody(resp, body['floating_ip']) - - def create_floating_ip(self, pool_name=None): - """Allocate a floating IP to the project.""" - url = 'os-floating-ips' - post_body = {'pool': pool_name} - post_body = json.dumps(post_body) - resp, body = self.post(url, post_body) - body = json.loads(body) - self.validate_response(schema.floating_ip, resp, body) - return service_client.ResponseBody(resp, body['floating_ip']) - - def delete_floating_ip(self, floating_ip_id): - """Deletes the provided floating IP from the project.""" - url = "os-floating-ips/%s" % str(floating_ip_id) - resp, body = self.delete(url) - self.validate_response(schema.add_remove_floating_ip, resp, body) - return service_client.ResponseBody(resp, body) - - def associate_floating_ip_to_server(self, floating_ip, server_id): - """Associate the provided floating IP to a specific server.""" - url = "servers/%s/action" % str(server_id) - post_body = { - 'addFloatingIp': { - 'address': floating_ip, - } - } - - post_body = json.dumps(post_body) - resp, body = self.post(url, post_body) - self.validate_response(schema.add_remove_floating_ip, resp, body) - return service_client.ResponseBody(resp, body) - - def disassociate_floating_ip_from_server(self, floating_ip, server_id): - """Disassociate the provided floating IP from a specific server.""" - url = "servers/%s/action" % str(server_id) - post_body = { - 'removeFloatingIp': { - 'address': floating_ip, - } - } - - post_body = json.dumps(post_body) - resp, body = self.post(url, post_body) - self.validate_response(schema.add_remove_floating_ip, resp, body) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_floating_ip_details(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'floating_ip' - - def list_floating_ip_pools(self, params=None): - """Returns a list of all floating IP Pools.""" - url = 'os-floating-ip-pools' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.floating_ip_pools, resp, body) - return service_client.ResponseBodyList(resp, body['floating_ip_pools']) - - def create_floating_ips_bulk(self, ip_range, pool, interface): - """Allocate floating IPs in bulk.""" - post_body = { - 'ip_range': ip_range, - 'pool': pool, - 'interface': interface - } - post_body = json.dumps({'floating_ips_bulk_create': post_body}) - resp, body = self.post('os-floating-ips-bulk', post_body) - body = json.loads(body) - self.validate_response(schema.create_floating_ips_bulk, resp, body) - return service_client.ResponseBody(resp, - body['floating_ips_bulk_create']) - - def list_floating_ips_bulk(self): - """Returns a list of all floating IPs bulk.""" - resp, body = self.get('os-floating-ips-bulk') - body = json.loads(body) - self.validate_response(schema.list_floating_ips_bulk, resp, body) - return service_client.ResponseBodyList(resp, body['floating_ip_info']) - - def delete_floating_ips_bulk(self, ip_range): - """Deletes the provided floating IPs bulk.""" - post_body = json.dumps({'ip_range': ip_range}) - resp, body = self.put('os-floating-ips-bulk/delete', post_body) - body = json.loads(body) - self.validate_response(schema.delete_floating_ips_bulk, resp, body) - data = body['floating_ips_bulk_delete'] - return service_client.ResponseBodyData(resp, data) diff --git a/test/tempest/tempest/services/compute/json/hosts_client.py b/test/tempest/tempest/services/compute/json/hosts_client.py deleted file mode 100644 index 088e6955..00000000 --- a/test/tempest/tempest/services/compute/json/hosts_client.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# 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 json -import urllib - -from tempest.api_schema.response.compute.v2_1 import hosts as schema -from tempest.common import service_client - - -class HostsClientJSON(service_client.ServiceClient): - - def list_hosts(self, params=None): - """Lists all hosts.""" - - url = 'os-hosts' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_hosts, resp, body) - return service_client.ResponseBodyList(resp, body['hosts']) - - def show_host_detail(self, hostname): - """Show detail information for the host.""" - - resp, body = self.get("os-hosts/%s" % str(hostname)) - body = json.loads(body) - self.validate_response(schema.get_host_detail, resp, body) - return service_client.ResponseBodyList(resp, body['host']) - - def update_host(self, hostname, **kwargs): - """Update a host.""" - - request_body = { - 'status': None, - 'maintenance_mode': None, - } - request_body.update(**kwargs) - request_body = json.dumps(request_body) - - resp, body = self.put("os-hosts/%s" % str(hostname), request_body) - body = json.loads(body) - self.validate_response(schema.update_host, resp, body) - return service_client.ResponseBody(resp, body) - - def startup_host(self, hostname): - """Startup a host.""" - - resp, body = self.get("os-hosts/%s/startup" % str(hostname)) - body = json.loads(body) - self.validate_response(schema.startup_host, resp, body) - return service_client.ResponseBody(resp, body['host']) - - def shutdown_host(self, hostname): - """Shutdown a host.""" - - resp, body = self.get("os-hosts/%s/shutdown" % str(hostname)) - body = json.loads(body) - self.validate_response(schema.shutdown_host, resp, body) - return service_client.ResponseBody(resp, body['host']) - - def reboot_host(self, hostname): - """reboot a host.""" - - resp, body = self.get("os-hosts/%s/reboot" % str(hostname)) - body = json.loads(body) - self.validate_response(schema.reboot_host, resp, body) - return service_client.ResponseBody(resp, body['host']) diff --git a/test/tempest/tempest/services/compute/json/hypervisor_client.py b/test/tempest/tempest/services/compute/json/hypervisor_client.py deleted file mode 100644 index 49ac2669..00000000 --- a/test/tempest/tempest/services/compute/json/hypervisor_client.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2013 IBM 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 json - -from tempest.api_schema.response.compute.v2_1 import hypervisors as schema -from tempest.common import service_client - - -class HypervisorClientJSON(service_client.ServiceClient): - - def get_hypervisor_list(self): - """List hypervisors information.""" - resp, body = self.get('os-hypervisors') - body = json.loads(body) - self.validate_response(schema.list_search_hypervisors, resp, body) - return service_client.ResponseBodyList(resp, body['hypervisors']) - - def get_hypervisor_list_details(self): - """Show detailed hypervisors information.""" - resp, body = self.get('os-hypervisors/detail') - body = json.loads(body) - self.validate_response(schema.list_hypervisors_detail, resp, body) - return service_client.ResponseBodyList(resp, body['hypervisors']) - - def get_hypervisor_show_details(self, hyper_id): - """Display the details of the specified hypervisor.""" - resp, body = self.get('os-hypervisors/%s' % hyper_id) - body = json.loads(body) - self.validate_response(schema.get_hypervisor, resp, body) - return service_client.ResponseBody(resp, body['hypervisor']) - - def get_hypervisor_servers(self, hyper_name): - """List instances belonging to the specified hypervisor.""" - resp, body = self.get('os-hypervisors/%s/servers' % hyper_name) - body = json.loads(body) - self.validate_response(schema.get_hypervisors_servers, resp, body) - return service_client.ResponseBodyList(resp, body['hypervisors']) - - def get_hypervisor_stats(self): - """Get hypervisor statistics over all compute nodes.""" - resp, body = self.get('os-hypervisors/statistics') - body = json.loads(body) - self.validate_response(schema.get_hypervisor_statistics, resp, body) - return service_client.ResponseBody(resp, body['hypervisor_statistics']) - - def get_hypervisor_uptime(self, hyper_id): - """Display the uptime of the specified hypervisor.""" - resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id) - body = json.loads(body) - self.validate_response(schema.get_hypervisor_uptime, resp, body) - return service_client.ResponseBody(resp, body['hypervisor']) - - def search_hypervisor(self, hyper_name): - """Search specified hypervisor.""" - resp, body = self.get('os-hypervisors/%s/search' % hyper_name) - body = json.loads(body) - self.validate_response(schema.list_search_hypervisors, resp, body) - return service_client.ResponseBodyList(resp, body['hypervisors']) diff --git a/test/tempest/tempest/services/compute/json/images_client.py b/test/tempest/tempest/services/compute/json/images_client.py deleted file mode 100644 index 1223fef7..00000000 --- a/test/tempest/tempest/services/compute/json/images_client.py +++ /dev/null @@ -1,142 +0,0 @@ -# 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 json -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import images as schema -from tempest.common import service_client -from tempest.common import waiters - - -class ImagesClientJSON(service_client.ServiceClient): - - def create_image(self, server_id, name, meta=None): - """Creates an image of the original server.""" - - post_body = { - 'createImage': { - 'name': name, - } - } - - if meta is not None: - post_body['createImage']['metadata'] = meta - - post_body = json.dumps(post_body) - resp, body = self.post('servers/%s/action' % str(server_id), - post_body) - self.validate_response(schema.create_image, resp, body) - return service_client.ResponseBody(resp, body) - - def list_images(self, params=None): - """Returns a list of all images filtered by any parameters.""" - url = 'images' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_images, resp, body) - return service_client.ResponseBodyList(resp, body['images']) - - def list_images_with_detail(self, params=None): - """Returns a detailed list of images filtered by any parameters.""" - url = 'images/detail' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_images_details, resp, body) - return service_client.ResponseBodyList(resp, body['images']) - - def get_image(self, image_id): - """Returns the details of a single image.""" - resp, body = self.get("images/%s" % str(image_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - self.validate_response(schema.get_image, resp, body) - return service_client.ResponseBody(resp, body['image']) - - def delete_image(self, image_id): - """Deletes the provided image.""" - resp, body = self.delete("images/%s" % str(image_id)) - self.validate_response(schema.delete, resp, body) - return service_client.ResponseBody(resp, body) - - def wait_for_image_status(self, image_id, status): - """Waits for an image to reach a given status.""" - waiters.wait_for_image_status(self, image_id, status) - - def list_image_metadata(self, image_id): - """Lists all metadata items for an image.""" - resp, body = self.get("images/%s/metadata" % str(image_id)) - body = json.loads(body) - self.validate_response(schema.image_metadata, resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def set_image_metadata(self, image_id, meta): - """Sets the metadata for an image.""" - post_body = json.dumps({'metadata': meta}) - resp, body = self.put('images/%s/metadata' % str(image_id), post_body) - body = json.loads(body) - self.validate_response(schema.image_metadata, resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def update_image_metadata(self, image_id, meta): - """Updates the metadata for an image.""" - post_body = json.dumps({'metadata': meta}) - resp, body = self.post('images/%s/metadata' % str(image_id), post_body) - body = json.loads(body) - self.validate_response(schema.image_metadata, resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def get_image_metadata_item(self, image_id, key): - """Returns the value for a specific image metadata key.""" - resp, body = self.get("images/%s/metadata/%s" % (str(image_id), key)) - body = json.loads(body) - self.validate_response(schema.image_meta_item, resp, body) - return service_client.ResponseBody(resp, body['meta']) - - def set_image_metadata_item(self, image_id, key, meta): - """Sets the value for a specific image metadata key.""" - post_body = json.dumps({'meta': meta}) - resp, body = self.put('images/%s/metadata/%s' % (str(image_id), key), - post_body) - body = json.loads(body) - self.validate_response(schema.image_meta_item, resp, body) - return service_client.ResponseBody(resp, body['meta']) - - def delete_image_metadata_item(self, image_id, key): - """Deletes a single image metadata key/value pair.""" - resp, body = self.delete("images/%s/metadata/%s" % - (str(image_id), key)) - self.validate_response(schema.delete, resp, body) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_image(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'image' diff --git a/test/tempest/tempest/services/compute/json/instance_usage_audit_log_client.py b/test/tempest/tempest/services/compute/json/instance_usage_audit_log_client.py deleted file mode 100644 index 33ba76fd..00000000 --- a/test/tempest/tempest/services/compute/json/instance_usage_audit_log_client.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2013 IBM 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 json - -from tempest.api_schema.response.compute.v2_1 import \ - instance_usage_audit_logs as schema -from tempest.common import service_client - - -class InstanceUsagesAuditLogClientJSON(service_client.ServiceClient): - - def list_instance_usage_audit_logs(self): - url = 'os-instance_usage_audit_log' - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_instance_usage_audit_log, - resp, body) - return service_client.ResponseBody(resp, - body["instance_usage_audit_logs"]) - - def get_instance_usage_audit_log(self, time_before): - url = 'os-instance_usage_audit_log/%s' % time_before - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_instance_usage_audit_log, resp, body) - return service_client.ResponseBody(resp, - body["instance_usage_audit_log"]) diff --git a/test/tempest/tempest/services/compute/json/interfaces_client.py b/test/tempest/tempest/services/compute/json/interfaces_client.py deleted file mode 100644 index 223e90ba..00000000 --- a/test/tempest/tempest/services/compute/json/interfaces_client.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 json -import time - -from tempest.api_schema.response.compute.v2_1 import interfaces as schema -from tempest.api_schema.response.compute.v2_1 import servers as servers_schema -from tempest.common import service_client -from tempest import exceptions - - -class InterfacesClientJSON(service_client.ServiceClient): - - def list_interfaces(self, server): - resp, body = self.get('servers/%s/os-interface' % server) - body = json.loads(body) - self.validate_response(schema.list_interfaces, resp, body) - return service_client.ResponseBodyList(resp, - body['interfaceAttachments']) - - def create_interface(self, server, port_id=None, network_id=None, - fixed_ip=None): - post_body = dict(interfaceAttachment=dict()) - if port_id: - post_body['interfaceAttachment']['port_id'] = port_id - if network_id: - post_body['interfaceAttachment']['net_id'] = network_id - if fixed_ip: - fip = dict(ip_address=fixed_ip) - post_body['interfaceAttachment']['fixed_ips'] = [fip] - post_body = json.dumps(post_body) - resp, body = self.post('servers/%s/os-interface' % server, - body=post_body) - body = json.loads(body) - self.validate_response(schema.get_create_interfaces, resp, body) - return service_client.ResponseBody(resp, body['interfaceAttachment']) - - def show_interface(self, server, port_id): - resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id)) - body = json.loads(body) - self.validate_response(schema.get_create_interfaces, resp, body) - return service_client.ResponseBody(resp, body['interfaceAttachment']) - - def delete_interface(self, server, port_id): - resp, body = self.delete('servers/%s/os-interface/%s' % (server, - port_id)) - self.validate_response(schema.delete_interface, resp, body) - return service_client.ResponseBody(resp, body) - - def wait_for_interface_status(self, server, port_id, status): - """Waits for a interface to reach a given status.""" - body = self.show_interface(server, port_id) - interface_status = body['port_state'] - start = int(time.time()) - - while(interface_status != status): - time.sleep(self.build_interval) - body = self.show_interface(server, port_id) - interface_status = body['port_state'] - - timed_out = int(time.time()) - start >= self.build_timeout - - if interface_status != status and timed_out: - message = ('Interface %s failed to reach %s status ' - '(current %s) within the required time (%s s).' % - (port_id, status, interface_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - - return body - - def add_fixed_ip(self, server_id, network_id): - """Add a fixed IP to input server instance.""" - post_body = json.dumps({ - 'addFixedIp': { - 'networkId': network_id - } - }) - resp, body = self.post('servers/%s/action' % str(server_id), - post_body) - self.validate_response(servers_schema.server_actions_common_schema, - resp, body) - return service_client.ResponseBody(resp, body) - - def remove_fixed_ip(self, server_id, ip_address): - """Remove input fixed IP from input server instance.""" - post_body = json.dumps({ - 'removeFixedIp': { - 'address': ip_address - } - }) - resp, body = self.post('servers/%s/action' % str(server_id), - post_body) - self.validate_response(servers_schema.server_actions_common_schema, - resp, body) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/compute/json/keypairs_client.py b/test/tempest/tempest/services/compute/json/keypairs_client.py deleted file mode 100644 index 7fe335bf..00000000 --- a/test/tempest/tempest/services/compute/json/keypairs_client.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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 json - -from tempest.api_schema.response.compute.v2_1 import keypairs as schema -from tempest.common import service_client - - -class KeyPairsClientJSON(service_client.ServiceClient): - - def list_keypairs(self): - resp, body = self.get("os-keypairs") - body = json.loads(body) - # Each returned keypair is embedded within an unnecessary 'keypair' - # element which is a deviation from other resources like floating-ips, - # servers, etc. A bug? - # For now we shall adhere to the spec, but the spec for keypairs - # is yet to be found - self.validate_response(schema.list_keypairs, resp, body) - return service_client.ResponseBodyList(resp, body['keypairs']) - - def get_keypair(self, key_name): - resp, body = self.get("os-keypairs/%s" % str(key_name)) - body = json.loads(body) - self.validate_response(schema.get_keypair, resp, body) - return service_client.ResponseBody(resp, body['keypair']) - - def create_keypair(self, name, pub_key=None): - post_body = {'keypair': {'name': name}} - if pub_key: - post_body['keypair']['public_key'] = pub_key - post_body = json.dumps(post_body) - resp, body = self.post("os-keypairs", body=post_body) - body = json.loads(body) - self.validate_response(schema.create_keypair, resp, body) - return service_client.ResponseBody(resp, body['keypair']) - - def delete_keypair(self, key_name): - resp, body = self.delete("os-keypairs/%s" % str(key_name)) - self.validate_response(schema.delete_keypair, resp, body) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/compute/json/limits_client.py b/test/tempest/tempest/services/compute/json/limits_client.py deleted file mode 100644 index d2aaec6f..00000000 --- a/test/tempest/tempest/services/compute/json/limits_client.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 json - -from tempest.api_schema.response.compute.v2_1 import limits as schema -from tempest.common import service_client - - -class LimitsClientJSON(service_client.ServiceClient): - - def get_absolute_limits(self): - resp, body = self.get("limits") - body = json.loads(body) - self.validate_response(schema.get_limit, resp, body) - return service_client.ResponseBody(resp, body['limits']['absolute']) - - def get_specific_absolute_limit(self, absolute_limit): - resp, body = self.get("limits") - body = json.loads(body) - self.validate_response(schema.get_limit, resp, body) - if absolute_limit not in body['limits']['absolute']: - return None - else: - return body['limits']['absolute'][absolute_limit] diff --git a/test/tempest/tempest/services/compute/json/migrations_client.py b/test/tempest/tempest/services/compute/json/migrations_client.py deleted file mode 100644 index a65b655f..00000000 --- a/test/tempest/tempest/services/compute/json/migrations_client.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2014 NEC Corporation. -# -# 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 json -import urllib - -from tempest.api_schema.response.compute import migrations as schema -from tempest.common import service_client - - -class MigrationsClientJSON(service_client.ServiceClient): - - def list_migrations(self, params=None): - """Lists all migrations.""" - - url = 'os-migrations' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_migrations, resp, body) - return service_client.ResponseBodyList(resp, body['migrations']) diff --git a/test/tempest/tempest/services/compute/json/networks_client.py b/test/tempest/tempest/services/compute/json/networks_client.py deleted file mode 100644 index 0ae0920a..00000000 --- a/test/tempest/tempest/services/compute/json/networks_client.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 json - -from tempest.common import service_client - - -class NetworksClientJSON(service_client.ServiceClient): - - def list_networks(self, name=None): - resp, body = self.get("os-networks") - body = json.loads(body) - self.expected_success(200, resp.status) - if name: - networks = [n for n in body['networks'] if n['label'] == name] - else: - networks = body['networks'] - return service_client.ResponseBodyList(resp, networks) - - def get_network(self, network_id): - resp, body = self.get("os-networks/%s" % str(network_id)) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['network']) diff --git a/test/tempest/tempest/services/compute/json/quotas_client.py b/test/tempest/tempest/services/compute/json/quotas_client.py deleted file mode 100644 index 6e38c47e..00000000 --- a/test/tempest/tempest/services/compute/json/quotas_client.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2012 NTT Data -# 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 json - -from tempest.api_schema.response.compute.v2_1\ - import quota_classes as classes_schema -from tempest.api_schema.response.compute.v2_1 import quotas as schema -from tempest.common import service_client - - -class QuotasClientJSON(service_client.ServiceClient): - - def get_quota_set(self, tenant_id, user_id=None): - """List the quota set for a tenant.""" - - url = 'os-quota-sets/%s' % str(tenant_id) - if user_id: - url += '?user_id=%s' % str(user_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_quota_set, resp, body) - return service_client.ResponseBody(resp, body['quota_set']) - - def get_default_quota_set(self, tenant_id): - """List the default quota set for a tenant.""" - - url = 'os-quota-sets/%s/defaults' % str(tenant_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_quota_set, resp, body) - return service_client.ResponseBody(resp, body['quota_set']) - - def update_quota_set(self, tenant_id, user_id=None, - force=None, injected_file_content_bytes=None, - metadata_items=None, ram=None, floating_ips=None, - fixed_ips=None, key_pairs=None, instances=None, - security_group_rules=None, injected_files=None, - cores=None, injected_file_path_bytes=None, - security_groups=None): - """ - Updates the tenant's quota limits for one or more resources - """ - post_body = {} - - if force is not None: - post_body['force'] = force - - if injected_file_content_bytes is not None: - post_body['injected_file_content_bytes'] = \ - injected_file_content_bytes - - if metadata_items is not None: - post_body['metadata_items'] = metadata_items - - if ram is not None: - post_body['ram'] = ram - - if floating_ips is not None: - post_body['floating_ips'] = floating_ips - - if fixed_ips is not None: - post_body['fixed_ips'] = fixed_ips - - if key_pairs is not None: - post_body['key_pairs'] = key_pairs - - if instances is not None: - post_body['instances'] = instances - - if security_group_rules is not None: - post_body['security_group_rules'] = security_group_rules - - if injected_files is not None: - post_body['injected_files'] = injected_files - - if cores is not None: - post_body['cores'] = cores - - if injected_file_path_bytes is not None: - post_body['injected_file_path_bytes'] = injected_file_path_bytes - - if security_groups is not None: - post_body['security_groups'] = security_groups - - post_body = json.dumps({'quota_set': post_body}) - - if user_id: - resp, body = self.put('os-quota-sets/%s?user_id=%s' % - (str(tenant_id), str(user_id)), post_body) - else: - resp, body = self.put('os-quota-sets/%s' % str(tenant_id), - post_body) - - body = json.loads(body) - self.validate_response(schema.update_quota_set, resp, body) - return service_client.ResponseBody(resp, body['quota_set']) - - def delete_quota_set(self, tenant_id): - """Delete the tenant's quota set.""" - resp, body = self.delete('os-quota-sets/%s' % str(tenant_id)) - self.validate_response(schema.delete_quota, resp, body) - return service_client.ResponseBody(resp, body) - - -class QuotaClassesClientJSON(service_client.ServiceClient): - - def get_quota_class_set(self, quota_class_id): - """List the quota class set for a quota class.""" - - url = 'os-quota-class-sets/%s' % str(quota_class_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(classes_schema.get_quota_class_set, resp, body) - return service_client.ResponseBody(resp, body['quota_class_set']) - - def update_quota_class_set(self, quota_class_id, **kwargs): - """ - Updates the quota class's limits for one or more resources. - """ - post_body = json.dumps({'quota_class_set': kwargs}) - - resp, body = self.put('os-quota-class-sets/%s' % str(quota_class_id), - post_body) - - body = json.loads(body) - self.validate_response(classes_schema.update_quota_class_set, - resp, body) - return service_client.ResponseBody(resp, body['quota_class_set']) diff --git a/test/tempest/tempest/services/compute/json/security_group_default_rules_client.py b/test/tempest/tempest/services/compute/json/security_group_default_rules_client.py deleted file mode 100644 index 3bf3263c..00000000 --- a/test/tempest/tempest/services/compute/json/security_group_default_rules_client.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2014 NEC 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 json - -from tempest.api_schema.response.compute.v2_1 import \ - security_group_default_rule as schema -from tempest.common import service_client - - -class SecurityGroupDefaultRulesClientJSON(service_client.ServiceClient): - - def create_security_default_group_rule(self, ip_protocol, from_port, - to_port, **kwargs): - """ - Creating security group default rules. - ip_protocol : ip_protocol (icmp, tcp, udp). - from_port: Port at start of range. - to_port : Port at end of range. - cidr : CIDR for address range. - """ - post_body = { - 'ip_protocol': ip_protocol, - 'from_port': from_port, - 'to_port': to_port, - 'cidr': kwargs.get('cidr'), - } - post_body = json.dumps({'security_group_default_rule': post_body}) - url = 'os-security-group-default-rules' - resp, body = self.post(url, post_body) - body = json.loads(body) - self.validate_response(schema.create_get_security_group_default_rule, - resp, body) - rule = body['security_group_default_rule'] - return service_client.ResponseBody(resp, rule) - - def delete_security_group_default_rule(self, - security_group_default_rule_id): - """Deletes the provided Security Group default rule.""" - resp, body = self.delete('os-security-group-default-rules/%s' % str( - security_group_default_rule_id)) - self.validate_response(schema.delete_security_group_default_rule, - resp, body) - return service_client.ResponseBody(resp, body) - - def list_security_group_default_rules(self): - """List all Security Group default rules.""" - resp, body = self.get('os-security-group-default-rules') - body = json.loads(body) - self.validate_response(schema.list_security_group_default_rules, - resp, body) - rules = body['security_group_default_rules'] - return service_client.ResponseBodyList(resp, rules) - - def get_security_group_default_rule(self, security_group_default_rule_id): - """Return the details of provided Security Group default rule.""" - resp, body = self.get('os-security-group-default-rules/%s' % str( - security_group_default_rule_id)) - body = json.loads(body) - self.validate_response(schema.create_get_security_group_default_rule, - resp, body) - rule = body['security_group_default_rule'] - return service_client.ResponseBody(resp, rule) diff --git a/test/tempest/tempest/services/compute/json/security_groups_client.py b/test/tempest/tempest/services/compute/json/security_groups_client.py deleted file mode 100644 index d8c8d633..00000000 --- a/test/tempest/tempest/services/compute/json/security_groups_client.py +++ /dev/null @@ -1,144 +0,0 @@ -# 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 json -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import security_groups as schema -from tempest.common import service_client - - -class SecurityGroupsClientJSON(service_client.ServiceClient): - - def list_security_groups(self, params=None): - """List all security groups for a user.""" - - url = 'os-security-groups' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_security_groups, resp, body) - return service_client.ResponseBodyList(resp, body['security_groups']) - - def get_security_group(self, security_group_id): - """Get the details of a Security Group.""" - url = "os-security-groups/%s" % str(security_group_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_security_group, resp, body) - return service_client.ResponseBody(resp, body['security_group']) - - def create_security_group(self, name, description): - """ - Creates a new security group. - name (Required): Name of security group. - description (Required): Description of security group. - """ - post_body = { - 'name': name, - 'description': description, - } - post_body = json.dumps({'security_group': post_body}) - resp, body = self.post('os-security-groups', post_body) - body = json.loads(body) - self.validate_response(schema.get_security_group, resp, body) - return service_client.ResponseBody(resp, body['security_group']) - - def update_security_group(self, security_group_id, name=None, - description=None): - """ - Update a security group. - security_group_id: a security_group to update - name: new name of security group - description: new description of security group - """ - post_body = {} - if name: - post_body['name'] = name - if description: - post_body['description'] = description - post_body = json.dumps({'security_group': post_body}) - resp, body = self.put('os-security-groups/%s' % str(security_group_id), - post_body) - body = json.loads(body) - self.validate_response(schema.update_security_group, resp, body) - return service_client.ResponseBody(resp, body['security_group']) - - def delete_security_group(self, security_group_id): - """Deletes the provided Security Group.""" - resp, body = self.delete( - 'os-security-groups/%s' % str(security_group_id)) - self.validate_response(schema.delete_security_group, resp, body) - return service_client.ResponseBody(resp, body) - - def create_security_group_rule(self, parent_group_id, ip_proto, from_port, - to_port, **kwargs): - """ - Creating a new security group rules. - parent_group_id :ID of Security group - ip_protocol : ip_proto (icmp, tcp, udp). - from_port: Port at start of range. - to_port : Port at end of range. - Following optional keyword arguments are accepted: - cidr : CIDR for address range. - group_id : ID of the Source group - """ - post_body = { - 'parent_group_id': parent_group_id, - 'ip_protocol': ip_proto, - 'from_port': from_port, - 'to_port': to_port, - 'cidr': kwargs.get('cidr'), - 'group_id': kwargs.get('group_id'), - } - post_body = json.dumps({'security_group_rule': post_body}) - url = 'os-security-group-rules' - resp, body = self.post(url, post_body) - body = json.loads(body) - self.validate_response(schema.create_security_group_rule, resp, body) - return service_client.ResponseBody(resp, body['security_group_rule']) - - def delete_security_group_rule(self, group_rule_id): - """Deletes the provided Security Group rule.""" - resp, body = self.delete('os-security-group-rules/%s' % - str(group_rule_id)) - self.validate_response(schema.delete_security_group_rule, resp, body) - return service_client.ResponseBody(resp, body) - - def list_security_group_rules(self, security_group_id): - """List all rules for a security group.""" - resp, body = self.get('os-security-groups') - body = json.loads(body) - self.validate_response(schema.list_security_groups, resp, body) - for sg in body['security_groups']: - if sg['id'] == security_group_id: - return service_client.ResponseBodyList(resp, sg['rules']) - raise lib_exc.NotFound('No such Security Group') - - def is_resource_deleted(self, id): - try: - self.get_security_group(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'security_group' diff --git a/test/tempest/tempest/services/compute/json/servers_client.py b/test/tempest/tempest/services/compute/json/servers_client.py deleted file mode 100644 index 5f2a194d..00000000 --- a/test/tempest/tempest/services/compute/json/servers_client.py +++ /dev/null @@ -1,601 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# 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 json -import time -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import servers as schema -from tempest.common import service_client -from tempest.common import waiters -from tempest import config -from tempest import exceptions - -CONF = config.CONF - - -class ServersClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, service, region, - enable_instance_password=True, **kwargs): - super(ServersClientJSON, self).__init__( - auth_provider, service, region, **kwargs) - self.enable_instance_password = enable_instance_password - - def create_server(self, name, image_ref, flavor_ref, **kwargs): - """ - Creates an instance of a server. - name (Required): The name of the server. - image_ref (Required): Reference to the image used to build the server. - flavor_ref (Required): The flavor used to build the server. - Following optional keyword arguments are accepted: - adminPass: Sets the initial root password. - key_name: Key name of keypair that was created earlier. - meta: A dictionary of values to be used as metadata. - personality: A list of dictionaries for files to be injected into - the server. - security_groups: A list of security group dicts. - networks: A list of network dicts with UUID and fixed_ip. - user_data: User data for instance. - availability_zone: Availability zone in which to launch instance. - accessIPv4: The IPv4 access address for the server. - accessIPv6: The IPv6 access address for the server. - min_count: Count of minimum number of instances to launch. - max_count: Count of maximum number of instances to launch. - disk_config: Determines if user or admin controls disk configuration. - return_reservation_id: Enable/Disable the return of reservation id - block_device_mapping: Block device mapping for the server. - block_device_mapping_v2: Block device mapping V2 for the server. - """ - post_body = { - 'name': name, - 'imageRef': image_ref, - 'flavorRef': flavor_ref - } - - # zfl add boot from volume - if image_ref == "": - post_body.pop('imageRef') - # zfl add boot from volume end - - # zfl add config_drive - for option in ['personality', 'adminPass', 'key_name', - 'security_groups', 'networks', 'user_data', - 'availability_zone', 'accessIPv4', 'accessIPv6', - 'min_count', 'max_count', ('metadata', 'meta'), - ('OS-DCF:diskConfig', 'disk_config'), - 'return_reservation_id', 'block_device_mapping', - 'block_device_mapping_v2', 'config_drive']: - if isinstance(option, tuple): - post_param = option[0] - key = option[1] - else: - post_param = option - key = option - value = kwargs.get(key) - if value is not None: - post_body[post_param] = value - # zfl add net-id in create_server(if no networks provided, - # use uuid=internal_network_id) - else: - if key == "networks": - netid = CONF.network.internal_network_id - post_body['networks'] = [{'uuid': netid}] - # zfl add end - if 'host' in kwargs: - post_body['availability_zone'] = kwargs.get('host') - - post_body = {'server': post_body} - - if 'sched_hints' in kwargs: - hints = {'os:scheduler_hints': kwargs.get('sched_hints')} - post_body = dict(post_body.items() + hints.items()) - - if 'uuid' in kwargs: - networks = {'networks': [kwargs.get('uuid')]} - post_body = dict(post_body.items() + networks.items()) - - post_body = json.dumps(post_body) - resp, body = self.post('servers', post_body) - - body = json.loads(body) - # NOTE(maurosr): this deals with the case of multiple server create - # with return reservation id set True - if 'reservation_id' in body: - return service_client.ResponseBody(resp, body) - if self.enable_instance_password: - create_schema = schema.create_server_with_admin_pass - else: - create_schema = schema.create_server - self.validate_response(create_schema, resp, body) - return service_client.ResponseBody(resp, body['server']) - - def update_server(self, server_id, name=None, meta=None, accessIPv4=None, - accessIPv6=None, disk_config=None): - """ - Updates the properties of an existing server. - server_id: The id of an existing server. - name: The name of the server. - personality: A list of files to be injected into the server. - accessIPv4: The IPv4 access address for the server. - accessIPv6: The IPv6 access address for the server. - """ - - post_body = {} - - if meta is not None: - post_body['metadata'] = meta - - if name is not None: - post_body['name'] = name - - if accessIPv4 is not None: - post_body['accessIPv4'] = accessIPv4 - - if accessIPv6 is not None: - post_body['accessIPv6'] = accessIPv6 - - if disk_config is not None: - post_body['OS-DCF:diskConfig'] = disk_config - - post_body = json.dumps({'server': post_body}) - resp, body = self.put("servers/%s" % str(server_id), post_body) - body = json.loads(body) - self.validate_response(schema.update_server, resp, body) - return service_client.ResponseBody(resp, body['server']) - - def get_server(self, server_id): - """Returns the details of an existing server.""" - resp, body = self.get("servers/%s" % str(server_id)) - body = json.loads(body) - self.validate_response(schema.get_server, resp, body) - return service_client.ResponseBody(resp, body['server']) - - def delete_server(self, server_id): - """Deletes the given server.""" - resp, body = self.delete("servers/%s" % str(server_id)) - self.validate_response(schema.delete_server, resp, body) - return service_client.ResponseBody(resp, body) - - def list_servers(self, params=None): - """Lists all servers for a user.""" - - url = 'servers' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_servers, resp, body) - return service_client.ResponseBody(resp, body) - - def list_servers_with_detail(self, params=None): - """Lists all servers in detail for a user.""" - - url = 'servers/detail' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_servers_detail, resp, body) - return service_client.ResponseBody(resp, body) - - def wait_for_server_status(self, server_id, status, extra_timeout=0, - raise_on_error=True, ready_wait=True): - """Waits for a server to reach a given status.""" - return waiters.wait_for_server_status(self, server_id, status, - extra_timeout=extra_timeout, - raise_on_error=raise_on_error, - ready_wait=ready_wait) - - def wait_for_server_termination(self, server_id, ignore_error=False): - """Waits for server to reach termination.""" - start_time = int(time.time()) - while True: - try: - body = self.get_server(server_id) - except lib_exc.NotFound: - return - - server_status = body['status'] - if server_status == 'ERROR' and not ignore_error: - raise exceptions.BuildErrorException(server_id=server_id) - - if int(time.time()) - start_time >= self.build_timeout: - raise exceptions.TimeoutException - - time.sleep(self.build_interval) - - def list_addresses(self, server_id): - """Lists all addresses for a server.""" - resp, body = self.get("servers/%s/ips" % str(server_id)) - body = json.loads(body) - self.validate_response(schema.list_addresses, resp, body) - return service_client.ResponseBody(resp, body['addresses']) - - def list_addresses_by_network(self, server_id, network_id): - """Lists all addresses of a specific network type for a server.""" - resp, body = self.get("servers/%s/ips/%s" % - (str(server_id), network_id)) - body = json.loads(body) - self.validate_response(schema.list_addresses_by_network, resp, body) - return service_client.ResponseBody(resp, body) - - def action(self, server_id, action_name, response_key, - schema=schema.server_actions_common_schema, - response_class=service_client.ResponseBody, **kwargs): - post_body = json.dumps({action_name: kwargs}) - resp, body = self.post('servers/%s/action' % str(server_id), - post_body) - if response_key is not None: - body = json.loads(body) - # Check for Schema as 'None' because if we do not have any server - # action schema implemented yet then they can pass 'None' to skip - # the validation.Once all server action has their schema - # implemented then, this check can be removed if every actions are - # supposed to validate their response. - # TODO(GMann): Remove the below 'if' check once all server actions - # schema are implemented. - if schema is not None: - self.validate_response(schema, resp, body) - body = body[response_key] - else: - self.validate_response(schema, resp, body) - return response_class(resp, body) - - def create_backup(self, server_id, backup_type, rotation, name): - """Backup a server instance.""" - return self.action(server_id, "createBackup", None, - backup_type=backup_type, - rotation=rotation, - name=name) - - def change_password(self, server_id, adminPass): - """Changes the root password for the server.""" - return self.action(server_id, 'changePassword', None, - adminPass=adminPass) - - def get_password(self, server_id): - resp, body = self.get("servers/%s/os-server-password" % - str(server_id)) - body = json.loads(body) - self.validate_response(schema.get_password, resp, body) - return service_client.ResponseBody(resp, body) - - def delete_password(self, server_id): - """ - Removes the encrypted server password from the metadata server - Note that this does not actually change the instance server - password. - """ - resp, body = self.delete("servers/%s/os-server-password" % - str(server_id)) - self.validate_response(schema.server_actions_delete_password, - resp, body) - return service_client.ResponseBody(resp, body) - - def reboot(self, server_id, reboot_type): - """Reboots a server.""" - return self.action(server_id, 'reboot', None, type=reboot_type) - - def rebuild(self, server_id, image_ref, **kwargs): - """Rebuilds a server with a new image.""" - kwargs['imageRef'] = image_ref - if 'disk_config' in kwargs: - kwargs['OS-DCF:diskConfig'] = kwargs['disk_config'] - del kwargs['disk_config'] - if self.enable_instance_password: - rebuild_schema = schema.rebuild_server_with_admin_pass - else: - rebuild_schema = schema.rebuild_server - return self.action(server_id, 'rebuild', 'server', - rebuild_schema, **kwargs) - - def evacuate(self, server_id, **kwargs): - return self.action(server_id, 'evacuate', 'adminPass', - schema.evacuate_server, - response_class=service_client.ResponseBodyData, - **kwargs) - - def resize(self, server_id, flavor_ref, **kwargs): - """Changes the flavor of a server.""" - kwargs['flavorRef'] = flavor_ref - if 'disk_config' in kwargs: - kwargs['OS-DCF:diskConfig'] = kwargs['disk_config'] - del kwargs['disk_config'] - return self.action(server_id, 'resize', None, **kwargs) - - def confirm_resize(self, server_id, **kwargs): - """Confirms the flavor change for a server.""" - return self.action(server_id, 'confirmResize', - None, schema.server_actions_confirm_resize, - **kwargs) - - def revert_resize(self, server_id, **kwargs): - """Reverts a server back to its original flavor.""" - return self.action(server_id, 'revertResize', None, **kwargs) - - def list_server_metadata(self, server_id): - resp, body = self.get("servers/%s/metadata" % str(server_id)) - body = json.loads(body) - self.validate_response(schema.list_server_metadata, resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def set_server_metadata(self, server_id, meta, no_metadata_field=False): - if no_metadata_field: - post_body = "" - else: - post_body = json.dumps({'metadata': meta}) - resp, body = self.put('servers/%s/metadata' % str(server_id), - post_body) - body = json.loads(body) - self.validate_response(schema.set_server_metadata, resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def update_server_metadata(self, server_id, meta): - post_body = json.dumps({'metadata': meta}) - resp, body = self.post('servers/%s/metadata' % str(server_id), - post_body) - body = json.loads(body) - self.validate_response(schema.update_server_metadata, - resp, body) - return service_client.ResponseBody(resp, body['metadata']) - - def get_server_metadata_item(self, server_id, key): - resp, body = self.get("servers/%s/metadata/%s" % (str(server_id), key)) - body = json.loads(body) - self.validate_response(schema.set_get_server_metadata_item, - resp, body) - return service_client.ResponseBody(resp, body['meta']) - - def set_server_metadata_item(self, server_id, key, meta): - post_body = json.dumps({'meta': meta}) - resp, body = self.put('servers/%s/metadata/%s' % (str(server_id), key), - post_body) - body = json.loads(body) - self.validate_response(schema.set_get_server_metadata_item, - resp, body) - return service_client.ResponseBody(resp, body['meta']) - - def delete_server_metadata_item(self, server_id, key): - resp, body = self.delete("servers/%s/metadata/%s" % - (str(server_id), key)) - self.validate_response(schema.delete_server_metadata_item, - resp, body) - return service_client.ResponseBody(resp, body) - - def stop(self, server_id, **kwargs): - return self.action(server_id, 'os-stop', None, **kwargs) - - def start(self, server_id, **kwargs): - return self.action(server_id, 'os-start', None, **kwargs) - - def attach_volume(self, server_id, volume_id, device='/dev/vdz'): - """Attaches a volume to a server instance.""" - post_body = json.dumps({ - 'volumeAttachment': { - 'volumeId': volume_id, - 'device': device, - } - }) - resp, body = self.post('servers/%s/os-volume_attachments' % server_id, - post_body) - body = json.loads(body) - self.validate_response(schema.attach_volume, resp, body) - return service_client.ResponseBody(resp, body['volumeAttachment']) - - def detach_volume(self, server_id, volume_id): - """Detaches a volume from a server instance.""" - resp, body = self.delete('servers/%s/os-volume_attachments/%s' % - (server_id, volume_id)) - self.validate_response(schema.detach_volume, resp, body) - return service_client.ResponseBody(resp, body) - - def get_volume_attachment(self, server_id, attach_id): - """Return details about the given volume attachment.""" - resp, body = self.get('servers/%s/os-volume_attachments/%s' % ( - str(server_id), attach_id)) - body = json.loads(body) - self.validate_response(schema.get_volume_attachment, resp, body) - return service_client.ResponseBody(resp, body['volumeAttachment']) - - def list_volume_attachments(self, server_id): - """Returns the list of volume attachments for a given instance.""" - resp, body = self.get('servers/%s/os-volume_attachments' % ( - str(server_id))) - body = json.loads(body) - self.validate_response(schema.list_volume_attachments, resp, body) - return service_client.ResponseBodyList(resp, body['volumeAttachments']) - - def add_security_group(self, server_id, name): - """Adds a security group to the server.""" - return self.action(server_id, 'addSecurityGroup', None, name=name) - - def remove_security_group(self, server_id, name): - """Removes a security group from the server.""" - return self.action(server_id, 'removeSecurityGroup', None, name=name) - - def live_migrate_server(self, server_id, dest_host, use_block_migration): - """This should be called with administrator privileges .""" - - migrate_params = { - "disk_over_commit": False, - "block_migration": use_block_migration, - "host": dest_host - } - - req_body = json.dumps({'os-migrateLive': migrate_params}) - - resp, body = self.post("servers/%s/action" % str(server_id), req_body) - self.validate_response(schema.server_actions_common_schema, - resp, body) - return service_client.ResponseBody(resp, body) - - def migrate_server(self, server_id, **kwargs): - """Migrates a server to a new host.""" - return self.action(server_id, 'migrate', None, **kwargs) - - def lock_server(self, server_id, **kwargs): - """Locks the given server.""" - return self.action(server_id, 'lock', None, **kwargs) - - def unlock_server(self, server_id, **kwargs): - """UNlocks the given server.""" - return self.action(server_id, 'unlock', None, **kwargs) - - def suspend_server(self, server_id, **kwargs): - """Suspends the provided server.""" - return self.action(server_id, 'suspend', None, **kwargs) - - def resume_server(self, server_id, **kwargs): - """Un-suspends the provided server.""" - return self.action(server_id, 'resume', None, **kwargs) - - def pause_server(self, server_id, **kwargs): - """Pauses the provided server.""" - return self.action(server_id, 'pause', None, **kwargs) - - def unpause_server(self, server_id, **kwargs): - """Un-pauses the provided server.""" - return self.action(server_id, 'unpause', None, **kwargs) - - def reset_state(self, server_id, state='error'): - """Resets the state of a server to active/error.""" - return self.action(server_id, 'os-resetState', None, state=state) - - def shelve_server(self, server_id, **kwargs): - """Shelves the provided server.""" - return self.action(server_id, 'shelve', None, **kwargs) - - def unshelve_server(self, server_id, **kwargs): - """Un-shelves the provided server.""" - return self.action(server_id, 'unshelve', None, **kwargs) - - def shelve_offload_server(self, server_id, **kwargs): - """Shelve-offload the provided server.""" - return self.action(server_id, 'shelveOffload', None, **kwargs) - - def get_console_output(self, server_id, length): - kwargs = {'length': length} if length else {} - return self.action(server_id, 'os-getConsoleOutput', 'output', - schema.get_console_output, - response_class=service_client.ResponseBodyData, - **kwargs) - - def list_virtual_interfaces(self, server_id): - """ - List the virtual interfaces used in an instance. - """ - resp, body = self.get('/'.join(['servers', server_id, - 'os-virtual-interfaces'])) - body = json.loads(body) - self.validate_response(schema.list_virtual_interfaces, resp, body) - return service_client.ResponseBody(resp, body) - - def rescue_server(self, server_id, **kwargs): - """Rescue the provided server.""" - return self.action(server_id, 'rescue', 'adminPass', - schema.rescue_server, - response_class=service_client.ResponseBodyData, - **kwargs) - - def unrescue_server(self, server_id): - """Unrescue the provided server.""" - return self.action(server_id, 'unrescue', None) - - def get_server_diagnostics(self, server_id): - """Get the usage data for a server.""" - resp, body = self.get("servers/%s/diagnostics" % str(server_id)) - return service_client.ResponseBody(resp, json.loads(body)) - - def list_instance_actions(self, server_id): - """List the provided server action.""" - resp, body = self.get("servers/%s/os-instance-actions" % - str(server_id)) - body = json.loads(body) - self.validate_response(schema.list_instance_actions, resp, body) - return service_client.ResponseBodyList(resp, body['instanceActions']) - - def get_instance_action(self, server_id, request_id): - """Returns the action details of the provided server.""" - resp, body = self.get("servers/%s/os-instance-actions/%s" % - (str(server_id), str(request_id))) - body = json.loads(body) - self.validate_response(schema.get_instance_action, resp, body) - return service_client.ResponseBody(resp, body['instanceAction']) - - def force_delete_server(self, server_id, **kwargs): - """Force delete a server.""" - return self.action(server_id, 'forceDelete', None, **kwargs) - - def restore_soft_deleted_server(self, server_id, **kwargs): - """Restore a soft-deleted server.""" - return self.action(server_id, 'restore', None, **kwargs) - - def reset_network(self, server_id, **kwargs): - """Resets the Network of a server""" - return self.action(server_id, 'resetNetwork', None, **kwargs) - - def inject_network_info(self, server_id, **kwargs): - """Inject the Network Info into server""" - return self.action(server_id, 'injectNetworkInfo', None, **kwargs) - - def get_vnc_console(self, server_id, console_type): - """Get URL of VNC console.""" - return self.action(server_id, "os-getVNCConsole", - "console", schema.get_vnc_console, - type=console_type) - - def create_server_group(self, name, policies): - """ - Create the server group - name : Name of the server-group - policies : List of the policies - affinity/anti-affinity) - """ - post_body = { - 'name': name, - 'policies': policies, - } - - post_body = json.dumps({'server_group': post_body}) - resp, body = self.post('os-server-groups', post_body) - - body = json.loads(body) - self.validate_response(schema.create_get_server_group, resp, body) - return service_client.ResponseBody(resp, body['server_group']) - - def delete_server_group(self, server_group_id): - """Delete the given server-group.""" - resp, body = self.delete("os-server-groups/%s" % str(server_group_id)) - self.validate_response(schema.delete_server_group, resp, body) - return service_client.ResponseBody(resp, body) - - def list_server_groups(self): - """List the server-groups.""" - resp, body = self.get("os-server-groups") - body = json.loads(body) - self.validate_response(schema.list_server_groups, resp, body) - return service_client.ResponseBodyList(resp, body['server_groups']) - - def get_server_group(self, server_group_id): - """Get the details of given server_group.""" - resp, body = self.get("os-server-groups/%s" % str(server_group_id)) - body = json.loads(body) - self.validate_response(schema.create_get_server_group, resp, body) - return service_client.ResponseBody(resp, body['server_group']) diff --git a/test/tempest/tempest/services/compute/json/services_client.py b/test/tempest/tempest/services/compute/json/services_client.py deleted file mode 100644 index fc2274d3..00000000 --- a/test/tempest/tempest/services/compute/json/services_client.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2013 NEC Corporation -# Copyright 2013 IBM Corp. -# 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 json -import urllib - -from tempest.api_schema.response.compute import services as schema -from tempest.common import service_client - - -class ServicesClientJSON(service_client.ServiceClient): - - def list_services(self, params=None): - url = 'os-services' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_services, resp, body) - return service_client.ResponseBodyList(resp, body['services']) - - def enable_service(self, host_name, binary): - """ - Enable service on a host - host_name: Name of host - binary: Service binary - """ - post_body = json.dumps({'binary': binary, 'host': host_name}) - resp, body = self.put('os-services/enable', post_body) - body = json.loads(body) - self.validate_response(schema.enable_service, resp, body) - return service_client.ResponseBody(resp, body['service']) - - def disable_service(self, host_name, binary): - """ - Disable service on a host - host_name: Name of host - binary: Service binary - """ - post_body = json.dumps({'binary': binary, 'host': host_name}) - resp, body = self.put('os-services/disable', post_body) - body = json.loads(body) - return service_client.ResponseBody(resp, body['service']) diff --git a/test/tempest/tempest/services/compute/json/tenant_networks_client.py b/test/tempest/tempest/services/compute/json/tenant_networks_client.py deleted file mode 100644 index 11251f6c..00000000 --- a/test/tempest/tempest/services/compute/json/tenant_networks_client.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2015 NEC 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 json - -from tempest.api_schema.response.compute.v2_1 import tenant_networks as schema -from tempest.common import service_client - - -class TenantNetworksClientJSON(service_client.ServiceClient): - - def list_tenant_networks(self): - resp, body = self.get("os-tenant-networks") - body = json.loads(body) - self.validate_response(schema.list_tenant_networks, resp, body) - return service_client.ResponseBodyList(resp, body['networks']) - - def get_tenant_network(self, network_id): - resp, body = self.get("os-tenant-networks/%s" % str(network_id)) - body = json.loads(body) - self.validate_response(schema.get_tenant_network, resp, body) - return service_client.ResponseBody(resp, body['network']) diff --git a/test/tempest/tempest/services/compute/json/tenant_usages_client.py b/test/tempest/tempest/services/compute/json/tenant_usages_client.py deleted file mode 100644 index ff6e7a2d..00000000 --- a/test/tempest/tempest/services/compute/json/tenant_usages_client.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2013 NEC 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 json -import urllib - -from tempest.api_schema.response.compute.v2_1 import tenant_usages as schema -from tempest.common import service_client - - -class TenantUsagesClientJSON(service_client.ServiceClient): - - def list_tenant_usages(self, params=None): - url = 'os-simple-tenant-usage' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_tenant, resp, body) - return service_client.ResponseBodyList(resp, body['tenant_usages'][0]) - - def get_tenant_usage(self, tenant_id, params=None): - url = 'os-simple-tenant-usage/%s' % tenant_id - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.get_tenant, resp, body) - return service_client.ResponseBodyList(resp, body['tenant_usage']) diff --git a/test/tempest/tempest/services/compute/json/volumes_extensions_client.py b/test/tempest/tempest/services/compute/json/volumes_extensions_client.py deleted file mode 100644 index ba5921ea..00000000 --- a/test/tempest/tempest/services/compute/json/volumes_extensions_client.py +++ /dev/null @@ -1,122 +0,0 @@ -# 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 json -import time -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.api_schema.response.compute.v2_1 import volumes as schema -from tempest.common import service_client -from tempest import exceptions - - -class VolumesExtensionsClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, service, region, - default_volume_size=1, **kwargs): - super(VolumesExtensionsClientJSON, self).__init__( - auth_provider, service, region, **kwargs) - self.default_volume_size = default_volume_size - - def list_volumes(self, params=None): - """List all the volumes created.""" - url = 'os-volumes' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_volumes, resp, body) - return service_client.ResponseBodyList(resp, body['volumes']) - - def list_volumes_with_detail(self, params=None): - """List all the details of volumes.""" - url = 'os-volumes/detail' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.list_volumes, resp, body) - return service_client.ResponseBodyList(resp, body['volumes']) - - def get_volume(self, volume_id): - """Returns the details of a single volume.""" - url = "os-volumes/%s" % str(volume_id) - resp, body = self.get(url) - body = json.loads(body) - self.validate_response(schema.create_get_volume, resp, body) - return service_client.ResponseBody(resp, body['volume']) - - def create_volume(self, size=None, **kwargs): - """ - Creates a new Volume. - size(Required): Size of volume in GB. - Following optional keyword arguments are accepted: - display_name: Optional Volume Name. - metadata: A dictionary of values to be used as metadata. - """ - if size is None: - size = self.default_volume_size - post_body = { - 'size': size - } - post_body.update(kwargs) - - post_body = json.dumps({'volume': post_body}) - resp, body = self.post('os-volumes', post_body) - body = json.loads(body) - self.validate_response(schema.create_get_volume, resp, body) - return service_client.ResponseBody(resp, body['volume']) - - def delete_volume(self, volume_id): - """Deletes the Specified Volume.""" - resp, body = self.delete("os-volumes/%s" % str(volume_id)) - self.validate_response(schema.delete_volume, resp, body) - return service_client.ResponseBody(resp, body) - - def wait_for_volume_status(self, volume_id, status): - """Waits for a Volume to reach a given status.""" - body = self.get_volume(volume_id) - volume_status = body['status'] - start = int(time.time()) - - while volume_status != status: - time.sleep(self.build_interval) - body = self.get_volume(volume_id) - volume_status = body['status'] - if volume_status == 'error': - raise exceptions.VolumeBuildErrorException(volume_id=volume_id) - - if int(time.time()) - start >= self.build_timeout: - message = ('Volume %s failed to reach %s status (current %s) ' - 'within the required time (%s s).' % - (volume_id, status, volume_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - - def is_resource_deleted(self, id): - try: - self.get_volume(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'volume' diff --git a/test/tempest/tempest/services/daisy/__init__.py b/test/tempest/tempest/services/daisy/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/daisy/v1/__init__.py b/test/tempest/tempest/services/daisy/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/daisy/v1/json/__init__.py b/test/tempest/tempest/services/daisy/v1/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/daisy/v1/json/daisy_client.py b/test/tempest/tempest/services/daisy/v1/json/daisy_client.py deleted file mode 100644 index 94d68b47..00000000 --- a/test/tempest/tempest/services/daisy/v1/json/daisy_client.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 json -import time -import urllib - -from oslo_log import log as logging -from tempest_lib.common.utils import misc as misc_utils -from tempest_lib import exceptions as lib_exc - -from tempest.common import glance_http -from tempest.common import service_client -from tempest import exceptions -from tempest.services.image.v1.json.image_client import ImageClientJSON - -LOG = logging.getLogger(__name__) - - -class DaisyClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, catalog_type, region, endpoint_type=None, - build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - super(ImageClientJSON, self).__init__( - auth_provider, - catalog_type, - region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=( - disable_ssl_certificate_validation), - ca_certs=ca_certs, - trace_requests=trace_requests) - self._http = None - self.dscv = disable_ssl_certificate_validation - self.ca_certs = ca_certs - - def _get_http(self): - return glance_http.HTTPClient(auth_provider=self.auth_provider, - filters=self.filters, - insecure=self.dscv, - ca_certs=self.ca_certs) - - def _create_with_data(self, headers, data): - resp, body_iter = self.http.raw_request('POST', '/v1/images', - headers=headers, body=data) - self._error_checker('POST', '/v1/images', headers, data, resp, - body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - def _update_with_data(self, image_id, headers, data): - url = '/v1/images/%s' % image_id - resp, body_iter = self.http.raw_request('PUT', url, headers=headers, - body=data) - self._error_checker('PUT', url, headers, data, - resp, body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - @property - def http(self): - if self._http is None: - self._http = self._get_http() - return self._http - - def create_image(self, name, container_format, disk_format, **kwargs): - params = { - "name": name, - "container_format": container_format, - "disk_format": disk_format, - } - - headers = {} - - for option in ['is_public', 'location', 'properties', - 'copy_from', 'min_ram']: - if option in kwargs: - params[option] = kwargs.get(option) - - headers.update(self._image_meta_to_headers(params)) - - if 'data' in kwargs: - return self._create_with_data(headers, kwargs.get('data')) - - resp, body = self.post('v1/images', None, headers) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def update_image(self, image_id, name=None, container_format=None, - data=None, properties=None): - params = {} - headers = {} - if name is not None: - params['name'] = name - - if container_format is not None: - params['container_format'] = container_format - - if properties is not None: - params['properties'] = properties - - headers.update(self._image_meta_to_headers(params)) - - if data is not None: - return self._update_with_data(image_id, headers, data) - - url = 'v1/images/%s' % image_id - resp, body = self.put(url, data, headers) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def delete_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.delete(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def image_list(self, **kwargs): - url = 'v1/images' - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def image_list_detail(self, properties=dict(), changes_since=None, - **kwargs): - url = 'v1/images/detail' - - params = {} - for key, value in properties.items(): - params['property-%s' % key] = value - - kwargs.update(params) - - if changes_since is not None: - kwargs['changes-since'] = changes_since - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def get_image_meta(self, image_id): - url = 'v1/images/%s' % image_id - resp, __ = self.head(url) - self.expected_success(200, resp.status) - body = self._image_meta_from_headers(resp) - return service_client.ResponseBody(resp, body) - - def get_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyData(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_image_meta(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'image_meta' - - def get_image_membership(self, image_id): - url = 'v1/images/%s/members' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def get_shared_images(self, member_id): - url = 'v1/shared-images/%s' % member_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_member(self, member_id, image_id, can_share=False): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - body = None - if can_share: - body = json.dumps({'member': {'can_share': True}}) - resp, __ = self.put(url, body) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def delete_member(self, member_id, image_id): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - resp, __ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - # NOTE(afazekas): just for the wait function - def _get_image_status(self, image_id): - meta = self.get_image_meta(image_id) - status = meta['status'] - return status - - # NOTE(afazkas): Wait reinvented again. It is not in the correct layer - def wait_for_image_status(self, image_id, status): - """Waits for a Image to reach a given status.""" - start_time = time.time() - old_value = value = self._get_image_status(image_id) - while True: - dtime = time.time() - start_time - time.sleep(self.build_interval) - if value != old_value: - LOG.info('Value transition from "%s" to "%s"' - 'in %d second(s).', old_value, - value, dtime) - if value == status: - return value - - if value == 'killed': - raise exceptions.ImageKilledException(image_id=image_id, - status=status) - if dtime > self.build_timeout: - message = ('Time Limit Exceeded! (%ds)' - 'while waiting for %s, ' - 'but we got %s.' % - (self.build_timeout, status, value)) - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - old_value = value - value = self._get_image_status(image_id) diff --git a/test/tempest/tempest/services/daisy/v1/json/image_client.py b/test/tempest/tempest/services/daisy/v1/json/image_client.py deleted file mode 100644 index ec7900b8..00000000 --- a/test/tempest/tempest/services/daisy/v1/json/image_client.py +++ /dev/null @@ -1,324 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 -import errno -import json -import os -import time -import urllib - -from oslo_log import log as logging -from tempest_lib.common.utils import misc as misc_utils -from tempest_lib import exceptions as lib_exc - -from tempest.common import glance_http -from tempest.common import service_client -from tempest import exceptions - -LOG = logging.getLogger(__name__) - - -class ImageClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, catalog_type, region, endpoint_type=None, - build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - super(ImageClientJSON, self).__init__( - auth_provider, - catalog_type, - region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=( - disable_ssl_certificate_validation), - ca_certs=ca_certs, - trace_requests=trace_requests) - self._http = None - self.dscv = disable_ssl_certificate_validation - self.ca_certs = ca_certs - - def _image_meta_from_headers(self, headers): - meta = {'properties': {}} - for key, value in headers.iteritems(): - if key.startswith('x-image-meta-property-'): - _key = key[22:] - meta['properties'][_key] = value - elif key.startswith('x-image-meta-'): - _key = key[13:] - meta[_key] = value - - for key in ['is_public', 'protected', 'deleted']: - if key in meta: - meta[key] = meta[key].strip().lower() in ('t', 'true', 'yes', - '1') - for key in ['size', 'min_ram', 'min_disk']: - if key in meta: - try: - meta[key] = int(meta[key]) - except ValueError: - pass - return meta - - def _image_meta_to_headers(self, fields): - headers = {} - fields_copy = copy.deepcopy(fields) - copy_from = fields_copy.pop('copy_from', None) - if copy_from is not None: - headers['x-glance-api-copy-from'] = copy_from - for key, value in fields_copy.pop('properties', {}).iteritems(): - headers['x-image-meta-property-%s' % key] = str(value) - for key, value in fields_copy.pop('api', {}).iteritems(): - headers['x-glance-api-property-%s' % key] = str(value) - for key, value in fields_copy.iteritems(): - headers['x-image-meta-%s' % key] = str(value) - return headers - - def _get_file_size(self, obj): - """Analyze file-like object and attempt to determine its size. - - :param obj: file-like object, typically redirected from stdin. - :retval The file's size or None if it cannot be determined. - """ - # For large images, we need to supply the size of the - # image file. See LP Bugs #827660 and #845788. - if hasattr(obj, 'seek') and hasattr(obj, 'tell'): - try: - obj.seek(0, os.SEEK_END) - obj_size = obj.tell() - obj.seek(0) - return obj_size - except IOError as e: - if e.errno == errno.ESPIPE: - # Illegal seek. This means the user is trying - # to pipe image data to the client, e.g. - # echo testdata | bin/glance add blah..., or - # that stdin is empty, or that a file-like - # object which doesn't support 'seek/tell' has - # been supplied. - return None - else: - raise - else: - # Cannot determine size of input image - return None - - def _get_http(self): - return glance_http.HTTPClient(auth_provider=self.auth_provider, - filters=self.filters, - insecure=self.dscv, - ca_certs=self.ca_certs) - - def _create_with_data(self, headers, data): - resp, body_iter = self.http.raw_request('POST', '/v1/images', - headers=headers, body=data) - self._error_checker('POST', '/v1/images', headers, data, resp, - body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - def _update_with_data(self, image_id, headers, data): - url = '/v1/images/%s' % image_id - resp, body_iter = self.http.raw_request('PUT', url, headers=headers, - body=data) - self._error_checker('PUT', url, headers, data, - resp, body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - @property - def http(self): - if self._http is None: - self._http = self._get_http() - return self._http - - def create_image(self, name, container_format, disk_format, **kwargs): - params = { - "name": name, - "container_format": container_format, - "disk_format": disk_format, - } - - headers = {} - - for option in ['is_public', 'location', 'properties', - 'copy_from', 'min_ram']: - if option in kwargs: - params[option] = kwargs.get(option) - - headers.update(self._image_meta_to_headers(params)) - - if 'data' in kwargs: - return self._create_with_data(headers, kwargs.get('data')) - - resp, body = self.post('v1/images', None, headers) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def update_image(self, image_id, name=None, container_format=None, - data=None, properties=None): - params = {} - headers = {} - if name is not None: - params['name'] = name - - if container_format is not None: - params['container_format'] = container_format - - if properties is not None: - params['properties'] = properties - - headers.update(self._image_meta_to_headers(params)) - - if data is not None: - return self._update_with_data(image_id, headers, data) - - url = 'v1/images/%s' % image_id - resp, body = self.put(url, data, headers) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def delete_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.delete(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def image_list(self, **kwargs): - url = 'v1/images' - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def image_list_detail(self, properties=dict(), changes_since=None, - **kwargs): - url = 'v1/images/detail' - - params = {} - for key, value in properties.items(): - params['property-%s' % key] = value - - kwargs.update(params) - - if changes_since is not None: - kwargs['changes-since'] = changes_since - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def get_image_meta(self, image_id): - url = 'v1/images/%s' % image_id - resp, __ = self.head(url) - self.expected_success(200, resp.status) - body = self._image_meta_from_headers(resp) - return service_client.ResponseBody(resp, body) - - def get_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyData(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_image_meta(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'image_meta' - - def get_image_membership(self, image_id): - url = 'v1/images/%s/members' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def get_shared_images(self, member_id): - url = 'v1/shared-images/%s' % member_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_member(self, member_id, image_id, can_share=False): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - body = None - if can_share: - body = json.dumps({'member': {'can_share': True}}) - resp, __ = self.put(url, body) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def delete_member(self, member_id, image_id): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - resp, __ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - # NOTE(afazekas): just for the wait function - def _get_image_status(self, image_id): - meta = self.get_image_meta(image_id) - status = meta['status'] - return status - - # NOTE(afazkas): Wait reinvented again. It is not in the correct layer - def wait_for_image_status(self, image_id, status): - """Waits for a Image to reach a given status.""" - start_time = time.time() - old_value = value = self._get_image_status(image_id) - while True: - dtime = time.time() - start_time - time.sleep(self.build_interval) - if value != old_value: - LOG.info('Value transition from "%s" to "%s"' - 'in %d second(s).', old_value, - value, dtime) - if value == status: - return value - - if value == 'killed': - raise exceptions.ImageKilledException(image_id=image_id, - status=status) - if dtime > self.build_timeout: - message = ('Time Limit Exceeded! (%ds)' - 'while waiting for %s, ' - 'but we got %s.' % - (self.build_timeout, status, value)) - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - old_value = value - value = self._get_image_status(image_id) diff --git a/test/tempest/tempest/services/data_processing/__init__.py b/test/tempest/tempest/services/data_processing/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/data_processing/v1_1/__init__.py b/test/tempest/tempest/services/data_processing/v1_1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/data_processing/v1_1/data_processing_client.py b/test/tempest/tempest/services/data_processing/v1_1/data_processing_client.py deleted file mode 100644 index 04cf9a33..00000000 --- a/test/tempest/tempest/services/data_processing/v1_1/data_processing_client.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# 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 json - -from tempest.common import service_client - - -class DataProcessingClient(service_client.ServiceClient): - - def _request_and_check_resp(self, request_func, uri, resp_status): - """Make a request using specified request_func and check response - status code. - - It returns a ResponseBody. - """ - resp, body = request_func(uri) - self.expected_success(resp_status, resp.status) - return service_client.ResponseBody(resp, body) - - def _request_and_check_resp_data(self, request_func, uri, resp_status): - """Make a request using specified request_func and check response - status code. - - It returns pair: resp and response data. - """ - resp, body = request_func(uri) - self.expected_success(resp_status, resp.status) - return resp, body - - def _request_check_and_parse_resp(self, request_func, uri, resp_status, - resource_name, *args, **kwargs): - """Make a request using specified request_func, check response status - code and parse response body. - - It returns a ResponseBody. - """ - headers = {'Content-Type': 'application/json'} - resp, body = request_func(uri, headers=headers, *args, **kwargs) - self.expected_success(resp_status, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body[resource_name]) - - def _request_check_and_parse_resp_list(self, request_func, uri, - resp_status, resource_name, - *args, **kwargs): - """Make a request using specified request_func, check response status - code and parse response body. - - It returns a ResponseBodyList. - """ - headers = {'Content-Type': 'application/json'} - resp, body = request_func(uri, headers=headers, *args, **kwargs) - self.expected_success(resp_status, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body[resource_name]) - - def list_node_group_templates(self): - """List all node group templates for a user.""" - - uri = 'node-group-templates' - return self._request_check_and_parse_resp_list(self.get, uri, - 200, - 'node_group_templates') - - def get_node_group_template(self, tmpl_id): - """Returns the details of a single node group template.""" - - uri = 'node-group-templates/%s' % tmpl_id - return self._request_check_and_parse_resp(self.get, uri, - 200, 'node_group_template') - - def create_node_group_template(self, name, plugin_name, hadoop_version, - node_processes, flavor_id, - node_configs=None, **kwargs): - """Creates node group template with specified params. - - It supports passing additional params using kwargs and returns created - object. - """ - uri = 'node-group-templates' - body = kwargs.copy() - body.update({ - 'name': name, - 'plugin_name': plugin_name, - 'hadoop_version': hadoop_version, - 'node_processes': node_processes, - 'flavor_id': flavor_id, - 'node_configs': node_configs or dict(), - }) - return self._request_check_and_parse_resp(self.post, uri, 202, - 'node_group_template', - body=json.dumps(body)) - - def delete_node_group_template(self, tmpl_id): - """Deletes the specified node group template by id.""" - - uri = 'node-group-templates/%s' % tmpl_id - return self._request_and_check_resp(self.delete, uri, 204) - - def list_plugins(self): - """List all enabled plugins.""" - - uri = 'plugins' - return self._request_check_and_parse_resp_list(self.get, - uri, 200, 'plugins') - - def get_plugin(self, plugin_name, plugin_version=None): - """Returns the details of a single plugin.""" - - uri = 'plugins/%s' % plugin_name - if plugin_version: - uri += '/%s' % plugin_version - return self._request_check_and_parse_resp(self.get, uri, 200, 'plugin') - - def list_cluster_templates(self): - """List all cluster templates for a user.""" - - uri = 'cluster-templates' - return self._request_check_and_parse_resp_list(self.get, uri, - 200, - 'cluster_templates') - - def get_cluster_template(self, tmpl_id): - """Returns the details of a single cluster template.""" - - uri = 'cluster-templates/%s' % tmpl_id - return self._request_check_and_parse_resp(self.get, - uri, 200, 'cluster_template') - - def create_cluster_template(self, name, plugin_name, hadoop_version, - node_groups, cluster_configs=None, - **kwargs): - """Creates cluster template with specified params. - - It supports passing additional params using kwargs and returns created - object. - """ - uri = 'cluster-templates' - body = kwargs.copy() - body.update({ - 'name': name, - 'plugin_name': plugin_name, - 'hadoop_version': hadoop_version, - 'node_groups': node_groups, - 'cluster_configs': cluster_configs or dict(), - }) - return self._request_check_and_parse_resp(self.post, uri, 202, - 'cluster_template', - body=json.dumps(body)) - - def delete_cluster_template(self, tmpl_id): - """Deletes the specified cluster template by id.""" - - uri = 'cluster-templates/%s' % tmpl_id - return self._request_and_check_resp(self.delete, uri, 204) - - def list_data_sources(self): - """List all data sources for a user.""" - - uri = 'data-sources' - return self._request_check_and_parse_resp_list(self.get, - uri, 200, - 'data_sources') - - def get_data_source(self, source_id): - """Returns the details of a single data source.""" - - uri = 'data-sources/%s' % source_id - return self._request_check_and_parse_resp(self.get, - uri, 200, 'data_source') - - def create_data_source(self, name, data_source_type, url, **kwargs): - """Creates data source with specified params. - - It supports passing additional params using kwargs and returns created - object. - """ - uri = 'data-sources' - body = kwargs.copy() - body.update({ - 'name': name, - 'type': data_source_type, - 'url': url - }) - return self._request_check_and_parse_resp(self.post, uri, - 202, 'data_source', - body=json.dumps(body)) - - def delete_data_source(self, source_id): - """Deletes the specified data source by id.""" - - uri = 'data-sources/%s' % source_id - return self._request_and_check_resp(self.delete, uri, 204) - - def list_job_binary_internals(self): - """List all job binary internals for a user.""" - - uri = 'job-binary-internals' - return self._request_check_and_parse_resp_list(self.get, - uri, 200, 'binaries') - - def get_job_binary_internal(self, job_binary_id): - """Returns the details of a single job binary internal.""" - - uri = 'job-binary-internals/%s' % job_binary_id - return self._request_check_and_parse_resp(self.get, uri, - 200, 'job_binary_internal') - - def create_job_binary_internal(self, name, data): - """Creates job binary internal with specified params.""" - - uri = 'job-binary-internals/%s' % name - return self._request_check_and_parse_resp(self.put, uri, 202, - 'job_binary_internal', data) - - def delete_job_binary_internal(self, job_binary_id): - """Deletes the specified job binary internal by id.""" - - uri = 'job-binary-internals/%s' % job_binary_id - return self._request_and_check_resp(self.delete, uri, 204) - - def get_job_binary_internal_data(self, job_binary_id): - """Returns data of a single job binary internal.""" - - uri = 'job-binary-internals/%s/data' % job_binary_id - return self._request_and_check_resp_data(self.get, uri, 200) - - def list_job_binaries(self): - """List all job binaries for a user.""" - - uri = 'job-binaries' - return self._request_check_and_parse_resp_list(self.get, - uri, 200, 'binaries') - - def get_job_binary(self, job_binary_id): - """Returns the details of a single job binary.""" - - uri = 'job-binaries/%s' % job_binary_id - return self._request_check_and_parse_resp(self.get, - uri, 200, 'job_binary') - - def create_job_binary(self, name, url, extra=None, **kwargs): - """Creates job binary with specified params. - - It supports passing additional params using kwargs and returns created - object. - """ - uri = 'job-binaries' - body = kwargs.copy() - body.update({ - 'name': name, - 'url': url, - 'extra': extra or dict(), - }) - return self._request_check_and_parse_resp(self.post, uri, - 202, 'job_binary', - body=json.dumps(body)) - - def delete_job_binary(self, job_binary_id): - """Deletes the specified job binary by id.""" - - uri = 'job-binaries/%s' % job_binary_id - return self._request_and_check_resp(self.delete, uri, 204) - - def get_job_binary_data(self, job_binary_id): - """Returns data of a single job binary.""" - - uri = 'job-binaries/%s/data' % job_binary_id - return self._request_and_check_resp_data(self.get, uri, 200) - - def list_jobs(self): - """List all jobs for a user.""" - - uri = 'jobs' - return self._request_check_and_parse_resp_list(self.get, - uri, 200, 'jobs') - - def get_job(self, job_id): - """Returns the details of a single job.""" - - uri = 'jobs/%s' % job_id - return self._request_check_and_parse_resp(self.get, uri, 200, 'job') - - def create_job(self, name, job_type, mains, libs=None, **kwargs): - """Creates job with specified params. - - It supports passing additional params using kwargs and returns created - object. - """ - uri = 'jobs' - body = kwargs.copy() - body.update({ - 'name': name, - 'type': job_type, - 'mains': mains, - 'libs': libs or list(), - }) - return self._request_check_and_parse_resp(self.post, uri, 202, - 'job', body=json.dumps(body)) - - def delete_job(self, job_id): - """Deletes the specified job by id.""" - - uri = 'jobs/%s' % job_id - return self._request_and_check_resp(self.delete, uri, 204) diff --git a/test/tempest/tempest/services/database/__init__.py b/test/tempest/tempest/services/database/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/database/json/__init__.py b/test/tempest/tempest/services/database/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/database/json/flavors_client.py b/test/tempest/tempest/services/database/json/flavors_client.py deleted file mode 100644 index c956e27f..00000000 --- a/test/tempest/tempest/services/database/json/flavors_client.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2014 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 urllib - -from tempest.common import service_client - - -class DatabaseFlavorsClientJSON(service_client.ServiceClient): - - def list_db_flavors(self, params=None): - url = 'flavors' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def get_db_flavor_details(self, db_flavor_id): - resp, body = self.get("flavors/%s" % str(db_flavor_id)) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) diff --git a/test/tempest/tempest/services/database/json/limits_client.py b/test/tempest/tempest/services/database/json/limits_client.py deleted file mode 100644 index ae758bc3..00000000 --- a/test/tempest/tempest/services/database/json/limits_client.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2014 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 urllib - -from tempest.common import service_client - - -class DatabaseLimitsClientJSON(service_client.ServiceClient): - - def list_db_limits(self, params=None): - """List all limits.""" - url = 'limits' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) diff --git a/test/tempest/tempest/services/database/json/versions_client.py b/test/tempest/tempest/services/database/json/versions_client.py deleted file mode 100644 index aa2fef7c..00000000 --- a/test/tempest/tempest/services/database/json/versions_client.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 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 urllib - -from tempest.common import service_client - - -class DatabaseVersionsClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, service, region, - endpoint_type=None, build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, ca_certs=None, - trace_requests=None): - dscv = disable_ssl_certificate_validation - super(DatabaseVersionsClientJSON, self).__init__( - auth_provider, service, region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=dscv, - ca_certs=ca_certs, - trace_requests=trace_requests) - self.skip_path() - - def list_db_versions(self, params=None): - """List all versions.""" - url = '' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) diff --git a/test/tempest/tempest/services/identity/__init__.py b/test/tempest/tempest/services/identity/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/identity/v2/__init__.py b/test/tempest/tempest/services/identity/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/identity/v2/json/__init__.py b/test/tempest/tempest/services/identity/v2/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/identity/v2/json/identity_client.py b/test/tempest/tempest/services/identity/v2/json/identity_client.py deleted file mode 100644 index 039f9bbf..00000000 --- a/test/tempest/tempest/services/identity/v2/json/identity_client.py +++ /dev/null @@ -1,283 +0,0 @@ -# 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 json -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client - - -class IdentityClientJSON(service_client.ServiceClient): - - def has_admin_extensions(self): - """ - Returns True if the KSADM Admin Extensions are supported - False otherwise - """ - if hasattr(self, '_has_admin_extensions'): - return self._has_admin_extensions - # Try something that requires admin - try: - self.list_roles() - self._has_admin_extensions = True - except Exception: - self._has_admin_extensions = False - return self._has_admin_extensions - - def create_role(self, name): - """Create a role.""" - post_body = { - 'name': name, - } - post_body = json.dumps({'role': post_body}) - resp, body = self.post('OS-KSADM/roles', post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def get_role(self, role_id): - """Get a role by its id.""" - resp, body = self.get('OS-KSADM/roles/%s' % role_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['role']) - - def create_tenant(self, name, **kwargs): - """ - Create a tenant - name (required): New tenant name - description: Description of new tenant (default is none) - enabled : Initial tenant status (default is true) - """ - post_body = { - 'name': name, - 'description': kwargs.get('description', ''), - 'enabled': kwargs.get('enabled', True), - } - post_body = json.dumps({'tenant': post_body}) - resp, body = self.post('tenants', post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def delete_role(self, role_id): - """Delete a role.""" - resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id)) - self.expected_success(204, resp.status) - return resp, body - - def list_user_roles(self, tenant_id, user_id): - """Returns a list of roles assigned to a user for a tenant.""" - url = '/tenants/%s/users/%s/roles' % (tenant_id, user_id) - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def assign_user_role(self, tenant_id, user_id, role_id): - """Add roles to a user on a tenant.""" - resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' % - (tenant_id, user_id, role_id), "") - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def remove_user_role(self, tenant_id, user_id, role_id): - """Removes a role assignment for a user on a tenant.""" - resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' % - (tenant_id, user_id, role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def delete_tenant(self, tenant_id): - """Delete a tenant.""" - resp, body = self.delete('tenants/%s' % str(tenant_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def get_tenant(self, tenant_id): - """Get tenant details.""" - resp, body = self.get('tenants/%s' % str(tenant_id)) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def list_roles(self): - """Returns roles.""" - resp, body = self.get('OS-KSADM/roles') - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def list_tenants(self): - """Returns tenants.""" - resp, body = self.get('tenants') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['tenants']) - - def get_tenant_by_name(self, tenant_name): - tenants = self.list_tenants() - for tenant in tenants: - if tenant['name'] == tenant_name: - return tenant - raise lib_exc.NotFound('No such tenant') - - def update_tenant(self, tenant_id, **kwargs): - """Updates a tenant.""" - body = self.get_tenant(tenant_id) - name = kwargs.get('name', body['name']) - desc = kwargs.get('description', body['description']) - en = kwargs.get('enabled', body['enabled']) - post_body = { - 'id': tenant_id, - 'name': name, - 'description': desc, - 'enabled': en, - } - post_body = json.dumps({'tenant': post_body}) - resp, body = self.post('tenants/%s' % tenant_id, post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def create_user(self, name, password, tenant_id, email, **kwargs): - """Create a user.""" - post_body = { - 'name': name, - 'password': password, - 'email': email - } - if tenant_id is not None: - post_body['tenantId'] = tenant_id - if kwargs.get('enabled') is not None: - post_body['enabled'] = kwargs.get('enabled') - post_body = json.dumps({'user': post_body}) - resp, body = self.post('users', post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def update_user(self, user_id, **kwargs): - """Updates a user.""" - put_body = json.dumps({'user': kwargs}) - resp, body = self.put('users/%s' % user_id, put_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def get_user(self, user_id): - """GET a user.""" - resp, body = self.get("users/%s" % user_id) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def delete_user(self, user_id): - """Delete a user.""" - resp, body = self.delete("users/%s" % user_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def get_users(self): - """Get the list of users.""" - resp, body = self.get("users") - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def enable_disable_user(self, user_id, enabled): - """Enables or disables a user.""" - put_body = { - 'enabled': enabled - } - put_body = json.dumps({'user': put_body}) - resp, body = self.put('users/%s/enabled' % user_id, put_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def get_token(self, token_id): - """Get token details.""" - resp, body = self.get("tokens/%s" % token_id) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def delete_token(self, token_id): - """Delete a token.""" - resp, body = self.delete("tokens/%s" % token_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_users_for_tenant(self, tenant_id): - """List users for a Tenant.""" - resp, body = self.get('/tenants/%s/users' % tenant_id) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def get_user_by_username(self, tenant_id, username): - users = self.list_users_for_tenant(tenant_id) - for user in users: - if user['name'] == username: - return user - raise lib_exc.NotFound('No such user') - - def create_service(self, name, type, **kwargs): - """Create a service.""" - post_body = { - 'name': name, - 'type': type, - 'description': kwargs.get('description') - } - post_body = json.dumps({'OS-KSADM:service': post_body}) - resp, body = self.post('/OS-KSADM/services', post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def get_service(self, service_id): - """Get Service.""" - url = '/OS-KSADM/services/%s' % service_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def list_services(self): - """List Service - Returns Services.""" - resp, body = self.get('/OS-KSADM/services') - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) - - def delete_service(self, service_id): - """Delete Service.""" - url = '/OS-KSADM/services/%s' % service_id - resp, body = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def update_user_password(self, user_id, new_pass): - """Update User Password.""" - put_body = { - 'password': new_pass, - 'id': user_id - } - put_body = json.dumps({'user': put_body}) - resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def list_extensions(self): - """List all the extensions.""" - resp, body = self.get('/extensions') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, - body['extensions']['values']) - - def create_user_ec2_credentials(self, user_id, tenant_id): - post_body = json.dumps({'tenant_id': tenant_id}) - resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id, - post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def list_user_ec2_credentials(self, user_id): - resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, self._parse_resp(body)) diff --git a/test/tempest/tempest/services/identity/v2/json/token_client.py b/test/tempest/tempest/services/identity/v2/json/token_client.py deleted file mode 100644 index 898709a1..00000000 --- a/test/tempest/tempest/services/identity/v2/json/token_client.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2015 NEC 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 json -from tempest_lib.common import rest_client -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class TokenClientJSON(rest_client.RestClient): - - def __init__(self, auth_url, disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - dscv = disable_ssl_certificate_validation - super(TokenClientJSON, self).__init__( - None, None, None, disable_ssl_certificate_validation=dscv, - ca_certs=ca_certs, trace_requests=trace_requests) - - # Normalize URI to ensure /tokens is in it. - if 'tokens' not in auth_url: - auth_url = auth_url.rstrip('/') + '/tokens' - - self.auth_url = auth_url - - def auth(self, user, password, tenant=None): - creds = { - 'auth': { - 'passwordCredentials': { - 'username': user, - 'password': password, - }, - } - } - - if tenant: - creds['auth']['tenantName'] = tenant - - body = json.dumps(creds) - resp, body = self.post(self.auth_url, body=body) - self.expected_success(200, resp.status) - - return service_client.ResponseBody(resp, body['access']) - - def auth_token(self, token_id, tenant=None): - creds = { - 'auth': { - 'token': { - 'id': token_id, - }, - } - } - - if tenant: - creds['auth']['tenantName'] = tenant - - body = json.dumps(creds) - resp, body = self.post(self.auth_url, body=body) - self.expected_success(200, resp.status) - - return service_client.ResponseBody(resp, body['access']) - - def request(self, method, url, extra_headers=False, headers=None, - body=None): - """A simple HTTP request interface.""" - if headers is None: - headers = self.get_headers(accept_type="json") - elif extra_headers: - try: - headers.update(self.get_headers(accept_type="json")) - except (ValueError, TypeError): - headers = self.get_headers(accept_type="json") - - resp, resp_body = self.raw_request(url, method, - headers=headers, body=body) - self._log_request(method, url, resp, req_body=body) # zfl add - - if resp.status in [401, 403]: - resp_body = json.loads(resp_body) - raise lib_exc.Unauthorized(resp_body['error']['message']) - elif resp.status not in [200, 201]: - raise exceptions.IdentityError( - 'Unexpected status code {0}'.format(resp.status)) - - if isinstance(resp_body, str): - resp_body = json.loads(resp_body) - return resp, resp_body - - def get_token(self, user, password, tenant, auth_data=False): - """ - Returns (token id, token data) for supplied credentials - """ - body = self.auth(user, password, tenant) - - if auth_data: - return body['token']['id'], body - else: - return body['token']['id'] diff --git a/test/tempest/tempest/services/identity/v3/__init__.py b/test/tempest/tempest/services/identity/v3/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/identity/v3/json/__init__.py b/test/tempest/tempest/services/identity/v3/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/identity/v3/json/credentials_client.py b/test/tempest/tempest/services/identity/v3/json/credentials_client.py deleted file mode 100644 index 0a614cdc..00000000 --- a/test/tempest/tempest/services/identity/v3/json/credentials_client.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2013 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 json - -from tempest.common import service_client - - -class CredentialsClientJSON(service_client.ServiceClient): - api_version = "v3" - - def create_credential(self, access_key, secret_key, user_id, project_id): - """Creates a credential.""" - blob = "{\"access\": \"%s\", \"secret\": \"%s\"}" % ( - access_key, secret_key) - post_body = { - "blob": blob, - "project_id": project_id, - "type": "ec2", - "user_id": user_id - } - post_body = json.dumps({'credential': post_body}) - resp, body = self.post('credentials', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - body['credential']['blob'] = json.loads(body['credential']['blob']) - return service_client.ResponseBody(resp, body['credential']) - - def update_credential(self, credential_id, **kwargs): - """Updates a credential.""" - body = self.get_credential(credential_id) - cred_type = kwargs.get('type', body['type']) - access_key = kwargs.get('access_key', body['blob']['access']) - secret_key = kwargs.get('secret_key', body['blob']['secret']) - project_id = kwargs.get('project_id', body['project_id']) - user_id = kwargs.get('user_id', body['user_id']) - blob = "{\"access\": \"%s\", \"secret\": \"%s\"}" % ( - access_key, secret_key) - post_body = { - "blob": blob, - "project_id": project_id, - "type": cred_type, - "user_id": user_id - } - post_body = json.dumps({'credential': post_body}) - resp, body = self.patch('credentials/%s' % credential_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - body['credential']['blob'] = json.loads(body['credential']['blob']) - return service_client.ResponseBody(resp, body['credential']) - - def get_credential(self, credential_id): - """To GET Details of a credential.""" - resp, body = self.get('credentials/%s' % credential_id) - self.expected_success(200, resp.status) - body = json.loads(body) - body['credential']['blob'] = json.loads(body['credential']['blob']) - return service_client.ResponseBody(resp, body['credential']) - - def list_credentials(self): - """Lists out all the available credentials.""" - resp, body = self.get('credentials') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['credentials']) - - def delete_credential(self, credential_id): - """Deletes a credential.""" - resp, body = self.delete('credentials/%s' % credential_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/identity/v3/json/endpoints_client.py b/test/tempest/tempest/services/identity/v3/json/endpoints_client.py deleted file mode 100644 index 5b7e8121..00000000 --- a/test/tempest/tempest/services/identity/v3/json/endpoints_client.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2013 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 json - -from tempest.common import service_client - - -class EndPointClientJSON(service_client.ServiceClient): - api_version = "v3" - - def list_endpoints(self): - """GET endpoints.""" - resp, body = self.get('endpoints') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['endpoints']) - - def create_endpoint(self, service_id, interface, url, **kwargs): - """Create endpoint. - - Normally this function wouldn't allow setting values that are not - allowed for 'enabled'. Use `force_enabled` to set a non-boolean. - - """ - region = kwargs.get('region', None) - if 'force_enabled' in kwargs: - enabled = kwargs.get('force_enabled', None) - else: - enabled = kwargs.get('enabled', None) - post_body = { - 'service_id': service_id, - 'interface': interface, - 'url': url, - 'region': region, - 'enabled': enabled - } - post_body = json.dumps({'endpoint': post_body}) - resp, body = self.post('endpoints', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['endpoint']) - - def update_endpoint(self, endpoint_id, service_id=None, interface=None, - url=None, region=None, enabled=None, **kwargs): - """Updates an endpoint with given parameters. - - Normally this function wouldn't allow setting values that are not - allowed for 'enabled'. Use `force_enabled` to set a non-boolean. - - """ - post_body = {} - if service_id is not None: - post_body['service_id'] = service_id - if interface is not None: - post_body['interface'] = interface - if url is not None: - post_body['url'] = url - if region is not None: - post_body['region'] = region - if 'force_enabled' in kwargs: - post_body['enabled'] = kwargs['force_enabled'] - elif enabled is not None: - post_body['enabled'] = enabled - post_body = json.dumps({'endpoint': post_body}) - resp, body = self.patch('endpoints/%s' % endpoint_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['endpoint']) - - def delete_endpoint(self, endpoint_id): - """Delete endpoint.""" - resp_header, resp_body = self.delete('endpoints/%s' % endpoint_id) - self.expected_success(204, resp_header.status) - return service_client.ResponseBody(resp_header, resp_body) diff --git a/test/tempest/tempest/services/identity/v3/json/identity_client.py b/test/tempest/tempest/services/identity/v3/json/identity_client.py deleted file mode 100644 index bc90fd11..00000000 --- a/test/tempest/tempest/services/identity/v3/json/identity_client.py +++ /dev/null @@ -1,526 +0,0 @@ -# Copyright 2013 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 json -import urllib - -from tempest.common import service_client - - -class IdentityV3ClientJSON(service_client.ServiceClient): - api_version = "v3" - - def create_user(self, user_name, password=None, project_id=None, - email=None, domain_id='default', **kwargs): - """Creates a user.""" - en = kwargs.get('enabled', True) - description = kwargs.get('description', None) - default_project_id = kwargs.get('default_project_id') - post_body = { - 'project_id': project_id, - 'default_project_id': default_project_id, - 'description': description, - 'domain_id': domain_id, - 'email': email, - 'enabled': en, - 'name': user_name, - 'password': password - } - post_body = json.dumps({'user': post_body}) - resp, body = self.post('users', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['user']) - - def update_user(self, user_id, name, **kwargs): - """Updates a user.""" - body = self.get_user(user_id) - email = kwargs.get('email', body['email']) - en = kwargs.get('enabled', body['enabled']) - project_id = kwargs.get('project_id', body['project_id']) - if 'default_project_id' in body.keys(): - default_project_id = kwargs.get('default_project_id', - body['default_project_id']) - else: - default_project_id = kwargs.get('default_project_id') - description = kwargs.get('description', body['description']) - domain_id = kwargs.get('domain_id', body['domain_id']) - post_body = { - 'name': name, - 'email': email, - 'enabled': en, - 'project_id': project_id, - 'default_project_id': default_project_id, - 'id': user_id, - 'domain_id': domain_id, - 'description': description - } - post_body = json.dumps({'user': post_body}) - resp, body = self.patch('users/%s' % user_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['user']) - - def update_user_password(self, user_id, password, original_password): - """Updates a user password.""" - update_user = { - 'password': password, - 'original_password': original_password - } - update_user = json.dumps({'user': update_user}) - resp, _ = self.post('users/%s/password' % user_id, update_user) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def list_user_projects(self, user_id): - """Lists the projects on which a user has roles assigned.""" - resp, body = self.get('users/%s/projects' % user_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['projects']) - - def get_users(self, params=None): - """Get the list of users.""" - url = 'users' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['users']) - - def get_user(self, user_id): - """GET a user.""" - resp, body = self.get("users/%s" % user_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['user']) - - def delete_user(self, user_id): - """Deletes a User.""" - resp, body = self.delete("users/%s" % user_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_project(self, name, **kwargs): - """Creates a project.""" - description = kwargs.get('description', None) - en = kwargs.get('enabled', True) - domain_id = kwargs.get('domain_id', 'default') - post_body = { - 'description': description, - 'domain_id': domain_id, - 'enabled': en, - 'name': name - } - post_body = json.dumps({'project': post_body}) - resp, body = self.post('projects', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['project']) - - def list_projects(self, params=None): - url = "projects" - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['projects']) - - def update_project(self, project_id, **kwargs): - body = self.get_project(project_id) - name = kwargs.get('name', body['name']) - desc = kwargs.get('description', body['description']) - en = kwargs.get('enabled', body['enabled']) - domain_id = kwargs.get('domain_id', body['domain_id']) - post_body = { - 'id': project_id, - 'name': name, - 'description': desc, - 'enabled': en, - 'domain_id': domain_id, - } - post_body = json.dumps({'project': post_body}) - resp, body = self.patch('projects/%s' % project_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['project']) - - def get_project(self, project_id): - """GET a Project.""" - resp, body = self.get("projects/%s" % project_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['project']) - - def delete_project(self, project_id): - """Delete a project.""" - resp, body = self.delete('projects/%s' % str(project_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_role(self, name): - """Create a Role.""" - post_body = { - 'name': name - } - post_body = json.dumps({'role': post_body}) - resp, body = self.post('roles', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['role']) - - def get_role(self, role_id): - """GET a Role.""" - resp, body = self.get('roles/%s' % str(role_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['role']) - - def list_roles(self): - """Get the list of Roles.""" - resp, body = self.get("roles") - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def update_role(self, name, role_id): - """Create a Role.""" - post_body = { - 'name': name - } - post_body = json.dumps({'role': post_body}) - resp, body = self.patch('roles/%s' % str(role_id), post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['role']) - - def delete_role(self, role_id): - """Delete a role.""" - resp, body = self.delete('roles/%s' % str(role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def assign_user_role(self, project_id, user_id, role_id): - """Add roles to a user on a project.""" - resp, body = self.put('projects/%s/users/%s/roles/%s' % - (project_id, user_id, role_id), None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_domain(self, name, **kwargs): - """Creates a domain.""" - description = kwargs.get('description', None) - en = kwargs.get('enabled', True) - post_body = { - 'description': description, - 'enabled': en, - 'name': name - } - post_body = json.dumps({'domain': post_body}) - resp, body = self.post('domains', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['domain']) - - def delete_domain(self, domain_id): - """Delete a domain.""" - resp, body = self.delete('domains/%s' % str(domain_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_domains(self, params=None): - """List Domains.""" - url = 'domains' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['domains']) - - def update_domain(self, domain_id, **kwargs): - """Updates a domain.""" - body = self.get_domain(domain_id) - description = kwargs.get('description', body['description']) - en = kwargs.get('enabled', body['enabled']) - name = kwargs.get('name', body['name']) - post_body = { - 'description': description, - 'enabled': en, - 'name': name - } - post_body = json.dumps({'domain': post_body}) - resp, body = self.patch('domains/%s' % domain_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['domain']) - - def get_domain(self, domain_id): - """Get Domain details.""" - resp, body = self.get('domains/%s' % domain_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['domain']) - - def get_token(self, resp_token): - """Get token details.""" - headers = {'X-Subject-Token': resp_token} - resp, body = self.get("auth/tokens", headers=headers) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['token']) - - def delete_token(self, resp_token): - """Deletes token.""" - headers = {'X-Subject-Token': resp_token} - resp, body = self.delete("auth/tokens", headers=headers) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_group(self, name, **kwargs): - """Creates a group.""" - description = kwargs.get('description', None) - domain_id = kwargs.get('domain_id', 'default') - project_id = kwargs.get('project_id', None) - post_body = { - 'description': description, - 'domain_id': domain_id, - 'project_id': project_id, - 'name': name - } - post_body = json.dumps({'group': post_body}) - resp, body = self.post('groups', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['group']) - - def get_group(self, group_id): - """Get group details.""" - resp, body = self.get('groups/%s' % group_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['group']) - - def list_groups(self): - """Lists the groups.""" - resp, body = self.get('groups') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['groups']) - - def update_group(self, group_id, **kwargs): - """Updates a group.""" - body = self.get_group(group_id) - name = kwargs.get('name', body['name']) - description = kwargs.get('description', body['description']) - post_body = { - 'name': name, - 'description': description - } - post_body = json.dumps({'group': post_body}) - resp, body = self.patch('groups/%s' % group_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['group']) - - def delete_group(self, group_id): - """Delete a group.""" - resp, body = self.delete('groups/%s' % str(group_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def add_group_user(self, group_id, user_id): - """Add user into group.""" - resp, body = self.put('groups/%s/users/%s' % (group_id, user_id), - None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_group_users(self, group_id): - """List users in group.""" - resp, body = self.get('groups/%s/users' % group_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['users']) - - def list_user_groups(self, user_id): - """Lists groups which a user belongs to.""" - resp, body = self.get('users/%s/groups' % user_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['groups']) - - def delete_group_user(self, group_id, user_id): - """Delete user in group.""" - resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def assign_user_role_on_project(self, project_id, user_id, role_id): - """Add roles to a user on a project.""" - resp, body = self.put('projects/%s/users/%s/roles/%s' % - (project_id, user_id, role_id), None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def assign_user_role_on_domain(self, domain_id, user_id, role_id): - """Add roles to a user on a domain.""" - resp, body = self.put('domains/%s/users/%s/roles/%s' % - (domain_id, user_id, role_id), None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_user_roles_on_project(self, project_id, user_id): - """list roles of a user on a project.""" - resp, body = self.get('projects/%s/users/%s/roles' % - (project_id, user_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def list_user_roles_on_domain(self, domain_id, user_id): - """list roles of a user on a domain.""" - resp, body = self.get('domains/%s/users/%s/roles' % - (domain_id, user_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def revoke_role_from_user_on_project(self, project_id, user_id, role_id): - """Delete role of a user on a project.""" - resp, body = self.delete('projects/%s/users/%s/roles/%s' % - (project_id, user_id, role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id): - """Delete role of a user on a domain.""" - resp, body = self.delete('domains/%s/users/%s/roles/%s' % - (domain_id, user_id, role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def assign_group_role_on_project(self, project_id, group_id, role_id): - """Add roles to a user on a project.""" - resp, body = self.put('projects/%s/groups/%s/roles/%s' % - (project_id, group_id, role_id), None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def assign_group_role_on_domain(self, domain_id, group_id, role_id): - """Add roles to a user on a domain.""" - resp, body = self.put('domains/%s/groups/%s/roles/%s' % - (domain_id, group_id, role_id), None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_group_roles_on_project(self, project_id, group_id): - """list roles of a user on a project.""" - resp, body = self.get('projects/%s/groups/%s/roles' % - (project_id, group_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def list_group_roles_on_domain(self, domain_id, group_id): - """list roles of a user on a domain.""" - resp, body = self.get('domains/%s/groups/%s/roles' % - (domain_id, group_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def revoke_role_from_group_on_project(self, project_id, group_id, role_id): - """Delete role of a user on a project.""" - resp, body = self.delete('projects/%s/groups/%s/roles/%s' % - (project_id, group_id, role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id): - """Delete role of a user on a domain.""" - resp, body = self.delete('domains/%s/groups/%s/roles/%s' % - (domain_id, group_id, role_id)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_trust(self, trustor_user_id, trustee_user_id, project_id, - role_names, impersonation, expires_at): - """Creates a trust.""" - roles = [{'name': n} for n in role_names] - post_body = { - 'trustor_user_id': trustor_user_id, - 'trustee_user_id': trustee_user_id, - 'project_id': project_id, - 'impersonation': impersonation, - 'roles': roles, - 'expires_at': expires_at - } - post_body = json.dumps({'trust': post_body}) - resp, body = self.post('OS-TRUST/trusts', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['trust']) - - def delete_trust(self, trust_id): - """Deletes a trust.""" - resp, body = self.delete("OS-TRUST/trusts/%s" % trust_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def get_trusts(self, trustor_user_id=None, trustee_user_id=None): - """GET trusts.""" - if trustor_user_id: - resp, body = self.get("OS-TRUST/trusts?trustor_user_id=%s" - % trustor_user_id) - elif trustee_user_id: - resp, body = self.get("OS-TRUST/trusts?trustee_user_id=%s" - % trustee_user_id) - else: - resp, body = self.get("OS-TRUST/trusts") - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['trusts']) - - def get_trust(self, trust_id): - """GET trust.""" - resp, body = self.get("OS-TRUST/trusts/%s" % trust_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['trust']) - - def get_trust_roles(self, trust_id): - """GET roles delegated by a trust.""" - resp, body = self.get("OS-TRUST/trusts/%s/roles" % trust_id) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['roles']) - - def get_trust_role(self, trust_id, role_id): - """GET role delegated by a trust.""" - resp, body = self.get("OS-TRUST/trusts/%s/roles/%s" - % (trust_id, role_id)) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['role']) - - def check_trust_role(self, trust_id, role_id): - """HEAD Check if role is delegated by a trust.""" - resp, body = self.head("OS-TRUST/trusts/%s/roles/%s" - % (trust_id, role_id)) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/identity/v3/json/policy_client.py b/test/tempest/tempest/services/identity/v3/json/policy_client.py deleted file mode 100644 index 8c9c9ce7..00000000 --- a/test/tempest/tempest/services/identity/v3/json/policy_client.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2013 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 json - -from tempest.common import service_client - - -class PolicyClientJSON(service_client.ServiceClient): - api_version = "v3" - - def create_policy(self, blob, type): - """Creates a Policy.""" - post_body = { - "blob": blob, - "type": type - } - post_body = json.dumps({'policy': post_body}) - resp, body = self.post('policies', post_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['policy']) - - def list_policies(self): - """Lists the policies.""" - resp, body = self.get('policies') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['policies']) - - def get_policy(self, policy_id): - """Lists out the given policy.""" - url = 'policies/%s' % policy_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['policy']) - - def update_policy(self, policy_id, **kwargs): - """Updates a policy.""" - type = kwargs.get('type') - post_body = { - 'type': type - } - post_body = json.dumps({'policy': post_body}) - url = 'policies/%s' % policy_id - resp, body = self.patch(url, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['policy']) - - def delete_policy(self, policy_id): - """Deletes the policy.""" - url = "policies/%s" % policy_id - resp, body = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/identity/v3/json/region_client.py b/test/tempest/tempest/services/identity/v3/json/region_client.py deleted file mode 100644 index faaf43c5..00000000 --- a/test/tempest/tempest/services/identity/v3/json/region_client.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2014 Hewlett-Packard Development Company, L.P -# 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 json -import urllib - -from tempest.common import service_client - - -class RegionClientJSON(service_client.ServiceClient): - api_version = "v3" - - def create_region(self, description, **kwargs): - """Create region.""" - req_body = { - 'description': description, - } - if kwargs.get('parent_region_id'): - req_body['parent_region_id'] = kwargs.get('parent_region_id') - req_body = json.dumps({'region': req_body}) - if kwargs.get('unique_region_id'): - resp, body = self.put( - 'regions/%s' % kwargs.get('unique_region_id'), req_body) - else: - resp, body = self.post('regions', req_body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['region']) - - def update_region(self, region_id, **kwargs): - """Updates a region.""" - post_body = {} - if 'description' in kwargs: - post_body['description'] = kwargs.get('description') - if 'parent_region_id' in kwargs: - post_body['parent_region_id'] = kwargs.get('parent_region_id') - post_body = json.dumps({'region': post_body}) - resp, body = self.patch('regions/%s' % region_id, post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['region']) - - def get_region(self, region_id): - """Get region.""" - url = 'regions/%s' % region_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['region']) - - def list_regions(self, params=None): - """List regions.""" - url = 'regions' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['regions']) - - def delete_region(self, region_id): - """Delete region.""" - resp, body = self.delete('regions/%s' % region_id) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/identity/v3/json/service_client.py b/test/tempest/tempest/services/identity/v3/json/service_client.py deleted file mode 100644 index e039dc65..00000000 --- a/test/tempest/tempest/services/identity/v3/json/service_client.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2013 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 json - -from tempest.common import service_client - - -class ServiceClientJSON(service_client.ServiceClient): - api_version = "v3" - - def update_service(self, service_id, **kwargs): - """Updates a service.""" - body = self.get_service(service_id) - name = kwargs.get('name', body['name']) - type = kwargs.get('type', body['type']) - desc = kwargs.get('description', body['description']) - patch_body = { - 'description': desc, - 'type': type, - 'name': name - } - patch_body = json.dumps({'service': patch_body}) - resp, body = self.patch('services/%s' % service_id, patch_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['service']) - - def get_service(self, service_id): - """Get Service.""" - url = 'services/%s' % service_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['service']) - - def create_service(self, serv_type, name=None, description=None, - enabled=True): - body_dict = { - 'name': name, - 'type': serv_type, - 'enabled': enabled, - 'description': description, - } - body = json.dumps({'service': body_dict}) - resp, body = self.post("services", body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body["service"]) - - def delete_service(self, serv_id): - url = "services/" + serv_id - resp, body = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_services(self): - resp, body = self.get('services') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['services']) diff --git a/test/tempest/tempest/services/identity/v3/json/token_client.py b/test/tempest/tempest/services/identity/v3/json/token_client.py deleted file mode 100644 index 3e374036..00000000 --- a/test/tempest/tempest/services/identity/v3/json/token_client.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2015 NEC 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 json -from tempest_lib.common import rest_client -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class V3TokenClientJSON(rest_client.RestClient): - - def __init__(self, auth_url, disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - dscv = disable_ssl_certificate_validation - super(V3TokenClientJSON, self).__init__( - None, None, None, disable_ssl_certificate_validation=dscv, - ca_certs=ca_certs, trace_requests=trace_requests) - if not auth_url: - raise exceptions.InvalidConfiguration('you must specify a v3 uri ' - 'if using the v3 identity ' - 'api') - if 'auth/tokens' not in auth_url: - auth_url = auth_url.rstrip('/') + '/auth/tokens' - - self.auth_url = auth_url - - def auth(self, user_id=None, username=None, password=None, project_id=None, - project_name=None, user_domain_id=None, user_domain_name=None, - project_domain_id=None, project_domain_name=None, domain_id=None, - domain_name=None, token=None): - """ - :param user_id: user id - :param username: user name - :param user_domain_id: the user domain id - :param user_domain_name: the user domain name - :param project_domain_id: the project domain id - :param project_domain_name: the project domain name - :param domain_id: a domain id to scope to - :param domain_name: a domain name to scope to - :param project_id: a project id to scope to - :param project_name: a project name to scope to - :param token: a token to re-scope. - - Accepts different combinations of credentials. - Sample sample valid combinations: - - token - - token, project_name, project_domain_id - - user_id, password - - username, password, user_domain_id - - username, password, project_name, user_domain_id, project_domain_id - Validation is left to the server side. - """ - creds = { - 'auth': { - 'identity': { - 'methods': [], - } - } - } - id_obj = creds['auth']['identity'] - if token: - id_obj['methods'].append('token') - id_obj['token'] = { - 'id': token - } - - if (user_id or username) and password: - id_obj['methods'].append('password') - id_obj['password'] = { - 'user': { - 'password': password, - } - } - if user_id: - id_obj['password']['user']['id'] = user_id - else: - id_obj['password']['user']['name'] = username - - _domain = None - if user_domain_id is not None: - _domain = dict(id=user_domain_id) - elif user_domain_name is not None: - _domain = dict(name=user_domain_name) - if _domain: - id_obj['password']['user']['domain'] = _domain - - if (project_id or project_name): - _project = dict() - - if project_id: - _project['id'] = project_id - elif project_name: - _project['name'] = project_name - - if project_domain_id is not None: - _project['domain'] = {'id': project_domain_id} - elif project_domain_name is not None: - _project['domain'] = {'name': project_domain_name} - - creds['auth']['scope'] = dict(project=_project) - elif domain_id: - creds['auth']['scope'] = dict(domain={'id': domain_id}) - elif domain_name: - creds['auth']['scope'] = dict(domain={'name': domain_name}) - - body = json.dumps(creds) - resp, body = self.post(self.auth_url, body=body) - self.expected_success(201, resp.status) - return service_client.ResponseBody(resp, body) - - def request(self, method, url, extra_headers=False, headers=None, - body=None): - """A simple HTTP request interface.""" - if headers is None: - # Always accept 'json', for xml token client too. - # Because XML response is not easily - # converted to the corresponding JSON one - headers = self.get_headers(accept_type="json") - elif extra_headers: - try: - headers.update(self.get_headers(accept_type="json")) - except (ValueError, TypeError): - headers = self.get_headers(accept_type="json") - - resp, resp_body = self.raw_request(url, method, - headers=headers, body=body) - self._log_request(method, url, resp) - - if resp.status in [401, 403]: - resp_body = json.loads(resp_body) - raise lib_exc.Unauthorized(resp_body['error']['message']) - elif resp.status not in [200, 201, 204]: - raise exceptions.IdentityError( - 'Unexpected status code {0}'.format(resp.status)) - - return resp, json.loads(resp_body) - - def get_token(self, **kwargs): - """ - Returns (token id, token data) for supplied credentials - """ - - auth_data = kwargs.pop('auth_data', False) - - if not (kwargs.get('user_domain_id') or - kwargs.get('user_domain_name')): - kwargs['user_domain_name'] = 'Default' - - if not (kwargs.get('project_domain_id') or - kwargs.get('project_domain_name')): - kwargs['project_domain_name'] = 'Default' - - body = self.auth(**kwargs) - - token = body.response.get('x-subject-token') - if auth_data: - return token, body['token'] - else: - return token diff --git a/test/tempest/tempest/services/image/__init__.py b/test/tempest/tempest/services/image/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/image/v1/__init__.py b/test/tempest/tempest/services/image/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/image/v1/json/__init__.py b/test/tempest/tempest/services/image/v1/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/image/v1/json/image_client.py b/test/tempest/tempest/services/image/v1/json/image_client.py deleted file mode 100644 index ec7900b8..00000000 --- a/test/tempest/tempest/services/image/v1/json/image_client.py +++ /dev/null @@ -1,324 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 -import errno -import json -import os -import time -import urllib - -from oslo_log import log as logging -from tempest_lib.common.utils import misc as misc_utils -from tempest_lib import exceptions as lib_exc - -from tempest.common import glance_http -from tempest.common import service_client -from tempest import exceptions - -LOG = logging.getLogger(__name__) - - -class ImageClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, catalog_type, region, endpoint_type=None, - build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, - ca_certs=None, trace_requests=None): - super(ImageClientJSON, self).__init__( - auth_provider, - catalog_type, - region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=( - disable_ssl_certificate_validation), - ca_certs=ca_certs, - trace_requests=trace_requests) - self._http = None - self.dscv = disable_ssl_certificate_validation - self.ca_certs = ca_certs - - def _image_meta_from_headers(self, headers): - meta = {'properties': {}} - for key, value in headers.iteritems(): - if key.startswith('x-image-meta-property-'): - _key = key[22:] - meta['properties'][_key] = value - elif key.startswith('x-image-meta-'): - _key = key[13:] - meta[_key] = value - - for key in ['is_public', 'protected', 'deleted']: - if key in meta: - meta[key] = meta[key].strip().lower() in ('t', 'true', 'yes', - '1') - for key in ['size', 'min_ram', 'min_disk']: - if key in meta: - try: - meta[key] = int(meta[key]) - except ValueError: - pass - return meta - - def _image_meta_to_headers(self, fields): - headers = {} - fields_copy = copy.deepcopy(fields) - copy_from = fields_copy.pop('copy_from', None) - if copy_from is not None: - headers['x-glance-api-copy-from'] = copy_from - for key, value in fields_copy.pop('properties', {}).iteritems(): - headers['x-image-meta-property-%s' % key] = str(value) - for key, value in fields_copy.pop('api', {}).iteritems(): - headers['x-glance-api-property-%s' % key] = str(value) - for key, value in fields_copy.iteritems(): - headers['x-image-meta-%s' % key] = str(value) - return headers - - def _get_file_size(self, obj): - """Analyze file-like object and attempt to determine its size. - - :param obj: file-like object, typically redirected from stdin. - :retval The file's size or None if it cannot be determined. - """ - # For large images, we need to supply the size of the - # image file. See LP Bugs #827660 and #845788. - if hasattr(obj, 'seek') and hasattr(obj, 'tell'): - try: - obj.seek(0, os.SEEK_END) - obj_size = obj.tell() - obj.seek(0) - return obj_size - except IOError as e: - if e.errno == errno.ESPIPE: - # Illegal seek. This means the user is trying - # to pipe image data to the client, e.g. - # echo testdata | bin/glance add blah..., or - # that stdin is empty, or that a file-like - # object which doesn't support 'seek/tell' has - # been supplied. - return None - else: - raise - else: - # Cannot determine size of input image - return None - - def _get_http(self): - return glance_http.HTTPClient(auth_provider=self.auth_provider, - filters=self.filters, - insecure=self.dscv, - ca_certs=self.ca_certs) - - def _create_with_data(self, headers, data): - resp, body_iter = self.http.raw_request('POST', '/v1/images', - headers=headers, body=data) - self._error_checker('POST', '/v1/images', headers, data, resp, - body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - def _update_with_data(self, image_id, headers, data): - url = '/v1/images/%s' % image_id - resp, body_iter = self.http.raw_request('PUT', url, headers=headers, - body=data) - self._error_checker('PUT', url, headers, data, - resp, body_iter) - body = json.loads(''.join([c for c in body_iter])) - return service_client.ResponseBody(resp, body['image']) - - @property - def http(self): - if self._http is None: - self._http = self._get_http() - return self._http - - def create_image(self, name, container_format, disk_format, **kwargs): - params = { - "name": name, - "container_format": container_format, - "disk_format": disk_format, - } - - headers = {} - - for option in ['is_public', 'location', 'properties', - 'copy_from', 'min_ram']: - if option in kwargs: - params[option] = kwargs.get(option) - - headers.update(self._image_meta_to_headers(params)) - - if 'data' in kwargs: - return self._create_with_data(headers, kwargs.get('data')) - - resp, body = self.post('v1/images', None, headers) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def update_image(self, image_id, name=None, container_format=None, - data=None, properties=None): - params = {} - headers = {} - if name is not None: - params['name'] = name - - if container_format is not None: - params['container_format'] = container_format - - if properties is not None: - params['properties'] = properties - - headers.update(self._image_meta_to_headers(params)) - - if data is not None: - return self._update_with_data(image_id, headers, data) - - url = 'v1/images/%s' % image_id - resp, body = self.put(url, data, headers) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['image']) - - def delete_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.delete(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def image_list(self, **kwargs): - url = 'v1/images' - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def image_list_detail(self, properties=dict(), changes_since=None, - **kwargs): - url = 'v1/images/detail' - - params = {} - for key, value in properties.items(): - params['property-%s' % key] = value - - kwargs.update(params) - - if changes_since is not None: - kwargs['changes-since'] = changes_since - - if len(kwargs) > 0: - url += '?%s' % urllib.urlencode(kwargs) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['images']) - - def get_image_meta(self, image_id): - url = 'v1/images/%s' % image_id - resp, __ = self.head(url) - self.expected_success(200, resp.status) - body = self._image_meta_from_headers(resp) - return service_client.ResponseBody(resp, body) - - def get_image(self, image_id): - url = 'v1/images/%s' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyData(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_image_meta(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'image_meta' - - def get_image_membership(self, image_id): - url = 'v1/images/%s/members' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def get_shared_images(self, member_id): - url = 'v1/shared-images/%s' % member_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_member(self, member_id, image_id, can_share=False): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - body = None - if can_share: - body = json.dumps({'member': {'can_share': True}}) - resp, __ = self.put(url, body) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def delete_member(self, member_id, image_id): - url = 'v1/images/%s/members/%s' % (image_id, member_id) - resp, __ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - # NOTE(afazekas): just for the wait function - def _get_image_status(self, image_id): - meta = self.get_image_meta(image_id) - status = meta['status'] - return status - - # NOTE(afazkas): Wait reinvented again. It is not in the correct layer - def wait_for_image_status(self, image_id, status): - """Waits for a Image to reach a given status.""" - start_time = time.time() - old_value = value = self._get_image_status(image_id) - while True: - dtime = time.time() - start_time - time.sleep(self.build_interval) - if value != old_value: - LOG.info('Value transition from "%s" to "%s"' - 'in %d second(s).', old_value, - value, dtime) - if value == status: - return value - - if value == 'killed': - raise exceptions.ImageKilledException(image_id=image_id, - status=status) - if dtime > self.build_timeout: - message = ('Time Limit Exceeded! (%ds)' - 'while waiting for %s, ' - 'but we got %s.' % - (self.build_timeout, status, value)) - caller = misc_utils.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - old_value = value - value = self._get_image_status(image_id) diff --git a/test/tempest/tempest/services/image/v2/__init__.py b/test/tempest/tempest/services/image/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/image/v2/json/__init__.py b/test/tempest/tempest/services/image/v2/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/image/v2/json/image_client.py b/test/tempest/tempest/services/image/v2/json/image_client.py deleted file mode 100644 index 6b04144b..00000000 --- a/test/tempest/tempest/services/image/v2/json/image_client.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 json -import urllib - -import jsonschema -from tempest_lib import exceptions as lib_exc - -from tempest.common import glance_http -from tempest.common import service_client - - -class ImageClientV2JSON(service_client.ServiceClient): - - def __init__(self, auth_provider, catalog_type, region, endpoint_type=None, - build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, ca_certs=None, - trace_requests=None): - super(ImageClientV2JSON, self).__init__( - auth_provider, - catalog_type, - region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=( - disable_ssl_certificate_validation), - ca_certs=ca_certs, - trace_requests=trace_requests) - self._http = None - self.dscv = disable_ssl_certificate_validation - self.ca_certs = ca_certs - - def _get_http(self): - return glance_http.HTTPClient(auth_provider=self.auth_provider, - filters=self.filters, - insecure=self.dscv, - ca_certs=self.ca_certs) - - def _validate_schema(self, body, type='image'): - if type in ['image', 'images']: - schema = self.get_schema(type) - else: - raise ValueError("%s is not a valid schema type" % type) - - jsonschema.validate(body, schema) - - @property - def http(self): - if self._http is None: - self._http = self._get_http() - return self._http - - def update_image(self, image_id, patch): - data = json.dumps(patch) - self._validate_schema(data) - - headers = {"Content-Type": "application/openstack-images-v2.0" - "-json-patch"} - resp, body = self.patch('v2/images/%s' % image_id, data, headers) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def create_image(self, name, container_format, disk_format, **kwargs): - params = { - "name": name, - "container_format": container_format, - "disk_format": disk_format, - } - - for option in kwargs: - value = kwargs.get(option) - if isinstance(value, dict) or isinstance(value, tuple): - params.update(value) - else: - params[option] = value - - data = json.dumps(params) - self._validate_schema(data) - - resp, body = self.post('v2/images', data) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def delete_image(self, image_id): - url = 'v2/images/%s' % image_id - resp, _ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def image_list(self, params=None): - url = 'v2/images' - - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - self._validate_schema(body, type='images') - return service_client.ResponseBodyList(resp, body['images']) - - def get_image(self, image_id): - url = 'v2/images/%s' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - try: - self.get_image(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'image' - - def store_image(self, image_id, data): - url = 'v2/images/%s/file' % image_id - headers = {'Content-Type': 'application/octet-stream'} - resp, body = self.http.raw_request('PUT', url, headers=headers, - body=data) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def get_image_file(self, image_id): - url = 'v2/images/%s/file' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBodyData(resp, body) - - def add_image_tag(self, image_id, tag): - url = 'v2/images/%s/tags/%s' % (image_id, tag) - resp, body = self.put(url, body=None) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def delete_image_tag(self, image_id, tag): - url = 'v2/images/%s/tags/%s' % (image_id, tag) - resp, _ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def get_image_membership(self, image_id): - url = 'v2/images/%s/members' % image_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_member(self, image_id, member_id): - url = 'v2/images/%s/members' % image_id - data = json.dumps({'member': member_id}) - resp, body = self.post(url, data) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_member_status(self, image_id, member_id, status): - """Valid status are: ``pending``, ``accepted``, ``rejected``.""" - url = 'v2/images/%s/members/%s' % (image_id, member_id) - data = json.dumps({'status': status}) - resp, body = self.put(url, data) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def get_member(self, image_id, member_id): - url = 'v2/images/%s/members/%s' % (image_id, member_id) - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, json.loads(body)) - - def remove_member(self, image_id, member_id): - url = 'v2/images/%s/members/%s' % (image_id, member_id) - resp, _ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def get_schema(self, schema): - url = 'v2/schemas/%s' % schema - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/messaging/__init__.py b/test/tempest/tempest/services/messaging/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/messaging/json/__init__.py b/test/tempest/tempest/services/messaging/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/messaging/json/messaging_client.py b/test/tempest/tempest/services/messaging/json/messaging_client.py deleted file mode 100644 index 483ba93e..00000000 --- a/test/tempest/tempest/services/messaging/json/messaging_client.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (c) 2014 Rackspace, Inc. -# -# 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 json -import urllib -import uuid - -from tempest.api_schema.response.messaging.v1 import queues as queues_schema -from tempest.common import service_client - - -class MessagingClientJSON(service_client.ServiceClient): - - def __init__(self, auth_provider, service, region, - endpoint_type=None, build_interval=None, build_timeout=None, - disable_ssl_certificate_validation=None, ca_certs=None, - trace_requests=None): - dscv = disable_ssl_certificate_validation - super(MessagingClientJSON, self).__init__( - auth_provider, service, region, - endpoint_type=endpoint_type, - build_interval=build_interval, - build_timeout=build_timeout, - disable_ssl_certificate_validation=dscv, - ca_certs=ca_certs, - trace_requests=trace_requests) - - self.version = '1' - self.uri_prefix = 'v{0}'.format(self.version) - - client_id = uuid.uuid4().hex - self.headers = {'Client-ID': client_id} - - def list_queues(self): - uri = '{0}/queues'.format(self.uri_prefix) - resp, body = self.get(uri) - - if resp['status'] != '204': - body = json.loads(body) - self.validate_response(queues_schema.list_queues, resp, body) - return resp, body - - def create_queue(self, queue_name): - uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) - resp, body = self.put(uri, body=None) - self.expected_success(201, resp.status) - return resp, body - - def show_queue(self, queue_name): - uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) - resp, body = self.get(uri) - self.expected_success(204, resp.status) - return resp, body - - def head_queue(self, queue_name): - uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) - resp, body = self.head(uri) - self.expected_success(204, resp.status) - return resp, body - - def delete_queue(self, queue_name): - uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return resp, body - - def show_queue_stats(self, queue_name): - uri = '{0}/queues/{1}/stats'.format(self.uri_prefix, queue_name) - resp, body = self.get(uri) - body = json.loads(body) - self.validate_response(queues_schema.queue_stats, resp, body) - return resp, body - - def show_queue_metadata(self, queue_name): - uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return resp, body - - def set_queue_metadata(self, queue_name, rbody): - uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name) - resp, body = self.put(uri, body=json.dumps(rbody)) - self.expected_success(204, resp.status) - return resp, body - - def post_messages(self, queue_name, rbody): - uri = '{0}/queues/{1}/messages'.format(self.uri_prefix, queue_name) - resp, body = self.post(uri, body=json.dumps(rbody), - extra_headers=True, - headers=self.headers) - - body = json.loads(body) - self.validate_response(queues_schema.post_messages, resp, body) - return resp, body - - def list_messages(self, queue_name): - uri = '{0}/queues/{1}/messages?echo=True'.format(self.uri_prefix, - queue_name) - resp, body = self.get(uri, extra_headers=True, headers=self.headers) - - if resp['status'] != '204': - body = json.loads(body) - self.validate_response(queues_schema.list_messages, resp, body) - - return resp, body - - def show_single_message(self, message_uri): - resp, body = self.get(message_uri, extra_headers=True, - headers=self.headers) - if resp['status'] != '204': - body = json.loads(body) - self.validate_response(queues_schema.get_single_message, resp, - body) - return resp, body - - def show_multiple_messages(self, message_uri): - resp, body = self.get(message_uri, extra_headers=True, - headers=self.headers) - - if resp['status'] != '204': - body = json.loads(body) - self.validate_response(queues_schema.get_multiple_messages, - resp, - body) - - return resp, body - - def delete_messages(self, message_uri): - resp, body = self.delete(message_uri) - self.expected_success(204, resp.status) - return resp, body - - def post_claims(self, queue_name, rbody, url_params=False): - uri = '{0}/queues/{1}/claims'.format(self.uri_prefix, queue_name) - if url_params: - uri += '?%s' % urllib.urlencode(url_params) - - resp, body = self.post(uri, body=json.dumps(rbody), - extra_headers=True, - headers=self.headers) - - body = json.loads(body) - self.validate_response(queues_schema.claim_messages, resp, body) - return resp, body - - def query_claim(self, claim_uri): - resp, body = self.get(claim_uri) - - if resp['status'] != '204': - body = json.loads(body) - self.validate_response(queues_schema.query_claim, resp, body) - return resp, body - - def update_claim(self, claim_uri, rbody): - resp, body = self.patch(claim_uri, body=json.dumps(rbody)) - self.expected_success(204, resp.status) - return resp, body - - def release_claim(self, claim_uri): - resp, body = self.delete(claim_uri) - self.expected_success(204, resp.status) - return resp, body diff --git a/test/tempest/tempest/services/network/__init__.py b/test/tempest/tempest/services/network/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/network/json/__init__.py b/test/tempest/tempest/services/network/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/network/json/network_client.py b/test/tempest/tempest/services/network/json/network_client.py deleted file mode 100644 index 53645a5e..00000000 --- a/test/tempest/tempest/services/network/json/network_client.py +++ /dev/null @@ -1,581 +0,0 @@ -# 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 json -import time -import urllib - -from tempest_lib.common.utils import misc -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class NetworkClientJSON(service_client.ServiceClient): - - """ - Tempest REST client for Neutron. Uses v2 of the Neutron API, since the - V1 API has been removed from the code base. - - Implements create, delete, update, list and show for the basic Neutron - abstractions (networks, sub-networks, routers, ports and floating IP): - - Implements add/remove interface to router using subnet ID / port ID - - It also implements list, show, update and reset for OpenStack Networking - quotas - """ - - version = '2.0' - uri_prefix = "v2.0" - - def get_uri(self, plural_name): - # get service prefix from resource name - - # The following list represents resource names that do not require - # changing underscore to a hyphen - hyphen_exceptions = ["health_monitors", "firewall_rules", - "firewall_policies"] - # the following map is used to construct proper URI - # for the given neutron resource - service_resource_prefix_map = { - 'networks': '', - 'subnets': '', - 'ports': '', - 'pools': 'lb', - 'vips': 'lb', - 'health_monitors': 'lb', - 'members': 'lb', - 'ipsecpolicies': 'vpn', - 'vpnservices': 'vpn', - 'ikepolicies': 'vpn', - 'ipsec-site-connections': 'vpn', - 'metering_labels': 'metering', - 'metering_label_rules': 'metering', - 'firewall_rules': 'fw', - 'firewall_policies': 'fw', - 'firewalls': 'fw' - } - service_prefix = service_resource_prefix_map.get( - plural_name) - if plural_name not in hyphen_exceptions: - plural_name = plural_name.replace("_", "-") - if service_prefix: - uri = '%s/%s/%s' % (self.uri_prefix, service_prefix, - plural_name) - else: - uri = '%s/%s' % (self.uri_prefix, plural_name) - return uri - - def pluralize(self, resource_name): - # get plural from map or just add 's' - - # map from resource name to a plural name - # needed only for those which can't be constructed as name + 's' - resource_plural_map = { - 'security_groups': 'security_groups', - 'security_group_rules': 'security_group_rules', - 'ipsecpolicy': 'ipsecpolicies', - 'ikepolicy': 'ikepolicies', - 'ipsec_site_connection': 'ipsec-site-connections', - 'quotas': 'quotas', - 'firewall_policy': 'firewall_policies' - } - return resource_plural_map.get(resource_name, resource_name + 's') - - def _lister(self, plural_name): - def _list(**filters): - uri = self.get_uri(plural_name) - if filters: - uri += '?' + urllib.urlencode(filters, doseq=1) - resp, body = self.get(uri) - result = {plural_name: self.deserialize_list(body)} - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, result) - - return _list - - def _deleter(self, resource_name): - def _delete(resource_id): - plural = self.pluralize(resource_name) - uri = '%s/%s' % (self.get_uri(plural), resource_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - return _delete - - def _shower(self, resource_name): - def _show(resource_id, **fields): - # fields is a dict which key is 'fields' and value is a - # list of field's name. An example: - # {'fields': ['id', 'name']} - plural = self.pluralize(resource_name) - uri = '%s/%s' % (self.get_uri(plural), resource_id) - if fields: - uri += '?' + urllib.urlencode(fields, doseq=1) - resp, body = self.get(uri) - body = self.deserialize_single(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - return _show - - def _creater(self, resource_name): - def _create(**kwargs): - plural = self.pluralize(resource_name) - uri = self.get_uri(plural) - post_data = self.serialize({resource_name: kwargs}) - resp, body = self.post(uri, post_data) - body = self.deserialize_single(body) - self.expected_success(201, resp.status) - return service_client.ResponseBody(resp, body) - - return _create - - def _updater(self, resource_name): - def _update(res_id, **kwargs): - plural = self.pluralize(resource_name) - uri = '%s/%s' % (self.get_uri(plural), res_id) - post_data = self.serialize({resource_name: kwargs}) - resp, body = self.put(uri, post_data) - body = self.deserialize_single(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - return _update - - def __getattr__(self, name): - method_prefixes = ["list_", "delete_", "show_", "create_", "update_"] - method_functors = [self._lister, - self._deleter, - self._shower, - self._creater, - self._updater] - for index, prefix in enumerate(method_prefixes): - prefix_len = len(prefix) - if name[:prefix_len] == prefix: - return method_functors[index](name[prefix_len:]) - raise AttributeError(name) - - # Common methods that are hard to automate - def create_bulk_network(self, names): - network_list = [{'name': name} for name in names] - post_data = {'networks': network_list} - body = self.serialize_list(post_data, "networks", "network") - uri = self.get_uri("networks") - resp, body = self.post(uri, body) - body = {'networks': self.deserialize_list(body)} - self.expected_success(201, resp.status) - return service_client.ResponseBody(resp, body) - - def create_bulk_subnet(self, subnet_list): - post_data = {'subnets': subnet_list} - body = self.serialize_list(post_data, 'subnets', 'subnet') - uri = self.get_uri('subnets') - resp, body = self.post(uri, body) - body = {'subnets': self.deserialize_list(body)} - self.expected_success(201, resp.status) - return service_client.ResponseBody(resp, body) - - def create_bulk_port(self, port_list): - post_data = {'ports': port_list} - body = self.serialize_list(post_data, 'ports', 'port') - uri = self.get_uri('ports') - resp, body = self.post(uri, body) - body = {'ports': self.deserialize_list(body)} - self.expected_success(201, resp.status) - return service_client.ResponseBody(resp, body) - - def wait_for_resource_deletion(self, resource_type, id): - """Waits for a resource to be deleted.""" - start_time = int(time.time()) - while True: - if self.is_resource_deleted(resource_type, id): - return - if int(time.time()) - start_time >= self.build_timeout: - raise exceptions.TimeoutException - time.sleep(self.build_interval) - - def is_resource_deleted(self, resource_type, id): - method = 'show_' + resource_type - try: - getattr(self, method)(id) - except AttributeError: - raise Exception("Unknown resource type %s " % resource_type) - except lib_exc.NotFound: - return True - return False - - def wait_for_resource_status(self, fetch, status, interval=None, - timeout=None): - """ - @summary: Waits for a network resource to reach a status - @param fetch: the callable to be used to query the resource status - @type fecth: callable that takes no parameters and returns the resource - @param status: the status that the resource has to reach - @type status: String - @param interval: the number of seconds to wait between each status - query - @type interval: Integer - @param timeout: the maximum number of seconds to wait for the resource - to reach the desired status - @type timeout: Integer - """ - if not interval: - interval = self.build_interval - if not timeout: - timeout = self.build_timeout - start_time = time.time() - - while time.time() - start_time <= timeout: - resource = fetch() - if resource['status'] == status: - return - time.sleep(interval) - - # At this point, the wait has timed out - message = 'Resource %s' % (str(resource)) - message += ' failed to reach status %s' % status - message += ' (current: %s)' % resource['status'] - message += ' within the required time %s' % timeout - caller = misc.find_test_caller() - if caller: - message = '(%s) %s' % (caller, message) - raise exceptions.TimeoutException(message) - - def deserialize_single(self, body): - return json.loads(body) - - def deserialize_list(self, body): - res = json.loads(body) - # expecting response in form - # {'resources': [ res1, res2] } => when pagination disabled - # {'resources': [..], 'resources_links': {}} => if pagination enabled - for k in res.keys(): - if k.endswith("_links"): - continue - return res[k] - - def serialize(self, data): - return json.dumps(data) - - def serialize_list(self, data, root=None, item=None): - return self.serialize(data) - - def update_quotas(self, tenant_id, **kwargs): - put_body = {'quota': kwargs} - body = json.dumps(put_body) - uri = '%s/quotas/%s' % (self.uri_prefix, tenant_id) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['quota']) - - def reset_quotas(self, tenant_id): - uri = '%s/quotas/%s' % (self.uri_prefix, tenant_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_router(self, name, admin_state_up=True, **kwargs): - post_body = {'router': kwargs} - post_body['router']['name'] = name - post_body['router']['admin_state_up'] = admin_state_up - body = json.dumps(post_body) - uri = '%s/routers' % (self.uri_prefix) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def _update_router(self, router_id, set_enable_snat, **kwargs): - uri = '%s/routers/%s' % (self.uri_prefix, router_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - update_body = {} - update_body['name'] = kwargs.get('name', body['router']['name']) - update_body['admin_state_up'] = kwargs.get( - 'admin_state_up', body['router']['admin_state_up']) - cur_gw_info = body['router']['external_gateway_info'] - if cur_gw_info: - # TODO(kevinbenton): setting the external gateway info is not - # allowed for a regular tenant. If the ability to update is also - # merged, a test case for this will need to be added similar to - # the SNAT case. - cur_gw_info.pop('external_fixed_ips', None) - if not set_enable_snat: - cur_gw_info.pop('enable_snat', None) - update_body['external_gateway_info'] = kwargs.get( - 'external_gateway_info', body['router']['external_gateway_info']) - if 'distributed' in kwargs: - update_body['distributed'] = kwargs['distributed'] - update_body = dict(router=update_body) - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_router(self, router_id, **kwargs): - """Update a router leaving enable_snat to its default value.""" - # If external_gateway_info contains enable_snat the request will fail - # with 404 unless executed with admin client, and therefore we instruct - # _update_router to not set this attribute - # NOTE(salv-orlando): The above applies as long as Neutron's default - # policy is to restrict enable_snat usage to admins only. - return self._update_router(router_id, set_enable_snat=False, **kwargs) - - def update_router_with_snat_gw_info(self, router_id, **kwargs): - """Update a router passing also the enable_snat attribute. - - This method must be execute with admin credentials, otherwise the API - call will return a 404 error. - """ - return self._update_router(router_id, set_enable_snat=True, **kwargs) - - def add_router_interface_with_subnet_id(self, router_id, subnet_id): - uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix, - router_id) - update_body = {"subnet_id": subnet_id} - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_router_interface_with_port_id(self, router_id, port_id): - uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix, - router_id) - update_body = {"port_id": port_id} - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def remove_router_interface_with_subnet_id(self, router_id, subnet_id): - uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix, - router_id) - update_body = {"subnet_id": subnet_id} - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def remove_router_interface_with_port_id(self, router_id, port_id): - uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix, - router_id) - update_body = {"port_id": port_id} - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def associate_health_monitor_with_pool(self, health_monitor_id, - pool_id): - post_body = { - "health_monitor": { - "id": health_monitor_id, - } - } - body = json.dumps(post_body) - uri = '%s/lb/pools/%s/health_monitors' % (self.uri_prefix, - pool_id) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def disassociate_health_monitor_with_pool(self, health_monitor_id, - pool_id): - uri = '%s/lb/pools/%s/health_monitors/%s' % (self.uri_prefix, pool_id, - health_monitor_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_router_interfaces(self, uuid): - uri = '%s/ports?device_id=%s' % (self.uri_prefix, uuid) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_agent(self, agent_id, agent_info): - """ - :param agent_info: Agent update information. - E.g {"admin_state_up": True} - """ - uri = '%s/agents/%s' % (self.uri_prefix, agent_id) - agent = {"agent": agent_info} - body = json.dumps(agent) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_pools_hosted_by_one_lbaas_agent(self, agent_id): - uri = '%s/agents/%s/loadbalancer-pools' % (self.uri_prefix, agent_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def show_lbaas_agent_hosting_pool(self, pool_id): - uri = ('%s/lb/pools/%s/loadbalancer-agent' % - (self.uri_prefix, pool_id)) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_routers_on_l3_agent(self, agent_id): - uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_l3_agents_hosting_router(self, router_id): - uri = '%s/routers/%s/l3-agents' % (self.uri_prefix, router_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_router_to_l3_agent(self, agent_id, router_id): - uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id) - post_body = {"router_id": router_id} - body = json.dumps(post_body) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def remove_router_from_l3_agent(self, agent_id, router_id): - uri = '%s/agents/%s/l3-routers/%s' % ( - self.uri_prefix, agent_id, router_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def list_dhcp_agent_hosting_network(self, network_id): - uri = '%s/networks/%s/dhcp-agents' % (self.uri_prefix, network_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_networks_hosted_by_one_dhcp_agent(self, agent_id): - uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def remove_network_from_dhcp_agent(self, agent_id, network_id): - uri = '%s/agents/%s/dhcp-networks/%s' % (self.uri_prefix, agent_id, - network_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp, body) - - def create_ikepolicy(self, name, **kwargs): - post_body = { - "ikepolicy": { - "name": name, - } - } - for key, val in kwargs.items(): - post_body['ikepolicy'][key] = val - body = json.dumps(post_body) - uri = '%s/vpn/ikepolicies' % (self.uri_prefix) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_extra_routes(self, router_id, nexthop, destination): - uri = '%s/routers/%s' % (self.uri_prefix, router_id) - put_body = { - 'router': { - 'routes': [{'nexthop': nexthop, - "destination": destination}] - } - } - body = json.dumps(put_body) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def delete_extra_routes(self, router_id): - uri = '%s/routers/%s' % (self.uri_prefix, router_id) - null_routes = None - put_body = { - 'router': { - 'routes': null_routes - } - } - body = json.dumps(put_body) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_lb_pool_stats(self, pool_id): - uri = '%s/lb/pools/%s/stats' % (self.uri_prefix, pool_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def add_dhcp_agent_to_network(self, agent_id, network_id): - post_body = {'network_id': network_id} - body = json.dumps(post_body) - uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def insert_firewall_rule_in_policy(self, firewall_policy_id, - firewall_rule_id, insert_after="", - insert_before=""): - uri = '%s/fw/firewall_policies/%s/insert_rule' % (self.uri_prefix, - firewall_policy_id) - body = { - "firewall_rule_id": firewall_rule_id, - "insert_after": insert_after, - "insert_before": insert_before - } - body = json.dumps(body) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def remove_firewall_rule_from_policy(self, firewall_policy_id, - firewall_rule_id): - uri = '%s/fw/firewall_policies/%s/remove_rule' % (self.uri_prefix, - firewall_policy_id) - update_body = {"firewall_rule_id": firewall_rule_id} - update_body = json.dumps(update_body) - resp, body = self.put(uri, update_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) diff --git a/test/tempest/tempest/services/network/resources.py b/test/tempest/tempest/services/network/resources.py deleted file mode 100644 index 4d45515a..00000000 --- a/test/tempest/tempest/services/network/resources.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# 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 abc - -import six - - -class AttributeDict(dict): - - """ - Provide attribute access (dict.key) to dictionary values. - """ - - def __getattr__(self, name): - """Allow attribute access for all keys in the dict.""" - if name in self: - return self[name] - return super(AttributeDict, self).__getattribute__(name) - - -@six.add_metaclass(abc.ABCMeta) -class DeletableResource(AttributeDict): - - """ - Support deletion of neutron resources (networks, subnets) via a - delete() method, as is supported by keystone and nova resources. - """ - - def __init__(self, *args, **kwargs): - self.client = kwargs.pop('client', None) - super(DeletableResource, self).__init__(*args, **kwargs) - - def __str__(self): - return '<%s id="%s" name="%s">' % (self.__class__.__name__, - self.id, self.name) - - @abc.abstractmethod - def delete(self): - return - - @abc.abstractmethod - def refresh(self): - return - - def __hash__(self): - return hash(self.id) - - def wait_for_status(self, status): - if not hasattr(self, 'status'): - return - - def helper_get(): - self.refresh() - return self - - return self.client.wait_for_resource_status(helper_get, status) - - -class DeletableNetwork(DeletableResource): - - def delete(self): - self.client.delete_network(self.id) - - -class DeletableSubnet(DeletableResource): - - def __init__(self, *args, **kwargs): - super(DeletableSubnet, self).__init__(*args, **kwargs) - self._router_ids = set() - - def update(self, *args, **kwargs): - result = self.client.update_subnet(self.id, - *args, - **kwargs) - return super(DeletableSubnet, self).update(**result['subnet']) - - def add_to_router(self, router_id): - self._router_ids.add(router_id) - self.client.add_router_interface_with_subnet_id(router_id, - subnet_id=self.id) - - def delete(self): - for router_id in self._router_ids.copy(): - self.client.remove_router_interface_with_subnet_id( - router_id, - subnet_id=self.id) - self._router_ids.remove(router_id) - self.client.delete_subnet(self.id) - - -class DeletableRouter(DeletableResource): - - def set_gateway(self, network_id): - return self.update(external_gateway_info=dict(network_id=network_id)) - - def unset_gateway(self): - return self.update(external_gateway_info=dict()) - - def update(self, *args, **kwargs): - result = self.client.update_router(self.id, - *args, - **kwargs) - return super(DeletableRouter, self).update(**result['router']) - - def delete(self): - self.unset_gateway() - self.client.delete_router(self.id) - - -class DeletableFloatingIp(DeletableResource): - - def refresh(self, *args, **kwargs): - result = self.client.show_floatingip(self.id, - *args, - **kwargs) - super(DeletableFloatingIp, self).update(**result['floatingip']) - - def update(self, *args, **kwargs): - result = self.client.update_floatingip(self.id, - *args, - **kwargs) - super(DeletableFloatingIp, self).update(**result['floatingip']) - - def __repr__(self): - return '<%s addr="%s">' % (self.__class__.__name__, - self.floating_ip_address) - - def __str__(self): - return '<"FloatingIP" addr="%s" id="%s">' % (self.floating_ip_address, - self.id) - - def delete(self): - self.client.delete_floatingip(self.id) - - -class DeletablePort(DeletableResource): - - def delete(self): - self.client.delete_port(self.id) - - -class DeletableSecurityGroup(DeletableResource): - - def delete(self): - self.client.delete_security_group(self.id) - - -class DeletableSecurityGroupRule(DeletableResource): - - def __repr__(self): - return '<%s id="%s">' % (self.__class__.__name__, self.id) - - def delete(self): - self.client.delete_security_group_rule(self.id) - - -class DeletablePool(DeletableResource): - - def delete(self): - self.client.delete_pool(self.id) - - -class DeletableMember(DeletableResource): - - def delete(self): - self.client.delete_member(self.id) - - -class DeletableVip(DeletableResource): - - def delete(self): - self.client.delete_vip(self.id) - - def refresh(self): - result = self.client.show_vip(self.id) - super(DeletableVip, self).update(**result['vip']) diff --git a/test/tempest/tempest/services/object_storage/__init__.py b/test/tempest/tempest/services/object_storage/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/object_storage/account_client.py b/test/tempest/tempest/services/object_storage/account_client.py deleted file mode 100644 index af00eff4..00000000 --- a/test/tempest/tempest/services/object_storage/account_client.py +++ /dev/null @@ -1,159 +0,0 @@ -# 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 json -import urllib -from xml.etree import ElementTree as etree - -from tempest.common import service_client - - -class AccountClient(service_client.ServiceClient): - - def create_account(self, data=None, - params=None, - metadata=None, - remove_metadata=None, - metadata_prefix='X-Account-Meta-', - remove_metadata_prefix='X-Remove-Account-Meta-'): - """Create an account.""" - if metadata is None: - metadata = {} - if remove_metadata is None: - remove_metadata = {} - url = '' - if params: - url += '?%s' % urllib.urlencode(params) - - headers = {} - for key in metadata: - headers[metadata_prefix + key] = metadata[key] - for key in remove_metadata: - headers[remove_metadata_prefix + key] = remove_metadata[key] - - resp, body = self.put(url, data, headers) - self.expected_success(200, resp.status) - return resp, body - - def delete_account(self, data=None, params=None): - """Delete an account.""" - url = '' - if params: - url = '?%s%s' % (url, urllib.urlencode(params)) - - resp, body = self.delete(url, headers={}, body=data) - self.expected_success(200, resp.status) - return resp, body - - def list_account_metadata(self): - """ - HEAD on the storage URL - Returns all account metadata headers - """ - resp, body = self.head('') - self.expected_success(204, resp.status) - return resp, body - - def create_account_metadata(self, metadata, - metadata_prefix='X-Account-Meta-', - data=None, params=None): - """Creates an account metadata entry.""" - headers = {} - if metadata: - for key in metadata: - headers[metadata_prefix + key] = metadata[key] - - url = '' - if params: - url = '?%s%s' % (url, urllib.urlencode(params)) - - resp, body = self.post(url, headers=headers, body=data) - self.expected_success([200, 204], resp.status) - return resp, body - - def delete_account_metadata(self, metadata, - metadata_prefix='X-Remove-Account-Meta-'): - """ - Deletes an account metadata entry. - """ - - headers = {} - for item in metadata: - headers[metadata_prefix + item] = metadata[item] - resp, body = self.post('', headers=headers, body=None) - self.expected_success(204, resp.status) - return resp, body - - def create_and_delete_account_metadata( - self, - create_metadata=None, - delete_metadata=None, - create_metadata_prefix='X-Account-Meta-', - delete_metadata_prefix='X-Remove-Account-Meta-'): - """ - Creates and deletes an account metadata entry. - """ - headers = {} - for key in create_metadata: - headers[create_metadata_prefix + key] = create_metadata[key] - for key in delete_metadata: - headers[delete_metadata_prefix + key] = delete_metadata[key] - - resp, body = self.post('', headers=headers, body=None) - self.expected_success(204, resp.status) - return resp, body - - def list_account_containers(self, params=None): - """ - GET on the (base) storage URL - Given valid X-Auth-Token, returns a list of all containers for the - account. - - Optional Arguments: - limit=[integer value N] - Limits the number of results to at most N values - DEFAULT: 10,000 - - marker=[string value X] - Given string value X, return object names greater in value - than the specified marker. - DEFAULT: No Marker - - format=[string value, either 'json' or 'xml'] - Specify either json or xml to return the respective serialized - response. - DEFAULT: Python-List returned in response body - """ - url = '?%s' % urllib.urlencode(params) if params else '' - - resp, body = self.get(url, headers={}) - if params and params.get('format') == 'json': - body = json.loads(body) - elif params and params.get('format') == 'xml': - body = etree.fromstring(body) - else: - body = body.strip().splitlines() - self.expected_success([200, 204], resp.status) - return resp, body - - def list_extensions(self): - self.skip_path() - try: - resp, body = self.get('info') - finally: - self.reset_path() - body = json.loads(body) - self.expected_success(200, resp.status) - return resp, body diff --git a/test/tempest/tempest/services/object_storage/container_client.py b/test/tempest/tempest/services/object_storage/container_client.py deleted file mode 100644 index ed74de40..00000000 --- a/test/tempest/tempest/services/object_storage/container_client.py +++ /dev/null @@ -1,186 +0,0 @@ -# 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 json -import urllib -from xml.etree import ElementTree as etree - -from tempest.common import service_client - - -class ContainerClient(service_client.ServiceClient): - - def create_container( - self, container_name, - metadata=None, - remove_metadata=None, - metadata_prefix='X-Container-Meta-', - remove_metadata_prefix='X-Remove-Container-Meta-'): - """ - Creates a container, with optional metadata passed in as a - dictionary - """ - url = str(container_name) - headers = {} - - if metadata is not None: - for key in metadata: - headers[metadata_prefix + key] = metadata[key] - if remove_metadata is not None: - for key in remove_metadata: - headers[remove_metadata_prefix + key] = remove_metadata[key] - - resp, body = self.put(url, body=None, headers=headers) - self.expected_success([201, 202], resp.status) - return resp, body - - def delete_container(self, container_name): - """Deletes the container (if it's empty).""" - url = str(container_name) - resp, body = self.delete(url) - self.expected_success(204, resp.status) - return resp, body - - def update_container_metadata( - self, container_name, - metadata=None, - remove_metadata=None, - metadata_prefix='X-Container-Meta-', - remove_metadata_prefix='X-Remove-Container-Meta-'): - """Updates arbitrary metadata on container.""" - url = str(container_name) - headers = {} - - if metadata is not None: - for key in metadata: - headers[metadata_prefix + key] = metadata[key] - if remove_metadata is not None: - for key in remove_metadata: - headers[remove_metadata_prefix + key] = remove_metadata[key] - - resp, body = self.post(url, body=None, headers=headers) - self.expected_success(204, resp.status) - return resp, body - - def delete_container_metadata(self, container_name, metadata, - metadata_prefix='X-Remove-Container-Meta-'): - """Deletes arbitrary metadata on container.""" - url = str(container_name) - headers = {} - - if metadata is not None: - for item in metadata: - headers[metadata_prefix + item] = metadata[item] - - resp, body = self.post(url, body=None, headers=headers) - self.expected_success(204, resp.status) - return resp, body - - def list_container_metadata(self, container_name): - """ - Retrieves container metadata headers - """ - url = str(container_name) - resp, body = self.head(url) - self.expected_success(204, resp.status) - return resp, body - - def list_all_container_objects(self, container, params=None): - """ - Returns complete list of all objects in the container, even if - item count is beyond 10,000 item listing limit. - Does not require any parameters aside from container name. - """ - # TODO(dwalleck): Rewrite using json format to avoid newlines at end of - # obj names. Set limit to API limit - 1 (max returned items = 9999) - limit = 9999 - if params is not None: - if 'limit' in params: - limit = params['limit'] - - if 'marker' in params: - limit = params['marker'] - - resp, objlist = self.list_container_contents( - container, - params={'limit': limit, 'format': 'json'}) - self.expected_success(200, resp.status) - return objlist - """tmp = [] - for obj in objlist: - tmp.append(obj['name']) - objlist = tmp - - if len(objlist) >= limit: - - # Increment marker - marker = objlist[len(objlist) - 1] - - # Get the next chunk of the list - objlist.extend(_list_all_container_objects(container, - params={'marker': marker, - 'limit': limit})) - return objlist - else: - # Return final, complete list - return objlist""" - - def list_container_contents(self, container, params=None): - """ - List the objects in a container, given the container name - - Returns the container object listing as a plain text list, or as - xml or json if that option is specified via the 'format' argument. - - Optional Arguments: - limit = integer - For an integer value n, limits the number of results to at most - n values. - - marker = 'string' - Given a string value x, return object names greater in value - than the specified marker. - - prefix = 'string' - For a string value x, causes the results to be limited to names - beginning with the substring x. - - format = 'json' or 'xml' - Specify either json or xml to return the respective serialized - response. - If json, returns a list of json objects - if xml, returns a string of xml - - path = 'string' - For a string value x, return the object names nested in the - pseudo path (assuming preconditions are met - see below). - - delimiter = 'character' - For a character c, return all the object names nested in the - container (without the need for the directory marker objects). - """ - - url = str(container) - if params: - url += '?' - url += '&%s' % urllib.urlencode(params) - - resp, body = self.get(url, headers={}) - if params and params.get('format') == 'json': - body = json.loads(body) - elif params and params.get('format') == 'xml': - body = etree.fromstring(body) - self.expected_success([200, 204], resp.status) - return resp, body diff --git a/test/tempest/tempest/services/object_storage/object_client.py b/test/tempest/tempest/services/object_storage/object_client.py deleted file mode 100644 index 3466c8af..00000000 --- a/test/tempest/tempest/services/object_storage/object_client.py +++ /dev/null @@ -1,261 +0,0 @@ -# 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 urllib - -from six.moves import http_client as httplib -from six.moves.urllib import parse as urlparse - -from tempest.common import service_client - - -class ObjectClient(service_client.ServiceClient): - - def create_object(self, container, object_name, data, - params=None, metadata=None, headers=None): - """Create storage object.""" - - if headers is None: - headers = self.get_headers() - if not data: - headers['content-length'] = '0' - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - url = "%s/%s" % (str(container), str(object_name)) - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.put(url, data, headers) - self.expected_success(201, resp.status) - return resp, body - - def update_object(self, container, object_name, data): - """Upload data to replace current storage object.""" - resp, body = self.create_object(container, object_name, data) - self.expected_success(201, resp.status) - return resp, body - - def delete_object(self, container, object_name, params=None): - """Delete storage object.""" - url = "%s/%s" % (str(container), str(object_name)) - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.delete(url, headers={}) - self.expected_success([200, 204], resp.status) - return resp, body - - def update_object_metadata(self, container, object_name, metadata, - metadata_prefix='X-Object-Meta-'): - """Add, remove, or change X-Object-Meta metadata for storage object.""" - - headers = {} - for key in metadata: - headers["%s%s" % (str(metadata_prefix), str(key))] = metadata[key] - - url = "%s/%s" % (str(container), str(object_name)) - resp, body = self.post(url, None, headers=headers) - self.expected_success(202, resp.status) - return resp, body - - def list_object_metadata(self, container, object_name): - """List all storage object X-Object-Meta- metadata.""" - - url = "%s/%s" % (str(container), str(object_name)) - resp, body = self.head(url) - self.expected_success(200, resp.status) - return resp, body - - def get_object(self, container, object_name, metadata=None): - """Retrieve object's data.""" - - headers = {} - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - - url = "{0}/{1}".format(container, object_name) - resp, body = self.get(url, headers=headers) - self.expected_success([200, 206], resp.status) - return resp, body - - def copy_object_in_same_container(self, container, src_object_name, - dest_object_name, metadata=None): - """Copy storage object's data to the new object using PUT.""" - - url = "{0}/{1}".format(container, dest_object_name) - headers = {} - headers['X-Copy-From'] = "%s/%s" % (str(container), - str(src_object_name)) - headers['content-length'] = '0' - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - - resp, body = self.put(url, None, headers=headers) - self.expected_success(201, resp.status) - return resp, body - - def copy_object_across_containers(self, src_container, src_object_name, - dst_container, dst_object_name, - metadata=None): - """Copy storage object's data to the new object using PUT.""" - - url = "{0}/{1}".format(dst_container, dst_object_name) - headers = {} - headers['X-Copy-From'] = "%s/%s" % (str(src_container), - str(src_object_name)) - headers['content-length'] = '0' - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - - resp, body = self.put(url, None, headers=headers) - self.expected_success(201, resp.status) - return resp, body - - def copy_object_2d_way(self, container, src_object_name, dest_object_name, - metadata=None): - """Copy storage object's data to the new object using COPY.""" - - url = "{0}/{1}".format(container, src_object_name) - headers = {} - headers['Destination'] = "%s/%s" % (str(container), - str(dest_object_name)) - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - - resp, body = self.copy(url, headers=headers) - self.expected_success(201, resp.status) - return resp, body - - def create_object_segments(self, container, object_name, segment, data): - """Creates object segments.""" - url = "{0}/{1}/{2}".format(container, object_name, segment) - resp, body = self.put(url, data) - self.expected_success(201, resp.status) - return resp, body - - def put_object_with_chunk(self, container, name, contents, chunk_size): - """ - Put an object with Transfer-Encoding header - """ - if self.base_url is None: - self._set_auth() - - headers = {'Transfer-Encoding': 'chunked'} - if self.token: - headers['X-Auth-Token'] = self.token - - conn = put_object_connection(self.base_url, container, name, contents, - chunk_size, headers) - - resp = conn.getresponse() - body = resp.read() - - resp_headers = {} - for header, value in resp.getheaders(): - resp_headers[header.lower()] = value - - self._error_checker('PUT', None, headers, contents, resp, body) - self.expected_success(201, resp.status) - return resp.status, resp.reason, resp_headers - - def create_object_continue(self, container, object_name, - data, metadata=None): - """Create storage object.""" - headers = {} - if metadata: - for key in metadata: - headers[str(key)] = metadata[key] - - if not data: - headers['content-length'] = '0' - - if self.base_url is None: - self._set_auth() - headers['X-Auth-Token'] = self.token - - conn = put_object_connection(self.base_url, str(container), - str(object_name), data, None, headers) - - response = conn.response_class(conn.sock, - strict=conn.strict, - method=conn._method) - version, status, reason = response._read_status() - resp = {'version': version, - 'status': str(status), - 'reason': reason} - - return resp - - -def put_object_connection(base_url, container, name, contents=None, - chunk_size=65536, headers=None, query_string=None): - """ - Helper function to make connection to put object with httplib - :param base_url: base_url of an object client - :param container: container name that the object is in - :param name: object name to put - :param contents: a string or a file like object to read object data - from; if None, a zero-byte put will be done - :param chunk_size: chunk size of data to write; it defaults to 65536; - used only if the the contents object has a 'read' - method, eg. file-like objects, ignored otherwise - :param headers: additional headers to include in the request, if any - :param query_string: if set will be appended with '?' to generated path - """ - parsed = urlparse.urlparse(base_url) - if parsed.scheme == 'https': - conn = httplib.HTTPSConnection(parsed.netloc) - else: - conn = httplib.HTTPConnection(parsed.netloc) - path = str(parsed.path) + "/" - path += "%s/%s" % (str(container), str(name)) - - if query_string: - path += '?' + query_string - if headers: - headers = dict(headers) - else: - headers = {} - if hasattr(contents, 'read'): - conn.putrequest('PUT', path) - for header, value in headers.iteritems(): - conn.putheader(header, value) - if 'Content-Length' not in headers: - if 'Transfer-Encoding' not in headers: - conn.putheader('Transfer-Encoding', 'chunked') - conn.endheaders() - chunk = contents.read(chunk_size) - while chunk: - conn.send('%x\r\n%s\r\n' % (len(chunk), chunk)) - chunk = contents.read(chunk_size) - conn.send('0\r\n\r\n') - else: - conn.endheaders() - left = headers['Content-Length'] - while left > 0: - size = chunk_size - if size > left: - size = left - chunk = contents.read(size) - conn.send(chunk) - left -= len(chunk) - else: - conn.request('PUT', path, contents, headers) - - return conn diff --git a/test/tempest/tempest/services/orchestration/__init__.py b/test/tempest/tempest/services/orchestration/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/orchestration/json/__init__.py b/test/tempest/tempest/services/orchestration/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/orchestration/json/orchestration_client.py b/test/tempest/tempest/services/orchestration/json/orchestration_client.py deleted file mode 100644 index debf39bb..00000000 --- a/test/tempest/tempest/services/orchestration/json/orchestration_client.py +++ /dev/null @@ -1,449 +0,0 @@ -# Copyright 2013 IBM Corp. -# 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 json -import re -import time -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class OrchestrationClient(service_client.ServiceClient): - - def list_stacks(self, params=None): - """Lists all stacks for a user.""" - - uri = 'stacks' - if params: - uri += '?%s' % urllib.urlencode(params) - - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['stacks']) - - def create_stack(self, name, disable_rollback=True, parameters=None, - timeout_mins=60, template=None, template_url=None, - environment=None, files=None): - if parameters is None: - parameters = {} - headers, body = self._prepare_update_create( - name, - disable_rollback, - parameters, - timeout_mins, - template, - template_url, - environment, - files) - uri = 'stacks' - resp, body = self.post(uri, headers=headers, body=body) - self.expected_success(201, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_stack(self, stack_identifier, name, disable_rollback=True, - parameters=None, timeout_mins=60, template=None, - template_url=None, environment=None, files=None): - if parameters is None: - parameters = {} - headers, body = self._prepare_update_create( - name, - disable_rollback, - parameters, - timeout_mins, - template, - template_url, - environment) - - uri = "stacks/%s" % stack_identifier - resp, body = self.put(uri, headers=headers, body=body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def _prepare_update_create(self, name, disable_rollback=True, - parameters=None, timeout_mins=60, - template=None, template_url=None, - environment=None, files=None): - if parameters is None: - parameters = {} - post_body = { - "stack_name": name, - "disable_rollback": disable_rollback, - "parameters": parameters, - "timeout_mins": timeout_mins, - "template": "HeatTemplateFormatVersion: '2012-12-12'\n", - "environment": environment, - "files": files - } - if template: - post_body['template'] = template - if template_url: - post_body['template_url'] = template_url - body = json.dumps(post_body) - - # Password must be provided on stack create so that heat - # can perform future operations on behalf of the user - headers = self.get_headers() - headers['X-Auth-Key'] = self.password - headers['X-Auth-User'] = self.user - return headers, body - - def show_stack(self, stack_identifier): - """Returns the details of a single stack.""" - url = "stacks/%s" % stack_identifier - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['stack']) - - def suspend_stack(self, stack_identifier): - """Suspend a stack.""" - url = 'stacks/%s/actions' % stack_identifier - body = {'suspend': None} - resp, body = self.post(url, json.dumps(body)) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp) - - def resume_stack(self, stack_identifier): - """Resume a stack.""" - url = 'stacks/%s/actions' % stack_identifier - body = {'resume': None} - resp, body = self.post(url, json.dumps(body)) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp) - - def list_resources(self, stack_identifier): - """Returns the details of a single resource.""" - url = "stacks/%s/resources" % stack_identifier - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['resources']) - - def show_resource(self, stack_identifier, resource_name): - """Returns the details of a single resource.""" - url = "stacks/%s/resources/%s" % (stack_identifier, resource_name) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['resource']) - - def delete_stack(self, stack_identifier): - """Deletes the specified Stack.""" - resp, _ = self.delete("stacks/%s" % str(stack_identifier)) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def wait_for_resource_status(self, stack_identifier, resource_name, - status, failure_pattern='^.*_FAILED$'): - """Waits for a Resource to reach a given status.""" - start = int(time.time()) - fail_regexp = re.compile(failure_pattern) - - while True: - try: - body = self.show_resource( - stack_identifier, resource_name) - except lib_exc.NotFound: - # ignore this, as the resource may not have - # been created yet - pass - else: - resource_name = body['resource_name'] - resource_status = body['resource_status'] - if resource_status == status: - return - if fail_regexp.search(resource_status): - raise exceptions.StackResourceBuildErrorException( - resource_name=resource_name, - stack_identifier=stack_identifier, - resource_status=resource_status, - resource_status_reason=body['resource_status_reason']) - - if int(time.time()) - start >= self.build_timeout: - message = ('Resource %s failed to reach %s status ' - '(current %s) within the required time (%s s).' % - (resource_name, - status, - resource_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - - def wait_for_stack_status(self, stack_identifier, status, - failure_pattern='^.*_FAILED$'): - """Waits for a Stack to reach a given status.""" - start = int(time.time()) - fail_regexp = re.compile(failure_pattern) - - while True: - try: - body = self.show_stack(stack_identifier) - except lib_exc.NotFound: - if status == 'DELETE_COMPLETE': - return - stack_name = body['stack_name'] - stack_status = body['stack_status'] - if stack_status == status: - return body - if fail_regexp.search(stack_status): - raise exceptions.StackBuildErrorException( - stack_identifier=stack_identifier, - stack_status=stack_status, - stack_status_reason=body['stack_status_reason']) - - if int(time.time()) - start >= self.build_timeout: - message = ('Stack %s failed to reach %s status (current: %s) ' - 'within the required time (%s s).' % - (stack_name, status, stack_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - - def show_resource_metadata(self, stack_identifier, resource_name): - """Returns the resource's metadata.""" - url = ('stacks/{stack_identifier}/resources/{resource_name}' - '/metadata'.format(**locals())) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['metadata']) - - def list_events(self, stack_identifier): - """Returns list of all events for a stack.""" - url = 'stacks/{stack_identifier}/events'.format(**locals()) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['events']) - - def list_resource_events(self, stack_identifier, resource_name): - """Returns list of all events for a resource from stack.""" - url = ('stacks/{stack_identifier}/resources/{resource_name}' - '/events'.format(**locals())) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['events']) - - def show_event(self, stack_identifier, resource_name, event_id): - """Returns the details of a single stack's event.""" - url = ('stacks/{stack_identifier}/resources/{resource_name}/events' - '/{event_id}'.format(**locals())) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['event']) - - def show_template(self, stack_identifier): - """Returns the template for the stack.""" - url = ('stacks/{stack_identifier}/template'.format(**locals())) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def _validate_template(self, post_body): - """Returns the validation request result.""" - post_body = json.dumps(post_body) - resp, body = self.post('validate', post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def validate_template(self, template, parameters=None): - """Returns the validation result for a template with parameters.""" - if parameters is None: - parameters = {} - post_body = { - 'template': template, - 'parameters': parameters, - } - return self._validate_template(post_body) - - def validate_template_url(self, template_url, parameters=None): - """Returns the validation result for a template with parameters.""" - if parameters is None: - parameters = {} - post_body = { - 'template_url': template_url, - 'parameters': parameters, - } - return self._validate_template(post_body) - - def list_resource_types(self): - """List resource types.""" - resp, body = self.get('resource_types') - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBodyList(resp, body['resource_types']) - - def show_resource_type(self, resource_type_name): - """Return the schema of a resource type.""" - url = 'resource_types/%s' % resource_type_name - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, json.loads(body)) - - def show_resource_type_template(self, resource_type_name): - """Return the template of a resource type.""" - url = 'resource_types/%s/template' % resource_type_name - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, json.loads(body)) - - def create_software_config(self, name=None, config=None, group=None, - inputs=None, outputs=None, options=None): - headers, body = self._prep_software_config_create( - name, config, group, inputs, outputs, options) - - url = 'software_configs' - resp, body = self.post(url, headers=headers, body=body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def show_software_config(self, conf_id): - """Returns a software configuration resource.""" - url = 'software_configs/%s' % str(conf_id) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def delete_software_config(self, conf_id): - """Deletes a specific software configuration.""" - url = 'software_configs/%s' % str(conf_id) - resp, _ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def create_software_deploy(self, server_id=None, config_id=None, - action=None, status=None, - input_values=None, output_values=None, - status_reason=None, signal_transport=None): - """Creates or updates a software deployment.""" - headers, body = self._prep_software_deploy_update( - None, server_id, config_id, action, status, input_values, - output_values, status_reason, signal_transport) - - url = 'software_deployments' - resp, body = self.post(url, headers=headers, body=body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def update_software_deploy(self, deploy_id=None, server_id=None, - config_id=None, action=None, status=None, - input_values=None, output_values=None, - status_reason=None, signal_transport=None): - """Creates or updates a software deployment.""" - headers, body = self._prep_software_deploy_update( - deploy_id, server_id, config_id, action, status, input_values, - output_values, status_reason, signal_transport) - - url = 'software_deployments/%s' % str(deploy_id) - resp, body = self.put(url, headers=headers, body=body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def list_software_deployments(self): - """Returns a list of all deployments.""" - url = 'software_deployments' - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def show_software_deployment(self, deploy_id): - """Returns a specific software deployment.""" - url = 'software_deployments/%s' % str(deploy_id) - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def show_software_deployment_metadata(self, server_id): - """Return a config metadata for a specific server.""" - url = 'software_deployments/metadata/%s' % server_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body) - - def delete_software_deploy(self, deploy_id): - """Deletes a specific software deployment.""" - url = 'software_deployments/%s' % str(deploy_id) - resp, _ = self.delete(url) - self.expected_success(204, resp.status) - return service_client.ResponseBody(resp) - - def _prep_software_config_create(self, name=None, conf=None, group=None, - inputs=None, outputs=None, options=None): - """Prepares a software configuration body.""" - post_body = {} - if name is not None: - post_body["name"] = name - if conf is not None: - post_body["config"] = conf - if group is not None: - post_body["group"] = group - if inputs is not None: - post_body["inputs"] = inputs - if outputs is not None: - post_body["outputs"] = outputs - if options is not None: - post_body["options"] = options - body = json.dumps(post_body) - - headers = self.get_headers() - return headers, body - - def _prep_software_deploy_update(self, deploy_id=None, server_id=None, - config_id=None, action=None, status=None, - input_values=None, output_values=None, - status_reason=None, - signal_transport=None): - """Prepares a deployment create or update (if an id was given).""" - post_body = {} - - if deploy_id is not None: - post_body["id"] = deploy_id - if server_id is not None: - post_body["server_id"] = server_id - if config_id is not None: - post_body["config_id"] = config_id - if action is not None: - post_body["action"] = action - if status is not None: - post_body["status"] = status - if input_values is not None: - post_body["input_values"] = input_values - if output_values is not None: - post_body["output_values"] = output_values - if status_reason is not None: - post_body["status_reason"] = status_reason - if signal_transport is not None: - post_body["signal_transport"] = signal_transport - body = json.dumps(post_body) - - headers = self.get_headers() - return headers, body diff --git a/test/tempest/tempest/services/telemetry/__init__.py b/test/tempest/tempest/services/telemetry/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/telemetry/json/__init__.py b/test/tempest/tempest/services/telemetry/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/telemetry/json/telemetry_client.py b/test/tempest/tempest/services/telemetry/json/telemetry_client.py deleted file mode 100644 index 0c019084..00000000 --- a/test/tempest/tempest/services/telemetry/json/telemetry_client.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright 2014 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 urllib - -from oslo_serialization import jsonutils as json - -from tempest.common import service_client - - -class TelemetryClientJSON(service_client.ServiceClient): - - version = '2' - uri_prefix = "v2" - - def deserialize(self, body): - return json.loads(body.replace("\n", "")) - - def serialize(self, body): - return json.dumps(body) - - def add_sample(self, sample_list, meter_name, meter_unit, volume, - sample_type, resource_id, **kwargs): - sample = {"counter_name": meter_name, "counter_unit": meter_unit, - "counter_volume": volume, "counter_type": sample_type, - "resource_id": resource_id} - for key in kwargs: - sample[key] = kwargs[key] - - sample_list.append(self.serialize(sample)) - return sample_list - - def create_sample(self, meter_name, sample_list): - uri = "%s/meters/%s" % (self.uri_prefix, meter_name) - body = self.serialize(sample_list) - resp, body = self.post(uri, body) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def _helper_list(self, uri, query=None, period=None): - uri_dict = {} - if query: - uri_dict = {'q.field': query[0], - 'q.op': query[1], - 'q.value': query[2]} - if period: - uri_dict['period'] = period - if uri_dict: - uri += "?%s" % urllib.urlencode(uri_dict) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBodyList(resp, body) - - def list_resources(self, query=None): - uri = '%s/resources' % self.uri_prefix - return self._helper_list(uri, query) - - def list_meters(self, query=None): - uri = '%s/meters' % self.uri_prefix - return self._helper_list(uri, query) - - def list_alarms(self, query=None): - uri = '%s/alarms' % self.uri_prefix - return self._helper_list(uri, query) - - def list_statistics(self, meter, period=None, query=None): - uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter) - return self._helper_list(uri, query, period) - - def list_samples(self, meter_id, query=None): - uri = '%s/meters/%s' % (self.uri_prefix, meter_id) - return self._helper_list(uri, query) - - def show_resource(self, resource_id): - uri = '%s/resources/%s' % (self.uri_prefix, resource_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def show_alarm(self, alarm_id): - uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def delete_alarm(self, alarm_id): - uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id) - resp, body = self.delete(uri) - self.expected_success(204, resp.status) - if body: - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def create_alarm(self, **kwargs): - uri = "%s/alarms" % self.uri_prefix - body = self.serialize(kwargs) - resp, body = self.post(uri, body) - self.expected_success(201, resp.status) - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def update_alarm(self, alarm_id, **kwargs): - uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id) - body = self.serialize(kwargs) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBody(resp, body) - - def show_alarm_state(self, alarm_id): - uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id) - resp, body = self.get(uri) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBodyData(resp, body) - - def alarm_set_state(self, alarm_id, state): - uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id) - body = self.serialize(state) - resp, body = self.put(uri, body) - self.expected_success(200, resp.status) - body = self.deserialize(body) - return service_client.ResponseBodyData(resp, body) diff --git a/test/tempest/tempest/services/volume/__init__.py b/test/tempest/tempest/services/volume/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/json/__init__.py b/test/tempest/tempest/services/volume/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/json/admin/__init__.py b/test/tempest/tempest/services/volume/json/admin/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/json/admin/volume_hosts_client.py b/test/tempest/tempest/services/volume/json/admin/volume_hosts_client.py deleted file mode 100644 index 1cd92b7d..00000000 --- a/test/tempest/tempest/services/volume/json/admin/volume_hosts_client.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2013 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 json -import urllib - -from tempest.common import service_client - - -class BaseVolumeHostsClientJSON(service_client.ServiceClient): - """ - Client class to send CRUD Volume Hosts API requests to a Cinder endpoint - """ - - def list_hosts(self, params=None): - """Lists all hosts.""" - - url = 'os-hosts' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['hosts']) - - -class VolumeHostsClientJSON(BaseVolumeHostsClientJSON): - """ - Client class to send CRUD Volume Host API V1 requests to a Cinder endpoint - """ diff --git a/test/tempest/tempest/services/volume/json/admin/volume_quotas_client.py b/test/tempest/tempest/services/volume/json/admin/volume_quotas_client.py deleted file mode 100644 index 5092afc2..00000000 --- a/test/tempest/tempest/services/volume/json/admin/volume_quotas_client.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2014 eNovance SAS -# -# 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 urllib - -from oslo_serialization import jsonutils - -from tempest.common import service_client - - -class BaseVolumeQuotasClientJSON(service_client.ServiceClient): - """ - Client class to send CRUD Volume Quotas API requests to a Cinder endpoint - """ - - TYPE = "json" - - def show_default_quota_set(self, tenant_id): - """List the default volume quota set for a tenant.""" - - url = 'os-quota-sets/%s/defaults' % tenant_id - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def show_quota_set(self, tenant_id, params=None): - """List the quota set for a tenant.""" - - url = 'os-quota-sets/%s' % tenant_id - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def show_quota_usage(self, tenant_id): - """List the quota set for a tenant.""" - - body = self.show_quota_set(tenant_id, params={'usage': True}) - return body - - def update_quota_set(self, tenant_id, gigabytes=None, volumes=None, - snapshots=None): - post_body = {} - - if gigabytes is not None: - post_body['gigabytes'] = gigabytes - - if volumes is not None: - post_body['volumes'] = volumes - - if snapshots is not None: - post_body['snapshots'] = snapshots - - post_body = jsonutils.dumps({'quota_set': post_body}) - resp, body = self.put('os-quota-sets/%s' % tenant_id, post_body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, self._parse_resp(body)) - - def delete_quota_set(self, tenant_id): - """Delete the tenant's quota set.""" - resp, body = self.delete('os-quota-sets/%s' % tenant_id) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - -class VolumeQuotasClientJSON(BaseVolumeQuotasClientJSON): - """ - Client class to send CRUD Volume Type API V1 requests to a Cinder endpoint - """ diff --git a/test/tempest/tempest/services/volume/json/admin/volume_services_client.py b/test/tempest/tempest/services/volume/json/admin/volume_services_client.py deleted file mode 100644 index 1c4433f0..00000000 --- a/test/tempest/tempest/services/volume/json/admin/volume_services_client.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2014 NEC 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 json -import urllib - -from tempest.common import service_client - - -class BaseVolumesServicesClientJSON(service_client.ServiceClient): - - def list_services(self, params=None): - url = 'os-services' - if params: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['services']) - - -class VolumesServicesClientJSON(BaseVolumesServicesClientJSON): - """Volume V1 volume services client""" diff --git a/test/tempest/tempest/services/volume/json/admin/volume_types_client.py b/test/tempest/tempest/services/volume/json/admin/volume_types_client.py deleted file mode 100644 index 93669840..00000000 --- a/test/tempest/tempest/services/volume/json/admin/volume_types_client.py +++ /dev/null @@ -1,192 +0,0 @@ -# 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 json -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client - - -class BaseVolumeTypesClientJSON(service_client.ServiceClient): - """ - Client class to send CRUD Volume Types API requests to a Cinder endpoint - """ - - def is_resource_deleted(self, resource): - # to use this method self.resource must be defined to respective value - # Resource is a dictionary containing resource id and type - # Resource : {"id" : resource_id - # "type": resource_type} - try: - if resource['type'] == "volume-type": - self.show_volume_type(resource['id']) - elif resource['type'] == "encryption-type": - body = self.show_encryption_type(resource['id']) - if not body: - return True - else: - msg = (" resource value is either not defined or incorrect.") - raise lib_exc.UnprocessableEntity(msg) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'volume-type/encryption-type' - - def list_volume_types(self, params=None): - """List all the volume_types created.""" - url = 'types' - if params is not None: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['volume_types']) - - def show_volume_type(self, volume_id): - """Returns the details of a single volume_type.""" - url = "types/%s" % str(volume_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['volume_type']) - - def create_volume_type(self, name, **kwargs): - """ - Creates a new Volume_type. - name(Required): Name of volume_type. - Following optional keyword arguments are accepted: - extra_specs: A dictionary of values to be used as extra_specs. - """ - post_body = { - 'name': name, - 'extra_specs': kwargs.get('extra_specs'), - } - - post_body = json.dumps({'volume_type': post_body}) - resp, body = self.post('types', post_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['volume_type']) - - def delete_volume_type(self, volume_id): - """Deletes the Specified Volume_type.""" - resp, body = self.delete("types/%s" % str(volume_id)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def list_volume_types_extra_specs(self, vol_type_id, params=None): - """List all the volume_types extra specs created.""" - url = 'types/%s/extra_specs' % str(vol_type_id) - if params is not None: - url += '?%s' % urllib.urlencode(params) - - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['extra_specs']) - - def show_volume_type_extra_specs(self, vol_type_id, extra_spec_name): - """Returns the details of a single volume_type extra spec.""" - url = "types/%s/extra_specs/%s" % (str(vol_type_id), - str(extra_spec_name)) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def create_volume_type_extra_specs(self, vol_type_id, extra_spec): - """ - Creates a new Volume_type extra spec. - vol_type_id: Id of volume_type. - extra_specs: A dictionary of values to be used as extra_specs. - """ - url = "types/%s/extra_specs" % str(vol_type_id) - post_body = json.dumps({'extra_specs': extra_spec}) - resp, body = self.post(url, post_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['extra_specs']) - - def delete_volume_type_extra_specs(self, vol_id, extra_spec_name): - """Deletes the Specified Volume_type extra spec.""" - resp, body = self.delete("types/%s/extra_specs/%s" % ( - (str(vol_id)), str(extra_spec_name))) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name, - extra_spec): - """ - Update a volume_type extra spec. - vol_type_id: Id of volume_type. - extra_spec_name: Name of the extra spec to be updated. - extra_spec: A dictionary of with key as extra_spec_name and the - updated value. - """ - url = "types/%s/extra_specs/%s" % (str(vol_type_id), - str(extra_spec_name)) - put_body = json.dumps(extra_spec) - resp, body = self.put(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def show_encryption_type(self, vol_type_id): - """ - Get the volume encryption type for the specified volume type. - vol_type_id: Id of volume_type. - """ - url = "/types/%s/encryption" % str(vol_type_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def create_encryption_type(self, vol_type_id, **kwargs): - """ - Create a new encryption type for the specified volume type. - - vol_type_id: Id of volume_type. - provider: Class providing encryption support. - cipher: Encryption algorithm/mode to use. - key_size: Size of the encryption key, in bits. - control_location: Notional service where encryption is performed. - """ - url = "/types/%s/encryption" % str(vol_type_id) - post_body = {} - post_body.update(kwargs) - post_body = json.dumps({'encryption': post_body}) - resp, body = self.post(url, post_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['encryption']) - - def delete_encryption_type(self, vol_type_id): - """Delete the encryption type for the specified volume-type.""" - resp, body = self.delete( - "/types/%s/encryption/provider" % str(vol_type_id)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - -class VolumeTypesClientJSON(BaseVolumeTypesClientJSON): - """Volume V1 Volume Types client""" diff --git a/test/tempest/tempest/services/volume/json/availability_zone_client.py b/test/tempest/tempest/services/volume/json/availability_zone_client.py deleted file mode 100644 index dc0388ff..00000000 --- a/test/tempest/tempest/services/volume/json/availability_zone_client.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2014 NEC 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 json - -from tempest.common import service_client - - -class BaseVolumeAvailabilityZoneClientJSON(service_client.ServiceClient): - - def list_availability_zones(self): - resp, body = self.get('os-availability-zone') - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['availabilityZoneInfo']) - - -class VolumeAvailabilityZoneClientJSON(BaseVolumeAvailabilityZoneClientJSON): - """ - Volume V1 availability zone client. - """ diff --git a/test/tempest/tempest/services/volume/json/backups_client.py b/test/tempest/tempest/services/volume/json/backups_client.py deleted file mode 100644 index 83ec1829..00000000 --- a/test/tempest/tempest/services/volume/json/backups_client.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2014 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 json -import time - -from tempest.common import service_client -from tempest import exceptions - - -class BaseBackupsClientJSON(service_client.ServiceClient): - """ - Client class to send CRUD Volume backup API requests to a Cinder endpoint - """ - - def create_backup(self, volume_id, container=None, name=None, - description=None): - """Creates a backup of volume.""" - post_body = {'volume_id': volume_id} - if container: - post_body['container'] = container - if name: - post_body['name'] = name - if description: - post_body['description'] = description - post_body = json.dumps({'backup': post_body}) - resp, body = self.post('backups', post_body) - body = json.loads(body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body['backup']) - - def restore_backup(self, backup_id, volume_id=None): - """Restore volume from backup.""" - post_body = {'volume_id': volume_id} - post_body = json.dumps({'restore': post_body}) - resp, body = self.post('backups/%s/restore' % (backup_id), post_body) - body = json.loads(body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body['restore']) - - def delete_backup(self, backup_id): - """Delete a backup of volume.""" - resp, body = self.delete('backups/%s' % (str(backup_id))) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def show_backup(self, backup_id): - """Returns the details of a single backup.""" - url = "backups/%s" % str(backup_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['backup']) - - def list_backups(self, detail=False): - """Information for all the tenant's backups.""" - url = "backups" - if detail: - url += "/detail" - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['backups']) - - def wait_for_backup_status(self, backup_id, status): - """Waits for a Backup to reach a given status.""" - body = self.show_backup(backup_id) - backup_status = body['status'] - start = int(time.time()) - - while backup_status != status: - time.sleep(self.build_interval) - body = self.show_backup(backup_id) - backup_status = body['status'] - if backup_status == 'error': - raise exceptions.VolumeBackupException(backup_id=backup_id) - - if int(time.time()) - start >= self.build_timeout: - message = ('Volume backup %s failed to reach %s status ' - '(current %s) within the required time (%s s).' % - (backup_id, status, backup_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - - -class BackupsClientJSON(BaseBackupsClientJSON): - """Volume V1 Backups client""" diff --git a/test/tempest/tempest/services/volume/json/extensions_client.py b/test/tempest/tempest/services/volume/json/extensions_client.py deleted file mode 100644 index 8a7bce7b..00000000 --- a/test/tempest/tempest/services/volume/json/extensions_client.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 json - -from tempest.common import service_client - - -class BaseExtensionsClientJSON(service_client.ServiceClient): - - def list_extensions(self): - url = 'extensions' - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['extensions']) - - -class ExtensionsClientJSON(BaseExtensionsClientJSON): - """ - Volume V1 extensions client. - """ diff --git a/test/tempest/tempest/services/volume/json/qos_client.py b/test/tempest/tempest/services/volume/json/qos_client.py deleted file mode 100644 index e9d37775..00000000 --- a/test/tempest/tempest/services/volume/json/qos_client.py +++ /dev/null @@ -1,161 +0,0 @@ -# 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 json -import time - -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class BaseQosSpecsClientJSON(service_client.ServiceClient): - """Client class to send CRUD QoS API requests""" - - def is_resource_deleted(self, qos_id): - try: - self.show_qos(qos_id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'qos' - - def wait_for_qos_operations(self, qos_id, operation, args=None): - """Waits for a qos operations to be completed. - - NOTE : operation value is required for wait_for_qos_operations() - operation = 'qos-key' / 'disassociate' / 'disassociate-all' - args = keys[] when operation = 'qos-key' - args = volume-type-id disassociated when operation = 'disassociate' - args = None when operation = 'disassociate-all' - """ - start_time = int(time.time()) - while True: - if operation == 'qos-key-unset': - body = self.show_qos(qos_id) - if not any(key in body['specs'] for key in args): - return - elif operation == 'disassociate': - body = self.show_association_qos(qos_id) - if not any(args in body[i]['id'] for i in range(0, len(body))): - return - elif operation == 'disassociate-all': - body = self.show_association_qos(qos_id) - if not body: - return - else: - msg = (" operation value is either not defined or incorrect.") - raise lib_exc.UnprocessableEntity(msg) - - if int(time.time()) - start_time >= self.build_timeout: - raise exceptions.TimeoutException - time.sleep(self.build_interval) - - def create_qos(self, name, consumer, **kwargs): - """Create a QoS Specification. - - name : name of the QoS specifications - consumer : conumer of Qos ( front-end / back-end / both ) - """ - post_body = {'name': name, 'consumer': consumer} - post_body.update(kwargs) - post_body = json.dumps({'qos_specs': post_body}) - resp, body = self.post('qos-specs', post_body) - self.expected_success(200, resp.status) - body = json.loads(body) - return service_client.ResponseBody(resp, body['qos_specs']) - - def delete_qos(self, qos_id, force=False): - """Delete the specified QoS specification.""" - resp, body = self.delete( - "qos-specs/%s?force=%s" % (str(qos_id), force)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def list_qos(self): - """List all the QoS specifications created.""" - url = 'qos-specs' - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['qos_specs']) - - def show_qos(self, qos_id): - """Get the specified QoS specification.""" - url = "qos-specs/%s" % str(qos_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['qos_specs']) - - def set_qos_key(self, qos_id, **kwargs): - """Set the specified keys/values of QoS specification. - - kwargs : it is the dictionary of the key=value pairs to set - """ - put_body = json.dumps({"qos_specs": kwargs}) - resp, body = self.put('qos-specs/%s' % qos_id, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['qos_specs']) - - def unset_qos_key(self, qos_id, keys): - """Unset the specified keys of QoS specification. - - keys : it is the array of the keys to unset - """ - put_body = json.dumps({'keys': keys}) - resp, body = self.put('qos-specs/%s/delete_keys' % qos_id, put_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def associate_qos(self, qos_id, vol_type_id): - """Associate the specified QoS with specified volume-type.""" - url = "qos-specs/%s/associate" % str(qos_id) - url += "?vol_type_id=%s" % vol_type_id - resp, body = self.get(url) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def show_association_qos(self, qos_id): - """Get the association of the specified QoS specification.""" - url = "qos-specs/%s/associations" % str(qos_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['qos_associations']) - - def disassociate_qos(self, qos_id, vol_type_id): - """Disassociate the specified QoS with specified volume-type.""" - url = "qos-specs/%s/disassociate" % str(qos_id) - url += "?vol_type_id=%s" % vol_type_id - resp, body = self.get(url) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def disassociate_all_qos(self, qos_id): - """Disassociate the specified QoS with all associations.""" - url = "qos-specs/%s/disassociate_all" % str(qos_id) - resp, body = self.get(url) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - -class QosSpecsClientJSON(BaseQosSpecsClientJSON): - """Volume V1 QoS client.""" diff --git a/test/tempest/tempest/services/volume/json/snapshots_client.py b/test/tempest/tempest/services/volume/json/snapshots_client.py deleted file mode 100644 index 2140c62a..00000000 --- a/test/tempest/tempest/services/volume/json/snapshots_client.py +++ /dev/null @@ -1,202 +0,0 @@ -# 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 json -import time -import urllib - -from oslo_log import log as logging -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -LOG = logging.getLogger(__name__) - - -class BaseSnapshotsClientJSON(service_client.ServiceClient): - """Base Client class to send CRUD Volume API requests.""" - - create_resp = 200 - - def list_snapshots(self, detail=False, params=None): - """List all the snapshot.""" - url = 'snapshots' - 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) - return service_client.ResponseBodyList(resp, body['snapshots']) - - def show_snapshot(self, snapshot_id): - """Returns the details of a single snapshot.""" - url = "snapshots/%s" % str(snapshot_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['snapshot']) - - def create_snapshot(self, volume_id, **kwargs): - """ - Creates a new snapshot. - volume_id(Required): id of the volume. - force: Create a snapshot even if the volume attached (Default=False) - display_name: Optional snapshot Name. - display_description: User friendly snapshot description. - """ - post_body = {'volume_id': volume_id} - post_body.update(kwargs) - post_body = json.dumps({'snapshot': post_body}) - resp, body = self.post('snapshots', post_body) - body = json.loads(body) - self.expected_success(self.create_resp, resp.status) - return service_client.ResponseBody(resp, body['snapshot']) - - def update_snapshot(self, snapshot_id, **kwargs): - """Updates a snapshot.""" - put_body = json.dumps({'snapshot': kwargs}) - resp, body = self.put('snapshots/%s' % snapshot_id, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['snapshot']) - - # NOTE(afazekas): just for the wait function - def _get_snapshot_status(self, snapshot_id): - body = self.show_snapshot(snapshot_id) - status = body['status'] - # NOTE(afazekas): snapshot can reach an "error" - # state in a "normal" lifecycle - if (status == 'error'): - raise exceptions.SnapshotBuildErrorException( - snapshot_id=snapshot_id) - - return status - - # NOTE(afazkas): Wait reinvented again. It is not in the correct layer - def wait_for_snapshot_status(self, snapshot_id, status): - """Waits for a Snapshot to reach a given status.""" - start_time = time.time() - old_value = value = self._get_snapshot_status(snapshot_id) - while True: - dtime = time.time() - start_time - time.sleep(self.build_interval) - if value != old_value: - LOG.info('Value transition from "%s" to "%s"' - 'in %d second(s).', old_value, - value, dtime) - if (value == status): - return value - - if dtime > self.build_timeout: - message = ('Time Limit Exceeded! (%ds)' - 'while waiting for %s, ' - 'but we got %s.' % - (self.build_timeout, status, value)) - raise exceptions.TimeoutException(message) - time.sleep(self.build_interval) - old_value = value - value = self._get_snapshot_status(snapshot_id) - - def delete_snapshot(self, snapshot_id): - """Delete Snapshot.""" - resp, body = self.delete("snapshots/%s" % str(snapshot_id)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def is_resource_deleted(self, id): - try: - self.show_snapshot(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'volume-snapshot' - - def reset_snapshot_status(self, snapshot_id, status): - """Reset the specified snapshot's status.""" - post_body = json.dumps({'os-reset_status': {"status": status}}) - resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def update_snapshot_status(self, snapshot_id, status, progress): - """Update the specified snapshot's status.""" - post_body = { - 'status': status, - 'progress': progress - } - post_body = json.dumps({'os-update_snapshot_status': post_body}) - url = 'snapshots/%s/action' % str(snapshot_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def create_snapshot_metadata(self, snapshot_id, metadata): - """Create metadata for the snapshot.""" - put_body = json.dumps({'metadata': metadata}) - url = "snapshots/%s/metadata" % str(snapshot_id) - resp, body = self.post(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def show_snapshot_metadata(self, snapshot_id): - """Get metadata of the snapshot.""" - url = "snapshots/%s/metadata" % str(snapshot_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def update_snapshot_metadata(self, snapshot_id, metadata): - """Update metadata for the snapshot.""" - put_body = json.dumps({'metadata': metadata}) - url = "snapshots/%s/metadata" % str(snapshot_id) - resp, body = self.put(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def update_snapshot_metadata_item(self, snapshot_id, id, meta_item): - """Update metadata item for the snapshot.""" - put_body = json.dumps({'meta': meta_item}) - url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id)) - resp, body = self.put(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['meta']) - - def delete_snapshot_metadata_item(self, snapshot_id, id): - """Delete metadata item for the snapshot.""" - url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id)) - resp, body = self.delete(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def force_delete_snapshot(self, snapshot_id): - """Force Delete Snapshot.""" - post_body = json.dumps({'os-force_delete': {}}) - resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - -class SnapshotsClientJSON(BaseSnapshotsClientJSON): - """Client class to send CRUD Volume V1 API requests.""" diff --git a/test/tempest/tempest/services/volume/json/volumes_client.py b/test/tempest/tempest/services/volume/json/volumes_client.py deleted file mode 100644 index a82291a7..00000000 --- a/test/tempest/tempest/services/volume/json/volumes_client.py +++ /dev/null @@ -1,342 +0,0 @@ -# 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 json -import time -import urllib - -from tempest_lib import exceptions as lib_exc - -from tempest.common import service_client -from tempest import exceptions - - -class BaseVolumesClientJSON(service_client.ServiceClient): - """ - Base client class to send CRUD Volume API requests to a Cinder endpoint - """ - - create_resp = 200 - - def __init__(self, auth_provider, service, region, - default_volume_size=1, **kwargs): - super(BaseVolumesClientJSON, self).__init__( - auth_provider, service, region, **kwargs) - self.default_volume_size = default_volume_size - - def get_attachment_from_volume(self, volume): - """Return the element 'attachment' from input volumes.""" - return volume['attachments'][0] - - def list_volumes(self, detail=False, params=None): - """List all the volumes created.""" - url = 'volumes' - 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) - return service_client.ResponseBodyList(resp, body['volumes']) - - def show_volume(self, volume_id): - """Returns the details of a single volume.""" - url = "volumes/%s" % str(volume_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['volume']) - - def create_volume(self, size=None, **kwargs): - """ - Creates a new Volume. - size: Size of volume in GB. - Following optional keyword arguments are accepted: - display_name: Optional Volume Name(only for V1). - name: Optional Volume Name(only for V2). - metadata: A dictionary of values to be used as metadata. - volume_type: Optional Name of volume_type for the volume - snapshot_id: When specified the volume is created from this snapshot - imageRef: When specified the volume is created from this image - """ - if size is None: - size = self.default_volume_size - post_body = {'size': size} - post_body.update(kwargs) - post_body = json.dumps({'volume': post_body}) - resp, body = self.post('volumes', post_body) - body = json.loads(body) - self.expected_success(self.create_resp, resp.status) - return service_client.ResponseBody(resp, body['volume']) - - def update_volume(self, volume_id, **kwargs): - """Updates the Specified Volume.""" - put_body = json.dumps({'volume': kwargs}) - resp, body = self.put('volumes/%s' % volume_id, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['volume']) - - def delete_volume(self, volume_id): - """Deletes the Specified Volume.""" - resp, body = self.delete("volumes/%s" % str(volume_id)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def upload_volume(self, volume_id, image_name, disk_format): - """Uploads a volume in Glance.""" - post_body = { - 'image_name': image_name, - 'disk_format': disk_format - } - post_body = json.dumps({'os-volume_upload_image': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - body = json.loads(body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, - body['os-volume_upload_image']) - - def attach_volume(self, volume_id, instance_uuid, mountpoint): - """Attaches a volume to a given instance on a given mountpoint.""" - post_body = { - 'instance_uuid': instance_uuid, - 'mountpoint': mountpoint, - } - post_body = json.dumps({'os-attach': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def detach_volume(self, volume_id): - """Detaches a volume from an instance.""" - post_body = {} - post_body = json.dumps({'os-detach': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def reserve_volume(self, volume_id): - """Reserves a volume.""" - post_body = {} - post_body = json.dumps({'os-reserve': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def unreserve_volume(self, volume_id): - """Restore a reserved volume .""" - post_body = {} - post_body = json.dumps({'os-unreserve': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def wait_for_volume_status(self, volume_id, status): - """Waits for a Volume to reach a given status.""" - body = self.show_volume(volume_id) - volume_status = body['status'] - start = int(time.time()) - - while volume_status != status: - time.sleep(self.build_interval) - body = self.show_volume(volume_id) - volume_status = body['status'] - if volume_status == 'error': - raise exceptions.VolumeBuildErrorException(volume_id=volume_id) - - if int(time.time()) - start >= self.build_timeout: - message = ('Volume %s failed to reach %s status (current: %s) ' - 'within the required time ' - '(%s s).' % (volume_id, - status, - volume_status, - self.build_timeout)) - raise exceptions.TimeoutException(message) - - def is_resource_deleted(self, id): - try: - self.show_volume(id) - except lib_exc.NotFound: - return True - return False - - @property - def resource_type(self): - """Returns the primary type of resource this client works with.""" - return 'volume' - - def extend_volume(self, volume_id, extend_size): - """Extend a volume.""" - post_body = { - 'new_size': extend_size - } - post_body = json.dumps({'os-extend': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def reset_volume_status(self, volume_id, status): - """Reset the Specified Volume's Status.""" - post_body = json.dumps({'os-reset_status': {"status": status}}) - resp, body = self.post('volumes/%s/action' % volume_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def volume_begin_detaching(self, volume_id): - """Volume Begin Detaching.""" - # ref cinder/api/contrib/volume_actions.py#L158 - post_body = json.dumps({'os-begin_detaching': {}}) - resp, body = self.post('volumes/%s/action' % volume_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def volume_roll_detaching(self, volume_id): - """Volume Roll Detaching.""" - # cinder/api/contrib/volume_actions.py#L170 - post_body = json.dumps({'os-roll_detaching': {}}) - resp, body = self.post('volumes/%s/action' % volume_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def create_volume_transfer(self, vol_id, display_name=None): - """Create a volume transfer.""" - post_body = { - 'volume_id': vol_id - } - if display_name: - post_body['name'] = display_name - post_body = json.dumps({'transfer': post_body}) - resp, body = self.post('os-volume-transfer', post_body) - body = json.loads(body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body['transfer']) - - def show_volume_transfer(self, transfer_id): - """Returns the details of a volume transfer.""" - url = "os-volume-transfer/%s" % str(transfer_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['transfer']) - - def list_volume_transfers(self, params=None): - """List all the volume transfers created.""" - url = 'os-volume-transfer' - if params: - url += '?%s' % urllib.urlencode(params) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBodyList(resp, body['transfers']) - - def delete_volume_transfer(self, transfer_id): - """Delete a volume transfer.""" - resp, body = self.delete("os-volume-transfer/%s" % str(transfer_id)) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def accept_volume_transfer(self, transfer_id, transfer_auth_key): - """Accept a volume transfer.""" - post_body = { - 'auth_key': transfer_auth_key, - } - url = 'os-volume-transfer/%s/accept' % transfer_id - post_body = json.dumps({'accept': post_body}) - resp, body = self.post(url, post_body) - body = json.loads(body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body['transfer']) - - def update_volume_readonly(self, volume_id, readonly): - """Update the Specified Volume readonly.""" - post_body = { - 'readonly': readonly - } - post_body = json.dumps({'os-update_readonly_flag': post_body}) - url = 'volumes/%s/action' % (volume_id) - resp, body = self.post(url, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def force_delete_volume(self, volume_id): - """Force Delete Volume.""" - post_body = json.dumps({'os-force_delete': {}}) - resp, body = self.post('volumes/%s/action' % volume_id, post_body) - self.expected_success(202, resp.status) - return service_client.ResponseBody(resp, body) - - def create_volume_metadata(self, volume_id, metadata): - """Create metadata for the volume.""" - put_body = json.dumps({'metadata': metadata}) - url = "volumes/%s/metadata" % str(volume_id) - resp, body = self.post(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def show_volume_metadata(self, volume_id): - """Get metadata of the volume.""" - url = "volumes/%s/metadata" % str(volume_id) - resp, body = self.get(url) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def update_volume_metadata(self, volume_id, metadata): - """Update metadata for the volume.""" - put_body = json.dumps({'metadata': metadata}) - url = "volumes/%s/metadata" % str(volume_id) - resp, body = self.put(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['metadata']) - - def update_volume_metadata_item(self, volume_id, id, meta_item): - """Update metadata item for the volume.""" - put_body = json.dumps({'meta': meta_item}) - url = "volumes/%s/metadata/%s" % (str(volume_id), str(id)) - resp, body = self.put(url, put_body) - body = json.loads(body) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body['meta']) - - def delete_volume_metadata_item(self, volume_id, id): - """Delete metadata item for the volume.""" - url = "volumes/%s/metadata/%s" % (str(volume_id), str(id)) - resp, body = self.delete(url) - self.expected_success(200, resp.status) - return service_client.ResponseBody(resp, body) - - def retype_volume(self, volume_id, volume_type, **kwargs): - """Updates volume with new volume type.""" - post_body = {'new_type': volume_type} - post_body.update(kwargs) - post_body = json.dumps({'os-retype': post_body}) - resp, body = self.post('volumes/%s/action' % volume_id, post_body) - self.expected_success(202, resp.status) - - -class VolumesClientJSON(BaseVolumesClientJSON): - """ - Client class to send CRUD Volume V1 API requests to a Cinder endpoint - """ diff --git a/test/tempest/tempest/services/volume/v2/__init__.py b/test/tempest/tempest/services/volume/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/v2/json/__init__.py b/test/tempest/tempest/services/volume/v2/json/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/v2/json/admin/__init__.py b/test/tempest/tempest/services/volume/v2/json/admin/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/tempest/tempest/services/volume/v2/json/admin/volume_hosts_client.py b/test/tempest/tempest/services/volume/v2/json/admin/volume_hosts_client.py deleted file mode 100644 index b93d0319..00000000 --- a/test/tempest/tempest/services/volume/v2/json/admin/volume_hosts_client.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from tempest.services.volume.json.admin import volume_hosts_client - - -class VolumeHostsV2ClientJSON(volume_hosts_client.BaseVolumeHostsClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/test/tempest/tempest/services/volume/v2/json/admin/volume_quotas_client.py deleted file mode 100644 index 1dc48cd7..00000000 --- a/test/tempest/tempest/services/volume/v2/json/admin/volume_quotas_client.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.services.volume.json.admin import volume_quotas_client - - -class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/admin/volume_services_client.py b/test/tempest/tempest/services/volume/v2/json/admin/volume_services_client.py deleted file mode 100644 index 51224c52..00000000 --- a/test/tempest/tempest/services/volume/v2/json/admin/volume_services_client.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.services.volume.json.admin import volume_services_client as vs_cli - - -class VolumesServicesV2ClientJSON(vs_cli.BaseVolumesServicesClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/admin/volume_types_client.py b/test/tempest/tempest/services/volume/v2/json/admin/volume_types_client.py deleted file mode 100644 index 24099b2f..00000000 --- a/test/tempest/tempest/services/volume/v2/json/admin/volume_types_client.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - - -from tempest.services.volume.json.admin import volume_types_client - - -class VolumeTypesV2ClientJSON(volume_types_client.BaseVolumeTypesClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/availability_zone_client.py b/test/tempest/tempest/services/volume/v2/json/availability_zone_client.py deleted file mode 100644 index dc856348..00000000 --- a/test/tempest/tempest/services/volume/v2/json/availability_zone_client.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2014 IBM Corp. -# 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.services.volume.json import availability_zone_client - - -class VolumeV2AvailabilityZoneClientJSON( - availability_zone_client.BaseVolumeAvailabilityZoneClientJSON): - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/backups_client.py b/test/tempest/tempest/services/volume/v2/json/backups_client.py deleted file mode 100644 index 30d9e8eb..00000000 --- a/test/tempest/tempest/services/volume/v2/json/backups_client.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.services.volume.json import backups_client - - -class BackupsClientV2JSON(backups_client.BaseBackupsClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/extensions_client.py b/test/tempest/tempest/services/volume/v2/json/extensions_client.py deleted file mode 100644 index 8dda833a..00000000 --- a/test/tempest/tempest/services/volume/v2/json/extensions_client.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2014 IBM Corp. -# 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.services.volume.json import extensions_client - - -class ExtensionsV2ClientJSON(extensions_client.BaseExtensionsClientJSON): - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/qos_client.py b/test/tempest/tempest/services/volume/v2/json/qos_client.py deleted file mode 100644 index d17da6d6..00000000 --- a/test/tempest/tempest/services/volume/v2/json/qos_client.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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.services.volume.json import qos_client - - -class QosSpecsV2ClientJSON(qos_client.BaseQosSpecsClientJSON): - api_version = "v2" diff --git a/test/tempest/tempest/services/volume/v2/json/snapshots_client.py b/test/tempest/tempest/services/volume/v2/json/snapshots_client.py deleted file mode 100644 index 90580f93..00000000 --- a/test/tempest/tempest/services/volume/v2/json/snapshots_client.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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.services.volume.json import snapshots_client - - -class SnapshotsV2ClientJSON(snapshots_client.BaseSnapshotsClientJSON): - """Client class to send CRUD Volume V2 API requests.""" - api_version = "v2" - create_resp = 202 diff --git a/test/tempest/tempest/services/volume/v2/json/volumes_client.py b/test/tempest/tempest/services/volume/v2/json/volumes_client.py deleted file mode 100644 index 85ffb912..00000000 --- a/test/tempest/tempest/services/volume/v2/json/volumes_client.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - -from tempest.services.volume.json import volumes_client - - -class VolumesV2ClientJSON(volumes_client.BaseVolumesClientJSON): - """ - Client class to send CRUD Volume V2 API requests to a Cinder endpoint - """ - api_version = "v2" - create_resp = 202 diff --git a/test/tempest/tempest/test.py b/test/tempest/tempest/test.py deleted file mode 100755 index f22796bd..00000000 --- a/test/tempest/tempest/test.py +++ /dev/null @@ -1,767 +0,0 @@ -# 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 atexit -import functools -import json -import os -import re -import sys -import time -import urllib -import uuid - -import fixtures -from oslo_log import log as logging -from oslo_utils import importutils -import six -import testscenarios -import testtools - -from tempest import clients -from tempest.common import credentials -from tempest.common import fixed_network -import tempest.common.generator.valid_generator as valid -from tempest import config -from tempest import exceptions - -from tempest_lib.common.utils import misc - -LOG = logging.getLogger(__name__) - -CONF = config.CONF - - -def attr(*args, **kwargs): - """A decorator which applies the testtools attr decorator - - This decorator applies the testtools.testcase.attr if it is in the list of - attributes to testtools we want to apply. - """ - - def decorator(f): - if 'type' in kwargs and isinstance(kwargs['type'], str): - f = testtools.testcase.attr(kwargs['type'])(f) - elif 'type' in kwargs and isinstance(kwargs['type'], list): - for attr in kwargs['type']: - f = testtools.testcase.attr(attr)(f) - return f - - return decorator - - -def idempotent_id(id): - """Stub for metadata decorator""" - if not isinstance(id, six.string_types): - raise TypeError('Test idempotent_id must be string not %s' - '' % type(id).__name__) - uuid.UUID(id) - - def decorator(f): - f = testtools.testcase.attr('id-%s' % id)(f) - if f.__doc__: - f.__doc__ = 'Test idempotent id: %s\n%s' % (id, f.__doc__) - else: - f.__doc__ = 'Test idempotent id: %s' % id - return f - return decorator - - -def get_service_list(): - service_list = { - 'compute': CONF.service_available.nova, - 'image': CONF.service_available.glance, - 'baremetal': CONF.service_available.ironic, - 'volume': CONF.service_available.cinder, - 'orchestration': CONF.service_available.heat, - # NOTE(mtreinish) nova-network will provide networking functionality - # if neutron isn't available, so always set to True. - 'network': True, - 'identity': True, - 'object_storage': CONF.service_available.swift, - 'dashboard': CONF.service_available.horizon, - 'telemetry': CONF.service_available.ceilometer, - 'data_processing': CONF.service_available.sahara, - 'database': CONF.service_available.trove - } - return service_list - - -def services(*args, **kwargs): - """A decorator used to set an attr for each service used in a test case - - This decorator applies a testtools attr for each service that gets - exercised by a test case. - """ - def decorator(f): - services = ['compute', 'image', 'baremetal', 'volume', 'orchestration', - 'network', 'identity', 'object_storage', 'dashboard', - 'telemetry', 'data_processing', 'database'] - for service in args: - if service not in services: - raise exceptions.InvalidServiceTag('%s is not a valid ' - 'service' % service) - attr(type=list(args))(f) - - @functools.wraps(f) - def wrapper(self, *func_args, **func_kwargs): - service_list = get_service_list() - - for service in args: - if not service_list[service]: - msg = 'Skipped because the %s service is not available' % ( - service) - raise testtools.TestCase.skipException(msg) - return f(self, *func_args, **func_kwargs) - return wrapper - return decorator - - -def stresstest(*args, **kwargs): - """Add stress test decorator - - For all functions with this decorator a attr stress will be - set automatically. - - @param class_setup_per: allowed values are application, process, action - ``application``: once in the stress job lifetime - ``process``: once in the worker process lifetime - ``action``: on each action - @param allow_inheritance: allows inheritance of this attribute - """ - def decorator(f): - if 'class_setup_per' in kwargs: - setattr(f, "st_class_setup_per", kwargs['class_setup_per']) - else: - setattr(f, "st_class_setup_per", 'process') - if 'allow_inheritance' in kwargs: - setattr(f, "st_allow_inheritance", kwargs['allow_inheritance']) - else: - setattr(f, "st_allow_inheritance", False) - attr(type='stress')(f) - return f - return decorator - - -def requires_ext(*args, **kwargs): - """A decorator to skip tests if an extension is not enabled - - @param extension - @param service - """ - def decorator(func): - @functools.wraps(func) - def wrapper(*func_args, **func_kwargs): - if not is_extension_enabled(kwargs['extension'], - kwargs['service']): - msg = "Skipped because %s extension: %s is not enabled" % ( - kwargs['service'], kwargs['extension']) - raise testtools.TestCase.skipException(msg) - return func(*func_args, **func_kwargs) - return wrapper - return decorator - - -def is_extension_enabled(extension_name, service): - """A function that will check the list of enabled extensions from config - - """ - config_dict = { - 'compute': CONF.compute_feature_enabled.api_extensions, - 'volume': CONF.volume_feature_enabled.api_extensions, - 'network': CONF.network_feature_enabled.api_extensions, - 'object': CONF.object_storage_feature_enabled.discoverable_apis, - } - if len(config_dict[service]) == 0: - return False - if config_dict[service][0] == 'all': - return True - if extension_name in config_dict[service]: - return True - return False - - -at_exit_set = set() - - -def validate_tearDownClass(): - if at_exit_set: - LOG.error( - "tearDownClass does not call the super's " - "tearDownClass in these classes: \n" + - str(at_exit_set)) - - -atexit.register(validate_tearDownClass) - - -class BaseTestCase(testtools.testcase.WithAttributes, - testtools.TestCase): - """The test base class defines Tempest framework for class level fixtures. - `setUpClass` and `tearDownClass` are defined here and cannot be overwritten - by subclasses (enforced via hacking rule T105). - - Set-up is split in a series of steps (setup stages), which can be - overwritten by test classes. Set-up stages are: - - skip_checks - - setup_credentials - - setup_clients - - resource_setup - - Tear-down is also split in a series of steps (teardown stages), which are - stacked for execution only if the corresponding setup stage had been - reached during the setup phase. Tear-down stages are: - - clear_isolated_creds (defined in the base test class) - - resource_cleanup - """ - - setUpClassCalled = False - _service = None - - # NOTE(andreaf) credentials holds a list of the credentials to be allocated - # at class setup time. Credential types can be 'primary', 'alt' or 'admin' - credentials = [] - network_resources = {} - - # NOTE(sdague): log_format is defined inline here instead of using the oslo - # default because going through the config path recouples config to the - # stress tests too early, and depending on testr order will fail unit tests - log_format = ('%(asctime)s %(process)d %(levelname)-8s ' - '[%(name)s] %(message)s') - - @classmethod - def setUpClass(cls): - # It should never be overridden by descendants - if hasattr(super(BaseTestCase, cls), 'setUpClass'): - super(BaseTestCase, cls).setUpClass() - cls.setUpClassCalled = True - # Stack of (name, callable) to be invoked in reverse order at teardown - cls.teardowns = [] - # All the configuration checks that may generate a skip - cls.skip_checks() - try: - # Allocation of all required credentials and client managers - cls.teardowns.append(('credentials', cls.clear_isolated_creds)) - cls.setup_credentials() - # Shortcuts to clients - cls.setup_clients() - # Additional class-wide test resources - cls.teardowns.append(('resources', cls.resource_cleanup)) - cls.resource_setup() - except Exception: - etype, value, trace = sys.exc_info() - LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass." % ( - etype, cls.__name__)) - cls.tearDownClass() - try: - raise etype, value, trace - finally: - del trace # to avoid circular refs - - @classmethod - def tearDownClass(cls): - at_exit_set.discard(cls) - # It should never be overridden by descendants - if hasattr(super(BaseTestCase, cls), 'tearDownClass'): - super(BaseTestCase, cls).tearDownClass() - # Save any existing exception, we always want to re-raise the original - # exception only - etype, value, trace = sys.exc_info() - # If there was no exception during setup we shall re-raise the first - # exception in teardown - re_raise = (etype is None) - while cls.teardowns: - name, teardown = cls.teardowns.pop() - # Catch any exception in tearDown so we can re-raise the original - # exception at the end - try: - teardown() - except Exception as te: - sys_exec_info = sys.exc_info() - tetype = sys_exec_info[0] - # TODO(andreaf): Till we have the ability to cleanup only - # resources that were successfully setup in resource_cleanup, - # log AttributeError as info instead of exception. - if tetype is AttributeError and name == 'resources': - LOG.info("tearDownClass of %s failed: %s" % (name, te)) - else: - LOG.exception("teardown of %s failed: %s" % (name, te)) - if not etype: - etype, value, trace = sys_exec_info - # If exceptions were raised during teardown, an not before, re-raise - # the first one - if re_raise and etype is not None: - try: - raise etype, value, trace - finally: - del trace # to avoid circular refs - - @classmethod - def sdn_skip_check(cls): - if not hasattr(cls, 'is_sdn'): - BaseTestCase.is_sdn = misc.sdn_skip_check() - - if BaseTestCase.is_sdn: - raise testtools.TestCase.skipException( - "skip : SDN not support this function") - - @classmethod - def dvs_skip_check(cls): - if not hasattr(cls, 'is_dvs'): - BaseTestCase.is_dvs = misc.dvs_skip_check() - - if BaseTestCase.is_dvs: - raise testtools.TestCase.skipException( - "skip : DVS not support this function") - - @classmethod - def lvm_skip_check(cls): - if not hasattr(cls, 'is_lvm'): - BaseTestCase.is_lvm = misc.lvm_skip_check() - - if BaseTestCase.is_lvm: - raise testtools.TestCase.skipException("skip: don't support LVM") - - @classmethod - def connectvm_skip_check(cls): - if not hasattr(cls, 'can_connect_vm'): - BaseTestCase.can_connect_vm =\ - (CONF.network.tenant_networks_reachable or - CONF.compute.use_floatingip_for_ssh) - - if not BaseTestCase.can_connect_vm: - raise testtools.TestCase.skipException("skip : no network " - "reachable to ssh vm") - - @classmethod - def skip_checks(cls): - """Class level skip checks. Subclasses verify in here all - conditions that might prevent the execution of the entire test class. - Checks implemented here may not make use API calls, and should rely on - configuration alone. - In general skip checks that require an API call are discouraged. - If one is really needed it may be implemented either in the - resource_setup or at test level. - """ - if 'admin' in cls.credentials and not credentials.is_admin_available(): - msg = "Missing Identity Admin API credentials in configuration." - raise cls.skipException(msg) - if 'alt' is cls.credentials and not credentials.is_alt_available(): - msg = "Missing a 2nd set of API credentials in configuration." - raise cls.skipException(msg) - - @classmethod - def setup_credentials(cls): - """Allocate credentials and the client managers from them. - A test class that requires network resources must override - setup_credentials and defined the required resources before super - is invoked. - """ - for credentials_type in cls.credentials: - # This may raise an exception in case credentials are not available - # In that case we want to let the exception through and the test - # fail accordingly - manager = cls.get_client_manager( - credential_type=credentials_type) - setattr(cls, 'os_%s' % credentials_type, manager) - # Setup some common aliases - # TODO(andreaf) The aliases below are a temporary hack - # to avoid changing too much code in one patch. They should - # be removed eventually - if credentials_type == 'primary': - cls.os = cls.manager = cls.os_primary - if credentials_type == 'admin': - cls.os_adm = cls.admin_manager = cls.os_admin - if credentials_type == 'alt': - cls.alt_manager = cls.os_alt - - @classmethod - def setup_clients(cls): - """Create links to the clients into the test object.""" - # TODO(andreaf) There is a fair amount of code that could me moved from - # base / test classes in here. Ideally tests should be able to only - # specify which client is `client` and nothing else. - pass - - @classmethod - def resource_setup(cls): - """Class level resource setup for test cases. - """ - pass - - @classmethod - def resource_cleanup(cls): - """Class level resource cleanup for test cases. - Resource cleanup must be able to handle the case of partially setup - resources, in case a failure during `resource_setup` should happen. - """ - pass - - def setUp(self): - super(BaseTestCase, self).setUp() - if not self.setUpClassCalled: - raise RuntimeError("setUpClass does not calls the super's" - "setUpClass in the " + - self.__class__.__name__) - at_exit_set.add(self.__class__) - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) - try: - test_timeout = int(test_timeout) - except ValueError: - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) - - if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or - os.environ.get('OS_STDOUT_CAPTURE') == '1'): - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or - os.environ.get('OS_STDERR_CAPTURE') == '1'): - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - if (os.environ.get('OS_LOG_CAPTURE') != 'False' and - os.environ.get('OS_LOG_CAPTURE') != '0'): - self.useFixture(fixtures.LoggerFixture(nuke_handlers=False, - format=self.log_format, - level=None)) - - @classmethod - def get_client_manager(cls, identity_version=None, - credential_type='primary'): - """ - Returns an OpenStack client manager - """ - force_tenant_isolation = getattr(cls, 'force_tenant_isolation', None) - identity_version = identity_version or CONF.identity.auth_version - - if (not hasattr(cls, 'isolated_creds') or - not cls.isolated_creds.name == cls.__name__): - cls.isolated_creds = credentials.get_isolated_credentials( - name=cls.__name__, network_resources=cls.network_resources, - force_tenant_isolation=force_tenant_isolation, - identity_version=identity_version - ) - - credentials_method = 'get_%s_creds' % credential_type - if hasattr(cls.isolated_creds, credentials_method): - creds = getattr(cls.isolated_creds, credentials_method)() - else: - raise exceptions.InvalidCredentials( - "Invalid credentials type %s" % credential_type) - os = clients.Manager(credentials=creds, service=cls._service) - return os - - @classmethod - def clear_isolated_creds(cls): - """ - Clears isolated creds if set - """ - if hasattr(cls, 'isolated_creds'): - cls.isolated_creds.clear_isolated_creds() - - @classmethod - def set_network_resources(cls, network=False, router=False, subnet=False, - dhcp=False): - """Specify which network resources should be created - - @param network - @param router - @param subnet - @param dhcp - """ - # network resources should be set only once from callers - # in order to ensure that even if it's called multiple times in - # a chain of overloaded methods, the attribute is set only - # in the leaf class - if not cls.network_resources: - cls.network_resources = { - 'network': network, - 'router': router, - 'subnet': subnet, - 'dhcp': dhcp} - - @classmethod - def get_tenant_network(cls): - """Get the network to be used in testing - - :return: network dict including 'id' and 'name' - """ - # Make sure isolated_creds exists and get a network client - networks_client = cls.get_client_manager().networks_client - isolated_creds = getattr(cls, 'isolated_creds', None) - # In case of nova network, isolated tenants are not able to list the - # network configured in fixed_network_name, even if the can use it - # for their servers, so using an admin network client to validate - # the network name - if (not CONF.service_available.neutron and - credentials.is_admin_available()): - admin_creds = isolated_creds.get_admin_creds() - networks_client = clients.Manager(admin_creds).networks_client - return fixed_network.get_tenant_network(isolated_creds, - networks_client) - - def assertEmpty(self, list, msg=None): - self.assertTrue(len(list) == 0, msg) - - def assertNotEmpty(self, list, msg=None): - self.assertTrue(len(list) > 0, msg) - - def assertRaisesMessage(self, exc, msg, func, *args, **kwargs): - try: - func(*args, **kwargs) - except Exception, e: - self.assertEqual(msg, str(e)) - self.assertTrue(isinstance(e, exc), - "Expected %s, got %s" % (exc, type(e))) - - -class NegativeAutoTest(BaseTestCase): - - _resources = {} - - @classmethod - def setUpClass(cls): - super(NegativeAutoTest, cls).setUpClass() - os = cls.get_client_manager(credential_type='primary') - cls.client = os.negative_client - - @staticmethod - def load_tests(*args): - """ - Wrapper for testscenarios to set the mandatory scenarios variable - only in case a real test loader is in place. Will be automatically - called in case the variable "load_tests" is set. - """ - if getattr(args[0], 'suiteClass', None) is not None: - loader, standard_tests, pattern = args - else: - standard_tests, module, loader = args - for test in testtools.iterate_tests(standard_tests): - schema = getattr(test, '_schema', None) - if schema is not None: - setattr(test, 'scenarios', - NegativeAutoTest.generate_scenario(schema)) - return testscenarios.load_tests_apply_scenarios(*args) - - @staticmethod - def generate_scenario(description): - """ - Generates the test scenario list for a given description. - - :param description: A file or dictionary with the following entries: - name (required) name for the api - http-method (required) one of HEAD,GET,PUT,POST,PATCH,DELETE - url (required) the url to be appended to the catalog url with '%s' - for each resource mentioned - resources: (optional) A list of resource names such as "server", - "flavor", etc. with an element for each '%s' in the url. This - method will call self.get_resource for each element when - constructing the positive test case template so negative - subclasses are expected to return valid resource ids when - appropriate. - json-schema (optional) A valid json schema that will be used to - create invalid data for the api calls. For "GET" and "HEAD", - the data is used to generate query strings appended to the url, - otherwise for the body of the http call. - """ - LOG.debug(description) - generator = importutils.import_class( - CONF.negative.test_generator)() - generator.validate_schema(description) - schema = description.get("json-schema", None) - resources = description.get("resources", []) - scenario_list = [] - expected_result = None - for resource in resources: - if isinstance(resource, dict): - expected_result = resource['expected_result'] - resource = resource['name'] - LOG.debug("Add resource to test %s" % resource) - scn_name = "inv_res_%s" % (resource) - scenario_list.append((scn_name, {"resource": (resource, - str(uuid.uuid4())), - "expected_result": expected_result - })) - if schema is not None: - for scenario in generator.generate_scenarios(schema): - scenario_list.append((scenario['_negtest_name'], - scenario)) - LOG.debug(scenario_list) - return scenario_list - - def execute(self, description): - """ - Execute a http call on an api that are expected to - result in client errors. First it uses invalid resources that are part - of the url, and then invalid data for queries and http request bodies. - - :param description: A json file or dictionary with the following - entries: - name (required) name for the api - http-method (required) one of HEAD,GET,PUT,POST,PATCH,DELETE - url (required) the url to be appended to the catalog url with '%s' - for each resource mentioned - resources: (optional) A list of resource names such as "server", - "flavor", etc. with an element for each '%s' in the url. This - method will call self.get_resource for each element when - constructing the positive test case template so negative - subclasses are expected to return valid resource ids when - appropriate. - json-schema (optional) A valid json schema that will be used to - create invalid data for the api calls. For "GET" and "HEAD", - the data is used to generate query strings appended to the url, - otherwise for the body of the http call. - - """ - LOG.info("Executing %s" % description["name"]) - LOG.debug(description) - generator = importutils.import_class( - CONF.negative.test_generator)() - schema = description.get("json-schema", None) - method = description["http-method"] - url = description["url"] - expected_result = None - if "default_result_code" in description: - expected_result = description["default_result_code"] - - resources = [self.get_resource(r) for - r in description.get("resources", [])] - - if hasattr(self, "resource"): - # Note(mkoderer): The resources list already contains an invalid - # entry (see get_resource). - # We just send a valid json-schema with it - valid_schema = None - if schema: - valid_schema = \ - valid.ValidTestGenerator().generate_valid(schema) - new_url, body = self._http_arguments(valid_schema, url, method) - elif hasattr(self, "_negtest_name"): - schema_under_test = \ - valid.ValidTestGenerator().generate_valid(schema) - local_expected_result = \ - generator.generate_payload(self, schema_under_test) - if local_expected_result is not None: - expected_result = local_expected_result - new_url, body = \ - self._http_arguments(schema_under_test, url, method) - else: - raise Exception("testscenarios are not active. Please make sure " - "that your test runner supports the load_tests " - "mechanism") - - if "admin_client" in description and description["admin_client"]: - if not credentials.is_admin_available(): - msg = ("Missing Identity Admin API credentials in" - "configuration.") - raise self.skipException(msg) - creds = self.isolated_creds.get_admin_creds() - os_adm = clients.Manager(credentials=creds) - client = os_adm.negative_client - else: - client = self.client - resp, resp_body = client.send_request(method, new_url, - resources, body=body) - self._check_negative_response(expected_result, resp.status, resp_body) - - def _http_arguments(self, json_dict, url, method): - LOG.debug("dict: %s url: %s method: %s" % (json_dict, url, method)) - if not json_dict: - return url, None - elif method in ["GET", "HEAD", "PUT", "DELETE"]: - return "%s?%s" % (url, urllib.urlencode(json_dict)), None - else: - return url, json.dumps(json_dict) - - def _check_negative_response(self, expected_result, result, body): - self.assertTrue(result >= 400 and result < 500 and result != 413, - "Expected client error, got %s:%s" % - (result, body)) - self.assertTrue(expected_result is None or expected_result == result, - "Expected %s, got %s:%s" % - (expected_result, result, body)) - - @classmethod - def set_resource(cls, name, resource): - """ - This function can be used in setUpClass context to register a resoruce - for a test. - - :param name: The name of the kind of resource such as "flavor", "role", - etc. - :resource: The id of the resource - """ - cls._resources[name] = resource - - def get_resource(self, name): - """ - Return a valid uuid for a type of resource. If a real resource is - needed as part of a url then this method should return one. Otherwise - it can return None. - - :param name: The name of the kind of resource such as "flavor", "role", - etc. - """ - if isinstance(name, dict): - name = name['name'] - if hasattr(self, "resource") and self.resource[0] == name: - LOG.debug("Return invalid resource (%s) value: %s" % - (self.resource[0], self.resource[1])) - return self.resource[1] - if name in self._resources: - return self._resources[name] - return None - - -def SimpleNegativeAutoTest(klass): - """ - This decorator registers a test function on basis of the class name. - """ - @attr(type=['negative']) - def generic_test(self): - if hasattr(self, '_schema'): - self.execute(self._schema) - - cn = klass.__name__ - cn = cn.replace('JSON', '') - cn = cn.replace('Test', '') - # NOTE(mkoderer): replaces uppercase chars inside the class name with '_' - lower_cn = re.sub('(?>$log_path/install_venv.err - exit 1 -fi - -rm -rf /etc/yum.repos.d/opencos.repo -opencos_repo=/etc/yum.repos.d/opencos.repo -echo "Create $opencos_repo ..." -echo "[opencos]">>$opencos_repo -echo "name=opencos">>$opencos_repo -echo "baseurl=http://10.43.177.17/pypi/">>$opencos_repo -echo "enabled=1">>$opencos_repo -echo "gpgcheck=0">>$opencos_repo - -rm -rf ~/.pip/pip.conf -pip_config=~/.pip/pip.conf -echo "Create $pip_config ..." -if [ ! -d `dirname $pip_config` ]; then - mkdir -p `dirname $pip_config` -fi -echo "[global]">$pip_config -echo "find-links = http://10.43.177.17/pypi">>$pip_config -echo "no-index = true">>$pip_config - -rm -rf ~/.pydistutils.cfg -pydistutils_cfg=~/.pydistutils.cfg -echo "Create $pydistutils_cfg ..." -echo "[easy_install]">$pydistutils_cfg -echo "index_url = http://10.43.177.17/pypi">>$pydistutils_cfg - - -modules=(virtualenv mariadb-devel testtools testrepository testresources fixtures python-subunit testscenarios postgresql-devel oslo.serialization oslo.utils libffi-devel - cyrus-sasl-devel sqlite-devel libxslt-devel openldap-devel) - -yum clean all 1>/dev/null 2>/dev/null -# for virtual environment demand pip version>=1.6, so install it whether installed. -yum --disablerepo=* --enablerepo=opencos install -y pip extras 1>$log_path/$mod.log 2>$log_path/$mod.err -# install modules -echo "install modules">>$log_path/install_venv.log -for mod in ${modules[@]}; do - echo -n "yum install $mod ... " - already_install=`rpm -qa | grep $mod` - if [ "$already_install" == "" ]; then - yum --disablerepo=* --enablerepo=opencos install -y $mod 1>$log_path/$mod.log 2>$log_path/$mod.err - if [ -s $log_path/$mod.err ]; then - echo "fail!" - echo "Install $mod fail! Please manually using the yum installation package,commond is \"yum install $mod\"">>$log_path/install_venv.err - # exit 1 - else - echo "ok(install finish)" - fi - else - echo "ok(already exist)" - fi -done - -#echo "install venv ... ">>$log_path/install_venv.log -#chmod +x tools/* -#python tools/install_venv.py 1>$log_path/install_venv.log 2>$log_path/install_venv.err -#if grep "development environment setup is complete." $log_path/install_venv.log -# then -# echo "development environment setup is complete...">>$log_path/install_venv.log -#else -# echo "development environment setup is fail,please check $log_path/install_venv.err" -# cat $log_path/install_venv.err -## exit 1 -#fi - -echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" -echo "copy tempest.conf.sample to tempest.conf....." -tempestconf=etc/tempest.conf -if [ ! -e $tempestconf ];then - cp etc/tempest.conf.sample etc/tempest.conf 2>>err.txt -fi - -source /root/keystonerc_admin - -#######Tempest CONF####### - -#######[DEFAULT]####### -echo "config tempest.conf DEFAULT lock_path /tmp" -openstack-config --set $tempestconf DEFAULT lock_path /tmp 2>>$errfile - -echo "config tempest.conf DEFAULT log_file tempest.log" -openstack-config --set $tempestconf DEFAULT log_file tempest.log 2>>$errfile - -########[identity]######## -if [ ! -n "`keystone user-list 2>>$errfile | grep -w Member`" ]; then - keystone user-create --name Member 2>>$errfile -fi - -if [ ! -n "`keystone role-list 2>>$errfile | grep -w Member`" ]; then - keystone role-create --name Member 2>>$errfile -fi - -if [ ! -n "`keystone tenant-list 2>>$errfile |grep -w demo`" ]; then - keystone tenant-create --name demo --enabled true 2>>$errfile -fi - -if [ ! -n "`keystone user-list 2>>$errfile |grep -w demo`" ]; then - keystone user-create --name demo --tenant demo --pass secret --enabled true 2>>$errfile -fi - -if [ ! -n "`keystone tenant-list 2>>$errfile |grep -w alt_demo`" ]; then - keystone tenant-create --name alt_demo --enabled true 2>>$errfile -fi - -if [ ! -n "`keystone user-list 2>>$errfile |grep -w alt_demo`" ]; then - keystone user-create --name alt_demo --tenant alt_demo --pass secret --enabled true 2>>$errfile -fi - -openstack-config --set $tempestconf identity admin_username admin 2>>$errfile -openstack-config --set $tempestconf identity admin_role admin 2>>$errfile -openstack-config --set $tempestconf identity admin_tenant_name admin 2>>$errfile -openstack-config --set $tempestconf identity admin_password keystone 2>>$errfile -openstack-config --set $tempestconf identity alt_tenant_name alt_demo 2>>$errfile -openstack-config --set $tempestconf identity alt_username alt_demo 2>>$errfile -openstack-config --set $tempestconf identity alt_password secret 2>>$errfile -openstack-config --set $tempestconf identity tenant_name demo 2>>$errfile -openstack-config --set $tempestconf identity username demo 2>>$errfile -openstack-config --set $tempestconf identity password secret 2>>$errfile -openstack-config --set $tempestconf identity auth_version v2 2>>$errfile -openstack-config --set $tempestconf identity catalog_type identity 2>>$errfile -openstack-config --set $tempestconf identity endpoint_type publicURL 2>>$errfile -openstack-config --set $tempestconf identity region RegionOne 2>>$errfile -openstack-config --set $tempestconf identity uri http://127.0.0.1:5000/v2.0/ 2>>$errfile -openstack-config --set $tempestconf identity uri_v3 http://127.0.0.1:5000/v3/ 2>>$errfile - -#######[cli]####### -openstack-config --set $tempestconf cli cli_dir /usr/bin 2>>$errfile - -#######[compute]####### -openstack-config --set $tempestconf compute build_timeout 300 2>>$errfile -openstack-config --set $tempestconf compute run_ssh true 2>>$errfile -openstack-config --set $tempestconf compute ssh_auth_method adminpass 2>>$errfile -openstack-config --set $tempestconf compute ssh_user cirros 2>>$errfile -openstack-config --set $tempestconf compute image_ssh_user cirros 2>>$errfile -openstack-config --set $tempestconf compute image_ssh_password cubswin:\) 2>>$errfile - -if [ ! -n "`glance image-list 2>>$errfile |grep -w cirros_icehouse_test |awk '{print $2}'`" ]; then -glance image-create --name cirros_icehouse_test --is-public true --disk-format qcow2 --copy-from http://10.43.175.61:8081/files/linux/cirros-0.3.0-x86_64-disk.img 2>>$errfile -fi - -if [ ! -n "`glance image-list 2>>$errfile |grep -w cirros_icehouse_test_alt |awk '{print $2}'`" ]; then -glance image-create --name cirros_icehouse_test_alt --is-public true --disk-format qcow2 --copy-from http://10.43.175.61:8081/files/linux/cirros-0.3.2-x86_64-disk.img 2>>$errfile -fi - -IMAGE=`glance image-list 2>>$errfile |grep -w cirros_icehouse_test |awk -F " " '{print $2}'` -IMAGE_ALT=`glance image-list 2>>$errfile |grep -w cirros_icehouse_test_alt |awk -F " " '{print $2}'` - -openstack-config --set $tempestconf compute image_ref $IMAGE 2>>$errfile -openstack-config --set $tempestconf compute image_ref_alt $IMAGE_ALT 2>>$errfile - -#CONF.compute.flavor_ref -FLAVORNAME=m1.tiny -FLAVORALT=m1.small -FLAVORID=`nova flavor-list 2>>$errfile |grep -w $FLAVORNAME |awk '{print $2}'` -FLAVORALTID=`nova flavor-list 2>>$errfile |grep -w $FLAVORALT |awk '{print $2}'` -openstack-config --set $tempestconf compute flavor_ref $FLAVORID 2>>$errfile -openstack-config --set $tempestconf compute flavor_ref_alt $FLAVORALTID 2>>$errfile - -#######[dashboard]####### -openstack-config --set $tempestconf dashboard dashboard_url http://localhost/dashboard/ 2>>$errfile -openstack-config --set $tempestconf dashboard login_url http://localhost/dashboard/auth/login/ 2>>$errfile - -#######[service_available]####### -openstack-config --set $tempestconf service_available ceilometer false 2>>$errfile -openstack-config --set $tempestconf service_available cinder true 2>>$errfile -openstack-config --set $tempestconf service_available glance true 2>>$errfile -openstack-config --set $tempestconf service_available heat false 2>>$errfile -openstack-config --set $tempestconf service_available horizon true 2>>$errfile -openstack-config --set $tempestconf service_available ironic false 2>>$errfile -openstack-config --set $tempestconf service_available neutron true 2>>$errfile -openstack-config --set $tempestconf service_available nova true 2>>$errfile -openstack-config --set $tempestconf service_available sahara false 2>>$errfile -openstack-config --set $tempestconf service_available swift false 2>>$errfile -openstack-config --set $tempestconf service_available trove false 2>>$errfile -openstack-config --set $tempestconf service_available zaqar false 2>>$errfile - - -if [ -s err.txt ];then - cat err.txt - exit 1 -fi - -echo "tempest envirmonent and tempest.conf config successful..." -exit 0 diff --git a/test/tempest/test-requirements.txt b/test/tempest/test-requirements.txt deleted file mode 100644 index 76ae5216..00000000 --- a/test/tempest/test-requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking<0.11,>=0.10.0 -# needed for doc build -sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 -python-subunit>=0.0.18 -oslosphinx>=2.5.0,<2.6.0 # Apache-2.0 -mox>=0.5.3 -mock>=1.0 -coverage>=3.6 -oslotest>=1.5.1,<1.6.0 # Apache-2.0 -stevedore>=1.3.0,<1.4.0 # Apache-2.0 diff --git a/test/tempest/tox.ini b/test/tempest/tox.ini index 208cd5e3..4c31607e 100644 --- a/test/tempest/tox.ini +++ b/test/tempest/tox.ini @@ -1,128 +1,3 @@ -[tox] -envlist = pep8,py27 -minversion = 1.6 -skipsdist = True - -[tempestenv] -sitepackages = False -setenv = VIRTUAL_ENV={envdir} - OS_TEST_PATH=./tempest/test_discover -deps = setuptools - -r{toxinidir}/requirements.txt - -[testenv] -setenv = VIRTUAL_ENV={envdir} - OS_TEST_PATH=./tempest/tests -usedevelop = True -install_command = pip install -U {opts} {packages} -whitelist_externals = * -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox.sh '{posargs}' - -[testenv:genconfig] -commands = oslo-config-generator --config-file tools/config/config-generator.tempest.conf - -[testenv:cover] -setenv = OS_TEST_PATH=./tempest/tests -commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}' - -[testenv:all] -sitepackages = {[tempestenv]sitepackages} -# 'all' includes slow tests -setenv = {[tempestenv]setenv} - OS_TEST_TIMEOUT=1200 -deps = {[tempestenv]deps} -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox.sh '{posargs}' - -[testenv:full] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -# The regex below is used to select which tests to run and exclude the slow tag: -# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610 -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}' - -[testenv:full-serial] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -# The regex below is used to select which tests to run and exclude the slow tag: -# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610 -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}' - -[testenv:heat-slow] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} - OS_TEST_TIMEOUT=1200 -deps = {[tempestenv]deps} -# The regex below is used to select heat api/scenario tests tagged as slow. -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox.sh '(?=.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)\.orchestration) {posargs}' - -[testenv:large-ops] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -commands = - find . -type f -name "*.pyc" -delete - python setup.py testr --slowest --testr-args='tempest.scenario.test_large_ops {posargs}' - -[testenv:smoke] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])((smoke)|(^tempest\.scenario)) {posargs}' - -[testenv:smoke-serial] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -# This is still serial because neutron doesn't work with parallel. See: -# https://bugs.launchpad.net/tempest/+bug/1216076 so the neutron smoke -# job would fail if we moved it to parallel. -commands = - find . -type f -name "*.pyc" -delete - bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])((smoke)|(^tempest\.scenario)) {posargs}' - -[testenv:stress] -sitepackages = {[tempestenv]sitepackages} -setenv = {[tempestenv]setenv} -deps = {[tempestenv]deps} -commands = - run-tempest-stress {posargs} - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = python setup.py build_sphinx {posargs} - -[testenv:pep8] -commands = - flake8 {posargs} - {toxinidir}/tools/config/check_uptodate.sh - python tools/check_uuid.py - -[testenv:uuidgen] -commands = - python tools/check_uuid.py --fix - -[hacking] -local-check-factory = tempest.hacking.checks.factory -import_exceptions = tempest.services - [flake8] # E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved. For further detail see https://review.openstack.org/#/c/36788/ # E123 skipped because it is ignored by default in the default pep8