7d9a330f18dc52df841a07e2beabc3ed371396e0
[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
40     def __init__(self, cloud, case_name, guid):
41         self.cloud = None
42         self.orig_cloud = cloud
43         self.case_name = case_name
44         self.guid = guid
45         self.project = None
46         self.user = None
47
48     def create(self):
49         """Create projects/users"""
50         assert self.orig_cloud
51         assert self.case_name
52         password = str(uuid.uuid4())
53         domain = self.orig_cloud.get_domain(
54             name_or_id=self.orig_cloud.auth.get(
55                 "project_domain_name", "Default"))
56         self.project = self.orig_cloud.create_project(
57             name='{}-project_{}'.format(self.case_name, self.guid),
58             description="Created by OPNFV Functest: {}".format(
59                 self.case_name),
60             domain_id=domain.id)
61         self.__logger.debug("project: %s", self.project)
62         self.user = self.orig_cloud.create_user(
63             name='{}-user_{}'.format(self.case_name, self.guid),
64             password=password,
65             domain_id=domain.id)
66         self.__logger.debug("user: %s", self.user)
67         self.orig_cloud.grant_role(
68             "_member_", user=self.user.id, project=self.project.id,
69             domain=domain.id)
70         osconfig = os_client_config.config.OpenStackConfig()
71         osconfig.cloud_config[
72             'clouds']['envvars']['project_name'] = self.project.name
73         osconfig.cloud_config['clouds']['envvars']['username'] = self.user.name
74         osconfig.cloud_config['clouds']['envvars']['password'] = password
75         self.cloud = shade.OpenStackCloud(
76             cloud_config=osconfig.get_one_cloud())
77
78     def clean(self):
79         """Remove projects/users"""
80         try:
81             assert self.orig_cloud
82             assert self.user.id
83             assert self.project.id
84             self.orig_cloud.delete_user(self.user.id)
85             self.orig_cloud.delete_project(self.project.id)
86         except Exception:  # pylint: disable=broad-except
87             self.__logger.exception("Cannot clean all ressources")
88
89
90 class TenantNetwork1(testcase.TestCase):
91     # pylint: disable=too-many-instance-attributes
92     """Create a tenant network (scenario1)
93
94     It creates and configures all tenant network ressources required by
95     advanced testcases (subnet, network and router).
96
97     It ensures that all testcases inheriting from TenantNetwork1 could work
98     without network specific configurations (or at least read the same config
99     data).
100     """
101
102     __logger = logging.getLogger(__name__)
103     cidr = '192.168.0.0/24'
104
105     def __init__(self, **kwargs):
106         if "case_name" not in kwargs:
107             kwargs["case_name"] = 'tenantnetwork1'
108         super(TenantNetwork1, self).__init__(**kwargs)
109         self.res_dir = os.path.join(
110             getattr(config.CONF, 'dir_results'), self.case_name)
111         try:
112             cloud_config = os_client_config.get_config()
113             self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
114         except Exception:  # pylint: disable=broad-except
115             self.cloud = None
116             self.ext_net = None
117             self.__logger.exception("Cannot connect to Cloud")
118         try:
119             self.ext_net = functest_utils.get_external_network(self.cloud)
120         except Exception:  # pylint: disable=broad-except
121             self.__logger.exception("Cannot get the external network")
122         self.guid = str(uuid.uuid4())
123         self.network = None
124         self.subnet = None
125         self.router = None
126
127     def _create_network_ressources(self):
128         assert self.cloud
129         assert self.ext_net
130         provider = {}
131         if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
132             provider["network_type"] = getattr(
133                 config.CONF, '{}_network_type'.format(self.case_name))
134         if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
135             provider["physical_network"] = getattr(
136                 config.CONF, '{}_physical_network'.format(self.case_name))
137         if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
138             provider["segmentation_id"] = getattr(
139                 config.CONF, '{}_segmentation_id'.format(self.case_name))
140         self.network = self.cloud.create_network(
141             '{}-net_{}'.format(self.case_name, self.guid),
142             provider=provider)
143         self.__logger.debug("network: %s", self.network)
144
145         self.subnet = self.cloud.create_subnet(
146             self.network.id,
147             subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
148             cidr=getattr(
149                 config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
150                 self.cidr),
151             enable_dhcp=True,
152             dns_nameservers=[env.get('NAMESERVER')])
153         self.__logger.debug("subnet: %s", self.subnet)
154
155         self.router = self.cloud.create_router(
156             name='{}-router_{}'.format(self.case_name, self.guid),
157             ext_gateway_net_id=self.ext_net.id)
158         self.__logger.debug("router: %s", self.router)
159         self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
160
161     def run(self, **kwargs):
162         status = testcase.TestCase.EX_RUN_ERROR
163         try:
164             assert self.cloud
165             self.start_time = time.time()
166             self._create_network_ressources()
167             self.result = 100
168             status = testcase.TestCase.EX_OK
169         except Exception:  # pylint: disable=broad-except
170             self.__logger.exception('Cannot run %s', self.case_name)
171         finally:
172             self.stop_time = time.time()
173         return status
174
175     def clean(self):
176         try:
177             assert self.cloud
178             self.cloud.remove_router_interface(self.router, self.subnet.id)
179             self.cloud.delete_router(self.router.id)
180             self.cloud.delete_subnet(self.subnet.id)
181             self.cloud.delete_network(self.network.id)
182         except Exception:  # pylint: disable=broad-except
183             self.__logger.exception("cannot clean all ressources")
184
185
186 class TenantNetwork2(TenantNetwork1):
187     """Create a tenant network (scenario2)
188
189     It creates new user/project before creating and configuring all tenant
190     network ressources required by a testcase (subnet, network and router).
191
192     It ensures that all testcases inheriting from TenantNetwork2 could work
193     without network specific configurations (or at least read the same config
194     data).
195     """
196
197     __logger = logging.getLogger(__name__)
198
199     def __init__(self, **kwargs):
200         if "case_name" not in kwargs:
201             kwargs["case_name"] = 'tenantnetwork2'
202         super(TenantNetwork2, self).__init__(**kwargs)
203         try:
204             assert self.cloud
205             self.project = NewProject(
206                 self.cloud, self.case_name, self.guid)
207             self.project.create()
208             self.cloud = self.project.cloud
209         except Exception:  # pylint: disable=broad-except
210             self.__logger.exception("Cannot create user or project")
211             self.cloud = None
212             self.project = None
213
214     def clean(self):
215         try:
216             super(TenantNetwork2, self).clean()
217             assert self.project
218             self.project.clean()
219         except Exception:  # pylint: disable=broad-except
220             self.__logger.exception("Cannot clean all ressources")