X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FRO.git;a=blobdiff_plain;f=RO-plugin%2Fosm_ro_plugin%2Fvim_dummy.py;h=fe3a8115399fffb019ba90fe00698549676d59ed;hp=8154304de25fbe1d1be0c4bbd29160bf9604a21d;hb=23f50011d5be26c8aa16c54984c21f551c612b5e;hpb=7277486065c905f91477bb064da86855a8fa269a diff --git a/RO-plugin/osm_ro_plugin/vim_dummy.py b/RO-plugin/osm_ro_plugin/vim_dummy.py index 8154304d..fe3a8115 100644 --- a/RO-plugin/osm_ro_plugin/vim_dummy.py +++ b/RO-plugin/osm_ro_plugin/vim_dummy.py @@ -24,9 +24,11 @@ import yaml from osm_ro_plugin import vimconn from uuid import uuid4 from copy import deepcopy +import logging +from random import randrange __author__ = "Alfonso Tierno" -__date__ = "2020-04-20" +__date__ = "2020-04-20" class VimDummyConnector(vimconn.VimConnector): @@ -35,16 +37,45 @@ class VimDummyConnector(vimconn.VimConnector): 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) + + 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.logger = logging.getLogger("ro.vim.dummy") + + if log_level: + self.logger.setLevel(getattr(logging, log_level)) + self.nets = { "mgmt": { "id": "mgmt", "name": "mgmt", "status": "ACTIVE", - "vim_info": '{status: ACTIVE}' + "vim_info": "{status: ACTIVE}", } } self.vms = {} @@ -55,42 +86,54 @@ class VimDummyConnector(vimconn.VimConnector): "90681b39-dc09-49b7-ba2e-2c00c6b33b76": { "id": "90681b39-dc09-49b7-ba2e-2c00c6b33b76", "name": "cirros034", - "checksum": "ee1eca47dc88f4879d8a229cc70a07c6" + "checksum": "ee1eca47dc88f4879d8a229cc70a07c6", }, "83a39656-65db-47dc-af03-b55289115a53": { "id": "", "name": "cirros040", - "checksum": "443b7623e27ecf03dc9e01ee93f67afe" + "checksum": "443b7623e27ecf03dc9e01ee93f67afe", }, "208314f2-8eb6-4101-965d-fe2ffbaedf3c": { "id": "208314f2-8eb6-4101-965d-fe2ffbaedf3c", "name": "ubuntu18.04", - "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95" + "checksum": "b6fc7b9b91bca32e989e1edbcdeecb95", }, "c03321f8-4b6e-4045-a309-1b3878bd32c1": { "id": "c03321f8-4b6e-4045-a309-1b3878bd32c1", "name": "ubuntu16.04", - "checksum": "8f08442faebad2d4a99fedb22fca11b5" + "checksum": "8f08442faebad2d4a99fedb22fca11b5", }, "4f6399a2-3554-457e-916e-ada01f8b950b": { "id": "4f6399a2-3554-457e-916e-ada01f8b950b", "name": "ubuntu1604", - "checksum": "8f08442faebad2d4a99fedb22fca11b5" + "checksum": "8f08442faebad2d4a99fedb22fca11b5", }, "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3": { "id": "59ac0b79-5c7d-4e83-b517-4c6c6a8ac1d3", "name": "hackfest3-mgmt", - "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a" + "checksum": "acec1e5d5ad7be9be7e6342a16bcf66a", }, "f8818a03-f099-4c18-b1c7-26b1324203c1": { "id": "f8818a03-f099-4c18-b1c7-26b1324203c1", "name": "hackfest-pktgen", - "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1" + "checksum": "f8818a03-f099-4c18-b1c7-26b1324203c1", }, } - def new_network(self, net_name, net_type, ip_profile=None, shared=False, provider_network_profile=None): + def new_network( + self, + net_name, + net_type, + ip_profile=None, + shared=False, + provider_network_profile=None, + ): net_id = str(uuid4()) + self.logger.debug( + "new network id={}, name={}, net_type={}, ip_profile={}, provider_network_profile={}".format( + net_id, net_name, net_type, ip_profile, provider_network_profile + ) + ) net = { "id": net_id, "name": net_name, @@ -98,64 +141,103 @@ class VimDummyConnector(vimconn.VimConnector): "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) + + # if no network is returned and search by name create a new one + if not nets and filter_dict and filter_dict.get("name"): + net_id, net = self.new_network(filter_dict.get("name"), "mgmt") 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)) + 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 + raise vimconn.VimConnNotFoundException( + "network with id {} not found".format(net_id) + ) + + self.logger.debug( + "delete network id={}, created_items={}".format(net_id, created_items) + ) self.nets.pop(net_id) + return 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) + 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)) + 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()) + self.logger.debug( + "new flavor id={}, flavor_data={}".format(flavor_id, flavor_data) + ) 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 + raise vimconn.VimConnNotFoundException( + "flavor with id {} not found".format(flavor_id) + ) + + self.logger.debug("delete flavor id={}".format(flavor_id)) self.flavors.pop(flavor_id) + return 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"): @@ -163,76 +245,150 @@ class VimDummyConnector(vimconn.VimConnector): 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 "")) + + 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.logger.debug( + "new tenant id={}, description={}".format(tenant_id, tenant_description) + ) + 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 + raise vimconn.VimConnNotFoundException( + "tenant with id {} not found".format(tenant_id) + ) + self.tenants.pop(tenant_id) + self.logger.debug("delete tenant id={}".format(tenant_id)) + + return 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()) + self.logger.debug("new image id={}, iamge_dict={}".format(image_id, image_dict)) 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 + raise vimconn.VimConnNotFoundException( + "image with id {} not found".format(image_id) + ) + + self.logger.debug("delete image id={}".format(image_id)) self.images.pop(image_id) + return 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): + 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 = [] + self.logger.debug( + "new vm id={}, name={}, image_id={}, flavor_id={}, net_list={}, cloud_config={}".format( + vm_id, name, image_id, flavor_id, net_list, cloud_config + ) + ) + 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", + "ip_address": iface.get("ip_address") + or self.config.get("vm_ip") + or "192.168.4.2", + "mac_address": iface.get("mac_address") + or self.config.get("vm_mac") + or "00:11:22:33:44:55", "vim_interface_id": str(iface_index), "vim_net_id": iface["net_id"], } + + if iface.get("type") in ("SR-IOV", "PCI-PASSTHROUGH") and self.config.get( + "sdn-port-mapping" + ): + compute_index = randrange(len(self.config["sdn-port-mapping"])) + port_index = randrange( + len(self.config["sdn-port-mapping"][compute_index]["ports"]) + ) + interface["compute_node"] = self.config["sdn-port-mapping"][ + compute_index + ]["compute_node"] + interface["pci"] = self.config["sdn-port-mapping"][compute_index][ + "ports" + ][port_index]["pci"] + interfaces.append(interface) + vm = { "id": vm_id, "name": name, @@ -242,40 +398,69 @@ class VimDummyConnector(vimconn.VimConnector): "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)) + 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.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)) + 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 + raise vimconn.VimConnNotFoundException( + "vm with id {} not found".format(vm_id) + ) + self.vms.pop(vm_id) + self.logger.debug( + "delete vm id={}, created_items={}".format(vm_id, created_items) + ) + + return 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) + 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): + 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) + + return super().inject_user_key( + ip_addr=ip_addr, user=user, key=key, ro_key=ro_key, password=password + )