From 0937f203806a304b6bed8705c0c17f58de8dc844 Mon Sep 17 00:00:00 2001 From: tierno Date: Mon, 20 Apr 2020 08:54:21 +0000 Subject: [PATCH] add vim dummy plugin Change-Id: I218ff0684a6b2e7fbdb1a9976b493814b141e776 Signed-off-by: tierno --- RO/osm_ro/nfvo.py | 10 +- RO/osm_ro/vim_dummy.py | 281 +++++++++++++++++++++++++++++++++++++++++ RO/osm_ro/vimconn.py | 2 +- 3 files changed, 285 insertions(+), 8 deletions(-) create mode 100644 RO/osm_ro/vim_dummy.py diff --git a/RO/osm_ro/nfvo.py b/RO/osm_ro/nfvo.py index 2efd6104..30aae222 100644 --- a/RO/osm_ro/nfvo.py +++ b/RO/osm_ro/nfvo.py @@ -36,7 +36,7 @@ from osm_ro import utils from osm_ro.utils import deprecated from osm_ro.vim_thread import vim_thread import osm_ro.console_proxy_thread as cli -from osm_ro import vimconn +from osm_ro import vimconn, vim_dummy import logging import collections import math @@ -46,13 +46,7 @@ from osm_ro.db_base import db_base_Exception from osm_ro import nfvo_db from threading import Lock import time as t -# TODO py3 BEGIN from osm_ro.sdn import Sdn, SdnException as ovimException -# from lib_osm_openvim.ovim import ovimException -# from unittest.mock import MagicMock -# class ovimException(Exception): -# pass -# TODO py3 END from Crypto.PublicKey import RSA @@ -198,6 +192,8 @@ def start_service(mydb, persistence=None, wim=None): worker_id = get_process_id() if "rosdn_dummy" not in plugins: plugins["rosdn_dummy"] = DummyConnector + if "rovim_dummy" not in plugins: + plugins["rovim_dummy"] = vim_dummy # starts ovim library ovim = Sdn(db, plugins) diff --git a/RO/osm_ro/vim_dummy.py b/RO/osm_ro/vim_dummy.py new file mode 100644 index 00000000..9636377c --- /dev/null +++ b/RO/osm_ro/vim_dummy.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2020 Telefonica Investigacion y Desarrollo, S.A.U. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +## + +""" +Implements a Dummy vim plugin. +""" + +import yaml +from osm_ro import vimconn +from uuid import uuid4 +from copy import deepcopy + +__author__ = "Alfonso Tierno" +__date__ = "2020-04-20" + + +class vimconnector(vimconn.vimconnector): + """Dummy vim connector that does nothing + Provide config with: + vm_ip: ip address to provide at VM creation. For some tests must be a valid reachable VM + ssh_key: private ssh key to use for inserting an authorized ssh key + """ + def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, + config={}, persistent_info={}): + super().__init__(uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level, + config, persistent_info) + self.nets = { + "mgmt": { + "id": "mgmt", + "name": "mgmt", + "status": "ACTIVE", + "vim_info": '{status: ACTIVE}' + } + } + self.vms = {} + self.flavors = {} + self.tenants = {} + # preload some images + self.images = { + "90681b39-dc09-49b7-ba2e-2c00c6b33b76": { + "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76", + "name": "cirros034", + "checksum": "ee1eca47dc88f4879d8a229cc70a07c6" + }, + "83a39656-65db-47dc-af03-b55289115a53": { + "id": "", + "name": "cirros040", + "checksum": "443b7623e27ecf03dc9e01ee93f67afe" + }, + "208314f2-8eb6-4101-965d-fe2ffbaedf3c": { + "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c", + "name": "ubuntu18.04", + "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95" + }, + "c03321f8-4b6e-4045-a309-1b3878bd32c1": { + "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1", + "name": "ubuntu16.04", + "checksum": "8f08442faebad2d4a99fedb22fca11b5" + }, + "4f6399a2-3554-457e-916e-ada01f8b950b": { + "id": "4f6399a2-3554-457e-916e-ada01f8b950b", + "name": "ubuntu1604", + "checksum": "8f08442faebad2d4a99fedb22fca11b5" + }, + "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": { + "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3", + "name": "hackfest3-mgmt", + "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a" + }, + "f8818a03-f099-4c18-b1c7-26b1324203c1": { + "id": "f8818a03-f099-4c18-b1c7-26b1324203c1", + "name": "hackfest-pktgen", + "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1" + }, + } + + def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None): + net_id = str(uuid4()) + net = { + "id": net_id, + "name": net_name, + "net_type": net_type, + "status": "ACTIVE", + } + self.nets[net_id] = net + return net_id, net + + def get_network_list(self, filter_dict=None): + nets = [] + for net_id, net in self.nets.items(): + if filter_dict and filter_dict.get("name"): + if net["name"] != filter_dict.get("name"): + continue + if filter_dict and filter_dict.get("id"): + if net_id != filter_dict.get("id"): + continue + nets.append(net) + return nets + + def get_network(self, net_id): + if net_id not in self.nets: + raise vimconn.vimconnNotFoundException("network with id {} not found".format(net_id)) + return self.nets[net_id] + + def delete_network(self, net_id, created_items=None): + if net_id not in self.nets: + raise vimconn.vimconnNotFoundException("network with id {} not found".format(net_id)) + return net_id + self.nets.pop(net_id) + + def refresh_nets_status(self, net_list): + nets = {} + for net_id in net_list: + if net_id not in self.nets: + net = {"status": "DELETED"} + else: + net = self.nets[net_id].copy() + net["vim_info"] = yaml.dump({"status": "ACTIVE", "name": net["name"]}, + default_flow_style=True, width=256) + nets[net_id] = net + + return nets + + def get_flavor(self, flavor_id): + if flavor_id not in self.flavors: + raise vimconn.vimconnNotFoundException("flavor with id {} not found".format(flavor_id)) + return self.flavors[flavor_id] + + def new_flavor(self, flavor_data): + flavor_id = str(uuid4()) + flavor = deepcopy(flavor_data) + flavor["id"] = flavor_id + if "name" not in flavor: + flavor["name"] = flavor_id + self.flavors[flavor_id] = flavor + return flavor_id + + def delete_flavor(self, flavor_id): + if flavor_id not in self.flavors: + raise vimconn.vimconnNotFoundException("flavor with id {} not found".format(flavor_id)) + return flavor_id + self.flavors.pop(flavor_id) + + def get_flavor_id_from_data(self, flavor_dict): + for flavor_id, flavor_data in self.flavors.items(): + for k in ("ram", "vcpus", "disk", "extended"): + if flavor_data.get(k) != flavor_dict.get(k): + break + else: + return flavor_id + raise vimconn.vimconnNotFoundException("flavor with ram={} cpu={} disk={} {} not found".format( + flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"], + "and extended" if flavor_dict.get("extended") else "")) + + def new_tenant(self, tenant_name, tenant_description): + tenant_id = str(uuid4()) + tenant = {'name': tenant_name, 'description': tenant_description, 'id': tenant_id} + self.tenants[tenant_id] = tenant + return tenant_id + + def delete_tenant(self, tenant_id): + if tenant_id not in self.tenants: + raise vimconn.vimconnNotFoundException("tenant with id {} not found".format(tenant_id)) + return tenant_id + self.tenants.pop(tenant_id) + + def get_tenant_list(self, filter_dict=None): + tenants = [] + for tenant_id, tenant in self.tenants.items(): + if filter_dict and filter_dict.get("name"): + if tenant["name"] != filter_dict.get("name"): + continue + if filter_dict and filter_dict.get("id"): + if tenant_id != filter_dict.get("id"): + continue + tenants.append(tenant) + return tenants + + def new_image(self, image_dict): + image_id = str(uuid4()) + image = deepcopy(image_dict) + image["id"] = image_id + if "name" not in image: + image["id"] = image_id + self.images[image_id] = image + return image_id + + def delete_image(self, image_id): + if image_id not in self.images: + raise vimconn.vimconnNotFoundException("image with id {} not found".format(image_id)) + return image_id + self.images.pop(image_id) + + def get_image_list(self, filter_dict=None): + images = [] + for image_id, image in self.images.items(): + if filter_dict and filter_dict.get("name"): + if image["name"] != filter_dict.get("name"): + continue + if filter_dict and filter_dict.get("checksum"): + if image["checksum"] != filter_dict.get("checksum"): + continue + if filter_dict and filter_dict.get("id"): + if image_id != filter_dict.get("id"): + continue + images.append(image) + return images + + def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None, + availability_zone_index=None, availability_zone_list=None): + vm_id = str(uuid4()) + interfaces = [] + for iface_index, iface in enumerate(net_list): + iface["vim_id"] = str(iface_index) + interface = { + "ip_address": self.config.get("vm_ip") or "192.168.4.2", + "vim_interface_id": str(iface_index), + "vim_net_id": iface["net_id"], + } + interfaces.append(interface) + vm = { + "id": vm_id, + "name": name, + "status": "ACTIVE", + "description": description, + "interfaces": interfaces, + "image_id": image_id, + "flavor_id": flavor_id, + } + if image_id not in self.images: + self.logger.error("vm create, image_id '{}' not found. Skip".format(image_id)) + if flavor_id not in self.flavors: + self.logger.error("vm create flavor_id '{}' not found. Skip".format(flavor_id)) + self.vms[vm_id] = vm + return vm_id, vm + + def get_vminstance(self, vm_id): + if vm_id not in self.vms: + raise vimconn.vimconnNotFoundException("vm with id {} not found".format(vm_id)) + return self.vms[vm_id] + + def delete_vminstance(self, vm_id, created_items=None): + if vm_id not in self.vms: + raise vimconn.vimconnNotFoundException("vm with id {} not found".format(vm_id)) + return vm_id + self.vms.pop(vm_id) + + def refresh_vms_status(self, vm_list): + vms = {} + for vm_id in vm_list: + if vm_id not in self.vms: + vm = {"status": "DELETED"} + else: + vm = deepcopy(self.vms[vm_id]) + vm["vim_info"] = yaml.dump({"status": "ACTIVE", "name": vm["name"]}, + default_flow_style=True, width=256) + vms[vm_id] = vm + return vms + + def action_vminstance(self, vm_id, action_dict, created_items={}): + return None + + def inject_user_key(self, ip_addr=None, user=None, key=None, ro_key=None, password=None): + if self.config.get("ssh_key"): + ro_key = self.config.get("ssh_key") + return super().inject_user_key(ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password) diff --git a/RO/osm_ro/vimconn.py b/RO/osm_ro/vimconn.py index 4b78e2a7..2cef7efd 100644 --- a/RO/osm_ro/vimconn.py +++ b/RO/osm_ro/vimconn.py @@ -106,7 +106,7 @@ class vimconnector(): and all these privated methods """ def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, - config={}, persitent_info={}): + config={}, persistent_info={}): """ Constructor of VIM. Raise an exception is some needed parameter is missing, but it must not do any connectivity checking against the VIM -- 2.17.1