Merge "Fixes bug #57"
[osm/RO.git] / nfvo.py
diff --git a/nfvo.py b/nfvo.py
index 98c4bbd..dd3eb55 100644 (file)
--- a/nfvo.py
+++ b/nfvo.py
@@ -41,10 +41,11 @@ from db_base import db_base_Exception
 
 global global_config
 global vimconn_imported
+global logger
 
 
 vimconn_imported={} #dictionary with VIM type as key, loaded module as value
-logger = logging.getLogger('mano.nfvo')
+logger = logging.getLogger('openmano.nfvo')
 
 class NfvoException(Exception):
     def __init__(self, message, http_code):
@@ -91,7 +92,7 @@ def get_imagelist(mydb, vnf_id, nfvo_tenant=None):
         imageList.append(image['image_id'])
     return imageList
 
-def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vim_tenant=None):
+def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vim_tenant=None, vim_tenant_name=None, vim_user=None, vim_passwd=None):
     '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
     return dictionary with {datacenter_id: vim_class, ... }. vim_class contain: 
             'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
@@ -135,9 +136,9 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vi
                 #    return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
                 vim_dict[ vim['datacenter_id'] ] = vimconn_imported[ vim["type"] ].vimconnector(
                                 uuid=vim['datacenter_id'], name=vim['datacenter_name'],
-                                tenant_id=vim.get('vim_tenant_id'), tenant_name=vim.get('vim_tenant_name'),
+                                tenant_id=vim.get('vim_tenant_id',vim_tenant), tenant_name=vim.get('vim_tenant_name',vim_tenant_name),
                                 url=vim['vim_url'], url_admin=vim['vim_url_admin'], 
-                                user=vim.get('user'), passwd=vim.get('passwd'),
+                                user=vim.get('user',vim_user), passwd=vim.get('passwd',vim_passwd),
                                 config=extra
                         )
             except Exception as e:
@@ -952,6 +953,7 @@ def new_scenario(mydb, tenant_id, topo):
 #1.4 get list of connections
     conections = topo['topology']['connections']
     conections_list = []
+    conections_list_name = []
     for k in conections.keys():
         if type(conections[k]['nodes'])==dict: #dict with node:iface pairs
             ifaces_list = conections[k]['nodes'].items()
@@ -980,7 +982,7 @@ def new_scenario(mydb, tenant_id, topo):
         if con_type == "dataplane_net" or con_type == "bridge_net": 
             other_nets[k]["model"] = con_type
         
-        
+        conections_list_name.append(k)
         conections_list.append(set(ifaces_list)) #from list to set to operate as a set (this conversion removes elements that are repeated in a list)
         #print set(ifaces_list)
     #check valid VNF and iface names
@@ -1000,6 +1002,7 @@ def new_scenario(mydb, tenant_id, topo):
             if len(conections_list[index] & conections_list[index2])>0: #common interface, join nets
                 conections_list[index] |= conections_list[index2]
                 del conections_list[index2]
+                del conections_list_name[index2]
             else:
                 index2 += 1
         conections_list[index] = list(conections_list[index])  # from set to list again
@@ -1106,7 +1109,8 @@ def new_scenario(mydb, tenant_id, topo):
                 net_type_bridge=False
                 net_type_data=False
                 net_target = "__-__net"+str(net_nb)
-                net_list[net_target] = {'name': "net-"+str(net_nb), 'description':"net-%s in scenario %s" %(net_nb,topo['name']),
+                net_list[net_target] = {'name': conections_list_name[net_nb],  #"net-"+str(net_nb), 
+                    'description':"net-%s in scenario %s" %(net_nb,topo['name']),
                     'external':False} 
                 for iface in con:
                     vnfs[ iface[0] ]['ifaces'][ iface[1] ]['net_key'] = net_target
@@ -1182,7 +1186,7 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
         where={}
         where_or={"tenant_id": tenant_id, 'public': "true"}
         error_text = ""
-        error_pos = "'topology':'nodes':'" + name + "'"
+        error_pos = "'scenario':'vnfs':'" + name + "'"
         if 'vnf_id' in vnf:
             error_text += " 'vnf_id' " +  vnf['vnf_id']
             where['uuid'] = vnf['vnf_id']
@@ -1190,7 +1194,7 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
             error_text += " 'vnf_name' " +  vnf['vnf_name']
             where['name'] = vnf['vnf_name']
         if len(where) == 0:
-            raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos, HTTP_Bad_Request)
+            raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos, HTTP_Bad_Request)
         vnf_db = mydb.get_rows(SELECT=('uuid','name','description'),
                                FROM='vnfs',
                                WHERE=where,
@@ -1316,6 +1320,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 sce_net['vim_id'] = network_id
                 auxNetDict['scenario'][sce_net['uuid']] = network_id
                 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
+                sce_net["created"] = True
             else:
                 if sce_net['vim_id'] == None:
                     error_text = "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name, sce_net['name'])
@@ -1349,6 +1354,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                     auxNetDict[sce_vnf['uuid']] = {}
                 auxNetDict[sce_vnf['uuid']][net['uuid']] = network_id
                 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
+                net["created"] = True
     
         #print "auxNetDict:"
         #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
@@ -1521,7 +1527,7 @@ def new_scenario_v03(mydb, tenant_id, scenario_dict):
         where={}
         where_or={"tenant_id": tenant_id, 'public': "true"}
         error_text = ""
-        error_pos = "'topology':'nodes':'" + name + "'"
+        error_pos = "'scenario':'vnfs':'" + name + "'"
         if 'vnf_id' in vnf:
             error_text += " 'vnf_id' " +  vnf['vnf_id']
             where['uuid'] = vnf['vnf_id']
@@ -1529,7 +1535,7 @@ def new_scenario_v03(mydb, tenant_id, scenario_dict):
             error_text += " 'vnf_name' " +  vnf['vnf_name']
             where['name'] = vnf['vnf_name']
         if len(where) == 0:
-            raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos, HTTP_Bad_Request)
+            raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos, HTTP_Bad_Request)
         vnf_db = mydb.get_rows(SELECT=('uuid','name','description'),
                                FROM='vnfs',
                                WHERE=where,
@@ -1726,7 +1732,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                             ipprofile['dhcp_count'] = ipprofile['dhcp'].get('count',None)
                             del ipprofile['dhcp']
                         update(scenario_net['ip_profile'],ipprofile)
-            for interface in net_instance_desc['interfaces']:
+            for interface in net_instance_desc.get('interfaces', () ):
                 if 'ip_address' in interface:
                     for vnf in scenarioDict['vnfs']:
                         if interface['vnf'] == vnf['name']:
@@ -1816,6 +1822,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                     sce_net["vim_id_sites"][datacenter_id] = network_id
                     auxNetDict['scenario'][sce_net['uuid']][datacenter_id] = network_id
                     rollbackList.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id, 'uuid':network_id})
