Merge "Enhance tests for flavor_extra_spec API"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index fc4f9cd..567b85a 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -1,456 +1,737 @@
[DEFAULT]
-#log_config = /opt/stack/tempest/etc/logging.conf.sample
-# disable logging to the stderr
-use_stderr = false
+#
+# Options defined in tempest.openstack.common.lockutils
+#
-# log file
-log_file = tempest.log
+# Whether to disable inter-process locks (boolean value)
+#disable_process_locking=false
-# lock/semaphore base directory
-lock_path=/tmp
+# Directory to use for lock files. (string value)
+#lock_path=<None>
-default_log_levels=tempest.stress=INFO,amqplib=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,eventlet.wsgi.server=WARN
+
+#
+# Options defined in tempest.openstack.common.log
+#
+
+# 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
+
+# Log output to standard error (boolean value)
+#use_stderr=true
+
+# 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)s %(tenant)s] %(instance)s%(message)s
+
+# 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
+
+# data to append to log format when level is DEBUG (string
+# value)
+#logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d
+
+# 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
+
+# list of logger=LEVEL pairs (list value)
+#default_log_levels=amqplib=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO
+
+# publish error events (boolean value)
+#publish_errors=false
+
+# make deprecations fatal (boolean value)
+#fatal_deprecations=false
+
+# If an instance is passed with the log message, format it
+# like this (string value)
+#instance_format="[instance: %(uuid)s] "
+
+# If an instance UUID is passed with the log message, format
+# it like this (string value)
+#instance_uuid_format="[instance: %(uuid)s] "
+
+# If this option is specified, the logging configuration file
+# specified is used and overrides any other logging options
+# specified. Please see the Python logging module
+# documentation for details on logging configuration files.
+# (string value)
+#log_config=<None>
+
+# 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=<None>
+
+# Format string for %%(asctime)s in log records. Default:
+# %(default)s (string value)
+#log_date_format=%Y-%m-%d %H:%M:%S
+
+# (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=<None>
+
+# (Optional) The base directory used for relative --log-file
+# paths (string value)
+# Deprecated group/name - [DEFAULT]/logdir
+#log_dir=<None>
+
+# Use syslog for logging. (boolean value)
+#use_syslog=false
+
+# syslog facility to receive log lines (string value)
+#syslog_log_facility=LOG_USER
+
[identity]
-# This section contains configuration options that a variety of Tempest
-# test clients use when authenticating with different user/tenant
-# combinations
-# The type of endpoint for a Identity service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "identity"
-catalog_type = identity
-# Ignore SSL certificate validation failures? Use when in testing
-# environments that have self-signed SSL certs.
-disable_ssl_certificate_validation = false
-# URL for where to find the OpenStack Identity API endpoint (Keystone)
-uri = http://127.0.0.1:5000/v2.0/
-# URL for where to find the OpenStack V3 Identity API endpoint (Keystone)
-uri_v3 = http://127.0.0.1:5000/v3/
-# The identity region. Also used as the other services' region name unless
-# they are set explicitly.
-region = RegionOne
+#
+# Options defined in tempest.config
+#
-# This should be the username of a user WITHOUT administrative privileges
-username = demo
-# The above non-administrative user's password
-password = secret
-# The above non-administrative user's tenant name
-tenant_name = demo
+# Catalog type of the Identity service. (string value)
+#catalog_type=identity
-# This should be the username of an alternate user WITHOUT
-# administrative privileges
-alt_username = alt_demo
-# The above non-administrative user's password
-alt_password = secret
-# The above non-administrative user's tenant name
-alt_tenant_name = alt_demo
+# Set to True if using self-signed SSL certificates. (boolean
+# value)
+#disable_ssl_certificate_validation=false
-# This should be the username of a user WITH administrative privileges
-admin_username = admin
-# The above administrative user's password
-admin_password = secret
-# The above administrative user's tenant name
-admin_tenant_name = admin
+# Full URI of the OpenStack Identity API (Keystone), v2
+# (string value)
+#uri=<None>
-# The role that is required to administrate keystone.
-admin_role = admin
+# Full URI of the OpenStack Identity API (Keystone), v3
+# (string value)
+#uri_v3=<None>
-[compute]
-# This section contains configuration options used when executing tests
-# against the OpenStack Compute API.
+# 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
-# Allows test cases to create/destroy tenants and users. This option
-# enables isolated test cases and better parallel execution,
-# but also requires that OpenStack Identity API admin credentials
-# are known.
-allow_tenant_isolation = true
+# Username to use for Nova API requests. (string value)
+#username=demo
-# Allows test cases to create/destroy tenants and users. This option
-# enables isolated test cases and better parallel execution,
-# but also requires that OpenStack Identity API admin credentials
-# are known.
-allow_tenant_reuse = true
+# Tenant name to use for Nova API requests. (string value)
+#tenant_name=demo
-# Reference data for tests. The ref and ref_alt should be
-# distinct images/flavors.
-image_ref = {$IMAGE_ID}
-image_ref_alt = {$IMAGE_ID_ALT}
-flavor_ref = 1
-flavor_ref_alt = 2
+# Role required to administrate keystone. (string value)
+#admin_role=admin
-# User name used to authenticate to an instance
-image_ssh_user = root
+# API key to use when authenticating. (string value)
+#password=pass
-# Password used to authenticate to an instance
-image_ssh_password = password
+# Username of alternate user to use for Nova API requests.
+# (string value)
+#alt_username=<None>
-# User name used to authenticate to an instance using the alternate image
-image_alt_ssh_user = root
+# Alternate user's Tenant name to use for Nova API requests.
+# (string value)
+#alt_tenant_name=<None>
-# Password used to authenticate to an instance using the alternate image
-image_alt_ssh_password = password
+# API key to use when authenticating as alternate user.
+# (string value)
+#alt_password=<None>
-# Number of seconds to wait while looping to check the status of an
-# instance that is building.
-build_interval = 10
+# Administrative Username to use forKeystone API requests.
+# (string value)
+#admin_username=admin
-# Number of seconds to time out on waiting for an instance
-# to build or reach an expected status
-build_timeout = 600
+# Administrative Tenant name to use for Keystone API requests.
+# (string value)
+#admin_tenant_name=admin
-# Run additional tests that use SSH for instance validation?
-# This requires the instances be routable from the host
-# executing the tests
-run_ssh = false
+# API key to use when authenticating as admin. (string value)
+#admin_password=pass
-# Name of a user used to authenticate to an instance.
-ssh_user = cirros
-# Visible fixed network name
-fixed_network_name = private
+[stress]
-# Network id used for SSH (public, private, etc)
-network_for_ssh = public
+#
+# Options defined in tempest.config
+#
-# IP version of the address used for SSH
-ip_version_for_ssh = 4
+# Directory containing log files on the compute nodes (string
+# value)
+#nova_logdir=<None>
-# Number of seconds to wait to ping to an instance
-ping_timeout = 60
+# Maximum number of instances to create during test. (integer
+# value)
+#max_instances=16
-# Number of seconds to wait to authenticate to an instance
-ssh_timeout = 300
+# Controller host. (string value)
+#controller=<None>
-# Additinal wait time for clean state, when there is
-# no OS-EXT-STS extension availiable
-ready_wait = 0
+# Controller host. (string value)
+#target_controller=<None>
-# Number of seconds to wait for output from ssh channel
-ssh_channel_timeout = 60
+# ssh user. (string value)
+#target_ssh_user=<None>
-# Dose the SSH uses Floating IP?
-use_floatingip_for_ssh = true
+# Path to private key. (string value)
+#target_private_key_path=<None>
-# The type of endpoint for a Compute API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "compute"
-catalog_type = compute
+# regexp for list of log files. (string value)
+#target_logfiles=<None>
-# The type of endpoint for a Compute v3 API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "computev3"
-catalog_v3_type = computev3
+# time (in seconds) between log file error checks. (integer
+# value)
+#log_check_interval=60
-# The name of a region for compute. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
+# The number of threads created while stress test. (integer
+# value)
+#default_thread_number_per_action=4
-# Expected first device name when a volume is attached to an instance
-volume_device_name = vdb
-
-[compute-feature-enabled]
-# Do we run the Nova V3 API tests?
-api_v3 = false
-
-# Does the Compute API support creation of images?
-create_image = true
-
-# For resize to work with libvirt/kvm, one of the following must be true:
-# Single node: allow_resize_to_same_host=true must be set in nova.conf
-# Cluster: the 'nova' user must have scp access between cluster nodes
-resize = true
-
-# Does the compute API support changing the admin password?
-change_password = false
-
-# Run live migration tests (requires 2 hosts)
-live_migration = false
-
-# Use block live migration (Otherwise, non-block migration will be
-# performed, which requires XenServer pools in case of using XS)
-block_migration_for_live_migration = false
-
-# Supports iSCSI block migration - depends on a XAPI supporting
-# relax-xsm-sr-check
-block_migrate_cinder_iscsi = false
-
-# When set to false, disk config tests are forced to skip
-disk_config = true
-
-# When set to false, flavor extra data tests are forced to skip
-flavor_extra = true
-
-[compute-admin]
-# This should be the username of a user WITH administrative privileges
-# If not defined the admin user from the identity section will be used
-username =
-# The above administrative user's password
-password =
-# The above administrative user's tenant name
-tenant_name =
-
-[image]
-# This section contains configuration options used when executing tests
-# against the OpenStack Images API
-
-# The type of endpoint for an Image API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "image"
-catalog_type = image
-
-# The name of a region for image. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-
-# HTTP image to use for glance http image testing
-http_image = http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz
[image-feature-enabled]
-# Is the image api_v1 enabled
-api_v1 = True
-# Is the image api_v2 enabled
-api_v2 = True
+
+#
+# Options defined in tempest.config
+#
+
+# Is the v2 image API enabled (boolean value)
+#api_v2=true
+
+# Is the v1 image API enabled (boolean value)
+#api_v1=true
+
+
+[compute]
+
+#
+# Options defined in tempest.config
+#
+
+# Allows test cases to create/destroy tenants and users. This
+# option enables isolated test cases and better parallel
+# execution, but also requires that OpenStack Identity API
+# admin credentials are known. (boolean value)
+#allow_tenant_isolation=false
+
+# If allow_tenant_isolation is True and a tenant that would be
+# created for a given test already exists (such as from a
+# previously-failed run), re-use that tenant instead of
+# failing because of the conflict. Note that this would result
+# in the tenant being deleted at the end of a subsequent
+# successful run. (boolean value)
+#allow_tenant_reuse=true
+
+# Valid secondary image reference to be used in tests. (string
+# value)
+#image_ref={$IMAGE_ID}
+
+# Valid secondary image reference to be used in tests. (string
+# value)
+#image_ref_alt={$IMAGE_ID_ALT}
+
+# Valid primary flavor to use in tests. (integer value)
+#flavor_ref=1
+
+# Valid secondary flavor to be used in tests. (integer value)
+#flavor_ref_alt=2
+
+# User name used to authenticate to an instance. (string
+# value)
+#image_ssh_user=root
+
+# Password used to authenticate to an instance. (string value)
+#image_ssh_password=password
+
+# User name used to authenticate to an instance using the
+# alternate image. (string value)
+#image_alt_ssh_user=root
+
+# Password used to authenticate to an instance using the
+# alternate image. (string value)
+#image_alt_ssh_password=password
+
+# Time in seconds between build status checks. (integer value)
+#build_interval=10
+
+# Timeout in seconds to wait for an instance to build.
+# (integer value)
+#build_timeout=300
+
+# Does the test environment support snapshots? (boolean value)
+#run_ssh=false
+
+# User name used to authenticate to an instance. (string
+# value)
+#ssh_user=root
+
+# Timeout in seconds to wait for ping to succeed. (integer
+# value)
+#ping_timeout=60
+
+# Timeout in seconds to wait for authentication to succeed.
+# (integer value)
+#ssh_timeout=300
+
+# Additional wait time for clean state, when there is no OS-
+# EXT-STS extension available (integer value)
+#ready_wait=0
+
+# Timeout in seconds to wait for output from ssh channel.
+# (integer value)
+#ssh_channel_timeout=60
+
+# Visible fixed network name (string value)
+#fixed_network_name=private
+
+# Network used for SSH connections. (string value)
+#network_for_ssh=public
+
+# IP version used for SSH connections. (integer value)
+#ip_version_for_ssh=4
+
+# Dose the SSH uses Floating IP? (boolean value)
+#use_floatingip_for_ssh=true
+
+# Catalog type of the Compute service. (string value)
+#catalog_type=compute
+
+# 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=
+
+# Catalog type of the Compute v3 service. (string value)
+#catalog_v3_type=computev3
+
+# Path to a private key file for SSH access to remote hosts
+# (string value)
+#path_to_private_key=<None>
+
+# Expected device name when a volume is attached to an
+# instance (string value)
+#volume_device_name=vdb
+
+# 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
+
[network]
-# This section contains configuration options used when executing tests
-# against the OpenStack Network API.
-# Version of the Neutron API
-api_version = v1.1
-# Catalog type of the Neutron Service
-catalog_type = network
+#
+# Options defined in tempest.config
+#
-# The name of a region for network. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
+# Catalog type of the Neutron service. (string value)
+#catalog_type=network
-# A large private cidr block from which to allocate smaller blocks for
-# tenant networks.
-tenant_network_cidr = 10.100.0.0/16
+# 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 mask bits used to partition the tenant block.
-tenant_network_mask_bits = 24
+# The cidr block to allocate tenant networks from (string
+# value)
+#tenant_network_cidr=10.100.0.0/16
-# If tenant networks are reachable, connectivity checks will be
-# performed directly against addresses on those networks.
-tenant_networks_reachable = false
+# The mask bits for tenant networks (integer value)
+#tenant_network_mask_bits=28
-# Id of the public network that provides external connectivity.
-public_network_id = {$PUBLIC_NETWORK_ID}
+# Whether tenant network connectivity should be evaluated
+# directly (boolean value)
+#tenant_networks_reachable=false
-# Id of a shared public router that provides external connectivity.
-# A shared public router would commonly be used where IP namespaces
-# were disabled. If namespaces are enabled, it would be preferable
-# for each tenant to have their own router.
-public_router_id = {$PUBLIC_ROUTER_ID}
+# Id of the public network that provides external connectivity
+# (string value)
+#public_network_id=
+
+# Id of the public router that provides external connectivity
+# (string value)
+#public_router_id=
+
+
+[boto]
+
+#
+# Options defined in tempest.config
+#
+
+# EC2 URL (string value)
+#ec2_url=http://localhost:8773/services/Cloud
+
+# S3 URL (string value)
+#s3_url=http://localhost:8080
+
+# AWS Secret Key (string value)
+#aws_secret=<None>
+
+# AWS Access Key (string value)
+#aws_access=<None>
+
+# S3 Materials Path (string value)
+#s3_materials_path=/opt/stack/devstack/files/images/s3-materials/cirros-0.3.0
+
+# ARI Ramdisk Image manifest (string value)
+#ari_manifest=cirros-0.3.0-x86_64-initrd.manifest.xml
+
+# AMI Machine Image manifest (string value)
+#ami_manifest=cirros-0.3.0-x86_64-blank.img.manifest.xml
+
+# AKI Kernel Image manifest (string value)
+#aki_manifest=cirros-0.3.0-x86_64-vmlinuz.manifest.xml
+
+# Instance type (string value)
+#instance_type=m1.tiny
+
+# boto Http socket timeout (integer value)
+#http_socket_timeout=3
+
+# boto num_retries on error (integer value)
+#num_retries=1
+
+# Status Change Timeout (integer value)
+#build_timeout=60
+
+# Status Change Test Interval (integer value)
+#build_interval=1
+
+
+[scenario]
+
+#
+# Options defined in tempest.config
+#
+
+# Directory containing image files (string value)
+#img_dir=/opt/stack/new/devstack/files/images/cirros-0.3.1-x86_64-uec
+
+# 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
+
+# AKI image file name (string value)
+#aki_img_file=cirros-0.3.1-x86_64-vmlinuz
+
+# ssh username for the image file (string value)
+#ssh_user=cirros
+
+# specifies how many resources to request at once. Used for
+# large operations testing. (integer value)
+#large_ops_number=0
+
+
+[image]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Image service. (string value)
+#catalog_type=image
+
+# 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=
+
+# http accessible image (string value)
+#http_image=http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz
+
+
+[compute-admin]
+
+#
+# Options defined in tempest.config
+#
+
+# Administrative Username to use for Nova API requests.
+# (string value)
+#username=admin
+
+# Administrative Tenant name to use for Nova API requests.
+# (string value)
+#tenant_name=admin
+
+# API key to use when authenticating as admin. (string value)
+#password=pass
+
+
+[cli]
+
+#
+# Options defined in tempest.cli
+#
+
+# enable cli tests (boolean value)
+#enabled=true
+
+# directory where python client binaries are located (string
+# value)
+#cli_dir=/usr/local/bin
+
+# Number of seconds to wait on a CLI timeout (integer value)
+#timeout=15
[volume]
-# This section contains the configuration options used when executing tests
-# against the OpenStack Block Storage API service
-# The type of endpoint for a Cinder or Block Storage API service.
-# Unless you have a custom Keystone service catalog implementation, you
-# probably want to leave this value as "volume"
-catalog_type = volume
-# The name of a region for volume. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-# The disk format to use when copying a volume to image
-disk_format = raw
-# Number of seconds to wait while looping to check the status of a
-# volume that is being made available
-build_interval = 10
-# Number of seconds to time out on waiting for a volume
-# to be available or reach an expected status
-build_timeout = 300
-# If multi_backend is enabled there must be 2 volume_backend_names (
-# backend1_name and backend2_name) which have to be different)
-backend1_name = BACKEND_1
-backend2_name = BACKEND_2
-# Protocol and vendor of volume backend to target when testing volume-types.
-# You should update to reflect those exported by configured backend driver.
-storage_protocol = iSCSI
-vendor_name = Open Source
+#
+# Options defined in tempest.config
+#
-[volume-feature-enabled]
-#Runs Cinder multi-backend tests (requires 2 backends declared in cinder.conf)
-multi_backend = false
+# Time in seconds between volume availability checks. (integer
+# value)
+#build_interval=10
-[object-storage]
-# This section contains configuration options used when executing tests
-# against the OpenStack Object Storage API.
+# Timeout in seconds to wait for a volume to becomeavailable.
+# (integer value)
+#build_timeout=300
-# You can configure the credentials in the compute section
+# Catalog type of the Volume Service (string value)
+#catalog_type=volume
-# The type of endpoint for an Object Storage API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "object-store"
-catalog_type = object-store
+# 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=
-# The name of a region for object storage. If empty or commented-out, the
-# value of identity.region is used instead. If no such region is found in
-# the service catalog, the first found one is used.
-#region = RegionOne
+# Name of the backend1 (must be declared in cinder.conf)
+# (string value)
+#backend1_name=BACKEND_1
-# Number of seconds to time on waiting for a container to container
-# synchronization complete
-container_sync_timeout = 120
-# Number of seconds to wait while looping to check the status of a
-# container to container synchronization
-container_sync_interval = 5
+# Name of the backend2 (must be declared in cinder.conf)
+# (string value)
+#backend2_name=BACKEND_2
-# Set operator role for tests that require creating a container
-operator_role = Member
+# Backend protocol to target when creating volume types
+# (string value)
+#storage_protocol=iSCSI
-[object-feature-enabled]
-# Set to True if the Account Quota middleware is enabled
-accounts_quotas = True
-# Set to True if the Container Quota middleware is enabled
-container_quotas = True
+# Backend vendor to target when creating volume types (string
+# value)
+#vendor_name=Open Source
-[boto]
-# This section contains configuration options used when executing tests
-# with boto.
+# Disk format to use when copying a volume to image (string
+# value)
+#disk_format=raw
-# EC2 URL
-ec2_url = http://localhost:8773/services/Cloud
-# S3 URL
-s3_url = http://localhost:3333
-
-# Use keystone ec2-* command to get those values for your test user and tenant
-aws_access =
-aws_secret =
-
-# Image materials for S3 upload
-# ALL content of the specified directory will be uploaded to S3
-s3_materials_path = /opt/stack/devstack/files/images/s3-materials/cirros-0.3.1
-
-# The manifest.xml files, must be in the s3_materials_path directory
-# Subdirectories not allowed!
-# The filenames will be used as a Keys in the S3 Buckets
-
-# ARI Ramdisk manifest. Must be in the above s3_materials_path
-ari_manifest = cirros-0.3.1-x86_64-initrd.manifest.xml
-
-# AMI Machine Image manifest. Must be in the above s3_materials_path
-ami_manifest = cirros-0.3.1-x86_64-blank.img.manifest.xml
-
-# AKI Kernel Image manifest, Must be in the above s3_materials_path
-aki_manifest = cirros-0.3.1-x86_64-vmlinuz.manifest.xml
-
-# Instance type
-instance_type = m1.tiny
-
-# TCP/IP connection timeout
-http_socket_timeout = 5
-
-# Number of retries actions on connection or 5xx error
-num_retries = 1
-
-# Status change wait timout
-build_timeout = 120
-
-# Status change wait interval
-build_interval = 1
-
-[orchestration]
-# The type of endpoint for an Orchestration API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "orchestration"
-catalog_type = orchestration
-
-# The name of a region for orchestration. If empty or commented-out, the value
-# of identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-
-# Status change wait interval
-build_interval = 1
-
-# Status change wait timout. This may vary across environments as some some
-# tests spawn full VMs, which could be slow if the test is already in a VM.
-build_timeout = 300
-
-# Instance type for tests. Needs to be big enough for a
-# full OS plus the test workload
-instance_type = m1.micro
-
-# Name of heat-cfntools enabled image to use when launching test instances
-# If not specified, tests that spawn instances will not run
-#image_ref = ubuntu-vm-heat-cfntools
-
-# Name of existing keypair to launch servers with. The default is not to specify
-# any key, which will generate a keypair for each test class
-#keypair_name = heat_key
[dashboard]
-# URL where to find the dashboard home page
-dashboard_url = 'http://localhost/'
-# URL where to submit the login form
-login_url = 'http://localhost/auth/login/'
+#
+# Options defined in tempest.config
+#
-[scenario]
-# Directory containing image files
-img_dir = /opt/stack/new/devstack/files/images/cirros-0.3.1-x86_64-uec
+# Where the dashboard can be found (string value)
+#dashboard_url=http://localhost/
-# AMI image file name
-ami_img_file = cirros-0.3.1-x86_64-blank.img
+# Login page for the dashboard (string value)
+#login_url=http://localhost/auth/login/
-# ARI image file name
-ari_img_file = cirros-0.3.1-x86_64-initrd
-# AKI image file name
-aki_img_file = cirros-0.3.1-x86_64-vmlinuz
+[orchestration]
-# ssh username for the image file
-ssh_user = cirros
+#
+# Options defined in tempest.config
+#
-# specifies how many resources to request at once. Used for large operations
-# testing."
-large_ops_number = 0
+# Catalog type of the Orchestration service. (string value)
+#catalog_type=orchestration
-[cli]
-# Enable cli tests
-enabled = true
-# directory where python client binaries are located
-cli_dir = /usr/local/bin
-# Number of seconds to wait on a CLI timeout
-timeout = 15
+# 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=
-[service_available]
-# Whether or not cinder is expected to be available
-cinder = true
-# Whether or not neutron is expected to be available
-neutron = false
-# Whether or not glance is expected to be available
-glance = true
-# Whether or not swift is expected to be available
-swift = true
-# Whether or not nova is expected to be available
-nova = true
-# Whether or not Heat is expected to be available
-heat = false
-# Whether or not Ceilometer is expected to be available
-ceilometer = True
-# Whether or not horizon is expected to be available
-horizon = true
+# Allows test cases to create/destroy tenants and users. This
+# option enables isolated test cases and better parallel
+# execution, but also requires that OpenStack Identity API
+# admin credentials are known. (boolean value)
+#allow_tenant_isolation=false
-[stress]
-# Maximum number of instances to create during test
-max_instances = 32
-# Time (in seconds) between log file error checks
-log_check_interval = 60
-# The default number of threads created while stress test
-default_thread_number_per_action = 4
+# 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=300
+
+# 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 heat-cfntools enabled image to use when launching
+# test instances. (string value)
+#image_ref=<None>
+
+# Name of existing keypair to launch servers with. (string
+# value)
+#keypair_name=<None>
+
+# Value must match heat configuration of the same name.
+# (integer value)
+#max_template_size=524288
+
+
+[object-storage]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Object-Storage service. (string value)
+#catalog_type=object-store
+
+# 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=
+
+# Number of seconds to time on waiting for a containerto
+# container synchronization complete. (integer value)
+#container_sync_timeout=120
+
+# Number of seconds to wait while looping to check thestatus
+# of a container to container synchronization (integer value)
+#container_sync_interval=5
+
+# Role to add to users created for swift tests to enable
+# creating containers (string value)
+#operator_role=Member
+
[debug]
-# Enable diagnostic commands
-enable = true
+
+#
+# Options defined in tempest.config
+#
+
+# Enable diagnostic commands (boolean value)
+#enable=true
+
+
+[service_available]
+
+#
+# Options defined in tempest.config
+#
+
+# Whether or not cinder is expected to be available (boolean
+# value)
+#cinder=true
+
+# Whether or not neutron is expected to be available (boolean
+# value)
+#neutron=false
+
+# Whether or not glance is expected to be available (boolean
+# value)
+#glance=true
+
+# Whether or not swift is expected to be available (boolean
+# value)
+#swift=true
+
+# Whether or not nova is expected to be available (boolean
+# value)
+#nova=true
+
+# Whether or not Heat is expected to be available (boolean
+# value)
+#heat=false
+
+# Whether or not Ceilometer is expected to be available
+# (boolean value)
+#ceilometer=true
+
+# Whether or not Horizon is expected to be available (boolean
+# value)
+#horizon=true
+
+
+[compute-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# If false, skip all nova v3 tests. (boolean value)
+#api_v3=false
+
+# If false, skip disk config tests (boolean value)
+#disk_config=true
+
+# If false, skip flavor extra data test (boolean value)
+#flavor_extra=true
+
+# Does the test environment support changing the admin
+# password? (boolean value)
+#change_password=false
+
+# Does the test environment support snapshots? (boolean value)
+#create_image=false
+
+# Does the test environment support resizing? (boolean value)
+#resize=false
+
+# Does the test environment support live migration available?
+# (boolean value)
+#live_migration=false
+
+# Does the test environment use block devices for live
+# migration (boolean value)
+#block_migration_for_live_migration=false
+
+# Does the test environment block migration support cinder
+# iSCSI volumes (boolean value)
+#block_migrate_cinder_iscsi=false
+
+
+[object-storage-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# Set to True if the container quota middleware is enabled
+# (boolean value)
+#container_quotas=true
+
+# Set to True if the Account Quota middleware is enabled
+# (boolean value)
+#accounts_quotas=true
+
+# Set to True if the Crossdomain middleware is enabled
+# (boolean value)
+#crossdomain=true
+
+
+[volume-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# Runs Cinder multi-backend test (requires 2 backends)
+# (boolean value)
+#multi_backend=false
+
+
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index ff1ef81..467a6f9 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -17,7 +17,7 @@
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -47,7 +47,7 @@
@attr(type='gate')
def test_aggregate_create_delete(self):
# Create and delete an aggregate.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.assertEqual(200, resp.status)
self.assertEqual(aggregate_name, aggregate['name'])
@@ -60,8 +60,8 @@
@attr(type='gate')
def test_aggregate_create_delete_with_az(self):
# Create and delete an aggregate.
- aggregate_name = rand_name(self.aggregate_name_prefix)
- az_name = rand_name(self.az_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+ az_name = data_utils.rand_name(self.az_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
self.assertEqual(200, resp.status)
self.assertEqual(aggregate_name, aggregate['name'])
@@ -74,7 +74,7 @@
@attr(type='gate')
def test_aggregate_create_verify_entry_in_list(self):
# Create an aggregate and ensure it is listed.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -87,7 +87,7 @@
@attr(type='gate')
def test_aggregate_create_update_metadata_get_details(self):
# Create an aggregate and ensure its details are returned.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -113,8 +113,8 @@
def test_aggregate_create_update_with_az(self):
# Update an aggregate and ensure properties are updated correctly
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
- az_name = rand_name(self.az_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+ az_name = data_utils.rand_name(self.az_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -144,7 +144,7 @@
@attr(type=['negative', 'gate'])
def test_aggregate_create_as_user(self):
# Regular user is not allowed to create an aggregate.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
self.assertRaises(exceptions.Unauthorized,
self.user_client.create_aggregate,
aggregate_name)
@@ -152,7 +152,7 @@
@attr(type=['negative', 'gate'])
def test_aggregate_delete_as_user(self):
# Regular user is not allowed to delete an aggregate.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -169,7 +169,7 @@
@attr(type=['negative', 'gate'])
def test_aggregate_get_details_as_user(self):
# Regular user is not allowed to get aggregate details.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -193,7 +193,7 @@
def test_aggregate_add_remove_host(self):
# Add an host to the given aggregate and remove.
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -215,7 +215,7 @@
def test_aggregate_add_host_list(self):
# Add an host to the given aggregate and list.
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
self.client.add_host(aggregate['id'], self.host)
@@ -233,7 +233,7 @@
def test_aggregate_add_host_get_details(self):
# Add an host to the given aggregate and get details.
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
self.client.add_host(aggregate['id'], self.host)
@@ -248,13 +248,13 @@
def test_aggregate_add_host_create_server_with_az(self):
# Add an host to the given aggregate and create a server.
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
- az_name = rand_name(self.az_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+ az_name = data_utils.rand_name(self.az_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
self.client.add_host(aggregate['id'], self.host)
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
- server_name = rand_name('test_server_')
+ server_name = data_utils.rand_name('test_server_')
admin_servers_client = self.os_adm.servers_client
resp, server = self.create_test_server(name=server_name,
availability_zone=az_name,
@@ -268,11 +268,11 @@
resp, hosts_all = self.os_adm.hosts_client.list_hosts()
hosts = map(lambda x: x['host_name'], hosts_all)
while True:
- non_exist_host = rand_name('nonexist_host_')
+ non_exist_host = data_utils.rand_name('nonexist_host_')
if non_exist_host not in hosts:
break
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -282,7 +282,7 @@
@attr(type=['negative', 'gate'])
def test_aggregate_add_host_as_user(self):
# Regular user is not allowed to add a host to an aggregate.
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
@@ -294,7 +294,7 @@
def test_aggregate_remove_host_as_user(self):
# Regular user is not allowed to remove a host from an aggregate.
self.useFixture(fixtures.LockFixture('availability_zone'))
- aggregate_name = rand_name(self.aggregate_name_prefix)
+ aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
self.client.add_host(aggregate['id'], self.host)
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 05bb457..8d2fcac 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -17,8 +17,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import skip_because
@@ -58,8 +57,8 @@
def test_create_flavor(self):
# Create a flavor and ensure it is listed
# This operation requires the user to have 'admin' role
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -91,8 +90,8 @@
def test_create_flavor_verify_entry_in_list_details(self):
# Create a flavor and ensure it's details are listed
# This operation requires the user to have 'admin' role
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -116,8 +115,8 @@
def test_get_flavor_details_for_deleted_flavor(self):
# Delete a flavor and ensure it is not listed
# Create a test flavor
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, flavor = self.client.create_flavor(flavor_name,
self.ram,
@@ -158,8 +157,8 @@
self.assertEqual(int(flavor['OS-FLV-EXT-DATA:ephemeral']), 0)
self.assertEqual(flavor['os-flavor-access:is_public'], True)
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -196,8 +195,8 @@
# Create a flavor with os-flavor-access:is_public false should
# be present in list_details.
# This operation requires the user to have 'admin' role
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -227,8 +226,8 @@
@attr(type='gate')
def test_create_server_with_non_public_flavor(self):
# Create a flavor with os-flavor-access:is_public false
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -248,8 +247,8 @@
def test_list_public_flavor_with_other_user(self):
# Create a Flavor with public access.
# Try to List/Get flavor with another user
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
# Create the flavor
resp, flavor = self.client.create_flavor(flavor_name,
@@ -270,10 +269,10 @@
@attr(type='gate')
def test_is_public_string_variations(self):
- flavor_id_not_public = rand_int_id(start=1000)
- flavor_name_not_public = rand_name(self.flavor_name_prefix)
- flavor_id_public = rand_int_id(start=1000)
- flavor_name_public = rand_name(self.flavor_name_prefix)
+ flavor_id_not_public = data_utils.rand_int_id(start=1000)
+ flavor_name_not_public = data_utils.rand_name(self.flavor_name_prefix)
+ flavor_id_public = data_utils.rand_int_id(start=1000)
+ flavor_name_public = data_utils.rand_name(self.flavor_name_prefix)
# Create a non public flavor
resp, flavor = self.client.create_flavor(flavor_name_not_public,
@@ -313,8 +312,8 @@
@attr(type='gate')
def test_create_flavor_using_string_ram(self):
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
ram = " 1024 "
resp, flavor = self.client.create_flavor(flavor_name,
@@ -337,8 +336,8 @@
@attr(type=['negative', 'gate'])
def test_create_flavor_as_user(self):
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
self.assertRaises(exceptions.Unauthorized,
self.user_client.create_flavor,
@@ -354,8 +353,8 @@
@attr(type=['negative', 'gate'])
def test_create_flavor_using_invalid_ram(self):
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
self.assertRaises(exceptions.BadRequest,
self.client.create_flavor,
@@ -364,8 +363,8 @@
@attr(type=['negative', 'gate'])
def test_create_flavor_using_invalid_vcpus(self):
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
self.assertRaises(exceptions.BadRequest,
self.client.create_flavor,
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 43d4ea3..b866db1 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -17,8 +17,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -55,8 +54,8 @@
@attr(type='gate')
def test_flavor_access_list_with_private_flavor(self):
# Test to list flavor access successfully by querying private flavor
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
@@ -74,8 +73,8 @@
@attr(type='gate')
def test_flavor_access_add_remove(self):
# Test to add and remove flavor access to a given tenant.
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 4d2983c..340c1c7 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -19,8 +19,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -58,8 +57,8 @@
@attr(type=['negative', 'gate'])
def test_flavor_access_list_with_public_flavor(self):
# Test to list flavor access with exceptions by querying public flavor
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
@@ -74,8 +73,8 @@
@attr(type=['negative', 'gate'])
def test_flavor_non_admin_add(self):
# Test to add flavor access as a user without admin privileges.
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
@@ -90,8 +89,8 @@
@attr(type=['negative', 'gate'])
def test_flavor_non_admin_remove(self):
# Test to remove flavor access as a user without admin privileges.
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
@@ -110,8 +109,8 @@
@attr(type=['negative', 'gate'])
def test_add_flavor_access_duplicate(self):
# Create a new flavor.
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
@@ -134,8 +133,8 @@
@attr(type=['negative', 'gate'])
def test_remove_flavor_access_not_found(self):
# Create a new flavor.
- flavor_name = rand_name(self.flavor_name_prefix)
- new_flavor_id = rand_int_id(start=1000)
+ flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
resp, new_flavor = self.client.create_flavor(flavor_name,
self.ram, self.vcpus,
self.disk,
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 6101332..49b0429 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -17,8 +17,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -40,12 +39,12 @@
raise cls.skipException(msg)
cls.client = cls.os_adm.flavors_client
- flavor_name = rand_name('test_flavor')
+ flavor_name = data_utils.rand_name('test_flavor')
ram = 512
vcpus = 1
disk = 10
ephemeral = 10
- cls.new_flavor_id = rand_int_id(start=1000)
+ cls.new_flavor_id = data_utils.rand_int_id(start=1000)
swap = 1024
rxtx = 1
# Create a flavor so as to set/get/unset extra specs
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index 223c902..d7e1f9f 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -18,8 +18,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -41,12 +40,12 @@
raise cls.skipException(msg)
cls.client = cls.os_adm.flavors_client
- flavor_name = rand_name('test_flavor')
+ flavor_name = data_utils.rand_name('test_flavor')
ram = 512
vcpus = 1
disk = 10
ephemeral = 10
- cls.new_flavor_id = rand_int_id(start=1000)
+ cls.new_flavor_id = data_utils.rand_int_id(start=1000)
swap = 1024
rxtx = 1
# Create a flavor
@@ -100,7 +99,7 @@
@attr(type=['negative', 'gate'])
def test_flavor_unset_nonexistent_key(self):
- nonexistent_key = rand_name('flavor_key')
+ nonexistent_key = data_utils.rand_name('flavor_key')
self.assertRaises(exceptions.NotFound,
self.client.unset_flavor_extra_spec,
self.flavor['id'],
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
new file mode 100644
index 0000000..cea6e92
--- /dev/null
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -0,0 +1,64 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 datetime
+
+from tempest.api.compute import base
+from tempest.test import attr
+import urllib
+
+
+class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(InstanceUsageAuditLogTestJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+
+ @attr(type='gate')
+ def test_list_instance_usage_audit_logs(self):
+ # list instance usage audit logs
+ resp, body = self.adm_client.list_instance_usage_audit_logs()
+ self.assertEqual(200, resp.status)
+ expected_items = ['total_errors', 'total_instances', 'log',
+ 'num_hosts_running', 'num_hosts_done',
+ 'num_hosts', 'hosts_not_run', 'overall_status',
+ 'period_ending', 'period_beginning',
+ 'num_hosts_not_run']
+ for item in expected_items:
+ self.assertIn(item, body)
+
+ @attr(type='gate')
+ def test_get_instance_usage_audit_log(self):
+ # Get instance usage audit log before specified time
+ now = datetime.datetime.now()
+ resp, body = self.adm_client.get_instance_usage_audit_log(
+ urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
+
+ self.assertEqual(200, resp.status)
+ expected_items = ['total_errors', 'total_instances', 'log',
+ 'num_hosts_running', 'num_hosts_done', 'num_hosts',
+ 'hosts_not_run', 'overall_status', 'period_ending',
+ 'period_beginning', 'num_hosts_not_run']
+ for item in expected_items:
+ self.assertIn(item, body)
+
+
+class InstanceUsageAuditLogTestXML(InstanceUsageAuditLogTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
new file mode 100644
index 0000000..dcf41c5
--- /dev/null
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -0,0 +1,56 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 datetime
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+import urllib
+
+
+class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(InstanceUsageAuditLogNegativeTestJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+
+ @attr(type=['negative', 'gate'])
+ def test_instance_usage_audit_logs_with_nonadmin_user(self):
+ # the instance_usage_audit_logs API just can be accessed by admin user
+ self.assertRaises(exceptions.Unauthorized,
+ self.instance_usages_audit_log_client.
+ list_instance_usage_audit_logs)
+ now = datetime.datetime.now()
+ self.assertRaises(exceptions.Unauthorized,
+ self.instance_usages_audit_log_client.
+ get_instance_usage_audit_log,
+ urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
+
+ @attr(type=['negative', 'gate'])
+ def test_get_instance_usage_audit_logs_with_invalid_time(self):
+ self.assertRaises(exceptions.BadRequest,
+ self.adm_client.get_instance_usage_audit_log,
+ "invalid_time")
+
+
+class InstanceUsageAuditLogNegativeTestXML(
+ InstanceUsageAuditLogNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index ded0477..f49aae4 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.test import attr
@@ -87,7 +87,7 @@
@attr(type='gate')
def test_get_updated_quotas(self):
# Verify that GET shows the updated quota set
- tenant_name = rand_name('cpu_quota_tenant_')
+ tenant_name = data_utils.rand_name('cpu_quota_tenant_')
tenant_desc = tenant_name + '-desc'
identity_client = self.os_adm.identity_client
_, tenant = identity_client.create_tenant(name=tenant_name,
@@ -200,8 +200,8 @@
self.demo_tenant_id,
security_group_rules=default_sg_rules_quota)
- s_name = rand_name('securitygroup-')
- s_description = rand_name('description-')
+ s_name = data_utils.rand_name('securitygroup-')
+ s_description = data_utils.rand_name('description-')
resp, securitygroup =\
self.sg_client.create_security_group(s_name, s_description)
self.addCleanup(self.sg_client.delete_security_group,
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 8c6cf8d..a3bccc3 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -15,8 +15,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import skip_because
@@ -41,23 +40,23 @@
cls.client.tenant_name)
cls.tenant_id = tenant['id']
- cls.s1_name = rand_name('server')
+ cls.s1_name = data_utils.rand_name('server')
resp, server = cls.create_test_server(name=cls.s1_name,
wait_until='ACTIVE')
cls.s1_id = server['id']
- cls.s2_name = rand_name('server')
+ cls.s2_name = data_utils.rand_name('server')
resp, server = cls.create_test_server(name=cls.s2_name,
wait_until='ACTIVE')
def _get_unused_flavor_id(self):
- flavor_id = rand_int_id(start=1000)
+ flavor_id = data_utils.rand_int_id(start=1000)
while True:
try:
resp, body = self.flavors_client.get_flavor_details(flavor_id)
except exceptions.NotFound:
break
- flavor_id = rand_int_id(start=1000)
+ flavor_id = data_utils.rand_int_id(start=1000)
return flavor_id
@attr(type='gate')
@@ -90,7 +89,7 @@
@attr(type=['negative', 'gate'])
def test_resize_server_using_overlimit_ram(self):
- flavor_name = rand_name("flavor-")
+ flavor_name = data_utils.rand_name("flavor-")
flavor_id = self._get_unused_flavor_id()
resp, quota_set = self.quotas_client.get_default_quota_set(
self.tenant_id)
@@ -108,7 +107,7 @@
@attr(type=['negative', 'gate'])
def test_resize_server_using_overlimit_vcpus(self):
- flavor_name = rand_name("flavor-")
+ flavor_name = data_utils.rand_name("flavor-")
flavor_id = self._get_unused_flavor_id()
ram = 512
resp, quota_set = self.quotas_client.get_default_quota_set(
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 715ec16..4b6816b 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -19,8 +19,7 @@
from tempest.api import compute
from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import log as logging
import tempest.test
@@ -94,7 +93,7 @@
@classmethod
def create_test_server(cls, **kwargs):
"""Wrapper utility that returns a test server."""
- name = rand_name(cls.__name__ + "-instance")
+ name = data_utils.rand_name(cls.__name__ + "-instance")
if 'name' in kwargs:
name = kwargs.pop('name')
flavor = kwargs.get('flavor', cls.flavor_ref)
@@ -156,6 +155,8 @@
cls.availability_zone_client = cls.os.availability_zone_client
cls.aggregates_client = cls.os.aggregates_client
cls.services_client = cls.os.services_client
+ cls.instance_usages_audit_log_client = \
+ cls.os.instance_usages_audit_log_client
cls.hypervisor_client = cls.os.hypervisor_client
cls.servers_client_v3_auth = cls.os.servers_client_v3_auth
cls.certificates_client = cls.os.certificates_client
@@ -163,13 +164,13 @@
@classmethod
def create_image_from_server(cls, server_id, **kwargs):
"""Wrapper utility that returns an image created from the server."""
- name = rand_name(cls.__name__ + "-image")
+ name = data_utils.rand_name(cls.__name__ + "-image")
if 'name' in kwargs:
name = kwargs.pop('name')
resp, image = cls.images_client.create_image(
server_id, name)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
cls.images.append(image_id)
if 'wait_until' in kwargs:
@@ -236,13 +237,13 @@
@classmethod
def create_image_from_server(cls, server_id, **kwargs):
"""Wrapper utility that returns an image created from the server."""
- name = rand_name(cls.__name__ + "-image")
+ name = data_utils.rand_name(cls.__name__ + "-image")
if 'name' in kwargs:
name = kwargs.pop('name')
resp, image = cls.servers_client.create_image(
server_id, name)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
cls.images.append(image_id)
if 'wait_until' in kwargs:
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index 21a2256..a06309a 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -37,7 +37,6 @@
# Server creation
resp, server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
- resp, body = cls.servers_client.get_server(server['id'])
# Floating IP creation
resp, body = cls.client.create_floating_ip()
cls.floating_ip_id = body['id']
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 7fec2d1..6387f4e 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -32,7 +32,6 @@
cls.client = cls.floating_ips_client
cls.floating_ip = []
cls.floating_ip_id = []
- cls.random_number = 0
for i in range(3):
resp, body = cls.client.create_floating_ip()
cls.floating_ip.append(body)
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index e497062..618abe2 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -38,7 +38,7 @@
cls.server_id = server['id']
# Snapshot the server once to save time
- name = rand_name('image')
+ name = data_utils.rand_name('image')
resp, _ = cls.client.create_image(cls.server_id, name, {})
cls.image_id = resp['location'].rsplit('/', 1)[1]
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index bb6ead9..4539981 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -17,8 +17,7 @@
from tempest.api import compute
from tempest.api.compute import base
from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -58,7 +57,7 @@
def __create_image__(self, server_id, name, meta=None):
resp, body = self.client.create_image(server_id, name, meta)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
self.client.wait_for_image_status(image_id, 'ACTIVE')
self.image_ids.append(image_id)
return resp, body
@@ -72,7 +71,7 @@
self.servers_client.delete_server(server['id'])
self.servers_client.wait_for_server_termination(server['id'])
# Create a new image after server is deleted
- name = rand_name('image')
+ name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
self.assertRaises(exceptions.NotFound,
self.__create_image__,
@@ -82,7 +81,7 @@
def test_create_image_from_invalid_server(self):
# An image should not be created with invalid server id
# Create a new image with invalid server id
- name = rand_name('image')
+ name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
resp = {}
resp['status'] = None
@@ -96,7 +95,7 @@
self.servers_client.wait_for_server_status(server['id'],
'SHUTOFF')
self.addCleanup(self.servers_client.delete_server, server['id'])
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
resp, image = self.create_image_from_server(server['id'],
name=snapshot_name,
wait_until='ACTIVE')
@@ -105,7 +104,7 @@
@attr(type='gate')
def test_delete_saving_image(self):
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
resp, server = self.create_test_server(wait_until='ACTIVE')
self.addCleanup(self.servers_client.delete_server, server['id'])
resp, image = self.create_image_from_server(server['id'],
@@ -117,7 +116,7 @@
@attr(type=['negative', 'gate'])
def test_create_image_specify_uuid_35_characters_or_less(self):
# Return an error if Image ID passed is 35 characters or less
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 35)
self.assertRaises(exceptions.NotFound, self.client.create_image,
test_uuid, snapshot_name)
@@ -125,7 +124,7 @@
@attr(type=['negative', 'gate'])
def test_create_image_specify_uuid_37_characters_or_more(self):
# Return an error if Image ID passed is 37 characters or more
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 37)
self.assertRaises(exceptions.NotFound, self.client.create_image,
test_uuid, snapshot_name)
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index d0bed57..612c110 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -20,12 +20,9 @@
from tempest.api import compute
from tempest.api.compute import base
from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.test import attr
-from tempest.test import skip_because
LOG = logging.getLogger(__name__)
@@ -83,31 +80,6 @@
cls.alt_manager = clients.AltManager()
cls.alt_client = cls.alt_manager.images_client
- @skip_because(bug="1006725")
- @attr(type=['negative', 'gate'])
- def test_create_image_specify_multibyte_character_image_name(self):
- # Return an error if the image name has multi-byte characters
- snapshot_name = rand_name('\xef\xbb\xbf')
- self.assertRaises(exceptions.BadRequest,
- self.client.create_image, self.server_id,
- snapshot_name)
-
- @attr(type=['negative', 'gate'])
- def test_create_image_specify_invalid_metadata(self):
- # Return an error when creating image with invalid metadata
- snapshot_name = rand_name('test-snap-')
- meta = {'': ''}
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
- self.server_id, snapshot_name, meta)
-
- @attr(type=['negative', 'gate'])
- def test_create_image_specify_metadata_over_limits(self):
- # Return an error when creating image with meta data over 256 chars
- snapshot_name = rand_name('test-snap-')
- meta = {'a' * 260: 'b' * 260}
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
- self.server_id, snapshot_name, meta)
-
def _get_default_flavor_disk_size(self, flavor_id):
resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
return flavor['disk']
@@ -118,11 +90,11 @@
def test_create_delete_image(self):
# Create a new image
- name = rand_name('image')
+ name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
resp, body = self.client.create_image(self.server_id, name, meta)
self.assertEqual(202, resp.status)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
self.client.wait_for_image_status(image_id, 'ACTIVE')
# Verify the image was created correctly
@@ -145,49 +117,6 @@
self.assertEqual('204', resp['status'])
self.client.wait_for_resource_deletion(image_id)
- @attr(type=['negative', 'gate'])
- def test_create_second_image_when_first_image_is_being_saved(self):
- # Disallow creating another image when first image is being saved
-
- # Create first snapshot
- snapshot_name = rand_name('test-snap-')
- resp, body = self.client.create_image(self.server_id,
- snapshot_name)
- self.assertEqual(202, resp.status)
- image_id = parse_image_id(resp['location'])
- self.image_ids.append(image_id)
-
- # Create second snapshot
- alt_snapshot_name = rand_name('test-snap-')
- self.assertRaises(exceptions.Conflict, self.client.create_image,
- self.server_id, alt_snapshot_name)
- self.client.wait_for_image_status(image_id, 'ACTIVE')
-
- @attr(type=['negative', 'gate'])
- def test_create_image_specify_name_over_256_chars(self):
- # Return an error if snapshot name over 256 characters is passed
-
- snapshot_name = rand_name('a' * 260)
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
- self.server_id, snapshot_name)
-
- @attr(type=['negative', 'gate'])
- def test_delete_image_that_is_not_yet_active(self):
- # Return an error while trying to delete an image what is creating
-
- snapshot_name = rand_name('test-snap-')
- resp, body = self.client.create_image(self.server_id, snapshot_name)
- self.assertEqual(202, resp.status)
- image_id = parse_image_id(resp['location'])
- self.image_ids.append(image_id)
-
- # Do not wait, attempt to delete the image, ensure it's successful
- resp, body = self.client.delete_image(image_id)
- self.assertEqual('204', resp['status'])
- self.image_ids.remove(image_id)
-
- self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
-
class ImagesOneServerTestXML(ImagesOneServerTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
new file mode 100644
index 0000000..db3acb5
--- /dev/null
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -0,0 +1,155 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# 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 tempest.api import compute
+from tempest.api.compute import base
+from tempest import clients
+from tempest.common.utils.data_utils import parse_image_id
+from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+from tempest.openstack.common import log as logging
+from tempest.test import attr
+from tempest.test import skip_because
+
+LOG = logging.getLogger(__name__)
+
+
+class ImagesOneServerNegativeTestJSON(base.BaseV2ComputeTest):
+ _interface = 'json'
+
+ def tearDown(self):
+ """Terminate test instances created after a test is executed."""
+ for image_id in self.image_ids:
+ self.client.delete_image(image_id)
+ self.image_ids.remove(image_id)
+ super(ImagesOneServerNegativeTestJSON, self).tearDown()
+
+ def setUp(self):
+ # NOTE(afazekas): Normally we use the same server with all test cases,
+ # but if it has an issue, we build a new one
+ super(ImagesOneServerNegativeTestJSON, self).setUp()
+ # Check if the server is in a clean state after test
+ try:
+ self.servers_client.wait_for_server_status(self.server_id,
+ 'ACTIVE')
+ except Exception as exc:
+ LOG.exception(exc)
+ # Rebuild server if cannot reach the ACTIVE state
+ # Usually it means the server had a serius accident
+ self.rebuild_server()
+
+ @classmethod
+ def setUpClass(cls):
+ super(ImagesOneServerNegativeTestJSON, cls).setUpClass()
+ cls.client = cls.images_client
+ if not cls.config.service_available.glance:
+ skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ try:
+ resp, server = cls.create_test_server(wait_until='ACTIVE')
+ cls.server_id = server['id']
+ except Exception:
+ cls.tearDownClass()
+ raise
+
+ cls.image_ids = []
+
+ if compute.MULTI_USER:
+ if cls.config.compute.allow_tenant_isolation:
+ creds = cls.isolated_creds.get_alt_creds()
+ username, tenant_name, password = creds
+ cls.alt_manager = clients.Manager(username=username,
+ password=password,
+ tenant_name=tenant_name)
+ else:
+ # Use the alt_XXX credentials in the config file
+ cls.alt_manager = clients.AltManager()
+ cls.alt_client = cls.alt_manager.images_client
+
+ @skip_because(bug="1006725")
+ @attr(type=['negative', 'gate'])
+ def test_create_image_specify_multibyte_character_image_name(self):
+ # Return an error if the image name has multi-byte characters
+ snapshot_name = rand_name('\xef\xbb\xbf')
+ self.assertRaises(exceptions.BadRequest,
+ self.client.create_image, self.server_id,
+ snapshot_name)
+
+ @attr(type=['negative', 'gate'])
+ def test_create_image_specify_invalid_metadata(self):
+ # Return an error when creating image with invalid metadata
+ snapshot_name = rand_name('test-snap-')
+ meta = {'': ''}
+ self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.server_id, snapshot_name, meta)
+
+ @attr(type=['negative', 'gate'])
+ def test_create_image_specify_metadata_over_limits(self):
+ # Return an error when creating image with meta data over 256 chars
+ snapshot_name = rand_name('test-snap-')
+ meta = {'a' * 260: 'b' * 260}
+ self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.server_id, snapshot_name, meta)
+
+ @attr(type=['negative', 'gate'])
+ def test_create_second_image_when_first_image_is_being_saved(self):
+ # Disallow creating another image when first image is being saved
+
+ # Create first snapshot
+ snapshot_name = rand_name('test-snap-')
+ resp, body = self.client.create_image(self.server_id,
+ snapshot_name)
+ self.assertEqual(202, resp.status)
+ image_id = parse_image_id(resp['location'])
+ self.image_ids.append(image_id)
+
+ # Create second snapshot
+ alt_snapshot_name = rand_name('test-snap-')
+ self.assertRaises(exceptions.Conflict, self.client.create_image,
+ self.server_id, alt_snapshot_name)
+ self.client.wait_for_image_status(image_id, 'ACTIVE')
+
+ @attr(type=['negative', 'gate'])
+ def test_create_image_specify_name_over_256_chars(self):
+ # Return an error if snapshot name over 256 characters is passed
+
+ snapshot_name = rand_name('a' * 260)
+ self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.server_id, snapshot_name)
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_image_that_is_not_yet_active(self):
+ # Return an error while trying to delete an image what is creating
+
+ snapshot_name = rand_name('test-snap-')
+ resp, body = self.client.create_image(self.server_id, snapshot_name)
+ self.assertEqual(202, resp.status)
+ image_id = parse_image_id(resp['location'])
+ self.image_ids.append(image_id)
+
+ # Do not wait, attempt to delete the image, ensure it's successful
+ resp, body = self.client.delete_image(image_id)
+ self.assertEqual('204', resp['status'])
+ self.image_ids.remove(image_id)
+
+ self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+
+class ImagesOneServerNegativeTestXML(ImagesOneServerNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 00a172a..1401654 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import parse_image_id
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.test import attr
@@ -46,7 +46,7 @@
# Create images to be used in the filter tests
resp, body = cls.create_image_from_server(cls.server1['id'])
- cls.image1_id = parse_image_id(resp['location'])
+ cls.image1_id = data_utils.parse_image_id(resp['location'])
cls.client.wait_for_image_status(cls.image1_id, 'ACTIVE')
resp, cls.image1 = cls.client.get_image(cls.image1_id)
@@ -54,12 +54,12 @@
# Performing back-to-back create image calls on a single
# server will sometimes cause failures
resp, body = cls.create_image_from_server(cls.server2['id'])
- cls.image3_id = parse_image_id(resp['location'])
+ cls.image3_id = data_utils.parse_image_id(resp['location'])
cls.client.wait_for_image_status(cls.image3_id, 'ACTIVE')
resp, cls.image3 = cls.client.get_image(cls.image3_id)
resp, body = cls.create_image_from_server(cls.server1['id'])
- cls.image2_id = parse_image_id(resp['location'])
+ cls.image2_id = data_utils.parse_image_id(resp['location'])
cls.client.wait_for_image_status(cls.image2_id, 'ACTIVE')
resp, cls.image2 = cls.client.get_image(cls.image2_id)
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index d059994..475b218 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -35,7 +35,7 @@
# Create 3 keypairs
key_list = list()
for i in range(3):
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
resp, keypair = self.client.create_keypair(k_name)
# Need to pop these keys so that our compare doesn't fail later,
# as the keypair dicts from list API doesn't have them.
@@ -66,7 +66,7 @@
@attr(type='gate')
def test_keypair_create_delete(self):
# Keypair should be created, verified and deleted
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
resp, keypair = self.client.create_keypair(k_name)
self.assertEqual(200, resp.status)
private_key = keypair['private_key']
@@ -82,7 +82,7 @@
@attr(type='gate')
def test_get_keypair_detail(self):
# Keypair should be created, Got details by name and deleted
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
resp, keypair = self.client.create_keypair(k_name)
self.addCleanup(self.client.delete_keypair, k_name)
resp, keypair_detail = self.client.get_keypair(k_name)
@@ -99,7 +99,7 @@
@attr(type='gate')
def test_keypair_create_with_pub_key(self):
# Keypair should be created with a given public key
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
pub_key = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs"
"Ne3/1ILNCqFyfYWDeTKLD6jEXC2OQHLmietMWW+/vd"
"aZq7KZEwO0jhglaFjU1mpqq4Gz5RX156sCTNM9vRbw"
@@ -123,7 +123,7 @@
@attr(type=['negative', 'gate'])
def test_keypair_create_with_invalid_pub_key(self):
# Keypair should not be created with a non RSA public key
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
pub_key = "ssh-rsa JUNK nova@ubuntu"
self.assertRaises(exceptions.BadRequest,
self.client.create_keypair, k_name, pub_key)
@@ -131,14 +131,14 @@
@attr(type=['negative', 'gate'])
def test_keypair_delete_nonexistant_key(self):
# Non-existant key deletion should throw a proper error
- k_name = rand_name("keypair-non-existant-")
+ k_name = data_utils.rand_name("keypair-non-existant-")
self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
k_name)
@attr(type=['negative', 'gate'])
def test_create_keypair_with_empty_public_key(self):
# Keypair should not be created with an empty public key
- k_name = rand_name("keypair-")
+ k_name = data_utils.rand_name("keypair-")
pub_key = ' '
self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
k_name, pub_key)
@@ -146,7 +146,7 @@
@attr(type=['negative', 'gate'])
def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
# Keypair should not be created when public key bits are too long
- k_name = rand_name("keypair-")
+ k_name = data_utils.rand_name("keypair-")
pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
k_name, pub_key)
@@ -154,7 +154,7 @@
@attr(type=['negative', 'gate'])
def test_create_keypair_with_duplicate_name(self):
# Keypairs with duplicate names should not be created
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
resp, _ = self.client.create_keypair(k_name)
self.assertEqual(200, resp.status)
# Now try the same keyname to create another key
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 58606eb..44ce405 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -22,7 +22,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
import tempest.config
from tempest.test import attr
@@ -39,7 +39,7 @@
cls.meta = {'hello': 'world'}
cls.accessIPv4 = '1.1.1.1'
cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
- cls.name = rand_name('server')
+ cls.name = data_utils.rand_name('server')
file_contents = 'This is a test file.'
personality = [{'path': '/test.txt',
'contents': base64.b64encode(file_contents)}]
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index d3eaaa1..5e9ee5c 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -32,19 +32,25 @@
raise cls.skipException(msg)
super(ServerDiskConfigTestJSON, cls).setUpClass()
cls.client = cls.os.servers_client
+ resp, server = cls.create_test_server(wait_until='ACTIVE')
+ cls.server_id = server['id']
+
+ def _update_server_with_disk_config(self, disk_config):
+ resp, server = self.client.get_server(self.server_id)
+ if disk_config != server['OS-DCF:diskConfig']:
+ resp, server = self.client.update_server(self.server_id,
+ disk_config=disk_config)
+ self.assertEqual(200, resp.status)
+ self.client.wait_for_server_status(server['id'], 'ACTIVE')
+ resp, server = self.client.get_server(server['id'])
+ self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
@attr(type='gate')
def test_rebuild_server_with_manual_disk_config(self):
# A server should be rebuilt using the manual disk config option
- resp, server = self.create_test_server(disk_config='AUTO',
- wait_until='ACTIVE')
- self.addCleanup(self.client.delete_server, server['id'])
+ self._update_server_with_disk_config(disk_config='AUTO')
- # Verify the specified attributes are set correctly
- resp, server = self.client.get_server(server['id'])
- self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
-
- resp, server = self.client.rebuild(server['id'],
+ resp, server = self.client.rebuild(self.server_id,
self.image_ref_alt,
disk_config='MANUAL')
@@ -58,15 +64,9 @@
@attr(type='gate')
def test_rebuild_server_with_auto_disk_config(self):
# A server should be rebuilt using the auto disk config option
- resp, server = self.create_test_server(disk_config='MANUAL',
- wait_until='ACTIVE')
- self.addCleanup(self.client.delete_server, server['id'])
+ self._update_server_with_disk_config(disk_config='MANUAL')
- # Verify the specified attributes are set correctly
- resp, server = self.client.get_server(server['id'])
- self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
-
- resp, server = self.client.rebuild(server['id'],
+ resp, server = self.client.rebuild(self.server_id,
self.image_ref_alt,
disk_config='AUTO')
@@ -77,55 +77,53 @@
resp, server = self.client.get_server(server['id'])
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
+ def _get_alternative_flavor(self):
+ resp, server = self.client.get_server(self.server_id)
+
+ if int(server['flavor']['id']) == self.flavor_ref:
+ return self.flavor_ref_alt
+ else:
+ return self.flavor_ref
+
@testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
@attr(type='gate')
def test_resize_server_from_manual_to_auto(self):
# A server should be resized from manual to auto disk config
- resp, server = self.create_test_server(disk_config='MANUAL',
- wait_until='ACTIVE')
- self.addCleanup(self.client.delete_server, server['id'])
+ self._update_server_with_disk_config(disk_config='MANUAL')
# Resize with auto option
- self.client.resize(server['id'], self.flavor_ref_alt,
- disk_config='AUTO')
- self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
- self.client.confirm_resize(server['id'])
- self.client.wait_for_server_status(server['id'], 'ACTIVE')
+ flavor_id = self._get_alternative_flavor()
+ self.client.resize(self.server_id, flavor_id, disk_config='AUTO')
+ self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+ self.client.confirm_resize(self.server_id)
+ self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, server = self.client.get_server(server['id'])
+ resp, server = self.client.get_server(self.server_id)
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
@testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
@attr(type='gate')
def test_resize_server_from_auto_to_manual(self):
# A server should be resized from auto to manual disk config
- resp, server = self.create_test_server(disk_config='AUTO',
- wait_until='ACTIVE')
- self.addCleanup(self.client.delete_server, server['id'])
+ self._update_server_with_disk_config(disk_config='AUTO')
# Resize with manual option
- self.client.resize(server['id'], self.flavor_ref_alt,
- disk_config='MANUAL')
- self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
- self.client.confirm_resize(server['id'])
- self.client.wait_for_server_status(server['id'], 'ACTIVE')
+ flavor_id = self._get_alternative_flavor()
+ self.client.resize(self.server_id, flavor_id, disk_config='MANUAL')
+ self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+ self.client.confirm_resize(self.server_id)
+ self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, server = self.client.get_server(server['id'])
+ resp, server = self.client.get_server(self.server_id)
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
@attr(type='gate')
def test_update_server_from_auto_to_manual(self):
# A server should be updated from auto to manual disk config
- resp, server = self.create_test_server(disk_config='AUTO',
- wait_until='ACTIVE')
- self.addCleanup(self.client.delete_server, server['id'])
-
- # Verify the disk_config attribute is set correctly
- resp, server = self.client.get_server(server['id'])
- self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
+ self._update_server_with_disk_config(disk_config='AUTO')
# Update the disk_config attribute to manual
- resp, server = self.client.update_server(server['id'],
+ resp, server = self.client.update_server(self.server_id,
disk_config='MANUAL')
self.assertEqual(200, resp.status)
self.client.wait_for_server_status(server['id'], 'ACTIVE')
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 65bdd19..4cbf94d 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -17,7 +17,7 @@
from tempest.api.compute import base
from tempest.api import utils
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.test import attr
@@ -57,16 +57,16 @@
raise RuntimeError("Image %s (image_ref_alt) was not found!" %
cls.image_ref_alt)
- cls.s1_name = rand_name(cls.__name__ + '-instance')
+ cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
wait_until='ACTIVE')
- cls.s2_name = rand_name(cls.__name__ + '-instance')
+ cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
image_id=cls.image_ref_alt,
wait_until='ACTIVE')
- cls.s3_name = rand_name(cls.__name__ + '-instance')
+ cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
flavor=cls.flavor_ref_alt,
wait_until='ACTIVE')
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index a06e209..521a480 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -17,71 +17,19 @@
import datetime
-from tempest.api import compute
from tempest.api.compute import base
-from tempest import clients
from tempest import exceptions
from tempest.test import attr
class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
_interface = 'json'
-
- @classmethod
- def _ensure_no_servers(cls, servers, username, tenant_name):
- """
- If there are servers and there is tenant isolation then a
- skipException is raised to skip the test since it requires no servers
- to already exist for the given user/tenant.
- If there are servers and there is not tenant isolation then the test
- blocks while the servers are being deleted.
- """
- if len(servers):
- if not cls.config.compute.allow_tenant_isolation:
- for srv in servers:
- cls.client.wait_for_server_termination(srv['id'],
- ignore_error=True)
- else:
- msg = ("User/tenant %(u)s/%(t)s already have "
- "existing server instances. Skipping test." %
- {'u': username, 't': tenant_name})
- raise cls.skipException(msg)
+ force_tenant_isolation = True
@classmethod
def setUpClass(cls):
super(ListServersNegativeTestJSON, cls).setUpClass()
cls.client = cls.servers_client
- cls.servers = []
-
- if compute.MULTI_USER:
- if cls.config.compute.allow_tenant_isolation:
- creds = cls.isolated_creds.get_alt_creds()
- username, tenant_name, password = creds
- cls.alt_manager = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name)
- else:
- # Use the alt_XXX credentials in the config file
- cls.alt_manager = clients.AltManager()
- cls.alt_client = cls.alt_manager.servers_client
-
- # Under circumstances when there is not a tenant/user
- # created for the test case, the test case checks
- # to see if there are existing servers for the
- # either the normal user/tenant or the alt user/tenant
- # and if so, the whole test is skipped. We do this
- # because we assume a baseline of no servers at the
- # start of the test instead of destroying any existing
- # servers.
- resp, body = cls.client.list_servers()
- cls._ensure_no_servers(body['servers'],
- cls.os.username,
- cls.os.tenant_name)
-
- resp, body = cls.alt_client.list_servers()
- cls._ensure_no_servers(body['servers'],
- cls.alt_manager.username,
- cls.alt_manager.tenant_name)
# The following servers are created for use
# by the test methods in this class. These
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index d85db2f..080bd1a 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -26,7 +26,7 @@
_name = 'multiple-create-test'
def _generate_name(self):
- return rand_name(self._name)
+ return data_utils.rand_name(self._name)
def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
"""
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index b8700ec..1044ae1 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -22,8 +22,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
import tempest.config
from tempest import exceptions
@@ -113,7 +112,7 @@
def test_rebuild_server(self):
# The server should be rebuilt using the provided image and data
meta = {'rebuild': 'server'}
- new_name = rand_name('server')
+ new_name = data_utils.rand_name('server')
file_contents = 'Test server rebuild.'
personality = [{'path': 'rebuild.txt',
'contents': base64.b64encode(file_contents)}]
@@ -199,11 +198,12 @@
required time (%s s).' % (self.server_id, self.build_timeout)
raise exceptions.TimeoutException(message)
+ @skip_because(bug="1251920")
@attr(type='gate')
def test_create_backup(self):
# Positive test:create backup successfully and rotate backups correctly
# create the first and the second backup
- backup1 = rand_name('backup')
+ backup1 = data_utils.rand_name('backup')
resp, _ = self.servers_client.create_backup(self.server_id,
'daily',
2,
@@ -215,17 +215,17 @@
if oldest_backup_exist:
self.os.image_client.delete_image(oldest_backup)
- image1_id = parse_image_id(resp['location'])
+ image1_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(_clean_oldest_backup, image1_id)
self.assertEqual(202, resp.status)
- backup2 = rand_name('backup')
+ backup2 = data_utils.rand_name('backup')
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
resp, _ = self.servers_client.create_backup(self.server_id,
'daily',
2,
backup2)
- image2_id = parse_image_id(resp['location'])
+ image2_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image2_id)
self.assertEqual(202, resp.status)
@@ -246,13 +246,13 @@
# create the third one, due to the rotation is 2,
# the first one will be deleted
- backup3 = rand_name('backup')
+ backup3 = data_utils.rand_name('backup')
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
resp, _ = self.servers_client.create_backup(self.server_id,
'daily',
2,
backup3)
- image3_id = parse_image_id(resp['location'])
+ image3_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image3_id)
self.assertEqual(202, resp.status)
# the first back up should be deleted
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
new file mode 100644
index 0000000..93c6e44
--- /dev/null
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class ServerPasswordTestJSON(base.BaseV2ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(ServerPasswordTestJSON, cls).setUpClass()
+ cls.client = cls.servers_client
+ resp, cls.server = cls.create_test_server(wait_until="ACTIVE")
+
+ @attr(type='gate')
+ def test_get_server_password(self):
+ resp, body = self.client.get_password(self.server['id'])
+ self.assertEqual(200, resp.status)
+
+ @attr(type='gate')
+ def test_delete_server_password(self):
+ resp, body = self.client.delete_password(self.server['id'])
+ self.assertEqual(204, resp.status)
+
+
+class ServerPasswordTestXML(ServerPasswordTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 837ab48..1008670 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -35,8 +35,8 @@
cls.floating_ip = str(body['ip']).strip()
# Security group creation
- cls.sg_name = rand_name('sg')
- cls.sg_desc = rand_name('sg-desc')
+ cls.sg_name = data_utils.rand_name('sg')
+ cls.sg_desc = data_utils.rand_name('sg-desc')
resp, cls.sg = \
cls.security_groups_client.create_security_group(cls.sg_name,
cls.sg_desc)
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 8712234..d72476d 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -46,7 +46,7 @@
# Creating a server with a name that already exists is allowed
# TODO(sdague): clear out try, we do cleanup one layer up
- server_name = rand_name('server')
+ server_name = data_utils.rand_name('server')
resp, server = self.create_test_server(name=server_name,
wait_until='ACTIVE')
id1 = server['id']
@@ -64,7 +64,7 @@
def test_create_specify_keypair(self):
# Specify a keypair while creating a server
- key_name = rand_name('key')
+ key_name = data_utils.rand_name('key')
resp, keypair = self.keypairs_client.create_keypair(key_name)
resp, body = self.keypairs_client.list_keypairs()
resp, server = self.create_test_server(key_name=key_name)
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index b12afd1..5ec0cbe 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -21,7 +21,7 @@
from tempest.api.compute import base
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -155,7 +155,7 @@
# Rebuild a non existent server
nonexistent_server = str(uuid.uuid4())
meta = {'rebuild': 'server'}
- new_name = rand_name('server')
+ new_name = data_utils.rand_name('server')
file_contents = 'Test server rebuild.'
personality = [{'path': '/etc/rebuild.txt',
'contents': base64.b64encode(file_contents)}]
@@ -201,7 +201,7 @@
def test_create_with_non_existant_keypair(self):
# Pass a non-existent keypair while creating a server
- key_name = rand_name('key')
+ key_name = data_utils.rand_name('key')
self.assertRaises(exceptions.BadRequest,
self.create_test_server,
key_name=key_name)
@@ -219,8 +219,8 @@
def test_update_name_of_non_existent_server(self):
# Update name of a non-existent server
- server_name = rand_name('server')
- new_name = rand_name('server') + '_updated'
+ server_name = data_utils.rand_name('server')
+ new_name = data_utils.rand_name('server') + '_updated'
self.assertRaises(exceptions.NotFound, self.client.update_server,
server_name, name=new_name)
@@ -229,7 +229,7 @@
def test_update_server_set_empty_name(self):
# Update name of the server to an empty string
- server_name = rand_name('server')
+ server_name = data_utils.rand_name('server')
new_name = ''
self.assertRaises(exceptions.BadRequest, self.client.update_server,
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index d7309a6..77ada0b 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -18,7 +18,7 @@
import netaddr
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.test import attr
@@ -58,7 +58,7 @@
def test_list_virtual_interfaces_invalid_server_id(self):
# Negative test: Should not be able to GET virtual interfaces
# for an invalid server_id
- invalid_server_id = rand_name('!@#$%^&*()')
+ invalid_server_id = data_utils.rand_name('!@#$%^&*()')
self.assertRaises(exceptions.NotFound,
self.client.list_virtual_interfaces,
invalid_server_id)
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index cefbb63..49c4f32 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -18,8 +18,7 @@
from tempest.api import compute
from tempest.api.compute import base
from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.test import attr
@@ -62,18 +61,18 @@
resp, server = cls.create_test_server(wait_until='ACTIVE')
resp, cls.server = cls.client.get_server(server['id'])
- name = rand_name('image')
+ name = data_utils.rand_name('image')
resp, body = cls.client.create_image(server['id'], name)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
cls.images_client.wait_for_image_status(image_id, 'ACTIVE')
resp, cls.image = cls.images_client.get_image(image_id)
- cls.keypairname = rand_name('keypair')
+ cls.keypairname = data_utils.rand_name('keypair')
resp, keypair = \
cls.keypairs_client.create_keypair(cls.keypairname)
- name = rand_name('security')
- description = rand_name('description')
+ name = data_utils.rand_name('security')
+ description = data_utils.rand_name('description')
resp, cls.security_group = cls.security_client.create_security_group(
name, description)
@@ -191,7 +190,7 @@
# A create keypair request should fail if the tenant id does not match
# the current user
# POST keypair with other user tenant
- k_name = rand_name('keypair-')
+ k_name = data_utils.rand_name('keypair-')
self.alt_keypairs_client._set_auth()
self.saved_base_url = self.alt_keypairs_client.base_url
try:
@@ -241,8 +240,8 @@
# A create security group request should fail if the tenant id does not
# match the current user
# POST security group with other user tenant
- s_name = rand_name('security-')
- s_description = rand_name('security')
+ s_name = data_utils.rand_name('security-')
+ s_description = data_utils.rand_name('security')
self.saved_base_url = self.alt_security_client.base_url
try:
# Change the base URL to impersonate another user
diff --git a/tempest/api/compute/v3/admin/test_availability_zone.py b/tempest/api/compute/v3/admin/test_availability_zone.py
new file mode 100644
index 0000000..d6488c4
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_availability_zone.py
@@ -0,0 +1,70 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class AvailabilityZoneAdminTestJSON(base.BaseV2ComputeAdminTest):
+
+ """
+ Tests Availability Zone API List that require admin privileges
+ """
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(AvailabilityZoneAdminTestJSON, cls).setUpClass()
+ cls.client = cls.os_adm.availability_zone_client
+ cls.non_adm_client = cls.availability_zone_client
+
+ @attr(type='gate')
+ def test_get_availability_zone_list(self):
+ # List of availability zone
+ resp, availability_zone = self.client.get_availability_zone_list()
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(availability_zone) > 0)
+
+ @attr(type='gate')
+ def test_get_availability_zone_list_detail(self):
+ # List of availability zones and available services
+ resp, availability_zone = \
+ self.client.get_availability_zone_list_detail()
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(availability_zone) > 0)
+
+ @attr(type='gate')
+ def test_get_availability_zone_list_with_non_admin_user(self):
+ # List of availability zone with non-administrator user
+ resp, availability_zone = \
+ self.non_adm_client.get_availability_zone_list()
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(availability_zone) > 0)
+
+ @attr(type=['negative', 'gate'])
+ def test_get_availability_zone_list_detail_with_non_admin_user(self):
+ # List of availability zones and available services with
+ # non-administrator user
+ self.assertRaises(
+ exceptions.Unauthorized,
+ self.non_adm_client.get_availability_zone_list_detail)
+
+
+class AvailabilityZoneAdminTestXML(AvailabilityZoneAdminTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/images/test_images.py b/tempest/api/compute/v3/images/test_images.py
index ac2deb4..3aacafb 100644
--- a/tempest/api/compute/v3/images/test_images.py
+++ b/tempest/api/compute/v3/images/test_images.py
@@ -17,8 +17,7 @@
from tempest.api import compute
from tempest.api.compute import base
from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -49,7 +48,7 @@
def __create_image__(self, server_id, name, meta=None):
resp, body = self.servers_client.create_image(server_id, name, meta)
- image_id = parse_image_id(resp['location'])
+ image_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.client.delete_image, image_id)
self.client.wait_for_image_status(image_id, 'ACTIVE')
return resp, body
@@ -63,7 +62,7 @@
self.servers_client.delete_server(server['id'])
self.servers_client.wait_for_server_termination(server['id'])
# Create a new image after server is deleted
- name = rand_name('image')
+ name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
self.assertRaises(exceptions.NotFound,
self.__create_image__,
@@ -73,7 +72,7 @@
def test_create_image_from_invalid_server(self):
# An image should not be created with invalid server id
# Create a new image with invalid server id
- name = rand_name('image')
+ name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
resp = {}
resp['status'] = None
@@ -87,7 +86,7 @@
self.servers_client.wait_for_server_status(server['id'],
'SHUTOFF')
self.addCleanup(self.servers_client.delete_server, server['id'])
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
resp, image = self.create_image_from_server(server['id'],
name=snapshot_name,
wait_until='active')
@@ -96,7 +95,7 @@
@attr(type='gate')
def test_delete_queued_image(self):
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
resp, server = self.create_test_server(wait_until='ACTIVE')
self.addCleanup(self.servers_client.delete_server, server['id'])
resp, image = self.create_image_from_server(server['id'],
@@ -108,7 +107,7 @@
@attr(type=['negative', 'gate'])
def test_create_image_specify_uuid_35_characters_or_less(self):
# Return an error if Image ID passed is 35 characters or less
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 35)
self.assertRaises(exceptions.NotFound,
self.servers_client.create_image,
@@ -117,7 +116,7 @@
@attr(type=['negative', 'gate'])
def test_create_image_specify_uuid_37_characters_or_more(self):
# Return an error if Image ID passed is 37 characters or more
- snapshot_name = rand_name('test-snap-')
+ snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 37)
self.assertRaises(exceptions.NotFound,
self.servers_client.create_image,
diff --git a/tempest/api/compute/v3/servers/test_attach_interfaces.py b/tempest/api/compute/v3/servers/test_attach_interfaces.py
new file mode 100644
index 0000000..a177cea
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_attach_interfaces.py
@@ -0,0 +1,118 @@
+# 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 tempest.api.compute import base
+from tempest.test import attr
+
+import time
+
+
+class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ if not cls.config.service_available.neutron:
+ raise cls.skipException("Neutron is required")
+ super(AttachInterfacesTestJSON, cls).setUpClass()
+ cls.client = cls.os.interfaces_client
+
+ def _check_interface(self, iface, port_id=None, network_id=None,
+ fixed_ip=None):
+ self.assertIn('port_state', iface)
+ if port_id:
+ self.assertEqual(iface['port_id'], port_id)
+ if network_id:
+ self.assertEqual(iface['net_id'], network_id)
+ if fixed_ip:
+ self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
+
+ def _create_server_get_interfaces(self):
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+ resp, ifs = self.client.list_interfaces(server['id'])
+ resp, body = self.client.wait_for_interface_status(
+ server['id'], ifs[0]['port_id'], 'ACTIVE')
+ ifs[0]['port_state'] = body['port_state']
+ return server, ifs
+
+ def _test_create_interface(self, server):
+ resp, iface = self.client.create_interface(server['id'])
+ resp, iface = self.client.wait_for_interface_status(
+ server['id'], iface['port_id'], 'ACTIVE')
+ self._check_interface(iface)
+ return iface
+
+ def _test_create_interface_by_network_id(self, server, ifs):
+ network_id = ifs[0]['net_id']
+ resp, iface = self.client.create_interface(server['id'],
+ network_id=network_id)
+ resp, iface = self.client.wait_for_interface_status(
+ server['id'], iface['port_id'], 'ACTIVE')
+ self._check_interface(iface, network_id=network_id)
+ return iface
+
+ def _test_show_interface(self, server, ifs):
+ iface = ifs[0]
+ resp, _iface = self.client.show_interface(server['id'],
+ iface['port_id'])
+ self.assertEqual(iface, _iface)
+
+ def _test_delete_interface(self, server, ifs):
+ # NOTE(danms): delete not the first or last, but one in the middle
+ iface = ifs[1]
+ self.client.delete_interface(server['id'], iface['port_id'])
+ for i in range(0, 5):
+ _r, _ifs = self.client.list_interfaces(server['id'])
+ if len(ifs) != len(_ifs):
+ break
+ time.sleep(1)
+
+ self.assertEqual(len(_ifs), len(ifs) - 1)
+ for _iface in _ifs:
+ self.assertNotEqual(iface['port_id'], _iface['port_id'])
+ return _ifs
+
+ def _compare_iface_list(self, list1, list2):
+ # NOTE(danms): port_state will likely have changed, so just
+ # confirm the port_ids are the same at least
+ list1 = [x['port_id'] for x in list1]
+ list2 = [x['port_id'] for x in list2]
+
+ self.assertEqual(sorted(list1), sorted(list2))
+
+ @attr(type='gate')
+ def test_create_list_show_delete_interfaces(self):
+ server, ifs = self._create_server_get_interfaces()
+ interface_count = len(ifs)
+ self.assertTrue(interface_count > 0)
+ self._check_interface(ifs[0])
+
+ iface = self._test_create_interface(server)
+ ifs.append(iface)
+
+ iface = self._test_create_interface_by_network_id(server, ifs)
+ ifs.append(iface)
+
+ resp, _ifs = self.client.list_interfaces(server['id'])
+ self._compare_iface_list(ifs, _ifs)
+
+ self._test_show_interface(server, ifs)
+
+ _ifs = self._test_delete_interface(server, ifs)
+ self.assertEqual(len(ifs) - 1, len(_ifs))
+
+
+class AttachInterfacesTestXML(AttachInterfacesTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_instance_actions.py b/tempest/api/compute/v3/servers/test_instance_actions.py
new file mode 100644
index 0000000..ea92c9f
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_instance_actions.py
@@ -0,0 +1,69 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class InstanceActionsV3TestJSON(base.BaseV3ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(InstanceActionsV3TestJSON, cls).setUpClass()
+ cls.client = cls.servers_client
+ resp, server = cls.create_test_server(wait_until='ACTIVE')
+ cls.request_id = resp['x-compute-request-id']
+ cls.server_id = server['id']
+
+ @attr(type='gate')
+ def test_list_instance_actions(self):
+ # List actions of the provided server
+ resp, body = self.client.reboot(self.server_id, 'HARD')
+ self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+ resp, body = self.client.list_instance_actions(self.server_id)
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(body) == 2, str(body))
+ self.assertTrue(any([i for i in body if i['action'] == 'create']))
+ self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
+
+ @attr(type='gate')
+ def test_get_instance_action(self):
+ # Get the action details of the provided server
+ resp, body = self.client.get_instance_action(self.server_id,
+ self.request_id)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(self.server_id, body['instance_uuid'])
+ self.assertEqual('create', body['action'])
+
+ @attr(type=['negative', 'gate'])
+ def test_list_instance_actions_invalid_server(self):
+ # List actions of the invalid server id
+ self.assertRaises(exceptions.NotFound,
+ self.client.list_instance_actions, 'server-999')
+
+ @attr(type=['negative', 'gate'])
+ def test_get_instance_action_invalid_request(self):
+ # Get the action details of the provided server with invalid request
+ self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
+ self.server_id, '999')
+
+
+class InstanceActionsV3TestXML(InstanceActionsV3TestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_list_server_filters.py b/tempest/api/compute/v3/servers/test_list_server_filters.py
new file mode 100644
index 0000000..5f14460
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_list_server_filters.py
@@ -0,0 +1,239 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.api.compute import base
+from tempest.api import utils
+from tempest.common.utils.data_utils import rand_name
+from tempest import config
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class ListServerFiltersV3TestJSON(base.BaseV3ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(ListServerFiltersV3TestJSON, cls).setUpClass()
+ cls.client = cls.servers_client
+
+ # Check to see if the alternate image ref actually exists...
+ images_client = cls.images_client
+ resp, images = images_client.image_list()
+
+ if cls.image_ref != cls.image_ref_alt and \
+ any([image for image in images
+ if image['id'] == cls.image_ref_alt]):
+ cls.multiple_images = True
+ else:
+ cls.image_ref_alt = cls.image_ref
+
+ # Do some sanity checks here. If one of the images does
+ # not exist, fail early since the tests won't work...
+ try:
+ cls.images_client.get_image_meta(cls.image_ref)
+ except exceptions.NotFound:
+ raise RuntimeError("Image %s (image_ref) was not found!" %
+ cls.image_ref)
+
+ try:
+ cls.images_client.get_image_meta(cls.image_ref_alt)
+ except exceptions.NotFound:
+ raise RuntimeError("Image %s (image_ref_alt) was not found!" %
+ cls.image_ref_alt)
+
+ cls.s1_name = rand_name(cls.__name__ + '-instance')
+ resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
+
+ cls.s2_name = rand_name(cls.__name__ + '-instance')
+ resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
+ image_id=cls.image_ref_alt,
+ wait_until='ACTIVE')
+
+ cls.s3_name = rand_name(cls.__name__ + '-instance')
+ resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
+ flavor=cls.flavor_ref_alt,
+ wait_until='ACTIVE')
+
+ cls.fixed_network_name = cls.config.compute.fixed_network_name
+
+ @utils.skip_unless_attr('multiple_images', 'Only one image found')
+ @attr(type='gate')
+ def test_list_servers_filter_by_image(self):
+ # Filter the list of servers by image
+ params = {'image': self.image_ref}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_filter_by_flavor(self):
+ # Filter the list of servers by flavor
+ params = {'flavor': self.flavor_ref_alt}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_filter_by_server_name(self):
+ # Filter the list of servers by server name
+ params = {'name': self.s1_name}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_filter_by_server_status(self):
+ # Filter the list of servers by server status
+ params = {'status': 'active'}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_filter_by_limit(self):
+ # Verify only the expected number of servers are returned
+ params = {'limit': 1}
+ resp, servers = self.client.list_servers(params)
+ # when _interface='xml', one element for servers_links in servers
+ self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
+
+ @utils.skip_unless_attr('multiple_images', 'Only one image found')
+ @attr(type='gate')
+ def test_list_servers_detailed_filter_by_image(self):
+ # Filter the detailed list of servers by image
+ params = {'image': self.image_ref}
+ resp, body = self.client.list_servers_with_detail(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_detailed_filter_by_flavor(self):
+ # Filter the detailed list of servers by flavor
+ params = {'flavor': self.flavor_ref_alt}
+ resp, body = self.client.list_servers_with_detail(params)
+ servers = body['servers']
+
+ self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_detailed_filter_by_server_name(self):
+ # Filter the detailed list of servers by server name
+ params = {'name': self.s1_name}
+ resp, body = self.client.list_servers_with_detail(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_detailed_filter_by_server_status(self):
+ # Filter the detailed list of servers by server status
+ params = {'status': 'active'}
+ resp, body = self.client.list_servers_with_detail(params)
+ expected_servers = (self.s1['id'], self.s2['id'], self.s3['id'])
+ servers = [x for x in body['servers'] if x['id'] in expected_servers]
+
+ self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
+ self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+ self.assertEqual(['ACTIVE'] * 3, [x['status'] for x in servers])
+
+ @attr(type='gate')
+ def test_list_servers_filtered_by_name_wildcard(self):
+ # List all servers that contains '-instance' in name
+ params = {'name': '-instance'}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ # Let's take random part of name and try to search it
+ part_name = self.s1_name[6:-1]
+
+ params = {'name': part_name}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ @skip_because(bug="1170718")
+ @attr(type='gate')
+ def test_list_servers_filtered_by_ip(self):
+ # Filter servers by ip
+ # Here should be listed 1 server
+ resp, self.s1 = self.client.get_server(self.s1['id'])
+ ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
+ params = {'ip': ip}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ @skip_because(bug="1182883",
+ condition=config.TempestConfig().service_available.neutron)
+ @attr(type='gate')
+ def test_list_servers_filtered_by_ip_regex(self):
+ # Filter servers by regex ip
+ # List all servers filtered by part of ip address.
+ # Here should be listed all servers
+ resp, self.s1 = self.client.get_server(self.s1['id'])
+ ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
+ params = {'ip': ip}
+ resp, body = self.client.list_servers(params)
+ servers = body['servers']
+
+ self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+ self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
+ self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
+
+ @attr(type='gate')
+ def test_list_servers_detailed_limit_results(self):
+ # Verify only the expected number of detailed results are returned
+ params = {'limit': 1}
+ resp, servers = self.client.list_servers_with_detail(params)
+ self.assertEqual(1, len(servers['servers']))
+
+
+class ListServerFiltersV3TestXML(ListServerFiltersV3TestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
new file mode 100644
index 0000000..6225345
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -0,0 +1,222 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 datetime
+
+from tempest.api import compute
+from tempest.api.compute import base
+from tempest import clients
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ListServersNegativeV3TestJSON(base.BaseV3ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def _ensure_no_servers(cls, servers, username, tenant_name):
+ """
+ If there are servers and there is tenant isolation then a
+ skipException is raised to skip the test since it requires no servers
+ to already exist for the given user/tenant.
+ If there are servers and there is not tenant isolation then the test
+ blocks while the servers are being deleted.
+ """
+ if len(servers):
+ if not cls.config.compute.allow_tenant_isolation:
+ for srv in servers:
+ cls.client.wait_for_server_termination(srv['id'],
+ ignore_error=True)
+ else:
+ msg = ("User/tenant %(u)s/%(t)s already have "
+ "existing server instances. Skipping test." %
+ {'u': username, 't': tenant_name})
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setUpClass(cls):
+ super(ListServersNegativeV3TestJSON, cls).setUpClass()
+ cls.client = cls.servers_client
+ cls.servers = []
+
+ if compute.MULTI_USER:
+ if cls.config.compute.allow_tenant_isolation:
+ creds = cls.isolated_creds.get_alt_creds()
+ username, tenant_name, password = creds
+ cls.alt_manager = clients.Manager(username=username,
+ password=password,
+ tenant_name=tenant_name)
+ else:
+ # Use the alt_XXX credentials in the config file
+ cls.alt_manager = clients.AltManager()
+ cls.alt_client = cls.alt_manager.servers_client
+
+ # Under circumstances when there is not a tenant/user
+ # created for the test case, the test case checks
+ # to see if there are existing servers for the
+ # either the normal user/tenant or the alt user/tenant
+ # and if so, the whole test is skipped. We do this
+ # because we assume a baseline of no servers at the
+ # start of the test instead of destroying any existing
+ # servers.
+ resp, body = cls.client.list_servers()
+ cls._ensure_no_servers(body['servers'],
+ cls.os.username,
+ cls.os.tenant_name)
+
+ resp, body = cls.alt_client.list_servers()
+ cls._ensure_no_servers(body['servers'],
+ cls.alt_manager.username,
+ cls.alt_manager.tenant_name)
+
+ # The following servers are created for use
+ # by the test methods in this class. These
+ # servers are cleaned up automatically in the
+ # tearDownClass method of the super-class.
+ cls.existing_fixtures = []
+ cls.deleted_fixtures = []
+ cls.start_time = datetime.datetime.utcnow()
+ for x in xrange(2):
+ resp, srv = cls.create_test_server()
+ cls.existing_fixtures.append(srv)
+
+ resp, srv = cls.create_test_server()
+ cls.client.delete_server(srv['id'])
+ # We ignore errors on termination because the server may
+ # be put into ERROR status on a quick spawn, then delete,
+ # as the compute node expects the instance local status
+ # to be spawning, not deleted. See LP Bug#1061167
+ cls.client.wait_for_server_termination(srv['id'],
+ ignore_error=True)
+ cls.deleted_fixtures.append(srv)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_with_a_deleted_server(self):
+ # Verify deleted servers do not show by default in list servers
+ # List servers and verify server not returned
+ resp, body = self.client.list_servers()
+ servers = body['servers']
+ deleted_ids = [s['id'] for s in self.deleted_fixtures]
+ actual = [srv for srv in servers
+ if srv['id'] in deleted_ids]
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], actual)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_non_existing_image(self):
+ # Listing servers for a non existing image returns empty list
+ non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
+ resp, body = self.client.list_servers(dict(image=non_existing_image))
+ servers = body['servers']
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], servers)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_non_existing_flavor(self):
+ # Listing servers by non existing flavor returns empty list
+ non_existing_flavor = 1234
+ resp, body = self.client.list_servers(dict(flavor=non_existing_flavor))
+ servers = body['servers']
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], servers)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_non_existing_server_name(self):
+ # Listing servers for a non existent server name returns empty list
+ non_existing_name = 'junk_server_1234'
+ resp, body = self.client.list_servers(dict(name=non_existing_name))
+ servers = body['servers']
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], servers)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_status_non_existing(self):
+ # Return an empty list when invalid status is specified
+ non_existing_status = 'BALONEY'
+ resp, body = self.client.list_servers(dict(status=non_existing_status))
+ servers = body['servers']
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], servers)
+
+ @attr(type='gate')
+ def test_list_servers_by_limits(self):
+ # List servers by specifying limits
+ resp, body = self.client.list_servers({'limit': 1})
+ self.assertEqual('200', resp['status'])
+ # when _interface='xml', one element for servers_links in servers
+ self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_limits_greater_than_actual_count(self):
+ # List servers by specifying a greater value for limit
+ resp, body = self.client.list_servers({'limit': 100})
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(len(self.existing_fixtures), len(body['servers']))
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_limits_pass_string(self):
+ # Return an error if a string value is passed for limit
+ self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ {'limit': 'testing'})
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_limits_pass_negative_value(self):
+ # Return an error if a negative value for limit is passed
+ self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ {'limit': -1})
+
+ @attr(type='gate')
+ def test_list_servers_by_changes_since(self):
+ # Servers are listed by specifying changes-since date
+ changes_since = {'changes_since': self.start_time.isoformat()}
+ resp, body = self.client.list_servers(changes_since)
+ self.assertEqual('200', resp['status'])
+ # changes-since returns all instances, including deleted.
+ num_expected = (len(self.existing_fixtures) +
+ len(self.deleted_fixtures))
+ self.assertEqual(num_expected, len(body['servers']),
+ "Number of servers %d is wrong in %s" %
+ (num_expected, body['servers']))
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_changes_since_invalid_date(self):
+ # Return an error when invalid date format is passed
+ self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ {'changes_since': '2011/01/01'})
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_by_changes_since_future_date(self):
+ # Return an empty list when a date in the future is passed
+ changes_since = {'changes_since': '2051-01-01T12:34:00Z'}
+ resp, body = self.client.list_servers(changes_since)
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(0, len(body['servers']))
+
+ @attr(type=['negative', 'gate'])
+ def test_list_servers_detail_server_is_deleted(self):
+ # Server details are not listed for a deleted server
+ deleted_ids = [s['id'] for s in self.deleted_fixtures]
+ resp, body = self.client.list_servers_with_detail()
+ servers = body['servers']
+ actual = [srv for srv in servers
+ if srv['id'] in deleted_ids]
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], actual)
+
+
+class ListServersNegativeV3TestXML(ListServersNegativeV3TestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
index 8ac1f12..92b9e30 100644
--- a/tempest/api/compute/v3/servers/test_server_actions.py
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -22,7 +22,7 @@
from tempest.api import compute
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
import tempest.config
from tempest import exceptions
@@ -112,7 +112,7 @@
def test_rebuild_server(self):
# The server should be rebuilt using the provided image and data
meta = {'rebuild': 'server'}
- new_name = rand_name('server')
+ new_name = data_utils.rand_name('server')
file_contents = 'Test server rebuild.'
personality = [{'path': 'rebuild.txt',
'contents': base64.b64encode(file_contents)}]
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
new file mode 100644
index 0000000..7ca8a52
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServerAddressesTest(base.BaseV2ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(ServerAddressesTest, cls).setUpClass()
+ cls.client = cls.servers_client
+
+ resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+ @attr(type=['negative', 'gate'])
+ def test_list_server_addresses_invalid_server_id(self):
+ # List addresses request should fail if server id not in system
+ self.assertRaises(exceptions.NotFound, self.client.list_addresses,
+ '999')
+
+ @attr(type=['negative', 'gate'])
+ def test_list_server_addresses_by_network_neg(self):
+ # List addresses by network should fail if network name not valid
+ self.assertRaises(exceptions.NotFound,
+ self.client.list_addresses_by_network,
+ self.server['id'], 'invalid')
+
+ @attr(type='smoke')
+ def test_list_server_addresses(self):
+ # All public and private addresses for
+ # a server should be returned
+
+ resp, addresses = self.client.list_addresses(self.server['id'])
+ self.assertEqual('200', resp['status'])
+
+ # We do not know the exact network configuration, but an instance
+ # should at least have a single public or private address
+ self.assertTrue(len(addresses) >= 1)
+ for network_name, network_addresses in addresses.iteritems():
+ self.assertTrue(len(network_addresses) >= 1)
+ for address in network_addresses:
+ self.assertTrue(address['addr'])
+ self.assertTrue(address['version'])
+
+ @attr(type='smoke')
+ def test_list_server_addresses_by_network(self):
+ # Providing a network type should filter
+ # the addresses return by that type
+
+ resp, addresses = self.client.list_addresses(self.server['id'])
+
+ # Once again we don't know the environment's exact network config,
+ # but the response for each individual network should be the same
+ # as the partial result of the full address list
+ id = self.server['id']
+ for addr_type in addresses:
+ resp, addr = self.client.list_addresses_by_network(id, addr_type)
+ self.assertEqual('200', resp['status'])
+
+ addr = addr[addr_type]
+ for address in addresses[addr_type]:
+ self.assertTrue(any([a for a in addr if a == address]))
+
+
+class ServerAddressesTestXML(ServerAddressesTest):
+ _interface = 'xml'
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index 192d81e..ae6996d 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -36,7 +36,7 @@
def test_volume_create_get_delete(self):
# CREATE, GET, DELETE Volume
volume = None
- v_name = rand_name('Volume-%s-') % self._interface
+ v_name = data_utils.rand_name('Volume-%s-') % self._interface
metadata = {'Type': 'work'}
# Create volume
resp, volume = self.client.create_volume(size=1,
@@ -73,7 +73,7 @@
@attr(type='gate')
def test_volume_get_metadata_none(self):
# CREATE, GET empty metadata dict
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
# Create volume
resp, volume = self.client.create_volume(size=1,
display_name=v_name,
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index b4e00f9..f214641 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -43,7 +43,7 @@
cls.volume_list = []
cls.volume_id_list = []
for i in range(3):
- v_name = rand_name('volume-%s')
+ v_name = data_utils.rand_name('volume-%s')
metadata = {'Type': 'work'}
v_name += cls._interface
try:
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index 543cd91..8205d15 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -16,8 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -28,7 +27,8 @@
def setUpClass(cls):
super(RolesTestJSON, cls).setUpClass()
for _ in xrange(5):
- resp, role = cls.client.create_role(rand_name('role-'))
+ role_name = data_utils.rand_name(name='role-')
+ resp, role = cls.client.create_role(role_name)
cls.data.roles.append(role)
def _get_role_params(self):
@@ -55,23 +55,9 @@
self.assertEqual(len(found), len(self.data.roles))
@attr(type='gate')
- def test_list_roles_by_unauthorized_user(self):
- # Non-administrator user should not be able to list roles
- self.assertRaises(exceptions.Unauthorized,
- self.non_admin_client.list_roles)
-
- @attr(type='gate')
- def test_list_roles_request_without_token(self):
- # Request to list roles without a valid token should fail
- token = self.client.get_auth()
- self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
- self.client.clear_auth()
-
- @attr(type='gate')
def test_role_create_delete(self):
# Role should be created, verified, and deleted
- role_name = rand_name('role-test-')
+ role_name = data_utils.rand_name(name='role-test-')
resp, body = self.client.create_role(role_name)
self.assertIn('status', resp)
self.assertTrue(resp['status'].startswith('2'))
@@ -90,23 +76,6 @@
self.assertFalse(any(found))
@attr(type='gate')
- def test_role_create_blank_name(self):
- # Should not be able to create a role with a blank name
- self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
-
- @attr(type='gate')
- def test_role_create_duplicate(self):
- # Role names should be unique
- role_name = rand_name('role-dup-')
- resp, body = self.client.create_role(role_name)
- role1_id = body.get('id')
- self.assertIn('status', resp)
- self.assertTrue(resp['status'].startswith('2'))
- self.addCleanup(self.client.delete_role, role1_id)
- self.assertRaises(exceptions.Conflict, self.client.create_role,
- role_name)
-
- @attr(type='gate')
def test_assign_user_role(self):
# Assign a role to a user on a tenant
(user, tenant, role) = self._get_role_params()
@@ -115,55 +84,6 @@
self.assert_role_in_role_list(role, roles)
@attr(type='gate')
- def test_assign_user_role_by_unauthorized_user(self):
- # Non-administrator user should not be authorized to
- # assign a role to user
- (user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.Unauthorized,
- self.non_admin_client.assign_user_role,
- tenant['id'], user['id'], role['id'])
-
- @attr(type='gate')
- def test_assign_user_role_request_without_token(self):
- # Request to assign a role to a user without a valid token
- (user, tenant, role) = self._get_role_params()
- token = self.client.get_auth()
- self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized,
- self.client.assign_user_role, tenant['id'],
- user['id'], role['id'])
- self.client.clear_auth()
-
- @attr(type='gate')
- def test_assign_user_role_for_non_existent_user(self):
- # Attempt to assign a role to a non existent user should fail
- (user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
- tenant['id'], 'junk-user-id-999', role['id'])
-
- @attr(type='gate')
- def test_assign_user_role_for_non_existent_role(self):
- # Attempt to assign a non existent role to user should fail
- (user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
- tenant['id'], user['id'], 'junk-role-id-12345')
-
- @attr(type='gate')
- def test_assign_user_role_for_non_existent_tenant(self):
- # Attempt to assign a role on a non existent tenant should fail
- (user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
- 'junk-tenant-1234', user['id'], role['id'])
-
- @attr(type='gate')
- def test_assign_duplicate_user_role(self):
- # Duplicate user role should not get assigned
- (user, tenant, role) = self._get_role_params()
- self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
- tenant['id'], user['id'], role['id'])
-
- @attr(type='gate')
def test_remove_user_role(self):
# Remove a role assigned to a user on a tenant
(user, tenant, role) = self._get_role_params()
@@ -174,62 +94,6 @@
self.assertEqual(resp['status'], '204')
@attr(type='gate')
- def test_remove_user_role_by_unauthorized_user(self):
- # Non-administrator user should not be authorized to
- # remove a user's role
- (user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'],
- role['id'])
- self.assertRaises(exceptions.Unauthorized,
- self.non_admin_client.remove_user_role,
- tenant['id'], user['id'], role['id'])
-
- @attr(type='gate')
- def test_remove_user_role_request_without_token(self):
- # Request to remove a user's role without a valid token
- (user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'],
- role['id'])
- token = self.client.get_auth()
- self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized,
- self.client.remove_user_role, tenant['id'],
- user['id'], role['id'])
- self.client.clear_auth()
-
- @attr(type='gate')
- def test_remove_user_role_non_existant_user(self):
- # Attempt to remove a role from a non existent user should fail
- (user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'],
- role['id'])
- self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
- tenant['id'], 'junk-user-id-123', role['id'])
-
- @attr(type='gate')
- def test_remove_user_role_non_existant_role(self):
- # Attempt to delete a non existent role from a user should fail
- (user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'],
- role['id'])
- self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
- tenant['id'], user['id'], 'junk-user-role-123')
-
- @attr(type='gate')
- def test_remove_user_role_non_existant_tenant(self):
- # Attempt to remove a role from a non existent tenant should fail
- (user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'],
- role['id'])
- self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
- 'junk-tenant-id-123', user['id'], role['id'])
-
- @attr(type='gate')
def test_list_user_roles(self):
# List roles assigned to a user on tenant
(user, tenant, role) = self._get_role_params()
@@ -237,36 +101,6 @@
resp, roles = self.client.list_user_roles(tenant['id'], user['id'])
self.assert_role_in_role_list(role, roles)
- @attr(type='gate')
- def test_list_user_roles_by_unauthorized_user(self):
- # Non-administrator user should not be authorized to list
- # a user's roles
- (user, tenant, role) = self._get_role_params()
- self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- self.assertRaises(exceptions.Unauthorized,
- self.non_admin_client.list_user_roles, tenant['id'],
- user['id'])
-
- @attr(type='gate')
- def test_list_user_roles_request_without_token(self):
- # Request to list user's roles without a valid token should fail
- (user, tenant, role) = self._get_role_params()
- token = self.client.get_auth()
- self.client.delete_token(token)
- try:
- self.assertRaises(exceptions.Unauthorized,
- self.client.list_user_roles, tenant['id'],
- user['id'])
- finally:
- self.client.clear_auth()
-
- @attr(type='gate')
- def test_list_user_roles_for_non_existent_user(self):
- # Attempt to list roles of a non existent user should fail
- (user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.NotFound, self.client.list_user_roles,
- tenant['id'], 'junk-role-aabbcc11')
-
class RolesTestXML(RolesTestJSON):
_interface = 'xml'
diff --git a/tempest/api/identity/admin/test_roles_negative.py b/tempest/api/identity/admin/test_roles_negative.py
new file mode 100644
index 0000000..83d1d4d
--- /dev/null
+++ b/tempest/api/identity/admin/test_roles_negative.py
@@ -0,0 +1,262 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import uuid
+
+from tempest.api.identity import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class RolesNegativeTestJSON(base.BaseIdentityAdminTest):
+ _interface = 'json'
+
+ def _get_role_params(self):
+ self.data.setup_test_user()
+ self.data.setup_test_role()
+ user = self.get_user_by_name(self.data.test_user)
+ tenant = self.get_tenant_by_name(self.data.test_tenant)
+ role = self.get_role_by_name(self.data.test_role)
+ return (user, tenant, role)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_roles_by_unauthorized_user(self):
+ # Non-administrator user should not be able to list roles
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.list_roles)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_roles_request_without_token(self):
+ # Request to list roles without a valid token should fail
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_role_create_blank_name(self):
+ # Should not be able to create a role with a blank name
+ self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
+
+ @attr(type=['negative', 'gate'])
+ def test_create_role_by_unauthorized_user(self):
+ # Non-administrator user should not be able to create role
+ role_name = data_utils.rand_name(name='role-')
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.create_role, role_name)
+
+ @attr(type=['negative', 'gate'])
+ def test_create_role_request_without_token(self):
+ # Request to create role without a valid token should fail
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ role_name = data_utils.rand_name(name='role-')
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.create_role, role_name)
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_role_create_duplicate(self):
+ # Role names should be unique
+ role_name = data_utils.rand_name(name='role-dup-')
+ resp, body = self.client.create_role(role_name)
+ role1_id = body.get('id')
+ self.assertIn('status', resp)
+ self.assertTrue(resp['status'].startswith('2'))
+ self.addCleanup(self.client.delete_role, role1_id)
+ self.assertRaises(exceptions.Conflict, self.client.create_role,
+ role_name)
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_role_by_unauthorized_user(self):
+ # Non-administrator user should not be able to delete role
+ role_name = data_utils.rand_name(name='role-')
+ resp, body = self.client.create_role(role_name)
+ self.assertEqual(200, resp.status)
+ self.data.roles.append(body)
+ role_id = body.get('id')
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.delete_role, role_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_role_request_without_token(self):
+ # Request to delete role without a valid token should fail
+ role_name = data_utils.rand_name(name='role-')
+ resp, body = self.client.create_role(role_name)
+ self.assertEqual(200, resp.status)
+ self.data.roles.append(body)
+ role_id = body.get('id')
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.delete_role,
+ role_id)
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_role_non_existent(self):
+ # Attempt to delete a non existent role should fail
+ non_existent_role = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.delete_role,
+ non_existent_role)
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_user_role_by_unauthorized_user(self):
+ # Non-administrator user should not be authorized to
+ # assign a role to user
+ (user, tenant, role) = self._get_role_params()
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.assign_user_role,
+ tenant['id'], user['id'], role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_user_role_request_without_token(self):
+ # Request to assign a role to a user without a valid token
+ (user, tenant, role) = self._get_role_params()
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.assign_user_role, tenant['id'],
+ user['id'], role['id'])
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_user_role_for_non_existent_user(self):
+ # Attempt to assign a role to a non existent user should fail
+ (user, tenant, role) = self._get_role_params()
+ non_existent_user = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+ tenant['id'], non_existent_user, role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_user_role_for_non_existent_role(self):
+ # Attempt to assign a non existent role to user should fail
+ (user, tenant, role) = self._get_role_params()
+ non_existent_role = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+ tenant['id'], user['id'], non_existent_role)
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_user_role_for_non_existent_tenant(self):
+ # Attempt to assign a role on a non existent tenant should fail
+ (user, tenant, role) = self._get_role_params()
+ non_existent_tenant = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+ non_existent_tenant, user['id'], role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_assign_duplicate_user_role(self):
+ # Duplicate user role should not get assigned
+ (user, tenant, role) = self._get_role_params()
+ self.client.assign_user_role(tenant['id'], user['id'], role['id'])
+ self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
+ tenant['id'], user['id'], role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_remove_user_role_by_unauthorized_user(self):
+ # Non-administrator user should not be authorized to
+ # remove a user's role
+ (user, tenant, role) = self._get_role_params()
+ resp, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'],
+ role['id'])
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.remove_user_role,
+ tenant['id'], user['id'], role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_remove_user_role_request_without_token(self):
+ # Request to remove a user's role without a valid token
+ (user, tenant, role) = self._get_role_params()
+ resp, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'],
+ role['id'])
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.remove_user_role, tenant['id'],
+ user['id'], role['id'])
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_remove_user_role_non_existant_user(self):
+ # Attempt to remove a role from a non existent user should fail
+ (user, tenant, role) = self._get_role_params()
+ resp, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'],
+ role['id'])
+ non_existant_user = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+ tenant['id'], non_existant_user, role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_remove_user_role_non_existant_role(self):
+ # Attempt to delete a non existent role from a user should fail
+ (user, tenant, role) = self._get_role_params()
+ resp, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'],
+ role['id'])
+ non_existant_role = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+ tenant['id'], user['id'], non_existant_role)
+
+ @attr(type=['negative', 'gate'])
+ def test_remove_user_role_non_existant_tenant(self):
+ # Attempt to remove a role from a non existent tenant should fail
+ (user, tenant, role) = self._get_role_params()
+ resp, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'],
+ role['id'])
+ non_existant_tenant = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+ non_existant_tenant, user['id'], role['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_list_user_roles_by_unauthorized_user(self):
+ # Non-administrator user should not be authorized to list
+ # a user's roles
+ (user, tenant, role) = self._get_role_params()
+ self.client.assign_user_role(tenant['id'], user['id'], role['id'])
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.list_user_roles, tenant['id'],
+ user['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_list_user_roles_request_without_token(self):
+ # Request to list user's roles without a valid token should fail
+ (user, tenant, role) = self._get_role_params()
+ token = self.client.get_auth()
+ self.client.delete_token(token)
+ try:
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.list_user_roles, tenant['id'],
+ user['id'])
+ finally:
+ self.client.clear_auth()
+
+ @attr(type=['negative', 'gate'])
+ def test_list_user_roles_for_non_existent_user(self):
+ # Attempt to list roles of a non existent user should fail
+ (user, tenant, role) = self._get_role_params()
+ non_existent_user = str(uuid.uuid4().hex)
+ self.assertRaises(exceptions.NotFound, self.client.list_user_roles,
+ tenant['id'], non_existent_user)
+
+
+class RolesTestXML(RolesNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index df6c317..7fe5171 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -17,7 +17,7 @@
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -30,9 +30,9 @@
# GET Service
try:
# Creating a Service
- name = rand_name('service-')
- type = rand_name('type--')
- description = rand_name('description-')
+ name = data_utils.rand_name('service-')
+ type = data_utils.rand_name('type--')
+ description = data_utils.rand_name('description-')
resp, service_data = self.client.create_service(
name, type, description=description)
self.assertTrue(resp['status'].startswith('2'))
@@ -72,9 +72,9 @@
# Create, List, Verify and Delete Services
services = []
for _ in xrange(3):
- name = rand_name('service-')
- type = rand_name('type--')
- description = rand_name('description-')
+ name = data_utils.rand_name('service-')
+ type = data_utils.rand_name('type--')
+ description = data_utils.rand_name('description-')
resp, service = self.client.create_service(
name, type, description=description)
services.append(service)
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index 906fad3..5d5a814 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -31,8 +31,6 @@
cls.alt_user = data_utils.rand_name('test_user_')
cls.alt_password = data_utils.rand_name('pass_')
cls.alt_email = cls.alt_user + '@testmail.tm'
- cls.alt_tenant = data_utils.rand_name('test_tenant_')
- cls.alt_description = data_utils.rand_name('desc_')
@attr(type='smoke')
def test_create_user(self):
diff --git a/tempest/api/identity/admin/test_users_negative.py b/tempest/api/identity/admin/test_users_negative.py
index b29d155..3163c16 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/test_users_negative.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
import uuid
@@ -28,11 +28,9 @@
@classmethod
def setUpClass(cls):
super(UsersNegativeTestJSON, cls).setUpClass()
- cls.alt_user = rand_name('test_user_')
- cls.alt_password = rand_name('pass_')
+ cls.alt_user = data_utils.rand_name('test_user_')
+ cls.alt_password = data_utils.rand_name('pass_')
cls.alt_email = cls.alt_user + '@testmail.tm'
- cls.alt_tenant = rand_name('test_tenant_')
- cls.alt_description = rand_name('desc_')
@attr(type=['negative', 'gate'])
def test_create_user_by_unauthorized_user(self):
@@ -93,7 +91,7 @@
def test_create_user_with_enabled_non_bool(self):
# Attempt to create a user with valid enabled para should fail
self.data.setup_test_tenant()
- name = rand_name('test_user_')
+ name = data_utils.rand_name('test_user_')
self.assertRaises(exceptions.BadRequest, self.client.create_user,
name, self.alt_password,
self.data.tenant['id'],
@@ -102,7 +100,7 @@
@attr(type=['negative', 'gate'])
def test_update_user_for_non_existant_user(self):
# Attempt to update a user non-existent user should fail
- user_name = rand_name('user-')
+ user_name = data_utils.rand_name('user-')
non_existent_id = str(uuid.uuid4())
self.assertRaises(exceptions.NotFound, self.client.update_user,
non_existent_id, name=user_name)
@@ -222,9 +220,9 @@
# users for a non-existent tenant
# Assign invalid tenant ids
invalid_id = list()
- invalid_id.append(rand_name('999'))
+ invalid_id.append(data_utils.rand_name('999'))
invalid_id.append('alpha')
- invalid_id.append(rand_name("dddd@#%%^$"))
+ invalid_id.append(data_utils.rand_name("dddd@#%%^$"))
invalid_id.append('!@#()$%^&*?<>{}[]')
# List the users with invalid tenant id
for invalid in invalid_id:
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index cda5863..0b494f3 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -29,13 +29,14 @@
cls.projects = list()
cls.creds_list = [['project_id', 'user_id', 'id'],
['access', 'secret']]
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
for i in range(2):
resp, cls.project = cls.v3_client.create_project(
- rand_name('project-'), description=rand_name('project-desc-'))
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'))
assert resp['status'] == '201', "Expected %s" % resp['status']
cls.projects.append(cls.project['id'])
@@ -59,7 +60,8 @@
@attr(type='smoke')
def test_credentials_create_get_update_delete(self):
- keys = [rand_name('Access-'), rand_name('Secret-')]
+ keys = [data_utils.rand_name('Access-'),
+ data_utils.rand_name('Secret-')]
resp, cred = self.creds_client.create_credential(
keys[0], keys[1], self.user_body['id'],
self.projects[0])
@@ -70,7 +72,8 @@
for value2 in self.creds_list[1]:
self.assertIn(value2, cred['blob'])
- new_keys = [rand_name('NewAccess-'), rand_name('NewSecret-')]
+ new_keys = [data_utils.rand_name('NewAccess-'),
+ data_utils.rand_name('NewSecret-')]
resp, update_body = self.creds_client.update_credential(
cred['id'], access_key=new_keys[0], secret_key=new_keys[1],
project_id=self.projects[1])
@@ -97,7 +100,8 @@
for i in range(2):
resp, cred = self.creds_client.create_credential(
- rand_name('Access-'), rand_name('Secret-'),
+ data_utils.rand_name('Access-'),
+ data_utils.rand_name('Secret-'),
self.user_body['id'], self.projects[0])
self.assertEqual(resp['status'], '201')
created_cred_ids.append(cred['id'])
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 2fbef77..ed776cd 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -17,7 +17,7 @@
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -38,7 +38,8 @@
fetched_ids = list()
for _ in range(3):
_, domain = self.v3_client.create_domain(
- rand_name('domain-'), description=rand_name('domain-desc-'))
+ data_utils.rand_name('domain-'),
+ description=data_utils.rand_name('domain-desc-'))
# Delete the domain at the end of this method
self.addCleanup(self._delete_domain, domain['id'])
domain_ids.append(domain['id'])
@@ -52,8 +53,8 @@
@attr(type='smoke')
def test_create_update_delete_domain(self):
- d_name = rand_name('domain-')
- d_desc = rand_name('domain-desc-')
+ d_name = data_utils.rand_name('domain-')
+ d_desc = data_utils.rand_name('domain-desc-')
resp_1, domain = self.v3_client.create_domain(
d_name, description=d_desc)
self.assertEqual(resp_1['status'], '201')
@@ -70,8 +71,8 @@
self.assertEqual(True, domain['enabled'])
else:
self.assertEqual('true', str(domain['enabled']).lower())
- new_desc = rand_name('new-desc-')
- new_name = rand_name('new-name-')
+ new_desc = data_utils.rand_name('new-desc-')
+ new_name = data_utils.rand_name('new-name-')
resp_2, updated_domain = self.v3_client.update_domain(
domain['id'], name=new_name, description=new_desc)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 02a6f5b..d4d2109 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -29,9 +29,9 @@
cls.identity_client = cls.client
cls.client = cls.endpoints_client
cls.service_ids = list()
- s_name = rand_name('service-')
- s_type = rand_name('type--')
- s_description = rand_name('description-')
+ s_name = data_utils.rand_name('service-')
+ s_type = data_utils.rand_name('type--')
+ s_description = data_utils.rand_name('description-')
resp, cls.service_data =\
cls.identity_client.create_service(s_name, s_type,
description=s_description)
@@ -40,8 +40,8 @@
# Create endpoints so as to use for LIST and GET test cases
cls.setup_endpoints = list()
for i in range(2):
- region = rand_name('region')
- url = rand_name('url')
+ region = data_utils.rand_name('region')
+ url = data_utils.rand_name('url')
interface = 'public'
resp, endpoint = cls.client.create_endpoint(
cls.service_id, interface, url, region=region, enabled=True)
@@ -69,8 +69,8 @@
@attr(type='gate')
def test_create_list_delete_endpoint(self):
- region = rand_name('region')
- url = rand_name('url')
+ region = data_utils.rand_name('region')
+ url = data_utils.rand_name('url')
interface = 'public'
resp, endpoint =\
self.client.create_endpoint(self.service_id, interface, url,
@@ -97,24 +97,24 @@
def test_update_endpoint(self):
# Creating an endpoint so as to check update endpoint
# with new values
- region1 = rand_name('region')
- url1 = rand_name('url')
+ region1 = data_utils.rand_name('region')
+ url1 = data_utils.rand_name('url')
interface1 = 'public'
resp, endpoint_for_update =\
self.client.create_endpoint(self.service_id, interface1,
url1, region=region1,
enabled=True)
# Creating service so as update endpoint with new service ID
- s_name = rand_name('service-')
- s_type = rand_name('type--')
- s_description = rand_name('description-')
+ s_name = data_utils.rand_name('service-')
+ s_type = data_utils.rand_name('type--')
+ s_description = data_utils.rand_name('description-')
resp, self.service2 =\
self.identity_client.create_service(s_name, s_type,
description=s_description)
self.service_ids.append(self.service2['id'])
# Updating endpoint with new values
- region2 = rand_name('region')
- url2 = rand_name('url')
+ region2 = data_utils.rand_name('region')
+ url2 = data_utils.rand_name('url')
interface2 = 'internal'
resp, endpoint = \
self.client.update_endpoint(endpoint_for_update['id'],
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 737a0e0..48f8fcd 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -33,8 +33,8 @@
policy_ids = list()
fetched_ids = list()
for _ in range(3):
- blob = rand_name('BlobName-')
- policy_type = rand_name('PolicyType-')
+ blob = data_utils.rand_name('BlobName-')
+ policy_type = data_utils.rand_name('PolicyType-')
resp, policy = self.policy_client.create_policy(blob,
policy_type)
# Delete the Policy at the end of this method
@@ -51,8 +51,8 @@
@attr(type='smoke')
def test_create_update_delete_policy(self):
# Test to update policy
- blob = rand_name('BlobName-')
- policy_type = rand_name('PolicyType-')
+ blob = data_utils.rand_name('BlobName-')
+ policy_type = data_utils.rand_name('PolicyType-')
resp, policy = self.policy_client.create_policy(blob, policy_type)
self.addCleanup(self._delete_policy, policy['id'])
self.assertIn('id', policy)
@@ -64,7 +64,7 @@
resp, fetched_policy = self.policy_client.get_policy(policy['id'])
self.assertEqual(resp['status'], '200')
# Update policy
- update_type = rand_name('UpdatedPolicyType-')
+ update_type = data_utils.rand_name('UpdatedPolicyType-')
resp, data = self.policy_client.update_policy(
policy['id'], type=update_type)
self.assertIn('type', data)
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index ef9814a..cbfcd04 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -35,7 +35,7 @@
# Create several projects and delete them
for _ in xrange(3):
resp, project = self.v3_client.create_project(
- rand_name('project-new'))
+ data_utils.rand_name('project-new'))
self.addCleanup(self._delete_project, project['id'])
resp, list_projects = self.v3_client.list_projects()
@@ -47,8 +47,8 @@
@attr(type='gate')
def test_project_create_with_description(self):
# Create project with a description
- project_name = rand_name('project-')
- project_desc = rand_name('desc-')
+ project_name = data_utils.rand_name('project-')
+ project_desc = data_utils.rand_name('desc-')
resp, project = self.v3_client.create_project(
project_name, description=project_desc)
self.v3data.projects.append(project)
@@ -66,7 +66,7 @@
@attr(type='gate')
def test_project_create_enabled(self):
# Create a project that is enabled
- project_name = rand_name('project-')
+ project_name = data_utils.rand_name('project-')
resp, project = self.v3_client.create_project(
project_name, enabled=True)
self.v3data.projects.append(project)
@@ -82,7 +82,7 @@
@attr(type='gate')
def test_project_create_not_enabled(self):
# Create a project that is not enabled
- project_name = rand_name('project-')
+ project_name = data_utils.rand_name('project-')
resp, project = self.v3_client.create_project(
project_name, enabled=False)
self.v3data.projects.append(project)
@@ -99,13 +99,13 @@
@attr(type='gate')
def test_project_update_name(self):
# Update name attribute of a project
- p_name1 = rand_name('project-')
+ p_name1 = data_utils.rand_name('project-')
resp, project = self.v3_client.create_project(p_name1)
self.v3data.projects.append(project)
resp1_name = project['name']
- p_name2 = rand_name('project2-')
+ p_name2 = data_utils.rand_name('project2-')
resp, body = self.v3_client.update_project(project['id'], name=p_name2)
st2 = resp['status']
resp2_name = body['name']
@@ -122,14 +122,14 @@
@attr(type='gate')
def test_project_update_desc(self):
# Update description attribute of a project
- p_name = rand_name('project-')
- p_desc = rand_name('desc-')
+ p_name = data_utils.rand_name('project-')
+ p_desc = data_utils.rand_name('desc-')
resp, project = self.v3_client.create_project(
p_name, description=p_desc)
self.v3data.projects.append(project)
resp1_desc = project['description']
- p_desc2 = rand_name('desc2-')
+ p_desc2 = data_utils.rand_name('desc2-')
resp, body = self.v3_client.update_project(
project['id'], description=p_desc2)
st2 = resp['status']
@@ -147,7 +147,7 @@
@attr(type='gate')
def test_project_update_enable(self):
# Update the enabled attribute of a project
- p_name = rand_name('project-')
+ p_name = data_utils.rand_name('project-')
p_en = False
resp, project = self.v3_client.create_project(p_name, enabled=p_en)
self.v3data.projects.append(project)
@@ -173,15 +173,15 @@
def test_associate_user_to_project(self):
#Associate a user to a project
#Create a Project
- p_name = rand_name('project-')
+ p_name = data_utils.rand_name('project-')
resp, project = self.v3_client.create_project(p_name)
self.v3data.projects.append(project)
#Create a User
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
resp, user = self.v3_client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, project_id=project['id'])
@@ -207,7 +207,7 @@
@attr(type=['negative', 'gate'])
def test_project_create_duplicate(self):
# Project names should be unique
- project_name = rand_name('project-dup-')
+ project_name = data_utils.rand_name('project-dup-')
resp, project = self.v3_client.create_project(project_name)
self.v3data.projects.append(project)
@@ -217,7 +217,7 @@
@attr(type=['negative', 'gate'])
def test_create_project_by_unauthorized_user(self):
# Non-admin user should not be authorized to create a project
- project_name = rand_name('project-')
+ project_name = data_utils.rand_name('project-')
self.assertRaises(
exceptions.Unauthorized, self.v3_non_admin_client.create_project,
project_name)
@@ -238,7 +238,7 @@
@attr(type=['negative', 'gate'])
def test_project_delete_by_unauthorized_user(self):
# Non-admin user should not be able to delete a project
- project_name = rand_name('project-')
+ project_name = data_utils.rand_name('project-')
resp, project = self.v3_client.create_project(project_name)
self.v3data.projects.append(project)
self.assertRaises(
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index a238c46..a6a2bd7 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -27,23 +27,26 @@
def setUpClass(cls):
super(RolesV3TestJSON, cls).setUpClass()
cls.fetched_role_ids = list()
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
resp = [None] * 5
resp[0], cls.project = cls.v3_client.create_project(
- rand_name('project-'), description=rand_name('project-desc-'))
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'))
resp[1], cls.domain = cls.v3_client.create_domain(
- rand_name('domain-'), description=rand_name('domain-desc-'))
+ data_utils.rand_name('domain-'),
+ description=data_utils.rand_name('domain-desc-'))
resp[2], cls.group_body = cls.v3_client.create_group(
- rand_name('Group-'), project_id=cls.project['id'],
+ data_utils.rand_name('Group-'), project_id=cls.project['id'],
domain_id=cls.domain['id'])
resp[3], cls.user_body = cls.v3_client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, project_id=cls.project['id'],
domain_id=cls.domain['id'])
- resp[4], cls.role = cls.v3_client.create_role(rand_name('Role-'))
+ resp[4], cls.role = cls.v3_client.create_role(
+ data_utils.rand_name('Role-'))
for r in resp:
assert r['status'] == '201', "Expected: %s" % r['status']
@@ -69,14 +72,14 @@
@attr(type='smoke')
def test_role_create_update_get(self):
- r_name = rand_name('Role-')
+ r_name = data_utils.rand_name('Role-')
resp, role = self.v3_client.create_role(r_name)
self.addCleanup(self.v3_client.delete_role, role['id'])
self.assertEqual(resp['status'], '201')
self.assertIn('name', role)
self.assertEqual(role['name'], r_name)
- new_name = rand_name('NewRole-')
+ new_name = data_utils.rand_name('NewRole-')
resp, updated_role = self.v3_client.update_role(new_name, role['id'])
self.assertEqual(resp['status'], '200')
self.assertIn('name', updated_role)
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index bfa0d84..1751638 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -17,7 +17,7 @@
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -27,9 +27,9 @@
@attr(type='gate')
def test_update_service(self):
# Update description attribute of service
- name = rand_name('service-')
- type = rand_name('type--')
- description = rand_name('description-')
+ name = data_utils.rand_name('service-')
+ type = data_utils.rand_name('type--')
+ description = data_utils.rand_name('description-')
resp, body = self.client.create_service(
name, type, description=description)
self.assertEqual('200', resp['status'])
@@ -39,7 +39,7 @@
s_id = body['id']
resp1_desc = body['description']
- s_desc2 = rand_name('desc2-')
+ s_desc2 = data_utils.rand_name('desc2-')
resp, body = self.service_client.update_service(
s_id, description=s_desc2)
resp2_desc = body['description']
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index f8a62a6..2541e25 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -28,10 +28,10 @@
def test_tokens(self):
# Valid user's token is authenticated
# Create a User
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = '%s-description' % u_name
u_email = '%s@testmail.tm' % u_name
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
resp, user = self.v3_client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email)
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 50e9702..b1c4d82 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -27,10 +27,10 @@
def test_user_update(self):
# Test case to check if updating of user attributes is successful.
# Creating first user
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
resp, user = self.v3_client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, enabled=False)
@@ -38,11 +38,12 @@
self.addCleanup(self.v3_client.delete_user, user['id'])
# Creating second project for updation
resp, project = self.v3_client.create_project(
- rand_name('project-'), description=rand_name('project-desc-'))
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'))
# Delete the Project at the end of this method
self.addCleanup(self.v3_client.delete_project, project['id'])
# Updating user details with new values
- u_name2 = rand_name('user2-')
+ u_name2 = data_utils.rand_name('user2-')
u_email2 = u_name2 + '@testmail.tm'
u_description2 = u_name2 + ' description'
resp, update_user = self.v3_client.update_user(
@@ -73,21 +74,23 @@
assigned_project_ids = list()
fetched_project_ids = list()
_, u_project = self.v3_client.create_project(
- rand_name('project-'), description=rand_name('project-desc-'))
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'))
# Delete the Project at the end of this method
self.addCleanup(self.v3_client.delete_project, u_project['id'])
# Create a user.
- u_name = rand_name('user-')
+ u_name = data_utils.rand_name('user-')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = rand_name('pass-')
+ u_password = data_utils.rand_name('pass-')
_, user_body = self.v3_client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, enabled=False, project_id=u_project['id'])
# Delete the User at the end of this method
self.addCleanup(self.v3_client.delete_user, user_body['id'])
# Creating Role
- _, role_body = self.v3_client.create_role(rand_name('role-'))
+ _, role_body = self.v3_client.create_role(
+ data_utils.rand_name('role-'))
# Delete the Role at the end of this method
self.addCleanup(self.v3_client.delete_role, role_body['id'])
@@ -96,7 +99,8 @@
for i in range(2):
# Creating project so as to assign role
_, project_body = self.v3_client.create_project(
- rand_name('project-'), description=rand_name('project-desc-'))
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'))
_, project = self.v3_client.get_project(project_body['id'])
# Delete the Project at the end of this method
self.addCleanup(self.v3_client.delete_project, project_body['id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index ab89af4..876edfd 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -17,7 +17,7 @@
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
import tempest.test
@@ -94,8 +94,8 @@
def setup_test_user(self):
"""Set up a test user."""
self.setup_test_tenant()
- self.test_user = rand_name('test_user_')
- self.test_password = rand_name('pass_')
+ self.test_user = data_utils.rand_name('test_user_')
+ self.test_password = data_utils.rand_name('pass_')
self.test_email = self.test_user + '@testmail.tm'
resp, self.user = self.client.create_user(self.test_user,
self.test_password,
@@ -105,8 +105,8 @@
def setup_test_tenant(self):
"""Set up a test tenant."""
- self.test_tenant = rand_name('test_tenant_')
- self.test_description = rand_name('desc_')
+ self.test_tenant = data_utils.rand_name('test_tenant_')
+ self.test_description = data_utils.rand_name('desc_')
resp, self.tenant = self.client.create_tenant(
name=self.test_tenant,
description=self.test_description)
@@ -114,15 +114,15 @@
def setup_test_role(self):
"""Set up a test role."""
- self.test_role = rand_name('role')
+ self.test_role = data_utils.rand_name('role')
resp, self.role = self.client.create_role(self.test_role)
self.roles.append(self.role)
def setup_test_v3_user(self):
"""Set up a test v3 user."""
self.setup_test_project()
- self.test_user = rand_name('test_user_')
- self.test_password = rand_name('pass_')
+ self.test_user = data_utils.rand_name('test_user_')
+ self.test_password = data_utils.rand_name('pass_')
self.test_email = self.test_user + '@testmail.tm'
resp, self.v3_user = self.client.create_user(self.test_user,
self.test_password,
@@ -132,8 +132,8 @@
def setup_test_project(self):
"""Set up a test project."""
- self.test_project = rand_name('test_project_')
- self.test_description = rand_name('desc_')
+ self.test_project = data_utils.rand_name('test_project_')
+ self.test_description = data_utils.rand_name('desc_')
resp, self.project = self.client.create_project(
name=self.test_project,
description=self.test_description)
@@ -141,7 +141,7 @@
def setup_test_v3_role(self):
"""Set up a test v3 role."""
- self.test_role = rand_name('role')
+ self.test_role = data_utils.rand_name('role')
resp, self.v3_role = self.client.create_role(self.test_role)
self.v3_roles.append(self.v3_role)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index ee6d656..133bae0 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -123,8 +123,3 @@
image_list = map(lambda x: x['id'], images_list)
for image in self.created_images:
self.assertIn(image, image_list)
-
- @attr(type=['negative', 'gate'])
- def test_get_image_by_null_id(self):
- self.assertRaises(exceptions.NotFound,
- self.client.get_image, '')
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
new file mode 100644
index 0000000..5bdaa99
--- /dev/null
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+# 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 uuid
+
+from tempest.api.image import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ImagesNegativeTest(base.BaseV2ImageTest):
+
+ """
+ here we have -ve tests for get_image and delete_image api
+
+ Tests
+ ** get non-existent image
+ ** get image with image_id=NULL
+ ** get the deleted image
+ ** delete non-existent image
+ ** delete rimage with image_id=NULL
+ ** delete the deleted image
+ """
+
+ @attr(type=['negative', 'gate'])
+ def test_get_non_existent_image(self):
+ # get the non-existent image
+ non_existent_id = str(uuid.uuid4())
+ self.assertRaises(exceptions.NotFound, self.client.get_image,
+ non_existent_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_get_image_null_id(self):
+ # get image with image_id = NULL
+ image_id = ""
+ self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_get_delete_deleted_image(self):
+ # get and delete the deleted image
+ # create and delete image
+ resp, body = self.client.create_image(name='test',
+ container_format='bare',
+ disk_format='raw')
+ image_id = body['id']
+ self.assertEqual(201, resp.status)
+ self.client.delete_image(image_id)
+ self.client.wait_for_resource_deletion(image_id)
+
+ # get the deleted image
+ self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+ # delete the deleted image
+ self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ image_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_non_existing_image(self):
+ # delete non-existent image
+ non_existent_image_id = str(uuid.uuid4())
+ self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ non_existent_image_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_delete_image_null_id(self):
+ # delete image with image_id=NULL
+ image_id = ""
+ self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ image_id)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index ed915c1..b222ae3 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -18,7 +18,7 @@
import netaddr
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import log as logging
import tempest.test
@@ -105,7 +105,7 @@
@classmethod
def create_network(cls, network_name=None):
"""Wrapper utility that returns a test network."""
- network_name = network_name or rand_name('test-network-')
+ network_name = network_name or data_utils.rand_name('test-network-')
resp, body = cls.client.create_network(network_name)
network = body['network']
@@ -211,7 +211,7 @@
"""Wrapper utility that returns a test vpn service."""
resp, body = cls.client.create_vpn_service(
subnet_id, router_id, admin_state_up=True,
- name=rand_name("vpnservice-"))
+ name=data_utils.rand_name("vpnservice-"))
vpnservice = body['vpnservice']
cls.vpnservices.append(vpnservice)
return vpnservice
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 9acb6c5..35d4fa8 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -48,7 +48,7 @@
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
cls.router = cls.create_router(
- rand_name('router-'),
+ data_utils.rand_name('router-'),
external_network_id=cls.network_cfg.public_network_id)
resp, _ = cls.client.add_router_interface_with_subnet_id(
cls.router['id'], cls.subnet['id'])
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index e3bf4e8..7e4ec37 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -45,8 +45,8 @@
cls.network = cls.create_network()
cls.name = cls.network['name']
cls.subnet = cls.create_subnet(cls.network)
- pool_name = rand_name('pool-')
- vip_name = rand_name('vip-')
+ pool_name = data_utils.rand_name('pool-')
+ vip_name = data_utils.rand_name('vip-')
cls.pool = cls.create_pool(pool_name, "ROUND_ROBIN",
"HTTP", cls.subnet)
cls.vip = cls.create_vip(vip_name, "HTTP", 80, cls.subnet, cls.pool)
@@ -68,8 +68,8 @@
def test_create_update_delete_pool_vip(self):
# Creates a vip
- name = rand_name('vip-')
- resp, body = self.client.create_pool(rand_name("pool-"),
+ name = data_utils.rand_name('vip-')
+ resp, body = self.client.create_pool(data_utils.rand_name("pool-"),
"ROUND_ROBIN", "HTTP",
self.subnet['id'])
pool = body['pool']
@@ -134,7 +134,7 @@
@attr(type='smoke')
def test_create_update_delete_member(self):
# Creates a member
- resp, body = self.client.create_member("10.0.9.46", 80,
+ resp, body = self.client.create_member("10.0.9.47", 80,
self.pool['id'])
self.assertEqual('201', resp['status'])
member = body['member']
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index f2df1ee..14c8500 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,7 +18,7 @@
import netaddr
from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -66,7 +66,7 @@
@attr(type='smoke')
def test_create_update_delete_network_subnet(self):
# Creates a network
- name = rand_name('network-')
+ name = data_utils.rand_name('network-')
resp, body = self.client.create_network(name)
self.assertEqual('201', resp['status'])
network = body['network']
@@ -186,19 +186,19 @@
@attr(type=['negative', 'smoke'])
def test_show_non_existent_network(self):
- non_exist_id = rand_name('network')
+ non_exist_id = data_utils.rand_name('network')
self.assertRaises(exceptions.NotFound, self.client.show_network,
non_exist_id)
@attr(type=['negative', 'smoke'])
def test_show_non_existent_subnet(self):
- non_exist_id = rand_name('subnet')
+ non_exist_id = data_utils.rand_name('subnet')
self.assertRaises(exceptions.NotFound, self.client.show_subnet,
non_exist_id)
@attr(type=['negative', 'smoke'])
def test_show_non_existent_port(self):
- non_exist_id = rand_name('port')
+ non_exist_id = data_utils.rand_name('port')
self.assertRaises(exceptions.NotFound, self.client.show_port,
non_exist_id)
@@ -274,7 +274,8 @@
@attr(type='smoke')
def test_bulk_create_delete_network(self):
# Creates 2 networks in one request
- network_names = [rand_name('network-'), rand_name('network-')]
+ network_names = [data_utils.rand_name('network-'),
+ data_utils.rand_name('network-')]
resp, body = self.client.create_bulk_network(2, network_names)
created_networks = body['networks']
self.assertEqual('201', resp['status'])
@@ -299,7 +300,7 @@
names = []
networks = [self.network1['id'], self.network2['id']]
for i in range(len(networks)):
- names.append(rand_name('subnet-'))
+ names.append(data_utils.rand_name('subnet-'))
subnet_list = []
# TODO(raies): "for IPv6, version list [4, 6] will be used.
# and cidr for IPv6 will be of IPv6"
@@ -332,7 +333,7 @@
names = []
networks = [self.network1['id'], self.network2['id']]
for i in range(len(networks)):
- names.append(rand_name('port-'))
+ names.append(data_utils.rand_name('port-'))
port_list = []
state = [True, False]
for i in range(len(names)):
diff --git a/tempest/api/network/test_quotas.py b/tempest/api/network/test_quotas.py
index 51395ea..f7ba3cb 100644
--- a/tempest/api/network/test_quotas.py
+++ b/tempest/api/network/test_quotas.py
@@ -18,7 +18,7 @@
from tempest.api.network import base
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -55,8 +55,8 @@
@attr(type='gate')
def test_quotas(self):
# Add a tenant to conduct the test
- test_tenant = rand_name('test_tenant_')
- test_description = rand_name('desc_')
+ test_tenant = data_utils.rand_name('test_tenant_')
+ test_description = data_utils.rand_name('desc_')
_, tenant = self.identity_admin_client.create_tenant(
name=test_tenant,
description=test_description)
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 2f20cc9..3cbe23f 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -57,7 +57,7 @@
# Create a router
# NOTE(salv-orlando): Do not invoke self.create_router
# as we need to check the response code
- name = rand_name('router-')
+ name = data_utils.rand_name('router-')
resp, create_body = self.client.create_router(
name, external_gateway_info={
"network_id": self.network_cfg.public_network_id},
@@ -99,7 +99,7 @@
def test_add_remove_router_interface_with_subnet_id(self):
network = self.create_network()
subnet = self.create_subnet(network)
- router = self.create_router(rand_name('router-'))
+ router = self.create_router(data_utils.rand_name('router-'))
# Add router interface with subnet id
resp, interface = self.client.add_router_interface_with_subnet_id(
router['id'], subnet['id'])
@@ -118,7 +118,7 @@
def test_add_remove_router_interface_with_port_id(self):
network = self.create_network()
self.create_subnet(network)
- router = self.create_router(rand_name('router-'))
+ router = self.create_router(data_utils.rand_name('router-'))
resp, port_body = self.client.create_port(network['id'])
# add router interface to port created above
resp, interface = self.client.add_router_interface_with_port_id(
@@ -160,7 +160,7 @@
@attr(type='smoke')
def test_update_router_set_gateway(self):
- router = self.create_router(rand_name('router-'))
+ router = self.create_router(data_utils.rand_name('router-'))
self.client.update_router(
router['id'],
external_gateway_info={
@@ -175,7 +175,7 @@
@attr(type='smoke')
def test_update_router_set_gateway_with_snat_explicit(self):
- router = self.create_router(rand_name('router-'))
+ router = self.create_router(data_utils.rand_name('router-'))
self.admin_client.update_router_with_snat_gw_info(
router['id'],
external_gateway_info={
@@ -189,7 +189,7 @@
@attr(type='smoke')
def test_update_router_set_gateway_without_snat(self):
- router = self.create_router(rand_name('router-'))
+ router = self.create_router(data_utils.rand_name('router-'))
self.admin_client.update_router_with_snat_gw_info(
router['id'],
external_gateway_info={
@@ -204,7 +204,7 @@
@attr(type='smoke')
def test_update_router_unset_gateway(self):
router = self.create_router(
- rand_name('router-'),
+ data_utils.rand_name('router-'),
external_network_id=self.network_cfg.public_network_id)
self.client.update_router(router['id'], external_gateway_info={})
self._verify_router_gateway(router['id'])
@@ -217,7 +217,7 @@
@attr(type='smoke')
def test_update_router_reset_gateway_without_snat(self):
router = self.create_router(
- rand_name('router-'),
+ data_utils.rand_name('router-'),
external_network_id=self.network_cfg.public_network_id)
self.admin_client.update_router_with_snat_gw_info(
router['id'],
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index 7a8128b..9cbc7ac 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -39,7 +39,7 @@
super(VPNaaSJSON, cls).setUpClass()
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
- cls.router = cls.create_router(rand_name("router-"))
+ cls.router = cls.create_router(data_utils.rand_name("router-"))
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
cls.vpnservice = cls.create_vpnservice(cls.subnet['id'],
cls.router['id'])
@@ -55,7 +55,7 @@
@attr(type='smoke')
def test_create_update_delete_vpn_service(self):
# Creates a VPN service
- name = rand_name('vpn-service-')
+ name = data_utils.rand_name('vpn-service-')
resp, body = self.client.create_vpn_service(self.subnet['id'],
self.router['id'],
name=name,
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index a90d3f4..b4128e2 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -18,8 +18,7 @@
from tempest.api.object_storage import base
from tempest import clients
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.test import attr
@@ -32,7 +31,7 @@
@classmethod
def setUpClass(cls):
super(AccountQuotasTest, cls).setUpClass()
- cls.container_name = rand_name(name="TestContainer")
+ cls.container_name = data_utils.rand_name(name="TestContainer")
cls.container_client.create_container(cls.container_name)
cls.data.setup_test_user()
@@ -102,8 +101,8 @@
"Account Quotas middleware not available")
@attr(type="smoke")
def test_upload_valid_object(self):
- object_name = rand_name(name="TestObject")
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name="TestObject")
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
@@ -113,8 +112,8 @@
"Account Quotas middleware not available")
@attr(type=["negative", "smoke"])
def test_upload_large_object(self):
- object_name = rand_name(name="TestObject")
- data = arbitrary_string(30)
+ object_name = data_utils.rand_name(name="TestObject")
+ data = data_utils.arbitrary_string(30)
self.assertRaises(exceptions.OverLimit,
self.object_client.create_object,
self.container_name, object_name, data)
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 90b0914..615b179 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -18,7 +18,7 @@
import random
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import HTTP_SUCCESS
@@ -30,7 +30,7 @@
super(AccountTest, cls).setUpClass()
cls.containers = []
for i in xrange(ord('a'), ord('f') + 1):
- name = rand_name(name='%s-' % chr(i))
+ name = data_utils.rand_name(name='%s-' % chr(i))
cls.container_client.create_container(name)
cls.containers.append(name)
cls.containers_count = len(cls.containers)
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index de5307a..18000b9 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import HTTP_SUCCESS
@@ -39,7 +39,7 @@
def setUp(self):
super(ObjectTestACLs, self).setUp()
- self.container_name = rand_name(name='TestContainer')
+ self.container_name = data_utils.rand_name(name='TestContainer')
self.container_client.create_container(self.container_name)
def tearDown(self):
@@ -50,7 +50,7 @@
def test_write_object_without_using_creds(self):
# trying to create object with empty headers
# X-Auth-Token is not provided
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
self.assertRaises(exceptions.Unauthorized,
self.custom_object_client.create_object,
self.container_name, object_name, 'data')
@@ -58,7 +58,7 @@
@attr(type=['negative', 'gate'])
def test_delete_object_without_using_creds(self):
# create object
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(self.container_name,
object_name, 'data')
# trying to delete object with empty headers
@@ -71,7 +71,7 @@
def test_write_object_with_non_authorized_user(self):
# attempt to upload another file using non-authorized user
# User provided token is forbidden. ACL are not set
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
# trying to create object with non-authorized user
self.assertRaises(exceptions.Unauthorized,
self.custom_object_client.create_object,
@@ -82,7 +82,7 @@
def test_read_object_with_non_authorized_user(self):
# attempt to read object using non-authorized user
# User provided token is forbidden. ACL are not set
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(
self.container_name, object_name, 'data')
self.assertEqual(resp['status'], '201')
@@ -96,7 +96,7 @@
def test_delete_object_with_non_authorized_user(self):
# attempt to delete object using non-authorized user
# User provided token is forbidden. ACL are not set
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(
self.container_name, object_name, 'data')
self.assertEqual(resp['status'], '201')
@@ -116,7 +116,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# create object
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(self.container_name,
object_name, 'data')
self.assertEqual(resp['status'], '201')
@@ -136,7 +136,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# Trying to write the object without rights
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
self.assertRaises(exceptions.Unauthorized,
self.custom_object_client.create_object,
self.container_name,
@@ -154,7 +154,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# create object
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(self.container_name,
object_name, 'data')
self.assertEqual(resp['status'], '201')
@@ -175,7 +175,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# Trying to write the object with rights
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.custom_object_client.create_object(
self.container_name,
object_name, 'data',
@@ -194,7 +194,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# Trying to write the object without write rights
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
self.assertRaises(exceptions.Unauthorized,
self.custom_object_client.create_object,
self.container_name,
@@ -213,7 +213,7 @@
metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# create object
- object_name = rand_name(name='Object')
+ object_name = data_utils.rand_name(name='Object')
resp, _ = self.object_client.create_object(self.container_name,
object_name, 'data')
self.assertEqual(resp['status'], '201')
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 2e0d76a..04536fe 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -18,8 +18,7 @@
import testtools
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.test import attr
@@ -46,7 +45,7 @@
Maximum object count of the container.
"""
super(ContainerQuotasTest, self).setUp()
- self.container_name = rand_name(name="TestContainer")
+ self.container_name = data_utils.rand_name(name="TestContainer")
self.container_client.create_container(self.container_name)
metadata = {"quota-bytes": str(QUOTA_BYTES),
"quota-count": str(QUOTA_COUNT), }
@@ -62,8 +61,8 @@
@attr(type="smoke")
def test_upload_valid_object(self):
"""Attempts to uploads an object smaller than the bytes quota."""
- object_name = rand_name(name="TestObject")
- data = arbitrary_string(QUOTA_BYTES)
+ object_name = data_utils.rand_name(name="TestObject")
+ data = data_utils.arbitrary_string(QUOTA_BYTES)
nbefore = self._get_bytes_used()
@@ -78,8 +77,8 @@
@attr(type="smoke")
def test_upload_large_object(self):
"""Attempts to upload an object lagger than the bytes quota."""
- object_name = rand_name(name="TestObject")
- data = arbitrary_string(QUOTA_BYTES + 1)
+ object_name = data_utils.rand_name(name="TestObject")
+ data = data_utils.arbitrary_string(QUOTA_BYTES + 1)
nbefore = self._get_bytes_used()
@@ -95,7 +94,7 @@
def test_upload_too_many_objects(self):
"""Attempts to upload many objects that exceeds the count limit."""
for _ in range(QUOTA_COUNT):
- name = rand_name(name="TestObject")
+ name = data_utils.rand_name(name="TestObject")
self.object_client.create_object(self.container_name, name, "")
nbefore = self._get_object_count()
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 4b49d73..4fae953 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -16,8 +16,7 @@
# under the License.
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import HTTP_SUCCESS
@@ -35,7 +34,7 @@
@attr(type='smoke')
def test_create_container(self):
- container_name = rand_name(name='TestContainer')
+ container_name = data_utils.rand_name(name='TestContainer')
resp, body = self.container_client.create_container(container_name)
self.containers.append(container_name)
self.assertIn(resp['status'], ('202', '201'))
@@ -43,7 +42,7 @@
@attr(type='smoke')
def test_delete_container(self):
# create a container
- container_name = rand_name(name='TestContainer')
+ container_name = data_utils.rand_name(name='TestContainer')
resp, _ = self.container_client.create_container(container_name)
self.containers.append(container_name)
# delete container
@@ -56,17 +55,17 @@
# add metadata to an object
# create a container
- container_name = rand_name(name='TestContainer')
+ container_name = data_utils.rand_name(name='TestContainer')
resp, _ = self.container_client.create_container(container_name)
self.containers.append(container_name)
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(container_name,
object_name, data)
# set object metadata
- meta_key = rand_name(name='Meta-Test-')
- meta_value = rand_name(name='MetaValue-')
+ meta_key = data_utils.rand_name(name='Meta-Test-')
+ meta_value = data_utils.rand_name(name='MetaValue-')
orig_metadata = {meta_key: meta_value}
resp, _ = self.object_client.update_object_metadata(container_name,
object_name,
@@ -87,7 +86,7 @@
# update/retrieve/delete container metadata
# create a container
- container_name = rand_name(name='TestContainer')
+ container_name = data_utils.rand_name(name='TestContainer')
resp, _ = self.container_client.create_container(container_name)
self.containers.append(container_name)
# update container metadata
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index d07697a..9e405d6 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -15,8 +15,7 @@
# under the License.
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -25,15 +24,15 @@
@classmethod
def setUpClass(cls):
super(StaticWebTest, cls).setUpClass()
- cls.container_name = rand_name(name="TestContainer")
+ cls.container_name = data_utils.rand_name(name="TestContainer")
# This header should be posted on the container before every test
cls.headers_public_read_acl = {'Read': '.r:*'}
# Create test container and create one object in it
cls.container_client.create_container(cls.container_name)
- cls.object_name = rand_name(name="TestObject")
- cls.object_data = arbitrary_string()
+ cls.object_name = data_utils.rand_name(name="TestObject")
+ cls.object_data = data_utils.arbitrary_string()
cls.object_client.create_object(cls.container_name,
cls.object_name,
cls.object_data)
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index ff9f7bf..dcfe219 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -18,7 +18,7 @@
import time
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import skip_because
@@ -37,9 +37,9 @@
int(container_sync_timeout / cls.container_sync_interval)
# define container and object clients
cls.clients = {}
- cls.clients[rand_name(name='TestContainerSync')] = \
+ cls.clients[data_utils.rand_name(name='TestContainerSync')] = \
(cls.container_client, cls.object_client)
- cls.clients[rand_name(name='TestContainerSync')] = \
+ cls.clients[data_utils.rand_name(name='TestContainerSync')] = \
(cls.container_client_alt, cls.object_client_alt)
for cont_name, client in cls.clients.items():
client[0].create_container(cont_name)
@@ -71,8 +71,8 @@
'Error installing X-Container-Sync-To '
'for the container "%s"' % (cont[0]))
# create object in container
- object_name = rand_name(name='TestSyncObject')
- data = object_name[::-1] # arbitrary_string()
+ object_name = data_utils.rand_name(name='TestSyncObject')
+ data = object_name[::-1] # data_utils.arbitrary_string()
resp, _ = obj_client[0].create_object(cont[0], object_name, data)
self.assertEqual(resp['status'], '201',
'Error creating the object "%s" in'
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
new file mode 100644
index 0000000..0ae7e46
--- /dev/null
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -0,0 +1,82 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
+#
+# 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.object_storage import base
+from tempest import clients
+from tempest import config
+from tempest.test import attr
+from tempest.test import HTTP_SUCCESS
+
+
+class CrossdomainTest(base.BaseObjectTest):
+ crossdomain_available = \
+ config.TempestConfig().object_storage_feature_enabled.crossdomain
+
+ @classmethod
+ def setUpClass(cls):
+ super(CrossdomainTest, cls).setUpClass()
+
+ # skip this test if CORS isn't enabled in the conf file.
+ if not cls.crossdomain_available:
+ skip_msg = ("%s skipped as Crossdomain middleware not available"
+ % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ # creates a test user. The test user will set its base_url to the Swift
+ # endpoint and test the healthcheck feature.
+ cls.data.setup_test_user()
+
+ cls.os_test_user = clients.Manager(
+ cls.data.test_user,
+ cls.data.test_password,
+ cls.data.test_tenant)
+
+ cls.xml_start = '<?xml version="1.0"?>\n' \
+ '<!DOCTYPE cross-domain-policy SYSTEM ' \
+ '"http://www.adobe.com/xml/dtds/cross-domain-policy.' \
+ 'dtd" >\n<cross-domain-policy>\n'
+
+ cls.xml_end = "</cross-domain-policy>"
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.data.teardown_all()
+ super(CrossdomainTest, cls).tearDownClass()
+
+ def setUp(self):
+ super(CrossdomainTest, self).setUp()
+
+ client = self.os_test_user.account_client
+ client._set_auth()
+ # Turning http://.../v1/foobar into http://.../
+ client.base_url = "/".join(client.base_url.split("/")[:-2])
+
+ def tearDown(self):
+ # clear the base_url for subsequent requests
+ self.os_test_user.account_client.base_url = None
+
+ super(CrossdomainTest, self).tearDown()
+
+ @attr('gate')
+ def test_get_crossdomain_policy(self):
+ resp, body = self.os_test_user.account_client.get("crossdomain.xml",
+ {})
+
+ self.assertIn(int(resp['status']), HTTP_SUCCESS)
+ self.assertTrue(body.startswith(self.xml_start) and
+ body.endswith(self.xml_end))
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index cb52d88..6fc3853 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -18,8 +18,7 @@
import time
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import skip_because
@@ -29,7 +28,7 @@
@classmethod
def setUpClass(cls):
super(ObjectExpiryTest, cls).setUpClass()
- cls.container_name = rand_name(name='TestContainer')
+ cls.container_name = data_utils.rand_name(name='TestContainer')
cls.container_client.create_container(cls.container_name)
@classmethod
@@ -49,8 +48,8 @@
# "X-Delete-At", after this test case works.
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
# update object metadata with expiry time of 3 seconds
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 3389235..7626af1 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -18,8 +18,7 @@
import hashlib
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import HTTP_SUCCESS
@@ -28,7 +27,7 @@
@classmethod
def setUpClass(cls):
super(ObjectTest, cls).setUpClass()
- cls.container_name = rand_name(name='TestContainer')
+ cls.container_name = data_utils.rand_name(name='TestContainer')
cls.container_client.create_container(cls.container_name)
cls.containers = [cls.container_name]
@@ -51,13 +50,13 @@
@attr(type='smoke')
def test_create_object(self):
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
# create another object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
self.assertEqual(resp['status'], '201')
@@ -65,8 +64,8 @@
@attr(type='smoke')
def test_delete_object(self):
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
# delete object
@@ -79,13 +78,13 @@
# add metadata to storage object, test if metadata is retrievable
# create Object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
# set object metadata
- meta_key = rand_name(name='test-')
- meta_value = rand_name(name='MetaValue-')
+ meta_key = data_utils.rand_name(name='test-')
+ meta_value = data_utils.rand_name(name='MetaValue-')
orig_metadata = {meta_key: meta_value}
resp, _ = self.object_client.update_object_metadata(
self.container_name, object_name, orig_metadata)
@@ -104,8 +103,8 @@
# retrieve object's data (in response body)
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
# get object
@@ -117,16 +116,16 @@
@attr(type='smoke')
def test_copy_object_in_same_container(self):
# create source object
- src_object_name = rand_name(name='SrcObject')
- src_data = arbitrary_string(size=len(src_object_name) * 2,
- base_text=src_object_name)
+ src_object_name = data_utils.rand_name(name='SrcObject')
+ src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
+ base_text=src_object_name)
resp, _ = self.object_client.create_object(self.container_name,
src_object_name,
src_data)
# create destination object
- dst_object_name = rand_name(name='DstObject')
- dst_data = arbitrary_string(size=len(dst_object_name) * 3,
- base_text=dst_object_name)
+ dst_object_name = data_utils.rand_name(name='DstObject')
+ dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
+ base_text=dst_object_name)
resp, _ = self.object_client.create_object(self.container_name,
dst_object_name,
dst_data)
@@ -144,8 +143,8 @@
# change the content type of an existing object
# create object
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
self.object_client.create_object(self.container_name,
object_name, data)
# get the old content type
@@ -165,15 +164,15 @@
@attr(type='smoke')
def test_copy_object_2d_way(self):
# create source object
- src_object_name = rand_name(name='SrcObject')
- src_data = arbitrary_string(size=len(src_object_name) * 2,
- base_text=src_object_name)
+ src_object_name = data_utils.rand_name(name='SrcObject')
+ src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
+ base_text=src_object_name)
resp, _ = self.object_client.create_object(self.container_name,
src_object_name, src_data)
# create destination object
- dst_object_name = rand_name(name='DstObject')
- dst_data = arbitrary_string(size=len(dst_object_name) * 3,
- base_text=dst_object_name)
+ dst_object_name = data_utils.rand_name(name='DstObject')
+ dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
+ base_text=dst_object_name)
resp, _ = self.object_client.create_object(self.container_name,
dst_object_name, dst_data)
# copy source object to destination
@@ -189,22 +188,23 @@
@attr(type='smoke')
def test_copy_object_across_containers(self):
# create a container to use as asource container
- src_container_name = rand_name(name='TestSourceContainer')
+ src_container_name = data_utils.rand_name(name='TestSourceContainer')
self.container_client.create_container(src_container_name)
self.containers.append(src_container_name)
# create a container to use as a destination container
- dst_container_name = rand_name(name='TestDestinationContainer')
+ dst_container_name = data_utils.rand_name(
+ name='TestDestinationContainer')
self.container_client.create_container(dst_container_name)
self.containers.append(dst_container_name)
# create object in source container
- object_name = rand_name(name='Object')
- data = arbitrary_string(size=len(object_name) * 2,
- base_text=object_name)
+ object_name = data_utils.rand_name(name='Object')
+ data = data_utils.arbitrary_string(size=len(object_name) * 2,
+ base_text=object_name)
resp, _ = self.object_client.create_object(src_container_name,
object_name, data)
# set object metadata
- meta_key = rand_name(name='test-')
- meta_value = rand_name(name='MetaValue-')
+ meta_key = data_utils.rand_name(name='test-')
+ meta_value = data_utils.rand_name(name='MetaValue-')
orig_metadata = {meta_key: meta_value}
resp, _ = self.object_client.update_object_metadata(src_container_name,
object_name,
@@ -226,8 +226,8 @@
@attr(type='gate')
def test_object_upload_in_segments(self):
# create object
- object_name = rand_name(name='LObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='LObject')
+ data = data_utils.arbitrary_string()
segments = 10
data_segments = [data + str(i) for i in xrange(segments)]
# uploading segments
@@ -259,8 +259,8 @@
# Make a conditional request for an object using the If-None-Match
# header, it should get downloaded only if the local file is different,
# otherwise the response code should be 304 Not Modified
- object_name = rand_name(name='TestObject')
- data = arbitrary_string()
+ object_name = data_utils.rand_name(name='TestObject')
+ data = data_utils.arbitrary_string()
self.object_client.create_object(self.container_name,
object_name, data)
# local copy is identical, no download
@@ -281,7 +281,7 @@
class PublicObjectTest(base.BaseObjectTest):
def setUp(self):
super(PublicObjectTest, self).setUp()
- self.container_name = rand_name(name='TestContainer')
+ self.container_name = data_utils.rand_name(name='TestContainer')
self.container_client.create_container(self.container_name)
def tearDown(self):
@@ -299,9 +299,9 @@
self.container_name, metadata=cont_headers, metadata_prefix='')
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# create object
- object_name = rand_name(name='Object')
- data = arbitrary_string(size=len(object_name),
- base_text=object_name)
+ object_name = data_utils.rand_name(name='Object')
+ data = data_utils.arbitrary_string(size=len(object_name),
+ base_text=object_name)
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
self.assertEqual(resp['status'], '201')
@@ -329,9 +329,9 @@
self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
# create object
- object_name = rand_name(name='Object')
- data = arbitrary_string(size=len(object_name) * 1,
- base_text=object_name)
+ object_name = data_utils.rand_name(name='Object')
+ data = data_utils.arbitrary_string(size=len(object_name) * 1,
+ base_text=object_name)
resp, _ = self.object_client.create_object(self.container_name,
object_name, data)
self.assertEqual(resp['status'], '201')
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 0fd5499..77f3a53 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -21,8 +21,7 @@
import urlparse
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
from tempest.test import HTTP_SUCCESS
@@ -33,7 +32,7 @@
@classmethod
def setUpClass(cls):
super(ObjectTempUrlTest, cls).setUpClass()
- cls.container_name = rand_name(name='TestContainer')
+ cls.container_name = data_utils.rand_name(name='TestContainer')
cls.container_client.create_container(cls.container_name)
cls.containers = [cls.container_name]
@@ -66,9 +65,9 @@
self.key)
# create object
- self.object_name = rand_name(name='ObjectTemp')
- self.data = arbitrary_string(size=len(self.object_name),
- base_text=self.object_name)
+ self.object_name = data_utils.rand_name(name='ObjectTemp')
+ self.data = data_utils.arbitrary_string(size=len(self.object_name),
+ base_text=self.object_name)
self.object_client.create_object(self.container_name,
self.object_name, self.data)
@@ -111,8 +110,9 @@
@attr(type='gate')
def test_put_object_using_temp_url(self):
# make sure the metadata has been set
- new_data = arbitrary_string(size=len(self.object_name),
- base_text=rand_name(name="random"))
+ new_data = data_utils.arbitrary_string(
+ size=len(self.object_name),
+ base_text=data_utils.rand_name(name="random"))
EXPIRATION_TIME = 10000 # high to ensure the test finishes.
expires = int(time.time() + EXPIRATION_TIME)
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 2b75b77..c47e1b6 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -44,14 +44,14 @@
@attr(type='smoke')
def test_versioned_container(self):
# create container
- vers_container_name = rand_name(name='TestVersionContainer')
+ vers_container_name = data_utils.rand_name(name='TestVersionContainer')
resp, body = self.container_client.create_container(
vers_container_name)
self.containers.append(vers_container_name)
self.assertIn(resp['status'], ('202', '201'))
self.assertContainer(vers_container_name, '0', '0', 'Missing Header')
- base_container_name = rand_name(name='TestBaseContainer')
+ base_container_name = data_utils.rand_name(name='TestBaseContainer')
headers = {'X-versions-Location': vers_container_name}
resp, body = self.container_client.create_container(
base_container_name,
@@ -61,7 +61,7 @@
self.assertIn(resp['status'], ('202', '201'))
self.assertContainer(base_container_name, '0', '0',
vers_container_name)
- object_name = rand_name(name='TestObject')
+ object_name = data_utils.rand_name(name='TestObject')
# create object
resp, _ = self.object_client.create_object(base_container_name,
object_name, '1')
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 7c72991..f3ef99f 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -15,7 +15,7 @@
import time
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
import tempest.test
@@ -99,7 +99,7 @@
@classmethod
def _create_keypair(cls, name_start='keypair-heat-'):
- kp_name = rand_name(name_start)
+ kp_name = data_utils.rand_name(name_start)
resp, body = cls.keypairs_client.create_keypair(kp_name)
cls.keypairs.append(kp_name)
return body
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index aa59581..d294c7a 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -15,7 +15,7 @@
import logging
from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -30,7 +30,7 @@
def setUpClass(cls):
super(TestServerStackLimits, cls).setUpClass()
cls.client = cls.orchestration_client
- cls.stack_name = rand_name('heat')
+ cls.stack_name = data_utils.rand_name('heat')
@attr(type='gate')
def test_exceed_max_template_size_fails(self):
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 174c82a..c86edf0 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -17,7 +17,7 @@
from tempest.api.orchestration import base
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -101,7 +101,7 @@
if not cls.config.service_available.neutron:
raise cls.skipException("Neutron support is required")
cls.network_client = os.network_client
- cls.stack_name = rand_name('heat')
+ cls.stack_name = data_utils.rand_name('heat')
cls.keypair_name = (cls.orchestration_cfg.keypair_name or
cls._create_keypair()['name'])
cls.external_router_id = cls._get_external_router_id()
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index 0ecc5ff..35a7326 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -15,7 +15,7 @@
import logging
from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -76,7 +76,7 @@
if not cls.orchestration_cfg.image_ref:
raise cls.skipException("No image available to test")
cls.client = cls.orchestration_client
- cls.stack_name = rand_name('heat')
+ cls.stack_name = data_utils.rand_name('heat')
keypair_name = (cls.orchestration_cfg.keypair_name or
cls._create_keypair()['name'])
diff --git a/tempest/api/orchestration/stacks/test_server_cfn_init.py b/tempest/api/orchestration/stacks/test_server_cfn_init.py
index ea0bff5..3c2a2d2 100644
--- a/tempest/api/orchestration/stacks/test_server_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_server_cfn_init.py
@@ -16,7 +16,7 @@
import testtools
from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
import tempest.config
from tempest.openstack.common import log as logging
@@ -132,7 +132,7 @@
raise cls.skipException("No image available to test")
cls.client = cls.orchestration_client
- stack_name = rand_name('heat')
+ stack_name = data_utils.rand_name('heat')
if cls.orchestration_cfg.keypair_name:
keypair_name = cls.orchestration_cfg.keypair_name
else:
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 4bda5ab..0b7883d 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -13,7 +13,7 @@
# under the License.
from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.test import attr
@@ -39,7 +39,7 @@
@attr(type='smoke')
def test_stack_crud_no_resources(self):
- stack_name = rand_name('heat')
+ stack_name = data_utils.rand_name('heat')
# create the stack
stack_identifier = self.create_stack(
diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py
index 6a7c541..2589632 100644
--- a/tempest/api/orchestration/stacks/test_templates.py
+++ b/tempest/api/orchestration/stacks/test_templates.py
@@ -15,7 +15,7 @@
import logging
from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -41,7 +41,7 @@
def setUpClass(cls):
super(TemplateYAMLTestJSON, cls).setUpClass()
cls.client = cls.orchestration_client
- cls.stack_name = rand_name('heat')
+ cls.stack_name = data_utils.rand_name('heat')
cls.stack_identifier = cls.create_stack(cls.stack_name, cls.template)
cls.client.wait_for_stack_status(cls.stack_identifier,
'CREATE_COMPLETE')
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index eada639..6bc350a 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -13,7 +13,7 @@
# under the License.
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.services.volume.json.admin import volume_types_client
from tempest.services.volume.json import volumes_client
@@ -54,8 +54,8 @@
cls.volume_id_list = []
try:
# Volume/Type creation (uses backend1_name)
- type1_name = rand_name('Type-')
- vol1_name = rand_name('Volume-')
+ type1_name = data_utils.rand_name('Type-')
+ vol1_name = data_utils.rand_name('Volume-')
extra_specs1 = {"volume_backend_name": cls.backend1_name}
resp, cls.type1 = cls.type_client.create_volume_type(
type1_name, extra_specs=extra_specs1)
@@ -69,8 +69,8 @@
if cls.backend1_name != cls.backend2_name:
# Volume/Type creation (uses backend2_name)
- type2_name = rand_name('Type-')
- vol2_name = rand_name('Volume-')
+ type2_name = data_utils.rand_name('Type-')
+ vol2_name = data_utils.rand_name('Volume-')
extra_specs2 = {"volume_backend_name": cls.backend2_name}
resp, cls.type2 = cls.type_client.create_volume_type(
type2_name, extra_specs=extra_specs2)
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
new file mode 100644
index 0000000..5e838e5
--- /dev/null
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -0,0 +1,110 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.volume.base import BaseVolumeAdminTest
+from tempest.common.utils import data_utils
+from tempest.test import attr
+
+
+class SnapshotsActionsTest(BaseVolumeAdminTest):
+ _interface = "json"
+
+ @classmethod
+ def setUpClass(cls):
+ super(SnapshotsActionsTest, cls).setUpClass()
+ cls.client = cls.snapshots_client
+
+ # Create admin volume client
+ cls.admin_snapshots_client = cls.os_adm.snapshots_client
+
+ # Create a test shared volume for tests
+ vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
+ resp_vol, cls.volume = \
+ cls.volumes_client.create_volume(size=1, display_name=vol_name)
+ cls.volumes_client.wait_for_volume_status(cls.volume['id'],
+ 'available')
+
+ # Create a test shared snapshot for tests
+ snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot-')
+ resp_snap, cls.snapshot = \
+ cls.client.create_snapshot(cls.volume['id'],
+ display_name=snap_name)
+ cls.client.wait_for_snapshot_status(cls.snapshot['id'],
+ 'available')
+
+ @classmethod
+ def tearDownClass(cls):
+ # Delete the test snapshot
+ cls.client.delete_snapshot(cls.snapshot['id'])
+ cls.client.wait_for_resource_deletion(cls.snapshot['id'])
+
+ # Delete the test volume
+ cls.volumes_client.delete_volume(cls.volume['id'])
+ cls.volumes_client.wait_for_resource_deletion(cls.volume['id'])
+
+ super(SnapshotsActionsTest, cls).tearDownClass()
+
+ def tearDown(self):
+ # Set snapshot's status to available after test
+ status = 'available'
+ snapshot_id = self.snapshot['id']
+ self.admin_snapshots_client.reset_snapshot_status(snapshot_id,
+ status)
+ super(SnapshotsActionsTest, self).tearDown()
+
+ def _get_progress_alias(self):
+ return 'os-extended-snapshot-attributes:progress'
+
+ @attr(type='gate')
+ def test_reset_snapshot_status(self):
+ # Reset snapshot status to creating
+ status = 'creating'
+ resp, body = self.admin_snapshots_client.\
+ reset_snapshot_status(self.snapshot['id'], status)
+ self.assertEqual(202, resp.status)
+ resp_get, snapshot_get \
+ = self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
+ self.assertEqual(200, resp_get.status)
+ self.assertEqual(status, snapshot_get['status'])
+
+ @attr(type='gate')
+ def test_update_snapshot_status(self):
+ # Reset snapshot status to creating
+ status = 'creating'
+ self.admin_snapshots_client.\
+ reset_snapshot_status(self.snapshot['id'], status)
+
+ # Update snapshot status to error
+ progress = '80%'
+ status = 'error'
+ progress_alias = self._get_progress_alias()
+ resp, body = self.client.update_snapshot_status(self.snapshot['id'],
+ status, progress)
+ self.assertEqual(202, resp.status)
+ resp_get, snapshot_get \
+ = self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
+ self.assertEqual(200, resp_get.status)
+ self.assertEqual(status, snapshot_get['status'])
+ self.assertEqual(progress, snapshot_get[progress_alias])
+
+
+class SnapshotsActionsTestXML(SnapshotsActionsTest):
+ _interface = "xml"
+
+ def _get_progress_alias(self):
+ return '{http://docs.openstack.org/volume/ext' \
+ '/extended_snapshot_attributes/api/v1}progress'
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 7e9d242..5218f83 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.volume.base import BaseVolumeTest
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.services.volume.json.admin import volume_types_client
from tempest.test import attr
@@ -58,8 +58,8 @@
def test_create_get_delete_volume_with_volume_type_and_extra_specs(self):
# Create/get/delete volume with volume_type and extra spec.
volume = {}
- vol_name = rand_name("volume-")
- vol_type_name = rand_name("volume-type-")
+ vol_name = data_utils.rand_name("volume-")
+ vol_type_name = data_utils.rand_name("volume-type-")
proto = self.config.volume.storage_protocol
vendor = self.config.volume.vendor_name
extra_specs = {"storage_protocol": proto,
@@ -102,7 +102,7 @@
def test_volume_type_create_get_delete(self):
# Create/get volume type.
body = {}
- name = rand_name("volume-type-")
+ name = data_utils.rand_name("volume-type-")
proto = self.config.volume.storage_protocol
vendor = self.config.volume.vendor_name
extra_specs = {"storage_protocol": proto,
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 0892eae..dbb75af 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
@@ -26,7 +26,7 @@
@classmethod
def setUpClass(cls):
super(VolumeTypesExtraSpecsTest, cls).setUpClass()
- vol_type_name = rand_name('Volume-type-')
+ vol_type_name = data_utils.rand_name('Volume-type-')
resp, cls.volume_type = cls.client.create_volume_type(vol_type_name)
@classmethod
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index e76c0ac..8b5dce2 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -18,7 +18,7 @@
import uuid
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -29,7 +29,7 @@
@classmethod
def setUpClass(cls):
super(ExtraSpecsNegativeTest, cls).setUpClass()
- vol_type_name = rand_name('Volume-type-')
+ vol_type_name = data_utils.rand_name('Volume-type-')
cls.extra_specs = {"spec1": "val1"}
resp, cls.volume_type = cls.client.create_volume_type(vol_type_name,
extra_specs=
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
new file mode 100644
index 0000000..dacebf1
--- /dev/null
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -0,0 +1,120 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from tempest.api.volume.base import BaseVolumeTest
+from tempest import clients
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+class VolumesTransfersTest(BaseVolumeTest):
+ _interface = "json"
+
+ @classmethod
+ def setUpClass(cls):
+ super(VolumesTransfersTest, cls).setUpClass()
+
+ # Add another tenant to test volume-transfer
+ if cls.config.compute.allow_tenant_isolation:
+ creds = cls.isolated_creds.get_alt_creds()
+ username, tenant_name, password = creds
+ cls.os_alt = clients.Manager(username=username,
+ password=password,
+ tenant_name=tenant_name,
+ interface=cls._interface)
+ cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
+
+ # Add admin tenant to cleanup resources
+ adm_creds = cls.isolated_creds.get_admin_creds()
+ admin_username, admin_tenant_name, admin_password = adm_creds
+ cls.os_adm = clients.Manager(username=admin_username,
+ password=admin_password,
+ tenant_name=admin_tenant_name,
+ interface=cls._interface)
+ else:
+ cls.os_alt = clients.AltManager()
+ alt_tenant_name = cls.os_alt.tenant_name
+ identity_client = cls._get_identity_admin_client()
+ _, tenants = identity_client.list_tenants()
+ cls.alt_tenant_id = [tnt['id'] for tnt in tenants
+ if tnt['name'] == alt_tenant_name][0]
+ cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
+
+ cls.client = cls.volumes_client
+ cls.alt_client = cls.os_alt.volumes_client
+ cls.adm_client = cls.os_adm.volumes_client
+
+ @attr(type='gate')
+ def test_create_get_list_accept_volume_transfer(self):
+ # Create a volume first
+ vol_name = rand_name('-Volume-')
+ _, volume = self.client.create_volume(size=1, display_name=vol_name)
+ self.addCleanup(self.adm_client.delete_volume, volume['id'])
+ self.client.wait_for_volume_status(volume['id'], 'available')
+
+ # Create a volume transfer
+ resp, transfer = self.client.create_volume_transfer(volume['id'])
+ self.assertEqual(202, resp.status)
+ transfer_id = transfer['id']
+ auth_key = transfer['auth_key']
+ self.client.wait_for_volume_status(volume['id'],
+ 'awaiting-transfer')
+
+ # Get a volume transfer
+ resp, body = self.client.get_volume_transfer(transfer_id)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(volume['id'], body['volume_id'])
+
+ # List volume transfers, the result should be greater than
+ # or equal to 1
+ resp, body = self.client.list_volume_transfers()
+ self.assertEqual(200, resp.status)
+ self.assertGreaterEqual(len(body), 1)
+
+ # Accept a volume transfer by alt_tenant
+ resp, body = self.alt_client.accept_volume_transfer(transfer_id,
+ auth_key)
+ self.assertEqual(202, resp.status)
+ self.alt_client.wait_for_volume_status(volume['id'], 'available')
+
+ def test_create_list_delete_volume_transfer(self):
+ # Create a volume first
+ vol_name = rand_name('-Volume-')
+ _, volume = self.client.create_volume(size=1, display_name=vol_name)
+ self.addCleanup(self.adm_client.delete_volume, volume['id'])
+ self.client.wait_for_volume_status(volume['id'], 'available')
+
+ # Create a volume transfer
+ resp, body = self.client.create_volume_transfer(volume['id'])
+ self.assertEqual(202, resp.status)
+ transfer_id = body['id']
+ self.client.wait_for_volume_status(volume['id'],
+ 'awaiting-transfer')
+
+ # List all volume transfers, there's only one in this test
+ resp, body = self.client.list_volume_transfers()
+ self.assertEqual(200, resp.status)
+ self.assertEqual(volume['id'], body[0]['volume_id'])
+
+ # Delete a volume transfer
+ resp, body = self.client.delete_volume_transfer(transfer_id)
+ self.assertEqual(202, resp.status)
+ self.client.wait_for_volume_status(volume['id'], 'available')
+
+
+class VolumesTransfersTestXML(VolumesTransfersTest):
+ _interface = "xml"
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index f2915f7..14120fe 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -16,7 +16,7 @@
# under the License.
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import services
@@ -46,7 +46,7 @@
def _volume_create_get_update_delete(self, **kwargs):
# Create a volume, Get it's details and Delete the volume
volume = {}
- v_name = rand_name('Volume')
+ v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'Test'}
# Create a volume
resp, volume = self.client.create_volume(size=1,
@@ -88,7 +88,7 @@
self.assertEqual(boot_flag, False)
# Update Volume
- new_v_name = rand_name('new-Volume')
+ new_v_name = data_utils.rand_name('new-Volume')
new_desc = 'This is the new description of volume'
resp, update_volume = \
self.client.update_volume(volume['id'],
@@ -118,7 +118,7 @@
def test_volume_get_metadata_none(self):
# Create a volume without passing metadata, get details, and delete
volume = {}
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
# Create a volume without metadata
resp, volume = self.client.create_volume(size=1,
display_name=v_name,
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 2aaa71d..4dbc88a 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -17,8 +17,7 @@
# under the License.
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.test import attr
@@ -59,7 +58,7 @@
cls.volume_list = []
cls.volume_id_list = []
for i in range(3):
- v_name = rand_name('volume')
+ v_name = data_utils.rand_name('volume')
metadata = {'Type': 'work'}
try:
resp, volume = cls.client.create_volume(size=1,
@@ -107,7 +106,7 @@
@attr(type='gate')
def test_volume_list_by_name(self):
- volume = self.volume_list[rand_int_id(0, 2)]
+ volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {'display_name': volume['display_name']}
resp, fetched_vol = self.client.list_volumes(params)
self.assertEqual(200, resp.status)
@@ -117,7 +116,7 @@
@attr(type='gate')
def test_volume_list_details_by_name(self):
- volume = self.volume_list[rand_int_id(0, 2)]
+ volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {'display_name': volume['display_name']}
resp, fetched_vol = self.client.list_volumes_with_detail(params)
self.assertEqual(200, resp.status)
@@ -145,7 +144,7 @@
@attr(type='gate')
def test_volumes_list_by_availability_zone(self):
- volume = self.volume_list[rand_int_id(0, 2)]
+ volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
params = {'availability_zone': zone}
resp, fetched_list = self.client.list_volumes(params)
@@ -156,7 +155,7 @@
@attr(type='gate')
def test_volumes_list_details_by_availability_zone(self):
- volume = self.volume_list[rand_int_id(0, 2)]
+ volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
params = {'availability_zone': zone}
resp, fetched_list = self.client.list_volumes_with_detail(params)
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index f42c2f5..928bd49 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -18,7 +18,7 @@
import uuid
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
@@ -32,7 +32,7 @@
cls.client = cls.volumes_client
# Create a test shared instance and volume for attach/detach tests
- vol_name = rand_name('Volume-')
+ vol_name = data_utils.rand_name('Volume-')
cls.volume = cls.create_volume(size=1, display_name=vol_name)
cls.client.wait_for_volume_status(cls.volume['id'], 'available')
@@ -54,7 +54,7 @@
def test_create_volume_with_invalid_size(self):
# Should not be able to create volume with invalid size
# in request
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.BadRequest, self.client.create_volume,
size='#$%', display_name=v_name, metadata=metadata)
@@ -63,7 +63,7 @@
def test_create_volume_with_out_passing_size(self):
# Should not be able to create volume without passing size
# in request
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.BadRequest, self.client.create_volume,
size='', display_name=v_name, metadata=metadata)
@@ -71,7 +71,7 @@
@attr(type=['negative', 'gate'])
def test_create_volume_with_size_zero(self):
# Should not be able to create volume with size zero
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.BadRequest, self.client.create_volume,
size='0', display_name=v_name, metadata=metadata)
@@ -79,7 +79,7 @@
@attr(type=['negative', 'gate'])
def test_create_volume_with_size_negative(self):
# Should not be able to create volume with size negative
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.BadRequest, self.client.create_volume,
size='-1', display_name=v_name, metadata=metadata)
@@ -87,7 +87,7 @@
@attr(type=['negative', 'gate'])
def test_create_volume_with_nonexistant_volume_type(self):
# Should not be able to create volume with non-existant volume type
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.create_volume,
size='1', volume_type=str(uuid.uuid4()),
@@ -96,7 +96,7 @@
@attr(type=['negative', 'gate'])
def test_create_volume_with_nonexistant_snapshot_id(self):
# Should not be able to create volume with non-existant snapshot
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.create_volume,
size='1', snapshot_id=str(uuid.uuid4()),
@@ -105,7 +105,7 @@
@attr(type=['negative', 'gate'])
def test_create_volume_with_nonexistant_source_volid(self):
# Should not be able to create volume with non-existant source volume
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.create_volume,
size='1', source_volid=str(uuid.uuid4()),
@@ -113,7 +113,7 @@
@attr(type=['negative', 'gate'])
def test_update_volume_with_nonexistant_volume_id(self):
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.update_volume,
volume_id=str(uuid.uuid4()), display_name=v_name,
@@ -121,7 +121,7 @@
@attr(type=['negative', 'gate'])
def test_update_volume_with_invalid_volume_id(self):
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.update_volume,
volume_id='#$%%&^&^', display_name=v_name,
@@ -129,7 +129,7 @@
@attr(type=['negative', 'gate'])
def test_update_volume_with_empty_volume_id(self):
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
self.assertRaises(exceptions.NotFound, self.client.update_volume,
volume_id='', display_name=v_name,
@@ -159,7 +159,7 @@
@attr(type=['negative', 'gate'])
def test_attach_volumes_with_nonexistent_volume_id(self):
- srv_name = rand_name('Instance-')
+ srv_name = data_utils.rand_name('Instance-')
resp, server = self.servers_client.create_server(srv_name,
self.image_ref,
self.flavor_ref)
@@ -239,7 +239,7 @@
@attr(type=['negative', 'gate'])
def test_list_volumes_with_nonexistent_name(self):
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
params = {'display_name': v_name}
resp, fetched_volume = self.client.list_volumes(params)
self.assertEqual(200, resp.status)
@@ -247,7 +247,7 @@
@attr(type=['negative', 'gate'])
def test_list_volumes_detail_with_nonexistent_name(self):
- v_name = rand_name('Volume-')
+ v_name = data_utils.rand_name('Volume-')
params = {'display_name': v_name}
resp, fetched_volume = self.client.list_volumes_with_detail(params)
self.assertEqual(200, resp.status)
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 6b186e5..99e8de7 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -13,7 +13,7 @@
# under the License.
from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.test import attr
@@ -40,7 +40,7 @@
@attr(type='gate')
def test_snapshot_create_get_list_update_delete(self):
# Create a snapshot
- s_name = rand_name('snap')
+ s_name = data_utils.rand_name('snap')
snapshot = self.create_snapshot(self.volume_origin['id'],
display_name=s_name)
@@ -59,7 +59,7 @@
self.assertIn(tracking_data, snaps_data)
# Updates snapshot with new values
- new_s_name = rand_name('new-snap')
+ new_s_name = data_utils.rand_name('new-snap')
new_desc = 'This is the new description of snapshot.'
resp, update_snapshot = \
self.snapshots_client.update_snapshot(snapshot['id'],
diff --git a/tempest/clients.py b/tempest/clients.py
index a52ed5d..9029d5f 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -35,6 +35,8 @@
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
@@ -71,6 +73,8 @@
FloatingIPsClientXML
from tempest.services.compute.xml.hypervisor_client import HypervisorClientXML
from tempest.services.compute.xml.images_client import ImagesClientXML
+from tempest.services.compute.xml.instance_usage_audit_log_client import \
+ InstanceUsagesAuditLogClientXML
from tempest.services.compute.xml.interfaces_client import \
InterfacesClientXML
from tempest.services.compute.xml.keypairs_client import KeyPairsClientXML
@@ -217,6 +221,8 @@
self.token_v3_client = V3TokenClientXML(*client_args)
self.network_client = NetworkClientXML(*client_args)
self.credentials_client = CredentialsClientXML(*client_args)
+ self.instance_usages_audit_log_client = \
+ InstanceUsagesAuditLogClientXML(*client_args)
if client_args_v3_auth:
self.servers_client_v3_auth = ServersClientXML(
@@ -259,6 +265,8 @@
self.token_v3_client = V3TokenClientJSON(*client_args)
self.network_client = NetworkClientJSON(*client_args)
self.credentials_client = CredentialsClientJSON(*client_args)
+ self.instance_usages_audit_log_client = \
+ InstanceUsagesAuditLogClientJSON(*client_args)
if client_args_v3_auth:
self.servers_client_v3_auth = ServersClientJSON(
diff --git a/tempest/common/generate_sample_tempest.py b/tempest/common/generate_sample_tempest.py
new file mode 100644
index 0000000..3811088
--- /dev/null
+++ b/tempest/common/generate_sample_tempest.py
@@ -0,0 +1,26 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 sys
+
+from tempest import config
+from tempest.openstack.common.config import generator
+
+
+config.TempestConfig()
+generator.generate(sys.argv[1:])
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 8c82ec0..9459590 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -20,7 +20,7 @@
import neutronclient.v2_0.client as neutronclient
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
@@ -147,17 +147,17 @@
self.identity_admin_client.tenants.delete(tenant)
def _create_creds(self, suffix=None, admin=False):
- rand_name_root = rand_name(self.name)
+ data_utils.rand_name_root = data_utils.rand_name(self.name)
if suffix:
- rand_name_root += suffix
- tenant_name = rand_name_root + "-tenant"
+ data_utils.rand_name_root += suffix
+ tenant_name = data_utils.rand_name_root + "-tenant"
tenant_desc = tenant_name + "-desc"
tenant = self._create_tenant(name=tenant_name,
description=tenant_desc)
if suffix:
- rand_name_root += suffix
- username = rand_name_root + "-user"
- email = rand_name_root + "@example.com"
+ data_utils.rand_name_root += suffix
+ username = data_utils.rand_name_root + "-user"
+ email = data_utils.rand_name_root + "@example.com"
user = self._create_user(username, self.password,
tenant, email)
if admin:
@@ -197,13 +197,13 @@
network = None
subnet = None
router = None
- rand_name_root = rand_name(self.name)
- network_name = rand_name_root + "-network"
+ data_utils.rand_name_root = data_utils.rand_name(self.name)
+ network_name = data_utils.rand_name_root + "-network"
network = self._create_network(network_name, tenant_id)
try:
- subnet_name = rand_name_root + "-subnet"
+ subnet_name = data_utils.rand_name_root + "-subnet"
subnet = self._create_subnet(subnet_name, tenant_id, network['id'])
- router_name = rand_name_root + "-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:
diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py
index 3eaa203..742a354 100644
--- a/tempest/common/ssh.py
+++ b/tempest/common/ssh.py
@@ -66,7 +66,8 @@
_timeout = False
break
except (socket.error,
- paramiko.AuthenticationException):
+ paramiko.AuthenticationException,
+ paramiko.SSHException):
time.sleep(bsleep)
bsleep *= backoff
continue
diff --git a/tempest/config.py b/tempest/config.py
index ff8a170..009147b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -411,6 +411,9 @@
cfg.BoolOpt('accounts_quotas',
default=True,
help="Set to True if the Account Quota middleware is enabled"),
+ cfg.BoolOpt('crossdomain',
+ default=True,
+ help="Set to True if the Crossdomain middleware is enabled"),
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index d92a0c8..7848afc 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -34,7 +34,7 @@
from tempest.api.network import common as net_common
from tempest.common import isolated_creds
from tempest.common import ssh
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
from tempest import exceptions
import tempest.manager
@@ -399,7 +399,7 @@
if client is None:
client = self.compute_client
if name is None:
- name = rand_name('scenario-server-')
+ name = data_utils.rand_name('scenario-server-')
if image is None:
image = self.config.compute.image_ref
if flavor is None:
@@ -423,7 +423,7 @@
if client is None:
client = self.volume_client
if name is None:
- name = rand_name('scenario-volume-')
+ name = data_utils.rand_name('scenario-volume-')
LOG.debug("Creating a volume (size: %s, name: %s)", size, name)
volume = client.volumes.create(size=size, display_name=name,
snapshot_id=snapshot_id,
@@ -441,7 +441,7 @@
if image_client is None:
image_client = self.image_client
if name is None:
- name = rand_name('scenario-snapshot-')
+ name = data_utils.rand_name('scenario-snapshot-')
LOG.debug("Creating a snapshot image for server: %s", server.name)
image_id = compute_client.servers.create_image(server, name)
self.addCleanup(image_client.images.delete, image_id)
@@ -456,7 +456,7 @@
if client is None:
client = self.compute_client
if name is None:
- name = rand_name('scenario-keypair-')
+ name = data_utils.rand_name('scenario-keypair-')
keypair = client.keypairs.create(name)
self.assertEqual(keypair.name, name)
self.set_resource(name, keypair)
@@ -510,7 +510,7 @@
if client is None:
client = self.compute_client
# Create security group
- sg_name = rand_name(namestart)
+ sg_name = data_utils.rand_name(namestart)
sg_desc = sg_name + " description"
secgroup = client.security_groups.create(sg_name, sg_desc)
self.assertEqual(secgroup.name, sg_name)
@@ -523,7 +523,7 @@
return secgroup
def _create_network(self, tenant_id, namestart='network-smoke-'):
- name = rand_name(namestart)
+ name = data_utils.rand_name(namestart)
body = dict(
network=dict(
name=name,
@@ -579,11 +579,11 @@
subnet = net_common.DeletableSubnet(client=self.network_client,
**result['subnet'])
self.assertEqual(subnet.cidr, str(subnet_cidr))
- self.set_resource(rand_name(namestart), subnet)
+ self.set_resource(data_utils.rand_name(namestart), subnet)
return subnet
def _create_port(self, network, namestart='port-quotatest-'):
- name = rand_name(namestart)
+ name = data_utils.rand_name(namestart)
body = dict(
port=dict(name=name,
network_id=network.id,
@@ -612,7 +612,7 @@
floating_ip = net_common.DeletableFloatingIp(
client=self.network_client,
**result['floatingip'])
- self.set_resource(rand_name('floatingip-'), floating_ip)
+ self.set_resource(data_utils.rand_name('floatingip-'), floating_ip)
return floating_ip
def _ping_ip_address(self, ip_address):
@@ -675,7 +675,7 @@
@classmethod
def _stack_rand_name(cls):
- return rand_name(cls.__name__ + '-')
+ return data_utils.rand_name(cls.__name__ + '-')
@classmethod
def _get_default_network(cls):
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 22c543b..30c223f 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest.test import services
@@ -47,7 +47,7 @@
self.volume_client.volumes, volume_id, status)
def _image_create(self, name, fmt, path, properties={}):
- name = rand_name('%s-' % name)
+ name = data_utils.rand_name('%s-' % name)
image_file = open(path, 'rb')
self.addCleanup(image_file.close)
params = {
@@ -82,7 +82,7 @@
properties=properties)
def nova_boot(self):
- name = rand_name('scenario-server-')
+ name = data_utils.rand_name('scenario-server-')
client = self.compute_client
flavor_id = self.config.compute.flavor_ref
secgroup = self._create_security_group()
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 752ff6f..9cc8541 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest.test import services
@@ -48,7 +48,7 @@
self.volume_client.volumes, volume_id, status)
def _image_create(self, name, fmt, path, properties={}):
- name = rand_name('%s-' % name)
+ name = data_utils.rand_name('%s-' % name)
image_file = open(path, 'rb')
self.addCleanup(image_file.close)
params = {
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 6cd9fe8..a7618b1 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -18,7 +18,7 @@
from tempest.api.network import common as net_common
from tempest.common import debug
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import config
from tempest.openstack.common import log as logging
from tempest.scenario import manager
@@ -144,7 +144,7 @@
"'public_network_id' has been defined.")
def _create_router(self, tenant_id, namestart='router-smoke-'):
- name = rand_name(namestart)
+ name = data_utils.rand_name(namestart)
body = dict(
router=dict(
name=name,
@@ -161,7 +161,7 @@
def _create_keypairs(self):
self.keypairs[self.tenant_id] = self.create_keypair(
- name=rand_name('keypair-smoke-'))
+ name=data_utils.rand_name('keypair-smoke-'))
def _create_security_groups(self):
self.security_groups[self.tenant_id] = self._create_security_group()
@@ -214,7 +214,7 @@
def _create_servers(self):
for i, network in enumerate(self.networks):
- name = rand_name('server-smoke-%d-' % i)
+ name = data_utils.rand_name('server-smoke-%d-' % i)
server = self._create_server(name, network)
self.servers.append(server)
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index c32d49d..0b08f9c 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest.test import services
@@ -41,7 +41,7 @@
self.keypair = self.create_keypair()
def create_security_group(self):
- sg_name = rand_name('secgroup-smoke')
+ sg_name = data_utils.rand_name('secgroup-smoke')
sg_desc = sg_name + " description"
self.secgroup = self.compute_client.security_groups.create(sg_name,
sg_desc)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 6812d64..a8cedc7 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -19,7 +19,7 @@
from cinderclient import exceptions as cinder_exceptions
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.scenario import manager
@@ -75,7 +75,7 @@
return linux_client.ssh_client
def _create_volume_snapshot(self, volume):
- snapshot_name = rand_name('scenario-snapshot-')
+ snapshot_name = data_utils.rand_name('scenario-snapshot-')
volume_snapshots = self.volume_client.volume_snapshots
snapshot = volume_snapshots.create(
volume.id, display_name=snapshot_name)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index d12cd56..84846c1 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.scenario import manager
from tempest.test import services
@@ -34,7 +34,7 @@
def _create_volume_from_image(self):
img_uuid = self.config.compute.image_ref
- vol_name = rand_name('volume-origin')
+ vol_name = data_utils.rand_name('volume-origin')
return self.create_volume(name=vol_name, imageRef=img_uuid)
def _boot_instance_from_volume(self, vol_id, keypair):
@@ -53,7 +53,7 @@
def _create_snapshot_from_volume(self, vol_id):
volume_snapshots = self.volume_client.volume_snapshots
- snap_name = rand_name('snapshot')
+ snap_name = data_utils.rand_name('snapshot')
snap = volume_snapshots.create(volume_id=vol_id,
force=True,
display_name=snap_name)
@@ -64,7 +64,7 @@
return snap
def _create_volume_from_snapshot(self, snap_id):
- vol_name = rand_name('volume')
+ vol_name = data_utils.rand_name('volume')
return self.create_volume(name=vol_name, snapshot_id=snap_id)
def _stop_instances(self, instances):
@@ -88,7 +88,7 @@
def _ssh_to_server(self, server, keypair):
if self.config.compute.use_floatingip_for_ssh:
floating_ip = self.compute_client.floating_ips.create()
- fip_name = rand_name('scenario-fip')
+ fip_name = data_utils.rand_name('scenario-fip')
self.set_resource(fip_name, floating_ip)
server.add_floating_ip(floating_ip)
ip = floating_ip.ip
@@ -104,7 +104,7 @@
return ssh_client.exec_command('cat /tmp/text')
def _write_text(self, ssh_client):
- text = rand_name('text-')
+ text = data_utils.rand_name('text-')
ssh_client.exec_command('echo "%s" > /tmp/text; sync' % (text))
return self._get_content(ssh_client)
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
new file mode 100644
index 0000000..07ce1bb
--- /dev/null
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.common.rest_client import RestClient
+
+
+class InstanceUsagesAuditLogClientJSON(RestClient):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(InstanceUsagesAuditLogClientJSON, self).__init__(
+ config, username, password, auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def list_instance_usage_audit_logs(self):
+ url = 'os-instance_usage_audit_log'
+ resp, body = self.get(url)
+ body = json.loads(body)
+ return 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)
+ return resp, body["instance_usage_audit_log"]
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 87512fb..3c6a40f 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -210,6 +210,21 @@
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)
+ return 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.
+ """
+ return self.delete("servers/%s/os-server-password" %
+ str(server_id))
+
def reboot(self, server_id, reboot_type):
"""Reboots a server."""
return self.action(server_id, 'reboot', None, type=reboot_type)
diff --git a/tempest/services/compute/v3/json/availability_zone_client.py b/tempest/services/compute/v3/json/availability_zone_client.py
new file mode 100644
index 0000000..b11871b
--- /dev/null
+++ b/tempest/services/compute/v3/json/availability_zone_client.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.common.rest_client import RestClient
+
+
+class AvailabilityZoneClientJSON(RestClient):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(AvailabilityZoneClientJSON, self).__init__(config, username,
+ password, auth_url,
+ tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def get_availability_zone_list(self):
+ resp, body = self.get('os-availability-zone')
+ body = json.loads(body)
+ return resp, body['availabilityZoneInfo']
+
+ def get_availability_zone_list_detail(self):
+ resp, body = self.get('os-availability-zone/detail')
+ body = json.loads(body)
+ return resp, body['availabilityZoneInfo']
diff --git a/tempest/services/compute/v3/json/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
new file mode 100644
index 0000000..06e6476
--- /dev/null
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -0,0 +1,80 @@
+# 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.common.rest_client import RestClient
+from tempest import exceptions
+
+
+class InterfacesClientJSON(RestClient):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(InterfacesClientJSON, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def list_interfaces(self, server):
+ resp, body = self.get('servers/%s/os-interface' % server)
+ body = json.loads(body)
+ return 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['port_id'] = port_id
+ if network_id:
+ post_body['net_id'] = network_id
+ if fixed_ip:
+ post_body['fixed_ips'] = [dict(ip_address=fixed_ip)]
+ post_body = json.dumps(post_body)
+ resp, body = self.post('servers/%s/os-interface' % server,
+ headers=self.headers,
+ body=post_body)
+ body = json.loads(body)
+ return 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)
+ return resp, body['interfaceAttachment']
+
+ def delete_interface(self, server, port_id):
+ resp, body = self.delete('servers/%s/os-interface/%s' % (server,
+ port_id))
+ return resp, body
+
+ def wait_for_interface_status(self, server, port_id, status):
+ """Waits for a interface to reach a given status."""
+ resp, 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)
+ resp, 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 within '
+ 'the required time (%s s).' %
+ (port_id, status, self.build_timeout))
+ raise exceptions.TimeoutException(message)
+
+ return resp, body
diff --git a/tempest/services/compute/v3/xml/availability_zone_client.py b/tempest/services/compute/v3/xml/availability_zone_client.py
new file mode 100644
index 0000000..ae93774
--- /dev/null
+++ b/tempest/services/compute/v3/xml/availability_zone_client.py
@@ -0,0 +1,43 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class AvailabilityZoneClientXML(RestClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(AvailabilityZoneClientXML, self).__init__(config, username,
+ password, auth_url,
+ tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def _parse_array(self, node):
+ return [xml_to_json(x) for x in node]
+
+ def get_availability_zone_list(self):
+ resp, body = self.get('os-availability-zone', self.headers)
+ availability_zone = self._parse_array(etree.fromstring(body))
+ return resp, availability_zone
+
+ def get_availability_zone_list_detail(self):
+ resp, body = self.get('os-availability-zone/detail', self.headers)
+ availability_zone = self._parse_array(etree.fromstring(body))
+ return resp, availability_zone
diff --git a/tempest/services/compute/v3/xml/interfaces_client.py b/tempest/services/compute/v3/xml/interfaces_client.py
new file mode 100644
index 0000000..a84e0bd
--- /dev/null
+++ b/tempest/services/compute/v3/xml/interfaces_client.py
@@ -0,0 +1,105 @@
+# 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 time
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest import exceptions
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import Text
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class InterfacesClientXML(RestClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(InterfacesClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def _process_xml_interface(self, node):
+ iface = xml_to_json(node)
+ # NOTE(danms): if multiple addresses per interface is ever required,
+ # xml_to_json will need to be fixed or replaced in this case
+ iface['fixed_ips'] = [dict(iface['fixed_ips']['fixed_ip'].items())]
+ return iface
+
+ def list_interfaces(self, server):
+ resp, body = self.get('servers/%s/os-interface' % server, self.headers)
+ node = etree.fromstring(body)
+ interfaces = [self._process_xml_interface(x)
+ for x in node.getchildren()]
+ return resp, interfaces
+
+ def create_interface(self, server, port_id=None, network_id=None,
+ fixed_ip=None):
+ doc = Document()
+ iface = Element('interfaceAttachment')
+ if port_id:
+ _port_id = Element('port_id')
+ _port_id.append(Text(port_id))
+ iface.append(_port_id)
+ if network_id:
+ _network_id = Element('net_id')
+ _network_id.append(Text(network_id))
+ iface.append(_network_id)
+ if fixed_ip:
+ _fixed_ips = Element('fixed_ips')
+ _fixed_ip = Element('fixed_ip')
+ _ip_address = Element('ip_address')
+ _ip_address.append(Text(fixed_ip))
+ _fixed_ip.append(_ip_address)
+ _fixed_ips.append(_fixed_ip)
+ iface.append(_fixed_ips)
+ doc.append(iface)
+ resp, body = self.post('servers/%s/os-interface' % server,
+ headers=self.headers,
+ body=str(doc))
+ body = self._process_xml_interface(etree.fromstring(body))
+ return resp, body
+
+ def show_interface(self, server, port_id):
+ resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id),
+ self.headers)
+ body = self._process_xml_interface(etree.fromstring(body))
+ return resp, body
+
+ def delete_interface(self, server, port_id):
+ resp, body = self.delete('servers/%s/os-interface/%s' % (server,
+ port_id))
+ return resp, body
+
+ def wait_for_interface_status(self, server, port_id, status):
+ """Waits for a interface to reach a given status."""
+ resp, 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)
+ resp, 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 within '
+ 'the required time (%s s).' %
+ (port_id, status, self.build_timeout))
+ raise exceptions.TimeoutException(message)
+ return resp, body
diff --git a/tempest/services/compute/xml/instance_usage_audit_log_client.py b/tempest/services/compute/xml/instance_usage_audit_log_client.py
new file mode 100644
index 0000000..175997b
--- /dev/null
+++ b/tempest/services/compute/xml/instance_usage_audit_log_client.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class InstanceUsagesAuditLogClientXML(RestClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(InstanceUsagesAuditLogClientXML, self).__init__(
+ config, username, password, auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def list_instance_usage_audit_logs(self):
+ url = 'os-instance_usage_audit_log'
+ resp, body = self.get(url, self.headers)
+ instance_usage_audit_logs = xml_to_json(etree.fromstring(body))
+ return resp, 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, self.headers)
+ instance_usage_audit_log = xml_to_json(etree.fromstring(body))
+ return resp, instance_usage_audit_log
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index 3319238..3e5413c 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -431,6 +431,21 @@
return self.action(server_id, "changePassword", None,
adminPass=password)
+ def get_password(self, server_id):
+ resp, body = self.get("servers/%s/os-server-password" %
+ str(server_id), self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ return 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.
+ """
+ return self.delete("servers/%s/os-server-password" %
+ str(server_id))
+
def reboot(self, server_id, reboot_type):
return self.action(server_id, "reboot", None, type=reboot_type)
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 10ba3fd..5d980eb 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -131,3 +131,21 @@
except exceptions.NotFound:
return True
return False
+
+ 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.headers)
+ return 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.headers)
+ return resp, body
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 670492a..93b28a2 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -201,3 +201,48 @@
resp, body = self.post('volumes/%s/action' % volume_id, post_body,
self.headers)
return 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,
+ self.headers)
+ body = json.loads(body)
+ return resp, body['transfer']
+
+ def get_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, self.headers)
+ body = json.loads(body)
+ return 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)
+ return resp, body['transfers']
+
+ def delete_volume_transfer(self, transfer_id):
+ """Delete a volume transfer."""
+ return self.delete("os-volume-transfer/%s" % str(transfer_id))
+
+ 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, self.headers)
+ body = json.loads(body)
+ return resp, body['transfer']
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index b7ba56b..5d59b07 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -147,3 +147,26 @@
except exceptions.NotFound:
return True
return False
+
+ def reset_snapshot_status(self, snapshot_id, status):
+ """Reset the specified snapshot's status."""
+ post_body = Element("os-reset_status",
+ status=status
+ )
+ url = 'snapshots/%s/action' % str(snapshot_id)
+ resp, body = self.post(url, str(Document(post_body)), self.headers)
+ if body:
+ body = xml_to_json(etree.fromstring(body))
+ return resp, body
+
+ def update_snapshot_status(self, snapshot_id, status, progress):
+ """Update the specified snapshot's status."""
+ post_body = Element("os-update_snapshot_status",
+ status=status,
+ progress=progress
+ )
+ url = 'snapshots/%s/action' % str(snapshot_id)
+ resp, body = self.post(url, str(Document(post_body)), self.headers)
+ if body:
+ body = xml_to_json(etree.fromstring(body))
+ return resp, body
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 0edf7f3..b1e54ed 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -284,3 +284,56 @@
if body:
body = xml_to_json(etree.fromstring(body))
return resp, body
+
+ def create_volume_transfer(self, vol_id, display_name=None):
+ """Create a volume transfer."""
+ post_body = Element("transfer",
+ volume_id=vol_id)
+ if display_name:
+ post_body.add_attr('name', display_name)
+ resp, body = self.post('os-volume-transfer',
+ str(Document(post_body)),
+ self.headers)
+ volume = xml_to_json(etree.fromstring(body))
+ return resp, volume
+
+ def get_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, self.headers)
+ volume = xml_to_json(etree.fromstring(body))
+ return resp, volume
+
+ 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, self.headers)
+ body = etree.fromstring(body)
+ volumes = []
+ if body is not None:
+ volumes += [self._parse_volume_transfer(vol) for vol in list(body)]
+ return resp, volumes
+
+ def _parse_volume_transfer(self, body):
+ vol = dict((attr, body.get(attr)) for attr in body.keys())
+ for child in body.getchildren():
+ tag = child.tag
+ if tag.startswith("{"):
+ tag = tag.split("}", 1)
+ vol[tag] = xml_to_json(child)
+ return vol
+
+ def delete_volume_transfer(self, transfer_id):
+ """Delete a volume transfer."""
+ return self.delete("os-volume-transfer/%s" % str(transfer_id))
+
+ def accept_volume_transfer(self, transfer_id, transfer_auth_key):
+ """Accept a volume transfer."""
+ post_body = Element("accept", auth_key=transfer_auth_key)
+ url = 'os-volume-transfer/%s/accept' % transfer_id
+ resp, body = self.post(url, str(Document(post_body)), self.headers)
+ volume = xml_to_json(etree.fromstring(body))
+ return resp, volume
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 1a1e30b..84c7cf5 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
import tempest.stress.stressaction as stressaction
@@ -23,7 +23,7 @@
self.flavor = self.manager.config.compute.flavor_ref
def run(self):
- name = rand_name("instance")
+ name = data_utils.rand_name("instance")
self.logger.info("creating %s" % name)
resp, server = self.manager.servers_client.create_server(
name, self.image, self.flavor)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 36ef023..74a9739 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -15,7 +15,7 @@
import socket
import subprocess
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
import tempest.stress.stressaction as stressaction
import tempest.test
@@ -64,7 +64,7 @@
raise RuntimeError("Cannot ping the machine.")
def _create_vm(self):
- self.name = name = rand_name("instance")
+ self.name = name = data_utils.rand_name("instance")
servers_client = self.manager.servers_client
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
@@ -87,8 +87,8 @@
def _create_sec_group(self):
sec_grp_cli = self.manager.security_groups_client
- s_name = rand_name('sec_grp-')
- s_description = rand_name('desc-')
+ s_name = data_utils.rand_name('sec_grp-')
+ s_description = data_utils.rand_name('desc-')
_, _sec_grp = sec_grp_cli.create_security_group(s_name,
s_description)
self.sec_grp = _sec_grp['id']
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index a7b872f..e6fcb81 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
import tempest.stress.stressaction as stressaction
@@ -23,7 +23,7 @@
def run(self):
# Step 1: create volume
- name = rand_name("volume")
+ name = data_utils.rand_name("volume")
self.logger.info("creating volume: %s" % name)
resp, volume = self.manager.volumes_client.create_volume(size=1,
display_name=
@@ -34,7 +34,7 @@
self.logger.info("created volume: %s" % volume['id'])
# Step 2: create vm instance
- vm_name = rand_name("instance")
+ vm_name = data_utils.rand_name("instance")
self.logger.info("creating vm: %s" % vm_name)
resp, server = self.manager.servers_client.create_server(
vm_name, self.image, self.flavor)
diff --git a/tempest/stress/actions/volume_create_delete.py b/tempest/stress/actions/volume_create_delete.py
index e29d9c4..4e75be0 100644
--- a/tempest/stress/actions/volume_create_delete.py
+++ b/tempest/stress/actions/volume_create_delete.py
@@ -10,14 +10,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
import tempest.stress.stressaction as stressaction
class VolumeCreateDeleteTest(stressaction.StressAction):
def run(self):
- name = rand_name("volume")
+ name = data_utils.rand_name("volume")
self.logger.info("creating %s" % name)
volumes_client = self.manager.volumes_client
resp, volume = volumes_client.create_volume(size=1,
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index b5cab68..d37ab6d 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -19,25 +19,18 @@
from tempest import clients
from tempest.common import ssh
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.openstack.common import importutils
from tempest.openstack.common import log as logging
from tempest.stress import cleanup
-admin_manager = clients.AdminManager()
-
LOG = logging.getLogger(__name__)
processes = []
-def do_ssh(command, host):
- username = admin_manager.config.stress.target_ssh_user
- key_filename = admin_manager.config.stress.target_private_key_path
- if not (username and key_filename):
- LOG.error('username and key_filename should not be empty')
- return None
- ssh_client = ssh.Client(host, username, key_filename=key_filename)
+def do_ssh(command, host, ssh_user, ssh_key=None):
+ ssh_client = ssh.Client(host, ssh_user, key_filename=ssh_key)
try:
return ssh_client.exec_command(command)
except exceptions.SSHExecCommandFailed:
@@ -46,14 +39,14 @@
return None
-def _get_compute_nodes(controller):
+def _get_compute_nodes(controller, ssh_user, ssh_key=None):
"""
Returns a list of active compute nodes. List is generated by running
nova-manage on the controller.
"""
nodes = []
cmd = "nova-manage service list | grep ^nova-compute"
- output = do_ssh(cmd, controller)
+ output = do_ssh(cmd, controller, ssh_user, ssh_key)
if not output:
return nodes
# For example: nova-compute xg11eth0 nova enabled :-) 2011-10-31 18:57:46
@@ -65,14 +58,15 @@
return nodes
-def _has_error_in_logs(logfiles, nodes, stop_on_error=False):
+def _has_error_in_logs(logfiles, nodes, ssh_user, ssh_key=None,
+ stop_on_error=False):
"""
Detect errors in the nova log files on the controller and compute nodes.
"""
grep = 'egrep "ERROR|TRACE" %s' % logfiles
ret = False
for node in nodes:
- errors = do_ssh(grep, node)
+ errors = do_ssh(grep, node, ssh_user, ssh_key)
if len(errors) > 0:
LOG.error('%s: %s' % (node, errors))
ret = True
@@ -88,18 +82,17 @@
terminate_all_processes()
-def terminate_all_processes():
+def terminate_all_processes(check_interval=20):
"""
Goes through the process list and terminates all child processes.
"""
- log_check_interval = int(admin_manager.config.stress.log_check_interval)
for process in processes:
if process['process'].is_alive():
try:
process['process'].terminate()
except Exception:
pass
- time.sleep(log_check_interval)
+ time.sleep(check_interval)
for process in processes:
if process['process'].is_alive():
try:
@@ -115,15 +108,19 @@
"""
Workload driver. Executes an action function against a nova-cluster.
"""
+ admin_manager = clients.AdminManager()
+
+ ssh_user = admin_manager.config.stress.target_ssh_user
+ ssh_key = admin_manager.config.stress.target_private_key_path
logfiles = admin_manager.config.stress.target_logfiles
log_check_interval = int(admin_manager.config.stress.log_check_interval)
default_thread_num = int(admin_manager.config.stress.
default_thread_number_per_action)
if logfiles:
controller = admin_manager.config.stress.target_controller
- computes = _get_compute_nodes(controller)
+ computes = _get_compute_nodes(controller, ssh_user, ssh_key)
for node in computes:
- do_ssh("rm -f %s" % logfiles, node)
+ do_ssh("rm -f %s" % logfiles, node, ssh_user, ssh_key)
for test in tests:
if test.get('use_admin', False):
manager = admin_manager
@@ -131,8 +128,8 @@
manager = clients.Manager()
for p_number in xrange(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
- username = rand_name("stress_user")
- tenant_name = rand_name("stress_tenant")
+ username = data_utils.rand_name("stress_user")
+ tenant_name = data_utils.rand_name("stress_tenant")
password = "pass"
identity_client = admin_manager.identity_client
_, tenant = identity_client.create_tenant(name=tenant_name)
@@ -196,7 +193,8 @@
if not logfiles:
continue
- if _has_error_in_logs(logfiles, computes, stop_on_error):
+ if _has_error_in_logs(logfiles, computes, ssh_user, ssh_key,
+ stop_on_error):
had_errors = True
break
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 0f455e1..9ded9da 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -18,7 +18,7 @@
from boto import exception
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
from tempest import exceptions
from tempest.openstack.common import log as logging
@@ -50,8 +50,8 @@
aki_manifest = config.boto.aki_manifest
ari_manifest = config.boto.ari_manifest
cls.instance_type = config.boto.instance_type
- cls.bucket_name = rand_name("s3bucket-")
- cls.keypair_name = rand_name("keypair-")
+ cls.bucket_name = data_utils.rand_name("s3bucket-")
+ cls.keypair_name = data_utils.rand_name("keypair-")
cls.keypair = cls.ec2_client.create_key_pair(cls.keypair_name)
cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
cls.keypair_name)
@@ -61,13 +61,13 @@
cls.bucket_name)
s3_upload_dir(bucket, cls.materials_path)
cls.images = {"ami":
- {"name": rand_name("ami-name-"),
+ {"name": data_utils.rand_name("ami-name-"),
"location": cls.bucket_name + "/" + ami_manifest},
"aki":
- {"name": rand_name("aki-name-"),
+ {"name": data_utils.rand_name("aki-name-"),
"location": cls.bucket_name + "/" + aki_manifest},
"ari":
- {"name": rand_name("ari-name-"),
+ {"name": data_utils.rand_name("ari-name-"),
"location": cls.bucket_name + "/" + ari_manifest}}
for image in cls.images.itervalues():
image["image_id"] = cls.ec2_client.register_image(
@@ -238,7 +238,7 @@
def test_integration_1(self):
# EC2 1. integration test (not strict)
image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
- sec_group_name = rand_name("securitygroup-")
+ sec_group_name = data_utils.rand_name("securitygroup-")
group_desc = sec_group_name + " security group description "
security_group = self.ec2_client.create_security_group(sec_group_name,
group_desc)
@@ -285,7 +285,7 @@
ssh = RemoteClient(address.public_ip,
self.os.config.compute.ssh_user,
pkey=self.keypair.material)
- text = rand_name("Pattern text for console output -")
+ text = data_utils.rand_name("Pattern text for console output -")
resp = ssh.write_to_console(text)
self.assertFalse(resp)
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index 5592d8c..41db709 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -16,7 +16,7 @@
# under the License.
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import skip_because
from tempest.thirdparty.boto.test import BotoTestCase
@@ -40,7 +40,7 @@
@attr(type='smoke')
def test_create_ec2_keypair(self):
# EC2 create KeyPair
- key_name = rand_name("keypair-")
+ key_name = data_utils.rand_name("keypair-")
self.addResourceCleanUp(self.client.delete_key_pair, key_name)
keypair = self.client.create_key_pair(key_name)
self.assertTrue(compare_key_pairs(keypair,
@@ -50,7 +50,7 @@
@attr(type='smoke')
def test_delete_ec2_keypair(self):
# EC2 delete KeyPair
- key_name = rand_name("keypair-")
+ key_name = data_utils.rand_name("keypair-")
self.client.create_key_pair(key_name)
self.client.delete_key_pair(key_name)
self.assertEqual(None, self.client.get_key_pair(key_name))
@@ -58,7 +58,7 @@
@attr(type='smoke')
def test_get_ec2_keypair(self):
# EC2 get KeyPair
- key_name = rand_name("keypair-")
+ key_name = data_utils.rand_name("keypair-")
self.addResourceCleanUp(self.client.delete_key_pair, key_name)
keypair = self.client.create_key_pair(key_name)
self.assertTrue(compare_key_pairs(keypair,
@@ -67,7 +67,7 @@
@attr(type='smoke')
def test_duplicate_ec2_keypair(self):
# EC2 duplicate KeyPair
- key_name = rand_name("keypair-")
+ key_name = data_utils.rand_name("keypair-")
self.addResourceCleanUp(self.client.delete_key_pair, key_name)
keypair = self.client.create_key_pair(key_name)
self.assertBotoError(self.ec.client.InvalidKeyPair.Duplicate,
diff --git a/tempest/thirdparty/boto/test_ec2_security_groups.py b/tempest/thirdparty/boto/test_ec2_security_groups.py
index 3b10cfa..e8c6466 100644
--- a/tempest/thirdparty/boto/test_ec2_security_groups.py
+++ b/tempest/thirdparty/boto/test_ec2_security_groups.py
@@ -16,7 +16,7 @@
# under the License.
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.thirdparty.boto.test import BotoTestCase
@@ -32,7 +32,7 @@
@attr(type='smoke')
def test_create_authorize_security_group(self):
# EC2 Create, authorize/revoke security group
- group_name = rand_name("securty_group-")
+ group_name = data_utils.rand_name("securty_group-")
group_description = group_name + " security group description "
group = self.client.create_security_group(group_name,
group_description)
diff --git a/tempest/thirdparty/boto/test_s3_buckets.py b/tempest/thirdparty/boto/test_s3_buckets.py
index 1a8fbe0..56ee9e3 100644
--- a/tempest/thirdparty/boto/test_s3_buckets.py
+++ b/tempest/thirdparty/boto/test_s3_buckets.py
@@ -16,7 +16,7 @@
# under the License.
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.test import skip_because
from tempest.thirdparty.boto.test import BotoTestCase
@@ -34,7 +34,7 @@
@attr(type='smoke')
def test_create_and_get_delete_bucket(self):
# S3 Create, get and delete bucket
- bucket_name = rand_name("s3bucket-")
+ bucket_name = data_utils.rand_name("s3bucket-")
cleanup_key = self.addResourceCleanUp(self.client.delete_bucket,
bucket_name)
bucket = self.client.create_bucket(bucket_name)
diff --git a/tempest/thirdparty/boto/test_s3_ec2_images.py b/tempest/thirdparty/boto/test_s3_ec2_images.py
index aaf2569..2e7525a 100644
--- a/tempest/thirdparty/boto/test_s3_ec2_images.py
+++ b/tempest/thirdparty/boto/test_s3_ec2_images.py
@@ -18,7 +18,7 @@
import os
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.thirdparty.boto.test import BotoTestCase
from tempest.thirdparty.boto.utils.s3 import s3_upload_dir
@@ -43,7 +43,7 @@
cls.ami_path = cls.materials_path + os.sep + cls.ami_manifest
cls.aki_path = cls.materials_path + os.sep + cls.aki_manifest
cls.ari_path = cls.materials_path + os.sep + cls.ari_manifest
- cls.bucket_name = rand_name("bucket-")
+ cls.bucket_name = data_utils.rand_name("bucket-")
bucket = cls.s3_client.create_bucket(cls.bucket_name)
cls.addResourceCleanUp(cls.destroy_bucket,
cls.s3_client.connection_data,
@@ -53,7 +53,7 @@
@attr(type='smoke')
def test_register_get_deregister_ami_image(self):
# Register and deregister ami image
- image = {"name": rand_name("ami-name-"),
+ image = {"name": data_utils.rand_name("ami-name-"),
"location": self.bucket_name + "/" + self.ami_manifest,
"type": "ami"}
image["image_id"] = self.images_client.register_image(
@@ -76,7 +76,7 @@
def test_register_get_deregister_aki_image(self):
# Register and deregister aki image
- image = {"name": rand_name("aki-name-"),
+ image = {"name": data_utils.rand_name("aki-name-"),
"location": self.bucket_name + "/" + self.aki_manifest,
"type": "aki"}
image["image_id"] = self.images_client.register_image(
@@ -99,7 +99,7 @@
def test_register_get_deregister_ari_image(self):
# Register and deregister ari image
- image = {"name": rand_name("ari-name-"),
+ image = {"name": data_utils.rand_name("ari-name-"),
"location": "/" + self.bucket_name + "/" + self.ari_manifest,
"type": "ari"}
image["image_id"] = self.images_client.register_image(
diff --git a/tempest/thirdparty/boto/test_s3_objects.py b/tempest/thirdparty/boto/test_s3_objects.py
index 188d1db..57ec34a 100644
--- a/tempest/thirdparty/boto/test_s3_objects.py
+++ b/tempest/thirdparty/boto/test_s3_objects.py
@@ -20,7 +20,7 @@
import boto.s3.key
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
from tempest.test import attr
from tempest.thirdparty.boto.test import BotoTestCase
@@ -36,8 +36,8 @@
@attr(type='smoke')
def test_create_get_delete_object(self):
# S3 Create, get and delete object
- bucket_name = rand_name("s3bucket-")
- object_name = rand_name("s3object-")
+ bucket_name = data_utils.rand_name("s3bucket-")
+ object_name = data_utils.rand_name("s3object-")
content = 'x' * 42
bucket = self.client.create_bucket(bucket_name)
self.addResourceCleanUp(self.destroy_bucket,
diff --git a/tools/config/check_uptodate.sh b/tools/config/check_uptodate.sh
new file mode 100755
index 0000000..9882ab6
--- /dev/null
+++ b/tools/config/check_uptodate.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+TEMPDIR=`mktemp -d`
+CFGFILE=tempest.conf.sample
+tools/config/generate_sample.sh -b ./ -p tempest -o $TEMPDIR
+if ! diff $TEMPDIR/$CFGFILE etc/$CFGFILE
+then
+ echo "E: tempest.conf.sample is not up to date, please run:"
+ echo "MODULEPATH=tempest.common.generate_sample_tempest tools/config/generate_sample.sh"
+ exit 42
+fi
diff --git a/tools/tempest_auto_config.py b/tools/tempest_auto_config.py
index aef6a1f..fe9f5af 100644
--- a/tools/tempest_auto_config.py
+++ b/tools/tempest_auto_config.py
@@ -14,38 +14,50 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+#
+# This script aims to configure an initial Openstack environment with all the
+# necessary configurations for tempest's run using nothing but Openstack's
+# native API.
+# That includes, creating users, tenants, registering images (cirros),
+# configuring neutron and so on.
+#
+# ASSUMPTION: this script is run by an admin user as it is meant to configure
+# the Openstack environment prior to actual use.
# Config
import ConfigParser
import os
+import tarfile
+import urllib2
# Default client libs
+import glanceclient as glance_client
import keystoneclient.v2_0.client as keystone_client
# Import Openstack exceptions
+import glanceclient.exc as glance_exception
import keystoneclient.exceptions as keystone_exception
-DEFAULT_CONFIG_DIR = "%s/etc" % os.path.abspath(os.path.pardir)
-DEFAULT_CONFIG_FILE = "tempest.conf"
-DEFAULT_CONFIG_SAMPLE = "tempest.conf.sample"
+TEMPEST_TEMP_DIR = os.getenv("TEMPEST_TEMP_DIR", "/tmp").rstrip('/')
+TEMPEST_ROOT_DIR = os.getenv("TEMPEST_ROOT_DIR", os.getenv("HOME")).rstrip('/')
# Environment variables override defaults
-TEMPEST_CONFIG_DIR = os.environ.get('TEMPEST_CONFIG_DIR') or DEFAULT_CONFIG_DIR
-TEMPEST_CONFIG = os.environ.get('TEMPEST_CONFIG') or "%s/%s" % \
- (TEMPEST_CONFIG_DIR, DEFAULT_CONFIG_FILE)
-TEMPEST_CONFIG_SAMPLE = os.environ.get('TEMPEST_CONFIG_SAMPLE') or "%s/%s" % \
- (TEMPEST_CONFIG_DIR, DEFAULT_CONFIG_SAMPLE)
-
-# Admin credentials
-OS_USERNAME = os.environ.get('OS_USERNAME')
-OS_PASSWORD = os.environ.get('OS_PASSWORD')
-OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME')
-OS_AUTH_URL = os.environ.get('OS_AUTH_URL')
-
+TEMPEST_CONFIG_DIR = os.getenv("TEMPEST_CONFIG_DIR",
+ "%s%s" % (TEMPEST_ROOT_DIR, "/etc")).rstrip('/')
+TEMPEST_CONFIG_FILE = os.getenv("TEMPEST_CONFIG_FILE",
+ "%s%s" % (TEMPEST_CONFIG_DIR, "/tempest.conf"))
+TEMPEST_CONFIG_SAMPLE = os.getenv("TEMPEST_CONFIG_SAMPLE",
+ "%s%s" % (TEMPEST_CONFIG_DIR,
+ "/tempest.conf.sample"))
# Image references
-IMAGE_ID = os.environ.get('IMAGE_ID')
-IMAGE_ID_ALT = os.environ.get('IMAGE_ID_ALT')
+IMAGE_DOWNLOAD_CHUNK_SIZE = 8 * 1024
+IMAGE_UEC_SOURCE_URL = os.getenv("IMAGE_UEC_SOURCE_URL",
+ "http://download.cirros-cloud.net/0.3.1/"
+ "cirros-0.3.1-x86_64-uec.tar.gz")
+TEMPEST_IMAGE_ID = os.getenv('IMAGE_ID')
+TEMPEST_IMAGE_ID_ALT = os.getenv('IMAGE_ID_ALT')
+IMAGE_STATUS_ACTIVE = 'active'
class ClientManager(object):
@@ -76,26 +88,52 @@
return self.identity_client
+ def get_image_client(self, version="1", *args, **kwargs):
+ """
+ This method returns Openstack glance python client
+ :param version: a string representing the version of the glance client
+ to use.
+ :param string endpoint: A user-supplied endpoint URL for the glance
+ service.
+ :param string token: Token for authentication.
+ :param integer timeout: Allows customization of the timeout for client
+ http requests. (optional)
+ :return: a Client object representing the glance client
+ """
+ if not self.image_client:
+ self.image_client = glance_client.Client(version, *args, **kwargs)
-def getTempestConfigSample():
+ return self.image_client
+
+
+def get_tempest_config(path_to_config):
"""
Gets the tempest configuration file as a ConfigParser object
- :return: the tempest configuration file
+ :param path_to_config: path to the config file
+ :return: a ConfigParser object representing the tempest configuration file
"""
# get the sample config file from the sample
- config_sample = ConfigParser.ConfigParser()
- config_sample.readfp(open(TEMPEST_CONFIG_SAMPLE))
+ config = ConfigParser.ConfigParser()
+ config.readfp(open(path_to_config))
- return config_sample
+ return config
def update_config_admin_credentials(config, config_section):
"""
Updates the tempest config with the admin credentials
- :param config: an object representing the tempest config file
+ :param config: a ConfigParser object representing the tempest config file
:param config_section: the section name where the admin credentials are
"""
- # Check if credentials are present
+ # Check if credentials are present, default uses the config credentials
+ OS_USERNAME = os.getenv('OS_USERNAME',
+ config.get(config_section, "admin_username"))
+ OS_PASSWORD = os.getenv('OS_PASSWORD',
+ config.get(config_section, "admin_password"))
+ OS_TENANT_NAME = os.getenv('OS_TENANT_NAME',
+ config.get(config_section, "admin_tenant_name"))
+ OS_AUTH_URL = os.getenv('OS_AUTH_URL', config.get(config_section, "uri"))
+
if not (OS_AUTH_URL and
OS_USERNAME and
OS_PASSWORD and
@@ -113,31 +151,31 @@
config_identity_params)
-def update_config_section_with_params(config, section, params):
+def update_config_section_with_params(config, config_section, params):
"""
Updates a given config object with given params
- :param config: the object representing the config file of tempest
- :param section: the section we would like to update
+ :param config: a ConfigParser object representing the tempest config file
+ :param config_section: the section we would like to update
:param params: the parameters we wish to update for that section
"""
for option, value in params.items():
- config.set(section, option, value)
+ config.set(config_section, option, value)
-def get_identity_client_kwargs(config, section_name):
+def get_identity_client_kwargs(config, config_section):
"""
Get the required arguments for the identity python client
- :param config: the tempest configuration file
- :param section_name: the section name in the configuration where the
+ :param config: a ConfigParser object representing the tempest config file
+ :param config_section: the section name in the configuration where the
arguments can be found
:return: a dictionary representing the needed arguments for the identity
client
"""
- username = config.get(section_name, 'admin_username')
- password = config.get(section_name, 'admin_password')
- tenant_name = config.get(section_name, 'admin_tenant_name')
- auth_url = config.get(section_name, 'uri')
- dscv = config.get(section_name, 'disable_ssl_certificate_validation')
+ username = config.get(config_section, 'admin_username')
+ password = config.get(config_section, 'admin_password')
+ tenant_name = config.get(config_section, 'admin_tenant_name')
+ auth_url = config.get(config_section, 'uri')
+ dscv = config.get(config_section, 'disable_ssl_certificate_validation')
kwargs = {'username': username,
'password': password,
'tenant_name': tenant_name,
@@ -185,21 +223,21 @@
def create_users_and_tenants(identity_client,
config,
- identity_section):
+ config_section):
"""
Creates the two non admin users and tenants for tempest
:param identity_client: openstack identity python client
- :param config: tempest configuration file
- :param identity_section: the section name of identity in the config
+ :param config: a ConfigParser object representing the tempest config file
+ :param config_section: the section name of identity in the config
"""
# Get the necessary params from the config file
- tenant_name = config.get(identity_section, 'tenant_name')
- username = config.get(identity_section, 'username')
- password = config.get(identity_section, 'password')
+ tenant_name = config.get(config_section, 'tenant_name')
+ username = config.get(config_section, 'username')
+ password = config.get(config_section, 'password')
- alt_tenant_name = config.get(identity_section, 'alt_tenant_name')
- alt_username = config.get(identity_section, 'alt_username')
- alt_password = config.get(identity_section, 'alt_password')
+ alt_tenant_name = config.get(config_section, 'alt_tenant_name')
+ alt_username = config.get(config_section, 'alt_username')
+ alt_password = config.get(config_section, 'alt_password')
# Create the necessary users for the test runs
create_user_with_tenant(identity_client, username, password, tenant_name)
@@ -207,28 +245,153 @@
alt_tenant_name)
+def get_image_client_kwargs(identity_client, config, config_section):
+ """
+ Get the required arguments for the image python client
+ :param identity_client: openstack identity python client
+ :param config: a ConfigParser object representing the tempest config file
+ :param config_section: the section name of identity in the config
+ :return: a dictionary representing the needed arguments for the image
+ client
+ """
+
+ token = identity_client.auth_token
+ endpoint = identity_client.\
+ service_catalog.url_for(service_type='image', endpoint_type='publicURL'
+ )
+ dscv = config.get(config_section, 'disable_ssl_certificate_validation')
+ kwargs = {'endpoint': endpoint,
+ 'token': token,
+ 'insecure': dscv}
+
+ return kwargs
+
+
+def images_exist(image_client):
+ """
+ Checks whether the images ID's located in the environment variable are
+ indeed registered
+ :param image_client: the openstack python client representing the image
+ client
+ """
+ exist = True
+ if not TEMPEST_IMAGE_ID or not TEMPEST_IMAGE_ID_ALT:
+ exist = False
+ else:
+ try:
+ image_client.images.get(TEMPEST_IMAGE_ID)
+ image_client.images.get(TEMPEST_IMAGE_ID_ALT)
+ except glance_exception.HTTPNotFound:
+ exist = False
+
+ return exist
+
+
+def download_and_register_uec_images(image_client, download_url,
+ download_folder):
+ """
+ Downloads and registered the UEC AKI/AMI/ARI images
+ :param image_client:
+ :param download_url: the url of the uec tar file
+ :param download_folder: the destination folder we wish to save the file to
+ """
+ basename = os.path.basename(download_url)
+ path = os.path.join(download_folder, basename)
+
+ request = urllib2.urlopen(download_url)
+
+ # First, download the file
+ with open(path, "wb") as fp:
+ while True:
+ chunk = request.read(IMAGE_DOWNLOAD_CHUNK_SIZE)
+ if not chunk:
+ break
+
+ fp.write(chunk)
+
+ # Then extract and register images
+ tar = tarfile.open(path, "r")
+ for name in tar.getnames():
+ file_obj = tar.extractfile(name)
+ format = "aki"
+
+ if file_obj.name.endswith(".img"):
+ format = "ami"
+
+ if file_obj.name.endswith("initrd"):
+ format = "ari"
+
+ # Register images in image client
+ image_client.images.create(name=file_obj.name, disk_format=format,
+ container_format=format, data=file_obj,
+ is_public="true")
+
+ tar.close()
+
+
+def create_images(image_client, config, config_section,
+ download_url=IMAGE_UEC_SOURCE_URL,
+ download_folder=TEMPEST_TEMP_DIR):
+ """
+ Creates images for tempest's use and registers the environment variables
+ IMAGE_ID and IMAGE_ID_ALT with registered images
+ :param image_client: Openstack python image client
+ :param config: a ConfigParser object representing the tempest config file
+ :param config_section: the section name where the IMAGE ids are set
+ :param download_url: the URL from which we should download the UEC tar
+ :param download_folder: the place where we want to save the download file
+ """
+ if not images_exist(image_client):
+ # Falls down to the default uec images
+ download_and_register_uec_images(image_client, download_url,
+ download_folder)
+ image_ids = []
+ for image in image_client.images.list():
+ image_ids.append(image.id)
+
+ os.environ["IMAGE_ID"] = image_ids[0]
+ os.environ["IMAGE_ID_ALT"] = image_ids[1]
+
+ params = {'image_ref': os.getenv("IMAGE_ID"),
+ 'image_ref_alt': os.getenv("IMAGE_ID_ALT")}
+
+ update_config_section_with_params(config, config_section, params)
+
+
def main():
"""
Main module to control the script
"""
- # TODO(tkammer): add support for existing config file
- config_sample = getTempestConfigSample()
- update_config_admin_credentials(config_sample, 'identity')
+ # Check if config file exists or fall to the default sample otherwise
+ path_to_config = TEMPEST_CONFIG_SAMPLE
+
+ if os.path.isfile(TEMPEST_CONFIG_FILE):
+ path_to_config = TEMPEST_CONFIG_FILE
+
+ config = get_tempest_config(path_to_config)
+ update_config_admin_credentials(config, 'identity')
client_manager = ClientManager()
# Set the identity related info for tempest
- identity_client_kwargs = get_identity_client_kwargs(config_sample,
+ identity_client_kwargs = get_identity_client_kwargs(config,
'identity')
identity_client = client_manager.get_identity_client(
**identity_client_kwargs)
# Create the necessary users and tenants for tempest run
- create_users_and_tenants(identity_client,
- config_sample,
- 'identity')
+ create_users_and_tenants(identity_client, config, 'identity')
- # TODO(tkammer): add image implementation
+ # Set the image related info for tempest
+ image_client_kwargs = get_image_client_kwargs(identity_client,
+ config,
+ 'identity')
+ image_client = client_manager.get_image_client(**image_client_kwargs)
+
+ # Create the necessary users and tenants for tempest run
+ create_images(image_client, config, 'compute')
+
+ # TODO(tkammer): add network implementation
if __name__ == "__main__":
main()
diff --git a/tox.ini b/tox.ini
index 9356dd7..6efac78 100644
--- a/tox.ini
+++ b/tox.ini
@@ -106,7 +106,11 @@
-r{toxinidir}/test-requirements.txt
[testenv:pep8]
-commands = flake8
+setenv = MODULEPATH=tempest.common.generate_sample_tempest
+commands =
+ flake8 {posargs}
+ {toxinidir}/tools/config/check_uptodate.sh
+
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt