+def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
+ default_datacenter_id = params["default_datacenter_id"]
+ myvim_threads_id = params["myvim_threads_id"]
+ instance_uuid = params["instance_uuid"]
+ instance_name = params["instance_name"]
+ instance_action_id = params["instance_action_id"]
+ myvims = params["myvims"]
+ cloud_config = params["cloud_config"]
+ RO_pub_key = params["RO_pub_key"]
+
+ task_index = params_out["task_index"]
+ uuid_list = params_out["uuid_list"]
+ db_instance_nets = params_out["db_instance_nets"]
+ db_vim_actions = params_out["db_vim_actions"]
+ db_ip_profiles = params_out["db_ip_profiles"]
+ db_instance_vnfs = params_out["db_instance_vnfs"]
+ db_instance_vms = params_out["db_instance_vms"]
+ db_instance_interfaces = params_out["db_instance_interfaces"]
+ net2task_id = params_out["net2task_id"]
+ sce_net2instance = params_out["sce_net2instance"]
+
+ vnf_net2instance = {}
+
+ # 2. Creating new nets (vnf internal nets) in the VIM"
+ # For each vnf net, we create it and we add it to instanceNetlist.
+ if sce_vnf.get("datacenter"):
+ datacenter_id = sce_vnf["datacenter"]
+ myvim_thread_id = myvim_threads_id[sce_vnf["datacenter"]]
+ else:
+ datacenter_id = default_datacenter_id
+ myvim_thread_id = myvim_threads_id[default_datacenter_id]
+ for net in sce_vnf['nets']:
+ # TODO revis
+ # descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
+ # net_name = descriptor_net.get("name")
+ net_name = None
+ if not net_name:
+ net_name = "{}-{}".format(instance_name, net["name"])
+ net_name = net_name[:255] # limit length
+ net_type = net['type']
+
+ if sce_vnf['uuid'] not in vnf_net2instance:
+ vnf_net2instance[sce_vnf['uuid']] = {}
+ if sce_vnf['uuid'] not in net2task_id:
+ net2task_id[sce_vnf['uuid']] = {}
+ net2task_id[sce_vnf['uuid']][net['uuid']] = task_index
+
+ # fill database content
+ net_uuid = str(uuid4())
+ uuid_list.append(net_uuid)
+ vnf_net2instance[sce_vnf['uuid']][net['uuid']] = net_uuid
+ db_net = {
+ "uuid": net_uuid,
+ 'vim_net_id': None,
+ "instance_scenario_id": instance_uuid,
+ "net_id": net["uuid"],
+ "created": True,
+ 'datacenter_id': datacenter_id,
+ 'datacenter_tenant_id': myvim_thread_id,
+ }
+ 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": task_action,
+ "item": "instance_nets",
+ "item_id": net_uuid,
+ "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256)
+ }
+ task_index += 1
+ db_vim_actions.append(db_vim_action)
+
+ if 'ip_profile' in net:
+ db_ip_profile = {
+ 'instance_net_id': net_uuid,
+ 'ip_version': net['ip_profile']['ip_version'],
+ 'subnet_address': net['ip_profile']['subnet_address'],
+ 'gateway_address': net['ip_profile']['gateway_address'],
+ 'dns_address': net['ip_profile']['dns_address'],
+ 'dhcp_enabled': net['ip_profile']['dhcp_enabled'],
+ 'dhcp_start_address': net['ip_profile']['dhcp_start_address'],
+ 'dhcp_count': net['ip_profile']['dhcp_count'],
+ }
+ db_ip_profiles.append(db_ip_profile)
+
+ # print "vnf_net2instance:"
+ # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
+
+ # 3. Creating new vm instances in the VIM
+ # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
+ ssh_access = None
+ if sce_vnf.get('mgmt_access'):
+ ssh_access = sce_vnf['mgmt_access'].get('config-access', {}).get('ssh-access')
+ vnf_availability_zones = []
+ for vm in sce_vnf['vms']:
+ vm_av = vm.get('availability_zone')
+ if vm_av and vm_av not in vnf_availability_zones:
+ vnf_availability_zones.append(vm_av)
+
+ # check if there is enough availability zones available at vim level.
+ if myvims[datacenter_id].availability_zone and vnf_availability_zones:
+ if len(vnf_availability_zones) > len(myvims[datacenter_id].availability_zone):
+ raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request)
+
+ if sce_vnf.get("datacenter"):
+ vim = myvims[sce_vnf["datacenter"]]
+ myvim_thread_id = myvim_threads_id[sce_vnf["datacenter"]]
+ datacenter_id = sce_vnf["datacenter"]
+ else:
+ vim = myvims[default_datacenter_id]
+ myvim_thread_id = myvim_threads_id[default_datacenter_id]
+ datacenter_id = default_datacenter_id
+ sce_vnf["datacenter_id"] = datacenter_id
+ i = 0
+
+ vnf_uuid = str(uuid4())
+ uuid_list.append(vnf_uuid)
+ db_instance_vnf = {
+ 'uuid': vnf_uuid,
+ 'instance_scenario_id': instance_uuid,
+ 'vnf_id': sce_vnf['vnf_id'],
+ 'sce_vnf_id': sce_vnf['uuid'],
+ 'datacenter_id': datacenter_id,
+ 'datacenter_tenant_id': myvim_thread_id,
+ }
+ db_instance_vnfs.append(db_instance_vnf)
+
+ for vm in sce_vnf['vms']:
+ myVMDict = {}
+ sce_vnf_name = sce_vnf['member_vnf_index'] if sce_vnf['member_vnf_index'] else sce_vnf['name']
+ myVMDict['name'] = "{}-{}-{}".format(instance_name[:64], sce_vnf_name[:64], vm["name"][:64])
+ 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']
+ if vm.get("image_list"):
+ for alternative_image in vm["image_list"]:
+ if alternative_image["vim_type"] == vim["config"]["_vim_type_internal"]:
+ image_uuid = alternative_image['image_id']
+ break
+ image_dict = mydb.get_table_by_uuid_name("images", image_uuid)
+ image_id = create_or_use_image(mydb, {datacenter_id: vim}, image_dict, [], True)
+ vm['vim_image_id'] = image_id
+
+ # create flavor at vim in case it not exist
+ flavor_dict = mydb.get_table_by_uuid_name("flavors", vm['flavor_id'])
+ if flavor_dict['extended'] != None:
+ flavor_dict['extended'] = yaml.load(flavor_dict['extended'])
+ flavor_id = create_or_use_flavor(mydb, {datacenter_id: vim}, flavor_dict, rollbackList, True)
+
+ # Obtain information for additional disks
+ extended_flavor_dict = mydb.get_rows(FROM='datacenters_flavors', SELECT=('extended',),
+ WHERE={'vim_id': flavor_id})
+ if not extended_flavor_dict:
+ raise NfvoException("flavor '{}' not found".format(flavor_id), HTTP_Not_Found)
+
+ # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
+ myVMDict['disks'] = None
+ extended_info = extended_flavor_dict[0]['extended']
+ if extended_info != None:
+ 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']
+ myVMDict['flavorRef'] = vm['vim_flavor_id']
+ myVMDict['availability_zone'] = vm.get('availability_zone')
+ myVMDict['networks'] = []
+ task_depends_on = []
+ # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
+ db_vm_ifaces = []
+ for iface in vm['interfaces']:
+ netDict = {}
+ if iface['type'] == "data":
+ netDict['type'] = iface['model']
+ elif "model" in iface and iface["model"] != None:
+ netDict['model'] = iface['model']
+ # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
+ # is obtained from iterface table model
+ # discover type of interface looking at flavor
+ for numa in flavor_dict.get('extended', {}).get('numas', []):
+ for flavor_iface in numa.get('interfaces', []):
+ if flavor_iface.get('name') == iface['internal_name']:
+ if flavor_iface['dedicated'] == 'yes':
+ netDict['type'] = "PF" # passthrough
+ elif flavor_iface['dedicated'] == 'no':
+ netDict['type'] = "VF" # siov
+ elif flavor_iface['dedicated'] == 'yes:sriov':
+ netDict['type'] = "VFnotShared" # sriov but only one sriov on the PF
+ netDict["mac_address"] = flavor_iface.get("mac_address")
+ break
+ netDict["use"] = iface['type']
+ if netDict["use"] == "data" and not netDict.get("type"):
+ # print "netDict", netDict
+ # print "iface", iface
+ e_text = "Cannot determine the interface type PF or VF of VNF '{}' VM '{}' iface '{}'".fromat(
+ sce_vnf['name'], vm['name'], iface['internal_name'])
+ if flavor_dict.get('extended') == None:
+ raise NfvoException(e_text + "After database migration some information is not available. \
+ 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":
+ netDict["type"] = "virtual"
+ if iface.get("vpci"):
+ netDict['vpci'] = iface['vpci']
+ if iface.get("mac"):
+ netDict['mac_address'] = iface['mac']
+ if iface.get("ip_address"):
+ netDict['ip_address'] = iface['ip_address']
+ if iface.get("port-security") is not None:
+ netDict['port_security'] = iface['port-security']
+ if iface.get("floating-ip") is not None:
+ netDict['floating_ip'] = iface['floating-ip']
+ netDict['name'] = iface['internal_name']
+ if iface['net_id'] is None:
+ for vnf_iface in sce_vnf["interfaces"]:
+ # print iface
+ # print vnf_iface
+ if vnf_iface['interface_id'] == iface['uuid']:
+ netDict['net_id'] = "TASK-{}".format(
+ net2task_id['scenario'][vnf_iface['sce_net_id']][datacenter_id])
+ instance_net_id = sce_net2instance[vnf_iface['sce_net_id']][datacenter_id]
+ task_depends_on.append(net2task_id['scenario'][vnf_iface['sce_net_id']][datacenter_id])
+ break
+ else:
+ netDict['net_id'] = "TASK-{}".format(net2task_id[sce_vnf['uuid']][iface['net_id']])
+ instance_net_id = vnf_net2instance[sce_vnf['uuid']][iface['net_id']]
+ task_depends_on.append(net2task_id[sce_vnf['uuid']][iface['net_id']])
+ # skip bridge ifaces not connected to any net
+ if 'net_id' not in netDict or netDict['net_id'] == None:
+ continue
+ myVMDict['networks'].append(netDict)
+ db_vm_iface = {
+ # "uuid"
+ # 'instance_vm_id': instance_vm_uuid,
+ "instance_net_id": instance_net_id,
+ 'interface_id': iface['uuid'],
+ # 'vim_interface_id': ,
+ 'type': 'external' if iface['external_name'] is not None else 'internal',
+ 'ip_address': iface.get('ip_address'),
+ 'mac_address': iface.get('mac'),
+ 'floating_ip': int(iface.get('floating-ip', False)),
+ 'port_security': int(iface.get('port-security', True))
+ }
+ db_vm_ifaces.append(db_vm_iface)
+ # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
+ # print myVMDict['name']
+ # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
+ # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
+ # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
+
+ # 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 vm.get("boot_data"):
+ cloud_config_vm = unify_cloud_config(vm["boot_data"], cloud_config_vm)
+
+ if myVMDict.get('availability_zone'):
+ av_index = vnf_availability_zones.index(myVMDict['availability_zone'])
+ else:
+ av_index = None
+ for vm_index in range(0, vm.get('count', 1)):
+ 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]
+ for net in myVMDict['networks']:
+ if "vim_id" in net:
+ for iface in vm['interfaces']:
+ if net["name"] == iface["internal_name"]:
+ iface["vim_id"] = net["vim_id"]
+ break
+ vm_uuid = str(uuid4())
+ uuid_list.append(vm_uuid)
+ db_vm = {
+ "uuid": vm_uuid,
+ '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)
+
+ iface_index = 0
+ for db_vm_iface in db_vm_ifaces:
+ iface_uuid = str(uuid4())
+ uuid_list.append(iface_uuid)
+ db_vm_iface_instance = {
+ "uuid": iface_uuid,
+ "instance_vm_id": vm_uuid
+ }
+ db_vm_iface_instance.update(db_vm_iface)
+ if db_vm_iface_instance.get("ip_address"): # increment ip_address
+ ip = db_vm_iface_instance.get("ip_address")
+ i = ip.rfind(".")
+ if i > 0:
+ try:
+ i += 1
+ ip = ip[i:] + str(int(ip[:i]) + 1)
+ db_vm_iface_instance["ip_address"] = ip
+ except:
+ db_vm_iface_instance["ip_address"] = None
+ db_instance_interfaces.append(db_vm_iface_instance)
+ myVMDict['networks'][iface_index]["uuid"] = iface_uuid
+ iface_index += 1
+
+ db_vim_action = {
+ "instance_action_id": instance_action_id,
+ "task_index": task_index,
+ "datacenter_vim_id": myvim_thread_id,
+ "action": "CREATE",
+ "status": "SCHEDULED",
+ "item": "instance_vms",
+ "item_id": vm_uuid,
+ "extra": yaml.safe_dump({"params": task_params, "depends_on": task_depends_on},
+ default_flow_style=True, width=256)
+ }
+ task_index += 1
+ db_vim_actions.append(db_vim_action)
+ params_out["task_index"] = task_index
+ params_out["uuid_list"] = uuid_list
+
+