+                    sce_net["created"] = True
         
     #2. Creating new nets (vnf internal nets) in the VIM"
         #For each vnf net, we create it and we add it to instanceNetlist.
@@ -1839,6 +1846,8 @@ def create_instance(mydb, tenant_id, instance_dict):
                     auxNetDict[sce_vnf['uuid']] = {}
                 auxNetDict[sce_vnf['uuid']][net['uuid']] = network_id
                 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':network_id})
+                net["created"] = True
+
     
         #print "auxNetDict:"
         #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
@@ -2010,7 +2019,7 @@ def delete_instance(mydb, tenant_id, instance_id):
     #2.2 deleting NETS
     #net_fail_list=[]
     for net in instanceDict['nets']:
-        if net['external']:
+        if not net['created']:
             continue #skip not created nets
         if not myvim:
             continue
@@ -2076,7 +2085,7 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
                     if iface["type"]=="mgmt":
                         has_mgmt_iface = True
                 if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
-                        vm_dict[vm_id]['status'] = "ACTIVE"
+                    vm_dict[vm_id]['status'] = "ACTIVE"
                 if vm['status'] != vm_dict[vm_id]['status'] or vm.get('error_msg')!=vm_dict[vm_id].get('error_msg') or vm.get('vim_info')!=vm_dict[vm_id].get('vim_info'):
                     vm['status']    = vm_dict[vm_id]['status']
                     vm['error_msg'] = vm_dict[vm_id].get('error_msg')
@@ -2092,16 +2101,16 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
                 # 2.2. Update in openmano DB the interface VMs
                 for interface in interfaces:
                     #translate from vim_net_id to instance_net_id
-                    network_id=None
+                    network_id_list=[]
                     for net in instanceDict['nets']:
                         if net["vim_net_id"] == interface["vim_net_id"]:
-                            network_id = net["uuid"]
-                            break
-                    if not network_id:
+                            network_id_list.append(net["uuid"])
+                    if not network_id_list:
                         continue
                     del interface["vim_net_id"]
-                    try: 
-                        mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
+                    try:
+                        for network_id in network_id_list:
+                            mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
                     except db_base_Exception as e:
                         logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)        
         
@@ -2256,6 +2265,17 @@ def delete_tenant(mydb, tenant):
 def new_datacenter(mydb, datacenter_descriptor):
     if "config" in datacenter_descriptor:
         datacenter_descriptor["config"]=yaml.safe_dump(datacenter_descriptor["config"],default_flow_style=True,width=256)
+    #Check that datacenter-type is correct
+    datacenter_type = datacenter_descriptor.get("type", "openvim");
+    module_info = None
+    try:
+        module = "vimconn_" + datacenter_type
+        module_info = imp.find_module(module)
+    except (IOError, ImportError):
+        if module_info and module_info[0]:
+            file.close(module_info[0])
+        raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type, module), HTTP_Bad_Request)
+    
     datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True)
     return datacenter_id
 
@@ -2295,9 +2315,9 @@ def delete_datacenter(mydb, datacenter):
 def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=None, vim_tenant_name=None, vim_username=None, vim_password=None):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        vims = get_vim(mydb, datacenter_id=datacenter)
+        vims = get_vim(mydb, datacenter_id=datacenter, vim_tenant_name=vim_tenant_name, vim_user=vim_username, vim_passwd=vim_password)
     else:
-        vims = get_vim(mydb, datacenter_name=datacenter)
+        vims = get_vim(mydb, datacenter_name=datacenter, vim_tenant_name=vim_tenant_name, vim_user=vim_username, vim_passwd=vim_password)
     if len(vims) == 0:
         raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_Found)
     elif len(vims)>1: