diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/net_resources.py b/vmware_nsx_tempest/tests/nsxv/scenario/net_resources.py index 64686e8b52..cd790f236a 100644 --- a/vmware_nsx_tempest/tests/nsxv/scenario/net_resources.py +++ b/vmware_nsx_tempest/tests/nsxv/scenario/net_resources.py @@ -15,7 +15,8 @@ # This module inherents from resources module and enhances router functions # and block subnet's add_to/delete_from_router so it is more similar to CLI. -from tempest.scenario import network_resources as n_resources +# from tempest.scenario import network_resources as n_resources +import network_resources as n_resources DELETABLE_CLASS_DEF = """class %(cls_name)s(n_resources.%(cls_name)s): diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/network_resources.py b/vmware_nsx_tempest/tests/nsxv/scenario/network_resources.py new file mode 100644 index 0000000000..667476f0fe --- /dev/null +++ b/vmware_nsx_tempest/tests/nsxv/scenario/network_resources.py @@ -0,0 +1,220 @@ +# 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/vmware_nsx_tempest/tests/nsxv/scenario/test_dvr_basic_ops.py b/vmware_nsx_tempest/tests/nsxv/scenario/test_dvr_basic_ops.py index 3badfc8495..d7724016e7 100644 --- a/vmware_nsx_tempest/tests/nsxv/scenario/test_dvr_basic_ops.py +++ b/vmware_nsx_tempest/tests/nsxv/scenario/test_dvr_basic_ops.py @@ -18,15 +18,16 @@ import re import time from oslo_log import log as logging -from tempest.lib.common.utils import data_utils import testtools from tempest import config from tempest import exceptions +from tempest.lib.common.utils import data_utils from tempest.scenario import manager -from tempest.scenario import network_resources as net_resources from tempest import test +from vmware_nsx_tempest.tests.nsxv.scenario import net_resources + CONF = config.CONF FIP_OPS_TIMEOUT = 10 LOG = logging.getLogger(__name__) @@ -81,8 +82,8 @@ class TestDvrBasicOps(manager.NetworkScenarioTest): @classmethod def skip_checks(cls): super(TestDvrBasicOps, cls).skip_checks() - if not (CONF.network.project_networks_reachable - or CONF.network.public_network_id): + if not (CONF.network.project_networks_reachable or + CONF.network.public_network_id): msg = ('Either project_networks_reachable must be "true", or ' 'public_network_id must be defined.') raise cls.skipException(msg) diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/test_v1_lbaas_basic_ops.py b/vmware_nsx_tempest/tests/nsxv/scenario/test_v1_lbaas_basic_ops.py index 138dbef4cd..b0b701f89b 100644 --- a/vmware_nsx_tempest/tests/nsxv/scenario/test_v1_lbaas_basic_ops.py +++ b/vmware_nsx_tempest/tests/nsxv/scenario/test_v1_lbaas_basic_ops.py @@ -20,15 +20,14 @@ import tempfile import time import urllib2 -from tempest.lib.common.utils import data_utils - from tempest import config from tempest import exceptions +from tempest.lib.common.utils import data_utils from tempest.scenario import manager -from tempest.scenario import network_resources as net_resources from tempest import test from vmware_nsx_tempest.services import load_balancer_v1_client as LBV1C +from vmware_nsx_tempest.tests.nsxv.scenario import net_resources CONF = config.CONF