Refactor configuration setup and document config
* Adds documentation to the sample config file/template * Adds some log output for making diagnosing config issues easier * Rework the authorization test config option names * Remove obselete release_name config options * Remove ssh_timeout unused option Change-Id: Ia5d539771920728424bd73db3532f7670077e44d
This commit is contained in:
parent
764b51bafb
commit
3f981df854
@ -1,36 +1,90 @@
|
|||||||
[identity]
|
[identity]
|
||||||
|
# This section contains configuration options that a variety of Tempest
|
||||||
|
# test clients use when authenticating with different user/tenant
|
||||||
|
# combinations
|
||||||
|
|
||||||
|
# Set to True if your test environment's Keystone authentication service should
|
||||||
|
# be accessed over HTTPS
|
||||||
use_ssl = False
|
use_ssl = False
|
||||||
|
# This is the main host address of the authentication service API
|
||||||
host = 127.0.0.1
|
host = 127.0.0.1
|
||||||
|
# Port that the authentication service API is running on
|
||||||
port = 5000
|
port = 5000
|
||||||
|
# Version of the authentication service API (a string)
|
||||||
api_version = v2.0
|
api_version = v2.0
|
||||||
|
# Path to the authentication service tokens resource (do not modify unless you
|
||||||
|
# have a custom authentication API and are not using Keystone)
|
||||||
path = tokens
|
path = tokens
|
||||||
nonadmin_user1=user1
|
# Should typically be left as keystone unless you have a non-Keystone
|
||||||
nonadmin_user1_password=password
|
# authentication API service
|
||||||
nonadmin_user1_tenant_name=user1-project
|
|
||||||
nonadmin_user2=user2
|
|
||||||
nonadmin_user2_password=password
|
|
||||||
nonadmin_user2_tenant_name=user2-project
|
|
||||||
strategy = keystone
|
strategy = keystone
|
||||||
|
|
||||||
[compute]
|
[compute]
|
||||||
|
# This section contains configuration options used when executing tests
|
||||||
|
# against the OpenStack Compute API.
|
||||||
|
|
||||||
|
# This should be the username of a user WITHOUT administrative privileges
|
||||||
|
username = {$USERNAME}
|
||||||
|
# The above non-administrative user's password
|
||||||
|
password = {$PASSWORD}
|
||||||
|
# The above non-administrative user's tenant name
|
||||||
|
tenant_name = {$TENANT_NAME}
|
||||||
|
|
||||||
|
# This should be the username of an alternate user WITHOUT
|
||||||
|
# administrative privileges
|
||||||
|
alt_username = {$ALT_USERNAME}
|
||||||
|
# The above non-administrative user's password
|
||||||
|
alt_password = {$ALT_PASSWORD}
|
||||||
|
# The above non-administrative user's tenant name
|
||||||
|
alt_tenant_name = {$ALT_TENANT_NAME}
|
||||||
|
|
||||||
# Reference data for tests. The ref and ref_alt should be
|
# Reference data for tests. The ref and ref_alt should be
|
||||||
# distinct images/flavors.
|
# distinct images/flavors.
|
||||||
image_ref=e7ddc02e-92fa-4f82-b36f-59b39bf66a67
|
image_ref = {$IMAGE_ID}
|
||||||
image_ref_alt=346f4039-a81e-44e0-9223-4a3d13c92a07
|
image_ref_alt = {$IMAGE_ID_ALT}
|
||||||
flavor_ref = 1
|
flavor_ref = 1
|
||||||
flavor_ref_alt = 2
|
flavor_ref_alt = 2
|
||||||
ssh_timeout=300
|
|
||||||
|
# Number of seconds to wait while looping to check the status of an
|
||||||
|
# instance or volume that is building.
|
||||||
build_interval = 10
|
build_interval = 10
|
||||||
|
|
||||||
|
# Number of seconds to time out on waiting for an instance or volume
|
||||||
|
# to build or reach an expected status
|
||||||
build_timeout = 600
|
build_timeout = 600
|
||||||
|
|
||||||
|
# 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
|
catalog_type = compute
|
||||||
|
|
||||||
|
# Does the Compute API support creation of images?
|
||||||
create_image_enabled = true
|
create_image_enabled = true
|
||||||
|
|
||||||
# For resize to work with libvirt/kvm, one of the following must be 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
|
# 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
|
# Cluster: the 'nova' user must have scp access between cluster nodes
|
||||||
resize_available = true
|
resize_available = true
|
||||||
|
|
||||||
[image]
|
[image]
|
||||||
username=admin
|
# This section contains configuration options used when executing tests
|
||||||
password=********
|
# against the OpenStack Images API
|
||||||
tenant=admin
|
|
||||||
auth_url=http://localhost:5000/v2.0
|
# This should be the username of a user WITHOUT administrative privileges
|
||||||
|
username = {$USERNAME}
|
||||||
|
# The above non-administrative user's password
|
||||||
|
password = {$PASSWORD}
|
||||||
|
# The above non-administrative user's tenant name
|
||||||
|
tenant_name = {$TENANT_NAME}
|
||||||
|
|
||||||
|
[compute-admin]
|
||||||
|
# This section contains configuration options for an administrative
|
||||||
|
# user of the Compute API. These options are used in tests that stress
|
||||||
|
# the admin-only parts of the Compute API
|
||||||
|
|
||||||
|
# This should be the username of a user WITH administrative privileges
|
||||||
|
username = {$ADMIN_USERNAME}
|
||||||
|
# The above administrative user's password
|
||||||
|
password = {$ADMIN_PASSWORD}
|
||||||
|
# The above administrative user's tenant name
|
||||||
|
tenant_name = {$ADMIN_TENANT_NAME}
|
||||||
|
@ -1,8 +1,26 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 OpenStack, LLC
|
||||||
|
# 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 json
|
||||||
import httplib2
|
import httplib2
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,24 +1,49 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 OpenStack, LLC
|
||||||
|
# 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 ConfigParser
|
import ConfigParser
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from tempest.common.utils import data_utils
|
from tempest.common.utils import data_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IdentityConfig(object):
|
class BaseConfig(object):
|
||||||
"""Provides configuration information for authenticating with Keystone."""
|
|
||||||
|
SECTION_NAME = None
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
"""Initialize an Identity-specific configuration object"""
|
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
|
|
||||||
def get(self, item_name, default_value=None):
|
def get(self, item_name, default_value=None):
|
||||||
try:
|
try:
|
||||||
return self.conf.get("identity", item_name)
|
return self.conf.get(self.SECTION_NAME, item_name)
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
||||||
return default_value
|
return default_value
|
||||||
|
|
||||||
|
|
||||||
|
class IdentityConfig(BaseConfig):
|
||||||
|
|
||||||
|
"""Provides configuration information for authenticating with Keystone."""
|
||||||
|
|
||||||
|
SECTION_NAME = "identity"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host(self):
|
def host(self):
|
||||||
"""Host IP for making Identity API requests."""
|
"""Host IP for making Identity API requests."""
|
||||||
@ -54,62 +79,55 @@ class IdentityConfig(object):
|
|||||||
"""Specifies if we are using https."""
|
"""Specifies if we are using https."""
|
||||||
return self.get("use_ssl", 'false').lower() != 'false'
|
return self.get("use_ssl", 'false').lower() != 'false'
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user1(self):
|
|
||||||
"""Username to use for Nova API requests."""
|
|
||||||
return self.get("nonadmin_user1")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user1_tenant_name(self):
|
|
||||||
"""Tenant name to use for Nova API requests."""
|
|
||||||
return self.get("nonadmin_user1_tenant_name")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user1_password(self):
|
|
||||||
"""API key to use when authenticating."""
|
|
||||||
return self.get("nonadmin_user1_password")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user2(self):
|
|
||||||
"""Alternate username to use for Nova API requests."""
|
|
||||||
return self.get("nonadmin_user2")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user2_tenant_name(self):
|
|
||||||
"""Alternate tenant name for Nova API requests."""
|
|
||||||
return self.get("nonadmin_user2_tenant_name")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nonadmin_user2_password(self):
|
|
||||||
"""Alternate API key to use when authenticating."""
|
|
||||||
return self.get("nonadmin_user2_password")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def strategy(self):
|
def strategy(self):
|
||||||
"""Which auth method does the environment use? (basic|keystone)"""
|
"""Which auth method does the environment use? (basic|keystone)"""
|
||||||
return self.get("strategy", 'keystone')
|
return self.get("strategy", 'keystone')
|
||||||
|
|
||||||
|
|
||||||
class ComputeConfig(object):
|
class ComputeConfig(BaseConfig):
|
||||||
def __init__(self, conf):
|
|
||||||
"""Initialize a Compute-specific configuration object."""
|
|
||||||
self.conf = conf
|
|
||||||
|
|
||||||
def get(self, item_name, default_value):
|
SECTION_NAME = "compute"
|
||||||
try:
|
|
||||||
return self.conf.get("compute", item_name)
|
@property
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
def username(self):
|
||||||
return default_value
|
"""Username to use for Nova API requests."""
|
||||||
|
return self.get("username", "demo")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tenant_name(self):
|
||||||
|
"""Tenant name to use for Nova API requests."""
|
||||||
|
return self.get("tenant_name", "demo")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def password(self):
|
||||||
|
"""API key to use when authenticating."""
|
||||||
|
return self.get("password", "pass")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alt_username(self):
|
||||||
|
"""Username of alternate user to use for Nova API requests."""
|
||||||
|
return self.get("alt_username", "demo")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alt_tenant_name(self):
|
||||||
|
"""Alternate user's Tenant name to use for Nova API requests."""
|
||||||
|
return self.get("alt_tenant_name", "demo")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alt_password(self):
|
||||||
|
"""API key to use when authenticating as alternate user."""
|
||||||
|
return self.get("alt_password", "pass")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image_ref(self):
|
def image_ref(self):
|
||||||
"""Valid primary image to use in tests."""
|
"""Valid primary image to use in tests."""
|
||||||
return self.get("image_ref", 'e7ddc02e-92fa-4f82-b36f-59b39bf66a67')
|
return self.get("image_ref", "{$IMAGE_ID}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image_ref_alt(self):
|
def image_ref_alt(self):
|
||||||
"""Valid secondary image reference to be used in tests."""
|
"""Valid secondary image reference to be used in tests."""
|
||||||
return self.get("image_ref_alt", '346f4039-a81e-44e0-9223-4a3d13c907')
|
return self.get("image_ref_alt", "{$IMAGE_ID_ALT}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def flavor_ref(self):
|
def flavor_ref(self):
|
||||||
@ -131,21 +149,11 @@ class ComputeConfig(object):
|
|||||||
"""Does the test environment support snapshots?"""
|
"""Does the test environment support snapshots?"""
|
||||||
return self.get("create_image_enabled", 'false').lower() != 'false'
|
return self.get("create_image_enabled", 'false').lower() != 'false'
|
||||||
|
|
||||||
@property
|
|
||||||
def release_name(self):
|
|
||||||
"""Which release is this?"""
|
|
||||||
return self.get("release_name", 'essex')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def build_interval(self):
|
def build_interval(self):
|
||||||
"""Time in seconds between build status checks."""
|
"""Time in seconds between build status checks."""
|
||||||
return float(self.get("build_interval", 10))
|
return float(self.get("build_interval", 10))
|
||||||
|
|
||||||
@property
|
|
||||||
def ssh_timeout(self):
|
|
||||||
"""Timeout in seconds to use when connecting via ssh."""
|
|
||||||
return float(self.get("ssh_timeout", 300))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def build_timeout(self):
|
def build_timeout(self):
|
||||||
"""Timeout in seconds to wait for an entity to build."""
|
"""Timeout in seconds to wait for an entity to build."""
|
||||||
@ -157,20 +165,14 @@ class ComputeConfig(object):
|
|||||||
return self.get("catalog_type", 'compute')
|
return self.get("catalog_type", 'compute')
|
||||||
|
|
||||||
|
|
||||||
class ImagesConfig(object):
|
class ImagesConfig(BaseConfig):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Provides configuration information for connecting to an
|
Provides configuration information for connecting to an
|
||||||
OpenStack Images service.
|
OpenStack Images service.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, conf):
|
SECTION_NAME = "image"
|
||||||
self.conf = conf
|
|
||||||
|
|
||||||
def get(self, item_name, default_value=None):
|
|
||||||
try:
|
|
||||||
return self.conf.get("image", item_name)
|
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
|
||||||
return default_value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host(self):
|
def host(self):
|
||||||
@ -189,31 +191,34 @@ class ImagesConfig(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def username(self):
|
def username(self):
|
||||||
"""Username to use for Images API requests. Defaults to 'admin'."""
|
"""Username to use for Images API requests. Defaults to 'demo'."""
|
||||||
return self.get("user", "admin")
|
return self.get("user", "demo")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def password(self):
|
def password(self):
|
||||||
"""Password for user"""
|
"""Password for user"""
|
||||||
return self.get("password", "")
|
return self.get("password", "pass")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tenant(self):
|
def tenant_name(self):
|
||||||
"""Tenant to use for Images API requests. Defaults to 'admin'."""
|
"""Tenant to use for Images API requests. Defaults to 'demo'."""
|
||||||
return self.get("tenant", "admin")
|
return self.get("tenant_name", "demo")
|
||||||
|
|
||||||
@property
|
|
||||||
def service_token(self):
|
|
||||||
"""Token to use in querying the API. Default: None"""
|
|
||||||
return self.get("service_token")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def auth_url(self):
|
|
||||||
"""Optional URL to auth service. Will be discovered if None"""
|
|
||||||
return self.get("auth_url")
|
|
||||||
|
|
||||||
|
|
||||||
class TempestConfig(object):
|
# TODO(jaypipes): Move this to a common utils (not data_utils...)
|
||||||
|
def singleton(cls):
|
||||||
|
"""Simple wrapper for classes that should only have a single instance"""
|
||||||
|
instances = {}
|
||||||
|
|
||||||
|
def getinstance():
|
||||||
|
if cls not in instances:
|
||||||
|
instances[cls] = cls()
|
||||||
|
return instances[cls]
|
||||||
|
return getinstance
|
||||||
|
|
||||||
|
|
||||||
|
@singleton
|
||||||
|
class TempestConfig:
|
||||||
"""Provides OpenStack configuration information."""
|
"""Provides OpenStack configuration information."""
|
||||||
|
|
||||||
DEFAULT_CONFIG_DIR = os.path.join(
|
DEFAULT_CONFIG_DIR = os.path.join(
|
||||||
@ -235,6 +240,8 @@ class TempestConfig(object):
|
|||||||
|
|
||||||
path = os.path.join(conf_dir, conf_file)
|
path = os.path.join(conf_dir, conf_file)
|
||||||
|
|
||||||
|
LOG.info("Using tempest config file %s" % path)
|
||||||
|
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
msg = "Config file %(path)s not found" % locals()
|
msg = "Config file %(path)s not found" % locals()
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
@ -1,3 +1,22 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 OpenStack, LLC
|
||||||
|
# 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 logging
|
||||||
|
|
||||||
import tempest.config
|
import tempest.config
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
from tempest.services.image import service as image_service
|
from tempest.services.image import service as image_service
|
||||||
@ -12,25 +31,28 @@ from tempest.services.nova.json.floating_ips_client import FloatingIPsClient
|
|||||||
from tempest.services.nova.json.keypairs_client import KeyPairsClient
|
from tempest.services.nova.json.keypairs_client import KeyPairsClient
|
||||||
from tempest.services.nova.json.volumes_client import VolumesClient
|
from tempest.services.nova.json.volumes_client import VolumesClient
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
|
|
||||||
def __init__(self, username=None, password=None, tenant_name=None):
|
|
||||||
"""
|
"""
|
||||||
Top level manager for all Openstack APIs
|
Top level manager for OpenStack Compute clients
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
self.config = tempest.config.TempestConfig()
|
self.config = tempest.config.TempestConfig()
|
||||||
|
|
||||||
if None in [username, password, tenant_name]:
|
username = self.config.compute.username
|
||||||
# Pull from the default, the first non-admin user
|
password = self.config.compute.password
|
||||||
username = self.config.identity.nonadmin_user1
|
tenant_name = self.config.compute.tenant_name
|
||||||
password = self.config.identity.nonadmin_user1_password
|
|
||||||
tenant_name = self.config.identity.nonadmin_user1_tenant_name
|
if None in (username, password, tenant_name):
|
||||||
|
msg = ("Missing required credentials. "
|
||||||
|
"username: %(username)s, password: %(password)s, "
|
||||||
|
"tenant_name: %(tenant_name)s") % locals()
|
||||||
|
raise exceptions.InvalidConfiguration(msg)
|
||||||
|
|
||||||
if None in [username, password, tenant_name]:
|
|
||||||
# We can't find any usable credentials, fail early
|
|
||||||
raise exceptions.InvalidConfiguration(message="Missing complete \
|
|
||||||
user credentials.")
|
|
||||||
auth_url = self.config.identity.auth_url
|
auth_url = self.config.identity.auth_url
|
||||||
|
|
||||||
if self.config.identity.strategy == 'keystone':
|
if self.config.identity.strategy == 'keystone':
|
||||||
|
@ -42,14 +42,14 @@ class Service(BaseService):
|
|||||||
creds = {
|
creds = {
|
||||||
'username': config.images.username,
|
'username': config.images.username,
|
||||||
'password': config.images.password,
|
'password': config.images.password,
|
||||||
'tenant': config.images.tenant,
|
'tenant': config.images.tenant_name,
|
||||||
'auth_url': config.images.auth_url,
|
# rstrip() is necessary here because Glance client
|
||||||
'strategy': 'keystone'
|
# automatically adds the tokens/ part...
|
||||||
|
'auth_url': config.identity.auth_url.rstrip('/tokens'),
|
||||||
|
'strategy': config.identity.strategy
|
||||||
}
|
}
|
||||||
service_token = config.images.service_token
|
|
||||||
self._client = client.Client(config.images.host,
|
self._client = client.Client(config.images.host,
|
||||||
config.images.port,
|
config.images.port,
|
||||||
auth_tok=service_token,
|
|
||||||
creds=creds)
|
creds=creds)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -109,7 +109,6 @@ class CreateRegisterImagesTest(unittest.TestCase):
|
|||||||
self.assertEqual(1024, results['size'])
|
self.assertEqual(1024, results['size'])
|
||||||
|
|
||||||
@attr(type='image')
|
@attr(type='image')
|
||||||
@unittest.skip('Skipping until Glance Bug 912897 is fixed')
|
|
||||||
def test_register_remote_image(self):
|
def test_register_remote_image(self):
|
||||||
"""Register a new remote image"""
|
"""Register a new remote image"""
|
||||||
meta = {
|
meta = {
|
||||||
@ -141,7 +140,6 @@ class ListImagesTest(unittest.TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
if not GLANCE_INSTALLED:
|
if not GLANCE_INSTALLED:
|
||||||
raise SkipTest('Glance not installed')
|
raise SkipTest('Glance not installed')
|
||||||
raise SkipTest('Skipping until Glance Bug 912897 is fixed')
|
|
||||||
cls.os = openstack.ServiceManager()
|
cls.os = openstack.ServiceManager()
|
||||||
cls.client = cls.os.images.get_client()
|
cls.client = cls.os.images.get_client()
|
||||||
cls.created_images = []
|
cls.created_images = []
|
||||||
@ -149,7 +147,7 @@ class ListImagesTest(unittest.TestCase):
|
|||||||
|
|
||||||
# We add a few images here to test the listing functionality of
|
# We add a few images here to test the listing functionality of
|
||||||
# the images API
|
# the images API
|
||||||
for x in xrange(1, 10):
|
for x in xrange(0, 10):
|
||||||
# We make even images remote and odd images standard
|
# We make even images remote and odd images standard
|
||||||
if x % 2 == 0:
|
if x % 2 == 0:
|
||||||
cls.created_images.append(cls._create_remote_image(x))
|
cls.created_images.append(cls._create_remote_image(x))
|
||||||
|
@ -4,6 +4,8 @@ from nose.plugins.attrib import attr
|
|||||||
from nose.tools import raises
|
from nose.tools import raises
|
||||||
|
|
||||||
from tempest import openstack
|
from tempest import openstack
|
||||||
|
from tempest.services.nova.json.images_client import ImagesClient
|
||||||
|
from tempest.services.nova.json.servers_client import ServersClient
|
||||||
from tempest.common.utils.data_utils import rand_name
|
from tempest.common.utils.data_utils import rand_name
|
||||||
from tempest.exceptions import NotFound, ComputeFault, BadRequest, Unauthorized
|
from tempest.exceptions import NotFound, ComputeFault, BadRequest, Unauthorized
|
||||||
from tempest.tests import utils
|
from tempest.tests import utils
|
||||||
@ -23,10 +25,10 @@ class AuthorizationTest(unittest.TestCase):
|
|||||||
cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
|
cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
|
||||||
|
|
||||||
# Verify the second user is not the same as the first and is configured
|
# Verify the second user is not the same as the first and is configured
|
||||||
cls.user1 = cls.config.identity.nonadmin_user1
|
cls.user1 = cls.config.compute.username
|
||||||
cls.user2 = cls.config.identity.nonadmin_user2
|
cls.user2 = cls.config.compute.alt_username
|
||||||
cls.user2_password = cls.config.identity.nonadmin_user2_password
|
cls.user2_password = cls.config.compute.alt_password
|
||||||
cls.user2_tenant_name = cls.config.identity.nonadmin_user2_tenant_name
|
cls.user2_tenant_name = cls.config.compute.alt_tenant_name
|
||||||
cls.multi_user = False
|
cls.multi_user = False
|
||||||
|
|
||||||
if (cls.user2 != None and cls.user1 != cls.user2
|
if (cls.user2 != None and cls.user1 != cls.user2
|
||||||
@ -35,10 +37,18 @@ class AuthorizationTest(unittest.TestCase):
|
|||||||
|
|
||||||
# Setup a client instance for the second user
|
# Setup a client instance for the second user
|
||||||
cls.multi_user = True
|
cls.multi_user = True
|
||||||
cls.os_other = openstack.Manager(cls.user2, cls.user2_password,
|
|
||||||
cls.user2_tenant_name)
|
auth_url = self.config.identity.auth_url
|
||||||
cls.other_client = cls.os_other.servers_client
|
|
||||||
cls.other_images_client = cls.os_other.images_client
|
if self.config.identity.strategy == 'keystone':
|
||||||
|
client_args = (self.config, cls.user2, cls.user_2password,
|
||||||
|
auth_url, cls.user2_tenant_name)
|
||||||
|
else:
|
||||||
|
client_args = (self.config, cls.user2, cls.user2_password,
|
||||||
|
auth_url)
|
||||||
|
|
||||||
|
cls.other_client = ServersClient(*client_args)
|
||||||
|
cls.other_images_client = ImagesClient(*client_args)
|
||||||
|
|
||||||
name = rand_name('server')
|
name = rand_name('server')
|
||||||
resp, server = cls.client.create_server(name, cls.image_ref,
|
resp, server = cls.client.create_server(name, cls.image_ref,
|
||||||
|
@ -7,8 +7,6 @@ import tempest.config
|
|||||||
|
|
||||||
class FlavorsTest(unittest.TestCase):
|
class FlavorsTest(unittest.TestCase):
|
||||||
|
|
||||||
release = tempest.config.TempestConfig().compute.release_name
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.os = openstack.Manager()
|
cls.os = openstack.Manager()
|
||||||
@ -44,7 +42,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
|
self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
|
||||||
999)
|
999)
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive', bug='lp912922')
|
@attr(type='positive', bug='lp912922')
|
||||||
def test_list_flavors_limit_results(self):
|
def test_list_flavors_limit_results(self):
|
||||||
"""Only the expected number of flavors should be returned"""
|
"""Only the expected number of flavors should be returned"""
|
||||||
@ -52,7 +49,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
resp, flavors = self.client.list_flavors(params)
|
resp, flavors = self.client.list_flavors(params)
|
||||||
self.assertEqual(1, len(flavors))
|
self.assertEqual(1, len(flavors))
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive', bug='lp912922')
|
@attr(type='positive', bug='lp912922')
|
||||||
def test_list_flavors_detailed_limit_results(self):
|
def test_list_flavors_detailed_limit_results(self):
|
||||||
"""Only the expected number of flavors (detailed) should be returned"""
|
"""Only the expected number of flavors (detailed) should be returned"""
|
||||||
@ -84,7 +80,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
|
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
|
||||||
'The list of flavors did not start after the marker.')
|
'The list of flavors did not start after the marker.')
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive')
|
@attr(type='positive')
|
||||||
def test_list_flavors_detailed_filter_by_min_disk(self):
|
def test_list_flavors_detailed_filter_by_min_disk(self):
|
||||||
"""The detailed list of flavors should be filtered by disk space"""
|
"""The detailed list of flavors should be filtered by disk space"""
|
||||||
@ -96,7 +91,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
resp, flavors = self.client.list_flavors_with_detail(params)
|
resp, flavors = self.client.list_flavors_with_detail(params)
|
||||||
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive')
|
@attr(type='positive')
|
||||||
def test_list_flavors_detailed_filter_by_min_ram(self):
|
def test_list_flavors_detailed_filter_by_min_ram(self):
|
||||||
"""The detailed list of flavors should be filtered by RAM"""
|
"""The detailed list of flavors should be filtered by RAM"""
|
||||||
@ -108,7 +102,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
resp, flavors = self.client.list_flavors_with_detail(params)
|
resp, flavors = self.client.list_flavors_with_detail(params)
|
||||||
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive')
|
@attr(type='positive')
|
||||||
def test_list_flavors_filter_by_min_disk(self):
|
def test_list_flavors_filter_by_min_disk(self):
|
||||||
"""The list of flavors should be filtered by disk space"""
|
"""The list of flavors should be filtered by disk space"""
|
||||||
@ -120,7 +113,6 @@ class FlavorsTest(unittest.TestCase):
|
|||||||
resp, flavors = self.client.list_flavors(params)
|
resp, flavors = self.client.list_flavors(params)
|
||||||
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='positive')
|
@attr(type='positive')
|
||||||
def test_list_flavors_filter_by_min_ram(self):
|
def test_list_flavors_filter_by_min_ram(self):
|
||||||
"""The list of flavors should be filtered by RAM"""
|
"""The list of flavors should be filtered by RAM"""
|
||||||
|
@ -8,8 +8,6 @@ from tempest import exceptions
|
|||||||
|
|
||||||
class KeyPairsTest(unittest.TestCase):
|
class KeyPairsTest(unittest.TestCase):
|
||||||
|
|
||||||
release = tempest.config.TempestConfig().compute.release_name
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.os = openstack.Manager()
|
cls.os = openstack.Manager()
|
||||||
@ -138,7 +136,6 @@ class KeyPairsTest(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
self.fail('empty string')
|
self.fail('empty string')
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'bug in diablo')
|
|
||||||
@attr(type='negative')
|
@attr(type='negative')
|
||||||
def test_create_keypair_with_long_keynames(self):
|
def test_create_keypair_with_long_keynames(self):
|
||||||
"""Keypairs with name longer than 255 chars should not be created"""
|
"""Keypairs with name longer than 255 chars should not be created"""
|
||||||
|
@ -6,8 +6,6 @@ import tempest.config
|
|||||||
|
|
||||||
|
|
||||||
class ServersNegativeTest(unittest.TestCase):
|
class ServersNegativeTest(unittest.TestCase):
|
||||||
release = tempest.config.TempestConfig().\
|
|
||||||
compute.release_name
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@ -16,7 +14,6 @@ class ServersNegativeTest(unittest.TestCase):
|
|||||||
cls.config = cls.os.config
|
cls.config = cls.os.config
|
||||||
cls.image_ref = cls.config.compute.image_ref
|
cls.image_ref = cls.config.compute.image_ref
|
||||||
cls.flavor_ref = cls.config.compute.flavor_ref
|
cls.flavor_ref = cls.config.compute.flavor_ref
|
||||||
cls.ssh_timeout = cls.config.compute.ssh_timeout
|
|
||||||
|
|
||||||
def test_server_name_blank(self):
|
def test_server_name_blank(self):
|
||||||
"""Create a server with name parameter empty"""
|
"""Create a server with name parameter empty"""
|
||||||
@ -63,7 +60,6 @@ class ServersNegativeTest(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
self.fail('Cannot create a server with an invalid flavor')
|
self.fail('Cannot create a server with an invalid flavor')
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'Bug in Diablo, lp#891264')
|
|
||||||
def test_invalid_access_ip_v4_address(self):
|
def test_invalid_access_ip_v4_address(self):
|
||||||
"""An access IPv4 address must match a valid address pattern"""
|
"""An access IPv4 address must match a valid address pattern"""
|
||||||
accessIPv4 = '1.1.1.1.1.1'
|
accessIPv4 = '1.1.1.1.1.1'
|
||||||
@ -78,7 +74,6 @@ class ServersNegativeTest(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
self.fail('Access IPv4 address must match the correct format')
|
self.fail('Access IPv4 address must match the correct format')
|
||||||
|
|
||||||
@unittest.skipIf(release == 'diablo', 'Bug in Diablo, lp#891264')
|
|
||||||
def test_invalid_ip_v6_address(self):
|
def test_invalid_ip_v6_address(self):
|
||||||
"""An access IPv6 address must match a valid address pattern"""
|
"""An access IPv6 address must match a valid address pattern"""
|
||||||
accessIPv6 = 'notvalid'
|
accessIPv6 = 'notvalid'
|
||||||
|
Loading…
Reference in New Issue
Block a user