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