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 Returns 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})
167 def _create_network_ressources(self):
171 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
172 provider["network_type"] = getattr(
173 config.CONF, '{}_network_type'.format(self.case_name))
174 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
175 provider["physical_network"] = getattr(
176 config.CONF, '{}_physical_network'.format(self.case_name))
177 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
178 provider["segmentation_id"] = getattr(
179 config.CONF, '{}_segmentation_id'.format(self.case_name))
180 self.network = self.cloud.create_network(
181 '{}-net_{}'.format(self.case_name, self.guid),
183 shared=self.shared_network)
184 self.__logger.debug("network: %s", self.network)
186 self.subnet = self.cloud.create_subnet(
188 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
190 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
193 dns_nameservers=[env.get('NAMESERVER')])
194 self.__logger.debug("subnet: %s", self.subnet)
196 self.router = self.cloud.create_router(
197 name='{}-router_{}'.format(self.case_name, self.guid),
198 ext_gateway_net_id=self.ext_net.id)
199 self.__logger.debug("router: %s", self.router)
200 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
202 def run(self, **kwargs):
203 status = testcase.TestCase.EX_RUN_ERROR
206 self.start_time = time.time()
207 self._create_network_ressources()
209 status = testcase.TestCase.EX_OK
210 except Exception: # pylint: disable=broad-except
211 self.__logger.exception('Cannot run %s', self.case_name)
213 self.stop_time = time.time()
221 self.cloud.remove_router_interface(
222 self.router, self.subnet.id)
223 self.cloud.delete_router(self.router.id)
225 self.cloud.delete_subnet(self.subnet.id)
227 self.cloud.delete_network(self.network.id)
228 except Exception: # pylint: disable=broad-except
229 self.__logger.exception("cannot clean all ressources")
232 class TenantNetwork2(TenantNetwork1):
233 """Create a tenant network (scenario2)
235 It creates new user/project before creating and configuring all tenant
236 network ressources required by a testcase (subnet, network and router).
238 It ensures that all testcases inheriting from TenantNetwork2 could work
239 without network specific configurations (or at least read the same config
243 __logger = logging.getLogger(__name__)
245 def __init__(self, **kwargs):
246 if "case_name" not in kwargs:
247 kwargs["case_name"] = 'tenantnetwork2'
248 super(TenantNetwork2, self).__init__(**kwargs)
251 self.project = NewProject(
252 self.cloud, self.case_name, self.guid)
253 self.project.create()
254 self.cloud = self.project.cloud
255 except Exception: # pylint: disable=broad-except
256 self.__logger.exception("Cannot create user or project")
262 super(TenantNetwork2, self).clean()
265 except Exception: # pylint: disable=broad-except
266 self.__logger.exception("Cannot clean all ressources")