Merge "[wrappers] Move wrappers under plugins.openstack"
This commit is contained in:
commit
02b38b6268
@ -16,8 +16,8 @@
|
||||
from oslo_utils import uuidutils as uid
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark.wrappers import network as network_wrapper
|
||||
from rally.common import log as logging
|
||||
from rally.plugins.openstack.wrappers import network as network_wrapper
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,12 +19,12 @@ from rally.benchmark.scenarios import base
|
||||
from rally.benchmark.scenarios import utils as scenario_utils
|
||||
from rally.benchmark import types as types
|
||||
from rally.benchmark import validation
|
||||
from rally.benchmark.wrappers import network as network_wrapper
|
||||
from rally.common import log as logging
|
||||
from rally import consts
|
||||
from rally import exceptions as rally_exceptions
|
||||
from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils
|
||||
from rally.plugins.openstack.scenarios.nova import utils
|
||||
from rally.plugins.openstack.wrappers import network as network_wrapper
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -21,9 +21,8 @@ import six
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark import utils as bench_utils
|
||||
from rally.benchmark.wrappers import network as network_wrapper
|
||||
from rally import exceptions
|
||||
|
||||
from rally.plugins.openstack.wrappers import network as network_wrapper
|
||||
|
||||
NOVA_BENCHMARK_OPTS = []
|
||||
option_names_and_defaults = [
|
||||
|
@ -21,11 +21,11 @@ import six
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark import utils as bench_utils
|
||||
from rally.benchmark.wrappers import network as network_wrapper
|
||||
from rally.common.i18n import _
|
||||
from rally.common import log as logging
|
||||
from rally.common import sshutils
|
||||
from rally import exceptions
|
||||
from rally.plugins.openstack.wrappers import network as network_wrapper
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
0
rally/plugins/openstack/wrappers/__init__.py
Normal file
0
rally/plugins/openstack/wrappers/__init__.py
Normal file
217
rally/plugins/openstack/wrappers/keystone.py
Normal file
217
rally/plugins/openstack/wrappers/keystone.py
Normal file
@ -0,0 +1,217 @@
|
||||
# Copyright 2014: Mirantis Inc.
|
||||
# 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 collections
|
||||
|
||||
from keystoneclient import exceptions
|
||||
import six
|
||||
|
||||
from rally.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
Project = collections.namedtuple("Project", ["id", "name", "domain_id"])
|
||||
User = collections.namedtuple("User",
|
||||
["id", "name", "project_id", "domain_id"])
|
||||
Service = collections.namedtuple("Service", ["id", "name"])
|
||||
Role = collections.namedtuple("Role", ["id", "name"])
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class KeystoneWrapper(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def __getattr__(self, attr_name):
|
||||
return getattr(self.client, attr_name)
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_project(self, project_name, domain_name="Default"):
|
||||
"""Creates new project/tenant and return project object.
|
||||
|
||||
:param project_name: Name of project to be created.
|
||||
:param domain_name: Name or id of domain where to create project, for
|
||||
implementations that don't support domains this
|
||||
argument must be None or 'Default'.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_project(self, project_id):
|
||||
"""Deletes project."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_user(self, username, password, email=None, project_id=None,
|
||||
domain_name="Default"):
|
||||
"""Create user.
|
||||
|
||||
:param username: name of user
|
||||
:param password: user password
|
||||
:param project: user's default project
|
||||
:param domain_name: Name or id of domain where to create project, for
|
||||
implementations that don't support domains this
|
||||
argument must be None or 'Default'.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_user(self, user_id):
|
||||
"""Deletes user."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_users(self):
|
||||
"""List all users."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_projects(self):
|
||||
"""List all projects/tenants."""
|
||||
|
||||
def delete_service(self, service_id):
|
||||
"""Deletes service."""
|
||||
self.client.services.delete(service_id)
|
||||
|
||||
def list_services(self):
|
||||
"""List all services."""
|
||||
return map(KeystoneWrapper._wrap_service, self.client.services.list())
|
||||
|
||||
def delete_role(self, role_id):
|
||||
"""Deletes role."""
|
||||
self.client.roles.delete(role_id)
|
||||
|
||||
def list_roles(self):
|
||||
"""List all roles."""
|
||||
return map(KeystoneWrapper._wrap_role, self.client.roles.list())
|
||||
|
||||
@staticmethod
|
||||
def _wrap_service(service):
|
||||
return Service(id=service.id, name=service.name)
|
||||
|
||||
@staticmethod
|
||||
def _wrap_role(role):
|
||||
return Role(id=role.id, name=role.name)
|
||||
|
||||
|
||||
class KeystoneV2Wrapper(KeystoneWrapper):
|
||||
def _check_domain(self, domain_name):
|
||||
if domain_name.lower() != "default":
|
||||
raise NotImplementedError("Domain functionality not implemented "
|
||||
"in Keystone v2")
|
||||
|
||||
@staticmethod
|
||||
def _wrap_v2_tenant(tenant):
|
||||
return Project(id=tenant.id, name=tenant.name, domain_id="default")
|
||||
|
||||
@staticmethod
|
||||
def _wrap_v2_user(user):
|
||||
return User(id=user.id, name=user.name,
|
||||
project_id=getattr(user, "tenantId", None),
|
||||
domain_id="default")
|
||||
|
||||
def create_project(self, project_name, domain_name="Default"):
|
||||
self._check_domain(domain_name)
|
||||
tenant = self.client.tenants.create(project_name)
|
||||
return KeystoneV2Wrapper._wrap_v2_tenant(tenant)
|
||||
|
||||
def delete_project(self, project_id):
|
||||
self.client.tenants.delete(project_id)
|
||||
|
||||
def create_user(self, username, password, email=None, project_id=None,
|
||||
domain_name="Default"):
|
||||
self._check_domain(domain_name)
|
||||
user = self.client.users.create(username, password, email, project_id)
|
||||
return KeystoneV2Wrapper._wrap_v2_user(user)
|
||||
|
||||
def delete_user(self, user_id):
|
||||
self.client.users.delete(user_id)
|
||||
|
||||
def list_users(self):
|
||||
return map(KeystoneV2Wrapper._wrap_v2_user, self.client.users.list())
|
||||
|
||||
def list_projects(self):
|
||||
return map(KeystoneV2Wrapper._wrap_v2_tenant,
|
||||
self.client.tenants.list())
|
||||
|
||||
|
||||
class KeystoneV3Wrapper(KeystoneWrapper):
|
||||
def _get_domain_id(self, domain_name_or_id):
|
||||
try:
|
||||
# First try to find domain by ID
|
||||
return self.client.domains.get(domain_name_or_id).id
|
||||
except exceptions.NotFound:
|
||||
# Domain not found by ID, try to find it by name
|
||||
domains = self.client.domains.list(name=domain_name_or_id)
|
||||
if domains:
|
||||
return domains[0].id
|
||||
# Domain not found by name, raise original NotFound exception
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
def _wrap_v3_project(project):
|
||||
return Project(id=project.id, name=project.name,
|
||||
domain_id=project.domain_id)
|
||||
|
||||
@staticmethod
|
||||
def _wrap_v3_user(user):
|
||||
# When user has default_project_id that is None user.default_project_id
|
||||
# will raise AttributeError
|
||||
project_id = getattr(user, "default_project_id", None)
|
||||
return User(id=user.id, name=user.name, project_id=project_id,
|
||||
domain_id=user.domain_id)
|
||||
|
||||
def create_project(self, project_name, domain_name="Default"):
|
||||
domain_id = self._get_domain_id(domain_name)
|
||||
project = self.client.projects.create(
|
||||
name=project_name, domain=domain_id)
|
||||
return KeystoneV3Wrapper._wrap_v3_project(project)
|
||||
|
||||
def delete_project(self, project_id):
|
||||
self.client.projects.delete(project_id)
|
||||
|
||||
def create_user(self, username, password, email=None, project_id=None,
|
||||
domain_name="Default"):
|
||||
domain_id = self._get_domain_id(domain_name)
|
||||
user = self.client.users.create(name=username, password=password,
|
||||
default_project=project_id,
|
||||
email=email, domain=domain_id)
|
||||
for role in self.client.roles.list():
|
||||
if "member" in role.name.lower():
|
||||
self.client.roles.grant(role.id, user=user.id,
|
||||
project=project_id)
|
||||
break
|
||||
else:
|
||||
LOG.warning("Unable to set member role to created user.")
|
||||
return KeystoneV3Wrapper._wrap_v3_user(user)
|
||||
|
||||
def delete_user(self, user_id):
|
||||
self.client.users.delete(user_id)
|
||||
|
||||
def list_users(self):
|
||||
return map(KeystoneV3Wrapper._wrap_v3_user, self.client.users.list())
|
||||
|
||||
def list_projects(self):
|
||||
return map(KeystoneV3Wrapper._wrap_v3_project,
|
||||
self.client.projects.list())
|
||||
|
||||
|
||||
def wrap(client):
|
||||
"""Returns keystone wrapper based on keystone client version."""
|
||||
|
||||
if client.version == "v2.0":
|
||||
return KeystoneV2Wrapper(client)
|
||||
elif client.version == "v3":
|
||||
return KeystoneV3Wrapper(client)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Wrapper for version %s is not implemented." % client.version)
|
407
rally/plugins/openstack/wrappers/network.py
Normal file
407
rally/plugins/openstack/wrappers/network.py
Normal file
@ -0,0 +1,407 @@
|
||||
# Copyright 2014: Mirantis Inc.
|
||||
# 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 netaddr
|
||||
import six
|
||||
|
||||
from rally.benchmark import utils as bench_utils
|
||||
from rally.common.i18n import _
|
||||
from rally.common import log as logging
|
||||
from rally.common import utils
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
|
||||
from neutronclient.common import exceptions as neutron_exceptions
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
cidr_incr = utils.RAMInt()
|
||||
|
||||
|
||||
def generate_cidr(start_cidr="10.2.0.0/24"):
|
||||
"""Generate next CIDR for network or subnet, without IP overlapping.
|
||||
|
||||
This is process and thread safe, because `cidr_incr' points to
|
||||
value stored directly in RAM. This guarantees that CIDRs will be
|
||||
serial and unique even under hard multiprocessing/threading load.
|
||||
|
||||
:param start_cidr: start CIDR str
|
||||
:returns: next available CIDR str
|
||||
"""
|
||||
cidr = str(netaddr.IPNetwork(start_cidr).next(next(cidr_incr)))
|
||||
LOG.debug("CIDR generated: %s" % cidr)
|
||||
return cidr
|
||||
|
||||
|
||||
class NetworkWrapperException(exceptions.RallyException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class NetworkWrapper(object):
|
||||
"""Base class for network service implementations.
|
||||
|
||||
We actually have two network services implementations, with different API:
|
||||
NovaNetwork and Neutron. The idea is (at least to try) to use unified
|
||||
service, which hides most differences and routines behind the scenes.
|
||||
This allows to significantly re-use and simplify code.
|
||||
"""
|
||||
START_CIDR = "10.2.0.0/24"
|
||||
SERVICE_IMPL = None
|
||||
|
||||
def __init__(self, clients, config=None):
|
||||
if hasattr(clients, self.SERVICE_IMPL):
|
||||
self.client = getattr(clients, self.SERVICE_IMPL)()
|
||||
else:
|
||||
self.client = clients(self.SERVICE_IMPL)
|
||||
self.config = config or {}
|
||||
self.start_cidr = self.config.get("start_cidr", self.START_CIDR)
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_network(self):
|
||||
"""Create network."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_network(self):
|
||||
"""Delete network."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_networks(self):
|
||||
"""List networks."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_floating_ip(self):
|
||||
"""Create floating IP."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_floating_ip(self):
|
||||
"""Delete floating IP."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def supports_security_group(self):
|
||||
"""Checks whether security group is supported."""
|
||||
|
||||
|
||||
class NovaNetworkWrapper(NetworkWrapper):
|
||||
SERVICE_IMPL = consts.Service.NOVA
|
||||
|
||||
def __init__(self, *args):
|
||||
super(NovaNetworkWrapper, self).__init__(*args)
|
||||
self.skip_cidrs = [n.cidr for n in self.client.networks.list()]
|
||||
|
||||
def _generate_cidr(self):
|
||||
cidr = generate_cidr(start_cidr=self.start_cidr)
|
||||
while cidr in self.skip_cidrs:
|
||||
cidr = generate_cidr(start_cidr=self.start_cidr)
|
||||
return cidr
|
||||
|
||||
def create_network(self, tenant_id, **kwargs):
|
||||
"""Create network.
|
||||
|
||||
:param tenant_id: str, tenant ID
|
||||
:param **kwargs: for compatibility, not used here
|
||||
:returns: dict, network data
|
||||
"""
|
||||
cidr = self._generate_cidr()
|
||||
label = utils.generate_random_name("rally_net_")
|
||||
network = self.client.networks.create(
|
||||
tenant_id=tenant_id, cidr=cidr, label=label)
|
||||
return {"id": network.id,
|
||||
"cidr": network.cidr,
|
||||
"name": network.label,
|
||||
"status": "ACTIVE",
|
||||
"external": False,
|
||||
"tenant_id": tenant_id}
|
||||
|
||||
def delete_network(self, network):
|
||||
return self.client.networks.delete(network["id"])
|
||||
|
||||
def list_networks(self):
|
||||
return self.client.networks.list()
|
||||
|
||||
def create_floating_ip(self, ext_network=None, **kwargs):
|
||||
"""Allocate a floating ip from the given nova-network pool
|
||||
|
||||
:param ext_network: name or external network, str
|
||||
:param **kwargs: for compatibility, not used here
|
||||
:returns: floating IP dict
|
||||
"""
|
||||
if not ext_network:
|
||||
try:
|
||||
ext_network = self.client.floating_ip_pools.list()[0].name
|
||||
except IndexError:
|
||||
raise NetworkWrapperException("No floating IP pools found")
|
||||
fip = self.client.floating_ips.create(ext_network)
|
||||
return {"id": fip.id, "ip": fip.ip}
|
||||
|
||||
def _get_floating_ip(self, fip_id, do_raise=False):
|
||||
try:
|
||||
fip = self.client.floating_ips.get(fip_id)
|
||||
except nova_exceptions.NotFound:
|
||||
if not do_raise:
|
||||
return None
|
||||
raise exceptions.GetResourceNotFound(
|
||||
resource="Floating IP %s" % fip_id)
|
||||
return fip.id
|
||||
|
||||
def delete_floating_ip(self, fip_id, wait=False):
|
||||
"""Delete floating IP.
|
||||
|
||||
:param fip_id: int floating IP id
|
||||
:param wait: if True then wait to return until floating ip is deleted
|
||||
"""
|
||||
self.client.floating_ips.delete(fip_id)
|
||||
if not wait:
|
||||
return
|
||||
bench_utils.wait_for_delete(
|
||||
fip_id,
|
||||
update_resource=lambda i: self._get_floating_ip(i, do_raise=True))
|
||||
|
||||
def supports_security_group(self):
|
||||
"""Check whether security group is supported
|
||||
|
||||
:return: result tuple. Always (True, "") for nova-network.
|
||||
:rtype: (bool, string)
|
||||
"""
|
||||
return True, ""
|
||||
|
||||
|
||||
class NeutronWrapper(NetworkWrapper):
|
||||
SERVICE_IMPL = consts.Service.NEUTRON
|
||||
SUBNET_IP_VERSION = 4
|
||||
|
||||
@property
|
||||
def external_networks(self):
|
||||
return self.client.list_networks(**{
|
||||
"router:external": True})["networks"]
|
||||
|
||||
def get_network(self, net_id=None, name=None):
|
||||
net = None
|
||||
try:
|
||||
if net_id:
|
||||
net = self.client.show_network(net_id)["network"]
|
||||
else:
|
||||
for net in self.client.list_networks(name=name)["networks"]:
|
||||
break
|
||||
return {"id": net["id"],
|
||||
"name": net["name"],
|
||||
"tenant_id": net["tenant_id"],
|
||||
"status": net["status"],
|
||||
"external": net["router:external"],
|
||||
"subnets": net["subnets"],
|
||||
"router_id": None}
|
||||
except (TypeError, neutron_exceptions.NeutronClientException):
|
||||
raise NetworkWrapperException(
|
||||
"Network not found: %s" % (name or net_id))
|
||||
|
||||
def create_router(self, external=False, **kwargs):
|
||||
"""Create neutron router.
|
||||
|
||||
:param external: bool, whether to set setup external_gateway_info
|
||||
:param **kwargs: POST /v2.0/routers request options
|
||||
:returns: neutron router dict
|
||||
"""
|
||||
if "name" not in kwargs:
|
||||
kwargs["name"] = utils.generate_random_name("rally_router_")
|
||||
|
||||
if external and "external_gateway_info" not in kwargs:
|
||||
for net in self.external_networks:
|
||||
kwargs["external_gateway_info"] = {
|
||||
"network_id": net["id"], "enable_snat": True}
|
||||
return self.client.create_router({"router": kwargs})["router"]
|
||||
|
||||
def _generate_cidr(self):
|
||||
# TODO(amaretskiy): Generate CIDRs unique for network, not cluster
|
||||
return generate_cidr(start_cidr=self.start_cidr)
|
||||
|
||||
def create_network(self, tenant_id, **kwargs):
|
||||
"""Create network.
|
||||
|
||||
:param tenant_id: str, tenant ID
|
||||
:param **kwargs: extra options
|
||||
:returns: dict, network data
|
||||
"""
|
||||
network_args = {
|
||||
"network": {
|
||||
"tenant_id": tenant_id,
|
||||
"name": utils.generate_random_name("rally_net_")
|
||||
}
|
||||
}
|
||||
network = self.client.create_network(network_args)["network"]
|
||||
|
||||
router = None
|
||||
if kwargs.get("add_router", False):
|
||||
router = self.create_router(external=True, tenant_id=tenant_id)
|
||||
|
||||
subnets = []
|
||||
subnets_num = kwargs.get("subnets_num", 0)
|
||||
for i in range(subnets_num):
|
||||
subnet_args = {
|
||||
"subnet": {
|
||||
"tenant_id": tenant_id,
|
||||
"network_id": network["id"],
|
||||
"name": utils.generate_random_name("rally_subnet_"),
|
||||
"ip_version": self.SUBNET_IP_VERSION,
|
||||
"cidr": self._generate_cidr(),
|
||||
"enable_dhcp": True,
|
||||
"dns_nameservers": kwargs.get("dns_nameservers",
|
||||
["8.8.8.8", "8.8.4.4"])
|
||||
}
|
||||
}
|
||||
subnet = self.client.create_subnet(subnet_args)["subnet"]
|
||||
subnets.append(subnet["id"])
|
||||
|
||||
if router:
|
||||
self.client.add_interface_router(router["id"],
|
||||
{"subnet_id": subnet["id"]})
|
||||
|
||||
return {"id": network["id"],
|
||||
"name": network["name"],
|
||||
"status": network["status"],
|
||||
"subnets": subnets,
|
||||
"external": network.get("router:external", False),
|
||||
"router_id": router and router["id"] or None,
|
||||
"tenant_id": tenant_id}
|
||||
|
||||
def delete_network(self, network):
|
||||
net_dhcps = self.client.list_dhcp_agent_hosting_networks(
|
||||
network["id"])["agents"]
|
||||
for net_dhcp in net_dhcps:
|
||||
self.client.remove_network_from_dhcp_agent(net_dhcp["id"],
|
||||
network["id"])
|
||||
router_id = network["router_id"]
|
||||
if router_id:
|
||||
self.client.remove_gateway_router(router_id)
|
||||
for subnet_id in network["subnets"]:
|
||||
self.client.remove_interface_router(router_id,
|
||||
{"subnet_id": subnet_id})
|
||||
self.client.delete_router(router_id)
|
||||
|
||||
for port in self.client.list_ports(network_id=network["id"])["ports"]:
|
||||
self.client.delete_port(port["id"])
|
||||
|
||||
for subnet_id in network["subnets"]:
|
||||
self._delete_subnet(subnet_id)
|
||||
|
||||
return self.client.delete_network(network["id"])
|
||||
|
||||
def _delete_subnet(self, subnet_id):
|
||||
self.client.delete_subnet(subnet_id)
|
||||
|
||||
def list_networks(self):
|
||||
return self.client.list_networks()["networks"]
|
||||
|
||||
def create_port(self, network_id, **kwargs):
|
||||
"""Create neutron port.
|
||||
|
||||
:param network_id: neutron network id
|
||||
:param **kwargs: POST /v2.0/ports request options
|
||||
:returns: neutron port dict
|
||||
"""
|
||||
kwargs["network_id"] = network_id
|
||||
if "name" not in kwargs:
|
||||
kwargs["name"] = utils.generate_random_name("rally_port_")
|
||||
return self.client.create_port({"port": kwargs})["port"]
|
||||
|
||||
def create_floating_ip(self, ext_network=None, int_network=None,
|
||||
tenant_id=None, port_id=None, **kwargs):
|
||||
"""Create Neutron floating IP.
|
||||
|
||||
:param ext_network: floating network name or dict
|
||||
:param int_network: fixed network name or dict
|
||||
:param tenant_id str tenant id
|
||||
:param port_id: str port id
|
||||
:param **kwargs: for compatibility, not used here
|
||||
:returns: floating IP dict
|
||||
"""
|
||||
if not tenant_id:
|
||||
raise ValueError("Missed tenant_id")
|
||||
|
||||
net_id = None
|
||||
if type(ext_network) is dict:
|
||||
net_id = ext_network["id"]
|
||||
elif ext_network:
|
||||
ext_net = self.get_network(name=ext_network)
|
||||
if not ext_net["external"]:
|
||||
raise NetworkWrapperException("Network is not external: %s"
|
||||
% ext_network)
|
||||
net_id = ext_net["id"]
|
||||
else:
|
||||
ext_networks = self.external_networks
|
||||
if not ext_networks:
|
||||
raise NetworkWrapperException(
|
||||
"Failed to allocate floating IP: "
|
||||
"no external networks found")
|
||||
net_id = ext_networks[0]["id"]
|
||||
|
||||
if not port_id:
|
||||
if type(int_network) is dict:
|
||||
port_id = self.create_port(int_network["id"])["id"]
|
||||
elif int_network:
|
||||
int_net = self.get_network(name=int_network)
|
||||
if int_net["external"]:
|
||||
raise NetworkWrapperException("Network is external: %s"
|
||||
% int_network)
|
||||
port_id = self.create_port(int_net["id"])["id"]
|
||||
kwargs = {"floatingip": {"floating_network_id": net_id},
|
||||
"tenant_id": tenant_id,
|
||||
"port_id": port_id}
|
||||
|
||||
fip = self.client.create_floatingip(kwargs)["floatingip"]
|
||||
return {"id": fip["id"], "ip": fip["floating_ip_address"]}
|
||||
|
||||
def delete_floating_ip(self, fip_id, **kwargs):
|
||||
"""Delete floating IP.
|
||||
|
||||
:param fip_id: int floating IP id
|
||||
:param **kwargs: for compatibility, not used here
|
||||
"""
|
||||
self.client.delete_floatingip(fip_id)
|
||||
|
||||
def supports_security_group(self):
|
||||
"""Check whether security group is supported
|
||||
|
||||
:return: result tuple
|
||||
:rtype: (bool, string)
|
||||
"""
|
||||
extensions = self.client.list_extensions().get("extensions", [])
|
||||
use_sg = any(ext.get("alias") == "security-group"
|
||||
for ext in extensions)
|
||||
if use_sg:
|
||||
return True, ""
|
||||
|
||||
return False, _("neutron driver does not support security groups")
|
||||
|
||||
|
||||
def wrap(clients, config=None):
|
||||
"""Returns available network wrapper instance.
|
||||
|
||||
:param clients: rally.osclients.Clients instance
|
||||
:param config: task config dict
|
||||
:returns: NetworkWrapper subclass instance
|
||||
"""
|
||||
if hasattr(clients, "services"):
|
||||
services = clients.services()
|
||||
else:
|
||||
services = clients("services")
|
||||
|
||||
if consts.Service.NEUTRON in services.values():
|
||||
return NeutronWrapper(clients, config)
|
||||
return NovaNetworkWrapper(clients, config)
|
0
tests/unit/plugins/openstack/wrappers/__init__.py
Normal file
0
tests/unit/plugins/openstack/wrappers/__init__.py
Normal file
208
tests/unit/plugins/openstack/wrappers/test_keystone.py
Normal file
208
tests/unit/plugins/openstack/wrappers/test_keystone.py
Normal file
@ -0,0 +1,208 @@
|
||||
# Copyright 2014: Mirantis Inc.
|
||||
# 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 keystoneclient import exceptions
|
||||
import mock
|
||||
|
||||
from rally.plugins.openstack.wrappers import keystone
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
class KeystoneWrapperTestBase(object):
|
||||
def test_list_services(self):
|
||||
service = mock.MagicMock()
|
||||
service.id = "fake_id"
|
||||
service.name = "Foobar"
|
||||
service.extra_field = "extra_field"
|
||||
self.client.services.list.return_value = [service]
|
||||
result = list(self.wrapped_client.list_services())
|
||||
self.assertEqual([("fake_id", "Foobar")], result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("Foobar", result[0].name)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
||||
|
||||
def test_wrap(self):
|
||||
client = mock.MagicMock()
|
||||
client.version = "dummy"
|
||||
self.assertRaises(NotImplementedError, keystone.wrap, client)
|
||||
|
||||
def test_delete_service(self):
|
||||
self.wrapped_client.delete_service("fake_id")
|
||||
self.client.services.delete.assert_called_once_with("fake_id")
|
||||
|
||||
def test_list_roles(self):
|
||||
role = mock.MagicMock()
|
||||
role.id = "fake_id"
|
||||
role.name = "Foobar"
|
||||
role.extra_field = "extra_field"
|
||||
self.client.roles.list.return_value = [role]
|
||||
result = list(self.wrapped_client.list_roles())
|
||||
self.assertEqual([("fake_id", "Foobar")], result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("Foobar", result[0].name)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
||||
|
||||
def test_delete_role(self):
|
||||
self.wrapped_client.delete_role("fake_id")
|
||||
self.client.roles.delete.assert_called_once_with("fake_id")
|
||||
|
||||
|
||||
class KeystoneV2WrapperTestCase(test.TestCase, KeystoneWrapperTestBase):
|
||||
def setUp(self):
|
||||
super(KeystoneV2WrapperTestCase, self).setUp()
|
||||
self.client = mock.MagicMock()
|
||||
self.client.version = "v2.0"
|
||||
self.wrapped_client = keystone.wrap(self.client)
|
||||
|
||||
def test_create_project(self):
|
||||
self.wrapped_client.create_project("Foobar")
|
||||
self.client.tenants.create.assert_called_once_with("Foobar")
|
||||
|
||||
def test_create_project_in_non_default_domain_fail(self):
|
||||
self.assertRaises(
|
||||
NotImplementedError, self.wrapped_client.create_project,
|
||||
"Foobar", "non-default-domain")
|
||||
|
||||
def test_delete_project(self):
|
||||
self.wrapped_client.delete_project("fake_id")
|
||||
self.client.tenants.delete.assert_called_once_with("fake_id")
|
||||
|
||||
def test_list_projects(self):
|
||||
tenant = mock.MagicMock()
|
||||
tenant.id = "fake_id"
|
||||
tenant.name = "Foobar"
|
||||
tenant.extra_field = "extra_field"
|
||||
self.client.tenants.list.return_value = [tenant]
|
||||
result = list(self.wrapped_client.list_projects())
|
||||
self.assertEqual([("fake_id", "Foobar", "default")], result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("Foobar", result[0].name)
|
||||
self.assertEqual("default", result[0].domain_id)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
||||
|
||||
def test_create_user(self):
|
||||
self.wrapped_client.create_user("foo", "bar", email="foo@bar.com",
|
||||
project_id="tenant_id",
|
||||
domain_name="default")
|
||||
self.client.users.create.assert_called_once_with(
|
||||
"foo", "bar", "foo@bar.com", "tenant_id")
|
||||
|
||||
def test_create_user_in_non_default_domain_fail(self):
|
||||
self.assertRaises(
|
||||
NotImplementedError, self.wrapped_client.create_user,
|
||||
"foo", "bar", email="foo@bar.com", project_id="tenant_id",
|
||||
domain_name="non-default-domain")
|
||||
|
||||
def test_delete_user(self):
|
||||
self.wrapped_client.delete_user("fake_id")
|
||||
self.client.users.delete.assert_called_once_with("fake_id")
|
||||
|
||||
def test_list_users(self):
|
||||
user = mock.MagicMock()
|
||||
user.id = "fake_id"
|
||||
user.name = "foo"
|
||||
user.tenantId = "tenant_id"
|
||||
user.extra_field = "extra_field"
|
||||
self.client.users.list.return_value = [user]
|
||||
result = list(self.wrapped_client.list_users())
|
||||
self.assertEqual([("fake_id", "foo", "tenant_id", "default")], result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("foo", result[0].name)
|
||||
self.assertEqual("tenant_id", result[0].project_id)
|
||||
self.assertEqual("default", result[0].domain_id)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
||||
|
||||
|
||||
class KeystoneV3WrapperTestCase(test.TestCase, KeystoneWrapperTestBase):
|
||||
def setUp(self):
|
||||
super(KeystoneV3WrapperTestCase, self).setUp()
|
||||
self.client = mock.MagicMock()
|
||||
self.client.version = "v3"
|
||||
self.wrapped_client = keystone.wrap(self.client)
|
||||
self.client.domains.get.side_effect = exceptions.NotFound
|
||||
self.client.domains.list.return_value = [
|
||||
mock.MagicMock(id="domain_id")]
|
||||
|
||||
def test_create_project(self):
|
||||
self.wrapped_client.create_project("Foobar", "domain")
|
||||
self.client.projects.create.assert_called_once_with(
|
||||
name="Foobar", domain="domain_id")
|
||||
|
||||
def test_create_project_with_non_existing_domain_fail(self):
|
||||
self.client.domains.list.return_value = []
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.wrapped_client.create_project,
|
||||
"Foobar", "non-existing-domain")
|
||||
|
||||
def test_delete_project(self):
|
||||
self.wrapped_client.delete_project("fake_id")
|
||||
self.client.projects.delete.assert_called_once_with("fake_id")
|
||||
|
||||
def test_list_projects(self):
|
||||
project = mock.MagicMock()
|
||||
project.id = "fake_id"
|
||||
project.name = "Foobar"
|
||||
project.domain_id = "domain_id"
|
||||
project.extra_field = "extra_field"
|
||||
self.client.projects.list.return_value = [project]
|
||||
result = list(self.wrapped_client.list_projects())
|
||||
self.assertEqual([("fake_id", "Foobar", "domain_id")], result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("Foobar", result[0].name)
|
||||
self.assertEqual("domain_id", result[0].domain_id)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
||||
|
||||
def test_create_user(self):
|
||||
fake_role = mock.MagicMock(id="fake_role_id")
|
||||
fake_role.name = "__member__"
|
||||
self.client.roles.list.return_value = [fake_role]
|
||||
self.client.users.create.return_value = mock.MagicMock(
|
||||
id="fake_user_id")
|
||||
|
||||
self.wrapped_client.create_user(
|
||||
"foo", "bar", email="foo@bar.com",
|
||||
project_id="project_id", domain_name="domain")
|
||||
self.client.users.create.assert_called_once_with(
|
||||
name="foo", password="bar",
|
||||
email="foo@bar.com", default_project="project_id",
|
||||
domain="domain_id")
|
||||
|
||||
def test_create_user_with_non_existing_domain_fail(self):
|
||||
self.client.domains.list.return_value = []
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.wrapped_client.create_user, "foo", "bar",
|
||||
email="foo@bar.com", project_id="project_id",
|
||||
domain_name="non-existing-domain")
|
||||
|
||||
def test_delete_user(self):
|
||||
self.wrapped_client.delete_user("fake_id")
|
||||
self.client.users.delete.assert_called_once_with("fake_id")
|
||||
|
||||
def test_list_users(self):
|
||||
user = mock.MagicMock()
|
||||
user.id = "fake_id"
|
||||
user.name = "foo"
|
||||
user.default_project_id = "project_id"
|
||||
user.domain_id = "domain_id"
|
||||
user.extra_field = "extra_field"
|
||||
self.client.users.list.return_value = [user]
|
||||
result = list(self.wrapped_client.list_users())
|
||||
self.assertEqual([("fake_id", "foo", "project_id", "domain_id")],
|
||||
result)
|
||||
self.assertEqual("fake_id", result[0].id)
|
||||
self.assertEqual("foo", result[0].name)
|
||||
self.assertEqual("project_id", result[0].project_id)
|
||||
self.assertEqual("domain_id", result[0].domain_id)
|
||||
self.assertFalse(hasattr(result[0], "extra_field"))
|
494
tests/unit/plugins/openstack/wrappers/test_network.py
Normal file
494
tests/unit/plugins/openstack/wrappers/test_network.py
Normal file
@ -0,0 +1,494 @@
|
||||
# Copyright 2014: Mirantis Inc.
|
||||
# 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 mock
|
||||
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
from rally.plugins.openstack.wrappers import network
|
||||
from tests.unit import test
|
||||
|
||||
from neutronclient.common import exceptions as neutron_exceptions
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
|
||||
SVC = "rally.plugins.openstack.wrappers.network."
|
||||
|
||||
|
||||
class NovaNetworkWrapperTestCase(test.TestCase):
|
||||
|
||||
class Net(object):
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def get_wrapper(self, *skip_cidrs, **kwargs):
|
||||
mock_clients = mock.Mock()
|
||||
mock_clients.nova.return_value.networks.list.return_value = [
|
||||
self.Net(cidr=cidr) for cidr in skip_cidrs]
|
||||
return network.NovaNetworkWrapper(mock_clients, kwargs)
|
||||
|
||||
def test__init__(self):
|
||||
skip_cidrs = ["foo_cidr", "bar_cidr"]
|
||||
service = self.get_wrapper(*skip_cidrs)
|
||||
self.assertEqual(service.skip_cidrs, skip_cidrs)
|
||||
service.client.networks.list.assert_called_once_with()
|
||||
|
||||
@mock.patch("rally.plugins.openstack.wrappers.network.generate_cidr")
|
||||
def test__generate_cidr(self, mock_cidr):
|
||||
skip_cidrs = [5, 7]
|
||||
cidrs = iter(range(7))
|
||||
mock_cidr.side_effect = lambda start_cidr: start_cidr + next(cidrs)
|
||||
service = self.get_wrapper(*skip_cidrs, start_cidr=3)
|
||||
self.assertEqual(service._generate_cidr(), 3)
|
||||
self.assertEqual(service._generate_cidr(), 4)
|
||||
self.assertEqual(service._generate_cidr(), 6) # 5 is skipped
|
||||
self.assertEqual(service._generate_cidr(), 8) # 7 is skipped
|
||||
self.assertEqual(service._generate_cidr(), 9)
|
||||
self.assertEqual(mock_cidr.mock_calls, [mock.call(start_cidr=3)] * 7)
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name",
|
||||
return_value="foo_name")
|
||||
def test_create_network(self, mock_name):
|
||||
service = self.get_wrapper()
|
||||
service.client.networks.create.side_effect = (
|
||||
lambda **kwargs: self.Net(id="foo_id", **kwargs))
|
||||
service._generate_cidr = mock.Mock(return_value="foo_cidr")
|
||||
net = service.create_network("foo_tenant", bar="spam")
|
||||
self.assertEqual(net, {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"cidr": "foo_cidr",
|
||||
"status": "ACTIVE",
|
||||
"external": False,
|
||||
"tenant_id": "foo_tenant"})
|
||||
mock_name.assert_called_once_with("rally_net_")
|
||||
service._generate_cidr.assert_called_once_with()
|
||||
service.client.networks.create.assert_called_once_with(
|
||||
tenant_id="foo_tenant", cidr="foo_cidr", label="foo_name")
|
||||
|
||||
def test_delete_network(self):
|
||||
service = self.get_wrapper()
|
||||
service.client.networks.delete.return_value = "foo_deleted"
|
||||
self.assertEqual(service.delete_network({"id": "foo_id"}),
|
||||
"foo_deleted")
|
||||
service.client.networks.delete.assert_called_once_with("foo_id")
|
||||
|
||||
def test_list_networks(self):
|
||||
service = self.get_wrapper()
|
||||
service.client.networks.list.return_value = "foo_list"
|
||||
service.client.networks.list.reset_mock()
|
||||
self.assertEqual(service.list_networks(), "foo_list")
|
||||
service.client.networks.list.assert_called_once_with()
|
||||
|
||||
def test__get_floating_ip(self):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.client.floating_ips.get.return_value = mock.Mock(id="foo_id",
|
||||
ip="foo_ip")
|
||||
fip = wrap._get_floating_ip("fip_id")
|
||||
wrap.client.floating_ips.get.assert_called_once_with("fip_id")
|
||||
self.assertEqual(fip, "foo_id")
|
||||
|
||||
wrap.client.floating_ips.get.side_effect = (
|
||||
nova_exceptions.NotFound(""))
|
||||
self.assertIsNone(wrap._get_floating_ip("fip_id"))
|
||||
|
||||
self.assertRaises(exceptions.GetResourceNotFound,
|
||||
wrap._get_floating_ip, "fip_id", do_raise=True)
|
||||
|
||||
def test_create_floating_ip(self):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.client.floating_ips.create.return_value = mock.Mock(id="foo_id",
|
||||
ip="foo_ip")
|
||||
fip = wrap.create_floating_ip(ext_network="bar_net", bar="spam")
|
||||
self.assertEqual(fip, {"ip": "foo_ip", "id": "foo_id"})
|
||||
wrap.client.floating_ips.create.assert_called_once_with("bar_net")
|
||||
|
||||
net = mock.Mock()
|
||||
net.name = "foo_net"
|
||||
wrap.client.floating_ip_pools.list.return_value = [net]
|
||||
fip = wrap.create_floating_ip()
|
||||
self.assertEqual(fip, {"ip": "foo_ip", "id": "foo_id"})
|
||||
wrap.client.floating_ips.create.assert_called_with("foo_net")
|
||||
|
||||
def test_delete_floating_ip(self):
|
||||
wrap = self.get_wrapper()
|
||||
fip_found = iter(range(3))
|
||||
|
||||
def get_fip(*args, **kwargs):
|
||||
for i in fip_found:
|
||||
return "fip_id"
|
||||
raise exceptions.GetResourceNotFound
|
||||
wrap._get_floating_ip = mock.Mock(side_effect=get_fip)
|
||||
|
||||
wrap.delete_floating_ip("fip_id")
|
||||
wrap.client.floating_ips.delete.assert_called_once_with("fip_id")
|
||||
self.assertFalse(wrap._get_floating_ip.called)
|
||||
|
||||
wrap.delete_floating_ip("fip_id", wait=True)
|
||||
self.assertEqual(
|
||||
[mock.call("fip_id", do_raise=True)] * 4,
|
||||
wrap._get_floating_ip.mock_calls)
|
||||
|
||||
def test_supports_secgroup(self):
|
||||
wrap = self.get_wrapper()
|
||||
self.assertTrue(wrap.supports_security_group()[0])
|
||||
|
||||
|
||||
class NeutronWrapperTestCase(test.TestCase):
|
||||
def get_wrapper(self, *skip_cidrs, **kwargs):
|
||||
return network.NeutronWrapper(mock.Mock(), kwargs)
|
||||
|
||||
def test_SUBNET_IP_VERSION(self):
|
||||
self.assertEqual(network.NeutronWrapper.SUBNET_IP_VERSION, 4)
|
||||
|
||||
@mock.patch("rally.plugins.openstack.wrappers.network.generate_cidr")
|
||||
def test__generate_cidr(self, mock_cidr):
|
||||
cidrs = iter(range(5))
|
||||
mock_cidr.side_effect = lambda start_cidr: start_cidr + next(cidrs)
|
||||
service = self.get_wrapper(start_cidr=3)
|
||||
self.assertEqual(service._generate_cidr(), 3)
|
||||
self.assertEqual(service._generate_cidr(), 4)
|
||||
self.assertEqual(service._generate_cidr(), 5)
|
||||
self.assertEqual(service._generate_cidr(), 6)
|
||||
self.assertEqual(service._generate_cidr(), 7)
|
||||
self.assertEqual(mock_cidr.mock_calls, [mock.call(start_cidr=3)] * 5)
|
||||
|
||||
def test_external_networks(self):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.client.list_networks.return_value = {"networks": "foo_networks"}
|
||||
self.assertEqual(wrap.external_networks, "foo_networks")
|
||||
wrap.client.list_networks.assert_called_once_with(
|
||||
**{"router:external": True})
|
||||
|
||||
def test_get_network(self):
|
||||
wrap = self.get_wrapper()
|
||||
neutron_net = {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"tenant_id": "foo_tenant",
|
||||
"status": "foo_status",
|
||||
"router:external": "foo_external",
|
||||
"subnets": "foo_subnets"}
|
||||
expected_net = {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"tenant_id": "foo_tenant",
|
||||
"status": "foo_status",
|
||||
"external": "foo_external",
|
||||
"router_id": None,
|
||||
"subnets": "foo_subnets"}
|
||||
wrap.client.show_network.return_value = {"network": neutron_net}
|
||||
net = wrap.get_network(net_id="foo_id")
|
||||
self.assertEqual(net, expected_net)
|
||||
wrap.client.show_network.assert_called_once_with("foo_id")
|
||||
|
||||
wrap.client.show_network.side_effect = (
|
||||
neutron_exceptions.NeutronClientException)
|
||||
self.assertRaises(network.NetworkWrapperException, wrap.get_network,
|
||||
net_id="foo_id")
|
||||
|
||||
wrap.client.list_networks.return_value = {"networks": [neutron_net]}
|
||||
net = wrap.get_network(name="foo_name")
|
||||
self.assertEqual(net, expected_net)
|
||||
wrap.client.list_networks.assert_called_once_with(name="foo_name")
|
||||
|
||||
wrap.client.list_networks.return_value = {"networks": []}
|
||||
self.assertRaises(network.NetworkWrapperException, wrap.get_network,
|
||||
name="foo_name")
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_network(self, mock_name):
|
||||
mock_name.return_value = "foo_name"
|
||||
service = self.get_wrapper()
|
||||
service.client.create_network.return_value = {
|
||||
"network": {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status"}}
|
||||
net = service.create_network("foo_tenant")
|
||||
mock_name.assert_called_once_with("rally_net_")
|
||||
service.client.create_network.assert_called_once_with({
|
||||
"network": {"tenant_id": "foo_tenant", "name": "foo_name"}})
|
||||
self.assertEqual(net, {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status",
|
||||
"external": False,
|
||||
"tenant_id": "foo_tenant",
|
||||
"router_id": None,
|
||||
"subnets": []})
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_network_with_subnets(self, mock_name):
|
||||
subnets_num = 4
|
||||
mock_name.return_value = "foo_name"
|
||||
service = self.get_wrapper()
|
||||
subnets_cidrs = iter(range(subnets_num))
|
||||
subnets_ids = iter(range(subnets_num))
|
||||
service._generate_cidr = mock.Mock(
|
||||
side_effect=lambda: "cidr-%d" % next(subnets_cidrs))
|
||||
service.client.create_subnet = mock.Mock(
|
||||
side_effect=lambda i: {
|
||||
"subnet": {"id": "subnet-%d" % next(subnets_ids)}})
|
||||
service.client.create_network.return_value = {
|
||||
"network": {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status"}}
|
||||
net = service.create_network("foo_tenant", subnets_num=subnets_num)
|
||||
service.client.create_network.assert_called_once_with({
|
||||
"network": {"tenant_id": "foo_tenant", "name": "foo_name"}})
|
||||
self.assertEqual(net, {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status",
|
||||
"external": False,
|
||||
"router_id": None,
|
||||
"tenant_id": "foo_tenant",
|
||||
"subnets": ["subnet-%d" % i
|
||||
for i in range(subnets_num)]})
|
||||
self.assertEqual(
|
||||
service.client.create_subnet.mock_calls,
|
||||
[mock.call({"subnet": {"name": "foo_name",
|
||||
"enable_dhcp": True,
|
||||
"network_id": "foo_id",
|
||||
"tenant_id": "foo_tenant",
|
||||
"ip_version": service.SUBNET_IP_VERSION,
|
||||
"dns_nameservers": ["8.8.8.8", "8.8.4.4"],
|
||||
"cidr": "cidr-%d" % i}})
|
||||
for i in range(subnets_num)])
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_network_with_router(self, mock_name):
|
||||
mock_name.return_value = "foo_name"
|
||||
service = self.get_wrapper()
|
||||
service.create_router = mock.Mock(return_value={"id": "foo_router"})
|
||||
service.client.create_network.return_value = {
|
||||
"network": {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status"}}
|
||||
net = service.create_network("foo_tenant", add_router=True)
|
||||
self.assertEqual(net, {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status",
|
||||
"external": False,
|
||||
"tenant_id": "foo_tenant",
|
||||
"router_id": "foo_router",
|
||||
"subnets": []})
|
||||
service.create_router.assert_called_once_with(external=True,
|
||||
tenant_id="foo_tenant")
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_network_with_router_and_subnets(self, mock_name):
|
||||
subnets_num = 4
|
||||
mock_name.return_value = "foo_name"
|
||||
service = self.get_wrapper()
|
||||
service._generate_cidr = mock.Mock(return_value="foo_cidr")
|
||||
service.create_router = mock.Mock(return_value={"id": "foo_router"})
|
||||
service.client.create_subnet = mock.Mock(
|
||||
return_value={"subnet": {"id": "foo_subnet"}})
|
||||
service.client.create_network.return_value = {
|
||||
"network": {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status"}}
|
||||
net = service.create_network("foo_tenant", add_router=True,
|
||||
subnets_num=subnets_num,
|
||||
dns_nameservers=["foo_nameservers"])
|
||||
self.assertEqual(net, {"id": "foo_id",
|
||||
"name": "foo_name",
|
||||
"status": "foo_status",
|
||||
"external": False,
|
||||
"tenant_id": "foo_tenant",
|
||||
"router_id": "foo_router",
|
||||
"subnets": ["foo_subnet"] * subnets_num})
|
||||
service.create_router.assert_called_once_with(external=True,
|
||||
tenant_id="foo_tenant")
|
||||
self.assertEqual(
|
||||
service.client.create_subnet.mock_calls,
|
||||
[mock.call({"subnet": {"name": "foo_name",
|
||||
"enable_dhcp": True,
|
||||
"network_id": "foo_id",
|
||||
"tenant_id": "foo_tenant",
|
||||
"ip_version": service.SUBNET_IP_VERSION,
|
||||
"dns_nameservers": ["foo_nameservers"],
|
||||
"cidr": "foo_cidr"}})] * subnets_num)
|
||||
self.assertEqual(service.client.add_interface_router.mock_calls,
|
||||
[mock.call("foo_router", {"subnet_id": "foo_subnet"})
|
||||
for i in range(subnets_num)])
|
||||
|
||||
def test_delete_network(self):
|
||||
service = self.get_wrapper()
|
||||
service.client.list_dhcp_agent_hosting_networks.return_value = (
|
||||
{"agents": []})
|
||||
service.client.list_ports.return_value = {"ports": []}
|
||||
service.client.delete_network.return_value = "foo_deleted"
|
||||
result = service.delete_network({"id": "foo_id", "router_id": None,
|
||||
"subnets": []})
|
||||
self.assertEqual(result, "foo_deleted")
|
||||
self.assertEqual(
|
||||
service.client.remove_network_from_dhcp_agent.mock_calls, [])
|
||||
self.assertEqual(service.client.remove_gateway_router.mock_calls, [])
|
||||
self.assertEqual(
|
||||
service.client.remove_interface_router.mock_calls, [])
|
||||
self.assertEqual(service.client.delete_router.mock_calls, [])
|
||||
self.assertEqual(service.client.delete_subnet.mock_calls, [])
|
||||
service.client.delete_network.assert_called_once_with("foo_id")
|
||||
|
||||
def test_delete_network_with_dhcp_and_router_and_ports_and_subnets(self):
|
||||
service = self.get_wrapper()
|
||||
agents = ["foo_agent", "bar_agent"]
|
||||
subnets = ["foo_subnet", "bar_subnet"]
|
||||
ports = ["foo_port", "bar_port"]
|
||||
service.client.list_dhcp_agent_hosting_networks.return_value = (
|
||||
{"agents": [{"id": agent_id} for agent_id in agents]})
|
||||
service.client.list_ports.return_value = (
|
||||
{"ports": [{"id": port_id} for port_id in ports]})
|
||||
service.client.delete_network.return_value = "foo_deleted"
|
||||
result = service.delete_network(
|
||||
{"id": "foo_id", "router_id": "foo_router", "subnets": subnets})
|
||||
self.assertEqual(result, "foo_deleted")
|
||||
self.assertEqual(
|
||||
service.client.remove_network_from_dhcp_agent.mock_calls,
|
||||
[mock.call(agent_id, "foo_id") for agent_id in agents])
|
||||
self.assertEqual(service.client.remove_gateway_router.mock_calls,
|
||||
[mock.call("foo_router")])
|
||||
self.assertEqual(
|
||||
service.client.remove_interface_router.mock_calls,
|
||||
[mock.call("foo_router", {"subnet_id": subnet_id})
|
||||
for subnet_id in subnets])
|
||||
self.assertEqual(service.client.delete_router.mock_calls,
|
||||
[mock.call("foo_router")])
|
||||
self.assertEqual(service.client.delete_port.mock_calls,
|
||||
[mock.call(port_id) for port_id in ports])
|
||||
self.assertEqual(service.client.delete_subnet.mock_calls,
|
||||
[mock.call(subnet_id) for subnet_id in subnets])
|
||||
service.client.delete_network.assert_called_once_with("foo_id")
|
||||
|
||||
def test_list_networks(self):
|
||||
service = self.get_wrapper()
|
||||
service.client.list_networks.return_value = {"networks": "foo_nets"}
|
||||
self.assertEqual(service.list_networks(), "foo_nets")
|
||||
service.client.list_networks.assert_called_once_with()
|
||||
|
||||
@mock.patch(SVC + "NeutronWrapper.external_networks")
|
||||
def test_create_floating_ip(self, mock_ext_networks):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.create_port = mock.Mock(return_value={"id": "port_id"})
|
||||
wrap.client.create_floatingip = mock.Mock(
|
||||
return_value={"floatingip": {"id": "fip_id",
|
||||
"floating_ip_address": "fip_ip"}})
|
||||
|
||||
self.assertRaises(ValueError, wrap.create_floating_ip)
|
||||
|
||||
mock_ext_networks.__get__ = lambda *args: []
|
||||
self.assertRaises(network.NetworkWrapperException,
|
||||
wrap.create_floating_ip, tenant_id="foo_tenant")
|
||||
|
||||
mock_ext_networks.__get__ = lambda *args: [{"id": "ext_id"}]
|
||||
fip = wrap.create_floating_ip(tenant_id="foo_tenant")
|
||||
self.assertEqual(fip, {"id": "fip_id", "ip": "fip_ip"})
|
||||
|
||||
wrap.get_network = mock.Mock(
|
||||
return_value={"id": "foo_net", "external": True})
|
||||
self.assertRaises(network.NetworkWrapperException,
|
||||
wrap.create_floating_ip, tenant_id="foo_tenant",
|
||||
int_network="int_net")
|
||||
wrap.create_floating_ip(tenant_id="foo_tenant", ext_network="ext_net")
|
||||
|
||||
wrap.get_network = mock.Mock(
|
||||
return_value={"id": "foo_net", "external": False})
|
||||
wrap.create_floating_ip(tenant_id="foo_tenant", int_network="int_net")
|
||||
|
||||
self.assertRaises(network.NetworkWrapperException,
|
||||
wrap.create_floating_ip, tenant_id="foo_tenant",
|
||||
ext_network="ext_net")
|
||||
|
||||
def test_delete_floating_ip(self):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.delete_floating_ip("fip_id")
|
||||
wrap.delete_floating_ip("fip_id", ignored_kwarg="bar")
|
||||
self.assertEqual(wrap.client.delete_floatingip.mock_calls,
|
||||
[mock.call("fip_id")] * 2)
|
||||
|
||||
@mock.patch(SVC + "NeutronWrapper.external_networks")
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_router(self, mock_random, mock_ext_networks):
|
||||
wrap = self.get_wrapper()
|
||||
mock_random.return_value = "random_name"
|
||||
wrap.client.create_router.return_value = {"router": "foo_router"}
|
||||
mock_ext_networks.__get__ = lambda *args: [{"id": "ext_id"}]
|
||||
|
||||
router = wrap.create_router(name="foo_name")
|
||||
wrap.client.create_router.assert_called_once_with(
|
||||
{"router": {"name": "foo_name"}})
|
||||
self.assertEqual(router, "foo_router")
|
||||
|
||||
router = wrap.create_router(external=True, foo="bar")
|
||||
wrap.client.create_router.assert_called_with(
|
||||
{"router": {"name": "random_name",
|
||||
"external_gateway_info": {
|
||||
"network_id": "ext_id",
|
||||
"enable_snat": True},
|
||||
"foo": "bar"}})
|
||||
|
||||
@mock.patch("rally.common.utils.generate_random_name")
|
||||
def test_create_port(self, mock_random):
|
||||
wrap = self.get_wrapper()
|
||||
mock_random.return_value = "random_name"
|
||||
wrap.client.create_port.return_value = {"port": "foo_port"}
|
||||
|
||||
port = wrap.create_port("foo_net", name="foo_name")
|
||||
wrap.client.create_port.assert_called_once_with(
|
||||
{"port": {"network_id": "foo_net", "name": "foo_name"}})
|
||||
self.assertEqual(port, "foo_port")
|
||||
|
||||
port = wrap.create_port("foo_net", foo="bar")
|
||||
wrap.client.create_port.assert_called_with(
|
||||
{"port": {"network_id": "foo_net",
|
||||
"name": "random_name", "foo": "bar"}})
|
||||
|
||||
def test_supports_security_group(self):
|
||||
wrap = self.get_wrapper()
|
||||
wrap.client.list_extensions.return_value = (
|
||||
{"extensions": [{"alias": "security-group"}]})
|
||||
self.assertTrue(wrap.supports_security_group()[0])
|
||||
|
||||
wrap.client.list_extensions.return_value = (
|
||||
{"extensions": [{"alias": "dummy-group"}]})
|
||||
self.assertFalse(wrap.supports_security_group()[0])
|
||||
|
||||
wrap.client.list_extensions.return_value = {}
|
||||
self.assertFalse(wrap.supports_security_group()[0])
|
||||
|
||||
|
||||
class FunctionsTestCase(test.TestCase):
|
||||
|
||||
def test_generate_cidr(self):
|
||||
with mock.patch("rally.plugins.openstack.wrappers.network.cidr_incr",
|
||||
iter(range(1, 4))):
|
||||
self.assertEqual(network.generate_cidr(), "10.2.1.0/24")
|
||||
self.assertEqual(network.generate_cidr(), "10.2.2.0/24")
|
||||
self.assertEqual(network.generate_cidr(), "10.2.3.0/24")
|
||||
|
||||
with mock.patch("rally.plugins.openstack.wrappers.network.cidr_incr",
|
||||
iter(range(1, 4))):
|
||||
start_cidr = "1.1.0.0/26"
|
||||
self.assertEqual(network.generate_cidr(start_cidr), "1.1.0.64/26")
|
||||
self.assertEqual(network.generate_cidr(start_cidr), "1.1.0.128/26")
|
||||
self.assertEqual(network.generate_cidr(start_cidr), "1.1.0.192/26")
|
||||
|
||||
def test_wrap(self):
|
||||
mock_clients = mock.Mock()
|
||||
mock_clients.nova().networks.list.return_value = []
|
||||
|
||||
mock_clients.services.return_value = {"foo": consts.Service.NEUTRON}
|
||||
self.assertIsInstance(network.wrap(mock_clients, {}),
|
||||
network.NeutronWrapper)
|
||||
|
||||
mock_clients.services.return_value = {"foo": "bar"}
|
||||
self.assertIsInstance(network.wrap(mock_clients, {}),
|
||||
network.NovaNetworkWrapper)
|
Loading…
Reference in New Issue
Block a user