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