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, 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 except Exception: # pylint: disable=broad-except
110 self.__logger.exception("Cannot clean all resources")
113 class TenantNetwork1(testcase.TestCase):
114 # pylint: disable=too-many-instance-attributes
115 """Create a tenant network (scenario1)
117 It creates and configures all tenant network resources required by
118 advanced testcases (subnet, network and router).
120 It ensures that all testcases inheriting from TenantNetwork1 could work
121 without network specific configurations (or at least read the same config
125 __logger = logging.getLogger(__name__)
126 cidr = '192.168.120.0/24'
127 shared_network = False
129 def __init__(self, **kwargs):
130 if "case_name" not in kwargs:
131 kwargs["case_name"] = 'tenantnetwork1'
132 super(TenantNetwork1, self).__init__(**kwargs)
133 self.res_dir = os.path.join(
134 getattr(config.CONF, 'dir_results'), self.case_name)
136 cloud_config = os_client_config.get_config()
137 self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
138 except Exception: # pylint: disable=broad-except
141 self.__logger.exception("Cannot connect to Cloud")
143 self.ext_net = self.get_external_network(self.cloud)
144 except Exception: # pylint: disable=broad-except
145 self.__logger.exception("Cannot get the external network")
146 self.guid = str(uuid.uuid4())
152 def get_external_network(cloud):
154 Return the configured external network name or
155 the first retrieved external network name
158 if env.get("EXTERNAL_NETWORK"):
159 network = cloud.get_network(
160 env.get("EXTERNAL_NETWORK"), {"router:external": True})
163 networks = cloud.list_networks({"router:external": True})
169 def get_default_role(cloud, member="Member"):
170 """Get the default role
172 It also tests the role in lowercase to avoid possible conflicts.
174 role = cloud.get_role(member)
176 role = cloud.get_role(member.lower())
180 def get_public_auth_url(cloud):
181 """Get Keystone public endpoint"""
182 keystone_id = cloud.search_services('keystone')[0].id
183 endpoint = cloud.search_endpoints(
184 filters={'interface': 'public',
185 'service_id': keystone_id})[0].url
188 def create_network_resources(self):
189 """Create all tenant network resources
191 It creates a router which gateway is the external network detected.
192 The new subnet is attached to that router.
194 Raises: expection on error
199 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
200 provider["network_type"] = getattr(
201 config.CONF, '{}_network_type'.format(self.case_name))
202 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
203 provider["physical_network"] = getattr(
204 config.CONF, '{}_physical_network'.format(self.case_name))
205 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
206 provider["segmentation_id"] = getattr(
207 config.CONF, '{}_segmentation_id'.format(self.case_name))
208 self.network = self.cloud.create_network(
209 '{}-net_{}'.format(self.case_name, self.guid),
211 shared=self.shared_network)
212 self.__logger.debug("network: %s", self.network)
214 self.subnet = self.cloud.create_subnet(
216 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
218 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
221 dns_nameservers=[env.get('NAMESERVER')])
222 self.__logger.debug("subnet: %s", self.subnet)
224 self.router = self.cloud.create_router(
225 name='{}-router_{}'.format(self.case_name, self.guid),
226 ext_gateway_net_id=self.ext_net.id)
227 self.__logger.debug("router: %s", self.router)
228 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
230 def run(self, **kwargs):
231 status = testcase.TestCase.EX_RUN_ERROR
234 self.start_time = time.time()
235 self.create_network_resources()
237 status = testcase.TestCase.EX_OK
238 except Exception: # pylint: disable=broad-except
239 self.__logger.exception('Cannot run %s', self.case_name)
241 self.stop_time = time.time()
249 self.cloud.remove_router_interface(
250 self.router, self.subnet.id)
251 self.cloud.delete_router(self.router.id)
253 self.cloud.delete_subnet(self.subnet.id)
255 self.cloud.delete_network(self.network.id)
256 except Exception: # pylint: disable=broad-except
257 self.__logger.exception("cannot clean all resources")
260 class TenantNetwork2(TenantNetwork1):
261 """Create a tenant network (scenario2)
263 It creates new user/project before creating and configuring all tenant
264 network resources required by a testcase (subnet, network and router).
266 It ensures that all testcases inheriting from TenantNetwork2 could work
267 without network specific configurations (or at least read the same config
271 __logger = logging.getLogger(__name__)
273 def __init__(self, **kwargs):
274 if "case_name" not in kwargs:
275 kwargs["case_name"] = 'tenantnetwork2'
276 super(TenantNetwork2, self).__init__(**kwargs)
279 self.project = NewProject(
280 self.cloud, self.case_name, self.guid)
281 self.project.create()
282 self.cloud = self.project.cloud
283 except Exception: # pylint: disable=broad-except
284 self.__logger.exception("Cannot create user or project")
290 super(TenantNetwork2, self).clean()
293 except Exception: # pylint: disable=broad-except
294 self.__logger.exception("Cannot clean all resources")