Merge "Consider pre-existing VMs when testing server list"
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index 0bad96a..94edb6c 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -22,7 +22,7 @@
@test.idempotent_id('1d6ef640-3a20-4c84-8710-d95828fdb6ad')
def test_add_image_member(self):
image = self._create_image()
- self.image_member_client.add_member(self.alt_tenant_id, image)
+ self.image_member_client.create_image_member(image, self.alt_tenant_id)
body = self.image_member_client.list_image_members(image)
members = body['members']
members = map(lambda x: x['member_id'], members)
@@ -33,9 +33,10 @@
@test.idempotent_id('6a5328a5-80e8-4b82-bd32-6c061f128da9')
def test_get_shared_images(self):
image = self._create_image()
- self.image_member_client.add_member(self.alt_tenant_id, image)
+ self.image_member_client.create_image_member(image, self.alt_tenant_id)
share_image = self._create_image()
- self.image_member_client.add_member(self.alt_tenant_id, share_image)
+ self.image_member_client.create_image_member(share_image,
+ self.alt_tenant_id)
body = self.image_member_client.list_shared_images(
self.alt_tenant_id)
images = body['shared_images']
@@ -46,8 +47,10 @@
@test.idempotent_id('a76a3191-8948-4b44-a9d6-4053e5f2b138')
def test_remove_member(self):
image_id = self._create_image()
- self.image_member_client.add_member(self.alt_tenant_id, image_id)
- self.image_member_client.delete_member(self.alt_tenant_id, image_id)
+ self.image_member_client.create_image_member(image_id,
+ self.alt_tenant_id)
+ self.image_member_client.delete_image_member(image_id,
+ self.alt_tenant_id)
body = self.image_member_client.list_image_members(image_id)
members = body['members']
self.assertEqual(0, len(members), str(members))
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
index d46a836..2538781 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -26,8 +26,8 @@
# Add member with non existing image.
non_exist_image = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
- self.image_member_client.add_member,
- self.alt_tenant_id, non_exist_image)
+ self.image_member_client.create_image_member,
+ non_exist_image, self.alt_tenant_id)
@test.attr(type=['negative'])
@test.idempotent_id('e1559f05-b667-4f1b-a7af-518b52dc0c0f')
@@ -35,8 +35,8 @@
# Delete member with non existing image.
non_exist_image = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
- self.image_member_client.delete_member,
- self.alt_tenant_id, non_exist_image)
+ self.image_member_client.delete_image_member,
+ non_exist_image, self.alt_tenant_id)
@test.attr(type=['negative'])
@test.idempotent_id('f5720333-dd69-4194-bb76-d2f048addd56')
@@ -45,8 +45,8 @@
image_id = self._create_image()
non_exist_tenant = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound,
- self.image_member_client.delete_member,
- non_exist_tenant, image_id)
+ self.image_member_client.delete_image_member,
+ image_id, non_exist_tenant)
@test.attr(type=['negative'])
@test.idempotent_id('f25f89e4-0b6c-453b-a853-1f80b9d7ef26')
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 6d5559d..59ac646 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -16,6 +16,7 @@
from six import moves
from tempest.api.image import base
+from tempest.common import image as common_image
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
@@ -306,7 +307,8 @@
@test.idempotent_id('01752c1c-0275-4de3-9e5b-876e44541928')
def test_list_image_metadata(self):
# All metadata key/value pairs for an image should be returned
- resp_metadata = self.client.check_image(self.image_id)
+ resp = self.client.check_image(self.image_id)
+ resp_metadata = common_image.get_image_meta_from_headers(resp)
expected = {'key1': 'value1'}
self.assertEqual(expected, resp_metadata['properties'])
@@ -314,12 +316,14 @@
def test_update_image_metadata(self):
# The metadata for the image should match the updated values
req_metadata = {'key1': 'alt1', 'key2': 'value2'}
- metadata = self.client.check_image(self.image_id)
+ resp = self.client.check_image(self.image_id)
+ metadata = common_image.get_image_meta_from_headers(resp)
self.assertEqual(metadata['properties'], {'key1': 'value1'})
metadata['properties'].update(req_metadata)
metadata = self.client.update_image(
self.image_id, properties=metadata['properties'])['image']
- resp_metadata = self.client.check_image(self.image_id)
+ resp = self.client.check_image(self.image_id)
+ resp_metadata = common_image.get_image_meta_from_headers(resp)
expected = {'key1': 'alt1', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata['properties'])
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index db323de..f9d7a9b 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -157,7 +157,8 @@
spec.append([CONF.object_storage.operator_role])
spec.append([CONF.object_storage.reseller_admin_role])
if CONF.service_available.heat:
- spec.append([CONF.orchestration.stack_owner_role])
+ spec.append([CONF.orchestration.stack_owner_role,
+ CONF.object_storage.operator_role])
if admin:
spec.append('admin')
resources = []
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 5cce0bb..bf6c537 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -16,8 +16,8 @@
import six
-from tempest import exceptions
from tempest.lib import auth
+from tempest.lib import exceptions
@six.add_metaclass(abc.ABCMeta)
diff --git a/tempest/common/image.py b/tempest/common/image.py
new file mode 100644
index 0000000..42ce5ac
--- /dev/null
+++ b/tempest/common/image.py
@@ -0,0 +1,38 @@
+# Copyright 2016 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.
+
+
+def get_image_meta_from_headers(resp):
+ meta = {'properties': {}}
+ for key in resp.response:
+ value = resp.response[key]
+ if key.startswith('x-image-meta-property-'):
+ _key = key[22:]
+ meta['properties'][_key] = value
+ elif key.startswith('x-image-meta-'):
+ _key = key[13:]
+ meta[_key] = value
+
+ for key in ['is_public', 'protected', 'deleted']:
+ if key in meta:
+ meta[key] = meta[key].strip().lower() in ('t', 'true', 'yes', '1')
+
+ for key in ['size', 'min_ram', 'min_disk']:
+ if key in meta:
+ try:
+ meta[key] = int(meta[key])
+ except ValueError:
+ pass
+ return meta
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index c3c9a41..a55ee32 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -22,6 +22,26 @@
LOG = logging.getLogger(__name__)
+def _create_neutron_sec_group_rules(os, sec_group):
+ sec_group_rules_client = os.security_group_rules_client
+ ethertype = 'IPv4'
+ if CONF.validation.ip_version_for_ssh == 6:
+ ethertype = 'IPv6'
+
+ sec_group_rules_client.create_security_group_rule(
+ security_group_id=sec_group['id'],
+ protocol='tcp',
+ ethertype=ethertype,
+ port_range_min=22,
+ port_range_max=22,
+ direction='ingress')
+ sec_group_rules_client.create_security_group_rule(
+ security_group_id=sec_group['id'],
+ protocol='icmp',
+ ethertype=ethertype,
+ direction='ingress')
+
+
def create_ssh_security_group(os, add_rule=False):
security_groups_client = os.compute_security_groups_client
security_group_rules_client = os.compute_security_group_rules_client
@@ -30,12 +50,15 @@
security_group = security_groups_client.create_security_group(
name=sg_name, description=sg_description)['security_group']
if add_rule:
- security_group_rules_client.create_security_group_rule(
- parent_group_id=security_group['id'], ip_protocol='tcp',
- from_port=22, to_port=22)
- security_group_rules_client.create_security_group_rule(
- parent_group_id=security_group['id'], ip_protocol='icmp',
- from_port=-1, to_port=-1)
+ if CONF.service_available.neutron:
+ _create_neutron_sec_group_rules(os, security_group)
+ else:
+ security_group_rules_client.create_security_group_rule(
+ parent_group_id=security_group['id'], ip_protocol='tcp',
+ from_port=22, to_port=22)
+ security_group_rules_client.create_security_group_rule(
+ parent_group_id=security_group['id'], ip_protocol='icmp',
+ from_port=-1, to_port=-1)
LOG.debug("SSH Validation resource security group with tcp and icmp "
"rules %s created"
% sg_name)
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 23d7f88..d8dad69 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -15,6 +15,7 @@
from oslo_log import log as logging
+from tempest.common import image as common_image
from tempest import config
from tempest import exceptions
from tempest.lib.common.utils import misc as misc_utils
@@ -127,7 +128,11 @@
# The 'check_image' method is used here because the show_image method
# returns image details plus the image itself which is very expensive.
# The 'check_image' method returns just image details.
- show_image = client.check_image
+ def _show_image_v1(image_id):
+ resp = client.check_image(image_id)
+ return common_image.get_image_meta_from_headers(resp)
+
+ show_image = _show_image_v1
else:
show_image = client.show_image
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 92f335f..f534f30 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -13,157 +13,65 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
+
+from tempest.lib import exceptions
-class TempestException(Exception):
- """Base Tempest Exception
-
- To correctly use this class, inherit from it and define
- a 'message' property. That message will get printf'd
- with the keyword arguments provided to the constructor.
- """
- message = "An unknown exception occurred"
-
- def __init__(self, *args, **kwargs):
- super(TempestException, self).__init__()
- try:
- self._error_string = self.message % kwargs
- except Exception:
- # at least get the core message out if something happened
- self._error_string = self.message
- if len(args) > 0:
- # If there is a non-kwarg parameter, assume it's the error
- # message or reason description and tack it on to the end
- # of the exception message
- # Convert all arguments into their string representations...
- args = ["%s" % arg for arg in args]
- self._error_string = (self._error_string +
- "\nDetails: %s" % '\n'.join(args))
-
- def __str__(self):
- return self._error_string
-
-
-class RestClientException(TempestException,
- testtools.TestCase.failureException):
- pass
-
-
-class InvalidConfiguration(TempestException):
+class InvalidConfiguration(exceptions.TempestException):
message = "Invalid Configuration"
-class InvalidCredentials(TempestException):
- message = "Invalid Credentials"
-
-
-class InvalidServiceTag(TempestException):
+class InvalidServiceTag(exceptions.TempestException):
message = "Invalid service tag"
-class InvalidIdentityVersion(TempestException):
- message = "Invalid version %(identity_version)s of the identity service"
-
-
-class TimeoutException(TempestException):
+class TimeoutException(exceptions.TempestException):
message = "Request timed out"
-class BuildErrorException(TempestException):
+class BuildErrorException(exceptions.TempestException):
message = "Server %(server_id)s failed to build and is in ERROR status"
-class ImageKilledException(TempestException):
+class ImageKilledException(exceptions.TempestException):
message = "Image %(image_id)s 'killed' while waiting for '%(status)s'"
-class AddImageException(TempestException):
+class AddImageException(exceptions.TempestException):
message = "Image %(image_id)s failed to become ACTIVE in the allotted time"
-class VolumeBuildErrorException(TempestException):
+class VolumeBuildErrorException(exceptions.TempestException):
message = "Volume %(volume_id)s failed to build and is in ERROR status"
-class VolumeRestoreErrorException(TempestException):
+class VolumeRestoreErrorException(exceptions.TempestException):
message = "Volume %(volume_id)s failed to restore and is in ERROR status"
-class SnapshotBuildErrorException(TempestException):
+class SnapshotBuildErrorException(exceptions.TempestException):
message = "Snapshot %(snapshot_id)s failed to build and is in ERROR status"
-class VolumeBackupException(TempestException):
+class VolumeBackupException(exceptions.TempestException):
message = "Volume backup %(backup_id)s failed and is in ERROR status"
-class StackBuildErrorException(TempestException):
+class StackBuildErrorException(exceptions.TempestException):
message = ("Stack %(stack_identifier)s is in %(stack_status)s status "
"due to '%(stack_status_reason)s'")
-class EndpointNotFound(TempestException):
- message = "Endpoint not found"
-
-
-class IdentityError(TempestException):
- message = "Got identity error"
-
-
-class ServerUnreachable(TempestException):
+class ServerUnreachable(exceptions.TempestException):
message = "The server is not reachable via the configured network"
# NOTE(andreaf) This exception is added here to facilitate the migration
# of get_network_from_name and preprov_creds to tempest.lib, and it should
# be migrated along with them
-class InvalidTestResource(TempestException):
+class InvalidTestResource(exceptions.TempestException):
message = "%(name) is not a valid %(type), or the name is ambiguous"
-class RFCViolation(RestClientException):
+class RFCViolation(exceptions.RestClientException):
message = "RFC Violation"
-
-
-class InvalidHttpSuccessCode(RestClientException):
- message = "The success code is different than the expected one"
-
-
-class BadRequest(RestClientException):
- message = "Bad request"
-
-
-class ResponseWithNonEmptyBody(RFCViolation):
- message = ("RFC Violation! Response with %(status)d HTTP Status Code "
- "MUST NOT have a body")
-
-
-class ResponseWithEntity(RFCViolation):
- message = ("RFC Violation! Response with 205 HTTP Status Code "
- "MUST NOT have an entity")
-
-
-class InvalidHTTPResponseHeader(RestClientException):
- message = "HTTP response header is invalid"
-
-
-class InvalidStructure(TempestException):
- message = "Invalid structure of table with details"
-
-
-class CommandFailed(Exception):
- def __init__(self, returncode, cmd, output, stderr):
- super(CommandFailed, self).__init__()
- self.returncode = returncode
- self.cmd = cmd
- self.stdout = output
- self.stderr = stderr
-
- def __str__(self):
- return ("Command '%s' returned non-zero exit status %d.\n"
- "stdout:\n%s\n"
- "stderr:\n%s" % (self.cmd,
- self.returncode,
- self.stdout,
- self.stderr))
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 259bbbb..2a6a788 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -149,6 +149,10 @@
message = "Unexpected response code received"
+class InvalidIdentityVersion(TempestException):
+ message = "Invalid version %(identity_version)s of the identity service"
+
+
class InvalidStructure(TempestException):
message = "Invalid structure of table with details"
diff --git a/tempest/manager.py b/tempest/manager.py
index 72762ab..f2659a8 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -14,8 +14,8 @@
# under the License.
from tempest import config
-from tempest import exceptions
from tempest.lib import auth
+from tempest.lib import exceptions
CONF = config.CONF
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 6994b9c..dd6e0e5 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -23,6 +23,7 @@
import six
from tempest.common import compute
+from tempest.common import image as common_image
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
@@ -30,7 +31,6 @@
from tempest import exceptions
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
-from tempest.scenario import network_resources
import tempest.test
CONF = config.CONF
@@ -224,7 +224,7 @@
port = self._create_port(network_id=net_id,
client=clients.ports_client,
**create_port_body)
- ports.append({'port': port.id})
+ ports.append({'port': port['id']})
if ports:
kwargs['networks'] = ports
self.ports = ports
@@ -469,7 +469,8 @@
cleanup_args=[_image_client.delete_image, image_id])
if CONF.image_feature_enabled.api_v1:
# In glance v1 the additional properties are stored in the headers.
- snapshot_image = _image_client.check_image(image_id)
+ resp = _image_client.check_image(image_id)
+ snapshot_image = common_image.get_image_meta_from_headers(resp)
image_props = snapshot_image.get('properties', {})
else:
# In glance v2 the additional properties are flattened.
@@ -705,12 +706,12 @@
tenant_id = networks_client.tenant_id
name = data_utils.rand_name(namestart)
result = networks_client.create_network(name=name, tenant_id=tenant_id)
- network = network_resources.DeletableNetwork(
- networks_client=networks_client, routers_client=routers_client,
- **result['network'])
- self.assertEqual(network.name, name)
+ network = result['network']
+
+ self.assertEqual(network['name'], name)
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
- network.delete)
+ self.networks_client.delete_network,
+ network['id'])
return network
def _list_networks(self, *args, **kwargs):
@@ -780,13 +781,13 @@
# blocks until an unallocated block is found.
for subnet_cidr in tenant_cidr.subnet(num_bits):
str_cidr = str(subnet_cidr)
- if cidr_in_use(str_cidr, tenant_id=network.tenant_id):
+ if cidr_in_use(str_cidr, tenant_id=network['tenant_id']):
continue
subnet = dict(
name=data_utils.rand_name(namestart),
- network_id=network.id,
- tenant_id=network.tenant_id,
+ network_id=network['id'],
+ tenant_id=network['tenant_id'],
cidr=str_cidr,
ip_version=ip_version,
**kwargs
@@ -799,11 +800,13 @@
if not is_overlapping_cidr:
raise
self.assertIsNotNone(result, 'Unable to allocate tenant network')
- subnet = network_resources.DeletableSubnet(
- subnets_client=subnets_client,
- routers_client=routers_client, **result['subnet'])
- self.assertEqual(subnet.cidr, str_cidr)
- self.addCleanup(test_utils.call_and_ignore_notfound_exc, subnet.delete)
+
+ subnet = result['subnet']
+ self.assertEqual(subnet['cidr'], str_cidr)
+
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ subnets_client.delete_subnet, subnet['id'])
+
return subnet
def _create_port(self, network_id, client=None, namestart='port-quotatest',
@@ -816,9 +819,9 @@
network_id=network_id,
**kwargs)
self.assertIsNotNone(result, 'Unable to allocate port')
- port = network_resources.DeletablePort(ports_client=client,
- **result['port'])
- self.addCleanup(test_utils.call_and_ignore_notfound_exc, port.delete)
+ port = result['port']
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ client.delete_port, port['id'])
return port
def _get_server_port_id_and_ip4(self, server, ip_addr=None):
@@ -853,7 +856,7 @@
net = self._list_networks(name=network_name)
self.assertNotEqual(len(net), 0,
"Unable to get network by name: %s" % network_name)
- return network_resources.AttributeDict(net[0])
+ return net[0]
def create_floating_ip(self, thing, external_network_id=None,
port_id=None, client=None):
@@ -872,44 +875,51 @@
tenant_id=thing['tenant_id'],
fixed_ip_address=ip4
)
- floating_ip = network_resources.DeletableFloatingIp(
- client=client,
- **result['floatingip'])
+ floating_ip = result['floatingip']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
- floating_ip.delete)
+ self.floating_ips_client.delete_floatingip,
+ floating_ip['id'])
return floating_ip
def _associate_floating_ip(self, floating_ip, server):
port_id, _ = self._get_server_port_id_and_ip4(server)
- floating_ip.update(port_id=port_id)
- self.assertEqual(port_id, floating_ip.port_id)
+ kwargs = dict(port_id=port_id)
+ floating_ip = self.floating_ips_client.update_floatingip(
+ floating_ip['id'], **kwargs)['floatingip']
+ self.assertEqual(port_id, floating_ip['port_id'])
return floating_ip
def _disassociate_floating_ip(self, floating_ip):
- """:param floating_ip: type DeletableFloatingIp"""
- floating_ip.update(port_id=None)
- self.assertIsNone(floating_ip.port_id)
+ """:param floating_ip: floating_ips_client.create_floatingip"""
+ kwargs = dict(port_id=None)
+ floating_ip = self.floating_ips_client.update_floatingip(
+ floating_ip['id'], **kwargs)['floatingip']
+ self.assertIsNone(floating_ip['port_id'])
return floating_ip
def check_floating_ip_status(self, floating_ip, status):
"""Verifies floatingip reaches the given status
- :param floating_ip: network_resources.DeletableFloatingIp floating
- IP to check status
+ :param dict floating_ip: floating IP dict to check status
:param status: target status
:raises: AssertionError if status doesn't match
"""
+ floatingip_id = floating_ip['id']
+
def refresh():
- floating_ip.refresh()
- return status == floating_ip.status
+ result = (self.floating_ips_client.
+ show_floatingip(floatingip_id)['floatingip'])
+ return status == result['status']
tempest.test.call_until_true(refresh,
CONF.network.build_timeout,
CONF.network.build_interval)
- self.assertEqual(status, floating_ip.status,
+ floating_ip = self.floating_ips_client.show_floatingip(
+ floatingip_id)['floatingip']
+ self.assertEqual(status, floating_ip['status'],
message="FloatingIP: {fp} is at status: {cst}. "
"failed to reach status: {st}"
- .format(fp=floating_ip, cst=floating_ip.status,
+ .format(fp=floating_ip, cst=floating_ip['status'],
st=status))
LOG.info("FloatingIP: {fp} is at status: {st}"
.format(fp=floating_ip, st=status))
@@ -982,8 +992,8 @@
secgroup=secgroup,
security_groups_client=security_groups_client)
for rule in rules:
- self.assertEqual(tenant_id, rule.tenant_id)
- self.assertEqual(secgroup.id, rule.security_group_id)
+ self.assertEqual(tenant_id, rule['tenant_id'])
+ self.assertEqual(secgroup['id'], rule['security_group_id'])
return secgroup
def _create_empty_security_group(self, client=None, tenant_id=None,
@@ -995,7 +1005,7 @@
- IPv6 egress to any
:param tenant_id: secgroup will be created in this tenant
- :returns: DeletableSecurityGroup -- containing the secgroup created
+ :returns: the created security group
"""
if client is None:
client = self.security_groups_client
@@ -1007,15 +1017,14 @@
description=sg_desc)
sg_dict['tenant_id'] = tenant_id
result = client.create_security_group(**sg_dict)
- secgroup = network_resources.DeletableSecurityGroup(
- client=client, routers_client=self.routers_client,
- **result['security_group']
- )
- self.assertEqual(secgroup.name, sg_name)
- self.assertEqual(tenant_id, secgroup.tenant_id)
- self.assertEqual(secgroup.description, sg_desc)
+
+ secgroup = result['security_group']
+ self.assertEqual(secgroup['name'], sg_name)
+ self.assertEqual(tenant_id, secgroup['tenant_id'])
+ self.assertEqual(secgroup['description'], sg_desc)
+
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
- secgroup.delete)
+ client.delete_security_group, secgroup['id'])
return secgroup
def _default_security_group(self, client=None, tenant_id=None):
@@ -1033,8 +1042,7 @@
]
msg = "No default security group for tenant %s." % (tenant_id)
self.assertTrue(len(sgs) > 0, msg)
- return network_resources.DeletableSecurityGroup(client=client,
- **sgs[0])
+ return sgs[0]
def _create_security_group_rule(self, secgroup=None,
sec_group_rules_client=None,
@@ -1045,7 +1053,7 @@
Create a rule in a secgroup. if secgroup not defined will search for
default secgroup in tenant_id.
- :param secgroup: type DeletableSecurityGroup.
+ :param secgroup: the security group.
:param tenant_id: if secgroup not passed -- the tenant in which to
search for default secgroup
:param kwargs: a dictionary containing rule parameters:
@@ -1067,17 +1075,15 @@
secgroup = self._default_security_group(
client=security_groups_client, tenant_id=tenant_id)
- ruleset = dict(security_group_id=secgroup.id,
- tenant_id=secgroup.tenant_id)
+ ruleset = dict(security_group_id=secgroup['id'],
+ tenant_id=secgroup['tenant_id'])
ruleset.update(kwargs)
sg_rule = sec_group_rules_client.create_security_group_rule(**ruleset)
- sg_rule = network_resources.DeletableSecurityGroupRule(
- client=sec_group_rules_client,
- **sg_rule['security_group_rule']
- )
- self.assertEqual(secgroup.tenant_id, sg_rule.tenant_id)
- self.assertEqual(secgroup.id, sg_rule.security_group_id)
+ sg_rule = sg_rule['security_group_rule']
+
+ self.assertEqual(secgroup['tenant_id'], sg_rule['tenant_id'])
+ self.assertEqual(secgroup['id'], sg_rule['security_group_id'])
return sg_rule
@@ -1131,7 +1137,7 @@
if msg not in ex._error_string:
raise ex
else:
- self.assertEqual(r_direction, sg_rule.direction)
+ self.assertEqual(r_direction, sg_rule['direction'])
rules.append(sg_rule)
return rules
@@ -1153,10 +1159,11 @@
network_id = CONF.network.public_network_id
if router_id:
body = client.show_router(router_id)
- return network_resources.AttributeDict(**body['router'])
+ return body['router']
elif network_id:
router = self._create_router(client, tenant_id)
- router.set_gateway(network_id)
+ kwargs = {'external_gateway_info': dict(network_id=network_id)}
+ router = client.update_router(router['id'], **kwargs)['router']
return router
else:
raise Exception("Neither of 'public_router_id' or "
@@ -1172,15 +1179,18 @@
result = client.create_router(name=name,
admin_state_up=True,
tenant_id=tenant_id)
- router = network_resources.DeletableRouter(routers_client=client,
- **result['router'])
- self.assertEqual(router.name, name)
- self.addCleanup(test_utils.call_and_ignore_notfound_exc, router.delete)
+ router = result['router']
+ self.assertEqual(router['name'], name)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ client.delete_router,
+ router['id'])
return router
def _update_router_admin_state(self, router, admin_state_up):
- router.update(admin_state_up=admin_state_up)
- self.assertEqual(admin_state_up, router.admin_state_up)
+ kwargs = dict(admin_state_up=admin_state_up)
+ router = self.routers_client.update_router(
+ router['id'], **kwargs)['router']
+ self.assertEqual(admin_state_up, router['admin_state_up'])
def create_networks(self, networks_client=None,
routers_client=None, subnets_client=None,
@@ -1213,7 +1223,6 @@
tenant_id=tenant_id)
router = self._get_router(client=routers_client,
tenant_id=tenant_id)
-
subnet_kwargs = dict(network=network,
subnets_client=subnets_client,
routers_client=routers_client)
@@ -1221,7 +1230,17 @@
if dns_nameservers is not None:
subnet_kwargs['dns_nameservers'] = dns_nameservers
subnet = self._create_subnet(**subnet_kwargs)
- subnet.add_to_router(router.id)
+ if not routers_client:
+ routers_client = self.routers_client
+ router_id = router['id']
+ routers_client.add_router_interface(router_id,
+ subnet_id=subnet['id'])
+
+ # save a cleanup job to remove this association between
+ # router and subnet
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ routers_client.remove_router_interface, router_id,
+ subnet_id=subnet['id'])
return network, subnet, router
diff --git a/tempest/scenario/network_resources.py b/tempest/scenario/network_resources.py
deleted file mode 100644
index 667476f..0000000
--- a/tempest/scenario/network_resources.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import abc
-import time
-
-import six
-
-from tempest import exceptions
-from tempest.lib.common.utils import misc
-
-
-class AttributeDict(dict):
- """Provide attribute access (dict.key) to dictionary values."""
-
- def __getattr__(self, name):
- """Allow attribute access for all keys in the dict."""
- if name in self:
- return self[name]
- return super(AttributeDict, self).__getattribute__(name)
-
-
-@six.add_metaclass(abc.ABCMeta)
-class DeletableResource(AttributeDict):
- """Support deletion of neutron resources (networks, subnets)
-
- via a delete() method, as is supported by keystone and nova resources.
- """
-
- def __init__(self, *args, **kwargs):
- self.client = kwargs.pop('client', None)
- self.networks_client = kwargs.pop('networks_client', None)
- self.routers_client = kwargs.pop('routers_client', None)
- self.subnets_client = kwargs.pop('subnets_client', None)
- self.ports_client = kwargs.pop('ports_client', None)
- super(DeletableResource, self).__init__(*args, **kwargs)
-
- def __str__(self):
- return '<%s id="%s" name="%s">' % (self.__class__.__name__,
- self.id, self.name)
-
- @abc.abstractmethod
- def delete(self):
- return
-
- @abc.abstractmethod
- def refresh(self):
- return
-
- def __hash__(self):
- return hash(self.id)
-
- def wait_for_status(self, status):
- if not hasattr(self, 'status'):
- return
-
- def helper_get():
- self.refresh()
- return self
-
- return self.wait_for_resource_status(helper_get, status)
-
- def wait_for_resource_status(self, fetch, status):
- """Waits for a network resource to reach a status
-
- @param fetch: the callable to be used to query the resource status
- @type fetch: callable that takes no parameters and returns the resource
- @param status: the status that the resource has to reach
- @type status: String
- """
- interval = self.build_interval
- timeout = self.build_timeout
- start_time = time.time()
-
- while time.time() - start_time <= timeout:
- resource = fetch()
- if resource['status'] == status:
- return
- time.sleep(interval)
-
- # At this point, the wait has timed out
- message = 'Resource %s' % (str(resource))
- message += ' failed to reach status %s' % status
- message += ' (current: %s)' % resource['status']
- message += ' within the required time %s' % timeout
- caller = misc.find_test_caller()
- if caller:
- message = '(%s) %s' % (caller, message)
- raise exceptions.TimeoutException(message)
-
-
-class DeletableNetwork(DeletableResource):
-
- def delete(self):
- self.networks_client.delete_network(self.id)
-
-
-class DeletableSubnet(DeletableResource):
-
- def __init__(self, *args, **kwargs):
- super(DeletableSubnet, self).__init__(*args, **kwargs)
- self._router_ids = set()
-
- def update(self, *args, **kwargs):
- result = self.subnets_client.update_subnet(self.id,
- *args,
- **kwargs)
- return super(DeletableSubnet, self).update(**result['subnet'])
-
- def add_to_router(self, router_id):
- self._router_ids.add(router_id)
- self.routers_client.add_router_interface(router_id,
- subnet_id=self.id)
-
- def delete(self):
- for router_id in self._router_ids.copy():
- self.routers_client.remove_router_interface(router_id,
- subnet_id=self.id)
- self._router_ids.remove(router_id)
- self.subnets_client.delete_subnet(self.id)
-
-
-class DeletableRouter(DeletableResource):
-
- def set_gateway(self, network_id):
- return self.update(external_gateway_info=dict(network_id=network_id))
-
- def unset_gateway(self):
- return self.update(external_gateway_info=dict())
-
- def update(self, *args, **kwargs):
- result = self.routers_client.update_router(self.id,
- *args,
- **kwargs)
- return super(DeletableRouter, self).update(**result['router'])
-
- def delete(self):
- self.unset_gateway()
- self.routers_client.delete_router(self.id)
-
-
-class DeletableFloatingIp(DeletableResource):
-
- def refresh(self, *args, **kwargs):
- result = self.client.show_floatingip(self.id,
- *args,
- **kwargs)
- super(DeletableFloatingIp, self).update(**result['floatingip'])
-
- def update(self, *args, **kwargs):
- result = self.client.update_floatingip(self.id,
- *args,
- **kwargs)
- super(DeletableFloatingIp, self).update(**result['floatingip'])
-
- def __repr__(self):
- return '<%s addr="%s">' % (self.__class__.__name__,
- self.floating_ip_address)
-
- def __str__(self):
- return '<"FloatingIP" addr="%s" id="%s">' % (self.floating_ip_address,
- self.id)
-
- def delete(self):
- self.client.delete_floatingip(self.id)
-
-
-class DeletablePort(DeletableResource):
-
- def delete(self):
- self.ports_client.delete_port(self.id)
-
-
-class DeletableSecurityGroup(DeletableResource):
-
- def delete(self):
- self.client.delete_security_group(self.id)
-
-
-class DeletableSecurityGroupRule(DeletableResource):
-
- def __repr__(self):
- return '<%s id="%s">' % (self.__class__.__name__, self.id)
-
- def delete(self):
- self.client.delete_security_group_rule(self.id)
-
-
-class DeletablePool(DeletableResource):
-
- def delete(self):
- self.client.delete_pool(self.id)
-
-
-class DeletableMember(DeletableResource):
-
- def delete(self):
- self.client.delete_member(self.id)
-
-
-class DeletableVip(DeletableResource):
-
- def delete(self):
- self.client.delete_vip(self.id)
-
- def refresh(self):
- result = self.client.show_vip(self.id)
- super(DeletableVip, self).update(**result['vip'])
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index bfdb0c2..e4b699e 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -61,7 +61,7 @@
server_name = data_utils.rand_name('server-smoke')
server = self.create_server(
name=server_name,
- networks=[{'uuid': network.id}],
+ networks=[{'uuid': network['id']}],
key_name=keypair['name'],
security_groups=security_groups,
wait_until='ACTIVE')
@@ -81,7 +81,7 @@
server, username, private_key,
should_connect=should_connect,
servers_for_debug=[server])
- floating_ip_addr = floating_ip.floating_ip_address
+ floating_ip_addr = floating_ip['floating_ip_address']
# Check FloatingIP status before checking the connectivity
self.check_floating_ip_status(floating_ip, 'ACTIVE')
self.check_public_network_connectivity(floating_ip_addr, username,
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index f5134e5..402a70c 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -25,7 +25,6 @@
from tempest import exceptions
from tempest.lib.common.utils import test_utils
from tempest.scenario import manager
-from tempest.scenario import network_resources
from tempest import test
CONF = config.CONF
@@ -114,7 +113,7 @@
self.port_id = None
if boot_with_port:
# create a port on the network and boot with that
- self.port_id = self._create_port(self.network['id']).id
+ self.port_id = self._create_port(self.network['id'])['id']
self.ports.append({'port': self.port_id})
name = data_utils.rand_name('server-smoke')
@@ -133,30 +132,30 @@
seen_nets = self._list_networks()
seen_names = [n['name'] for n in seen_nets]
seen_ids = [n['id'] for n in seen_nets]
- self.assertIn(self.network.name, seen_names)
- self.assertIn(self.network.id, seen_ids)
+ self.assertIn(self.network['name'], seen_names)
+ self.assertIn(self.network['id'], seen_ids)
if self.subnet:
seen_subnets = self._list_subnets()
seen_net_ids = [n['network_id'] for n in seen_subnets]
seen_subnet_ids = [n['id'] for n in seen_subnets]
- self.assertIn(self.network.id, seen_net_ids)
- self.assertIn(self.subnet.id, seen_subnet_ids)
+ self.assertIn(self.network['id'], seen_net_ids)
+ self.assertIn(self.subnet['id'], seen_subnet_ids)
if self.router:
seen_routers = self._list_routers()
seen_router_ids = [n['id'] for n in seen_routers]
seen_router_names = [n['name'] for n in seen_routers]
- self.assertIn(self.router.name,
+ self.assertIn(self.router['name'],
seen_router_names)
- self.assertIn(self.router.id,
+ self.assertIn(self.router['id'],
seen_router_ids)
def _create_server(self, name, network, port_id=None):
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
security_groups = [{'name': self.security_group['name']}]
- network = {'uuid': network.id}
+ network = {'uuid': network['id']}
if port_id is not None:
network['port'] = port_id
@@ -198,7 +197,7 @@
"""
ssh_login = CONF.validation.image_ssh_user
floating_ip, server = self.floating_ip_tuple
- ip_address = floating_ip.floating_ip_address
+ ip_address = floating_ip['floating_ip_address']
private_key = None
floatingip_status = 'DOWN'
if should_connect:
@@ -239,7 +238,7 @@
def _hotplug_server(self):
old_floating_ip, server = self.floating_ip_tuple
- ip_address = old_floating_ip.floating_ip_address
+ ip_address = old_floating_ip['floating_ip_address']
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(
ip_address, private_key=private_key)
@@ -250,7 +249,7 @@
old_port = port_list[0]
interface = self.interface_client.create_interface(
server_id=server['id'],
- net_id=self.new_net.id)['interfaceAttachment']
+ net_id=self.new_net['id'])['interfaceAttachment']
self.addCleanup(self.ports_client.wait_for_resource_deletion,
interface['port_id'])
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
@@ -270,9 +269,7 @@
"Old port: %s. Number of new ports: %d" % (
CONF.network.build_timeout, old_port,
len(self.new_port_list)))
- new_port = network_resources.DeletablePort(
- ports_client=self.ports_client,
- **self.new_port_list[0])
+ new_port = self.new_port_list[0]
def check_new_nic():
new_nic_list = self._get_server_nics(ssh_client)
@@ -287,7 +284,8 @@
num, new_nic = self.diff_list[0]
ssh_client.assign_static_ip(nic=new_nic,
- addr=new_port.fixed_ips[0]['ip_address'])
+ addr=new_port['fixed_ips'][0][
+ 'ip_address'])
ssh_client.set_nic_state(nic=new_nic)
def _get_server_nics(self, ssh_client):
@@ -307,7 +305,7 @@
# get all network ports in the new network
internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
self._list_ports(tenant_id=server['tenant_id'],
- network_id=network.id)
+ network_id=network['id'])
if p['device_owner'].startswith('network'))
self._check_server_connectivity(floating_ip,
@@ -335,7 +333,7 @@
def _check_server_connectivity(self, floating_ip, address_list,
should_connect=True):
- ip_address = floating_ip.floating_ip_address
+ ip_address = floating_ip['floating_ip_address']
private_key = self._get_server_key(self.floating_ip_tuple.server)
ssh_source = self.get_remote_client(
ip_address, private_key=private_key)
@@ -451,7 +449,13 @@
self._create_server(name, self.new_net)
self._check_network_internal_connectivity(network=self.new_net,
should_connect=False)
- self.new_subnet.add_to_router(self.router.id)
+ router_id = self.router['id']
+ self.routers_client.add_router_interface(
+ router_id, subnet_id=self.new_subnet['id'])
+
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
+ router_id, subnet_id=self.new_subnet['id'])
self._check_network_internal_connectivity(network=self.new_net,
should_connect=True)
@@ -553,7 +557,7 @@
self.check_public_network_connectivity(should_connect=True)
floating_ip, server = self.floating_ip_tuple
- ip_address = floating_ip.floating_ip_address
+ ip_address = floating_ip['floating_ip_address']
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(
ip_address, private_key=private_key)
@@ -568,9 +572,11 @@
act_serv=servers,
trgt_serv=dns_servers))
- self.subnet.update(dns_nameservers=[alt_dns_server])
+ self.subnet = self.subnets_client.update_subnet(
+ self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
+
# asserts that Neutron DB has updated the nameservers
- self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
+ self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
"Failed to update subnet's nameservers")
def check_new_dns_server():
@@ -695,7 +701,8 @@
# NOTE(kevinbenton): we have to use the admin credentials to check
# for the distributed flag because self.router only has a project view.
- admin = self.admin_manager.routers_client.show_router(self.router.id)
+ admin = self.admin_manager.routers_client.show_router(
+ self.router['id'])
if admin['router'].get('distributed', False):
msg = "Rescheduling test does not apply to distributed routers."
raise self.skipException(msg)
@@ -704,16 +711,16 @@
# remove resource from agents
hosting_agents = set(a["id"] for a in
- list_hosts(self.router.id)['agents'])
+ list_hosts(self.router['id'])['agents'])
no_migration = agent_list_alive == hosting_agents
LOG.info("Router will be assigned to {mig} hosting agent".
format(mig="the same" if no_migration else "a new"))
for hosting_agent in hosting_agents:
- unschedule_router(hosting_agent, self.router.id)
+ unschedule_router(hosting_agent, self.router['id'])
self.assertNotIn(hosting_agent,
[a["id"] for a in
- list_hosts(self.router.id)['agents']],
+ list_hosts(self.router['id'])['agents']],
'unscheduling router failed')
# verify resource is un-functional
@@ -730,7 +737,7 @@
router_id=self.router['id'])
self.assertEqual(
target_agent,
- list_hosts(self.router.id)['agents'][0]['id'],
+ list_hosts(self.router['id'])['agents'][0]['id'],
"Router failed to reschedule. Hosting agent doesn't match "
"target agent")
@@ -776,12 +783,12 @@
network_id=self.new_net["id"])
spoof_port = new_ports[0]
private_key = self._get_server_key(server)
- ssh_client = self.get_remote_client(fip.floating_ip_address,
+ ssh_client = self.get_remote_client(fip['floating_ip_address'],
private_key=private_key)
spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
name = data_utils.rand_name('peer')
peer = self._create_server(name, self.new_net)
- peer_address = peer['addresses'][self.new_net.name][0]['addr']
+ peer_address = peer['addresses'][self.new_net['name']][0]['addr']
self._check_remote_connectivity(ssh_client, dest=peer_address,
nic=spoof_nic, should_succeed=True)
ssh_client.set_mac_address(spoof_nic, spoof_mac)
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index a52d8f9..59ebb7a 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -17,6 +17,7 @@
import six
from tempest import config
+from tempest.lib.common.utils import test_utils
from tempest.scenario import manager
from tempest import test
@@ -82,8 +83,12 @@
ip_version=4)
router = self._get_router(tenant_id=self.tenant_id)
- sub4.add_to_router(router_id=router['id'])
- self.addCleanup(sub4.delete)
+ self.routers_client.add_router_interface(router['id'],
+ subnet_id=sub4['id'])
+
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
+ router['id'], subnet_id=sub4['id'])
self.subnets_v6 = []
for _ in range(n_subnets6):
@@ -94,10 +99,14 @@
ipv6_ra_mode=address6_mode,
ipv6_address_mode=address6_mode)
- sub6.add_to_router(router_id=router['id'])
- self.addCleanup(sub6.delete)
- self.subnets_v6.append(sub6)
+ self.routers_client.add_router_interface(router['id'],
+ subnet_id=sub6['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
+ router['id'], subnet_id=sub6['id'])
+
+ self.subnets_v6.append(sub6)
return [self.network, self.network_v6] if dualnet else [self.network]
@staticmethod
@@ -119,12 +128,12 @@
srv = self.create_server(
key_name=self.keypair['name'],
security_groups=[{'name': self.sec_grp['name']}],
- networks=[{'uuid': n.id} for n in networks],
+ networks=[{'uuid': n['id']} for n in networks],
wait_until='ACTIVE')
fip = self.create_floating_ip(thing=srv)
ips = self.define_server_ips(srv=srv)
ssh = self.get_remote_client(
- ip_address=fip.floating_ip_address,
+ ip_address=fip['floating_ip_address'],
username=username)
return ssh, ips, srv["id"]
@@ -139,7 +148,7 @@
"""
ports = [p["mac_address"] for p in
self._list_ports(device_id=sid,
- network_id=self.network_v6.id)]
+ network_id=self.network_v6['id'])]
self.assertEqual(1, len(ports),
message=("Multiple IPv6 ports found on network %s. "
"ports: %s")
@@ -190,11 +199,11 @@
self._check_connectivity(sshv4_1,
ips_from_api_2['6'][i])
self._check_connectivity(sshv4_1,
- self.subnets_v6[i].gateway_ip)
+ self.subnets_v6[i]['gateway_ip'])
self._check_connectivity(sshv4_2,
ips_from_api_1['6'][i])
self._check_connectivity(sshv4_2,
- self.subnets_v6[i].gateway_ip)
+ self.subnets_v6[i]['gateway_ip'])
def _check_connectivity(self, source, dest):
self.assertTrue(
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index adc9008..86185c8 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -227,22 +227,23 @@
seen_names = [n['name'] for n in seen_nets]
seen_ids = [n['id'] for n in seen_nets]
- self.assertIn(tenant.network.name, seen_names)
- self.assertIn(tenant.network.id, seen_ids)
+ self.assertIn(tenant.network['name'], seen_names)
+ self.assertIn(tenant.network['id'], seen_ids)
seen_subnets = [(n['id'], n['cidr'], n['network_id'])
for n in self._list_subnets()]
- mysubnet = (tenant.subnet.id, tenant.subnet.cidr, tenant.network.id)
+ mysubnet = (tenant.subnet['id'], tenant.subnet['cidr'],
+ tenant.network['id'])
self.assertIn(mysubnet, seen_subnets)
seen_routers = self._list_routers()
seen_router_ids = [n['id'] for n in seen_routers]
seen_router_names = [n['name'] for n in seen_routers]
- self.assertIn(tenant.router.name, seen_router_names)
- self.assertIn(tenant.router.id, seen_router_ids)
+ self.assertIn(tenant.router['name'], seen_router_names)
+ self.assertIn(tenant.router['id'], seen_router_ids)
- myport = (tenant.router.id, tenant.subnet.id)
+ myport = (tenant.router['id'], tenant.subnet['id'])
router_ports = [(i['device_id'], i['fixed_ips'][0]['subnet_id']) for i
in self._list_ports()
if self._is_router_port(i)]
@@ -270,7 +271,7 @@
kwargs["scheduler_hints"] = {'different_host': self.servers}
server = self.create_server(
name=name,
- networks=[{'uuid': tenant.network.id}],
+ networks=[{'uuid': tenant.network["id"]}],
key_name=tenant.keypair['name'],
security_groups=security_groups_names,
wait_until='ACTIVE',
@@ -353,10 +354,10 @@
def _get_server_ip(self, server, floating=False):
"""returns the ip (floating/internal) of a server"""
if floating:
- server_ip = self.floating_ips[server['id']].floating_ip_address
+ server_ip = self.floating_ips[server['id']]['floating_ip_address']
else:
server_ip = None
- network_name = self.tenants[server['tenant_id']].network.name
+ network_name = self.tenants[server['tenant_id']].network['name']
if network_name in server['addresses']:
server_ip = server['addresses'][network_name][0]['addr']
return server_ip
@@ -364,7 +365,7 @@
def _connect_to_access_point(self, tenant):
"""create ssh connection to tenant access point"""
access_point_ssh = \
- self.floating_ips[tenant.access_point['id']].floating_ip_address
+ self.floating_ips[tenant.access_point['id']]['floating_ip_address']
private_key = tenant.keypair['private_key']
access_point_ssh = self.get_remote_client(
access_point_ssh, private_key=private_key)
@@ -388,7 +389,7 @@
def _test_in_tenant_allow(self, tenant):
ruleset = dict(
protocol='icmp',
- remote_group_id=tenant.security_groups['default'].id,
+ remote_group_id=tenant.security_groups['default']['id'],
direction='ingress'
)
self._create_security_group_rule(
@@ -464,7 +465,7 @@
for port in port_list if port['fixed_ips']
]
server_ip = self._get_server_ip(tenant.access_point)
- subnet_id = tenant.subnet.id
+ subnet_id = tenant.subnet['id']
self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list)
@test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
@@ -545,7 +546,7 @@
# update port with new security group and check connectivity
self.ports_client.update_port(port_id, security_groups=[
- new_tenant.security_groups['new_sg'].id])
+ new_tenant.security_groups['new_sg']['id']])
self._check_connectivity(
access_point=access_point_ssh,
ip=self._get_server_ip(server))
diff --git a/tempest/services/image/v1/json/image_members_client.py b/tempest/services/image/v1/json/image_members_client.py
index df16d2fd..e7fa0c9 100644
--- a/tempest/services/image/v1/json/image_members_client.py
+++ b/tempest/services/image/v1/json/image_members_client.py
@@ -39,7 +39,7 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
- def add_member(self, member_id, image_id, **kwargs):
+ def create_image_member(self, image_id, member_id, **kwargs):
"""Add a member to an image.
Available params: see http://developer.openstack.org/
@@ -51,7 +51,7 @@
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp)
- def delete_member(self, member_id, image_id):
+ def delete_image_member(self, image_id, member_id):
"""Removes a membership from the image.
Available params: see http://developer.openstack.org/
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index 4ffaf3b..30325c0 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -31,28 +31,6 @@
class ImagesClient(rest_client.RestClient):
api_version = "v1"
- def _image_meta_from_headers(self, headers):
- meta = {'properties': {}}
- for key, value in six.iteritems(headers):
- if key.startswith('x-image-meta-property-'):
- _key = key[22:]
- meta['properties'][_key] = value
- elif key.startswith('x-image-meta-'):
- _key = key[13:]
- meta[_key] = value
-
- for key in ['is_public', 'protected', 'deleted']:
- if key in meta:
- meta[key] = meta[key].strip().lower() in ('t', 'true', 'yes',
- '1')
- for key in ['size', 'min_ram', 'min_disk']:
- if key in meta:
- try:
- meta[key] = int(meta[key])
- except ValueError:
- pass
- return meta
-
def _image_meta_to_headers(self, fields):
headers = {}
fields_copy = copy.deepcopy(fields)
@@ -98,9 +76,13 @@
self._http = self._get_http()
return self._http
- def create_image(self, **kwargs):
+ def create_image(self, data=None, **kwargs):
+ """Create an image.
+
+ Available params: http://developer.openstack.org/
+ api-ref-image-v1.html#createImage-v1
+ """
headers = {}
- data = kwargs.pop('data', None)
headers.update(self._image_meta_to_headers(kwargs))
if data is not None:
@@ -111,9 +93,13 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
- def update_image(self, image_id, **kwargs):
+ def update_image(self, image_id, data=None, **kwargs):
+ """Update an image.
+
+ Available params: http://developer.openstack.org/
+ api-ref-image-v1.html#updateImage-v1
+ """
headers = {}
- data = kwargs.pop('data', None)
headers.update(self._image_meta_to_headers(kwargs))
if data is not None:
@@ -164,9 +150,8 @@
def check_image(self, image_id):
"""Check image metadata."""
url = 'images/%s' % image_id
- resp, __ = self.head(url)
+ resp, body = self.head(url)
self.expected_success(200, resp.status)
- body = self._image_meta_from_headers(resp)
return rest_client.ResponseBody(resp, body)
def show_image(self, image_id):
@@ -178,7 +163,8 @@
def is_resource_deleted(self, id):
try:
- if self.check_image(id)['status'] == 'deleted':
+ resp = self.check_image(id)
+ if resp.response["x-image-meta-status"] == 'deleted':
return True
except lib_exc.NotFound:
return True
diff --git a/tempest/test.py b/tempest/test.py
index 4c0d0bb..4e06db8 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -39,6 +39,7 @@
from tempest import exceptions
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
LOG = logging.getLogger(__name__)
@@ -539,7 +540,7 @@
if hasattr(cred_provider, credentials_method):
creds = getattr(cred_provider, credentials_method)()
else:
- raise exceptions.InvalidCredentials(
+ raise lib_exc.InvalidCredentials(
"Invalid credentials type %s" % credential_type)
return cls.client_manager(credentials=creds.credentials,
service=cls._service)
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index f253802..b3931d1 100755
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -234,7 +234,7 @@
self.assertIn('admin', resource_types)
self.assertIn(['fake_operator'], resource_types)
self.assertIn(['fake_reseller'], resource_types)
- self.assertIn(['fake_owner'], resource_types)
+ self.assertIn(['fake_owner', 'fake_operator'], resource_types)
for resource in resources:
self.assertIsNotNone(resource[1].network)
self.assertIsNotNone(resource[1].router)
diff --git a/tempest/tests/common/test_image.py b/tempest/tests/common/test_image.py
new file mode 100644
index 0000000..fdd0ae8
--- /dev/null
+++ b/tempest/tests/common/test_image.py
@@ -0,0 +1,40 @@
+# Copyright 2016 NEC Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.common import image
+from tempest.lib.common import rest_client
+from tempest.tests import base
+
+
+class TestImage(base.TestCase):
+
+ def test_get_image_meta_from_headers(self):
+ resp = {
+ 'x-image-meta-id': 'ea30c926-0629-4400-bb6e-f8a8da6a4e56',
+ 'x-image-meta-owner': '8f421f9470e645b1b10f5d2db7804924',
+ 'x-image-meta-status': 'queued',
+ 'x-image-meta-name': 'New Http Image'
+ }
+ respbody = rest_client.ResponseBody(resp)
+ observed = image.get_image_meta_from_headers(respbody)
+
+ expected = {
+ 'properties': {},
+ 'id': 'ea30c926-0629-4400-bb6e-f8a8da6a4e56',
+ 'owner': '8f421f9470e645b1b10f5d2db7804924',
+ 'status': 'queued',
+ 'name': 'New Http Image'
+ }
+ self.assertEqual(expected, observed)
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index c08bf6a..12590a3 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -802,3 +802,12 @@
_, auth_data = self.auth_provider.get_auth()
self.assertIn('domain', auth_data)
self.assertNotIn('project', auth_data)
+
+
+class TestGetCredentials(base.TestCase):
+
+ def test_invalid_identity_version(self):
+ with testtools.ExpectedException(exceptions.InvalidIdentityVersion,
+ '.* v1 .*'):
+ auth.get_credentials('http://localhost/identity/v3',
+ identity_version='v1')