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['clouds']['envvars']['username'] = self.user.name
90 osconfig.cloud_config['clouds']['envvars']['password'] = self.password
91 self.__logger.debug("cloud_config %s", osconfig.cloud_config)
92 self.cloud = shade.OpenStackCloud(
93 cloud_config=osconfig.get_one_cloud())
94 self.__logger.debug("new cloud %s", self.cloud.auth)
97 """Remove projects/users"""
99 assert self.orig_cloud
101 self.orig_cloud.delete_user(self.user.id)
103 self.orig_cloud.delete_project(self.project.id)
105 self.orig_cloud.delete_role(self.role.id)
106 except Exception: # pylint: disable=broad-except
107 self.__logger.exception("Cannot clean all ressources")
110 class TenantNetwork1(testcase.TestCase):
111 # pylint: disable=too-many-instance-attributes
112 """Create a tenant network (scenario1)
114 It creates and configures all tenant network ressources required by
115 advanced testcases (subnet, network and router).
117 It ensures that all testcases inheriting from TenantNetwork1 could work
118 without network specific configurations (or at least read the same config
122 __logger = logging.getLogger(__name__)
123 cidr = '192.168.0.0/24'
124 shared_network = False
126 def __init__(self, **kwargs):
127 if "case_name" not in kwargs:
128 kwargs["case_name"] = 'tenantnetwork1'
129 super(TenantNetwork1, self).__init__(**kwargs)
130 self.res_dir = os.path.join(
131 getattr(config.CONF, 'dir_results'), self.case_name)
133 cloud_config = os_client_config.get_config()
134 self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
135 except Exception: # pylint: disable=broad-except
138 self.__logger.exception("Cannot connect to Cloud")
140 self.ext_net = self.get_external_network(self.cloud)
141 except Exception: # pylint: disable=broad-except
142 self.__logger.exception("Cannot get the external network")
143 self.guid = str(uuid.uuid4())
149 def get_external_network(cloud):
151 Returns the configured external network name or
152 the first retrieved external network name
155 if env.get("EXTERNAL_NETWORK"):
156 network = cloud.get_network(
157 env.get("EXTERNAL_NETWORK"), {"router:external": True})
160 networks = cloud.list_networks({"router:external": True})
165 def _create_network_ressources(self):
169 if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
170 provider["network_type"] = getattr(
171 config.CONF, '{}_network_type'.format(self.case_name))
172 if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
173 provider["physical_network"] = getattr(
174 config.CONF, '{}_physical_network'.format(self.case_name))
175 if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
176 provider["segmentation_id"] = getattr(
177 config.CONF, '{}_segmentation_id'.format(self.case_name))
178 self.network = self.cloud.create_network(
179 '{}-net_{}'.format(self.case_name, self.guid),
181 shared=self.shared_network)
182 self.__logger.debug("network: %s", self.network)
184 self.subnet = self.cloud.create_subnet(
186 subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
188 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
191 dns_nameservers=[env.get('NAMESERVER')])
192 self.__logger.debug("subnet: %s", self.subnet)
194 self.router = self.cloud.create_router(
195 name='{}-router_{}'.format(self.case_name, self.guid),
196 ext_gateway_net_id=self.ext_net.id)
197 self.__logger.debug("router: %s", self.router)
198 self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
200 def run(self, **kwargs):
201 status = testcase.TestCase.EX_RUN_ERROR
204 self.start_time = time.time()
205 self._create_network_ressources()
207 status = testcase.TestCase.EX_OK
208 except Exception: # pylint: disable=broad-except
209 self.__logger.exception('Cannot run %s', self.case_name)
211 self.stop_time = time.time()
219 self.cloud.remove_router_interface(
220 self.router, self.subnet.id)
221 self.cloud.delete_router(self.router.id)
223 self.cloud.delete_subnet(self.subnet.id)
225 self.cloud.delete_network(self.network.id)
226 except Exception: # pylint: disable=broad-except
227 self.__logger.exception("cannot clean all ressources")
230 class TenantNetwork2(TenantNetwork1):
231 """Create a tenant network (scenario2)
233 It creates new user/project before creating and configuring all tenant
234 network ressources required by a testcase (subnet, network and router).
236 It ensures that all testcases inheriting from TenantNetwork2 could work
237 without network specific configurations (or at least read the same config
241 __logger = logging.getLogger(__name__)
243 def __init__(self, **kwargs):
244 if "case_name" not in kwargs:
245 kwargs["case_name"] = 'tenantnetwork2'
246 super(TenantNetwork2, self).__init__(**kwargs)
249 self.project = NewProject(
250 self.cloud, self.case_name, self.guid)
251 self.project.create()
252 self.cloud = self.project.cloud
253 except Exception: # pylint: disable=broad-except
254 self.__logger.exception("Cannot create user or project")
260 super(TenantNetwork2, self).clean()
263 except Exception: # pylint: disable=broad-except
264 self.__logger.exception("Cannot clean all ressources")