ea69fcba6e6d6a44c52b907fdfdcaa4378516946
[functest.git] / functest / core / tenantnetwork.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2018 Orange and others.
4 #
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
9
10 """Ease deploying tenant networks
11
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
16
17 This classes could be reused by more complexed scenarios (Single VM)
18 """
19
20 import logging
21 import os
22 import time
23 import uuid
24
25 import os_client_config
26 import shade
27 from xtesting.core import testcase
28
29 from functest.utils import config
30 from functest.utils import env
31 from functest.utils import functest_utils
32
33
34 class NewProject(object):
35     """Ease creating new projects/users"""
36     # pylint: disable=too-many-instance-attributes
37
38     __logger = logging.getLogger(__name__)
39     default_member = "Member"
40
41     def __init__(self, cloud, case_name, guid):
42         self.cloud = None
43         self.orig_cloud = cloud
44         self.case_name = case_name
45         self.guid = guid
46         self.project = None
47         self.user = None
48         self.password = None
49         self.domain = None
50         self.role = None
51
52     def create(self):
53         """Create projects/users"""
54         assert self.orig_cloud
55         assert self.case_name
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(
63                 self.case_name),
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)
71         try:
72             assert self.orig_cloud.get_role(self.default_member)
73         except Exception:  # pylint: disable=broad-except
74             self.__logger.info("Creating default role %s", self.default_member)
75             self.role = self.orig_cloud.create_role(self.default_member)
76             self.__logger.debug("role: %s", self.role)
77         self.orig_cloud.grant_role(
78             self.default_member, user=self.user.id, project=self.project.id,
79             domain=self.domain.id)
80         osconfig = os_client_config.config.OpenStackConfig()
81         osconfig.cloud_config[
82             'clouds']['envvars']['project_name'] = self.project.name
83         osconfig.cloud_config['clouds']['envvars']['username'] = self.user.name
84         osconfig.cloud_config['clouds']['envvars']['password'] = self.password
85         self.__logger.debug("cloud_config %s", osconfig.cloud_config)
86         self.cloud = shade.OpenStackCloud(
87             cloud_config=osconfig.get_one_cloud())
88         self.__logger.debug("new cloud %s", self.cloud.auth)
89
90     def clean(self):
91         """Remove projects/users"""
92         try:
93             assert self.orig_cloud
94             assert self.user.id
95             assert self.project.id
96             self.orig_cloud.delete_user(self.user.id)
97             self.orig_cloud.delete_project(self.project.id)
98             if self.role:
99                 self.orig_cloud.delete_role(self.role.id)
100         except Exception:  # pylint: disable=broad-except
101             self.__logger.exception("Cannot clean all ressources")
102
103
104 class TenantNetwork1(testcase.TestCase):
105     # pylint: disable=too-many-instance-attributes
106     """Create a tenant network (scenario1)
107
108     It creates and configures all tenant network ressources required by
109     advanced testcases (subnet, network and router).
110
111     It ensures that all testcases inheriting from TenantNetwork1 could work
112     without network specific configurations (or at least read the same config
113     data).
114     """
115
116     __logger = logging.getLogger(__name__)
117     cidr = '192.168.0.0/24'
118
119     def __init__(self, **kwargs):
120         if "case_name" not in kwargs:
121             kwargs["case_name"] = 'tenantnetwork1'
122         super(TenantNetwork1, self).__init__(**kwargs)
123         self.res_dir = os.path.join(
124             getattr(config.CONF, 'dir_results'), self.case_name)
125         try:
126             cloud_config = os_client_config.get_config()
127             self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
128         except Exception:  # pylint: disable=broad-except
129             self.cloud = None
130             self.ext_net = None
131             self.__logger.exception("Cannot connect to Cloud")
132         try:
133             self.ext_net = functest_utils.get_external_network(self.cloud)
134         except Exception:  # pylint: disable=broad-except
135             self.__logger.exception("Cannot get the external network")
136         self.guid = str(uuid.uuid4())
137         self.network = None
138         self.subnet = None
139         self.router = None
140
141     def _create_network_ressources(self):
142         assert self.cloud
143         assert self.ext_net
144         provider = {}
145         if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
146             provider["network_type"] = getattr(
147                 config.CONF, '{}_network_type'.format(self.case_name))
148         if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
149             provider["physical_network"] = getattr(
150                 config.CONF, '{}_physical_network'.format(self.case_name))
151         if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
152             provider["segmentation_id"] = getattr(
153                 config.CONF, '{}_segmentation_id'.format(self.case_name))
154         self.network = self.cloud.create_network(
155             '{}-net_{}'.format(self.case_name, self.guid),
156             provider=provider)
157         self.__logger.debug("network: %s", self.network)
158
159         self.subnet = self.cloud.create_subnet(
160             self.network.id,
161             subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
162             cidr=getattr(
163                 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
164                 self.cidr),
165             enable_dhcp=True,
166             dns_nameservers=[env.get('NAMESERVER')])
167         self.__logger.debug("subnet: %s", self.subnet)
168
169         self.router = self.cloud.create_router(
170             name='{}-router_{}'.format(self.case_name, self.guid),
171             ext_gateway_net_id=self.ext_net.id)
172         self.__logger.debug("router: %s", self.router)
173         self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
174
175     def run(self, **kwargs):
176         status = testcase.TestCase.EX_RUN_ERROR
177         try:
178             assert self.cloud
179             self.start_time = time.time()
180             self._create_network_ressources()
181             self.result = 100
182             status = testcase.TestCase.EX_OK
183         except Exception:  # pylint: disable=broad-except
184             self.__logger.exception('Cannot run %s', self.case_name)
185         finally:
186             self.stop_time = time.time()
187         return status
188
189     def clean(self):
190         try:
191             assert self.cloud
192             self.cloud.remove_router_interface(self.router, self.subnet.id)
193             self.cloud.delete_router(self.router.id)
194             self.cloud.delete_subnet(self.subnet.id)
195             self.cloud.delete_network(self.network.id)
196         except Exception:  # pylint: disable=broad-except
197             self.__logger.exception("cannot clean all ressources")
198
199
200 class TenantNetwork2(TenantNetwork1):
201     """Create a tenant network (scenario2)
202
203     It creates new user/project before creating and configuring all tenant
204     network ressources required by a testcase (subnet, network and router).
205
206     It ensures that all testcases inheriting from TenantNetwork2 could work
207     without network specific configurations (or at least read the same config
208     data).
209     """
210
211     __logger = logging.getLogger(__name__)
212
213     def __init__(self, **kwargs):
214         if "case_name" not in kwargs:
215             kwargs["case_name"] = 'tenantnetwork2'
216         super(TenantNetwork2, self).__init__(**kwargs)
217         try:
218             assert self.cloud
219             self.project = NewProject(
220                 self.cloud, self.case_name, self.guid)
221             self.project.create()
222             self.cloud = self.project.cloud
223         except Exception:  # pylint: disable=broad-except
224             self.__logger.exception("Cannot create user or project")
225             self.cloud = None
226             self.project = None
227
228     def clean(self):
229         try:
230             super(TenantNetwork2, self).clean()
231             assert self.project
232             self.project.clean()
233         except Exception:  # pylint: disable=broad-except
234             self.__logger.exception("Cannot clean all ressources")