blob: 669481309db832913ff73a32e66fdf569fb2423e [file] [log] [blame]
Ievgeniia Zadorozhna97dfde42022-06-17 20:05:09 +03001import logging
2import os
3import random
4import sys
5import time
6
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +02007from cinderclient import client as cinder_client
8from glanceclient import client as glance_client
9from keystoneauth1 import identity as keystone_identity
10from keystoneauth1 import session as keystone_session
11from keystoneclient.v3 import client as keystone_client
12from neutronclient.v2_0 import client as neutron_client
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +030013from neutronclient import common as neutron_common
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020014from novaclient import client as novaclient
15
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020016import utils
17
18logger = logging.getLogger(__name__)
19
20
21class OfficialClientManager(object):
22 """Manager that provides access to the official python clients for
23 calling various OpenStack APIs.
24 """
25
26 CINDERCLIENT_VERSION = 3
27 GLANCECLIENT_VERSION = 2
28 KEYSTONECLIENT_VERSION = 3
29 NEUTRONCLIENT_VERSION = 2
30 NOVACLIENT_VERSION = 2
31 INTERFACE = 'admin'
32 if "OS_ENDPOINT_TYPE" in list(os.environ.keys()):
33 INTERFACE = os.environ["OS_ENDPOINT_TYPE"]
34
35 def __init__(self, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030036 project_name=None, auth_url=None, endpoint_type="internalURL",
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020037 cert=False, domain="Default", **kwargs):
38 self.traceback = ""
39
40 self.client_attr_names = [
41 "auth",
42 "compute",
43 "network",
44 "volume",
45 "image",
46 ]
47 self.username = username
48 self.password = password
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030049 self.project_name = project_name
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020050 self.auth_url = auth_url
51 self.endpoint_type = endpoint_type
52 self.cert = cert
53 self.domain = domain
54 self.kwargs = kwargs
55
56 # Lazy clients
57 self._auth = None
58 self._compute = None
59 self._network = None
60 self._volume = None
61 self._image = None
62
63 @classmethod
64 def _get_auth_session(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030065 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020066 domain='Default'):
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030067 if None in (username, password, project_name):
68 sys.stdout.write((username, password, project_name))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020069 msg = ("Missing required credentials for identity client. "
70 "username: {username}, password: {password}, "
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030071 "project_name: {project_name}").format(
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020072 username=username,
73 password=password,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030074 project_name=project_name
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020075 )
76 raise msg
77
78 if cert and "https" not in auth_url:
79 auth_url = auth_url.replace("http", "https")
80
81 if "v2" in auth_url:
82 raise BaseException("Keystone v2 is deprecated since OpenStack"
83 "Queens release. So current OS_AUTH_URL {} "
84 "is not valid. Please use Keystone v3."
85 "".format(auth_url))
86 else:
87 auth_url = auth_url if ("v3" in auth_url) else "{}{}".format(
88 auth_url, "/v3")
89 auth = keystone_identity.v3.Password(
90 auth_url=auth_url,
91 user_domain_name=domain,
92 username=username,
93 password=password,
94 project_domain_name=domain,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +030095 project_name=project_name)
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +020096
97 auth_session = keystone_session.Session(auth=auth, verify=cert)
98 # auth_session.get_auth_headers()
99 return auth_session
100
101 @classmethod
102 def get_auth_client(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300103 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200104 domain='Default', **kwargs):
105 session = cls._get_auth_session(
106 username=username,
107 password=password,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300108 project_name=project_name,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200109 auth_url=auth_url,
110 cert=cert,
111 domain=domain)
112 keystone = keystone_client.Client(version=cls.KEYSTONECLIENT_VERSION,
113 session=session, **kwargs)
114 keystone.management_url = auth_url
115 return keystone
116
117 @classmethod
118 def get_compute_client(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300119 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200120 domain='Default', **kwargs):
121 session = cls._get_auth_session(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300122 username=username, password=password, project_name=project_name,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200123 auth_url=auth_url, cert=cert, domain=domain)
124 service_type = 'compute'
125 compute_client = novaclient.Client(
126 version=cls.NOVACLIENT_VERSION, session=session,
127 service_type=service_type, os_cache=False, **kwargs)
128 return compute_client
129
130 @classmethod
131 def get_network_client(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300132 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200133 domain='Default', **kwargs):
134 session = cls._get_auth_session(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300135 username=username, password=password, project_name=project_name,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200136 auth_url=auth_url, cert=cert, domain=domain)
137 service_type = 'network'
138 return neutron_client.Client(
139 service_type=service_type, session=session,
140 interface=cls.INTERFACE, **kwargs)
141
142 @classmethod
143 def get_volume_client(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300144 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200145 domain='Default', **kwargs):
146 session = cls._get_auth_session(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300147 username=username, password=password, project_name=project_name,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200148 auth_url=auth_url, cert=cert, domain=domain)
149 service_type = 'volume'
150 return cinder_client.Client(
151 version=cls.CINDERCLIENT_VERSION,
152 service_type=service_type,
153 interface=cls.INTERFACE,
154 session=session, **kwargs)
155
156 @classmethod
157 def get_image_client(cls, username=None, password=None,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300158 project_name=None, auth_url=None, cert=None,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200159 domain='Default', **kwargs):
160 session = cls._get_auth_session(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300161 username=username, password=password, project_name=project_name,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200162 auth_url=auth_url, cert=cert, domain=domain)
163 service_type = 'image'
164 return glance_client.Client(
165 version=cls.GLANCECLIENT_VERSION,
166 service_type=service_type,
167 session=session, interface=cls.INTERFACE,
168 **kwargs)
169
170 @property
171 def auth(self):
172 if self._auth is None:
173 self._auth = self.get_auth_client(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300174 self.username, self.password, self.project_name, self.auth_url,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200175 self.cert, self.domain, endpoint_type=self.endpoint_type
176 )
177 return self._auth
178
179 @property
180 def compute(self):
181 if self._compute is None:
182 self._compute = self.get_compute_client(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300183 self.username, self.password, self.project_name, self.auth_url,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200184 self.cert, self.domain, endpoint_type=self.endpoint_type
185 )
186 return self._compute
187
188 @property
189 def network(self):
190 if self._network is None:
191 self._network = self.get_network_client(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300192 self.username, self.password, self.project_name, self.auth_url,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200193 self.cert, self.domain, endpoint_type=self.endpoint_type
194 )
195 return self._network
196
197 @property
198 def volume(self):
199 if self._volume is None:
200 self._volume = self.get_volume_client(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300201 self.username, self.password, self.project_name, self.auth_url,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200202 self.cert, self.domain, endpoint_type=self.endpoint_type
203 )
204 return self._volume
205
206 @property
207 def image(self):
208
209 if self._image is None:
210 self._image = self.get_image_client(
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300211 self.username, self.password, self.project_name, self.auth_url,
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200212 self.cert, self.domain
213 )
214 return self._image
215
216
217class OSCliActions(object):
218 def __init__(self, os_clients):
219 self.os_clients = os_clients
220 self.create_fake_ext_net = False
221
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300222 def get_project_by_name(self, name):
223 return self.os_clients.auth.projects.find(name=name)
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200224
225 def get_internal_network(self):
226 networks = [
227 net for net in self.os_clients.network.list_networks()["networks"]
228 if net["admin_state_up"] and not net["router:external"] and
229 len(net["subnets"])
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300230 ]
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200231 if networks:
232 net = networks[0]
233 else:
234 net = self.create_network_resources()
235 return net
236
237 def create_fake_external_network(self):
238 logger.info(
239 "Could not find any external network, creating a fake one...")
240 net_name = "spt-ext-net-{}".format(random.randrange(100, 999))
241 net_body = {"network": {"name": net_name,
242 "router:external": True,
243 "provider:network_type": "local"}}
244 try:
245 ext_net = \
246 self.os_clients.network.create_network(net_body)['network']
247 logger.info("Created a fake external net {}".format(net_name))
248 except Exception as e:
249 # in case 'local' net type is absent, create with default type
250 net_body["network"].pop('provider:network_type', None)
251 ext_net = \
252 self.os_clients.network.create_network(net_body)['network']
253 subnet_name = "spt-ext-subnet-{}".format(random.randrange(100, 999))
254 subnet_body = {
255 "subnet": {
256 "name": subnet_name,
257 "network_id": ext_net["id"],
258 "ip_version": 4,
259 "cidr": "10.255.255.0/24",
260 "allocation_pools": [{"start": "10.255.255.100",
261 "end": "10.255.255.200"}]
262 }
263 }
264 self.os_clients.network.create_subnet(subnet_body)
265 self.create_fake_ext_net = True
266 return ext_net
267
268 def get_external_network(self):
269 config = utils.get_configuration()
270 ext_net = config.get('external_network') or ''
271 if not ext_net:
272 networks = [
273 net for net in
274 self.os_clients.network.list_networks()["networks"]
275 if net["admin_state_up"] and net["router:external"] and
276 len(net["subnets"])
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300277 ]
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200278 else:
279 networks = [net for net in
280 self.os_clients.network.list_networks()["networks"]
281 if net["name"] == ext_net]
282
283 if networks:
284 ext_net = networks[0]
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300285 logger.info("Using external net '{}'".format(ext_net["name"]))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200286 else:
287 ext_net = self.create_fake_external_network()
288 return ext_net
289
290 def create_flavor(self, name, ram=256, vcpus=1, disk=2):
291 logger.info("Creating a flavor {}".format(name))
292 return self.os_clients.compute.flavors.create(name, ram, vcpus, disk)
293
294 def create_sec_group(self, rulesets=None):
295 if rulesets is None:
296 rulesets = [
297 {
298 # ssh
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300299 'protocol': 'tcp',
300 'port_range_max': 22,
301 'port_range_min': 22,
302 'remote_ip_prefix': '0.0.0.0/0',
303 'direction': 'ingress'
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200304 },
305 {
306 # iperf3
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300307 'protocol': 'tcp',
308 'port_range_max': 5201,
309 'port_range_min': 5201,
310 'remote_ip_prefix': '0.0.0.0/0',
311 'direction': 'ingress'
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200312 },
313 {
Ievgeniia Zadorozhna5ed74e22022-07-26 16:56:23 +0300314 # iperf
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300315 'protocol': 'tcp',
316 'port_range_max': 5001,
317 'port_range_min': 5001,
318 'remote_ip_prefix': '0.0.0.0/0',
319 'direction': 'ingress'
Ievgeniia Zadorozhna5ed74e22022-07-26 16:56:23 +0300320 },
321 {
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200322 # ping
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300323 'protocol': 'icmp',
324 'remote_ip_prefix': '0.0.0.0/0',
325 'direction': 'ingress'
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200326 }
327 ]
328 sg_name = "spt-test-secgroup-{}".format(random.randrange(100, 999))
329 sg_desc = sg_name + " SPT"
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300330 body = {"security_group": {"name": sg_name, "description": sg_desc}}
331 secgroup = self.os_clients.network.create_security_group(body=body)
332
333 rule_body_teplate = {"security_group_rule": {}}
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200334 for ruleset in rulesets:
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300335 rule_body_teplate["security_group_rule"] = ruleset
336 rule_body_teplate["security_group_rule"]["security_group_id"] = \
337 secgroup['security_group']['id']
338 self.os_clients.network.create_security_group_rule(
339 body=rule_body_teplate)
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200340 logger.info("Created a security group {}".format(sg_name))
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300341 return secgroup['security_group']
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200342
343 def create_basic_server(self, image=None, flavor=None, net=None,
344 availability_zone=None, sec_groups=(),
345 keypair=None):
346 os_conn = self.os_clients
347 net = net or self.get_internal_network()
348 kwargs = {}
349 if sec_groups:
350 kwargs['security_groups'] = sec_groups
351 server = os_conn.compute.servers.create(
352 "spt-test-server-{}".format(random.randrange(100, 999)),
353 image, flavor, nics=[{"net-id": net["id"]}],
354 availability_zone=availability_zone, key_name=keypair, **kwargs)
355
356 return server
357
358 def get_vm(self, vm_id):
359 os_conn = self.os_clients
360 try:
361 vm = os_conn.compute.servers.find(id=vm_id)
362 except Exception as e:
363 raise Exception(
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300364 "Could not get the VM \"{}\": {}".format(
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200365 vm_id, e))
366 return vm
367
368 def check_vm_is_active(self, vm_uuid, retry_delay=5, timeout=500):
369 vm = None
370 timeout_reached = False
371 start_time = time.time()
372 expected_state = 'ACTIVE'
373 while not timeout_reached:
374 vm = self.get_vm(vm_uuid)
375 if vm.status == expected_state:
376 logger.info(
377 "VM {} is in {} status.".format(vm_uuid, vm.status))
378 break
379 if vm.status == 'ERROR':
380 break
381 time.sleep(retry_delay)
382 timeout_reached = (time.time() - start_time) > timeout
383 if vm.status != expected_state:
384 logger.info("VM {} is in {} status.".format(vm_uuid, vm.status))
385 raise TimeoutError(
386 "VM {vm_uuid} on is expected to be in '{expected_state}' "
387 "state, but is in '{actual}' state instead.".format(
388 vm_uuid=vm_uuid, expected_state=expected_state,
389 actual=vm.status))
390
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300391 def create_network(self, project_id):
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200392 net_name = "spt-test-net-{}".format(random.randrange(100, 999))
Ievgeniia Zadorozhnafa13ba62022-06-18 02:03:09 +0300393 config = utils.get_configuration()
394 mtu = config.get('custom_mtu') or 'default'
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200395 net_body = {
396 'network': {
397 'name': net_name,
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300398 'project_id': project_id
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200399 }
400 }
Ievgeniia Zadorozhna040dfe82023-03-03 04:48:05 +0300401 # in TF2011 we cannot set MTU while creating the net: 400 Bad request
402 # error can happen with 'mtu' field, so we update mtu of ports later
403 if (mtu != 'default') and (not self.is_cloud_tf()):
Ievgeniia Zadorozhnafa13ba62022-06-18 02:03:09 +0300404 try:
405 net_body['network']['mtu'] = int(mtu)
406 except ValueError as e:
407 raise ValueError("MTU value '{}' is not correct. "
408 "Must be an integer at 'custom_mtu' in "
409 "global_config.yaml.\n{}".format(mtu, e))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200410 net = self.os_clients.network.create_network(net_body)['network']
Ievgeniia Zadorozhnac67b86b2023-02-02 18:09:12 +0300411 # WA for TF because the network object does not have 'mtu' field by
412 # default, so this blocked running tests at TF envs with default MTU
413 if 'mtu' not in net:
414 net['mtu'] = None
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300415 logger.info("Created internal network {} in {} project".format(
416 net_name, project_id))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200417 return net
418
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300419 def create_subnet(self, net, project_id, cidr=None):
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200420 subnet_name = "spt-test-subnet-{}".format(random.randrange(100, 999))
421 subnet_body = {
422 'subnet': {
423 "name": subnet_name,
424 'network_id': net['id'],
425 'ip_version': 4,
426 'cidr': cidr if cidr else '10.1.7.0/24',
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300427 'project_id': project_id
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200428 }
429 }
430 subnet = self.os_clients.network.create_subnet(subnet_body)['subnet']
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300431 logger.info("Created subnet {} in {} project".format(
432 subnet_name, project_id))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200433 return subnet
434
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300435 def create_router(self, ext_net, project_id):
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200436 name = 'spt-test-router-{}'.format(random.randrange(100, 999))
437 router_body = {
438 'router': {
439 'name': name,
440 'external_gateway_info': {
441 'network_id': ext_net['id']
442 },
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300443 'project_id': project_id
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200444 }
445 }
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300446 logger.info("Created a router {} in {} project".format(
447 name, project_id))
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200448 router = self.os_clients.network.create_router(router_body)['router']
449 return router
450
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300451 def create_network_resources(self, project="admin", cidr=None):
452 project_id = self.get_project_by_name(project).id
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200453 self.get_external_network()
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300454 net = self.create_network(project_id)
455 self.create_subnet(net, project_id, cidr)
Ievgeniia Zadorozhna84023022021-12-30 13:00:41 +0200456 return net
457
458 def list_nova_computes(self):
459 nova_services = self.os_clients.compute.hosts.list()
460 computes_list = [h for h in nova_services if h.service == "compute"]
461 return computes_list
Ievgeniia Zadorozhna2c6469d2022-08-10 17:21:10 +0300462
463 def create_floating_ip(self, floating_net_id):
464 fip = self.os_clients.network.create_floatingip({"floatingip": {
465 "floating_network_id": floating_net_id}})
466 return fip['floatingip']
467
468 def delete_floating_ip(self, floatingip_id):
469 try:
470 return self.os_clients.network.delete_floatingip(floatingip_id)
471 except neutron_common.exceptions.NotFound as e:
472 msg = "Could not delete a Floating IP, UUID {}. Error: {}" \
473 "".format(floatingip_id, e)
474 logger.info(msg)
Ievgeniia Zadorozhnac67b86b2023-02-02 18:09:12 +0300475
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300476 def create_project(self):
477 project_name = "spt-test-project-{}".format(random.randrange(100, 999))
478 project = self.os_clients.auth.projects.create(
479 name=project_name, domain=self.os_clients.domain,
480 description="Mirantis SPT test project")
481 logger.info("Created a project {}, uuid: {}".format(
482 project.name, project.id))
483 return project
484
485 def add_roles_to_user_in_project(self, project_id, username='admin',
486 domain='default', roles=None):
487 user_id = [
488 user.id for user in self.os_clients.auth.users.list()
489 if (user.name == username) and (user.domain_id == domain)][0]
490 if roles is None:
491 roles = ["admin", "member", "creator"]
492 for role in roles:
493 try:
494 role_id = self.os_clients.auth.roles.list(name=role)[0].id
495 self.os_clients.auth.roles.grant(
496 role=role_id, user=user_id, project=project_id)
497 except Exception as e:
498 continue
499 logger.info("Added admin user to {} project".format(project_id))
500
501 def is_project_empty(self, project_id):
502 sec_groups = [i for i in self.os_clients.network.list_security_groups(
503 tenant_id=project_id)['security_groups'] if i['name'] != 'default']
504 servers = self.os_clients.compute.servers.list(
505 search_opts={'project_id': project_id})
506 nets = self.os_clients.network.list_networks(
507 project_id=project_id)["networks"]
508 subnets = self.os_clients.network.list_subnets(
509 project_id=project_id)["subnets"]
510 ports = self.os_clients.network.list_ports(
511 project_id=project_id)["ports"]
512 routers = self.os_clients.network.list_routers(
513 project_id=project_id)["routers"]
514 resources = [*sec_groups, *servers, *nets, *subnets, *ports, *routers]
515 return not bool(resources)
516
Ievgeniia Zadorozhnac67b86b2023-02-02 18:09:12 +0300517 def is_cloud_tf(self):
518 # Detect the TF cloud by assuming it does not have any neutron
519 # agents (404 in response)
520 try:
521 self.os_clients.network.list_agents()
522 except neutron_common.exceptions.NotFound:
523 logger.info("MOS TF cloud is detected.")
524 return True
525 return False
526
527 def update_network_port_with_custom_mtu(self, vm_uuid, custom_mtu):
528 port_uuid = self.os_clients.network.list_ports(
529 device_id=vm_uuid).get("ports")[0]["id"]
530 body = {"port": {"extra_dhcp_opts": [
531 {"opt_name": "interface-mtu", "opt_value": str(custom_mtu)}]}}
532 try:
533 self.os_clients.network.update_port(port_uuid, body)
534 except Exception as e:
535 raise Exception("Could not set custom MTU by updating the port. "
536 "See detailed error: {}".format(e))
537 logger.info("The port {} is updated with custom MTU {}."
538 "".format(port_uuid, custom_mtu))
Ievgeniia Zadorozhnaf22827b2022-07-20 13:30:32 +0300539
540 def get_flavor_id_by_name(self, name):
541 flavors = [flavor for flavor in self.os_clients.compute.flavors.list()]
542 flavor_id = [f.id for f in flavors if f.name == name]
543 if not flavor_id:
544 return None
545 return str(flavor_id[0])