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_ressources(self):
191 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
192 provider["network_type"] = getattr(
193 config.CONF, '{}_network_type'.format(self.case_name))
194 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
195 provider["physical_network"] = getattr(
196 config.CONF, '{}_physical_network'.format(self.case_name))
197 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
198 provider["segmentation_id"] = getattr(
199 config.CONF, '{}_segmentation_id'.format(self.case_name))
200 self.network = self.cloud.create_network(
201 '{}-net_{}'.format(self.case_name, self.guid),
203 shared=self.shared_network)
204 self.__logger.debug("network: %s", self.network)
206 self.subnet = self.cloud.create_subnet(
208 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
210 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
213 dns_nameservers=[env.get('NAMESERVER')])
214 self.__logger.debug("subnet: %s", self.subnet)
216 self.router = self.cloud.create_router(
217 name='{}-router_{}'.format(self.case_name, self.guid),
218 ext_gateway_net_id=self.ext_net.id)
219 self.__logger.debug("router: %s", self.router)
220 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
222 def run(self, **kwargs):
223 status = testcase.TestCase.EX_RUN_ERROR
226 self.start_time = time.time()
227 self._create_network_ressources()
229 status = testcase.TestCase.EX_OK
230 except Exception: # pylint: disable=broad-except
231 self.__logger.exception('Cannot run %s', self.case_name)
233 self.stop_time = time.time()
241 self.cloud.remove_router_interface(
242 self.router, self.subnet.id)
243 self.cloud.delete_router(self.router.id)
245 self.cloud.delete_subnet(self.subnet.id)
247 self.cloud.delete_network(self.network.id)
248 except Exception: # pylint: disable=broad-except
249 self.__logger.exception("cannot clean all ressources")
252 class TenantNetwork2(TenantNetwork1):
253 """Create a tenant network (scenario2)
255 It creates new user/project before creating and configuring all tenant
256 network ressources required by a testcase (subnet, network and router).
258 It ensures that all testcases inheriting from TenantNetwork2 could work
259 without network specific configurations (or at least read the same config
263 __logger = logging.getLogger(__name__)
265 def __init__(self, **kwargs):
266 if "case_name" not in kwargs:
267 kwargs["case_name"] = 'tenantnetwork2'
268 super(TenantNetwork2, self).__init__(**kwargs)
271 self.project = NewProject(
272 self.cloud, self.case_name, self.guid)
273 self.project.create()
274 self.cloud = self.project.cloud
275 except Exception: # pylint: disable=broad-except
276 self.__logger.exception("Cannot create user or project")
282 super(TenantNetwork2, self).clean()
285 except Exception: # pylint: disable=broad-except
286 self.__logger.exception("Cannot clean all ressources")