blob: dc0e00e9d747568587b582c7b9928a4c293d98e0 [file] [log] [blame]
tierno0937f202020-04-20 08:54:21 +00001# -*- coding: utf-8 -*-
2
3##
4# Copyright 2020 Telefonica Investigacion y Desarrollo, S.A.U.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
19"""
20Implements a Dummy vim plugin.
21"""
22
tierno0937f202020-04-20 08:54:21 +000023from copy import deepcopy
tierno274bfc72020-09-24 12:31:36 +000024import logging
elumalai51e72a02023-04-28 19:41:49 +053025from random import SystemRandom
sousaedu049cbb12022-01-05 11:39:35 +000026from uuid import uuid4
27
28from osm_ro_plugin import vimconn
29import yaml
30
tierno0937f202020-04-20 08:54:21 +000031
32__author__ = "Alfonso Tierno"
tierno1ec592d2020-06-16 15:29:47 +000033__date__ = "2020-04-20"
tierno0937f202020-04-20 08:54:21 +000034
35
tierno72774862020-05-04 11:44:15 +000036class VimDummyConnector(vimconn.VimConnector):
tierno0937f202020-04-20 08:54:21 +000037 """Dummy vim connector that does nothing
38 Provide config with:
39 vm_ip: ip address to provide at VM creation. For some tests must be a valid reachable VM
40 ssh_key: private ssh key to use for inserting an authorized ssh key
41 """
sousaedu80135b92021-02-17 15:05:18 +010042
43 def __init__(
44 self,
45 uuid,
46 name,
47 tenant_id,
48 tenant_name,
49 url,
50 url_admin=None,
51 user=None,
52 passwd=None,
53 log_level=None,
54 config={},
55 persistent_info={},
56 ):
57 super().__init__(
58 uuid,
59 name,
60 tenant_id,
61 tenant_name,
62 url,
63 url_admin,
64 user,
65 passwd,
66 log_level,
67 config,
68 persistent_info,
69 )
70 self.logger = logging.getLogger("ro.vim.dummy")
71
tierno274bfc72020-09-24 12:31:36 +000072 if log_level:
73 self.logger.setLevel(getattr(logging, log_level))
sousaedu80135b92021-02-17 15:05:18 +010074
tierno0937f202020-04-20 08:54:21 +000075 self.nets = {
76 "mgmt": {
77 "id": "mgmt",
78 "name": "mgmt",
79 "status": "ACTIVE",
sousaedu80135b92021-02-17 15:05:18 +010080 "vim_info": "{status: ACTIVE}",
tierno0937f202020-04-20 08:54:21 +000081 }
82 }
83 self.vms = {}
84 self.flavors = {}
85 self.tenants = {}
86 # preload some images
87 self.images = {
88 "90681b39-dc09-49b7-ba2e-2c00c6b33b76": {
89 "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76",
90 "name": "cirros034",
sousaedu80135b92021-02-17 15:05:18 +010091 "checksum": "ee1eca47dc88f4879d8a229cc70a07c6",
tierno0937f202020-04-20 08:54:21 +000092 },
93 "83a39656-65db-47dc-af03-b55289115a53": {
94 "id": "",
95 "name": "cirros040",
sousaedu80135b92021-02-17 15:05:18 +010096 "checksum": "443b7623e27ecf03dc9e01ee93f67afe",
tierno0937f202020-04-20 08:54:21 +000097 },
98 "208314f2-8eb6-4101-965d-fe2ffbaedf3c": {
99 "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c",
100 "name": "ubuntu18.04",
sousaedu80135b92021-02-17 15:05:18 +0100101 "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95",
tierno0937f202020-04-20 08:54:21 +0000102 },
103 "c03321f8-4b6e-4045-a309-1b3878bd32c1": {
104 "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1",
105 "name": "ubuntu16.04",
sousaedu80135b92021-02-17 15:05:18 +0100106 "checksum": "8f08442faebad2d4a99fedb22fca11b5",
tierno0937f202020-04-20 08:54:21 +0000107 },
108 "4f6399a2-3554-457e-916e-ada01f8b950b": {
109 "id": "4f6399a2-3554-457e-916e-ada01f8b950b",
110 "name": "ubuntu1604",
sousaedu80135b92021-02-17 15:05:18 +0100111 "checksum": "8f08442faebad2d4a99fedb22fca11b5",
tierno0937f202020-04-20 08:54:21 +0000112 },
113 "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": {
114 "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3",
115 "name": "hackfest3-mgmt",
sousaedu80135b92021-02-17 15:05:18 +0100116 "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a",
tierno0937f202020-04-20 08:54:21 +0000117 },
118 "f8818a03-f099-4c18-b1c7-26b1324203c1": {
119 "id": "f8818a03-f099-4c18-b1c7-26b1324203c1",
120 "name": "hackfest-pktgen",
sousaedu80135b92021-02-17 15:05:18 +0100121 "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1",
tierno0937f202020-04-20 08:54:21 +0000122 },
123 }
124
sousaedu80135b92021-02-17 15:05:18 +0100125 def new_network(
126 self,
127 net_name,
128 net_type,
129 ip_profile=None,
130 shared=False,
131 provider_network_profile=None,
132 ):
tierno0937f202020-04-20 08:54:21 +0000133 net_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100134 self.logger.debug(
135 "new network id={}, name={}, net_type={}, ip_profile={}, provider_network_profile={}".format(
136 net_id, net_name, net_type, ip_profile, provider_network_profile
137 )
138 )
tierno0937f202020-04-20 08:54:21 +0000139 net = {
140 "id": net_id,
141 "name": net_name,
142 "net_type": net_type,
143 "status": "ACTIVE",
144 }
145 self.nets[net_id] = net
sousaedu80135b92021-02-17 15:05:18 +0100146
tierno0937f202020-04-20 08:54:21 +0000147 return net_id, net
148
149 def get_network_list(self, filter_dict=None):
150 nets = []
sousaedu80135b92021-02-17 15:05:18 +0100151
tierno0937f202020-04-20 08:54:21 +0000152 for net_id, net in self.nets.items():
153 if filter_dict and filter_dict.get("name"):
154 if net["name"] != filter_dict.get("name"):
155 continue
sousaedu80135b92021-02-17 15:05:18 +0100156
tierno0937f202020-04-20 08:54:21 +0000157 if filter_dict and filter_dict.get("id"):
158 if net_id != filter_dict.get("id"):
159 continue
sousaedu80135b92021-02-17 15:05:18 +0100160
tierno0937f202020-04-20 08:54:21 +0000161 nets.append(net)
sousaedu80135b92021-02-17 15:05:18 +0100162
lloretgalleg23f50012021-04-23 11:25:09 +0000163 # if no network is returned and search by name create a new one
164 if not nets and filter_dict and filter_dict.get("name"):
165 net_id, net = self.new_network(filter_dict.get("name"), "mgmt")
166 nets.append(net)
167
tierno0937f202020-04-20 08:54:21 +0000168 return nets
169
170 def get_network(self, net_id):
171 if net_id not in self.nets:
sousaedu80135b92021-02-17 15:05:18 +0100172 raise vimconn.VimConnNotFoundException(
173 "network with id {} not found".format(net_id)
174 )
175
tierno0937f202020-04-20 08:54:21 +0000176 return self.nets[net_id]
177
178 def delete_network(self, net_id, created_items=None):
179 if net_id not in self.nets:
sousaedu80135b92021-02-17 15:05:18 +0100180 raise vimconn.VimConnNotFoundException(
181 "network with id {} not found".format(net_id)
182 )
183
184 self.logger.debug(
185 "delete network id={}, created_items={}".format(net_id, created_items)
186 )
tierno0937f202020-04-20 08:54:21 +0000187 self.nets.pop(net_id)
sousaedu80135b92021-02-17 15:05:18 +0100188
tiernob54edb52020-07-02 09:58:51 +0000189 return net_id
tierno0937f202020-04-20 08:54:21 +0000190
191 def refresh_nets_status(self, net_list):
192 nets = {}
sousaedu80135b92021-02-17 15:05:18 +0100193
tierno0937f202020-04-20 08:54:21 +0000194 for net_id in net_list:
195 if net_id not in self.nets:
196 net = {"status": "DELETED"}
197 else:
198 net = self.nets[net_id].copy()
sousaedu80135b92021-02-17 15:05:18 +0100199 net["vim_info"] = yaml.dump(
200 {"status": "ACTIVE", "name": net["name"]},
201 default_flow_style=True,
202 width=256,
203 )
204
tierno0937f202020-04-20 08:54:21 +0000205 nets[net_id] = net
206
207 return nets
208
209 def get_flavor(self, flavor_id):
210 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100211 raise vimconn.VimConnNotFoundException(
212 "flavor with id {} not found".format(flavor_id)
213 )
214
tierno0937f202020-04-20 08:54:21 +0000215 return self.flavors[flavor_id]
216
217 def new_flavor(self, flavor_data):
218 flavor_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100219 self.logger.debug(
220 "new flavor id={}, flavor_data={}".format(flavor_id, flavor_data)
221 )
tierno0937f202020-04-20 08:54:21 +0000222 flavor = deepcopy(flavor_data)
223 flavor["id"] = flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100224
tierno0937f202020-04-20 08:54:21 +0000225 if "name" not in flavor:
226 flavor["name"] = flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100227
tierno0937f202020-04-20 08:54:21 +0000228 self.flavors[flavor_id] = flavor
sousaedu80135b92021-02-17 15:05:18 +0100229
tierno0937f202020-04-20 08:54:21 +0000230 return flavor_id
231
232 def delete_flavor(self, flavor_id):
233 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100234 raise vimconn.VimConnNotFoundException(
235 "flavor with id {} not found".format(flavor_id)
236 )
237
tierno274bfc72020-09-24 12:31:36 +0000238 self.logger.debug("delete flavor id={}".format(flavor_id))
tierno0937f202020-04-20 08:54:21 +0000239 self.flavors.pop(flavor_id)
sousaedu80135b92021-02-17 15:05:18 +0100240
tierno274bfc72020-09-24 12:31:36 +0000241 return flavor_id
tierno0937f202020-04-20 08:54:21 +0000242
243 def get_flavor_id_from_data(self, flavor_dict):
244 for flavor_id, flavor_data in self.flavors.items():
245 for k in ("ram", "vcpus", "disk", "extended"):
246 if flavor_data.get(k) != flavor_dict.get(k):
247 break
248 else:
249 return flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100250
251 raise vimconn.VimConnNotFoundException(
252 "flavor with ram={} cpu={} disk={} {} not found".format(
253 flavor_dict["ram"],
254 flavor_dict["vcpus"],
255 flavor_dict["disk"],
256 "and extended" if flavor_dict.get("extended") else "",
257 )
258 )
tierno0937f202020-04-20 08:54:21 +0000259
260 def new_tenant(self, tenant_name, tenant_description):
261 tenant_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100262 self.logger.debug(
263 "new tenant id={}, description={}".format(tenant_id, tenant_description)
264 )
265 tenant = {
266 "name": tenant_name,
267 "description": tenant_description,
268 "id": tenant_id,
269 }
tierno0937f202020-04-20 08:54:21 +0000270 self.tenants[tenant_id] = tenant
sousaedu80135b92021-02-17 15:05:18 +0100271
tierno0937f202020-04-20 08:54:21 +0000272 return tenant_id
273
274 def delete_tenant(self, tenant_id):
275 if tenant_id not in self.tenants:
sousaedu80135b92021-02-17 15:05:18 +0100276 raise vimconn.VimConnNotFoundException(
277 "tenant with id {} not found".format(tenant_id)
278 )
279
tierno0937f202020-04-20 08:54:21 +0000280 self.tenants.pop(tenant_id)
tierno274bfc72020-09-24 12:31:36 +0000281 self.logger.debug("delete tenant id={}".format(tenant_id))
sousaedu80135b92021-02-17 15:05:18 +0100282
tierno274bfc72020-09-24 12:31:36 +0000283 return tenant_id
tierno0937f202020-04-20 08:54:21 +0000284
285 def get_tenant_list(self, filter_dict=None):
286 tenants = []
sousaedu80135b92021-02-17 15:05:18 +0100287
tierno0937f202020-04-20 08:54:21 +0000288 for tenant_id, tenant in self.tenants.items():
289 if filter_dict and filter_dict.get("name"):
290 if tenant["name"] != filter_dict.get("name"):
291 continue
sousaedu80135b92021-02-17 15:05:18 +0100292
tierno0937f202020-04-20 08:54:21 +0000293 if filter_dict and filter_dict.get("id"):
294 if tenant_id != filter_dict.get("id"):
295 continue
sousaedu80135b92021-02-17 15:05:18 +0100296
tierno0937f202020-04-20 08:54:21 +0000297 tenants.append(tenant)
sousaedu80135b92021-02-17 15:05:18 +0100298
tierno0937f202020-04-20 08:54:21 +0000299 return tenants
300
301 def new_image(self, image_dict):
302 image_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +0000303 self.logger.debug("new image id={}, iamge_dict={}".format(image_id, image_dict))
tierno0937f202020-04-20 08:54:21 +0000304 image = deepcopy(image_dict)
305 image["id"] = image_id
sousaedu80135b92021-02-17 15:05:18 +0100306
tierno0937f202020-04-20 08:54:21 +0000307 if "name" not in image:
308 image["id"] = image_id
sousaedu80135b92021-02-17 15:05:18 +0100309
tierno0937f202020-04-20 08:54:21 +0000310 self.images[image_id] = image
sousaedu80135b92021-02-17 15:05:18 +0100311
tierno0937f202020-04-20 08:54:21 +0000312 return image_id
313
314 def delete_image(self, image_id):
315 if image_id not in self.images:
sousaedu80135b92021-02-17 15:05:18 +0100316 raise vimconn.VimConnNotFoundException(
317 "image with id {} not found".format(image_id)
318 )
319
tierno274bfc72020-09-24 12:31:36 +0000320 self.logger.debug("delete image id={}".format(image_id))
tierno0937f202020-04-20 08:54:21 +0000321 self.images.pop(image_id)
sousaedu80135b92021-02-17 15:05:18 +0100322
tierno274bfc72020-09-24 12:31:36 +0000323 return image_id
tierno0937f202020-04-20 08:54:21 +0000324
325 def get_image_list(self, filter_dict=None):
326 images = []
327 for image_id, image in self.images.items():
328 if filter_dict and filter_dict.get("name"):
329 if image["name"] != filter_dict.get("name"):
330 continue
sousaedu80135b92021-02-17 15:05:18 +0100331
tierno0937f202020-04-20 08:54:21 +0000332 if filter_dict and filter_dict.get("checksum"):
333 if image["checksum"] != filter_dict.get("checksum"):
334 continue
sousaedu80135b92021-02-17 15:05:18 +0100335
tierno0937f202020-04-20 08:54:21 +0000336 if filter_dict and filter_dict.get("id"):
337 if image_id != filter_dict.get("id"):
338 continue
sousaedu80135b92021-02-17 15:05:18 +0100339
tierno0937f202020-04-20 08:54:21 +0000340 images.append(image)
sousaedu80135b92021-02-17 15:05:18 +0100341
tierno0937f202020-04-20 08:54:21 +0000342 return images
343
sousaedu80135b92021-02-17 15:05:18 +0100344 def new_vminstance(
345 self,
346 name,
347 description,
348 start,
349 image_id,
350 flavor_id,
Alexis Romerob70f4ed2022-03-11 18:00:49 +0100351 affinity_group_list,
sousaedu80135b92021-02-17 15:05:18 +0100352 net_list,
353 cloud_config=None,
354 disk_list=None,
355 availability_zone_index=None,
356 availability_zone_list=None,
357 ):
tierno0937f202020-04-20 08:54:21 +0000358 vm_id = str(uuid4())
359 interfaces = []
sousaedu80135b92021-02-17 15:05:18 +0100360 self.logger.debug(
361 "new vm id={}, name={}, image_id={}, flavor_id={}, net_list={}, cloud_config={}".format(
362 vm_id, name, image_id, flavor_id, net_list, cloud_config
363 )
364 )
365
tierno0937f202020-04-20 08:54:21 +0000366 for iface_index, iface in enumerate(net_list):
367 iface["vim_id"] = str(iface_index)
368 interface = {
sousaedu80135b92021-02-17 15:05:18 +0100369 "ip_address": iface.get("ip_address")
370 or self.config.get("vm_ip")
371 or "192.168.4.2",
372 "mac_address": iface.get("mac_address")
373 or self.config.get("vm_mac")
374 or "00:11:22:33:44:55",
tierno0937f202020-04-20 08:54:21 +0000375 "vim_interface_id": str(iface_index),
376 "vim_net_id": iface["net_id"],
377 }
sousaedu80135b92021-02-17 15:05:18 +0100378
379 if iface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH") and self.config.get(
380 "sdn-port-mapping"
381 ):
elumalai51e72a02023-04-28 19:41:49 +0530382 compute_index = SystemRandom().randrange(
383 len(self.config["sdn-port-mapping"])
384 )
385 port_index = SystemRandom().randrange(
sousaedu80135b92021-02-17 15:05:18 +0100386 len(self.config["sdn-port-mapping"][compute_index]["ports"])
387 )
388 interface["compute_node"] = self.config["sdn-port-mapping"][
389 compute_index
390 ]["compute_node"]
391 interface["pci"] = self.config["sdn-port-mapping"][compute_index][
392 "ports"
393 ][port_index]["pci"]
tierno70eeb182020-10-19 16:38:00 +0000394
tierno0937f202020-04-20 08:54:21 +0000395 interfaces.append(interface)
sousaedu80135b92021-02-17 15:05:18 +0100396
tierno0937f202020-04-20 08:54:21 +0000397 vm = {
398 "id": vm_id,
399 "name": name,
400 "status": "ACTIVE",
401 "description": description,
402 "interfaces": interfaces,
403 "image_id": image_id,
404 "flavor_id": flavor_id,
405 }
sousaedu80135b92021-02-17 15:05:18 +0100406
tierno0937f202020-04-20 08:54:21 +0000407 if image_id not in self.images:
sousaedu80135b92021-02-17 15:05:18 +0100408 self.logger.error(
409 "vm create, image_id '{}' not found. Skip".format(image_id)
410 )
411
tierno0937f202020-04-20 08:54:21 +0000412 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100413 self.logger.error(
414 "vm create flavor_id '{}' not found. Skip".format(flavor_id)
415 )
416
tierno0937f202020-04-20 08:54:21 +0000417 self.vms[vm_id] = vm
sousaedu80135b92021-02-17 15:05:18 +0100418
tierno0937f202020-04-20 08:54:21 +0000419 return vm_id, vm
420
421 def get_vminstance(self, vm_id):
422 if vm_id not in self.vms:
sousaedu80135b92021-02-17 15:05:18 +0100423 raise vimconn.VimConnNotFoundException(
424 "vm with id {} not found".format(vm_id)
425 )
426
tierno0937f202020-04-20 08:54:21 +0000427 return self.vms[vm_id]
428
garciadeblas89598d42022-06-30 13:57:43 +0200429 def delete_vminstance(self, vm_id, created_items=None, volumes_to_hold=None):
tierno0937f202020-04-20 08:54:21 +0000430 if vm_id not in self.vms:
sousaedu80135b92021-02-17 15:05:18 +0100431 raise vimconn.VimConnNotFoundException(
432 "vm with id {} not found".format(vm_id)
433 )
434
tierno0937f202020-04-20 08:54:21 +0000435 self.vms.pop(vm_id)
sousaedu80135b92021-02-17 15:05:18 +0100436 self.logger.debug(
437 "delete vm id={}, created_items={}".format(vm_id, created_items)
438 )
439
tierno274bfc72020-09-24 12:31:36 +0000440 return vm_id
tierno0937f202020-04-20 08:54:21 +0000441
442 def refresh_vms_status(self, vm_list):
443 vms = {}
sousaedu80135b92021-02-17 15:05:18 +0100444
tierno0937f202020-04-20 08:54:21 +0000445 for vm_id in vm_list:
446 if vm_id not in self.vms:
447 vm = {"status": "DELETED"}
448 else:
449 vm = deepcopy(self.vms[vm_id])
sousaedu80135b92021-02-17 15:05:18 +0100450 vm["vim_info"] = yaml.dump(
451 {"status": "ACTIVE", "name": vm["name"]},
452 default_flow_style=True,
453 width=256,
454 )
455
tierno0937f202020-04-20 08:54:21 +0000456 vms[vm_id] = vm
sousaedu80135b92021-02-17 15:05:18 +0100457
tierno0937f202020-04-20 08:54:21 +0000458 return vms
459
460 def action_vminstance(self, vm_id, action_dict, created_items={}):
461 return None
462
sousaedu80135b92021-02-17 15:05:18 +0100463 def inject_user_key(
464 self, ip_addr=None, user=None, key=None, ro_key=None, password=None
465 ):
tierno0937f202020-04-20 08:54:21 +0000466 if self.config.get("ssh_key"):
467 ro_key = self.config.get("ssh_key")
sousaedu80135b92021-02-17 15:05:18 +0100468
469 return super().inject_user_key(
470 ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password
471 )