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