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 resources required by a
13 testcase (including all Functest ones):
15 - TenantNetwork1 selects the user and the project set as env vars
16 - TenantNetwork2 creates a user and project to isolate the same resources
18 This classes could be reused by more complexed scenarios (Single VM)
26 import os_client_config
28 from xtesting.core import testcase
30 from functest.utils import config
31 from functest.utils import env
34 class NewProject(object):
35 """Ease creating new projects/users"""
36 # pylint: disable=too-many-instance-attributes
38 __logger = logging.getLogger(__name__)
40 def __init__(self, cloud, case_name, guid):
42 self.orig_cloud = cloud
43 self.case_name = case_name
51 self.default_member = env.get('NEW_USER_ROLE')
54 """Create projects/users"""
55 assert self.orig_cloud
57 self.password = str(uuid.uuid4())
58 self.domain = self.orig_cloud.get_domain(
59 name_or_id=self.orig_cloud.auth.get(
60 "project_domain_name", "Default"))
61 self.project = self.orig_cloud.create_project(
62 name='{}-project_{}'.format(self.case_name[:18], self.guid),
63 description="Created by OPNFV Functest: {}".format(
65 domain_id=self.domain.id)
66 self.__logger.debug("project: %s", self.project)
67 self.user = self.orig_cloud.create_user(
68 name='{}-user_{}'.format(self.case_name, self.guid),
69 password=self.password,
70 domain_id=self.domain.id)
71 self.__logger.debug("user: %s", self.user)
73 if self.orig_cloud.get_role(self.default_member):
74 self.role_name = self.default_member
75 elif self.orig_cloud.get_role(self.default_member.lower()):
76 self.role_name = self.default_member.lower()
78 raise Exception("Cannot detect {}".format(self.default_member))
79 except Exception: # pylint: disable=broad-except
80 self.__logger.info("Creating default role %s", self.default_member)
81 self.role = self.orig_cloud.create_role(self.default_member)
82 self.role_name = self.role.name
83 self.__logger.debug("role: %s", self.role)
84 self.orig_cloud.grant_role(
85 self.role_name, user=self.user.id, project=self.project.id,
86 domain=self.domain.id)
87 osconfig = os_client_config.config.OpenStackConfig()
88 osconfig.cloud_config[
89 'clouds']['envvars']['project_name'] = self.project.name
90 osconfig.cloud_config[
91 'clouds']['envvars']['project_id'] = self.project.id
92 osconfig.cloud_config['clouds']['envvars']['username'] = self.user.name
93 osconfig.cloud_config['clouds']['envvars']['password'] = self.password
94 self.__logger.debug("cloud_config %s", osconfig.cloud_config)
95 self.cloud = shade.OpenStackCloud(
96 cloud_config=osconfig.get_one_cloud())
97 self.__logger.debug("new cloud %s", self.cloud.auth)
100 """Remove projects/users"""
102 assert self.orig_cloud
104 self.orig_cloud.delete_user(self.user.id)
106 self.orig_cloud.delete_project(self.project.id)
108 self.orig_cloud.delete_role(self.role.id)
109 secgroups = self.orig_cloud.list_security_groups(
110 filters={'name': 'default',
111 'project_id': self.project.id})
113 sec_id = secgroups[0].id
114 self.orig_cloud.delete_security_group(sec_id)
115 except Exception: # pylint: disable=broad-except
116 self.__logger.exception("Cannot clean all resources")
119 class TenantNetwork1(testcase.TestCase):
120 # pylint: disable=too-many-instance-attributes
121 """Create a tenant network (scenario1)
123 It creates and configures all tenant network resources required by
124 advanced testcases (subnet, network and router).
126 It ensures that all testcases inheriting from TenantNetwork1 could work
127 without network specific configurations (or at least read the same config
131 __logger = logging.getLogger(__name__)
132 cidr = '192.168.120.0/24'
133 shared_network = False
135 def __init__(self, **kwargs):
136 if "case_name" not in kwargs:
137 kwargs["case_name"] = 'tenantnetwork1'
138 super(TenantNetwork1, self).__init__(**kwargs)
139 self.res_dir = os.path.join(
140 getattr(config.CONF, 'dir_results'), self.case_name)
142 cloud_config = os_client_config.get_config()
143 self.cloud = self.orig_cloud = shade.OpenStackCloud(
144 cloud_config=cloud_config)
145 except Exception: # pylint: disable=broad-except
146 self.cloud = self.orig_cloud = None
148 self.__logger.exception("Cannot connect to Cloud")
150 self.ext_net = self.get_external_network(self.cloud)
151 except Exception: # pylint: disable=broad-except
152 self.__logger.exception("Cannot get the external network")
153 self.guid = str(uuid.uuid4())
159 def get_external_network(cloud):
161 Return the configured external network name or
162 the first retrieved external network name
165 if env.get("EXTERNAL_NETWORK"):
166 network = cloud.get_network(
167 env.get("EXTERNAL_NETWORK"), {"router:external": True})
170 networks = cloud.list_networks({"router:external": True})
176 def get_default_role(cloud, member="Member"):
177 """Get the default role
179 It also tests the role in lowercase to avoid possible conflicts.
181 role = cloud.get_role(member)
183 role = cloud.get_role(member.lower())
187 def get_public_auth_url(cloud):
188 """Get Keystone public endpoint"""
189 keystone_id = cloud.search_services('keystone')[0].id
190 endpoint = cloud.search_endpoints(
191 filters={'interface': 'public',
192 'service_id': keystone_id})[0].url
195 def create_network_resources(self):
196 """Create all tenant network resources
198 It creates a router which gateway is the external network detected.
199 The new subnet is attached to that router.
201 Raises: expection on error
206 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
207 provider["network_type"] = getattr(
208 config.CONF, '{}_network_type'.format(self.case_name))
209 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
210 provider["physical_network"] = getattr(
211 config.CONF, '{}_physical_network'.format(self.case_name))
212 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
213 provider["segmentation_id"] = getattr(
214 config.CONF, '{}_segmentation_id'.format(self.case_name))
215 domain = self.orig_cloud.get_domain(
216 name_or_id=self.orig_cloud.auth.get(
217 "project_domain_name", "Default"))
218 project = self.orig_cloud.get_project(
219 self.cloud.auth['project_name'],
221 self.network = self.orig_cloud.create_network(
222 '{}-net_{}'.format(self.case_name, self.guid),
223 provider=provider, project_id=project.id,
224 shared=self.shared_network)
225 self.__logger.debug("network: %s", self.network)
227 self.subnet = self.cloud.create_subnet(
229 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
231 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
234 dns_nameservers=[env.get('NAMESERVER')])
235 self.__logger.debug("subnet: %s", self.subnet)
237 self.router = self.cloud.create_router(
238 name='{}-router_{}'.format(self.case_name, self.guid),
239 ext_gateway_net_id=self.ext_net.id)
240 self.__logger.debug("router: %s", self.router)
241 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
243 def run(self, **kwargs):
244 status = testcase.TestCase.EX_RUN_ERROR
247 self.start_time = time.time()
248 self.create_network_resources()
250 status = testcase.TestCase.EX_OK
251 except Exception: # pylint: disable=broad-except
252 self.__logger.exception('Cannot run %s', self.case_name)
254 self.stop_time = time.time()
262 self.cloud.remove_router_interface(
263 self.router, self.subnet.id)
264 self.cloud.delete_router(self.router.id)
266 self.cloud.delete_subnet(self.subnet.id)
268 self.cloud.delete_network(self.network.id)
269 except Exception: # pylint: disable=broad-except
270 self.__logger.exception("cannot clean all resources")
273 class TenantNetwork2(TenantNetwork1):
274 """Create a tenant network (scenario2)
276 It creates new user/project before creating and configuring all tenant
277 network resources required by a testcase (subnet, network and router).
279 It ensures that all testcases inheriting from TenantNetwork2 could work
280 without network specific configurations (or at least read the same config
284 __logger = logging.getLogger(__name__)
286 def __init__(self, **kwargs):
287 if "case_name" not in kwargs:
288 kwargs["case_name"] = 'tenantnetwork2'
289 super(TenantNetwork2, self).__init__(**kwargs)
292 self.project = NewProject(
293 self.cloud, self.case_name, self.guid)
294 self.project.create()
295 self.cloud = self.project.cloud
296 except Exception: # pylint: disable=broad-except
297 self.__logger.exception("Cannot create user or project")
303 super(TenantNetwork2, self).clean()
306 except Exception: # pylint: disable=broad-except
307 self.__logger.exception("Cannot clean all resources")