X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_ro%2Fnfvo.py;h=f4a2d798bbd4b39bde3607368a6a3306f882302a;hb=b7ff355a95cf7ce07874aa5dc1d4267541277778;hp=7c5870ce7332ecea593d5748b40b483ec1256f8c;hpb=7f426e900d00a76c3d583839f299982bbaf4c317;p=osm%2FRO.git diff --git a/osm_ro/nfvo.py b/osm_ro/nfvo.py index 7c5870ce..f4a2d798 100644 --- a/osm_ro/nfvo.py +++ b/osm_ro/nfvo.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U. # This file is part of openmano # All Rights Reserved. # @@ -31,6 +31,7 @@ __date__ ="$16-sep-2014 22:05:01$" # import json import yaml import utils +from utils import deprecated import vim_thread from db_base import HTTP_Unauthorized, HTTP_Bad_Request, HTTP_Internal_Server_Error, HTTP_Not_Found,\ HTTP_Conflict, HTTP_Method_Not_Allowed @@ -52,7 +53,8 @@ from Crypto.PublicKey import RSA import osm_im.vnfd as vnfd_catalog import osm_im.nsd as nsd_catalog from pyangbind.lib.serialise import pybindJSONDecoder -from itertools import chain +from copy import deepcopy + global global_config global vimconn_imported @@ -197,7 +199,7 @@ def start_service(mydb): HTTP_Internal_Server_Error) thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['vim_tenant_id'], vim['vim_tenant_name'], vim['vim_tenant_id']) - new_thread = vim_thread.vim_thread(myvim, task_lock, thread_name, vim['datacenter_name'], + new_thread = vim_thread.vim_thread(task_lock, thread_name, vim['datacenter_name'], vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim) new_thread.start() vim_threads["running"][thread_id] = new_thread @@ -720,8 +722,8 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_ for index in range(0,len(devices_original)) : device=devices_original[index] if "image" not in device and "image name" not in device: - if 'size' in device: - disk_list.append({'size': device.get('size', default_volume_size)}) + # if 'size' in device: + disk_list.append({'size': device.get('size', default_volume_size), 'name': device.get('name')}) continue image_dict={} image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img") @@ -915,6 +917,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): "vnf_id": vnf_uuid, "uuid": net_uuid, "description": get_str(vld, "description", 255), + "osm_id": get_str(vld, "id", 255), "type": "bridge", # TODO adjust depending on connection point type } net_id2uuid[vld.get("id")] = net_uuid @@ -994,7 +997,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): # volumes devices = [] if vdu.get("volumes"): - for volume_key in sorted(vdu["volumes"]): + for volume_key in vdu["volumes"]: volume = vdu["volumes"][volume_key] if not image_present: # Convert the first volume to vnfc.image @@ -1007,7 +1010,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): db_vm["image_id"] = image_uuid else: # Add Openmano devices - device = {} + device = {"name": str(volume.get("name"))} device["type"] = str(volume.get("device-type")) if volume.get("size"): device["size"] = int(volume["size"]) @@ -1015,6 +1018,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): device["image name"] = str(volume["image"]) if volume.get("image-checksum"): device["image checksum"] = str(volume["image-checksum"]) + devices.append(device) # cloud-init @@ -1068,7 +1072,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): if iface.get("virtual-interface").get("type") == "OM-MGMT": db_interface["type"] = "mgmt" - elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000"): + elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"): db_interface["type"] = "bridge" db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12) elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"): @@ -1083,6 +1087,9 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vnfd_id, vdu_id, iface.get("virtual-interface").get("type")), HTTP_Bad_Request) + if iface.get("mgmt-interface"): + db_interface["type"] = "mgmt" + if iface.get("external-connection-point-ref"): try: cp = vnfd.get("connection-point")[iface.get("external-connection-point-ref")] @@ -1148,8 +1155,8 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): vnf=vnfd_id, vdu=vdu_id, iface=iface["name"], cp=iface.get("internal-connection-point-ref"), msg=str(e)), HTTP_Bad_Request) - if iface.get("position") is not None: - db_interface["created_at"] = int(iface.get("position")) - 1000 + if iface.get("position"): + db_interface["created_at"] = int(iface.get("position")) * 50 if iface.get("mac-address"): db_interface["mac"] = str(iface.get("mac-address")) db_interfaces.append(db_interface) @@ -1299,6 +1306,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor): raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request) +@deprecated("Use new_vnfd_v3") def new_vnf(mydb, tenant_id, vnf_descriptor): global global_config @@ -1436,6 +1444,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor): raise NfvoException(error_text, e.http_code) +@deprecated("Use new_vnfd_v3") def new_vnf_v02(mydb, tenant_id, vnf_descriptor): global global_config @@ -1736,6 +1745,7 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None): # return "delete_vnf. Undeleted: %s" %(undeletedItems) +@deprecated("Not used") def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None): result, vims = get_vim(mydb, nfvo_tenant_id, None, datacenter_name) if result < 0: @@ -1786,6 +1796,7 @@ def get_hosts(mydb, nfvo_tenant_id): raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e)), e.http_code) +@deprecated("Use new_nsd_v3") def new_scenario(mydb, tenant_id, topo): # result, vims = get_vim(mydb, tenant_id) @@ -2067,6 +2078,7 @@ def new_scenario(mydb, tenant_id, topo): return c +@deprecated("Use new_nsd_v3") def new_scenario_v02(mydb, tenant_id, scenario_dict, version): """ This creates a new scenario for version 0.2 and 0.3""" scenario = scenario_dict["scenario"] @@ -2291,6 +2303,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor): "scenario_id": scenario_uuid, # "type": #TODO "multipoint": not vld.get("type") == "ELINE", + "osm_id": get_str(vld, "id", 255), # "external": #TODO "description": get_str(vld, "description", 255), } @@ -2511,6 +2524,7 @@ def edit_scenario(mydb, tenant_id, scenario_id, data): return c +@deprecated("Use create_instance") def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instance_scenario_description, datacenter=None,vim_tenant=None, startvms=True): #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id" datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter, vim_tenant=vim_tenant) @@ -2867,13 +2881,13 @@ def get_datacenter_uuid(mydb, tenant_id, datacenter_id_name): " dt on td.datacenter_tenant_id=dt.uuid" else: from_ = 'datacenters as d' - vimaccounts = mydb.get_rows(FROM=from_, SELECT=("d.uuid as uuid",), WHERE=WHERE_dict ) + vimaccounts = mydb.get_rows(FROM=from_, SELECT=("d.uuid as uuid, d.name as name",), WHERE=WHERE_dict ) if len(vimaccounts) == 0: raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), HTTP_Not_Found) elif len(vimaccounts)>1: #print "nfvo.datacenter_action() error. Several datacenters found" raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict) - return vimaccounts[0]["uuid"] + return vimaccounts[0]["uuid"], vimaccounts[0]["name"] def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extra_filter): @@ -2967,25 +2981,42 @@ def create_instance(mydb, tenant_id, instance_dict): sce_net2instance = {} net2task_id = {'scenario': {}} + def ip_profile_IM2RO(ip_profile_im): + # translate from input format to database format + ip_profile_ro = {} + if 'subnet-address' in ip_profile_im: + ip_profile_ro['subnet_address'] = ip_profile_im['subnet-address'] + if 'ip-version' in ip_profile_im: + ip_profile_ro['ip_version'] = ip_profile_im['ip-version'] + if 'gateway-address' in ip_profile_im: + ip_profile_ro['gateway_address'] = ip_profile_im['gateway-address'] + if 'dns-address' in ip_profile_im: + ip_profile_ro['dns_address'] = ip_profile_im['dns-address'] + if isinstance(ip_profile_ro['dns_address'], (list, tuple)): + ip_profile_ro['dns_address'] = ";".join(ip_profile_ro['dns_address']) + if 'dhcp' in ip_profile_im: + ip_profile_ro['dhcp_start_address'] = ip_profile_im['dhcp'].get('start-address') + ip_profile_ro['dhcp_enabled'] = ip_profile_im['dhcp'].get('enabled', True) + ip_profile_ro['dhcp_count'] = ip_profile_im['dhcp'].get('count') + return ip_profile_ro + # logger.debug("Creating instance from scenario-dict:\n%s", # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)) try: # 0 check correct parameters for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems(): - found = False for scenario_net in scenarioDict['nets']: - if net_name == scenario_net["name"]: - found = True + if net_name == scenario_net.get("name") or net_name == scenario_net.get("osm_id") or net_name == scenario_net.get("uuid"): break - if not found: - raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name), + else: + raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name), HTTP_Bad_Request) if "sites" not in net_instance_desc: net_instance_desc["sites"] = [ {} ] site_without_datacenter_field = False for site in net_instance_desc["sites"]: if site.get("datacenter"): - site["datacenter"] = get_datacenter_uuid(mydb, tenant_id, site["datacenter"]) + site["datacenter"], _ = get_datacenter_uuid(mydb, tenant_id, site["datacenter"]) if site["datacenter"] not in myvims: # Add this datacenter to myvims d, v = get_datacenter_by_name_uuid(mydb, tenant_id, site["datacenter"]) @@ -3000,22 +3031,52 @@ def create_instance(mydb, tenant_id, instance_dict): site["datacenter"] = default_datacenter_id # change name to id for vnf_name, vnf_instance_desc in instance_dict.get("vnfs",{}).iteritems(): - found = False for scenario_vnf in scenarioDict['vnfs']: - if vnf_name == scenario_vnf['name'] or vnf_name == scenario_vnf['member_vnf_index']: - found = True + if vnf_name == scenario_vnf['member_vnf_index'] or vnf_name == scenario_vnf['uuid'] or vnf_name == scenario_vnf['name']: break - if not found: + else: raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name), HTTP_Bad_Request) if "datacenter" in vnf_instance_desc: # Add this datacenter to myvims - vnf_instance_desc["datacenter"] = get_datacenter_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"]) + vnf_instance_desc["datacenter"], _ = get_datacenter_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"]) if vnf_instance_desc["datacenter"] not in myvims: d, v = get_datacenter_by_name_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"]) myvims[d] = v myvim_threads_id[d], _ = get_vim_thread(mydb, tenant_id, vnf_instance_desc["datacenter"]) scenario_vnf["datacenter"] = vnf_instance_desc["datacenter"] + for net_id, net_instance_desc in vnf_instance_desc.get("networks", {}).iteritems(): + for scenario_net in scenario_vnf['nets']: + if net_id == scenario_net['osm_id'] or net_id == scenario_net['uuid'] or net_id == scenario_net["name"]: + break + else: + raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id), HTTP_Bad_Request) + if net_instance_desc.get("vim-network-name"): + scenario_net["vim-network-name"] = net_instance_desc["vim-network-name"] + if net_instance_desc.get("name"): + scenario_net["name"] = net_instance_desc["name"] + if 'ip-profile' in net_instance_desc: + ipprofile_db = ip_profile_IM2RO(net_instance_desc['ip-profile']) + if 'ip_profile' not in scenario_net: + scenario_net['ip_profile'] = ipprofile_db + else: + update(scenario_net['ip_profile'], ipprofile_db) + + for vdu_id, vdu_instance_desc in vnf_instance_desc.get("vdus", {}).iteritems(): + for scenario_vm in scenario_vnf['vms']: + if vdu_id == scenario_vm['osm_id'] or vdu_id == scenario_vm["name"]: + break + else: + raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id), HTTP_Bad_Request) + scenario_vm["instance_parameters"] = vdu_instance_desc + for iface_id, iface_instance_desc in vdu_instance_desc.get("interfaces", {}).iteritems(): + for scenario_interface in scenario_vm['interfaces']: + if iface_id == scenario_interface['internal_name'] or iface_id == scenario_interface["external_name"]: + scenario_interface.update(iface_instance_desc) + break + else: + raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id), HTTP_Bad_Request) + # 0.1 parse cloud-config parameters cloud_config = unify_cloud_config(instance_dict.get("cloud-config"), scenarioDict.get("cloud-config")) @@ -3026,19 +3087,7 @@ def create_instance(mydb, tenant_id, instance_dict): for scenario_net in scenarioDict['nets']: if net_name == scenario_net["name"]: if 'ip-profile' in net_instance_desc: - # translate from input format to database format - ipprofile_in = net_instance_desc['ip-profile'] - ipprofile_db = {} - ipprofile_db['subnet_address'] = ipprofile_in.get('subnet-address') - ipprofile_db['ip_version'] = ipprofile_in.get('ip-version', 'IPv4') - ipprofile_db['gateway_address'] = ipprofile_in.get('gateway-address') - ipprofile_db['dns_address'] = ipprofile_in.get('dns-address') - if isinstance(ipprofile_db['dns_address'], (list, tuple)): - ipprofile_db['dns_address'] = ";".join(ipprofile_db['dns_address']) - if 'dhcp' in ipprofile_in: - ipprofile_db['dhcp_start_address'] = ipprofile_in['dhcp'].get('start-address') - ipprofile_db['dhcp_enabled'] = ipprofile_in['dhcp'].get('enabled', True) - ipprofile_db['dhcp_count'] = ipprofile_in['dhcp'].get('count' ) + ipprofile_db = ip_profile_IM2RO(net_instance_desc['ip-profile']) if 'ip_profile' not in scenario_net: scenario_net['ip_profile'] = ipprofile_db else: @@ -3059,21 +3108,41 @@ def create_instance(mydb, tenant_id, instance_dict): number_mgmt_networks = 0 db_instance_nets = [] for sce_net in scenarioDict['nets']: - descriptor_net = instance_dict.get("networks", {}).get(sce_net["name"], {}) + # get involved datacenters where this network need to be created + involved_datacenters = [] + for sce_vnf in scenarioDict.get("vnfs"): + vnf_datacenter = sce_vnf.get("datacenter", default_datacenter_id) + if vnf_datacenter in involved_datacenters: + continue + if sce_vnf.get("interfaces"): + for sce_vnf_ifaces in sce_vnf["interfaces"]: + if sce_vnf_ifaces.get("sce_net_id") == sce_net["uuid"]: + involved_datacenters.append(vnf_datacenter) + break + + descriptor_net = {} + if instance_dict.get("networks") and instance_dict["networks"].get(sce_net["name"]): + descriptor_net = instance_dict["networks"][sce_net["name"]] net_name = descriptor_net.get("vim-network-name") sce_net2instance[sce_net['uuid']] = {} net2task_id['scenario'][sce_net['uuid']] = {} - sites = descriptor_net.get("sites", [ {} ]) - for site in sites: - if site.get("datacenter"): - vim = myvims[ site["datacenter"] ] - datacenter_id = site["datacenter"] - myvim_thread_id = myvim_threads_id[ site["datacenter"] ] - else: - vim = myvims[ default_datacenter_id ] - datacenter_id = default_datacenter_id - myvim_thread_id = myvim_threads_id[default_datacenter_id] + if sce_net["external"]: + number_mgmt_networks += 1 + + for datacenter_id in involved_datacenters: + netmap_use = None + netmap_create = None + if descriptor_net.get("sites"): + for site in descriptor_net["sites"]: + if site.get("datacenter") == datacenter_id: + netmap_use = site.get("netmap-use") + netmap_create = site.get("netmap-create") + break + + vim = myvims[datacenter_id] + myvim_thread_id = myvim_threads_id[datacenter_id] + net_type = sce_net['type'] lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True @@ -3081,31 +3150,29 @@ def create_instance(mydb, tenant_id, instance_dict): if sce_net["external"]: net_name = sce_net["name"] else: - net_name = "{}.{}".format(instance_name, sce_net["name"]) + net_name = "{}-{}".format(instance_name, sce_net["name"]) net_name = net_name[:255] # limit length - if sce_net["external"]: - number_mgmt_networks += 1 - if "netmap-use" in site or "netmap-create" in site: + if netmap_use or netmap_create: create_network = False lookfor_network = False - if "netmap-use" in site: + if netmap_use: lookfor_network = True - if utils.check_valid_uuid(site["netmap-use"]): - lookfor_filter["id"] = site["netmap-use"] + if utils.check_valid_uuid(netmap_use): + lookfor_filter["id"] = netmap_use else: - lookfor_filter["name"] = site["netmap-use"] - if "netmap-create" in site: + lookfor_filter["name"] = netmap_use + if netmap_create: create_network = True net_vim_name = net_name - if site["netmap-create"]: - net_vim_name = site["netmap-create"] + if isinstance(netmap_create, str): + net_vim_name = netmap_create elif sce_net.get("vim_network_name"): create_network = False lookfor_network = True lookfor_filter["name"] = sce_net.get("vim_network_name") elif sce_net["external"]: - if sce_net['vim_id'] != None: + if sce_net['vim_id'] is not None: # there is a netmap at datacenter_nets database # TODO REVISE!!!! create_network = False lookfor_network = True @@ -3194,6 +3261,7 @@ def create_instance(mydb, tenant_id, instance_dict): "myvims": myvims, "cloud_config": cloud_config, "RO_pub_key": tenant[0].get('RO_pub_key'), + "instance_parameters": instance_dict, } vnf_params_out = { "task_index": task_index, @@ -3207,8 +3275,8 @@ def create_instance(mydb, tenant_id, instance_dict): "net2task_id": net2task_id, "sce_net2instance": sce_net2instance, } - sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name']) - for sce_vnf in sce_vnf_list: + # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name']) + for sce_vnf in scenarioDict['vnfs']: # sce_vnf_list: instantiate_vnf(mydb, sce_vnf, vnf_params, vnf_params_out, rollbackList) task_index = vnf_params_out["task_index"] uuid_list = vnf_params_out["uuid_list"] @@ -3444,7 +3512,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): # net_name = descriptor_net.get("name") net_name = None if not net_name: - net_name = "{}.{}".format(instance_name, net["name"]) + net_name = "{}-{}".format(instance_name, net["name"]) net_name = net_name[:255] # limit length net_type = net['type'] @@ -3469,16 +3537,23 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): } db_instance_nets.append(db_net) + if net.get("vim-network-name"): + lookfor_filter = {"name": net["vim-network-name"]} + task_action = "FIND" + task_extra = {"params": (lookfor_filter,)} + else: + task_action = "CREATE" + task_extra = {"params": (net_name, net_type, net.get('ip_profile', None))} + db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, "datacenter_vim_id": myvim_thread_id, "status": "SCHEDULED", - "action": "CREATE", + "action": task_action, "item": "instance_nets", "item_id": net_uuid, - "extra": yaml.safe_dump({"params": (net_name, net_type, net.get('ip_profile', None))}, - default_flow_style=True, width=256) + "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256) } task_index += 1 db_vim_actions.append(db_vim_action) @@ -3545,6 +3620,8 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): myVMDict['description'] = myVMDict['name'][0:99] # if not startvms: # myVMDict['start'] = "no" + if vm.get("instance_parameters") and vm["instance_parameters"].get("name"): + myVMDict['name'] = vm["instance_parameters"].get("name") myVMDict['name'] = myVMDict['name'][0:255] # limit name length # create image at vim in case it not exist image_uuid = vm['image_id'] @@ -3576,6 +3653,10 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): extended_flavor_dict_yaml = yaml.load(extended_info) if 'disks' in extended_flavor_dict_yaml: myVMDict['disks'] = extended_flavor_dict_yaml['disks'] + if vm.get("instance_parameters") and vm["instance_parameters"].get("devices"): + for disk in myVMDict['disks']: + if disk.get("name") in vm["instance_parameters"]["devices"]: + disk.update(vm["instance_parameters"]["devices"][disk.get("name")]) vm['vim_flavor_id'] = flavor_id myVMDict['imageRef'] = vm['vim_image_id'] @@ -3584,6 +3665,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): myVMDict['networks'] = [] task_depends_on = [] # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true + is_management_vm = False db_vm_ifaces = [] for iface in vm['interfaces']: netDict = {} @@ -3616,12 +3698,17 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): Try to delete and create the scenarios and VNFs again", HTTP_Conflict) else: raise NfvoException(e_text, HTTP_Internal_Server_Error) - if netDict["use"] == "mgmt" or netDict["use"] == "bridge": + if netDict["use"] == "mgmt": + is_management_vm = True + netDict["type"] = "virtual" + if netDict["use"] == "bridge": netDict["type"] = "virtual" if iface.get("vpci"): netDict['vpci'] = iface['vpci'] if iface.get("mac"): netDict['mac_address'] = iface['mac'] + if iface.get("mac_address"): + netDict['mac_address'] = iface['mac_address'] if iface.get("ip_address"): netDict['ip_address'] = iface['ip_address'] if iface.get("port-security") is not None: @@ -3668,9 +3755,16 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): # We add the RO key to cloud_config if vnf will need ssh access cloud_config_vm = cloud_config - if ssh_access and ssh_access['required'] and ssh_access['default-user'] and tenant[0].get('RO_pub_key'): - RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]} - cloud_config_vm = unify_cloud_config(cloud_config_vm, RO_key) + if is_management_vm and params["instance_parameters"].get("mgmt_keys"): + cloud_config_vm = unify_cloud_config({"key-pairs": params["instance_parameters"]["mgmt_keys"]}, + cloud_config_vm) + + if vm.get("instance_parameters") and vm["instance_parameters"].get("mgmt_keys"): + cloud_config_vm = unify_cloud_config({"key-pairs": vm["instance_parameters"]["mgmt_keys"]}, + cloud_config_vm) + # if ssh_access and ssh_access['required'] and ssh_access['default-user'] and tenant[0].get('RO_pub_key'): + # RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]} + # cloud_config_vm = unify_cloud_config(cloud_config_vm, RO_key) if vm.get("boot_data"): cloud_config_vm = unify_cloud_config(vm["boot_data"], cloud_config_vm) @@ -3679,10 +3773,8 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): else: av_index = None for vm_index in range(0, vm.get('count', 1)): - vm_index_name = "" - if vm.get('count', 1) > 1: - vm_index_name += "." + chr(97 + vm_index) - task_params = (myVMDict['name'] + vm_index_name, myVMDict['description'], myVMDict.get('start', None), + vm_name = myVMDict['name'] + "-" + str(vm_index+1) + task_params = (vm_name, myVMDict['description'], myVMDict.get('start', None), myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'], cloud_config_vm, myVMDict['disks'], av_index, vnf_availability_zones) # put interface uuid back to scenario[vnfs][vms[[interfaces] @@ -3699,6 +3791,7 @@ def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList): 'instance_vnf_id': vnf_uuid, # TODO delete "vim_vm_id": vm_id, "vm_id": vm["uuid"], + "vim_name": vm_name, # "status": } db_instance_vms.append(db_vm) @@ -3770,68 +3863,21 @@ def delete_instance(mydb, tenant_id, instance_id): # "number_tasks": 0 # filled bellow } - # 2.1 deleting VMs - # vm_fail_list=[] - for sce_vnf in instanceDict['vnfs']: - datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) - vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None - if datacenter_key not in myvims: - try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) - except NfvoException as e: - logger.error(str(e)) - myvim_thread = None - myvim_threads[datacenter_key] = myvim_thread - vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"], - datacenter_tenant_id=sce_vnf["datacenter_tenant_id"]) - if len(vims) == 0: - logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], - sce_vnf["datacenter_tenant_id"])) - myvims[datacenter_key] = None - else: - myvims[datacenter_key] = vims.values()[0] - myvim = myvims[datacenter_key] - myvim_thread = myvim_threads[datacenter_key] - for vm in sce_vnf['vms']: - if not myvim: - error_msg += "\n VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"]) - continue - db_vim_action = { - "instance_action_id": instance_action_id, - "task_index": task_index, - "datacenter_vim_id": sce_vnf["datacenter_tenant_id"], - "action": "DELETE", - "status": "SCHEDULED", - "item": "instance_vms", - "item_id": vm["uuid"], - "extra": yaml.safe_dump({"params": vm["interfaces"]}, - default_flow_style=True, width=256) - } - db_vim_actions.append(db_vim_action) - for interface in vm["interfaces"]: - if not interface.get("instance_net_id"): - continue - if interface["instance_net_id"] not in net2vm_dependencies: - net2vm_dependencies[interface["instance_net_id"]] = [] - net2vm_dependencies[interface["instance_net_id"]].append(task_index) - task_index += 1 - - # 2.2 deleting NETS - # net_fail_list=[] - for net in instanceDict['nets']: - vimthread_affected[net["datacenter_tenant_id"]] = None - datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"]) + # 2.1 deleting VNFFGs + for sfp in instanceDict.get('sfps', ()): + vimthread_affected[sfp["datacenter_tenant_id"]] = None + datacenter_key = (sfp["datacenter_id"], sfp["datacenter_tenant_id"]) if datacenter_key not in myvims: try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) + _, myvim_thread = get_vim_thread(mydb, tenant_id, sfp["datacenter_id"], sfp["datacenter_tenant_id"]) except NfvoException as e: logger.error(str(e)) myvim_thread = None myvim_threads[datacenter_key] = myvim_thread - vims = get_vim(mydb, tenant_id, datacenter_id=net["datacenter_id"], - datacenter_tenant_id=net["datacenter_tenant_id"]) + vims = get_vim(mydb, tenant_id, datacenter_id=sfp["datacenter_id"], + datacenter_tenant_id=sfp["datacenter_tenant_id"]) if len(vims) == 0: - logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])) + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp["datacenter_id"], sfp["datacenter_tenant_id"])) myvims[datacenter_key] = None else: myvims[datacenter_key] = vims.values()[0] @@ -3839,40 +3885,37 @@ def delete_instance(mydb, tenant_id, instance_id): myvim_thread = myvim_threads[datacenter_key] if not myvim: - error_msg += "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"]) + error_msg += "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp['vim_sfp_id'], sfp["datacenter_id"]) continue - extra = {"params": (net['vim_net_id'], net['sdn_net_id'])} - if net2vm_dependencies.get(net["uuid"]): - extra["depends_on"] = net2vm_dependencies[net["uuid"]] + extra = {"params": (sfp['vim_sfp_id'])} db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, - "datacenter_vim_id": net["datacenter_tenant_id"], + "datacenter_vim_id": sfp["datacenter_tenant_id"], "action": "DELETE", "status": "SCHEDULED", - "item": "instance_nets", - "item_id": net["uuid"], + "item": "instance_sfps", + "item_id": sfp["uuid"], "extra": yaml.safe_dump(extra, default_flow_style=True, width=256) } task_index += 1 db_vim_actions.append(db_vim_action) - # 2.3 deleting VNFFGs - - for sfp in instanceDict.get('sfps', ()): - vimthread_affected[sfp["datacenter_tenant_id"]] = None - datacenter_key = (sfp["datacenter_id"], sfp["datacenter_tenant_id"]) + for classification in instanceDict['classifications']: + vimthread_affected[classification["datacenter_tenant_id"]] = None + datacenter_key = (classification["datacenter_id"], classification["datacenter_tenant_id"]) if datacenter_key not in myvims: try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, sfp["datacenter_id"], sfp["datacenter_tenant_id"]) + _, myvim_thread = get_vim_thread(mydb, tenant_id, classification["datacenter_id"], classification["datacenter_tenant_id"]) except NfvoException as e: logger.error(str(e)) myvim_thread = None myvim_threads[datacenter_key] = myvim_thread - vims = get_vim(mydb, tenant_id, datacenter_id=sfp["datacenter_id"], - datacenter_tenant_id=sfp["datacenter_tenant_id"]) + vims = get_vim(mydb, tenant_id, datacenter_id=classification["datacenter_id"], + datacenter_tenant_id=classification["datacenter_tenant_id"]) if len(vims) == 0: - logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp["datacenter_id"], sfp["datacenter_tenant_id"])) + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification["datacenter_id"], + classification["datacenter_tenant_id"])) myvims[datacenter_key] = None else: myvims[datacenter_key] = vims.values()[0] @@ -3880,17 +3923,19 @@ def delete_instance(mydb, tenant_id, instance_id): myvim_thread = myvim_threads[datacenter_key] if not myvim: - error_msg += "\n vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp['vim_sfp_id'], sfp["datacenter_id"]) + error_msg += "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification['vim_classification_id'], + classification["datacenter_id"]) continue - extra = {"params": (sfp['vim_sfp_id'])} + depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"] + extra = {"params": (classification['vim_classification_id']), "depends_on": depends_on} db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, - "datacenter_vim_id": sfp["datacenter_tenant_id"], + "datacenter_vim_id": classification["datacenter_tenant_id"], "action": "DELETE", "status": "SCHEDULED", - "item": "instance_sfps", - "item_id": sfp["uuid"], + "item": "instance_classifications", + "item_id": classification["uuid"], "extra": yaml.safe_dump(extra, default_flow_style=True, width=256) } task_index += 1 @@ -3901,7 +3946,7 @@ def delete_instance(mydb, tenant_id, instance_id): datacenter_key = (sf["datacenter_id"], sf["datacenter_tenant_id"]) if datacenter_key not in myvims: try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, sf["datacenter_id"], sf["datacenter_tenant_id"]) + _, myvim_thread = get_vim_thread(mydb, tenant_id, sf["datacenter_id"], sf["datacenter_tenant_id"]) except NfvoException as e: logger.error(str(e)) myvim_thread = None @@ -3919,7 +3964,8 @@ def delete_instance(mydb, tenant_id, instance_id): if not myvim: error_msg += "\n vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf['vim_sf_id'], sf["datacenter_id"]) continue - extra = {"params": (sf['vim_sf_id'])} + depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"] + extra = {"params": (sf['vim_sf_id']), "depends_on": depends_on} db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, @@ -3938,7 +3984,7 @@ def delete_instance(mydb, tenant_id, instance_id): datacenter_key = (sfi["datacenter_id"], sfi["datacenter_tenant_id"]) if datacenter_key not in myvims: try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, sfi["datacenter_id"], sfi["datacenter_tenant_id"]) + _, myvim_thread = get_vim_thread(mydb, tenant_id, sfi["datacenter_id"], sfi["datacenter_tenant_id"]) except NfvoException as e: logger.error(str(e)) myvim_thread = None @@ -3956,7 +4002,8 @@ def delete_instance(mydb, tenant_id, instance_id): if not myvim: error_msg += "\n vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi['vim_sfi_id'], sfi["datacenter_id"]) continue - extra = {"params": (sfi['vim_sfi_id'])} + depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfs"] + extra = {"params": (sfi['vim_sfi_id']), "depends_on": depends_on} db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, @@ -3970,20 +4017,70 @@ def delete_instance(mydb, tenant_id, instance_id): task_index += 1 db_vim_actions.append(db_vim_action) - for classification in instanceDict['classifications']: - vimthread_affected[classification["datacenter_tenant_id"]] = None - datacenter_key = (classification["datacenter_id"], classification["datacenter_tenant_id"]) + # 2.2 deleting VMs + # vm_fail_list=[] + for sce_vnf in instanceDict['vnfs']: + datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) + vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None if datacenter_key not in myvims: try: - _,myvim_thread = get_vim_thread(mydb, tenant_id, classification["datacenter_id"], classification["datacenter_tenant_id"]) + _, myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) except NfvoException as e: logger.error(str(e)) myvim_thread = None myvim_threads[datacenter_key] = myvim_thread - vims = get_vim(mydb, tenant_id, datacenter_id=classification["datacenter_id"], - datacenter_tenant_id=classification["datacenter_tenant_id"]) + vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"], + datacenter_tenant_id=sce_vnf["datacenter_tenant_id"]) if len(vims) == 0: - logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification["datacenter_id"], classification["datacenter_tenant_id"])) + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], + sce_vnf["datacenter_tenant_id"])) + myvims[datacenter_key] = None + else: + myvims[datacenter_key] = vims.values()[0] + myvim = myvims[datacenter_key] + myvim_thread = myvim_threads[datacenter_key] + + for vm in sce_vnf['vms']: + if not myvim: + error_msg += "\n VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"]) + continue + sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"] + db_vim_action = { + "instance_action_id": instance_action_id, + "task_index": task_index, + "datacenter_vim_id": sce_vnf["datacenter_tenant_id"], + "action": "DELETE", + "status": "SCHEDULED", + "item": "instance_vms", + "item_id": vm["uuid"], + "extra": yaml.safe_dump({"params": vm["interfaces"], "depends_on": sfi_dependencies}, + default_flow_style=True, width=256) + } + db_vim_actions.append(db_vim_action) + for interface in vm["interfaces"]: + if not interface.get("instance_net_id"): + continue + if interface["instance_net_id"] not in net2vm_dependencies: + net2vm_dependencies[interface["instance_net_id"]] = [] + net2vm_dependencies[interface["instance_net_id"]].append(task_index) + task_index += 1 + + # 2.3 deleting NETS + # net_fail_list=[] + for net in instanceDict['nets']: + vimthread_affected[net["datacenter_tenant_id"]] = None + datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"]) + if datacenter_key not in myvims: + try: + _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]) + except NfvoException as e: + logger.error(str(e)) + myvim_thread = None + myvim_threads[datacenter_key] = myvim_thread + vims = get_vim(mydb, tenant_id, datacenter_id=net["datacenter_id"], + datacenter_tenant_id=net["datacenter_tenant_id"]) + if len(vims) == 0: + logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])) myvims[datacenter_key] = None else: myvims[datacenter_key] = vims.values()[0] @@ -3991,17 +4088,25 @@ def delete_instance(mydb, tenant_id, instance_id): myvim_thread = myvim_threads[datacenter_key] if not myvim: - error_msg += "\n vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification['vim_classification_id'], classification["datacenter_id"]) + error_msg += "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"]) continue - extra = {"params": (classification['vim_classification_id'])} + extra = {"params": (net['vim_net_id'], net['sdn_net_id'])} + if net2vm_dependencies.get(net["uuid"]): + extra["depends_on"] = net2vm_dependencies[net["uuid"]] + sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"] + if len(sfi_dependencies) > 0: + if "depends_on" in extra: + extra["depends_on"] += sfi_dependencies + else: + extra["depends_on"] = sfi_dependencies db_vim_action = { "instance_action_id": instance_action_id, "task_index": task_index, - "datacenter_vim_id": classification["datacenter_tenant_id"], + "datacenter_vim_id": net["datacenter_tenant_id"], "action": "DELETE", "status": "SCHEDULED", - "item": "instance_classifications", - "item_id": classification["uuid"], + "item": "instance_nets", + "item_id": net["uuid"], "extra": yaml.safe_dump(extra, default_flow_style=True, width=256) } task_index += 1 @@ -4046,6 +4151,7 @@ def get_instance_id(mydb, tenant_id, instance_id): } return instance_dict +@deprecated("Instance is automatically refreshed by vim_threads") def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenant=None): '''Refreshes a scenario instance. It modifies instanceDict''' '''Returns: @@ -4220,21 +4326,201 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict): if len(vims) == 0: raise NfvoException("datacenter '{}' not found".format(str(instanceDict['datacenter_id'])), HTTP_Not_Found) myvim = vims.values()[0] + vm_result = {} + vm_error = 0 + vm_ok = 0 - if action_dict.get("create-vdu"): - for vdu in action_dict["create-vdu"]: + myvim_threads_id = {} + if action_dict.get("vdu-scaling"): + db_instance_vms = [] + db_vim_actions = [] + db_instance_interfaces = [] + instance_action_id = get_task_id() + db_instance_action = { + "uuid": instance_action_id, # same uuid for the instance and the action on create + "tenant_id": nfvo_tenant, + "instance_id": instance_id, + "description": "SCALE", + } + vm_result["instance_action_id"] = instance_action_id + vm_result["created"] = [] + vm_result["deleted"] = [] + task_index = 0 + for vdu in action_dict["vdu-scaling"]: vdu_id = vdu.get("vdu-id") + osm_vdu_id = vdu.get("osm_vdu_id") + member_vnf_index = vdu.get("member-vnf-index") vdu_count = vdu.get("count", 1) - # get from database TODO - # insert tasks TODO - pass + if vdu_id: + target_vms = mydb.get_rows( + FROM="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid", + WHERE={"vms.uuid": vdu_id}, + ORDER_BY="vms.created_at" + ) + if not target_vms: + raise NfvoException("Cannot find the vdu with id {}".format(vdu_id), HTTP_Not_Found) + else: + if not osm_vdu_id and not member_vnf_index: + raise NfvoException("Invalid imput vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'") + target_vms = mydb.get_rows( + # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"), + FROM="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\ + " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\ + " join vms on ivms.vm_id=vms.uuid", + WHERE={"vms.osm_id": osm_vdu_id, "svnfs.member_vnf_index": member_vnf_index}, + ORDER_BY="ivms.created_at" + ) + if not target_vms: + raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id, member_vnf_index), HTTP_Not_Found) + vdu_id = target_vms[-1]["uuid"] + target_vm = target_vms[-1] + datacenter = target_vm["datacenter_id"] + myvim_threads_id[datacenter], _ = get_vim_thread(mydb, nfvo_tenant, datacenter) + + if vdu["type"] == "delete": + for index in range(0, vdu_count): + target_vm = target_vms[-1-index] + vdu_id = target_vm["uuid"] + # look for nm + vm_interfaces = None + for sce_vnf in instanceDict['vnfs']: + for vm in sce_vnf['vms']: + if vm["uuid"] == vdu_id: + vm_interfaces = vm["interfaces"] + break + + db_vim_action = { + "instance_action_id": instance_action_id, + "task_index": task_index, + "datacenter_vim_id": target_vm["datacenter_tenant_id"], + "action": "DELETE", + "status": "SCHEDULED", + "item": "instance_vms", + "item_id": vdu_id, + "extra": yaml.safe_dump({"params": vm_interfaces}, + default_flow_style=True, width=256) + } + task_index += 1 + db_vim_actions.append(db_vim_action) + vm_result["deleted"].append(vdu_id) + # delete from database + db_instance_vms.append({"TO-DELETE": vdu_id}) + + else: # vdu["type"] == "create": + iface2iface = {} + where = {"item": "instance_vms", "item_id": target_vm["uuid"], "action": "CREATE"} + + vim_action_to_clone = mydb.get_rows(FROM="vim_actions", WHERE=where) + if not vim_action_to_clone: + raise NfvoException("Cannot find the vim_action at database with {}".format(where), HTTP_Internal_Server_Error) + vim_action_to_clone = vim_action_to_clone[0] + extra = yaml.safe_load(vim_action_to_clone["extra"]) + + # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y + # TODO do the same for flavor and image when available + task_depends_on = [] + task_params = extra["params"] + task_params_networks = deepcopy(task_params[5]) + for iface in task_params[5]: + if iface["net_id"].startswith("TASK-"): + if "." not in iface["net_id"]: + task_depends_on.append("{}.{}".format(vim_action_to_clone["instance_action_id"], + iface["net_id"][5:])) + iface["net_id"] = "TASK-{}.{}".format(vim_action_to_clone["instance_action_id"], + iface["net_id"][5:]) + else: + task_depends_on.append(iface["net_id"][5:]) + if "mac_address" in iface: + del iface["mac_address"] + + vm_ifaces_to_clone = mydb.get_rows(FROM="instance_interfaces", WHERE={"instance_vm_id": target_vm["uuid"]}) + for index in range(0, vdu_count): + vm_uuid = str(uuid4()) + vm_name = target_vm.get('vim_name') + try: + suffix = vm_name.rfind("-") + vm_name = vm_name[:suffix+1] + str(index + 1 + int(vm_name[suffix+1:])) + except Exception: + pass + db_instance_vm = { + "uuid": vm_uuid, + 'instance_vnf_id': target_vm['instance_vnf_id'], + 'vm_id': target_vm['vm_id'], + 'vim_name': vm_name + } + db_instance_vms.append(db_instance_vm) + + for vm_iface in vm_ifaces_to_clone: + iface_uuid = str(uuid4()) + iface2iface[vm_iface["uuid"]] = iface_uuid + db_vm_iface = { + "uuid": iface_uuid, + 'instance_vm_id': vm_uuid, + "instance_net_id": vm_iface["instance_net_id"], + 'interface_id': vm_iface['interface_id'], + 'type': vm_iface['type'], + 'floating_ip': vm_iface['floating_ip'], + 'port_security': vm_iface['port_security'] + } + db_instance_interfaces.append(db_vm_iface) + task_params_copy = deepcopy(task_params) + for iface in task_params_copy[5]: + iface["uuid"] = iface2iface[iface["uuid"]] + # increment ip_address + if "ip_address" in iface: + ip = iface.get("ip_address") + i = ip.rfind(".") + if i > 0: + try: + i += 1 + ip = ip[i:] + str(int(ip[:i]) + 1) + iface["ip_address"] = ip + except: + iface["ip_address"] = None + if vm_name: + task_params_copy[0] = vm_name + db_vim_action = { + "instance_action_id": instance_action_id, + "task_index": task_index, + "datacenter_vim_id": vim_action_to_clone["datacenter_vim_id"], + "action": "CREATE", + "status": "SCHEDULED", + "item": "instance_vms", + "item_id": vm_uuid, + # ALF + # ALF + # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd. + # ALF + # ALF + "extra": yaml.safe_dump({"params": task_params_copy, "depends_on": task_depends_on}, default_flow_style=True, width=256) + } + task_index += 1 + db_vim_actions.append(db_vim_action) + vm_result["created"].append(vm_uuid) + + db_instance_action["number_tasks"] = task_index + db_tables = [ + {"instance_vms": db_instance_vms}, + {"instance_interfaces": db_instance_interfaces}, + {"instance_actions": db_instance_action}, + # TODO revise sfps + # {"instance_sfis": db_instance_sfis}, + # {"instance_sfs": db_instance_sfs}, + # {"instance_classifications": db_instance_classifications}, + # {"instance_sfps": db_instance_sfps}, + {"vim_actions": db_vim_actions} + ] + logger.debug("create_vdu done DB tables: %s", + yaml.safe_dump(db_tables, indent=4, default_flow_style=False)) + mydb.new_rows(db_tables, []) + for myvim_thread in myvim_threads_id.values(): + vim_threads["running"][myvim_thread].insert_task(db_vim_actions) + + return vm_result input_vnfs = action_dict.pop("vnfs", []) input_vms = action_dict.pop("vms", []) action_over_all = True if not input_vnfs and not input_vms else False - vm_result = {} - vm_error = 0 - vm_ok = 0 for sce_vnf in instanceDict['vnfs']: for vm in sce_vnf['vms']: if not action_over_all and sce_vnf['uuid'] not in input_vnfs and sce_vnf['vnf_name'] not in input_vnfs and \ @@ -4328,7 +4614,7 @@ def instance_action_get(mydb, nfvo_tenant, instance_id, action_id): raise NfvoException("Not found any action with this criteria", HTTP_Not_Found) vim_actions = mydb.get_rows(FROM="vim_actions", WHERE={"instance_action_id": action_id}) rows[0]["vim_actions"] = vim_actions - return {"ations": rows} + return {"actions": rows} def create_or_use_console_proxy_thread(console_server, console_port): @@ -4421,7 +4707,7 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor): # edit data datacenter_id = datacenter['uuid'] - where={'uuid': datacenter['uuid']} + where = {'uuid': datacenter['uuid']} remove_port_mapping = False new_sdn_port_mapping = None if "config" in datacenter_descriptor: @@ -4431,10 +4717,10 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor): if "sdn-port-mapping" in new_config_dict: remove_port_mapping = True new_sdn_port_mapping = new_config_dict.pop("sdn-port-mapping") - #delete null fields - to_delete=[] + # delete null fields + to_delete = [] for k in new_config_dict: - if new_config_dict[k] == None: + if new_config_dict[k] is None: to_delete.append(k) if k == 'sdn-controller': remove_port_mapping = True @@ -4444,7 +4730,7 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor): config_text = '{}' config_dict = yaml.load(config_text) config_dict.update(new_config_dict) - #delete null fields + # delete null fields for k in to_delete: del config_dict[k] except Exception as e: @@ -4457,14 +4743,16 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor): try: datacenter_sdn_port_mapping_delete(mydb, None, datacenter_id) except ovimException as e: - logger.error("Error deleting datacenter-port-mapping " + str(e)) + raise NfvoException("Error deleting datacenter-port-mapping " + str(e), HTTP_Conflict) mydb.update_rows('datacenters', datacenter_descriptor, where) if new_sdn_port_mapping: try: datacenter_sdn_port_mapping_set(mydb, None, datacenter_id, new_sdn_port_mapping) except ovimException as e: - logger.error("Error adding datacenter-port-mapping " + str(e)) + # Rollback + mydb.update_rows('datacenters', datacenter, where) + raise NfvoException("Error adding datacenter-port-mapping " + str(e), HTTP_Conflict) return datacenter_id @@ -4475,33 +4763,38 @@ def delete_datacenter(mydb, datacenter): try: datacenter_sdn_port_mapping_delete(mydb, None, datacenter_dict['uuid']) except ovimException as e: - logger.error("Error deleting datacenter-port-mapping " + str(e)) + raise NfvoException("Error deleting datacenter-port-mapping " + str(e)) return datacenter_dict['uuid'] + " " + datacenter_dict['name'] -def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=None, vim_tenant_name=None, vim_username=None, vim_password=None, config=None): +def create_vim_account(mydb, nfvo_tenant, datacenter_id, name=None, vim_id=None, vim_tenant=None, vim_tenant_name=None, + vim_username=None, vim_password=None, config=None): # get datacenter info try: - datacenter_id = get_datacenter_uuid(mydb, None, datacenter) + if not datacenter_id: + if not vim_id: + raise NfvoException("You must provide 'vim_id", http_code=HTTP_Bad_Request) + datacenter_id = vim_id + datacenter_id, datacenter_name = get_datacenter_uuid(mydb, None, datacenter_id) - create_vim_tenant = True if not vim_tenant_id and not vim_tenant_name else False + create_vim_tenant = True if not vim_tenant and not vim_tenant_name else False # get nfvo_tenant info tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant) if vim_tenant_name==None: vim_tenant_name=tenant_dict['name'] - #check that this association does not exist before tenants_datacenter_dict={"nfvo_tenant_id":tenant_dict['uuid'], "datacenter_id":datacenter_id } - tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict) - if len(tenants_datacenters)>0: - raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), HTTP_Conflict) + # #check that this association does not exist before + # tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict) + # if len(tenants_datacenters)>0: + # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), HTTP_Conflict) vim_tenant_id_exist_atdb=False if not create_vim_tenant: where_={"datacenter_id": datacenter_id} - if vim_tenant_id!=None: - where_["vim_tenant_id"] = vim_tenant_id + if vim_tenant!=None: + where_["vim_tenant_id"] = vim_tenant if vim_tenant_name!=None: where_["vim_tenant_name"] = vim_tenant_name #check if vim_tenant_id is already at database @@ -4513,25 +4806,29 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id= else: #result=0 datacenter_tenants_dict = {} #insert at table datacenter_tenants - else: #if vim_tenant_id==None: + else: #if vim_tenant==None: #create tenant at VIM if not provided try: _, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter, vim_user=vim_username, vim_passwd=vim_password) datacenter_name = myvim["name"] - vim_tenant_id = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name) + vim_tenant = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name) except vimconn.vimconnException as e: - raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id, str(e)), HTTP_Internal_Server_Error) + raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant, str(e)), HTTP_Internal_Server_Error) datacenter_tenants_dict = {} datacenter_tenants_dict["created"]="true" #fill datacenter_tenants table if not vim_tenant_id_exist_atdb: - datacenter_tenants_dict["vim_tenant_id"] = vim_tenant_id + datacenter_tenants_dict["vim_tenant_id"] = vim_tenant datacenter_tenants_dict["vim_tenant_name"] = vim_tenant_name datacenter_tenants_dict["user"] = vim_username datacenter_tenants_dict["passwd"] = vim_password datacenter_tenants_dict["datacenter_id"] = datacenter_id + if name: + datacenter_tenants_dict["name"] = name + else: + datacenter_tenants_dict["name"] = datacenter_name if config: datacenter_tenants_dict["config"] = yaml.safe_dump(config, default_flow_style=True, width=256) id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, add_uuid=True, confidential_data=True) @@ -4541,59 +4838,59 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id= datacenter_tenant_id = datacenter_tenants_dict["uuid"] tenants_datacenter_dict["datacenter_tenant_id"] = datacenter_tenant_id mydb.new_row('tenants_datacenters', tenants_datacenter_dict) + # create thread - datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_dict['uuid'], datacenter_id) # reload data - datacenter_name = myvim["name"] thread_name = get_non_used_vim_name(datacenter_name, datacenter_id, tenant_dict['name'], tenant_dict['uuid']) - new_thread = vim_thread.vim_thread(myvim, task_lock, thread_name, datacenter_name, datacenter_tenant_id, + new_thread = vim_thread.vim_thread(task_lock, thread_name, datacenter_name, datacenter_tenant_id, db=db, db_lock=db_lock, ovim=ovim) new_thread.start() thread_id = datacenter_tenants_dict["uuid"] vim_threads["running"][thread_id] = new_thread - return datacenter_id + return thread_id except vimconn.vimconnException as e: raise NfvoException(str(e), HTTP_Bad_Request) -def edit_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=None, vim_tenant_name=None, - vim_username=None, vim_password=None, config=None): - #Obtain the data of this datacenter_tenant_id - vim_data = mydb.get_rows( - SELECT=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user", - "datacenter_tenants.passwd", "datacenter_tenants.config"), - FROM="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id", - WHERE={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant, - "tenants_datacenters.datacenter_id": datacenter_id}) - - logger.debug(str(vim_data)) - if len(vim_data) < 1: - raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id, nfvo_tenant), HTTP_Conflict) - - v = vim_data[0] - if v['config']: - v['config'] = yaml.load(v['config']) - - if vim_tenant_id: - v['vim_tenant_id'] = vim_tenant_id +def edit_vim_account(mydb, nfvo_tenant, datacenter_tenant_id, datacenter_id=None, name=None, vim_tenant=None, + vim_tenant_name=None, vim_username=None, vim_password=None, config=None): + + # get vim_account; check is valid for this tenant + from_ = "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id" + where_ = {"td.nfvo_tenant_id": nfvo_tenant} + if datacenter_tenant_id: + where_["dt.uuid"] = datacenter_tenant_id + if datacenter_id: + where_["dt.datacenter_id"] = datacenter_id + vim_accounts = mydb.get_rows(SELECT="dt.uuid as uuid, config", FROM=from_, WHERE=where_) + if not vim_accounts: + raise NfvoException("vim_account not found for this tenant", http_code=HTTP_Not_Found) + elif len(vim_accounts) > 1: + raise NfvoException("found more than one vim_account for this tenant", http_code=HTTP_Conflict) + datacenter_tenant_id = vim_accounts[0]["uuid"] + original_config = vim_accounts[0]["config"] + + update_ = {} + if config: + original_config_dict = yaml.load(original_config) + original_config_dict.update(config) + update["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256) + if name: + update_['name'] = name + if vim_tenant: + update_['vim_tenant_id'] = vim_tenant if vim_tenant_name: - v['vim_tenant_name'] = vim_tenant_name + update_['vim_tenant_name'] = vim_tenant_name if vim_username: - v['user'] = vim_username + update_['user'] = vim_username if vim_password: - v['passwd'] = vim_password - if config: - if not v['config']: - v['config'] = {} - v['config'].update(config) - - logger.debug(str(v)) - deassociate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=v['vim_tenant_id']) - associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=v['vim_tenant_id'], vim_tenant_name=v['vim_tenant_name'], - vim_username=v['user'], vim_password=v['passwd'], config=v['config']) + update_['passwd'] = vim_password + if update_: + mydb.update_rows("datacenter_tenants", UPDATE=update_, WHERE={"uuid": datacenter_tenant_id}) - return datacenter_id + vim_threads["running"][datacenter_tenant_id].insert_task("reload") + return datacenter_tenant_id -def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=None): +def delete_vim_account(mydb, tenant_id, vim_account_id, datacenter=None): #get nfvo_tenant info if not tenant_id or tenant_id=="any": tenant_uuid = None @@ -4601,9 +4898,13 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id= tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id) tenant_uuid = tenant_dict['uuid'] - datacenter_id = get_datacenter_uuid(mydb, tenant_uuid, datacenter) #check that this association exist before - tenants_datacenter_dict={"datacenter_id": datacenter_id } + tenants_datacenter_dict = {} + if datacenter: + datacenter_id, _ = get_datacenter_uuid(mydb, tenant_uuid, datacenter) + tenants_datacenter_dict["datacenter_id"] = datacenter_id + elif vim_account_id: + tenants_datacenter_dict["datacenter_tenant_id"] = vim_account_id if tenant_uuid: tenants_datacenter_dict["nfvo_tenant_id"] = tenant_uuid tenant_datacenter_list = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)