# For those usages not covered by the Apache License, Version 2.0 please
# contact with: nfvlabs@tid.es
##
-
+
'''
NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
'''
# import imp
import json
+import string
import yaml
+from random import choice as random_choice
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_plugin.vim_dummy import VimDummyConnector
+from osm_ro_plugin.sdn_dummy import SdnDummyConnector
+from osm_ro_plugin.sdn_failing import SdnFailingConnector
+from osm_ro_plugin import vimconn, sdnconn
import logging
import collections
import math
from osm_ro import nfvo_db
from threading import Lock
import time as t
-# TODO py3 BEGIN
-# from lib_osm_openvim import ovim as ovim_module
-# from lib_osm_openvim.ovim import ovimException
-from unittest.mock import MagicMock
-ovim_module = MagicMock()
-class ovimException(Exception):
- pass
-ovim_module.ovimException = ovimException
-# TODO py3 END
+from osm_ro.sdn import Sdn, SdnException as ovimException
from Crypto.PublicKey import RSA
# WIM
-import osm_ro.wim.wimconn as wimconn
-import osm_ro.wim.wim_thread as wim_thread
-from osm_ro.http_tools import errors as httperrors
-from osm_ro.wim.engine import WimEngine
-from osm_ro.wim.persistence import WimPersistence
+from .http_tools import errors as httperrors
+from .wim.engine import WimEngine
+from .wim.persistence import WimPersistence
from copy import deepcopy
from pprint import pformat
#
# WIM
global wim_engine
wim_engine = None
-global wimconn_imported
+global sdnconn_imported
#
global logger
global default_volume_size
vim_threads = {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
vim_persistent_info = {}
# WIM
-wimconn_imported = {} # dictionary with WIM type as key, loaded module as value
+sdnconn_imported = {} # dictionary with WIM type as key, loaded module as value
wim_threads = {"running":{}, "deleting": {}, "names": []} # threads running for attached-WIMs
wim_persistent_info = {}
#
db = None
db_lock = Lock()
+worker_id = None
class NfvoException(httperrors.HttpMappedError):
"""Common Class for NFVO errors"""
-def _load_vim_plugin(name):
+def _load_plugin(name, type="vim"):
+ # type can be vim or sdn
global plugins
- for v in iter_entry_points('osm_rovim.plugins', name):
- plugins[name] = v.load()
+ try:
+ for v in iter_entry_points('osm_ro{}.plugins'.format(type), name):
+ plugins[name] = v.load()
+ except Exception as e:
+ logger.critical("Cannot load osm_{}: {}".format(name, e))
+ if name:
+ plugins[name] = SdnFailingConnector("Cannot load osm_{}: {}".format(name, e))
if name and name not in plugins:
- raise NfvoException("Unknown vim type '{}'. This plugin has not been registered".format(name),
- httperrors.Bad_Request)
+ error_text = "Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been" \
+ " registered".format(t=type, n=name)
+ logger.critical(error_text)
+ plugins[name] = SdnFailingConnector(error_text)
+ # raise NfvoException("Cannot load a module for {t} type '{n}'. The plugin 'osm_{n}' has not been registered".
+ # format(t=type, n=name), httperrors.Bad_Request)
def get_task_id():
global last_task_id
def is_task_id(id):
return True if id[:5] == "TASK-" else False
-
-def get_non_used_vim_name(datacenter_name, datacenter_id, tenant_name, tenant_id):
- name = datacenter_name[:16]
- if name not in vim_threads["names"]:
- vim_threads["names"].append(name)
- return name
- if tenant_name:
- name = datacenter_name[:16] + "." + tenant_name[:16]
- if name not in vim_threads["names"]:
- vim_threads["names"].append(name)
- return name
- name = datacenter_id
- vim_threads["names"].append(name)
- return name
+def get_process_id():
+ """
+ Obtain a unique ID for this process. If running from inside docker, it will get docker ID. If not it
+ will provide a random one
+ :return: Obtained ID
+ """
+ # Try getting docker id. If fails, get pid
+ try:
+ with open("/proc/self/cgroup", "r") as f:
+ for text_id_ in f.readlines():
+ if "docker/" not in text_id_:
+ continue
+ _, _, text_id = text_id_.rpartition("/")
+ text_id = text_id.replace("\n", "")[:12]
+ if text_id:
+ return text_id
+ except Exception:
+ pass
+ # Return a random id
+ return "".join(random_choice("0123456789abcdef") for _ in range(12))
+
+def get_non_used_vim_name(datacenter_name, datacenter_id):
+ return "{}:{}:{}".format(
+ worker_id[:12], datacenter_id.replace("-", "")[:32], datacenter_name[:16]
+ )
# -- Move
def get_non_used_wim_name(wim_name, wim_id, tenant_name, tenant_id):
def start_service(mydb, persistence=None, wim=None):
- global db, global_config, plugins
+ global db, global_config, plugins, ovim, worker_id
db = nfvo_db.nfvo_db(lock=db_lock)
mydb.lock = db_lock
db.connect(global_config['db_host'], global_config['db_user'], global_config['db_passwd'], global_config['db_name'])
- global ovim
persistence = persistence or WimPersistence(db)
- # Initialize openvim for SDN control
- # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
- # TODO: review ovim.py to delete not needed configuration
- ovim_configuration = {
- 'logger_name': 'openmano.ovim',
- 'network_vlan_range_start': 1000,
- 'network_vlan_range_end': 4096,
- 'db_name': global_config["db_ovim_name"],
- 'db_host': global_config["db_ovim_host"],
- 'db_user': global_config["db_ovim_user"],
- 'db_passwd': global_config["db_ovim_passwd"],
- 'bridge_ifaces': {},
- 'mode': 'normal',
- 'network_type': 'bridge',
- #TODO: log_level_of should not be needed. To be modified in ovim
- 'log_level_of': 'DEBUG'
- }
try:
+ worker_id = get_process_id()
+ if "rosdn_dummy" not in plugins:
+ plugins["rosdn_dummy"] = SdnDummyConnector
+ if "rovim_dummy" not in plugins:
+ plugins["rovim_dummy"] = VimDummyConnector
# starts ovim library
- ovim = ovim_module.ovim(ovim_configuration)
+ ovim = Sdn(db, plugins)
global wim_engine
- wim_engine = wim or WimEngine(persistence)
+ wim_engine = wim or WimEngine(persistence, plugins)
wim_engine.ovim = ovim
ovim.start_service()
extra.update(yaml.load(vim["dt_config"], Loader=yaml.Loader))
plugin_name = "rovim_" + vim["type"]
if plugin_name not in plugins:
- _load_vim_plugin(plugin_name)
+ _load_plugin(plugin_name, type="vim")
thread_id = vim['datacenter_tenant_id']
vim_persistent_info[thread_id] = {}
try:
#if not tenant:
# return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
- myvim = plugins[plugin_name].vimconnector(
+ myvim = plugins[plugin_name](
uuid=vim['datacenter_id'], name=vim['datacenter_name'],
tenant_id=vim['vim_tenant_id'], tenant_name=vim['vim_tenant_name'],
url=vim['vim_url'], url_admin=vim['vim_url_admin'],
user=vim['user'], passwd=vim['passwd'],
config=extra, persistent_info=vim_persistent_info[thread_id]
)
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
myvim = e
logger.error("Cannot launch thread for VIM {} '{}': {}".format(vim['datacenter_name'],
vim['datacenter_id'], e))
except Exception as e:
- raise NfvoException("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, e),
- httperrors.Internal_Server_Error)
- thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['datacenter_id'], vim['vim_tenant_name'],
- vim['vim_tenant_id'])
- new_thread = vim_thread(task_lock, plugins, thread_name, vim['datacenter_name'],
- vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim)
+ logger.critical("Cannot launch thread for VIM {} '{}': {}".format(vim['datacenter_name'],
+ vim['datacenter_id'], e))
+ # raise NfvoException("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, e),
+ # httperrors.Internal_Server_Error)
+ thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['datacenter_id'])
+ new_thread = vim_thread(task_lock, plugins, thread_name, None,
+ vim['datacenter_tenant_id'], db=db)
new_thread.start()
vim_threads["running"][thread_id] = new_thread
+ wims = mydb.get_rows(FROM="wim_accounts join wims on wim_accounts.wim_id=wims.uuid",
+ WHERE={"sdn": "true"},
+ SELECT=("wim_accounts.uuid as uuid", "type", "wim_accounts.name as name"))
+ for wim in wims:
+ plugin_name = "rosdn_" + wim["type"]
+ if plugin_name not in plugins:
+ _load_plugin(plugin_name, type="sdn")
+ thread_id = wim['uuid']
+ thread_name = get_non_used_vim_name(wim['name'], wim['uuid'])
+ new_thread = vim_thread(task_lock, plugins, thread_name, wim['uuid'], None, db=db)
+ new_thread.start()
+ vim_threads["running"][thread_id] = new_thread
wim_engine.start_threads()
except db_base_Exception as e:
raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code)
- except ovim_module.ovimException as e:
+ except ovimException as e:
message = str(e)
if message[:22] == "DATABASE wrong version":
message = "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
plugin_name = "rovim_" + vim["type"]
if plugin_name not in plugins:
try:
- _load_vim_plugin(plugin_name)
+ _load_plugin(plugin_name, type="vim")
except NfvoException as e:
if ignore_errors:
logger.error("{}".format(e))
persistent_info = {}
#if not tenant:
# return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
- vim_dict[vim['datacenter_id']] = plugins[plugin_name].vimconnector(
+ vim_dict[vim['datacenter_id']] = plugins[plugin_name](
uuid=vim['datacenter_id'], name=vim['datacenter_name'],
tenant_id=vim.get('vim_tenant_id',vim_tenant),
tenant_name=vim.get('vim_tenant_name',vim_tenant_name),
logger.error("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, str(e)))
continue
http_code = httperrors.Internal_Server_Error
- if isinstance(e, vimconn.vimconnException):
+ if isinstance(e, vimconn.VimConnException):
http_code = e.http_code
raise NfvoException("Error at VIM {}; {}: {}".format(vim["type"], type(e).__name__, str(e)), http_code)
return vim_dict
vim.delete_network(item["uuid"])
elif item["what"]=="vm":
vim.delete_vminstance(item["uuid"])
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
logger.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item['what'], item["uuid"], str(e))
undeleted_items.append("{} {} from VIM {}".format(item['what'], item["uuid"], vim["name"]))
except db_base_Exception as e:
logger.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item['what'], item["uuid"], str(e))
undeleted_items.append("{} '{}'".format(item['what'], item["uuid"]))
if len(undeleted_items)==0:
- return True," Rollback successful."
+ return True, "Rollback successful."
else:
- return False," Rollback fails to delete: " + str(undeleted_items)
+ return False, "Rollback fails to delete: " + str(undeleted_items)
def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
vim_images = vim.get_image_list(filter_dict)
#logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
if len(vim_images) > 1:
- raise vimconn.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict)), httperrors.Conflict)
+ raise vimconn.VimConnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict)), httperrors.Conflict)
elif len(vim_images) == 0:
- raise vimconn.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict)))
+ raise vimconn.VimConnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict)))
else:
#logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
image_vim_id = vim_images[0]['id']
- except vimconn.vimconnNotFoundException as e:
+ except vimconn.VimConnNotFoundException as e:
#Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
try:
#image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
image_created="true"
else:
#If we reach this point, then the image has image name, and optionally checksum, and could not be found
- raise vimconn.vimconnException(str(e))
- except vimconn.vimconnException as e:
+ raise vimconn.VimConnException(str(e))
+ except vimconn.VimConnException as e:
if return_on_error:
logger.error("Error creating image at VIM '%s': %s", vim["name"], str(e))
raise
image_vim_id = None
logger.warn("Error creating image at VIM '%s': %s", vim["name"], str(e))
continue
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
if return_on_error:
logger.error("Error contacting VIM to know if the image exists at VIM: %s", str(e))
raise
try:
vim.get_flavor(flavor_vim_id)
continue #flavor exist
- except vimconn.vimconnException:
+ except vimconn.VimConnException:
pass
#create flavor at vim
logger.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim["name"])
flavor_vim_id = None
flavor_vim_id=vim.get_flavor_id_from_data(flavor_dict)
flavor_created="false"
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
pass
try:
if not flavor_vim_id:
flavor_vim_id = vim.new_flavor(flavor_dict)
rollback_list.append({"where":"vim", "vim_id": vim_id, "what":"flavor","uuid":flavor_vim_id})
flavor_created="true"
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
if return_on_error:
logger.error("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
raise
# table nets (internal-vld)
net_id2uuid = {} # for mapping interface with network
+ net_id2index = {} # for mapping interface with network
for vld in vnfd.get("internal-vld").values():
net_uuid = str(uuid4())
uuid_list.append(net_uuid)
"type": "bridge", # TODO adjust depending on connection point type
}
net_id2uuid[vld.get("id")] = net_uuid
+ net_id2index[vld.get("id")] = len(db_nets)
db_nets.append(db_net)
# ip-profile, link db_ip_profile with db_sce_net
if vld.get("ip-profile-ref"):
raise KeyError()
if vdu_id in vdu_id2cp_name:
- vdu_id2cp_name[vdu_id] = None # more than two connecdtion point for this VDU
+ vdu_id2cp_name[vdu_id] = None # more than two connection point for this VDU
else:
vdu_id2cp_name[vdu_id] = db_interface["external_name"]
# port security
- if str(cp_descriptor.get("port-security-enabled")).lower() == "false":
+ if "port-security-disable-strategy" in cp_descriptor or str(cp_descriptor.get("port-security-enabled")).lower() == "false":
db_interface["port_security"] = 0
+ db_interface["port_security_disable_strategy"] = cp_descriptor.get("port-security-disable-strategy", "full")
elif str(cp_descriptor.get("port-security-enabled")).lower() == "true":
db_interface["port_security"] = 1
except KeyError:
if not icp:
raise KeyError("is not referenced by any 'internal-vld'")
+ # set network type as data
+ if iface.get("virtual-interface") and iface["virtual-interface"].get("type") in \
+ ("SR-IOV", "PCI-PASSTHROUGH"):
+ db_nets[net_id2index[icp_vld.get("id")]]["type"] = "data"
db_interface["net_id"] = net_id2uuid[icp_vld.get("id")]
- if str(icp_descriptor.get("port-security-enabled")).lower() == "false":
+ if "port-security-disable-strategy" in icp_descriptor or str(icp_descriptor.get("port-security-enabled")).lower() == "false":
db_interface["port_security"] = 0
+ db_interface["port_security_disable_strategy"] = icp_descriptor.get("port-security-disable-strategy", "full")
elif str(icp_descriptor.get("port-security-enabled")).lower() == "true":
db_interface["port_security"] = 1
if icp.get("ip-address"):
if vnfd["mgmt-interface"].get("ip-address"):
mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].get("ip-address"))
- if vnfd["mgmt-interface"].get("cp"):
+ if vnfd["mgmt-interface"].get("cp") and vnfd.get("vdu"):
if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid:
raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
"Reference to a non-existing connection-point".format(
# Step 8. Adding the VNF to the NFVO DB
vnf_id = mydb.new_vnf_as_a_whole(tenant_id,vnf_name,vnf_descriptor,VNFCDict)
return vnf_id
- except (db_base_Exception, vimconn.vimconnException, KeyError) as e:
+ except (db_base_Exception, vimconn.VimConnException, KeyError) as e:
_, message = rollback(mydb, vims, rollback_list)
if isinstance(e, db_base_Exception):
error_text = "Exception at database"
# Step 8. Adding the VNF to the NFVO DB
vnf_id = mydb.new_vnf_as_a_whole2(tenant_id,vnf_name,vnf_descriptor,VNFCDict)
return vnf_id
- except (db_base_Exception, vimconn.vimconnException, KeyError) as e:
+ except (db_base_Exception, vimconn.VimConnException, KeyError) as e:
_, message = rollback(mydb, vims, rollback_list)
if isinstance(e, db_base_Exception):
error_text = "Exception at database"
continue
try:
myvim.delete_flavor(flavor_vim["vim_id"])
- except vimconn.vimconnNotFoundException:
+ except vimconn.VimConnNotFoundException:
logger.warn("VIM flavor %s not exist at datacenter %s", flavor_vim["vim_id"],
flavor_vim["datacenter_vim_id"] )
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
logger.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
flavor_vim["vim_id"], flavor_vim["datacenter_vim_id"], type(e).__name__, str(e))
undeletedItems.append("flavor {} from VIM {}".format(flavor_vim["vim_id"],
myvim=vims[ image_vim["datacenter_id"] ]
try:
myvim.delete_image(image_vim["vim_id"])
- except vimconn.vimconnNotFoundException as e:
+ except vimconn.VimConnNotFoundException as e:
logger.warn("VIM image %s not exist at datacenter %s", image_vim["vim_id"], image_vim["datacenter_id"] )
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
logger.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
image_vim["vim_id"], image_vim["datacenter_id"], type(e).__name__, str(e))
undeletedItems.append("image {} from VIM {}".format(image_vim["vim_id"], image_vim["datacenter_id"] ))
#print 'datacenters '+ json.dumps(datacenter, indent=4)
return datacenter
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e)), e.http_code)
# table sce_interfaces (vld:vnfd-connection-point-ref)
for iface in vld.get("vnfd-connection-point-ref").values():
+ # Check if there are VDUs in the descriptor
vnf_index = str(iface['member-vnf-index-ref'])
- # check correct parameters
- if vnf_index not in vnf_index2vnf_uuid:
- raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
- "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
- "'nsd':'constituent-vnfd'".format(
- str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])),
- httperrors.Bad_Request)
-
- existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid', 'i.type as iface_type'),
- FROM="interfaces as i join vms on i.vm_id=vms.uuid",
- WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index],
- 'external_name': get_str(iface, "vnfd-connection-point-ref",
- 255)})
- if not existing_ifaces:
- raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
- "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
- "connection-point name at VNFD '{}'".format(
- str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
- str(iface.get("vnfd-id-ref"))[:255]),
- httperrors.Bad_Request)
- interface_uuid = existing_ifaces[0]["uuid"]
- if existing_ifaces[0]["iface_type"] == "data":
- db_sce_net["type"] = "data"
- sce_interface_uuid = str(uuid4())
- uuid_list.append(sce_net_uuid)
- iface_ip_address = None
- if iface.get("ip-address"):
- iface_ip_address = str(iface.get("ip-address"))
- db_sce_interface = {
- "uuid": sce_interface_uuid,
- "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
- "sce_net_id": sce_net_uuid,
- "interface_id": interface_uuid,
- "ip_address": iface_ip_address,
- }
- db_sce_interfaces.append(db_sce_interface)
- if not db_sce_net["type"]:
- db_sce_net["type"] = "bridge"
+ existing_vdus = mydb.get_rows(SELECT=('vms.uuid'), FROM="vms", WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index]})
+ if existing_vdus:
+ # check correct parameters
+ if vnf_index not in vnf_index2vnf_uuid:
+ raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
+ "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
+ "'nsd':'constituent-vnfd'".format(
+ str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])),
+ httperrors.Bad_Request)
+
+ existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid', 'i.type as iface_type'),
+ FROM="interfaces as i join vms on i.vm_id=vms.uuid",
+ WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index],
+ 'external_name': get_str(iface, "vnfd-connection-point-ref",
+ 255)})
+ if not existing_ifaces:
+ raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
+ "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
+ "connection-point name at VNFD '{}'".format(
+ str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
+ str(iface.get("vnfd-id-ref"))[:255]),
+ httperrors.Bad_Request)
+ interface_uuid = existing_ifaces[0]["uuid"]
+ if existing_ifaces[0]["iface_type"] == "data":
+ db_sce_net["type"] = "data"
+ sce_interface_uuid = str(uuid4())
+ uuid_list.append(sce_net_uuid)
+ iface_ip_address = None
+ if iface.get("ip-address"):
+ iface_ip_address = str(iface.get("ip-address"))
+ db_sce_interface = {
+ "uuid": sce_interface_uuid,
+ "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
+ "sce_net_id": sce_net_uuid,
+ "interface_id": interface_uuid,
+ "ip_address": iface_ip_address,
+ }
+ db_sce_interfaces.append(db_sce_interface)
+ if not db_sce_net["type"]:
+ db_sce_net["type"] = "bridge"
# table sce_vnffgs (vnffgd)
for vnffg in nsd.get("vnffgd").values():
myNetDict["type"] = myNetType
myNetDict["tenant_id"] = myvim_tenant
myNetIPProfile = sce_net.get('ip_profile', None)
+ myProviderNetwork = sce_net.get('provider_network', None)
#TODO:
#We should use the dictionary as input parameter for new_network
#print myNetDict
if not sce_net["external"]:
- network_id, _ = myvim.new_network(myNetName, myNetType, myNetIPProfile)
+ network_id, _ = myvim.new_network(myNetName, myNetType, myNetIPProfile, provider_network_profile=myProviderNetwork)
#print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
sce_net['vim_id'] = network_id
auxNetDict['scenario'][sce_net['uuid']] = network_id
myNetDict["type"] = myNetType
myNetDict["tenant_id"] = myvim_tenant
myNetIPProfile = net.get('ip_profile', None)
+ myProviderNetwork = sce_net.get('provider_network', None)
#print myNetDict
#TODO:
#We should use the dictionary as input parameter for new_network
- network_id, _ = myvim.new_network(myNetName, myNetType, myNetIPProfile)
+ network_id, _ = myvim.new_network(myNetName, myNetType, myNetIPProfile, provider_network_profile=myProviderNetwork)
#print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
net['vim_id'] = network_id
if sce_vnf['uuid'] not in auxNetDict:
instance_id = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_scenario_name, instance_scenario_description, scenarioDict)
return mydb.get_instance_scenario(instance_id)
- except (db_base_Exception, vimconn.vimconnException) as e:
+ except (db_base_Exception, vimconn.VimConnException) as e:
_, message = rollback(mydb, vims, rollbackList)
if isinstance(e, db_base_Exception):
error_text = "Exception at database"
def get_vim_thread(mydb, tenant_id, datacenter_id_name=None, datacenter_tenant_id=None):
+ global plugins
datacenter_id = None
datacenter_name = None
thread = None
if datacenter_tenant_id:
thread_id = datacenter_tenant_id
thread = vim_threads["running"].get(datacenter_tenant_id)
- else:
+ if not thread:
where_={"td.nfvo_tenant_id": tenant_id}
if datacenter_id_name:
if utils.check_valid_uuid(datacenter_id_name):
if datacenter_tenant_id:
where_["dt.uuid"] = datacenter_tenant_id
datacenters = mydb.get_rows(
- SELECT=("dt.uuid as datacenter_tenant_id",),
+ SELECT=("dt.uuid as datacenter_tenant_id, d.name as datacenter_name", "d.type as type"),
FROM="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
"join datacenters as d on d.uuid=dt.datacenter_id",
WHERE=where_)
raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict)
elif datacenters:
thread_id = datacenters[0]["datacenter_tenant_id"]
+ datacenter_name = datacenters[0]["datacenter_name"]
thread = vim_threads["running"].get(thread_id)
+ if not thread:
+ datacenter_type = datacenters[0]["type"]
+ plugin_name = "rovim_" + datacenter_type
+ if plugin_name not in plugins:
+ _load_plugin(plugin_name, type="vim")
+ thread_name = get_non_used_vim_name(datacenter_name, datacenter_id)
+ thread = vim_thread(task_lock, plugins, thread_name, None,
+ thread_id, db=mydb)
+ thread.start()
+ vim_threads["running"][thread_id] = thread
if not thread:
raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), httperrors.Not_Found)
return thread_id, thread
" dt on td.datacenter_tenant_id=dt.uuid"
else:
from_ = 'datacenters as d'
- vimaccounts = mydb.get_rows(FROM=from_, SELECT=("d.uuid as uuid, d.name as name",), WHERE=WHERE_dict )
+ vimaccounts = mydb.get_rows(FROM=from_, SELECT=("d.uuid as uuid", "d.name as name", "d.type as type"),
+ WHERE=WHERE_dict)
if len(vimaccounts) == 0:
raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), httperrors.Not_Found)
- elif len(vimaccounts)>1:
- #print "nfvo.datacenter_action() error. Several datacenters 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", httperrors.Conflict)
- return vimaccounts[0]["uuid"], vimaccounts[0]["name"]
+ return vimaccounts[0]["uuid"], vimaccounts[0]
def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extra_filter):
return d
+def _get_wim(db, wim_account_id):
+ # get wim from wim_account
+ wim_accounts = db.get_rows(FROM='wim_accounts', WHERE={"uuid": wim_account_id})
+ if not wim_accounts:
+ raise NfvoException("Not found sdn id={}".format(wim_account_id), http_code=httperrors.Not_Found)
+ return wim_accounts[0]["wim_id"]
+
+
def create_instance(mydb, tenant_id, instance_dict):
# print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
# logger.debug("Creating instance...")
+
scenario = instance_dict["scenario"]
# find main datacenter
}
# Auxiliary dictionaries from x to y
+ sce_net2wim_instance = {}
sce_net2instance = {}
net2task_id = {'scenario': {}}
# Mapping between local networks and WIMs
else:
update(scenario_net['ip_profile'], ipprofile_db)
+ if net_instance_desc.get('provider-network'):
+ provider_network_db = net_instance_desc['provider-network']
+ if 'provider_network' not in scenario_net:
+ scenario_net['provider_network'] = provider_network_db
+ else:
+ update(scenario_net['provider_network'], provider_network_db)
+
for vdu_id, vdu_instance_desc in vnf_instance_desc.get("vdus", {}).items():
for scenario_vm in scenario_vnf['vms']:
if vdu_id == scenario_vm['osm_id'] or vdu_id == scenario_vm["name"]:
scenario_net['ip_profile'] = ipprofile_db
else:
update(scenario_net['ip_profile'], ipprofile_db)
+ if 'provider-network' in net_instance_desc:
+ provider_network_db = net_instance_desc['provider-network']
+
+ if 'provider-network' not in scenario_net:
+ scenario_net['provider_network'] = provider_network_db
+ else:
+ update(scenario_net['provider-network'], provider_network_db)
+
for interface in net_instance_desc.get('interfaces', ()):
if 'ip_address' in interface:
for vnf in scenarioDict['vnfs']:
# logger.debug("Creating instance scenario-dict MERGED:\n%s",
# yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
+
# 1. Creating new nets (sce_nets) in the VIM"
number_mgmt_networks = 0
db_instance_nets = []
+ db_instance_wim_nets = []
for sce_net in scenarioDict['nets']:
+
sce_net_uuid = sce_net.get('uuid', sce_net["name"])
# get involved datacenters where this network need to be created
involved_datacenters = []
involved_datacenters.append(default_datacenter_id)
target_wim_account = sce_net.get("wim_account", default_wim_account)
- # --> WIM
- # TODO: use this information during network creation
- wim_account_id = wim_account_name = None
- if len(involved_datacenters) > 1 and 'uuid' in sce_net:
- if target_wim_account is None or target_wim_account is True: # automatic selection of WIM
- # OBS: sce_net without uuid are used internally to VNFs
- # and the assumption is that VNFs will not be split among
- # different datacenters
- wim_account = wim_engine.find_suitable_wim_account(
- involved_datacenters, tenant_id)
- wim_account_id = wim_account['uuid']
- wim_account_name = wim_account['name']
- wim_usage[sce_net['uuid']] = wim_account_id
- elif isinstance(target_wim_account, str): # manual selection of WIM
- wim_account.persist.get_wim_account_by(target_wim_account, tenant_id)
- wim_account_id = wim_account['uuid']
- wim_account_name = wim_account['name']
- wim_usage[sce_net['uuid']] = wim_account_id
- else: # not WIM usage
- wim_usage[sce_net['uuid']] = False
- # <-- WIM
-
descriptor_net = {}
if instance_dict.get("networks"):
if sce_net.get("uuid") in instance_dict["networks"]:
if site.get("datacenter") and site["datacenter"] not in involved_datacenters:
involved_datacenters.append(site["datacenter"])
sce_net2instance[sce_net_uuid] = {}
+ sce_net2wim_instance[sce_net_uuid] = {}
net2task_id['scenario'][sce_net_uuid] = {}
use_network = None
)
if not target_instance_nets:
raise NfvoException(
- "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name),
- httperrors.Bad_Request)
+ "Cannot find the target network at instance:networks[{}]:use-network".format(
+ descriptor_net_name), httperrors.Bad_Request)
else:
use_network = target_instance_nets[0]["related"]
if sce_net["external"]:
number_mgmt_networks += 1
+ # --> WIM
+ # TODO: use this information during network creation
+ wim_account_id = wim_account_name = None
+ if len(involved_datacenters) > 1 and 'uuid' in sce_net:
+ urls = [myvims[v].url for v in involved_datacenters]
+ if len(set(urls)) < 2:
+ wim_usage[sce_net['uuid']] = False
+ elif target_wim_account is None or target_wim_account is True: # automatic selection of WIM
+ # OBS: sce_net without uuid are used internally to VNFs
+ # and the assumption is that VNFs will not be split among
+ # different datacenters
+ wim_account = wim_engine.find_suitable_wim_account(
+ involved_datacenters, tenant_id)
+ wim_account_id = wim_account['uuid']
+ wim_account_name = wim_account['name']
+ wim_usage[sce_net['uuid']] = wim_account_id
+ elif isinstance(target_wim_account, str): # manual selection of WIM
+ wim_account.persist.get_wim_account_by(target_wim_account, tenant_id)
+ wim_account_id = wim_account['uuid']
+ wim_account_name = wim_account['name']
+ wim_usage[sce_net['uuid']] = wim_account_id
+ else: # not WIM usage
+ wim_usage[sce_net['uuid']] = False
+ # <-- WIM
+
for datacenter_id in involved_datacenters:
netmap_use = None
netmap_create = None
task_extra = {}
if create_network:
task_action = "CREATE"
- task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None), wim_account_name)
+ task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None), False,
+ sce_net.get('provider_network', None), wim_account_name)
+
if lookfor_network:
task_extra["find"] = (lookfor_filter,)
elif lookfor_network:
sce_net2instance[sce_net_uuid][datacenter_id] = net_uuid
if not related_network: # all db_instance_nets will have same related
related_network = use_network or net_uuid
+ sdn_net_id = None
+ sdn_controller = vim.config.get('sdn-controller')
+ sce_net2wim_instance[sce_net_uuid][datacenter_id] = None
+ if sdn_controller and net_type in ("data", "ptp"):
+ wim_id = _get_wim(mydb, sdn_controller)
+ sdn_net_id = str(uuid4())
+ sce_net2wim_instance[sce_net_uuid][datacenter_id] = sdn_net_id
+ task_extra["sdn_net_id"] = sdn_net_id
+ db_instance_wim_nets.append({
+ "uuid": sdn_net_id,
+ "instance_scenario_id": instance_uuid,
+ "sce_net_id": sce_net.get("uuid"),
+ "wim_id": wim_id,
+ "wim_account_id": sdn_controller,
+ 'status': 'BUILD', # if create_network else "ACTIVE"
+ "related": related_network,
+ 'multipoint': True if net_type=="data" else False,
+ "created": create_network, # TODO py3
+ "sdn": True,
+ })
+
+ task_wim_extra = {"params": [net_type, wim_account_name]}
+ # add sdn interfaces
+ if sce_net.get('provider_network') and sce_net['provider_network'].get("sdn-ports"):
+ task_wim_extra["sdn-ports"] = sce_net['provider_network'].get("sdn-ports")
+ db_vim_action = {
+ "instance_action_id": instance_action_id,
+ "status": "SCHEDULED",
+ "task_index": task_index,
+ # "datacenter_vim_id": myvim_thread_id,
+ "wim_account_id": sdn_controller,
+ "action": task_action,
+ "item": "instance_wim_nets",
+ "item_id": sdn_net_id,
+ "related": related_network,
+ "extra": yaml.safe_dump(task_wim_extra, default_flow_style=True, width=256)
+ }
+ task_index += 1
+ db_vim_actions.append(db_vim_action)
db_net = {
"uuid": net_uuid,
"osm_id": sce_net.get("osm_id") or sce_net["name"],
"created": create_network,
'datacenter_id': datacenter_id,
'datacenter_tenant_id': myvim_thread_id,
- 'status': 'BUILD' # if create_network else "ACTIVE"
+ 'status': 'BUILD', # if create_network else "ACTIVE"
+ 'sdn_net_id': sdn_net_id,
}
db_instance_nets.append(db_net)
db_vim_action = {
"task_index": task_index,
"uuid_list": uuid_list,
"db_instance_nets": db_instance_nets,
+ "db_instance_wim_nets": db_instance_wim_nets,
"db_vim_actions": db_vim_actions,
"db_ip_profiles": db_ip_profiles,
"db_instance_vnfs": db_instance_vnfs,
"db_instance_interfaces": db_instance_interfaces,
"net2task_id": net2task_id,
"sce_net2instance": sce_net2instance,
+ "sce_net2wim_instance": sce_net2wim_instance,
}
# sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
for sce_vnf in scenarioDict.get('vnfs', ()): # sce_vnf_list:
"source_ip": match["source_ip"],
"destination_ip": match["destination_ip"],
"source_port": match["source_port"],
- "destination_port": match["destination_port"]
+ "destination_port": match["destination_port"],
+ "logical_source_port": classifier["interface_id"]
}
db_vim_action = {
"instance_action_id": instance_action_id,
{"instance_sfs": db_instance_sfs},
{"instance_classifications": db_instance_classifications},
{"instance_sfps": db_instance_sfps},
- {"instance_wim_nets": wan_links},
+ {"instance_wim_nets": db_instance_wim_nets + wan_links},
{"vim_wim_actions": db_vim_actions + wim_actions}
]
returned_instance = mydb.get_instance_scenario(instance_uuid)
returned_instance["action_id"] = instance_action_id
return returned_instance
- except (NfvoException, vimconn.vimconnException, wimconn.WimConnectorError, db_base_Exception) as e:
- message = rollback(mydb, myvims, rollbackList)
+ except (NfvoException, vimconn.VimConnException, sdnconn.SdnConnectorError, db_base_Exception) as e:
+ _, message = rollback(mydb, myvims, rollbackList)
if isinstance(e, db_base_Exception):
error_text = "database Exception"
- elif isinstance(e, vimconn.vimconnException):
+ elif isinstance(e, vimconn.VimConnException):
error_text = "VIM Exception"
- elif isinstance(e, wimconn.WimConnectorError):
+ elif isinstance(e, sdnconn.SdnConnectorError):
error_text = "WIM Exception"
else:
- error_text = "Exception"
- error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
+ error_text = "Exception " + str(type(e).__name__)
+ error_text += " {}. {}".format(e, message)
# logger.error("create_instance: %s", error_text)
logger.exception(e)
raise NfvoException(error_text, e.http_code)
+def increment_ip_mac(ip_mac, vm_index=1):
+ if not isinstance(ip_mac, str):
+ return ip_mac
+ try:
+ # try with ipv4 look for last dot
+ i = ip_mac.rfind(".")
+ if i > 0:
+ i += 1
+ return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
+ # try with ipv6 or mac look for last colon. Operate in hex
+ i = ip_mac.rfind(":")
+ if i > 0:
+ i += 1
+ # format in hex, len can be 2 for mac or 4 for ipv6
+ return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(ip_mac[:i], int(ip_mac[i:], 16) + vm_index)
+ except:
+ pass
+ return None
+
def instantiate_vnf(mydb, sce_vnf, params, params_out, rollbackList):
default_datacenter_id = params["default_datacenter_id"]
task_index = params_out["task_index"]
uuid_list = params_out["uuid_list"]
db_instance_nets = params_out["db_instance_nets"]
+ db_instance_wim_nets = params_out["db_instance_wim_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_interfaces = params_out["db_instance_interfaces"]
net2task_id = params_out["net2task_id"]
sce_net2instance = params_out["sce_net2instance"]
+ sce_net2wim_instance = params_out["sce_net2wim_instance"]
vnf_net2instance = {}
+ vnf_net2wim_instance = {}
# 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"):
+ vim = myvims[sce_vnf["datacenter"]]
datacenter_id = sce_vnf["datacenter"]
myvim_thread_id = myvim_threads_id[sce_vnf["datacenter"]]
else:
+ vim = myvims[default_datacenter_id]
datacenter_id = default_datacenter_id
myvim_thread_id = myvim_threads_id[default_datacenter_id]
for net in sce_vnf['nets']:
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
+
+ sdn_controller = vim.config.get('sdn-controller')
+ sdn_net_id = None
+ if sdn_controller and net_type in ("data", "ptp"):
+ wim_id = _get_wim(mydb, sdn_controller)
+ sdn_net_id = str(uuid4())
+ db_instance_wim_nets.append({
+ "uuid": sdn_net_id,
+ "instance_scenario_id": instance_uuid,
+ "wim_id": wim_id,
+ "wim_account_id": sdn_controller,
+ 'status': 'BUILD', # if create_network else "ACTIVE"
+ "related": net_uuid,
+ 'multipoint': True if net_type == "data" else False,
+ "created": True, # TODO py3
+ "sdn": True,
+ })
+ vnf_net2wim_instance[net_uuid] = sdn_net_id
+
db_net = {
"uuid": net_uuid,
"related": net_uuid,
"created": True,
'datacenter_id': datacenter_id,
'datacenter_tenant_id': myvim_thread_id,
+ 'sdn_net_id': sdn_net_id,
}
db_instance_nets.append(db_net)
else:
task_action = "CREATE"
task_extra = {"params": (net_name, net_type, net.get('ip_profile', None))}
+ if sdn_net_id:
+ task_extra["sdn_net_id"] = sdn_net_id
+ if sdn_net_id:
+ task_wim_extra = {"params": [net_type, None]}
+ db_vim_action = {
+ "instance_action_id": instance_action_id,
+ "status": "SCHEDULED",
+ "task_index": task_index,
+ # "datacenter_vim_id": myvim_thread_id,
+ "wim_account_id": sdn_controller,
+ "action": task_action,
+ "item": "instance_wim_nets",
+ "item_id": sdn_net_id,
+ "related": net_uuid,
+ "extra": yaml.safe_dump(task_wim_extra, default_flow_style=True, width=256)
+ }
+ task_index += 1
+ db_vim_actions.append(db_vim_action)
db_vim_action = {
"instance_action_id": instance_action_id,
"task_index": task_index,
"related": net_uuid,
"extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256)
}
+ net2task_id[sce_vnf['uuid']][net['uuid']] = task_index
task_index += 1
db_vim_actions.append(db_vim_action)
netDict['ip_address'] = iface['ip_address']
if iface.get("port-security") is not None:
netDict['port_security'] = iface['port-security']
+ if iface.get("port_security_disable_strategy") is not None:
+ netDict['port_security_disable_strategy'] = iface['port_security_disable_strategy']
if iface.get("floating-ip") is not None:
netDict['floating_ip'] = iface['floating-ip']
netDict['name'] = iface['internal_name']
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]
+ instance_wim_net_id = sce_net2wim_instance[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']]
+ instance_wim_net_id = vnf_net2wim_instance.get(instance_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:
# "uuid"
# 'instance_vm_id': instance_vm_uuid,
"instance_net_id": instance_net_id,
+ "instance_wim_net_id": instance_wim_net_id,
'interface_id': iface['uuid'],
# 'vim_interface_id': ,
'type': 'external' if iface['external_name'] is not None else 'internal',
+ 'model': iface['model'],
'ip_address': iface.get('ip_address'),
'mac_address': iface.get('mac'),
'floating_ip': int(iface.get('floating-ip', False)),
else:
av_index = None
for vm_index in range(0, vm.get('count', 1)):
+ if vm.get("instance_parameters") and vm["instance_parameters"].get("cloud_init"):
+ cloud_config_vm_ = unify_cloud_config(cloud_config_vm,
+ {"user-data": vm["instance_parameters"]["cloud_init"][vm_index]})
+ else:
+ cloud_config_vm_ = cloud_config_vm
+
vm_name = myVMDict['name'] + "-" + str(vm_index+1)
+ vm_networks = deepcopy(myVMDict['networks'])
task_params = (vm_name, myVMDict['description'], myVMDict.get('start', None),
- myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'], cloud_config_vm,
+ myVMDict['imageRef'], myVMDict['flavorRef'], vm_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 = {
}
db_instance_vms.append(db_vm)
- iface_index = 0
- for db_vm_iface in db_vm_ifaces:
+ # put interface uuid back to scenario[vnfs][vms[[interfaces]
+ for net in vm_networks:
+ if "vim_id" in net:
+ for iface in vm['interfaces']:
+ if net["name"] == iface["internal_name"]:
+ iface["vim_id"] = net["vim_id"]
+ break
+
+ if vm_index > 0:
+ if net.get("ip_address"):
+ net["ip_address"] = increment_ip_mac(net.get("ip_address"), vm_index)
+ if net.get("mac_address"):
+ net["mac_address"] = increment_ip_mac(net.get("mac_address"), vm_index)
+
+ for iface_index, db_vm_iface in enumerate(db_vm_ifaces):
iface_uuid = str(uuid4())
uuid_list.append(iface_uuid)
db_vm_iface_instance = {
"uuid": iface_uuid,
- "instance_vm_id": vm_uuid
+ "instance_vm_id": vm_uuid,
+ "ip_address": vm_networks[iface_index].get("ip_address"),
+ "mac_address": vm_networks[iface_index].get("mac_address")
}
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
+ vm_networks[iface_index]["uuid"] = iface_uuid
db_vim_action = {
"instance_action_id": instance_action_id,
}
task_index += 1
db_vim_actions.append(db_vim_action)
+ for sdn_net in instanceDict['sdn_nets']:
+ if not sdn_net["sdn"]:
+ continue
+ extra = {}
+ db_vim_action = {
+ "instance_action_id": instance_action_id,
+ "task_index": task_index,
+ "wim_account_id": sdn_net["wim_account_id"],
+ "action": "DELETE",
+ "status": "SCHEDULED",
+ "item": "instance_wim_nets",
+ "item_id": sdn_net["uuid"],
+ "related": sdn_net["related"],
+ "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
+ }
+ task_index += 1
+ db_vim_actions.append(db_vim_action)
db_instance_action["number_tasks"] = task_index
#obtain data
instance_dict = mydb.get_instance_scenario(instance_id, tenant_id, verbose=True)
- for net in instance_dict["nets"]:
- if net.get("sdn_net_id"):
- net_sdn = ovim.show_network(net["sdn_net_id"])
- net["sdn_info"] = {
- "admin_state_up": net_sdn.get("admin_state_up"),
- "flows": net_sdn.get("flows"),
- "last_error": net_sdn.get("last_error"),
- "ports": net_sdn.get("ports"),
- "type": net_sdn.get("type"),
- "status": net_sdn.get("status"),
- "vlan": net_sdn.get("vlan"),
- }
+ # TODO py3
+ # for net in instance_dict["nets"]:
+ # if net.get("sdn_net_id"):
+ # net_sdn = ovim.show_network(net["sdn_net_id"])
+ # net["sdn_info"] = {
+ # "admin_state_up": net_sdn.get("admin_state_up"),
+ # "flows": net_sdn.get("flows"),
+ # "last_error": net_sdn.get("last_error"),
+ # "ports": net_sdn.get("ports"),
+ # "type": net_sdn.get("type"),
+ # "status": net_sdn.get("status"),
+ # "vlan": net_sdn.get("vlan"),
+ # }
return instance_dict
@deprecated("Instance is automatically refreshed by vim_threads")
# try:
# vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
# failed = False
- # except vimconn.vimconnException as e:
+ # except vimconn.VimConnException as e:
# logger.error("VIM exception %s %s", type(e).__name__, str(e))
# failed_message = str(e)
# if failed:
# try:
# net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
# failed = False
- # except vimconn.vimconnException as e:
+ # except vimconn.VimConnException as e:
# logger.error("VIM exception %s %s", type(e).__name__, str(e))
# failed_message = str(e)
# if failed:
"extra": yaml.safe_dump({"params": vm_interfaces},
default_flow_style=True, width=256)
}
+ # get affected instance_interfaces (deleted on cascade) to check if a wim_network must be updated
+ deleted_interfaces = mydb.get_rows(
+ SELECT=("instance_wim_net_id", ),
+ FROM="instance_interfaces",
+ WHERE={"instance_vm_id": vdu_id, "instance_wim_net_id<>": None},
+ )
+ for deleted_interface in deleted_interfaces:
+ db_vim_actions.append({"TO-UPDATE": {}, "WHERE": {
+ "item": "instance_wim_nets", "item_id": deleted_interface["instance_wim_net_id"]}})
+
task_index += 1
db_vim_actions.append(db_vim_action)
vm_result["deleted"].append(vdu_id)
# 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"]:
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):
"uuid": iface_uuid,
'instance_vm_id': vm_uuid,
"instance_net_id": vm_iface["instance_net_id"],
+ "instance_wim_net_id": vm_iface["instance_wim_net_id"],
'interface_id': vm_iface['interface_id'],
'type': vm_iface['type'],
+ 'model': vm_iface['model'],
'floating_ip': vm_iface['floating_ip'],
'port_security': vm_iface['port_security']
}
db_instance_interfaces.append(db_vm_iface)
+ if db_vm_iface["instance_wim_net_id"]:
+ db_vim_actions.append({"TO-UPDATE": {}, "WHERE": {
+ "item": "instance_wim_nets", "item_id": db_vm_iface["instance_wim_net_id"]}})
task_params_copy = deepcopy(task_params)
+ cloud_config_vm = task_params_copy[6] or {}
+ if vdu.get("cloud_init"):
+ cloud_config_vm.pop("user-data", None)
+ cloud_config_vm_ = unify_cloud_config(cloud_config_vm, {"user-data": vdu["cloud_init"][index]})
+ task_params_copy[6] = cloud_config_vm_
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 iface.get("ip_address"):
+ iface["ip_address"] = increment_ip_mac(iface.get("ip_address"), index+1)
+ if iface.get("mac_address"):
+ iface["mac_address"] = increment_ip_mac(iface.get("mac_address"), index+1)
+
if vm_name:
task_params_copy[0] = vm_name
db_vim_action = {
action_dict['add_public_key'],
password=password, ro_key=priv_RO_key)
vm_result[ vm['uuid'] ] = {"vim_result": 200,
- "description": "Public key injected",
- "name":vm['name']
+ "description": "Public key injected",
+ "name":vm['name']
}
-
except KeyError:
raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
httperrors.Internal_Server_Error)
else:
vm_result[ vm['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm['name']}
vm_ok +=1
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
vm_error+=1
datacenter_type = datacenter_descriptor.get("type", "openvim");
# module_info = None
+ for url_field in ('vim_url', 'vim_url_admin'):
+ # It is common that users copy and paste the URL from the VIM website
+ # (example OpenStack), therefore a common mistake is to include blank
+ # characters at the end of the URL. Let's remove it and just in case,
+ # lets remove trailing slash as well.
+ url = datacenter_descriptor.get(url_field)
+ if url:
+ datacenter_descriptor[url_field] = url.strip(string.whitespace + '/')
+
# load plugin
plugin_name = "rovim_" + datacenter_type
if plugin_name not in plugins:
- _load_vim_plugin(plugin_name)
+ _load_plugin(plugin_name, type="vim")
datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True, confidential_data=True)
if sdn_port_mapping:
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):
+ global plugins
# get datacenter info
try:
if not datacenter_id:
if not vim_id:
raise NfvoException("You must provide 'vim_id", http_code=httperrors.Bad_Request)
datacenter_id = vim_id
- datacenter_id, datacenter_name = get_datacenter_uuid(mydb, None, datacenter_id)
+ datacenter_id, datacenter = get_datacenter_uuid(mydb, None, datacenter_id)
+ datacenter_name = datacenter["name"]
+ datacenter_type = datacenter["type"]
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']
+ if vim_tenant_name is None:
+ vim_tenant_name = tenant_dict['name']
- tenants_datacenter_dict={"nfvo_tenant_id":tenant_dict['uuid'], "datacenter_id":datacenter_id }
+ tenants_datacenter_dict = {"nfvo_tenant_id": tenant_dict['uuid'], "datacenter_id": datacenter_id}
# #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']), httperrors.Conflict)
+ # raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(
+ # datacenter_id, tenant_dict['uuid']), httperrors.Conflict)
- vim_tenant_id_exist_atdb=False
+ vim_tenant_id_exist_atdb = False
if not create_vim_tenant:
where_={"datacenter_id": datacenter_id}
- if vim_tenant!=None:
+ if vim_tenant is not None:
where_["vim_tenant_id"] = vim_tenant
- if vim_tenant_name!=None:
+ if vim_tenant_name is not None:
where_["vim_tenant_name"] = vim_tenant_name
- #check if vim_tenant_id is already at database
+ # check if vim_tenant_id is already at database
datacenter_tenants_dict = mydb.get_rows(FROM='datacenter_tenants', WHERE=where_)
- if len(datacenter_tenants_dict)>=1:
+ if len(datacenter_tenants_dict) >= 1:
datacenter_tenants_dict = datacenter_tenants_dict[0]
- vim_tenant_id_exist_atdb=True
- #TODO check if a field has changed and edit entry at datacenter_tenants at DB
- else: #result=0
+ vim_tenant_id_exist_atdb = True
+ # TODO check if a field has changed and edit entry at datacenter_tenants at DB
+ else: # result=0
datacenter_tenants_dict = {}
- #insert at table datacenter_tenants
- else: #if vim_tenant==None:
- #create tenant at VIM if not provided
+ # insert at table datacenter_tenants
+ 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)
+ _, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter_id, vim_user=vim_username,
+ vim_passwd=vim_password)
datacenter_name = myvim["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)), httperrors.Internal_Server_Error)
- datacenter_tenants_dict = {}
- datacenter_tenants_dict["created"]="true"
+ except vimconn.VimConnException as e:
+ raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_name, e),
+ httperrors.Internal_Server_Error)
+ datacenter_tenants_dict = {"created": "true"}
- #fill datacenter_tenants table
+ # fill datacenter_tenants table
if not vim_tenant_id_exist_atdb:
datacenter_tenants_dict["vim_tenant_id"] = vim_tenant
datacenter_tenants_dict["vim_tenant_name"] = vim_tenant_name
id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, add_uuid=True, confidential_data=True)
datacenter_tenants_dict["uuid"] = id_
- #fill tenants_datacenters table
+ # fill tenants_datacenters table
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
- thread_name = get_non_used_vim_name(datacenter_name, datacenter_id, tenant_dict['name'], tenant_dict['uuid'])
- new_thread = vim_thread(task_lock, plugins, thread_name, datacenter_name, datacenter_tenant_id,
- db=db, db_lock=db_lock, ovim=ovim)
+ # load plugin and create thread
+ plugin_name = "rovim_" + datacenter_type
+ if plugin_name not in plugins:
+ _load_plugin(plugin_name, type="vim")
+ thread_name = get_non_used_vim_name(datacenter_name, datacenter_id)
+ new_thread = vim_thread(task_lock, plugins, thread_name, None, datacenter_tenant_id, db=db)
new_thread.start()
thread_id = datacenter_tenants_dict["uuid"]
vim_threads["running"][thread_id] = new_thread
return thread_id
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
raise NfvoException(str(e), httperrors.Bad_Request)
if config:
original_config_dict = yaml.load(original_config, Loader=yaml.Loader)
original_config_dict.update(config)
- update["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256)
+ update_["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256)
if name:
update_['name'] = name
if vim_tenant:
try:
datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
myvim.delete_tenant(vim_tenant_dict['vim_tenant_id'])
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
warning = "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict['vim_tenant_id'], str(e))
logger.warn(warning)
except db_base_Exception as e:
if 'check-connectivity' in action_dict:
try:
myvim.check_vim_connectivity()
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
#logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
raise NfvoException(str(e), e.http_code)
elif 'net-update' in action_dict:
try:
nets = myvim.get_network_list(filter_dict={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
#print content
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
#logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
raise NfvoException(str(e), httperrors.Internal_Server_Error)
#update nets Change from VIM format to NFVO format
try:
vim_nets = myvim.get_network_list(filter_dict=filter_dict)
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
#logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
raise NfvoException(str(e), httperrors.Internal_Server_Error)
if len(vim_nets)>1 and action_dict:
datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
network = myvim.get_network_list(filter_dict=filter_dict)
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e)), e.http_code)
# ensure the network is defined
datacenter)
else:
return {item: content}
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
print("vim_action Not possible to get_{}_list from VIM: {} ".format(item, str(e)))
raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item, str(e)), e.http_code)
content = myvim.delete_image(item_id)
else:
raise NfvoException(item + "?", httperrors.Method_Not_Allowed)
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
#logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item, name, str(e)), e.http_code)
net_public = net.pop("shared", False)
net_ipprofile = net.pop("ip_profile", None)
net_vlan = net.pop("vlan", None)
- content, _ = myvim.new_network(net_name, net_type, net_ipprofile, shared=net_public, vlan=net_vlan) #, **net)
+ net_provider_network_profile = None
+ if net_vlan:
+ net_provider_network_profile = {"segmentation-id": net_vlan}
+ content, _ = myvim.new_network(net_name, net_type, net_ipprofile, shared=net_public, provider_network_profile=net_provider_network_profile) #, **net)
#If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
if get_sdn_controller_id(mydb, datacenter) != None and (net_type == 'data' or net_type == 'ptp'):
content = myvim.new_tenant(tenant["name"], tenant.get("description"))
else:
raise NfvoException(item + "?", httperrors.Method_Not_Allowed)
- except vimconn.vimconnException as e:
+ except vimconn.VimConnException as e:
raise NfvoException("Not possible to create {} at VIM: {}".format(item, str(e)), e.http_code)
return vim_action_get(mydb, tenant_id, datacenter, item, content)
def sdn_controller_create(mydb, tenant_id, sdn_controller):
- data = ovim.new_of_controller(sdn_controller)
- logger.debug('New SDN controller created with uuid {}'.format(data))
- return data
+ try:
+ wim_id = ovim.new_of_controller(sdn_controller)
+
+ # Load plugin if not previously loaded
+ controller_type = sdn_controller.get("type")
+ plugin_name = "rosdn_" + controller_type
+ if plugin_name not in plugins:
+ _load_plugin(plugin_name, type="sdn")
+
+ thread_name = get_non_used_vim_name(sdn_controller['name'], wim_id)
+ new_thread = vim_thread(task_lock, plugins, thread_name, wim_id, None, db=db)
+ new_thread.start()
+ thread_id = wim_id
+ vim_threads["running"][thread_id] = new_thread
+ logger.debug('New SDN controller created with uuid {}'.format(wim_id))
+ return wim_id
+ except ovimException as e:
+ raise NfvoException(e) from e
def sdn_controller_update(mydb, tenant_id, controller_id, sdn_controller):
data = ovim.edit_of_controller(controller_id, sdn_controller)
msg = 'SDN controller {} updated'.format(data)
+ vim_threads["running"][controller_id].insert_task("reload")
logger.debug(msg)
return msg
#element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
element = dict()
element["compute_node"] = compute_node["compute_node"]
- for port in compute_node["ports"]:
- pci = port.get("pci")
- element["switch_port"] = port.get("switch_port")
- element["switch_mac"] = port.get("switch_mac")
- if not element["switch_port"] and not element["switch_mac"]:
- raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors.Bad_Request)
- for pci_expanded in utils.expand_brackets(pci):
- element["pci"] = pci_expanded
- maps.append(dict(element))
-
- return ovim.set_of_port_mapping(maps, ofc_id=sdn_controller_id, switch_dpid=switch_dpid, region=datacenter_id)
+ if compute_node["ports"]:
+ for port in compute_node["ports"]:
+ pci = port.get("pci")
+ element["switch_port"] = port.get("switch_port")
+ element["switch_mac"] = port.get("switch_mac")
+ element["switch_dpid"] = port.get("switch_dpid")
+ element["switch_id"] = port.get("switch_id")
+ if not element["switch_port"] and not element["switch_mac"]:
+ raise NfvoException ("The mapping must contain 'switch_port' or 'switch_mac'", httperrors.Bad_Request)
+ for pci_expanded in utils.expand_brackets(pci):
+ element["pci"] = pci_expanded
+ maps.append(dict(element))
+
+ out = ovim.set_of_port_mapping(maps, sdn_id=sdn_controller_id, switch_dpid=switch_dpid, vim_id=datacenter_id)
+ vim_threads["running"][sdn_controller_id].insert_task("reload")
+ return out
def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id):
- maps = ovim.get_of_port_mappings(db_filter={"region": datacenter_id})
+ maps = ovim.get_of_port_mappings(db_filter={"datacenter_id": datacenter_id})
result = {
"sdn-controller": None,
ports_correspondence_dict = dict()
for link in maps:
- if result["sdn-controller"] != link["ofc_id"]:
+ if result["sdn-controller"] != link["wim_id"]:
raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors.Internal_Server_Error)
if result["dpid"] != link["switch_dpid"]:
raise NfvoException("The dpid specified for different port mappings differ", httperrors.Internal_Server_Error)
+ link_config = link["service_mapping_info"]
element = dict()
- element["pci"] = link["pci"]
+ element["pci"] = link.get("device_interface_id")
if link["switch_port"]:
element["switch_port"] = link["switch_port"]
- if link["switch_mac"]:
- element["switch_mac"] = link["switch_mac"]
+ if link_config["switch_mac"]:
+ element["switch_mac"] = link_config.get("switch_mac")
- if not link["compute_node"] in ports_correspondence_dict:
+ if not link.get("interface_id") in ports_correspondence_dict:
content = dict()
- content["compute_node"] = link["compute_node"]
+ content["compute_node"] = link.get("interface_id")
content["ports"] = list()
- ports_correspondence_dict[link["compute_node"]] = content
+ ports_correspondence_dict[link.get("interface_id")] = content
- ports_correspondence_dict[link["compute_node"]]["ports"].append(element)
+ ports_correspondence_dict[link["interface_id"]]["ports"].append(element)
for key in sorted(ports_correspondence_dict):
result["ports_mapping"].append(ports_correspondence_dict[key])
return result
def datacenter_sdn_port_mapping_delete(mydb, tenant_id, datacenter_id):
- return ovim.clear_of_port_mapping(db_filter={"region":datacenter_id})
+ return ovim.clear_of_port_mapping(db_filter={"datacenter_id":datacenter_id})
def create_RO_keypair(tenant_id):
"""
private_key = key.exportKey(passphrase=tenant_id, pkcs=8)
except (ValueError, NameError) as e:
raise NfvoException("Unable to create private key: {}".format(e), httperrors.Internal_Server_Error)
+ if isinstance(public_key, bytes):
+ public_key = public_key.decode(encoding='UTF-8')
+ if isinstance(private_key, bytes):
+ private_key = private_key.decode(encoding='UTF-8')
return public_key, private_key
def decrypt_key (key, tenant_id):
unencrypted_key = key.exportKey('PEM')
if isinstance(unencrypted_key, ValueError):
raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key), httperrors.Internal_Server_Error)
+ if isinstance(unencrypted_key, bytes):
+ unencrypted_key = unencrypted_key.decode(encoding='UTF-8')
except ValueError as e:
raise NfvoException("Unable to decrypt the private key: {}".format(e), httperrors.Internal_Server_Error)
return unencrypted_key