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__)
38 default_member = "Member"
40 def __init__(self, cloud, case_name, guid):
42 self.orig_cloud = cloud
43 self.case_name = case_name
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.0.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())
178 def _create_network_ressources(self):
182 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
183 provider["network_type"] = getattr(
184 config.CONF, '{}_network_type'.format(self.case_name))
185 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
186 provider["physical_network"] = getattr(
187 config.CONF, '{}_physical_network'.format(self.case_name))
188 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
189 provider["segmentation_id"] = getattr(
190 config.CONF, '{}_segmentation_id'.format(self.case_name))
191 self.network = self.cloud.create_network(
192 '{}-net_{}'.format(self.case_name, self.guid),
194 shared=self.shared_network)
195 self.__logger.debug("network: %s", self.network)
197 self.subnet = self.cloud.create_subnet(
199 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
201 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
204 dns_nameservers=[env.get('NAMESERVER')])
205 self.__logger.debug("subnet: %s", self.subnet)
207 self.router = self.cloud.create_router(
208 name='{}-router_{}'.format(self.case_name, self.guid),
209 ext_gateway_net_id=self.ext_net.id)
210 self.__logger.debug("router: %s", self.router)
211 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
213 def run(self, **kwargs):
214 status = testcase.TestCase.EX_RUN_ERROR
217 self.start_time = time.time()
218 self._create_network_ressources()
220 status = testcase.TestCase.EX_OK
221 except Exception: # pylint: disable=broad-except
222 self.__logger.exception('Cannot run %s', self.case_name)
224 self.stop_time = time.time()
232 self.cloud.remove_router_interface(
233 self.router, self.subnet.id)
234 self.cloud.delete_router(self.router.id)
236 self.cloud.delete_subnet(self.subnet.id)
238 self.cloud.delete_network(self.network.id)
239 except Exception: # pylint: disable=broad-except
240 self.__logger.exception("cannot clean all ressources")
243 class TenantNetwork2(TenantNetwork1):
244 """Create a tenant network (scenario2)
246 It creates new user/project before creating and configuring all tenant
247 network ressources required by a testcase (subnet, network and router).
249 It ensures that all testcases inheriting from TenantNetwork2 could work
250 without network specific configurations (or at least read the same config
254 __logger = logging.getLogger(__name__)
256 def __init__(self, **kwargs):
257 if "case_name" not in kwargs:
258 kwargs["case_name"] = 'tenantnetwork2'
259 super(TenantNetwork2, self).__init__(**kwargs)
262 self.project = NewProject(
263 self.cloud, self.case_name, self.guid)
264 self.project.create()
265 self.cloud = self.project.cloud
266 except Exception: # pylint: disable=broad-except
267 self.__logger.exception("Cannot create user or project")
273 super(TenantNetwork2, self).clean()
276 except Exception: # pylint: disable=broad-except
277 self.__logger.exception("Cannot clean all ressources")