# 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
# WIM
from .wim import sdnconn
-from .wim.wimconn_fake import FakeConnector
+from .wim.wimconn_dummy import DummyConnector
from .wim.failing_connector import FailingConnector
from .http_tools import errors as httperrors
from .wim.engine import WimEngine
db = None
db_lock = Lock()
+worker_id = None
class NfvoException(httperrors.HttpMappedError):
"""Common Class for NFVO errors"""
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:
+ text_id_ = f.readline()
+ _, _, 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, ovim
+ 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'])
persistence = persistence or WimPersistence(db)
try:
- if "rosdn_fake" not in plugins:
- plugins["rosdn_fake"] = FakeConnector
+ worker_id = get_process_id()
+ if "rosdn_dummy" not in plugins:
+ plugins["rosdn_dummy"] = DummyConnector
# starts ovim library
ovim = Sdn(db, plugins)
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'], vim['vim_tenant_name'],
- vim['vim_tenant_id'])
+ 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()
_load_plugin(plugin_name, type="sdn")
thread_id = wim['uuid']
- thread_name = get_non_used_vim_name(wim['name'], wim['uuid'], wim['uuid'], None)
+ 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
# 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"]
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":
db_interface["port_security"] = 0
elif vld.get("vim-network-name"):
db_sce_net["vim_network_name"] = get_str(vld, "vim-network-name", 255)
-
# 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
"'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],
"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"
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",),
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:
+ 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
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)
+ 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']:
"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",
"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,
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.
"created": True, # TODO py3
"sdn": True,
})
+ vnf_net2wim_instance[net_uuid] = sdn_net_id
db_net = {
"uuid": net_uuid,
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:
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:
+ try:
+ i = ip.rfind(".")
+ if i > 0:
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
+ 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
"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)
"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)
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:
+ if iface.get("ip_address"):
+ try:
+ ip = iface["ip_address"]
+ i = ip.rfind(".")
+ if i > 0:
i += 1
ip = ip[i:] + str(int(ip[:i]) + 1)
iface["ip_address"] = ip
- except:
- iface["ip_address"] = None
+ except:
+ iface["ip_address"] = None
if vm_name:
task_params_copy[0] = vm_name
db_vim_action = {
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:
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'])
+ 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"]
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:
return vim_action_get(mydb, tenant_id, datacenter, item, content)
def sdn_controller_create(mydb, tenant_id, sdn_controller):
- wim_id = ovim.new_of_controller(sdn_controller)
+ 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, wim_id, None)
- 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
+ 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)
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):