blob: c00071f896ef1fd79e9dee81ade5639758d705c3 [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
23import yaml
tierno72774862020-05-04 11:44:15 +000024from osm_ro_plugin import vimconn
tierno0937f202020-04-20 08:54:21 +000025from uuid import uuid4
26from copy import deepcopy
tierno274bfc72020-09-24 12:31:36 +000027import logging
tierno70eeb182020-10-19 16:38:00 +000028from random import randrange
tierno0937f202020-04-20 08:54:21 +000029
30__author__ = "Alfonso Tierno"
tierno1ec592d2020-06-16 15:29:47 +000031__date__ = "2020-04-20"
tierno0937f202020-04-20 08:54:21 +000032
33
tierno72774862020-05-04 11:44:15 +000034class VimDummyConnector(vimconn.VimConnector):
tierno0937f202020-04-20 08:54:21 +000035 """Dummy vim connector that does nothing
36 Provide config with:
37 vm_ip: ip address to provide at VM creation. For some tests must be a valid reachable VM
38 ssh_key: private ssh key to use for inserting an authorized ssh key
39 """
sousaedu80135b92021-02-17 15:05:18 +010040
41 def __init__(
42 self,
43 uuid,
44 name,
45 tenant_id,
46 tenant_name,
47 url,
48 url_admin=None,
49 user=None,
50 passwd=None,
51 log_level=None,
52 config={},
53 persistent_info={},
54 ):
55 super().__init__(
56 uuid,
57 name,
58 tenant_id,
59 tenant_name,
60 url,
61 url_admin,
62 user,
63 passwd,
64 log_level,
65 config,
66 persistent_info,
67 )
68 self.logger = logging.getLogger("ro.vim.dummy")
69
tierno274bfc72020-09-24 12:31:36 +000070 if log_level:
71 self.logger.setLevel(getattr(logging, log_level))
sousaedu80135b92021-02-17 15:05:18 +010072
tierno0937f202020-04-20 08:54:21 +000073 self.nets = {
74 "mgmt": {
75 "id": "mgmt",
76 "name": "mgmt",
77 "status": "ACTIVE",
sousaedu80135b92021-02-17 15:05:18 +010078 "vim_info": "{status: ACTIVE}",
tierno0937f202020-04-20 08:54:21 +000079 }
80 }
81 self.vms = {}
82 self.flavors = {}
83 self.tenants = {}
84 # preload some images
85 self.images = {
86 "90681b39-dc09-49b7-ba2e-2c00c6b33b76": {
87 "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76",
88 "name": "cirros034",
sousaedu80135b92021-02-17 15:05:18 +010089 "checksum": "ee1eca47dc88f4879d8a229cc70a07c6",
tierno0937f202020-04-20 08:54:21 +000090 },
91 "83a39656-65db-47dc-af03-b55289115a53": {
92 "id": "",
93 "name": "cirros040",
sousaedu80135b92021-02-17 15:05:18 +010094 "checksum": "443b7623e27ecf03dc9e01ee93f67afe",
tierno0937f202020-04-20 08:54:21 +000095 },
96 "208314f2-8eb6-4101-965d-fe2ffbaedf3c": {
97 "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c",
98 "name": "ubuntu18.04",
sousaedu80135b92021-02-17 15:05:18 +010099 "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95",
tierno0937f202020-04-20 08:54:21 +0000100 },
101 "c03321f8-4b6e-4045-a309-1b3878bd32c1": {
102 "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1",
103 "name": "ubuntu16.04",
sousaedu80135b92021-02-17 15:05:18 +0100104 "checksum": "8f08442faebad2d4a99fedb22fca11b5",
tierno0937f202020-04-20 08:54:21 +0000105 },
106 "4f6399a2-3554-457e-916e-ada01f8b950b": {
107 "id": "4f6399a2-3554-457e-916e-ada01f8b950b",
108 "name": "ubuntu1604",
sousaedu80135b92021-02-17 15:05:18 +0100109 "checksum": "8f08442faebad2d4a99fedb22fca11b5",
tierno0937f202020-04-20 08:54:21 +0000110 },
111 "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": {
112 "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3",
113 "name": "hackfest3-mgmt",
sousaedu80135b92021-02-17 15:05:18 +0100114 "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a",
tierno0937f202020-04-20 08:54:21 +0000115 },
116 "f8818a03-f099-4c18-b1c7-26b1324203c1": {
117 "id": "f8818a03-f099-4c18-b1c7-26b1324203c1",
118 "name": "hackfest-pktgen",
sousaedu80135b92021-02-17 15:05:18 +0100119 "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1",
tierno0937f202020-04-20 08:54:21 +0000120 },
121 }
122
sousaedu80135b92021-02-17 15:05:18 +0100123 def new_network(
124 self,
125 net_name,
126 net_type,
127 ip_profile=None,
128 shared=False,
129 provider_network_profile=None,
130 ):
tierno0937f202020-04-20 08:54:21 +0000131 net_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100132 self.logger.debug(
133 "new network id={}, name={}, net_type={}, ip_profile={}, provider_network_profile={}".format(
134 net_id, net_name, net_type, ip_profile, provider_network_profile
135 )
136 )
tierno0937f202020-04-20 08:54:21 +0000137 net = {
138 "id": net_id,
139 "name": net_name,
140 "net_type": net_type,
141 "status": "ACTIVE",
142 }
143 self.nets[net_id] = net
sousaedu80135b92021-02-17 15:05:18 +0100144
tierno0937f202020-04-20 08:54:21 +0000145 return net_id, net
146
147 def get_network_list(self, filter_dict=None):
148 nets = []
sousaedu80135b92021-02-17 15:05:18 +0100149
tierno0937f202020-04-20 08:54:21 +0000150 for net_id, net in self.nets.items():
151 if filter_dict and filter_dict.get("name"):
152 if net["name"] != filter_dict.get("name"):
153 continue
sousaedu80135b92021-02-17 15:05:18 +0100154
tierno0937f202020-04-20 08:54:21 +0000155 if filter_dict and filter_dict.get("id"):
156 if net_id != filter_dict.get("id"):
157 continue
sousaedu80135b92021-02-17 15:05:18 +0100158
tierno0937f202020-04-20 08:54:21 +0000159 nets.append(net)
sousaedu80135b92021-02-17 15:05:18 +0100160
tierno0937f202020-04-20 08:54:21 +0000161 return nets
162
163 def get_network(self, net_id):
164 if net_id not in self.nets:
sousaedu80135b92021-02-17 15:05:18 +0100165 raise vimconn.VimConnNotFoundException(
166 "network with id {} not found".format(net_id)
167 )
168
tierno0937f202020-04-20 08:54:21 +0000169 return self.nets[net_id]
170
171 def delete_network(self, net_id, created_items=None):
172 if net_id not in self.nets:
sousaedu80135b92021-02-17 15:05:18 +0100173 raise vimconn.VimConnNotFoundException(
174 "network with id {} not found".format(net_id)
175 )
176
177 self.logger.debug(
178 "delete network id={}, created_items={}".format(net_id, created_items)
179 )
tierno0937f202020-04-20 08:54:21 +0000180 self.nets.pop(net_id)
sousaedu80135b92021-02-17 15:05:18 +0100181
tiernob54edb52020-07-02 09:58:51 +0000182 return net_id
tierno0937f202020-04-20 08:54:21 +0000183
184 def refresh_nets_status(self, net_list):
185 nets = {}
sousaedu80135b92021-02-17 15:05:18 +0100186
tierno0937f202020-04-20 08:54:21 +0000187 for net_id in net_list:
188 if net_id not in self.nets:
189 net = {"status": "DELETED"}
190 else:
191 net = self.nets[net_id].copy()
sousaedu80135b92021-02-17 15:05:18 +0100192 net["vim_info"] = yaml.dump(
193 {"status": "ACTIVE", "name": net["name"]},
194 default_flow_style=True,
195 width=256,
196 )
197
tierno0937f202020-04-20 08:54:21 +0000198 nets[net_id] = net
199
200 return nets
201
202 def get_flavor(self, flavor_id):
203 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100204 raise vimconn.VimConnNotFoundException(
205 "flavor with id {} not found".format(flavor_id)
206 )
207
tierno0937f202020-04-20 08:54:21 +0000208 return self.flavors[flavor_id]
209
210 def new_flavor(self, flavor_data):
211 flavor_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100212 self.logger.debug(
213 "new flavor id={}, flavor_data={}".format(flavor_id, flavor_data)
214 )
tierno0937f202020-04-20 08:54:21 +0000215 flavor = deepcopy(flavor_data)
216 flavor["id"] = flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100217
tierno0937f202020-04-20 08:54:21 +0000218 if "name" not in flavor:
219 flavor["name"] = flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100220
tierno0937f202020-04-20 08:54:21 +0000221 self.flavors[flavor_id] = flavor
sousaedu80135b92021-02-17 15:05:18 +0100222
tierno0937f202020-04-20 08:54:21 +0000223 return flavor_id
224
225 def delete_flavor(self, flavor_id):
226 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100227 raise vimconn.VimConnNotFoundException(
228 "flavor with id {} not found".format(flavor_id)
229 )
230
tierno274bfc72020-09-24 12:31:36 +0000231 self.logger.debug("delete flavor id={}".format(flavor_id))
tierno0937f202020-04-20 08:54:21 +0000232 self.flavors.pop(flavor_id)
sousaedu80135b92021-02-17 15:05:18 +0100233
tierno274bfc72020-09-24 12:31:36 +0000234 return flavor_id
tierno0937f202020-04-20 08:54:21 +0000235
236 def get_flavor_id_from_data(self, flavor_dict):
237 for flavor_id, flavor_data in self.flavors.items():
238 for k in ("ram", "vcpus", "disk", "extended"):
239 if flavor_data.get(k) != flavor_dict.get(k):
240 break
241 else:
242 return flavor_id
sousaedu80135b92021-02-17 15:05:18 +0100243
244 raise vimconn.VimConnNotFoundException(
245 "flavor with ram={} cpu={} disk={} {} not found".format(
246 flavor_dict["ram"],
247 flavor_dict["vcpus"],
248 flavor_dict["disk"],
249 "and extended" if flavor_dict.get("extended") else "",
250 )
251 )
tierno0937f202020-04-20 08:54:21 +0000252
253 def new_tenant(self, tenant_name, tenant_description):
254 tenant_id = str(uuid4())
sousaedu80135b92021-02-17 15:05:18 +0100255 self.logger.debug(
256 "new tenant id={}, description={}".format(tenant_id, tenant_description)
257 )
258 tenant = {
259 "name": tenant_name,
260 "description": tenant_description,
261 "id": tenant_id,
262 }
tierno0937f202020-04-20 08:54:21 +0000263 self.tenants[tenant_id] = tenant
sousaedu80135b92021-02-17 15:05:18 +0100264
tierno0937f202020-04-20 08:54:21 +0000265 return tenant_id
266
267 def delete_tenant(self, tenant_id):
268 if tenant_id not in self.tenants:
sousaedu80135b92021-02-17 15:05:18 +0100269 raise vimconn.VimConnNotFoundException(
270 "tenant with id {} not found".format(tenant_id)
271 )
272
tierno0937f202020-04-20 08:54:21 +0000273 self.tenants.pop(tenant_id)
tierno274bfc72020-09-24 12:31:36 +0000274 self.logger.debug("delete tenant id={}".format(tenant_id))
sousaedu80135b92021-02-17 15:05:18 +0100275
tierno274bfc72020-09-24 12:31:36 +0000276 return tenant_id
tierno0937f202020-04-20 08:54:21 +0000277
278 def get_tenant_list(self, filter_dict=None):
279 tenants = []
sousaedu80135b92021-02-17 15:05:18 +0100280
tierno0937f202020-04-20 08:54:21 +0000281 for tenant_id, tenant in self.tenants.items():
282 if filter_dict and filter_dict.get("name"):
283 if tenant["name"] != filter_dict.get("name"):
284 continue
sousaedu80135b92021-02-17 15:05:18 +0100285
tierno0937f202020-04-20 08:54:21 +0000286 if filter_dict and filter_dict.get("id"):
287 if tenant_id != filter_dict.get("id"):
288 continue
sousaedu80135b92021-02-17 15:05:18 +0100289
tierno0937f202020-04-20 08:54:21 +0000290 tenants.append(tenant)
sousaedu80135b92021-02-17 15:05:18 +0100291
tierno0937f202020-04-20 08:54:21 +0000292 return tenants
293
294 def new_image(self, image_dict):
295 image_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +0000296 self.logger.debug("new image id={}, iamge_dict={}".format(image_id, image_dict))
tierno0937f202020-04-20 08:54:21 +0000297 image = deepcopy(image_dict)
298 image["id"] = image_id
sousaedu80135b92021-02-17 15:05:18 +0100299
tierno0937f202020-04-20 08:54:21 +0000300 if "name" not in image:
301 image["id"] = image_id
sousaedu80135b92021-02-17 15:05:18 +0100302
tierno0937f202020-04-20 08:54:21 +0000303 self.images[image_id] = image
sousaedu80135b92021-02-17 15:05:18 +0100304
tierno0937f202020-04-20 08:54:21 +0000305 return image_id
306
307 def delete_image(self, image_id):
308 if image_id not in self.images:
sousaedu80135b92021-02-17 15:05:18 +0100309 raise vimconn.VimConnNotFoundException(
310 "image with id {} not found".format(image_id)
311 )
312
tierno274bfc72020-09-24 12:31:36 +0000313 self.logger.debug("delete image id={}".format(image_id))
tierno0937f202020-04-20 08:54:21 +0000314 self.images.pop(image_id)
sousaedu80135b92021-02-17 15:05:18 +0100315
tierno274bfc72020-09-24 12:31:36 +0000316 return image_id
tierno0937f202020-04-20 08:54:21 +0000317
318 def get_image_list(self, filter_dict=None):
319 images = []
320 for image_id, image in self.images.items():
321 if filter_dict and filter_dict.get("name"):
322 if image["name"] != filter_dict.get("name"):
323 continue
sousaedu80135b92021-02-17 15:05:18 +0100324
tierno0937f202020-04-20 08:54:21 +0000325 if filter_dict and filter_dict.get("checksum"):
326 if image["checksum"] != filter_dict.get("checksum"):
327 continue
sousaedu80135b92021-02-17 15:05:18 +0100328
tierno0937f202020-04-20 08:54:21 +0000329 if filter_dict and filter_dict.get("id"):
330 if image_id != filter_dict.get("id"):
331 continue
sousaedu80135b92021-02-17 15:05:18 +0100332
tierno0937f202020-04-20 08:54:21 +0000333 images.append(image)
sousaedu80135b92021-02-17 15:05:18 +0100334
tierno0937f202020-04-20 08:54:21 +0000335 return images
336
sousaedu80135b92021-02-17 15:05:18 +0100337 def new_vminstance(
338 self,
339 name,
340 description,
341 start,
342 image_id,
343 flavor_id,
344 net_list,
345 cloud_config=None,
346 disk_list=None,
347 availability_zone_index=None,
348 availability_zone_list=None,
349 ):
tierno0937f202020-04-20 08:54:21 +0000350 vm_id = str(uuid4())
351 interfaces = []
sousaedu80135b92021-02-17 15:05:18 +0100352 self.logger.debug(
353 "new vm id={}, name={}, image_id={}, flavor_id={}, net_list={}, cloud_config={}".format(
354 vm_id, name, image_id, flavor_id, net_list, cloud_config
355 )
356 )
357
tierno0937f202020-04-20 08:54:21 +0000358 for iface_index, iface in enumerate(net_list):
359 iface["vim_id"] = str(iface_index)
360 interface = {
sousaedu80135b92021-02-17 15:05:18 +0100361 "ip_address": iface.get("ip_address")
362 or self.config.get("vm_ip")
363 or "192.168.4.2",
364 "mac_address": iface.get("mac_address")
365 or self.config.get("vm_mac")
366 or "00:11:22:33:44:55",
tierno0937f202020-04-20 08:54:21 +0000367 "vim_interface_id": str(iface_index),
368 "vim_net_id": iface["net_id"],
369 }
sousaedu80135b92021-02-17 15:05:18 +0100370
371 if iface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH") and self.config.get(
372 "sdn-port-mapping"
373 ):
tierno70eeb182020-10-19 16:38:00 +0000374 compute_index = randrange(len(self.config["sdn-port-mapping"]))
sousaedu80135b92021-02-17 15:05:18 +0100375 port_index = randrange(
376 len(self.config["sdn-port-mapping"][compute_index]["ports"])
377 )
378 interface["compute_node"] = self.config["sdn-port-mapping"][
379 compute_index
380 ]["compute_node"]
381 interface["pci"] = self.config["sdn-port-mapping"][compute_index][
382 "ports"
383 ][port_index]["pci"]
tierno70eeb182020-10-19 16:38:00 +0000384
tierno0937f202020-04-20 08:54:21 +0000385 interfaces.append(interface)
sousaedu80135b92021-02-17 15:05:18 +0100386
tierno0937f202020-04-20 08:54:21 +0000387 vm = {
388 "id": vm_id,
389 "name": name,
390 "status": "ACTIVE",
391 "description": description,
392 "interfaces": interfaces,
393 "image_id": image_id,
394 "flavor_id": flavor_id,
395 }
sousaedu80135b92021-02-17 15:05:18 +0100396
tierno0937f202020-04-20 08:54:21 +0000397 if image_id not in self.images:
sousaedu80135b92021-02-17 15:05:18 +0100398 self.logger.error(
399 "vm create, image_id '{}' not found. Skip".format(image_id)
400 )
401
tierno0937f202020-04-20 08:54:21 +0000402 if flavor_id not in self.flavors:
sousaedu80135b92021-02-17 15:05:18 +0100403 self.logger.error(
404 "vm create flavor_id '{}' not found. Skip".format(flavor_id)
405 )
406
tierno0937f202020-04-20 08:54:21 +0000407 self.vms[vm_id] = vm
sousaedu80135b92021-02-17 15:05:18 +0100408
tierno0937f202020-04-20 08:54:21 +0000409 return vm_id, vm
410
411 def get_vminstance(self, vm_id):
412 if vm_id not in self.vms:
sousaedu80135b92021-02-17 15:05:18 +0100413 raise vimconn.VimConnNotFoundException(
414 "vm with id {} not found".format(vm_id)
415 )
416
tierno0937f202020-04-20 08:54:21 +0000417 return self.vms[vm_id]
418
419 def delete_vminstance(self, vm_id, created_items=None):
420 if vm_id not in self.vms:
sousaedu80135b92021-02-17 15:05:18 +0100421 raise vimconn.VimConnNotFoundException(
422 "vm with id {} not found".format(vm_id)
423 )
424
tierno0937f202020-04-20 08:54:21 +0000425 self.vms.pop(vm_id)
sousaedu80135b92021-02-17 15:05:18 +0100426 self.logger.debug(
427 "delete vm id={}, created_items={}".format(vm_id, created_items)
428 )
429
tierno274bfc72020-09-24 12:31:36 +0000430 return vm_id
tierno0937f202020-04-20 08:54:21 +0000431
432 def refresh_vms_status(self, vm_list):
433 vms = {}
sousaedu80135b92021-02-17 15:05:18 +0100434
tierno0937f202020-04-20 08:54:21 +0000435 for vm_id in vm_list:
436 if vm_id not in self.vms:
437 vm = {"status": "DELETED"}
438 else:
439 vm = deepcopy(self.vms[vm_id])
sousaedu80135b92021-02-17 15:05:18 +0100440 vm["vim_info"] = yaml.dump(
441 {"status": "ACTIVE", "name": vm["name"]},
442 default_flow_style=True,
443 width=256,
444 )
445
tierno0937f202020-04-20 08:54:21 +0000446 vms[vm_id] = vm
sousaedu80135b92021-02-17 15:05:18 +0100447
tierno0937f202020-04-20 08:54:21 +0000448 return vms
449
450 def action_vminstance(self, vm_id, action_dict, created_items={}):
451 return None
452
sousaedu80135b92021-02-17 15:05:18 +0100453 def inject_user_key(
454 self, ip_addr=None, user=None, key=None, ro_key=None, password=None
455 ):
tierno0937f202020-04-20 08:54:21 +0000456 if self.config.get("ssh_key"):
457 ro_key = self.config.get("ssh_key")
sousaedu80135b92021-02-17 15:05:18 +0100458
459 return super().inject_user_key(
460 ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password
461 )