31892399229f10e1303cd130882f26809d53e02f
[osm/RO.git] / RO-plugin / osm_ro_plugin / vim_dummy.py
1 # -*- 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 """
20 Implements a Dummy vim plugin.
21 """
22
23 import yaml
24 from osm_ro_plugin import vimconn
25 from uuid import uuid4
26 from copy import deepcopy
27 import logging
28
29 __author__ = "Alfonso Tierno"
30 __date__ = "2020-04-20"
31
32
33 class VimDummyConnector(vimconn.VimConnector):
34 """Dummy vim connector that does nothing
35 Provide config with:
36 vm_ip: ip address to provide at VM creation. For some tests must be a valid reachable VM
37 ssh_key: private ssh key to use for inserting an authorized ssh key
38 """
39 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None,
40 config={}, persistent_info={}):
41 super().__init__(uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
42 config, persistent_info)
43 self.logger = logging.getLogger('openmano.vim.dummy')
44 if log_level:
45 self.logger.setLevel(getattr(logging, log_level))
46 self.nets = {
47 "mgmt": {
48 "id": "mgmt",
49 "name": "mgmt",
50 "status": "ACTIVE",
51 "vim_info": '{status: ACTIVE}'
52 }
53 }
54 self.vms = {}
55 self.flavors = {}
56 self.tenants = {}
57 # preload some images
58 self.images = {
59 "90681b39-dc09-49b7-ba2e-2c00c6b33b76": {
60 "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76",
61 "name": "cirros034",
62 "checksum": "ee1eca47dc88f4879d8a229cc70a07c6"
63 },
64 "83a39656-65db-47dc-af03-b55289115a53": {
65 "id": "",
66 "name": "cirros040",
67 "checksum": "443b7623e27ecf03dc9e01ee93f67afe"
68 },
69 "208314f2-8eb6-4101-965d-fe2ffbaedf3c": {
70 "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c",
71 "name": "ubuntu18.04",
72 "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95"
73 },
74 "c03321f8-4b6e-4045-a309-1b3878bd32c1": {
75 "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1",
76 "name": "ubuntu16.04",
77 "checksum": "8f08442faebad2d4a99fedb22fca11b5"
78 },
79 "4f6399a2-3554-457e-916e-ada01f8b950b": {
80 "id": "4f6399a2-3554-457e-916e-ada01f8b950b",
81 "name": "ubuntu1604",
82 "checksum": "8f08442faebad2d4a99fedb22fca11b5"
83 },
84 "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": {
85 "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3",
86 "name": "hackfest3-mgmt",
87 "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a"
88 },
89 "f8818a03-f099-4c18-b1c7-26b1324203c1": {
90 "id": "f8818a03-f099-4c18-b1c7-26b1324203c1",
91 "name": "hackfest-pktgen",
92 "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1"
93 },
94 }
95
96 def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None):
97 net_id = str(uuid4())
98 self.logger.debug("new network id={}, name={}, net_type={}, ip_profile={}, provider_network_profile={}".
99 format(net_id, net_name, net_type, ip_profile, provider_network_profile))
100 net = {
101 "id": net_id,
102 "name": net_name,
103 "net_type": net_type,
104 "status": "ACTIVE",
105 }
106 self.nets[net_id] = net
107 return net_id, net
108
109 def get_network_list(self, filter_dict=None):
110 nets = []
111 for net_id, net in self.nets.items():
112 if filter_dict and filter_dict.get("name"):
113 if net["name"] != filter_dict.get("name"):
114 continue
115 if filter_dict and filter_dict.get("id"):
116 if net_id != filter_dict.get("id"):
117 continue
118 nets.append(net)
119 return nets
120
121 def get_network(self, net_id):
122 if net_id not in self.nets:
123 raise vimconn.VimConnNotFoundException("network with id {} not found".format(net_id))
124 return self.nets[net_id]
125
126 def delete_network(self, net_id, created_items=None):
127 if net_id not in self.nets:
128 raise vimconn.VimConnNotFoundException("network with id {} not found".format(net_id))
129 self.logger.debug("delete network id={}, created_items={}".format(net_id, created_items))
130 self.nets.pop(net_id)
131 return net_id
132
133 def refresh_nets_status(self, net_list):
134 nets = {}
135 for net_id in net_list:
136 if net_id not in self.nets:
137 net = {"status": "DELETED"}
138 else:
139 net = self.nets[net_id].copy()
140 net["vim_info"] = yaml.dump({"status": "ACTIVE", "name": net["name"]},
141 default_flow_style=True, width=256)
142 nets[net_id] = net
143
144 return nets
145
146 def get_flavor(self, flavor_id):
147 if flavor_id not in self.flavors:
148 raise vimconn.VimConnNotFoundException("flavor with id {} not found".format(flavor_id))
149 return self.flavors[flavor_id]
150
151 def new_flavor(self, flavor_data):
152 flavor_id = str(uuid4())
153 self.logger.debug("new flavor id={}, flavor_data={}".format(flavor_id, flavor_data))
154 flavor = deepcopy(flavor_data)
155 flavor["id"] = flavor_id
156 if "name" not in flavor:
157 flavor["name"] = flavor_id
158 self.flavors[flavor_id] = flavor
159 return flavor_id
160
161 def delete_flavor(self, flavor_id):
162 if flavor_id not in self.flavors:
163 raise vimconn.VimConnNotFoundException("flavor with id {} not found".format(flavor_id))
164 self.logger.debug("delete flavor id={}".format(flavor_id))
165 self.flavors.pop(flavor_id)
166 return flavor_id
167
168 def get_flavor_id_from_data(self, flavor_dict):
169 for flavor_id, flavor_data in self.flavors.items():
170 for k in ("ram", "vcpus", "disk", "extended"):
171 if flavor_data.get(k) != flavor_dict.get(k):
172 break
173 else:
174 return flavor_id
175 raise vimconn.VimConnNotFoundException("flavor with ram={} cpu={} disk={} {} not found".format(
176 flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"],
177 "and extended" if flavor_dict.get("extended") else ""))
178
179 def new_tenant(self, tenant_name, tenant_description):
180 tenant_id = str(uuid4())
181 self.logger.debug("new tenant id={}, description={}".format(tenant_id, tenant_description))
182 tenant = {'name': tenant_name, 'description': tenant_description, 'id': tenant_id}
183 self.tenants[tenant_id] = tenant
184 return tenant_id
185
186 def delete_tenant(self, tenant_id):
187 if tenant_id not in self.tenants:
188 raise vimconn.VimConnNotFoundException("tenant with id {} not found".format(tenant_id))
189 self.tenants.pop(tenant_id)
190 self.logger.debug("delete tenant id={}".format(tenant_id))
191 return tenant_id
192
193 def get_tenant_list(self, filter_dict=None):
194 tenants = []
195 for tenant_id, tenant in self.tenants.items():
196 if filter_dict and filter_dict.get("name"):
197 if tenant["name"] != filter_dict.get("name"):
198 continue
199 if filter_dict and filter_dict.get("id"):
200 if tenant_id != filter_dict.get("id"):
201 continue
202 tenants.append(tenant)
203 return tenants
204
205 def new_image(self, image_dict):
206 image_id = str(uuid4())
207 self.logger.debug("new image id={}, iamge_dict={}".format(image_id, image_dict))
208 image = deepcopy(image_dict)
209 image["id"] = image_id
210 if "name" not in image:
211 image["id"] = image_id
212 self.images[image_id] = image
213 return image_id
214
215 def delete_image(self, image_id):
216 if image_id not in self.images:
217 raise vimconn.VimConnNotFoundException("image with id {} not found".format(image_id))
218 self.logger.debug("delete image id={}".format(image_id))
219 self.images.pop(image_id)
220 return image_id
221
222 def get_image_list(self, filter_dict=None):
223 images = []
224 for image_id, image in self.images.items():
225 if filter_dict and filter_dict.get("name"):
226 if image["name"] != filter_dict.get("name"):
227 continue
228 if filter_dict and filter_dict.get("checksum"):
229 if image["checksum"] != filter_dict.get("checksum"):
230 continue
231 if filter_dict and filter_dict.get("id"):
232 if image_id != filter_dict.get("id"):
233 continue
234 images.append(image)
235 return images
236
237 def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
238 availability_zone_index=None, availability_zone_list=None):
239 vm_id = str(uuid4())
240 interfaces = []
241 self.logger.debug("new vm id={}, name={}, image_id={}, flavor_id={}, net_list={}, cloud_config={}".
242 format(vm_id, name, image_id, flavor_id, net_list, cloud_config))
243 for iface_index, iface in enumerate(net_list):
244 iface["vim_id"] = str(iface_index)
245 interface = {
246 "ip_address": iface.get("ip_address") or self.config.get("vm_ip") or "192.168.4.2",
247 "mac_address": iface.get("mac_address") or self.config.get("vm_mac") or "00:11:22:33:44:55",
248 "vim_interface_id": str(iface_index),
249 "vim_net_id": iface["net_id"],
250 }
251 interfaces.append(interface)
252 vm = {
253 "id": vm_id,
254 "name": name,
255 "status": "ACTIVE",
256 "description": description,
257 "interfaces": interfaces,
258 "image_id": image_id,
259 "flavor_id": flavor_id,
260 }
261 if image_id not in self.images:
262 self.logger.error("vm create, image_id '{}' not found. Skip".format(image_id))
263 if flavor_id not in self.flavors:
264 self.logger.error("vm create flavor_id '{}' not found. Skip".format(flavor_id))
265 self.vms[vm_id] = vm
266 return vm_id, vm
267
268 def get_vminstance(self, vm_id):
269 if vm_id not in self.vms:
270 raise vimconn.VimConnNotFoundException("vm with id {} not found".format(vm_id))
271 return self.vms[vm_id]
272
273 def delete_vminstance(self, vm_id, created_items=None):
274 if vm_id not in self.vms:
275 raise vimconn.VimConnNotFoundException("vm with id {} not found".format(vm_id))
276 self.vms.pop(vm_id)
277 self.logger.debug("delete vm id={}, created_items={}".format(vm_id, created_items))
278 return vm_id
279
280 def refresh_vms_status(self, vm_list):
281 vms = {}
282 for vm_id in vm_list:
283 if vm_id not in self.vms:
284 vm = {"status": "DELETED"}
285 else:
286 vm = deepcopy(self.vms[vm_id])
287 vm["vim_info"] = yaml.dump({"status": "ACTIVE", "name": vm["name"]},
288 default_flow_style=True, width=256)
289 vms[vm_id] = vm
290 return vms
291
292 def action_vminstance(self, vm_id, action_dict, created_items={}):
293 return None
294
295 def inject_user_key(self, ip_addr=None, user=None, key=None, ro_key=None, password=None):
296 if self.config.get("ssh_key"):
297 ro_key = self.config.get("ssh_key")
298 return super().inject_user_key(ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password)