blob: 22379b602ef21259ebb9c267ff04eb846591729c [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 """
40 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None,
41 config={}, persistent_info={}):
42 super().__init__(uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
43 config, persistent_info)
sousaedu3f8f2f42021-02-09 15:30:01 +010044 self.logger = logging.getLogger('ro.vim.dummy')
tierno274bfc72020-09-24 12:31:36 +000045 if log_level:
46 self.logger.setLevel(getattr(logging, log_level))
tierno0937f202020-04-20 08:54:21 +000047 self.nets = {
48 "mgmt": {
49 "id": "mgmt",
50 "name": "mgmt",
51 "status": "ACTIVE",
52 "vim_info": '{status: ACTIVE}'
53 }
54 }
55 self.vms = {}
56 self.flavors = {}
57 self.tenants = {}
58 # preload some images
59 self.images = {
60 "90681b39-dc09-49b7-ba2e-2c00c6b33b76": {
61 "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76",
62 "name": "cirros034",
63 "checksum": "ee1eca47dc88f4879d8a229cc70a07c6"
64 },
65 "83a39656-65db-47dc-af03-b55289115a53": {
66 "id": "",
67 "name": "cirros040",
68 "checksum": "443b7623e27ecf03dc9e01ee93f67afe"
69 },
70 "208314f2-8eb6-4101-965d-fe2ffbaedf3c": {
71 "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c",
72 "name": "ubuntu18.04",
73 "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95"
74 },
75 "c03321f8-4b6e-4045-a309-1b3878bd32c1": {
76 "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1",
77 "name": "ubuntu16.04",
78 "checksum": "8f08442faebad2d4a99fedb22fca11b5"
79 },
80 "4f6399a2-3554-457e-916e-ada01f8b950b": {
81 "id": "4f6399a2-3554-457e-916e-ada01f8b950b",
82 "name": "ubuntu1604",
83 "checksum": "8f08442faebad2d4a99fedb22fca11b5"
84 },
85 "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": {
86 "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3",
87 "name": "hackfest3-mgmt",
88 "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a"
89 },
90 "f8818a03-f099-4c18-b1c7-26b1324203c1": {
91 "id": "f8818a03-f099-4c18-b1c7-26b1324203c1",
92 "name": "hackfest-pktgen",
93 "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1"
94 },
95 }
96
97 def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None):
98 net_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +000099 self.logger.debug("new network id={}, name={}, net_type={}, ip_profile={}, provider_network_profile={}".
100 format(net_id, net_name, net_type, ip_profile, provider_network_profile))
tierno0937f202020-04-20 08:54:21 +0000101 net = {
102 "id": net_id,
103 "name": net_name,
104 "net_type": net_type,
105 "status": "ACTIVE",
106 }
107 self.nets[net_id] = net
108 return net_id, net
109
110 def get_network_list(self, filter_dict=None):
111 nets = []
112 for net_id, net in self.nets.items():
113 if filter_dict and filter_dict.get("name"):
114 if net["name"] != filter_dict.get("name"):
115 continue
116 if filter_dict and filter_dict.get("id"):
117 if net_id != filter_dict.get("id"):
118 continue
119 nets.append(net)
120 return nets
121
122 def get_network(self, net_id):
123 if net_id not in self.nets:
tierno72774862020-05-04 11:44:15 +0000124 raise vimconn.VimConnNotFoundException("network with id {} not found".format(net_id))
tierno0937f202020-04-20 08:54:21 +0000125 return self.nets[net_id]
126
127 def delete_network(self, net_id, created_items=None):
128 if net_id not in self.nets:
tierno72774862020-05-04 11:44:15 +0000129 raise vimconn.VimConnNotFoundException("network with id {} not found".format(net_id))
tierno274bfc72020-09-24 12:31:36 +0000130 self.logger.debug("delete network id={}, created_items={}".format(net_id, created_items))
tierno0937f202020-04-20 08:54:21 +0000131 self.nets.pop(net_id)
tiernob54edb52020-07-02 09:58:51 +0000132 return net_id
tierno0937f202020-04-20 08:54:21 +0000133
134 def refresh_nets_status(self, net_list):
135 nets = {}
136 for net_id in net_list:
137 if net_id not in self.nets:
138 net = {"status": "DELETED"}
139 else:
140 net = self.nets[net_id].copy()
141 net["vim_info"] = yaml.dump({"status": "ACTIVE", "name": net["name"]},
tierno1ec592d2020-06-16 15:29:47 +0000142 default_flow_style=True, width=256)
tierno0937f202020-04-20 08:54:21 +0000143 nets[net_id] = net
144
145 return nets
146
147 def get_flavor(self, flavor_id):
148 if flavor_id not in self.flavors:
tierno72774862020-05-04 11:44:15 +0000149 raise vimconn.VimConnNotFoundException("flavor with id {} not found".format(flavor_id))
tierno0937f202020-04-20 08:54:21 +0000150 return self.flavors[flavor_id]
151
152 def new_flavor(self, flavor_data):
153 flavor_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +0000154 self.logger.debug("new flavor id={}, flavor_data={}".format(flavor_id, flavor_data))
tierno0937f202020-04-20 08:54:21 +0000155 flavor = deepcopy(flavor_data)
156 flavor["id"] = flavor_id
157 if "name" not in flavor:
158 flavor["name"] = flavor_id
159 self.flavors[flavor_id] = flavor
160 return flavor_id
161
162 def delete_flavor(self, flavor_id):
163 if flavor_id not in self.flavors:
tierno72774862020-05-04 11:44:15 +0000164 raise vimconn.VimConnNotFoundException("flavor with id {} not found".format(flavor_id))
tierno274bfc72020-09-24 12:31:36 +0000165 self.logger.debug("delete flavor id={}".format(flavor_id))
tierno0937f202020-04-20 08:54:21 +0000166 self.flavors.pop(flavor_id)
tierno274bfc72020-09-24 12:31:36 +0000167 return flavor_id
tierno0937f202020-04-20 08:54:21 +0000168
169 def get_flavor_id_from_data(self, flavor_dict):
170 for flavor_id, flavor_data in self.flavors.items():
171 for k in ("ram", "vcpus", "disk", "extended"):
172 if flavor_data.get(k) != flavor_dict.get(k):
173 break
174 else:
175 return flavor_id
tierno72774862020-05-04 11:44:15 +0000176 raise vimconn.VimConnNotFoundException("flavor with ram={} cpu={} disk={} {} not found".format(
tierno0937f202020-04-20 08:54:21 +0000177 flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"],
178 "and extended" if flavor_dict.get("extended") else ""))
179
180 def new_tenant(self, tenant_name, tenant_description):
181 tenant_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +0000182 self.logger.debug("new tenant id={}, description={}".format(tenant_id, tenant_description))
tierno0937f202020-04-20 08:54:21 +0000183 tenant = {'name': tenant_name, 'description': tenant_description, 'id': tenant_id}
184 self.tenants[tenant_id] = tenant
185 return tenant_id
186
187 def delete_tenant(self, tenant_id):
188 if tenant_id not in self.tenants:
tierno72774862020-05-04 11:44:15 +0000189 raise vimconn.VimConnNotFoundException("tenant with id {} not found".format(tenant_id))
tierno0937f202020-04-20 08:54:21 +0000190 self.tenants.pop(tenant_id)
tierno274bfc72020-09-24 12:31:36 +0000191 self.logger.debug("delete tenant id={}".format(tenant_id))
192 return tenant_id
tierno0937f202020-04-20 08:54:21 +0000193
194 def get_tenant_list(self, filter_dict=None):
195 tenants = []
196 for tenant_id, tenant in self.tenants.items():
197 if filter_dict and filter_dict.get("name"):
198 if tenant["name"] != filter_dict.get("name"):
199 continue
200 if filter_dict and filter_dict.get("id"):
201 if tenant_id != filter_dict.get("id"):
202 continue
203 tenants.append(tenant)
204 return tenants
205
206 def new_image(self, image_dict):
207 image_id = str(uuid4())
tierno274bfc72020-09-24 12:31:36 +0000208 self.logger.debug("new image id={}, iamge_dict={}".format(image_id, image_dict))
tierno0937f202020-04-20 08:54:21 +0000209 image = deepcopy(image_dict)
210 image["id"] = image_id
211 if "name" not in image:
212 image["id"] = image_id
213 self.images[image_id] = image
214 return image_id
215
216 def delete_image(self, image_id):
217 if image_id not in self.images:
tierno72774862020-05-04 11:44:15 +0000218 raise vimconn.VimConnNotFoundException("image with id {} not found".format(image_id))
tierno274bfc72020-09-24 12:31:36 +0000219 self.logger.debug("delete image id={}".format(image_id))
tierno0937f202020-04-20 08:54:21 +0000220 self.images.pop(image_id)
tierno274bfc72020-09-24 12:31:36 +0000221 return image_id
tierno0937f202020-04-20 08:54:21 +0000222
223 def get_image_list(self, filter_dict=None):
224 images = []
225 for image_id, image in self.images.items():
226 if filter_dict and filter_dict.get("name"):
227 if image["name"] != filter_dict.get("name"):
228 continue
229 if filter_dict and filter_dict.get("checksum"):
230 if image["checksum"] != filter_dict.get("checksum"):
231 continue
232 if filter_dict and filter_dict.get("id"):
233 if image_id != filter_dict.get("id"):
234 continue
235 images.append(image)
236 return images
237
238 def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
tierno1ec592d2020-06-16 15:29:47 +0000239 availability_zone_index=None, availability_zone_list=None):
tierno0937f202020-04-20 08:54:21 +0000240 vm_id = str(uuid4())
241 interfaces = []
tierno274bfc72020-09-24 12:31:36 +0000242 self.logger.debug("new vm id={}, name={}, image_id={}, flavor_id={}, net_list={}, cloud_config={}".
243 format(vm_id, name, image_id, flavor_id, net_list, cloud_config))
tierno0937f202020-04-20 08:54:21 +0000244 for iface_index, iface in enumerate(net_list):
245 iface["vim_id"] = str(iface_index)
246 interface = {
tierno274bfc72020-09-24 12:31:36 +0000247 "ip_address": iface.get("ip_address") or self.config.get("vm_ip") or "192.168.4.2",
248 "mac_address": iface.get("mac_address") or self.config.get("vm_mac") or "00:11:22:33:44:55",
tierno0937f202020-04-20 08:54:21 +0000249 "vim_interface_id": str(iface_index),
250 "vim_net_id": iface["net_id"],
251 }
tierno70eeb182020-10-19 16:38:00 +0000252 if iface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH") and self.config.get("sdn-port-mapping"):
253 compute_index = randrange(len(self.config["sdn-port-mapping"]))
254 port_index = randrange(len(self.config["sdn-port-mapping"][compute_index]["ports"]))
255 interface["compute_node"] = self.config["sdn-port-mapping"][compute_index]["compute_node"]
256 interface["pci"] = self.config["sdn-port-mapping"][compute_index]["ports"][port_index]["pci"]
257
tierno0937f202020-04-20 08:54:21 +0000258 interfaces.append(interface)
259 vm = {
260 "id": vm_id,
261 "name": name,
262 "status": "ACTIVE",
263 "description": description,
264 "interfaces": interfaces,
265 "image_id": image_id,
266 "flavor_id": flavor_id,
267 }
268 if image_id not in self.images:
269 self.logger.error("vm create, image_id '{}' not found. Skip".format(image_id))
270 if flavor_id not in self.flavors:
271 self.logger.error("vm create flavor_id '{}' not found. Skip".format(flavor_id))
272 self.vms[vm_id] = vm
273 return vm_id, vm
274
275 def get_vminstance(self, vm_id):
276 if vm_id not in self.vms:
tierno72774862020-05-04 11:44:15 +0000277 raise vimconn.VimConnNotFoundException("vm with id {} not found".format(vm_id))
tierno0937f202020-04-20 08:54:21 +0000278 return self.vms[vm_id]
279
280 def delete_vminstance(self, vm_id, created_items=None):
281 if vm_id not in self.vms:
tierno72774862020-05-04 11:44:15 +0000282 raise vimconn.VimConnNotFoundException("vm with id {} not found".format(vm_id))
tierno0937f202020-04-20 08:54:21 +0000283 self.vms.pop(vm_id)
tierno274bfc72020-09-24 12:31:36 +0000284 self.logger.debug("delete vm id={}, created_items={}".format(vm_id, created_items))
285 return vm_id
tierno0937f202020-04-20 08:54:21 +0000286
287 def refresh_vms_status(self, vm_list):
288 vms = {}
289 for vm_id in vm_list:
290 if vm_id not in self.vms:
291 vm = {"status": "DELETED"}
292 else:
293 vm = deepcopy(self.vms[vm_id])
294 vm["vim_info"] = yaml.dump({"status": "ACTIVE", "name": vm["name"]},
tierno1ec592d2020-06-16 15:29:47 +0000295 default_flow_style=True, width=256)
tierno0937f202020-04-20 08:54:21 +0000296 vms[vm_id] = vm
297 return vms
298
299 def action_vminstance(self, vm_id, action_dict, created_items={}):
300 return None
301
302 def inject_user_key(self, ip_addr=None, user=None, key=None, ro_key=None, password=None):
303 if self.config.get("ssh_key"):
304 ro_key = self.config.get("ssh_key")
305 return super().inject_user_key(ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password)