3 # Copyright (c) 2018 Orange and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 """Ease deploying tenant networks
12 It offers a simple way to create all tenant network ressources required by a
13 testcase (including all Functest ones):
14 - TenantNetwork1 selects the user and the project set as env vars
15 - TenantNetwork2 creates a user and project to isolate the same ressources
17 This classes could be reused by more complexed scenarios (Single VM)
25 import os_client_config
27 from xtesting.core import testcase
29 from functest.utils import config
30 from functest.utils import env
33 class NewProject(object):
34 """Ease creating new projects/users"""
35 # pylint: disable=too-many-instance-attributes
37 __logger = logging.getLogger(__name__)
39 def __init__(self, cloud, case_name, guid):
41 self.orig_cloud = cloud
42 self.case_name = case_name
50 self.default_member = env.get('NEW_USER_ROLE')
53 """Create projects/users"""
54 assert self.orig_cloud
56 self.password = str(uuid.uuid4())
57 self.domain = self.orig_cloud.get_domain(
58 name_or_id=self.orig_cloud.auth.get(
59 "project_domain_name", "Default"))
60 self.project = self.orig_cloud.create_project(
61 name='{}-project_{}'.format(self.case_name, self.guid),
62 description="Created by OPNFV Functest: {}".format(
64 domain_id=self.domain.id)
65 self.__logger.debug("project: %s", self.project)
66 self.user = self.orig_cloud.create_user(
67 name='{}-user_{}'.format(self.case_name, self.guid),
68 password=self.password,
69 domain_id=self.domain.id)
70 self.__logger.debug("user: %s", self.user)
72 if self.orig_cloud.get_role(self.default_member):
73 self.role_name = self.default_member
74 elif self.orig_cloud.get_role(self.default_member.lower()):
75 self.role_name = self.default_member.lower()
77 raise Exception("Cannot detect {}".format(self.default_member))
78 except Exception: # pylint: disable=broad-except
79 self.__logger.info("Creating default role %s", self.default_member)
80 self.role = self.orig_cloud.create_role(self.default_member)
81 self.role_name = self.role.name
82 self.__logger.debug("role: %s", self.role)
83 self.orig_cloud.grant_role(
84 self.role_name, user=self.user.id, project=self.project.id,
85 domain=self.domain.id)
86 osconfig = os_client_config.config.OpenStackConfig()
87 osconfig.cloud_config[
88 'clouds']['envvars']['project_name'] = self.project.name
89 osconfig.cloud_config[
90 'clouds']['envvars']['project_id'] = self.project.id
91 osconfig.cloud_config['clouds']['envvars']['username'] = self.user.name
92 osconfig.cloud_config['clouds']['envvars']['password'] = self.password
93 self.__logger.debug("cloud_config %s", osconfig.cloud_config)
94 self.cloud = shade.OpenStackCloud(
95 cloud_config=osconfig.get_one_cloud())
96 self.__logger.debug("new cloud %s", self.cloud.auth)
99 """Remove projects/users"""
101 assert self.orig_cloud
103 self.orig_cloud.delete_user(self.user.id)
105 self.orig_cloud.delete_project(self.project.id)
107 self.orig_cloud.delete_role(self.role.id)
108 except Exception: # pylint: disable=broad-except
109 self.__logger.exception("Cannot clean all ressources")
112 class TenantNetwork1(testcase.TestCase):
113 # pylint: disable=too-many-instance-attributes
114 """Create a tenant network (scenario1)
116 It creates and configures all tenant network ressources required by
117 advanced testcases (subnet, network and router).
119 It ensures that all testcases inheriting from TenantNetwork1 could work
120 without network specific configurations (or at least read the same config
124 __logger = logging.getLogger(__name__)
125 cidr = '192.168.120.0/24'
126 shared_network = False
128 def __init__(self, **kwargs):
129 if "case_name" not in kwargs:
130 kwargs["case_name"] = 'tenantnetwork1'
131 super(TenantNetwork1, self).__init__(**kwargs)
132 self.res_dir = os.path.join(
133 getattr(config.CONF, 'dir_results'), self.case_name)
135 cloud_config = os_client_config.get_config()
136 self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
137 except Exception: # pylint: disable=broad-except
140 self.__logger.exception("Cannot connect to Cloud")
142 self.ext_net = self.get_external_network(self.cloud)
143 except Exception: # pylint: disable=broad-except
144 self.__logger.exception("Cannot get the external network")
145 self.guid = str(uuid.uuid4())
151 def get_external_network(cloud):
153 Return the configured external network name or
154 the first retrieved external network name
157 if env.get("EXTERNAL_NETWORK"):
158 network = cloud.get_network(
159 env.get("EXTERNAL_NETWORK"), {"router:external": True})
162 networks = cloud.list_networks({"router:external": True})
168 def get_default_role(cloud, member="Member"):
169 """Get the default role
171 It also tests the role in lowercase to avoid possible conflicts.
173 role = cloud.get_role(member)
175 role = cloud.get_role(member.lower())
179 def get_public_auth_url(cloud):
180 """Get Keystone public endpoint"""
181 keystone_id = cloud.search_services('keystone')[0].id
182 endpoint = cloud.search_endpoints(
183 filters={'interface': 'public',
184 'service_id': keystone_id})[0].url
187 def create_network_resources(self):
188 """Create all tenant network resources
190 It creates a router which gateway is the external network detected.
191 The new subnet is attached to that router.
193 Raises: expection on error
198 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
199 provider["network_type"] = getattr(
200 config.CONF, '{}_network_type'.format(self.case_name))
201 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
202 provider["physical_network"] = getattr(
203 config.CONF, '{}_physical_network'.format(self.case_name))
204 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
205 provider["segmentation_id"] = getattr(
206 config.CONF, '{}_segmentation_id'.format(self.case_name))
207 self.network = self.cloud.create_network(
208 '{}-net_{}'.format(self.case_name, self.guid),
210 shared=self.shared_network)
211 self.__logger.debug("network: %s", self.network)
213 self.subnet = self.cloud.create_subnet(
215 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
217 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
220 dns_nameservers=[env.get('NAMESERVER')])
221 self.__logger.debug("subnet: %s", self.subnet)
223 self.router = self.cloud.create_router(
224 name='{}-router_{}'.format(self.case_name, self.guid),
225 ext_gateway_net_id=self.ext_net.id)
226 self.__logger.debug("router: %s", self.router)
227 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
229 def run(self, **kwargs):
230 status = testcase.TestCase.EX_RUN_ERROR
233 self.start_time = time.time()
234 self.create_network_resources()
236 status = testcase.TestCase.EX_OK
237 except Exception: # pylint: disable=broad-except
238 self.__logger.exception('Cannot run %s', self.case_name)
240 self.stop_time = time.time()
248 self.cloud.remove_router_interface(
249 self.router, self.subnet.id)
250 self.cloud.delete_router(self.router.id)
252 self.cloud.delete_subnet(self.subnet.id)
254 self.cloud.delete_network(self.network.id)
255 except Exception: # pylint: disable=broad-except
256 self.__logger.exception("cannot clean all ressources")
259 class TenantNetwork2(TenantNetwork1):
260 """Create a tenant network (scenario2)
262 It creates new user/project before creating and configuring all tenant
263 network ressources required by a testcase (subnet, network and router).
265 It ensures that all testcases inheriting from TenantNetwork2 could work
266 without network specific configurations (or at least read the same config
270 __logger = logging.getLogger(__name__)
272 def __init__(self, **kwargs):
273 if "case_name" not in kwargs:
274 kwargs["case_name"] = 'tenantnetwork2'
275 super(TenantNetwork2, self).__init__(**kwargs)
278 self.project = NewProject(
279 self.cloud, self.case_name, self.guid)
280 self.project.create()
281 self.cloud = self.project.cloud
282 except Exception: # pylint: disable=broad-except
283 self.__logger.exception("Cannot create user or project")
289 super(TenantNetwork2, self).clean()
292 except Exception: # pylint: disable=broad-except
293 self.__logger.exception("Cannot clean all ressources")