VCD feature 7193-provider_nerwork
[osm/RO.git] / osm_ro / nfvo.py
index 6ce8cd0..8637245 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 ##
 # -*- coding: utf-8 -*-
 
 ##
-# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
 # This file is part of openmano
 # All Rights Reserved.
 #
 # This file is part of openmano
 # All Rights Reserved.
 #
@@ -20,7 +20,7 @@
 # For those usages not covered by the Apache License, Version 2.0 please
 # contact with: nfvlabs@tid.es
 ##
 # 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
 '''
 '''
 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
 '''
@@ -28,16 +28,16 @@ __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
 __date__ ="$16-sep-2014 22:05:01$"
 
 # import imp
 __date__ ="$16-sep-2014 22:05:01$"
 
 # import imp
-import json
+import json
 import yaml
 import utils
 import yaml
 import utils
+from utils import deprecated
 import vim_thread
 import vim_thread
-from db_base import HTTP_Unauthorized, HTTP_Bad_Request, HTTP_Internal_Server_Error, HTTP_Not_Found,\
-    HTTP_Conflict, HTTP_Method_Not_Allowed
 import console_proxy_thread as cli
 import vimconn
 import logging
 import collections
 import console_proxy_thread as cli
 import vimconn
 import logging
 import collections
+import math
 from uuid import uuid4
 from db_base import db_base_Exception
 
 from uuid import uuid4
 from db_base import db_base_Exception
 
@@ -51,10 +51,26 @@ from Crypto.PublicKey import RSA
 import osm_im.vnfd as vnfd_catalog
 import osm_im.nsd as nsd_catalog
 from pyangbind.lib.serialise import pybindJSONDecoder
 import osm_im.vnfd as vnfd_catalog
 import osm_im.nsd as nsd_catalog
 from pyangbind.lib.serialise import pybindJSONDecoder
-from itertools import chain
+from copy import deepcopy
+
+
+# WIM
+import wim.wimconn as wimconn
+import wim.wim_thread as wim_thread
+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
+#
 
 global global_config
 global vimconn_imported
 
 global global_config
 global vimconn_imported
+# WIM
+global wim_engine
+wim_engine  = None
+global wimconn_imported
+#
 global logger
 global default_volume_size
 default_volume_size = '5' #size in GB
 global logger
 global default_volume_size
 default_volume_size = '5' #size in GB
@@ -65,16 +81,21 @@ global_config = None
 vimconn_imported = {}   # dictionary with VIM type as key, loaded module as value
 vim_threads = {"running":{}, "deleting": {}, "names": []}      # threads running for attached-VIMs
 vim_persistent_info = {}
 vimconn_imported = {}   # dictionary with VIM type as key, loaded module as value
 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
+wim_threads = {"running":{}, "deleting": {}, "names": []}      # threads running for attached-WIMs
+wim_persistent_info = {}
+#
+
 logger = logging.getLogger('openmano.nfvo')
 task_lock = Lock()
 last_task_id = 0.0
 db = None
 db_lock = Lock()
 
 logger = logging.getLogger('openmano.nfvo')
 task_lock = Lock()
 last_task_id = 0.0
 db = None
 db_lock = Lock()
 
-class NfvoException(Exception):
-    def __init__(self, message, http_code):
-        self.http_code = http_code
-        Exception.__init__(self, message)
+
+class NfvoException(httperrors.HttpMappedError):
+    """Common Class for NFVO errors"""
 
 
 def get_task_id():
 
 
 def get_task_id():
@@ -105,21 +126,39 @@ def get_non_used_vim_name(datacenter_name, datacenter_id, tenant_name, tenant_id
     if name not in vim_threads["names"]:
         vim_threads["names"].append(name)
         return name
     if name not in vim_threads["names"]:
         vim_threads["names"].append(name)
         return 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 + "-" + tenant_id
+    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
 
     vim_threads["names"].append(name)
     return name
 
+# -- Move
+def get_non_used_wim_name(wim_name, wim_id, tenant_name, tenant_id):
+    name = wim_name[:16]
+    if name not in wim_threads["names"]:
+        wim_threads["names"].append(name)
+        return name
+    name = wim_name[:16] + "." + tenant_name[:16]
+    if name not in wim_threads["names"]:
+        wim_threads["names"].append(name)
+        return name
+    name = wim_id + "-" + tenant_id
+    wim_threads["names"].append(name)
+    return name
+
 
 
-def start_service(mydb):
+def start_service(mydb, persistence=None, wim=None):
     global db, global_config
     global db, global_config
-    db = nfvo_db.nfvo_db()
+    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
 
     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
     # 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
@@ -138,9 +177,19 @@ def start_service(mydb):
         'log_level_of': 'DEBUG'
     }
     try:
         'log_level_of': 'DEBUG'
     }
     try:
+        # starts ovim library
         ovim = ovim_module.ovim(ovim_configuration)
         ovim = ovim_module.ovim(ovim_configuration)
+
+        global wim_engine
+        wim_engine = wim or WimEngine(persistence)
+        wim_engine.ovim = ovim
+
         ovim.start_service()
 
         ovim.start_service()
 
+        #delete old unneeded vim_wim_actions
+        clean_db(mydb)
+
+        # starts vim_threads
         from_= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
                 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
         select_ = ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
         from_= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
                 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
         select_ = ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
@@ -168,13 +217,13 @@ def start_service(mydb):
                     # if module_info and module_info[0]:
                     #    file.close(module_info[0])
                     raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
                     # if module_info and module_info[0]:
                     #    file.close(module_info[0])
                     raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
-                        vim["type"], module, type(e).__name__, str(e)), HTTP_Bad_Request)
+                        vim["type"], module, type(e).__name__, str(e)), httperrors.Bad_Request)
 
             thread_id = vim['datacenter_tenant_id']
             vim_persistent_info[thread_id] = {}
             try:
                 #if not tenant:
 
             thread_id = vim['datacenter_tenant_id']
             vim_persistent_info[thread_id] = {}
             try:
                 #if not tenant:
-                #    return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
+                #    return -httperrors.Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
                 myvim = vimconn_imported[ vim["type"] ].vimconnector(
                     uuid=vim['datacenter_id'], name=vim['datacenter_name'],
                     tenant_id=vim['vim_tenant_id'], tenant_name=vim['vim_tenant_name'],
                 myvim = vimconn_imported[ vim["type"] ].vimconnector(
                     uuid=vim['datacenter_id'], name=vim['datacenter_name'],
                     tenant_id=vim['vim_tenant_id'], tenant_name=vim['vim_tenant_name'],
@@ -182,15 +231,21 @@ def start_service(mydb):
                     user=vim['user'], passwd=vim['passwd'],
                     config=extra, persistent_info=vim_persistent_info[thread_id]
                 )
                     user=vim['user'], passwd=vim['passwd'],
                     config=extra, persistent_info=vim_persistent_info[thread_id]
                 )
+            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),
             except Exception as e:
                 raise NfvoException("Error at VIM  {}; {}: {}".format(vim["type"], type(e).__name__, e),
-                                    HTTP_Internal_Server_Error)
-            thread_name = get_non_used_vim_name(vim['datacenter_name'], vim['vim_tenant_id'], vim['vim_tenant_name'],
+                                    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'])
                                                 vim['vim_tenant_id'])
-            new_thread = vim_thread.vim_thread(myvim, task_lock, thread_name, vim['datacenter_name'],
+            new_thread = vim_thread.vim_thread(task_lock, thread_name, vim['datacenter_name'],
                                                vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim)
             new_thread.start()
             vim_threads["running"][thread_id] = new_thread
                                                vim['datacenter_tenant_id'], db=db, db_lock=db_lock, ovim=ovim)
             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 db_base_Exception as e:
         raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code)
     except ovim_module.ovimException as e:
@@ -201,17 +256,21 @@ def start_service(mydb):
                             msg=message[22:-3], dbname=global_config["db_ovim_name"],
                             dbuser=global_config["db_ovim_user"], dbpass=global_config["db_ovim_passwd"],
                             ver=message[-3:-1], dbhost=global_config["db_ovim_host"])
                             msg=message[22:-3], dbname=global_config["db_ovim_name"],
                             dbuser=global_config["db_ovim_user"], dbpass=global_config["db_ovim_passwd"],
                             ver=message[-3:-1], dbhost=global_config["db_ovim_host"])
-        raise NfvoException(message, HTTP_Bad_Request)
+        raise NfvoException(message, httperrors.Bad_Request)
 
 
 def stop_service():
     global ovim, global_config
     if ovim:
         ovim.stop_service()
 
 
 def stop_service():
     global ovim, global_config
     if ovim:
         ovim.stop_service()
-    for thread_id,thread in vim_threads["running"].items():
+    for thread_id, thread in vim_threads["running"].items():
         thread.insert_task("exit")
         vim_threads["deleting"][thread_id] = thread
     vim_threads["running"] = {}
         thread.insert_task("exit")
         vim_threads["deleting"][thread_id] = thread
     vim_threads["running"] = {}
+
+    if wim_engine:
+        wim_engine.stop_threads()
+
     if global_config and global_config.get("console_thread"):
         for thread in global_config["console_thread"]:
             thread.terminate = True
     if global_config and global_config.get("console_thread"):
         for thread in global_config["console_thread"]:
             thread.terminate = True
@@ -220,6 +279,39 @@ def get_version():
     return  ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config["version"],
                                                                         global_config["version_date"] ))
 
     return  ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config["version"],
                                                                         global_config["version_date"] ))
 
+def clean_db(mydb):
+    """
+    Clean unused or old entries at database to avoid unlimited growing
+    :param mydb: database connector
+    :return: None
+    """
+    # get and delete unused vim_wim_actions: all elements deleted, one week before, instance not present
+    now = t.time()-3600*24*7
+    instance_action_id = None
+    nb_deleted = 0
+    while True:
+        actions_to_delete = mydb.get_rows(
+            SELECT=("item", "item_id", "instance_action_id"),
+            FROM="vim_wim_actions as va join instance_actions as ia on va.instance_action_id=ia.uuid "
+                    "left join instance_scenarios as i on ia.instance_id=i.uuid",
+            WHERE={"va.action": "DELETE", "va.modified_at<": now, "i.uuid": None,
+                   "va.status": ("DONE", "SUPERSEDED")},
+            LIMIT=100
+        )
+        for to_delete in actions_to_delete:
+            mydb.delete_row(FROM="vim_wim_actions", WHERE=to_delete)
+            if instance_action_id != to_delete["instance_action_id"]:
+                instance_action_id = to_delete["instance_action_id"]
+                mydb.delete_row(FROM="instance_actions", WHERE={"uuid": instance_action_id})
+        nb_deleted += len(actions_to_delete)
+        if len(actions_to_delete) < 100:
+            break
+    # clean locks
+    mydb.update_rows("vim_wim_actions", UPDATE={"worker": None}, WHERE={"worker<>": None})
+
+    if nb_deleted:
+        logger.debug("Removed {} unused vim_wim_actions".format(nb_deleted))
+
 
 def get_flavorlist(mydb, vnf_id, nfvo_tenant=None):
     '''Obtain flavorList
 
 def get_flavorlist(mydb, vnf_id, nfvo_tenant=None):
     '''Obtain flavorList
@@ -244,26 +336,28 @@ def get_flavorlist(mydb, vnf_id, nfvo_tenant=None):
 
 
 def get_imagelist(mydb, vnf_id, nfvo_tenant=None):
 
 
 def get_imagelist(mydb, vnf_id, nfvo_tenant=None):
-    '''Obtain imageList
-    return result, content:
-        <0, error_text upon error
-        nb_records, flavor_list on success
-    '''
-    WHERE_dict={}
-    WHERE_dict['vnf_id'] = vnf_id
-    if nfvo_tenant is not None:
-        WHERE_dict['nfvo_tenant_id'] = nfvo_tenant
-
-    #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
-    images = mydb.get_rows(FROM='vms join images on vms.image_id=images.uuid',SELECT=('image_id',),WHERE=WHERE_dict )
-    imageList=[]
-    for image in images:
-        imageList.append(image['image_id'])
-    return imageList
+    """
+    Get used images of all vms belonging to this VNFD
+    :param mydb: database conector
+    :param vnf_id: vnfd uuid
+    :param nfvo_tenant: tenant, not used
+    :return: The list of image uuid used
+    """
+    image_list = []
+    vms = mydb.get_rows(SELECT=('image_id','image_list'), FROM='vms', WHERE={'vnf_id': vnf_id})
+    for vm in vms:
+        if vm["image_id"] and vm["image_id"] not in image_list:
+            image_list.append(vm["image_id"])
+        if vm["image_list"]:
+            vm_image_list = yaml.load(vm["image_list"])
+            for image_dict in vm_image_list:
+                if image_dict["image_id"] not in image_list:
+                    image_list.append(image_dict["image_id"])
+    return image_list
 
 
 def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, datacenter_tenant_id=None,
 
 
 def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, datacenter_tenant_id=None,
-            vim_tenant=None, vim_tenant_name=None, vim_user=None, vim_passwd=None):
+            vim_tenant=None, vim_tenant_name=None, vim_user=None, vim_passwd=None, ignore_errors=False):
     '''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'
     '''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'
@@ -289,7 +383,8 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, da
         vim_dict={}
         for vim in vims:
             extra={'datacenter_tenant_id': vim.get('datacenter_tenant_id'),
         vim_dict={}
         for vim in vims:
             extra={'datacenter_tenant_id': vim.get('datacenter_tenant_id'),
-                   'datacenter_id': vim.get('datacenter_id')}
+                   'datacenter_id': vim.get('datacenter_id'),
+                   '_vim_type_internal': vim.get('type')}
             if vim["config"]:
                 extra.update(yaml.load(vim["config"]))
             if vim.get('dt_config'):
             if vim["config"]:
                 extra.update(yaml.load(vim["config"]))
             if vim.get('dt_config'):
@@ -306,8 +401,12 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, da
                 except (IOError, ImportError) as e:
                     # if module_info and module_info[0]:
                     #     file.close(module_info[0])
                 except (IOError, ImportError) as e:
                     # if module_info and module_info[0]:
                     #     file.close(module_info[0])
+                    if ignore_errors:
+                        logger.error("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
+                                            vim["type"], module, type(e).__name__, str(e)))
+                        continue
                     raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
                     raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
-                                            vim["type"], module, type(e).__name__, str(e)), HTTP_Bad_Request)
+                                            vim["type"], module, type(e).__name__, str(e)), httperrors.Bad_Request)
 
             try:
                 if 'datacenter_tenant_id' in vim:
 
             try:
                 if 'datacenter_tenant_id' in vim:
@@ -318,7 +417,7 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, da
                 else:
                     persistent_info = {}
                 #if not tenant:
                 else:
                     persistent_info = {}
                 #if not tenant:
-                #    return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
+                #    return -httperrors.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',vim_tenant),
                 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',vim_tenant),
@@ -328,7 +427,13 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, da
                                 config=extra, persistent_info=persistent_info
                         )
             except Exception as e:
                                 config=extra, persistent_info=persistent_info
                         )
             except Exception as e:
-                raise NfvoException("Error at VIM  {}; {}: {}".format(vim["type"], type(e).__name__, str(e)), HTTP_Internal_Server_Error)
+                if ignore_errors:
+                    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):
+                    http_code = e.http_code
+                raise NfvoException("Error at VIM  {}; {}: {}".format(vim["type"], type(e).__name__, str(e)), http_code)
         return vim_dict
     except db_base_Exception as e:
         raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code)
         return vim_dict
     except db_base_Exception as e:
         raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code)
@@ -351,7 +456,7 @@ def rollback(mydb,  vims, rollback_list):
                     mydb.delete_row(FROM="datacenters_images", WHERE={"datacenter_vim_id": vim["id"], "vim_id":item["uuid"]})
                 elif item["what"]=="flavor":
                     vim.delete_flavor(item["uuid"])
                     mydb.delete_row(FROM="datacenters_images", WHERE={"datacenter_vim_id": vim["id"], "vim_id":item["uuid"]})
                 elif item["what"]=="flavor":
                     vim.delete_flavor(item["uuid"])
-                    mydb.delete_row(FROM="datacenters_flavors", WHERE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
+                    mydb.delete_row(FROM="datacenters_flavors", WHERE={"datacenter_vim_id": vim["id"], "vim_id":item["uuid"]})
                 elif item["what"]=="network":
                     vim.delete_network(item["uuid"])
                 elif item["what"]=="vm":
                 elif item["what"]=="network":
                     vim.delete_network(item["uuid"])
                 elif item["what"]=="vm":
@@ -390,7 +495,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                     raise NfvoException(
                         "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
                             vnfc["name"], interface["name"]),
                     raise NfvoException(
                         "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
                             vnfc["name"], interface["name"]),
-                        HTTP_Bad_Request)
+                        httperrors.Bad_Request)
                 name_dict[ interface["name"] ] = "underlay"
         #bridge interfaces
         for interface in vnfc.get("bridge-ifaces",() ):
                 name_dict[ interface["name"] ] = "underlay"
         #bridge interfaces
         for interface in vnfc.get("bridge-ifaces",() ):
@@ -398,7 +503,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                 raise NfvoException(
                     "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
                         vnfc["name"], interface["name"]),
                 raise NfvoException(
                     "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
                         vnfc["name"], interface["name"]),
-                    HTTP_Bad_Request)
+                    httperrors.Bad_Request)
             name_dict[ interface["name"] ] = "overlay"
         vnfc_interfaces[ vnfc["name"] ] = name_dict
         # check bood-data info
             name_dict[ interface["name"] ] = "overlay"
         vnfc_interfaces[ vnfc["name"] ] = name_dict
         # check bood-data info
@@ -407,7 +512,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
         #     if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
         #         raise NfvoException(
         #             "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
         #     if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
         #         raise NfvoException(
         #             "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
-        #             HTTP_Bad_Request)
+        #             httperrors.Bad_Request)
 
     #check if the info in external_connections matches with the one in the vnfcs
     name_list=[]
 
     #check if the info in external_connections matches with the one in the vnfcs
     name_list=[]
@@ -416,20 +521,20 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
             raise NfvoException(
                 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
                     external_connection["name"]),
             raise NfvoException(
                 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
                     external_connection["name"]),
-                HTTP_Bad_Request)
+                httperrors.Bad_Request)
         name_list.append(external_connection["name"])
         if external_connection["VNFC"] not in vnfc_interfaces:
             raise NfvoException(
                 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
                     external_connection["name"], external_connection["VNFC"]),
         name_list.append(external_connection["name"])
         if external_connection["VNFC"] not in vnfc_interfaces:
             raise NfvoException(
                 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
                     external_connection["name"], external_connection["VNFC"]),
-                HTTP_Bad_Request)
+                httperrors.Bad_Request)
 
         if external_connection["local_iface_name"] not in vnfc_interfaces[ external_connection["VNFC"] ]:
             raise NfvoException(
                 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
                     external_connection["name"],
                     external_connection["local_iface_name"]),
 
         if external_connection["local_iface_name"] not in vnfc_interfaces[ external_connection["VNFC"] ]:
             raise NfvoException(
                 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
                     external_connection["name"],
                     external_connection["local_iface_name"]),
-                HTTP_Bad_Request )
+                httperrors.Bad_Request )
 
     #check if the info in internal_connections matches with the one in the vnfcs
     name_list=[]
 
     #check if the info in internal_connections matches with the one in the vnfcs
     name_list=[]
@@ -438,7 +543,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
             raise NfvoException(
                 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
                     internal_connection["name"]),
             raise NfvoException(
                 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
                     internal_connection["name"]),
-                HTTP_Bad_Request)
+                httperrors.Bad_Request)
         name_list.append(internal_connection["name"])
         #We should check that internal-connections of type "ptp" have only 2 elements
 
         name_list.append(internal_connection["name"])
         #We should check that internal-connections of type "ptp" have only 2 elements
 
@@ -448,7 +553,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                     internal_connection["name"],
                     'ptp' if vnf_descriptor_version==1 else 'e-line',
                     'data' if vnf_descriptor_version==1 else "e-lan"),
                     internal_connection["name"],
                     'ptp' if vnf_descriptor_version==1 else 'e-line',
                     'data' if vnf_descriptor_version==1 else "e-lan"),
-                HTTP_Bad_Request)
+                httperrors.Bad_Request)
         for port in internal_connection["elements"]:
             vnf = port["VNFC"]
             iface = port["local_iface_name"]
         for port in internal_connection["elements"]:
             vnf = port["VNFC"]
             iface = port["local_iface_name"]
@@ -456,13 +561,13 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                 raise NfvoException(
                     "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
                         internal_connection["name"], vnf),
                 raise NfvoException(
                     "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
                         internal_connection["name"], vnf),
-                    HTTP_Bad_Request)
+                    httperrors.Bad_Request)
             if iface not in vnfc_interfaces[ vnf ]:
                 raise NfvoException(
                     "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
                         internal_connection["name"], iface),
             if iface not in vnfc_interfaces[ vnf ]:
                 raise NfvoException(
                     "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
                         internal_connection["name"], iface),
-                    HTTP_Bad_Request)
-                return -HTTP_Bad_Request,
+                    httperrors.Bad_Request)
+                return -httperrors.Bad_Request,
             if vnf_descriptor_version==1 and "type" not in internal_connection:
                 if vnfc_interfaces[vnf][iface] == "overlay":
                     internal_connection["type"] = "bridge"
             if vnf_descriptor_version==1 and "type" not in internal_connection:
                 if vnfc_interfaces[vnf][iface] == "overlay":
                     internal_connection["type"] = "bridge"
@@ -480,7 +585,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                         internal_connection["name"],
                         iface, 'bridge' if vnf_descriptor_version==1 else 'overlay',
                         'data' if vnf_descriptor_version==1 else 'underlay'),
                         internal_connection["name"],
                         iface, 'bridge' if vnf_descriptor_version==1 else 'overlay',
                         'data' if vnf_descriptor_version==1 else 'underlay'),
-                    HTTP_Bad_Request)
+                    httperrors.Bad_Request)
             if (internal_connection.get("type") == "bridge" or internal_connection.get("implementation") == "overlay") and \
                 vnfc_interfaces[vnf][iface] == "underlay":
                 raise NfvoException(
             if (internal_connection.get("type") == "bridge" or internal_connection.get("implementation") == "overlay") and \
                 vnfc_interfaces[vnf][iface] == "underlay":
                 raise NfvoException(
@@ -488,7 +593,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                         internal_connection["name"], iface,
                         'data' if vnf_descriptor_version==1 else 'underlay',
                         'bridge' if vnf_descriptor_version==1 else 'overlay'),
                         internal_connection["name"], iface,
                         'data' if vnf_descriptor_version==1 else 'underlay',
                         'bridge' if vnf_descriptor_version==1 else 'overlay'),
-                    HTTP_Bad_Request)
+                    httperrors.Bad_Request)
 
 
 def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error=None):
 
 
 def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error=None):
@@ -533,7 +638,7 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi
                 vim_images = vim.get_image_list(filter_dict)
                 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
                 if len(vim_images) > 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)), HTTP_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)))
                 else:
                 elif len(vim_images) == 0:
                     raise vimconn.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict)))
                 else:
@@ -580,7 +685,7 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi
 
 
 def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = None):
 
 
 def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = None):
-    temp_flavor_dict= {'disk':flavor_dict.get('disk',1),
+    temp_flavor_dict= {'disk':flavor_dict.get('disk',0),
             'ram':flavor_dict.get('ram'),
             'vcpus':flavor_dict.get('vcpus'),
         }
             'ram':flavor_dict.get('ram'),
             'vcpus':flavor_dict.get('vcpus'),
         }
@@ -666,8 +771,8 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
             for index in range(0,len(devices_original)) :
                 device=devices_original[index]
                 if "image" not in device and "image name" not in device:
             for index in range(0,len(devices_original)) :
                 device=devices_original[index]
                 if "image" not in device and "image name" not in device:
-                    if 'size' in device:
-                        disk_list.append({'size': device.get('size', default_volume_size)})
+                    if 'size' in device:
+                    disk_list.append({'size': device.get('size', default_volume_size), 'name': device.get('name')})
                     continue
                 image_dict={}
                 image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img")
                     continue
                 image_dict={}
                 image_dict['name']=device.get('image name',flavor_dict['name']+str(dev_nb)+"-img")
@@ -703,7 +808,7 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
         try:
             flavor_vim_id = None
             flavor_vim_id=vim.get_flavor_id_from_data(flavor_dict)
         try:
             flavor_vim_id = None
             flavor_vim_id=vim.get_flavor_id_from_data(flavor_dict)
-            flavor_create="false"
+            flavor_created="false"
         except vimconn.vimconnException as e:
             pass
         try:
         except vimconn.vimconnException as e:
             pass
         try:
@@ -776,6 +881,21 @@ def _lookfor_or_create_image(db_image, mydb, descriptor):
         db_image["uuid"] = image_uuid
         return None
 
         db_image["uuid"] = image_uuid
         return None
 
+def get_resource_allocation_params(quota_descriptor):
+    """
+    read the quota_descriptor from vnfd and fetch the resource allocation properties from the descriptor object
+    :param quota_descriptor: cpu/mem/vif/disk-io quota descriptor
+    :return: quota params for limit, reserve, shares from the descriptor object
+    """
+    quota = {}
+    if quota_descriptor.get("limit"):
+        quota["limit"] = int(quota_descriptor["limit"])
+    if quota_descriptor.get("reserve"):
+        quota["reserve"] = int(quota_descriptor["reserve"])
+    if quota_descriptor.get("shares"):
+        quota["shares"] = int(quota_descriptor["shares"])
+    return quota
+
 def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
     """
     Parses an OSM IM vnfd_catalog and insert at DB
 def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
     """
     Parses an OSM IM vnfd_catalog and insert at DB
@@ -787,9 +907,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
     try:
         myvnfd = vnfd_catalog.vnfd()
         try:
     try:
         myvnfd = vnfd_catalog.vnfd()
         try:
-            pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd)
+            pybindJSONDecoder.load_ietf_json(vnf_descriptor, None, None, obj=myvnfd, path_helper=True,
+                                             skip_unknown=True)
         except Exception as e:
         except Exception as e:
-            raise NfvoException("Invalid yang descriptor format " + str(e), HTTP_Bad_Request)
+            raise NfvoException("Error. Invalid VNF descriptor format " + str(e), httperrors.Bad_Request)
         db_vnfs = []
         db_nets = []
         db_vms = []
         db_vnfs = []
         db_nets = []
         db_vms = []
@@ -797,18 +918,27 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
         db_interfaces = []
         db_images = []
         db_flavors = []
         db_interfaces = []
         db_images = []
         db_flavors = []
+        db_ip_profiles_index = 0
+        db_ip_profiles = []
         uuid_list = []
         vnfd_uuid_list = []
         uuid_list = []
         vnfd_uuid_list = []
-        for rift_vnfd in myvnfd.vnfd_catalog.vnfd.itervalues():
-            vnfd = rift_vnfd.get()
+        vnfd_catalog_descriptor = vnf_descriptor.get("vnfd:vnfd-catalog")
+        if not vnfd_catalog_descriptor:
+            vnfd_catalog_descriptor = vnf_descriptor.get("vnfd-catalog")
+        vnfd_descriptor_list = vnfd_catalog_descriptor.get("vnfd")
+        if not vnfd_descriptor_list:
+            vnfd_descriptor_list = vnfd_catalog_descriptor.get("vnfd:vnfd")
+        for vnfd_yang in myvnfd.vnfd_catalog.vnfd.itervalues():
+            vnfd = vnfd_yang.get()
 
             # table vnf
             vnf_uuid = str(uuid4())
             uuid_list.append(vnf_uuid)
             vnfd_uuid_list.append(vnf_uuid)
 
             # table vnf
             vnf_uuid = str(uuid4())
             uuid_list.append(vnf_uuid)
             vnfd_uuid_list.append(vnf_uuid)
+            vnfd_id = get_str(vnfd, "id", 255)
             db_vnf = {
                 "uuid": vnf_uuid,
             db_vnf = {
                 "uuid": vnf_uuid,
-                "osm_id": get_str(vnfd, "id", 255),
+                "osm_id": vnfd_id,
                 "name": get_str(vnfd, "name", 255),
                 "description": get_str(vnfd, "description", 255),
                 "tenant_id": tenant_id,
                 "name": get_str(vnfd, "name", 255),
                 "description": get_str(vnfd, "description", 255),
                 "tenant_id": tenant_id,
@@ -817,6 +947,31 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                 "descriptor": str(vnf_descriptor)[:60000]
             }
 
                 "descriptor": str(vnf_descriptor)[:60000]
             }
 
+            for vnfd_descriptor in vnfd_descriptor_list:
+                if vnfd_descriptor["id"] == str(vnfd["id"]):
+                    break
+
+            # table ip_profiles (ip-profiles)
+            ip_profile_name2db_table_index = {}
+            for ip_profile in vnfd.get("ip-profiles").itervalues():
+                db_ip_profile = {
+                    "ip_version": str(ip_profile["ip-profile-params"].get("ip-version", "ipv4")),
+                    "subnet_address": str(ip_profile["ip-profile-params"].get("subnet-address")),
+                    "gateway_address": str(ip_profile["ip-profile-params"].get("gateway-address")),
+                    "dhcp_enabled": str(ip_profile["ip-profile-params"]["dhcp-params"].get("enabled", True)),
+                    "dhcp_start_address": str(ip_profile["ip-profile-params"]["dhcp-params"].get("start-address")),
+                    "dhcp_count": str(ip_profile["ip-profile-params"]["dhcp-params"].get("count")),
+                }
+                dns_list = []
+                for dns in ip_profile["ip-profile-params"]["dns-server"].itervalues():
+                    dns_list.append(str(dns.get("address")))
+                db_ip_profile["dns_address"] = ";".join(dns_list)
+                if ip_profile["ip-profile-params"].get('security-group'):
+                    db_ip_profile["security_group"] = ip_profile["ip-profile-params"]['security-group']
+                ip_profile_name2db_table_index[str(ip_profile["name"])] = db_ip_profiles_index
+                db_ip_profiles_index += 1
+                db_ip_profiles.append(db_ip_profile)
+
             # table nets (internal-vld)
             net_id2uuid = {}  # for mapping interface with network
             for vld in vnfd.get("internal-vld").itervalues():
             # table nets (internal-vld)
             net_id2uuid = {}  # for mapping interface with network
             for vld in vnfd.get("internal-vld").itervalues():
@@ -827,22 +982,53 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                     "vnf_id": vnf_uuid,
                     "uuid": net_uuid,
                     "description": get_str(vld, "description", 255),
                     "vnf_id": vnf_uuid,
                     "uuid": net_uuid,
                     "description": get_str(vld, "description", 255),
+                    "osm_id": get_str(vld, "id", 255),
                     "type": "bridge",   # TODO adjust depending on connection point type
                 }
                 net_id2uuid[vld.get("id")] = net_uuid
                 db_nets.append(db_net)
                     "type": "bridge",   # TODO adjust depending on connection point type
                 }
                 net_id2uuid[vld.get("id")] = net_uuid
                 db_nets.append(db_net)
+                # ip-profile, link db_ip_profile with db_sce_net
+                if vld.get("ip-profile-ref"):
+                    ip_profile_name = vld.get("ip-profile-ref")
+                    if ip_profile_name not in ip_profile_name2db_table_index:
+                        raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vld[{}]':'ip-profile-ref':"
+                                            "'{}'. Reference to a non-existing 'ip_profiles'".format(
+                                                str(vnfd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])),
+                                            httperrors.Bad_Request)
+                    db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["net_id"] = net_uuid
+                else:  #check no ip-address has been defined
+                    for icp in vld.get("internal-connection-point").itervalues():
+                        if icp.get("ip-address"):
+                            raise NfvoException("Error at 'vnfd[{}]':'vld[{}]':'internal-connection-point[{}]' "
+                                            "contains an ip-address but no ip-profile has been defined at VLD".format(
+                                                str(vnfd["id"]), str(vld["id"]), str(icp["id"])),
+                                            httperrors.Bad_Request)
+
+            # connection points vaiable declaration
+            cp_name2iface_uuid = {}
+            cp_name2vdu_id = {}
+            cp_name2vm_uuid = {}
+            cp_name2db_interface = {}
+            vdu_id2cp_name = {}  # stored only when one external connection point is presented at this VDU
 
             # table vms (vdus)
             vdu_id2uuid = {}
             vdu_id2db_table_index = {}
 
             # table vms (vdus)
             vdu_id2uuid = {}
             vdu_id2db_table_index = {}
+            mgmt_access = {}
             for vdu in vnfd.get("vdu").itervalues():
             for vdu in vnfd.get("vdu").itervalues():
+
+                for vdu_descriptor in vnfd_descriptor["vdu"]:
+                    if vdu_descriptor["id"] == str(vdu["id"]):
+                        break
                 vm_uuid = str(uuid4())
                 uuid_list.append(vm_uuid)
                 vm_uuid = str(uuid4())
                 uuid_list.append(vm_uuid)
+                vdu_id = get_str(vdu, "id", 255)
                 db_vm = {
                     "uuid": vm_uuid,
                 db_vm = {
                     "uuid": vm_uuid,
-                    "osm_id": get_str(vdu, "id", 255),
+                    "osm_id": vdu_id,
                     "name": get_str(vdu, "name", 255),
                     "description": get_str(vdu, "description", 255),
                     "name": get_str(vdu, "name", 255),
                     "description": get_str(vdu, "description", 255),
+                    "pdu_type": get_str(vdu, "pdu-type", 255),
                     "vnf_id": vnf_uuid,
                 }
                 vdu_id2uuid[db_vm["osm_id"]] = vm_uuid
                     "vnf_id": vnf_uuid,
                 }
                 vdu_id2uuid[db_vm["osm_id"]] = vm_uuid
@@ -860,11 +1046,27 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                         image_uuid = db_image["uuid"]
                         db_images.append(db_image)
                     db_vm["image_id"] = image_uuid
                         image_uuid = db_image["uuid"]
                         db_images.append(db_image)
                     db_vm["image_id"] = image_uuid
+                if vdu.get("alternative-images"):
+                    vm_alternative_images = []
+                    for alt_image in vdu.get("alternative-images").itervalues():
+                        db_image = {}
+                        image_uuid = _lookfor_or_create_image(db_image, mydb, alt_image)
+                        if not image_uuid:
+                            image_uuid = db_image["uuid"]
+                            db_images.append(db_image)
+                        vm_alternative_images.append({
+                            "image_id": image_uuid,
+                            "vim_type": str(alt_image["vim-type"]),
+                            # "universal_name": str(alt_image["image"]),
+                            # "checksum": str(alt_image["image-checksum"]) if alt_image.get("image-checksum") else None
+                        })
+
+                    db_vm["image_list"] = yaml.safe_dump(vm_alternative_images, default_flow_style=True, width=256)
 
                 # volumes
                 devices = []
                 if vdu.get("volumes"):
 
                 # volumes
                 devices = []
                 if vdu.get("volumes"):
-                    for volume_key in sorted(vdu["volumes"]):
+                    for volume_key in vdu["volumes"]:
                         volume = vdu["volumes"][volume_key]
                         if not image_present:
                             # Convert the first volume to vnfc.image
                         volume = vdu["volumes"][volume_key]
                         if not image_present:
                             # Convert the first volume to vnfc.image
@@ -877,7 +1079,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                             db_vm["image_id"] = image_uuid
                         else:
                             # Add Openmano devices
                             db_vm["image_id"] = image_uuid
                         else:
                             # Add Openmano devices
-                            device = {}
+                            device = {"name": str(volume.get("name"))}
                             device["type"] = str(volume.get("device-type"))
                             if volume.get("size"):
                                 device["size"] = int(volume["size"])
                             device["type"] = str(volume.get("device-type"))
                             if volume.get("size"):
                                 device["size"] = int(volume["size"])
@@ -885,75 +1087,13 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                                 device["image name"] = str(volume["image"])
                                 if volume.get("image-checksum"):
                                     device["image checksum"] = str(volume["image-checksum"])
                                 device["image name"] = str(volume["image"])
                                 if volume.get("image-checksum"):
                                     device["image checksum"] = str(volume["image-checksum"])
-                            devices.append(device)
 
 
-                # table flavors
-                db_flavor = {
-                    "name": get_str(vdu, "name", 250) + "-flv",
-                    "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)),
-                    "ram": int(vdu["vm-flavor"].get("memory-mb", 1)),
-                    "disk": int(vdu["vm-flavor"].get("storage-gb", 1)),
-                }
-                # EPA  TODO revise
-                extended = {}
-                numa = {}
-                if devices:
-                    extended["devices"] = devices
-                if vdu.get("guest-epa"):   # TODO or dedicated_int:
-                    epa_vcpu_set = False
-                    if vdu["guest-epa"].get("numa-node-policy"):  # TODO or dedicated_int:
-                        numa_node_policy = vdu["guest-epa"].get("numa-node-policy")
-                        if numa_node_policy.get("node"):
-                            numa_node = numa_node_policy.node[0]
-                            if numa_node.get("num-cores"):
-                                numa["cores"] = numa_node["num-cores"]
-                                epa_vcpu_set = True
-                            if numa_node.get("paired-threads"):
-                                if numa_node["paired-threads"].get("num-paired-threads"):
-                                    numa["paired-threads"] = numa_node["paired-threads"]["num-paired-threads"]
-                                    epa_vcpu_set = True
-                                if len(numa_node["paired-threads"].get("paired-thread-ids")) > 0:
-                                    numa["paired-threads-id"] = []
-                                    for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues:
-                                        numa["paired-threads-id"].append(
-                                            (str(pair["thread-a"]), str(pair["thread-b"]))
-                                        )
-                            if numa_node.get("num-threads"):
-                                numa["threads"] = numa_node["num-threads"]
-                                epa_vcpu_set = True
-                            if numa_node.get("memory-mb"):
-                                numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1)
-                    if vdu["guest-epa"].get("mempage-size"):
-                        if vdu["guest-epa"]["mempage-size"] != "SMALL":
-                            numa["memory"] = max(int(db_flavor["ram"] / 1024), 1)
-                    if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set:
-                        if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
-                            if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \
-                                            vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
-                                numa["cores"] = max(db_flavor["vcpus"], 1)
-                            else:
-                                numa["threads"] = max(db_flavor["vcpus"], 1)
-                if numa:
-                    extended["numas"] = [numa]
-                if extended:
-                    extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256)
-                    db_flavor["extended"] = extended_text
-                # look if flavor exist
+                            devices.append(device)
 
 
-                temp_flavor_dict = {'disk': db_flavor.get('disk', 1),
-                                    'ram': db_flavor.get('ram'),
-                                    'vcpus': db_flavor.get('vcpus'),
-                                    'extended': db_flavor.get('extended')
-                                    }
-                existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict)
-                if existing_flavors:
-                    flavor_uuid = existing_flavors[0]["uuid"]
-                else:
-                    flavor_uuid = str(uuid4())
-                    uuid_list.append(flavor_uuid)
-                    db_flavor["uuid"] = flavor_uuid
-                    db_flavors.append(db_flavor)
-                db_vm["flavor_id"] = flavor_uuid
+                if not db_vm.get("image_id"):
+                    if not db_vm["pdu_type"]:
+                        raise NfvoException("Not defined image for VDU")
+                    # create a fake image
 
                 # cloud-init
                 boot_data = {}
 
                 # cloud-init
                 boot_data = {}
@@ -961,7 +1101,7 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                     boot_data["user-data"] = str(vdu["cloud-init"])
                 elif vdu.get("cloud-init-file"):
                     # TODO Where this file content is present???
                     boot_data["user-data"] = str(vdu["cloud-init"])
                 elif vdu.get("cloud-init-file"):
                     # TODO Where this file content is present???
-                    # boot_data["user-data"] = rift_vnfd.files[vdu["cloud-init-file"]]
+                    # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
                     boot_data["user-data"] = str(vdu["cloud-init-file"])
 
                 if vdu.get("supplemental-boot-data"):
                     boot_data["user-data"] = str(vdu["cloud-init-file"])
 
                 if vdu.get("supplemental-boot-data"):
@@ -982,10 +1122,10 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                 db_vms_index += 1
 
                 # table interfaces (internal/external interfaces)
                 db_vms_index += 1
 
                 # table interfaces (internal/external interfaces)
-                cp_name2iface_uuid = {}
-                cp_name2vm_uuid = {}
+                flavor_epa_interfaces = []
                 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
                 for iface in vdu.get("interface").itervalues():
                 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
                 for iface in vdu.get("interface").itervalues():
+                    flavor_epa_interface = {}
                     iface_uuid = str(uuid4())
                     uuid_list.append(iface_uuid)
                     db_interface = {
                     iface_uuid = str(uuid4())
                     uuid_list.append(iface_uuid)
                     db_interface = {
@@ -993,109 +1133,263 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                         "internal_name": get_str(iface, "name", 255),
                         "vm_id": vm_uuid,
                     }
                         "internal_name": get_str(iface, "name", 255),
                         "vm_id": vm_uuid,
                     }
+                    flavor_epa_interface["name"] = db_interface["internal_name"]
                     if iface.get("virtual-interface").get("vpci"):
                         db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12)
                     if iface.get("virtual-interface").get("vpci"):
                         db_interface["vpci"] = get_str(iface.get("virtual-interface"), "vpci", 12)
+                        flavor_epa_interface["vpci"] = db_interface["vpci"]
 
                     if iface.get("virtual-interface").get("bandwidth"):
                         bps = int(iface.get("virtual-interface").get("bandwidth"))
 
                     if iface.get("virtual-interface").get("bandwidth"):
                         bps = int(iface.get("virtual-interface").get("bandwidth"))
-                        db_interface["bw"] = bps/1000
+                        db_interface["bw"] = int(math.ceil(bps/1000000.0))
+                        flavor_epa_interface["bandwidth"] = "{} Mbps".format(db_interface["bw"])
 
                     if iface.get("virtual-interface").get("type") == "OM-MGMT":
                         db_interface["type"] = "mgmt"
 
                     if iface.get("virtual-interface").get("type") == "OM-MGMT":
                         db_interface["type"] = "mgmt"
-                    elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
+                    elif iface.get("virtual-interface").get("type") in ("VIRTIO", "E1000", "PARAVIRT"):
                         db_interface["type"] = "bridge"
                         db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
                     elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
                         db_interface["type"] = "data"
                         db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
                         db_interface["type"] = "bridge"
                         db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
                     elif iface.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
                         db_interface["type"] = "data"
                         db_interface["model"] = get_str(iface.get("virtual-interface"), "type", 12)
+                        flavor_epa_interface["dedicated"] = "no" if iface["virtual-interface"]["type"] == "SR-IOV" \
+                            else "yes"
+                        flavor_epa_interfaces.append(flavor_epa_interface)
                     else:
                     else:
-                        raise ValueError("Interface type {} not supported".format(iface.get("virtual-interface").get("type")))
+                        raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
+                                            "-interface':'type':'{}'. Interface type is not supported".format(
+                                                vnfd_id, vdu_id, iface.get("virtual-interface").get("type")),
+                                            httperrors.Bad_Request)
+
+                    if iface.get("mgmt-interface"):
+                        db_interface["type"] = "mgmt"
 
                     if iface.get("external-connection-point-ref"):
                         try:
                             cp = vnfd.get("connection-point")[iface.get("external-connection-point-ref")]
                             db_interface["external_name"] = get_str(cp, "name", 255)
                             cp_name2iface_uuid[db_interface["external_name"]] = iface_uuid
 
                     if iface.get("external-connection-point-ref"):
                         try:
                             cp = vnfd.get("connection-point")[iface.get("external-connection-point-ref")]
                             db_interface["external_name"] = get_str(cp, "name", 255)
                             cp_name2iface_uuid[db_interface["external_name"]] = iface_uuid
+                            cp_name2vdu_id[db_interface["external_name"]] = vdu_id
                             cp_name2vm_uuid[db_interface["external_name"]] = vm_uuid
                             cp_name2vm_uuid[db_interface["external_name"]] = vm_uuid
-                            # TODO add port-security-enable
-                            # if cp.get("port-security-enabled") == False:
-                            # elif cp.get("port-security-enabled") == True:
+                            cp_name2db_interface[db_interface["external_name"]] = db_interface
+                            for cp_descriptor in vnfd_descriptor["connection-point"]:
+                                if cp_descriptor["name"] == db_interface["external_name"]:
+                                    break
+                            else:
+                                raise KeyError()
+
+                            if vdu_id in vdu_id2cp_name:
+                                vdu_id2cp_name[vdu_id] = None  # more than two connecdtion 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":
+                                db_interface["port_security"] = 0
+                            elif str(cp_descriptor.get("port-security-enabled")).lower() == "true":
+                                db_interface["port_security"] = 1
                         except KeyError:
                         except KeyError:
-                            raise KeyError(
-                                "Error wrong reference at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
-                                "vnfd-connection-point-ref '{cp}' is not present at connection-point".format(
-                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
-                                    cp=iface.get("vnfd-connection-point-ref"))
-                            )
+                            raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
+                                                "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
+                                                " at connection-point".format(
+                                                    vnf=vnfd_id, vdu=vdu_id, iface=iface["name"],
+                                                    cp=iface.get("vnfd-connection-point-ref")),
+                                                httperrors.Bad_Request)
                     elif iface.get("internal-connection-point-ref"):
                         try:
                     elif iface.get("internal-connection-point-ref"):
                         try:
+                            for icp_descriptor in vdu_descriptor["internal-connection-point"]:
+                                if icp_descriptor["id"] == str(iface.get("internal-connection-point-ref")):
+                                    break
+                            else:
+                                raise KeyError("does not exist at vdu:internal-connection-point")
+                            icp = None
+                            icp_vld = None
                             for vld in vnfd.get("internal-vld").itervalues():
                                 for cp in vld.get("internal-connection-point").itervalues():
                                     if cp.get("id-ref") == iface.get("internal-connection-point-ref"):
                             for vld in vnfd.get("internal-vld").itervalues():
                                 for cp in vld.get("internal-connection-point").itervalues():
                                     if cp.get("id-ref") == iface.get("internal-connection-point-ref"):
-                                        db_interface["net_id"] = net_id2uuid[vld.get("id")]
-                                        break
-                        except KeyError:
-                            raise KeyError(
-                                "Error at vnfd['{vnf}'] vdu['{vdu}']:internal-interface['{iface}']:"
-                                "vdu-internal-connection-point-ref '{cp}' is not referenced by any internal-vld".format(
-                                    vnf=vnfd["id"], vdu=vdu["id"], iface=iface["name"],
-                                    cp=iface.get("vdu-internal-connection-point-ref"))
-                            )
-                    if iface.get("position") is not None:
-                        db_interface["created_at"] = int(iface.get("position")) - 1000
+                                        if icp:
+                                            raise KeyError("is referenced by more than one 'internal-vld'")
+                                        icp = cp
+                                        icp_vld = vld
+                            if not icp:
+                                raise KeyError("is not referenced by any 'internal-vld'")
+
+                            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 str(icp_descriptor.get("port-security-enabled")).lower() == "true":
+                                db_interface["port_security"] = 1
+                            if icp.get("ip-address"):
+                                if not icp_vld.get("ip-profile-ref"):
+                                    raise NfvoException
+                                db_interface["ip_address"] = str(icp.get("ip-address"))
+                        except KeyError as e:
+                            raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
+                                                "'interface[{iface}]':'internal-connection-point-ref':'{cp}'"
+                                                " {msg}".format(
+                                                    vnf=vnfd_id, vdu=vdu_id, iface=iface["name"],
+                                                    cp=iface.get("internal-connection-point-ref"), msg=str(e)),
+                                                httperrors.Bad_Request)
+                    if iface.get("position"):
+                        db_interface["created_at"] = int(iface.get("position")) * 50
+                    if iface.get("mac-address"):
+                        db_interface["mac"] = str(iface.get("mac-address"))
                     db_interfaces.append(db_interface)
 
                     db_interfaces.append(db_interface)
 
+                # table flavors
+                db_flavor = {
+                    "name": get_str(vdu, "name", 250) + "-flv",
+                    "vcpus": int(vdu["vm-flavor"].get("vcpu-count", 1)),
+                    "ram": int(vdu["vm-flavor"].get("memory-mb", 1)),
+                    "disk": int(vdu["vm-flavor"].get("storage-gb", 0)),
+                }
+                # TODO revise the case of several numa-node-policy node
+                extended = {}
+                numa = {}
+                if devices:
+                    extended["devices"] = devices
+                if flavor_epa_interfaces:
+                    numa["interfaces"] = flavor_epa_interfaces
+                if vdu.get("guest-epa"):   # TODO or dedicated_int:
+                    epa_vcpu_set = False
+                    if vdu["guest-epa"].get("numa-node-policy"):  # TODO or dedicated_int:
+                        numa_node_policy = vdu["guest-epa"].get("numa-node-policy")
+                        if numa_node_policy.get("node"):
+                            numa_node = numa_node_policy["node"].values()[0]
+                            if numa_node.get("num-cores"):
+                                numa["cores"] = numa_node["num-cores"]
+                                epa_vcpu_set = True
+                            if numa_node.get("paired-threads"):
+                                if numa_node["paired-threads"].get("num-paired-threads"):
+                                    numa["paired-threads"] = int(numa_node["paired-threads"]["num-paired-threads"])
+                                    epa_vcpu_set = True
+                                if len(numa_node["paired-threads"].get("paired-thread-ids")):
+                                    numa["paired-threads-id"] = []
+                                    for pair in numa_node["paired-threads"]["paired-thread-ids"].itervalues():
+                                        numa["paired-threads-id"].append(
+                                            (str(pair["thread-a"]), str(pair["thread-b"]))
+                                        )
+                            if numa_node.get("num-threads"):
+                                numa["threads"] = int(numa_node["num-threads"])
+                                epa_vcpu_set = True
+                            if numa_node.get("memory-mb"):
+                                numa["memory"] = max(int(numa_node["memory-mb"] / 1024), 1)
+                    if vdu["guest-epa"].get("mempage-size"):
+                        if vdu["guest-epa"]["mempage-size"] != "SMALL":
+                            numa["memory"] = max(int(db_flavor["ram"] / 1024), 1)
+                    if vdu["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set:
+                        if vdu["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
+                            if vdu["guest-epa"].get("cpu-thread-pinning-policy") and \
+                                            vdu["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
+                                numa["cores"] = max(db_flavor["vcpus"], 1)
+                            else:
+                                numa["threads"] = max(db_flavor["vcpus"], 1)
+                            epa_vcpu_set = True
+                    if vdu["guest-epa"].get("cpu-quota") and not epa_vcpu_set:
+                        cpuquota = get_resource_allocation_params(vdu["guest-epa"].get("cpu-quota"))
+                        if cpuquota:
+                            extended["cpu-quota"] = cpuquota
+                    if vdu["guest-epa"].get("mem-quota"):
+                        vduquota = get_resource_allocation_params(vdu["guest-epa"].get("mem-quota"))
+                        if vduquota:
+                            extended["mem-quota"] = vduquota
+                    if vdu["guest-epa"].get("disk-io-quota"):
+                        diskioquota = get_resource_allocation_params(vdu["guest-epa"].get("disk-io-quota"))
+                        if diskioquota:
+                            extended["disk-io-quota"] = diskioquota
+                    if vdu["guest-epa"].get("vif-quota"):
+                        vifquota = get_resource_allocation_params(vdu["guest-epa"].get("vif-quota"))
+                        if vifquota:
+                            extended["vif-quota"] = vifquota
+                if numa:
+                    extended["numas"] = [numa]
+                if extended:
+                    extended_text = yaml.safe_dump(extended, default_flow_style=True, width=256)
+                    db_flavor["extended"] = extended_text
+                # look if flavor exist
+                temp_flavor_dict = {'disk': db_flavor.get('disk', 0),
+                                    'ram': db_flavor.get('ram'),
+                                    'vcpus': db_flavor.get('vcpus'),
+                                    'extended': db_flavor.get('extended')
+                                    }
+                existing_flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict)
+                if existing_flavors:
+                    flavor_uuid = existing_flavors[0]["uuid"]
+                else:
+                    flavor_uuid = str(uuid4())
+                    uuid_list.append(flavor_uuid)
+                    db_flavor["uuid"] = flavor_uuid
+                    db_flavors.append(db_flavor)
+                db_vm["flavor_id"] = flavor_uuid
+
             # VNF affinity and antiaffinity
             for pg in vnfd.get("placement-groups").itervalues():
                 pg_name = get_str(pg, "name", 255)
                 for vdu in pg.get("member-vdus").itervalues():
                     vdu_id = get_str(vdu, "member-vdu-ref", 255)
                     if vdu_id not in vdu_id2db_table_index:
             # VNF affinity and antiaffinity
             for pg in vnfd.get("placement-groups").itervalues():
                 pg_name = get_str(pg, "name", 255)
                 for vdu in pg.get("member-vdus").itervalues():
                     vdu_id = get_str(vdu, "member-vdu-ref", 255)
                     if vdu_id not in vdu_id2db_table_index:
-                        raise KeyError(
-                            "Error at 'vnfd'['{vnf}']:'placement-groups'['{pg}']:'member-vdus':'{vdu}' references a non existing vdu".format(
-                                vnf=vnfd["id"], pg=pg_name, vdu=vdu_id))
+                        raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
+                                            "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
+                                                vnf=vnfd_id, pg=pg_name, vdu=vdu_id),
+                                            httperrors.Bad_Request)
                     db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
                     # TODO consider the case of isolation and not colocation
                     # if pg.get("strategy") == "ISOLATION":
                     db_vms[vdu_id2db_table_index[vdu_id]]["availability_zone"] = pg_name
                     # TODO consider the case of isolation and not colocation
                     # if pg.get("strategy") == "ISOLATION":
-                    
+
             # VNF mgmt configuration
             # VNF mgmt configuration
-            mgmt_access = {}
             if vnfd["mgmt-interface"].get("vdu-id"):
             if vnfd["mgmt-interface"].get("vdu-id"):
-                if vnfd["mgmt-interface"]["vdu-id"] not in vdu_id2uuid:
-                    raise KeyError(
-                        "Error at vnfd['{vnf}']:'mgmt-interface':'vdu-id':{vdu} reference a non existing vdu".format(
-                            vnf=vnfd["id"], vdu=vnfd["mgmt-interface"]["vdu-id"]))
+                mgmt_vdu_id = get_str(vnfd["mgmt-interface"], "vdu-id", 255)
+                if mgmt_vdu_id not in vdu_id2uuid:
+                    raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
+                                        "'{vdu}'. Reference to a non-existing vdu".format(
+                                            vnf=vnfd_id, vdu=mgmt_vdu_id),
+                                        httperrors.Bad_Request)
                 mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]]
                 mgmt_access["vm_id"] = vdu_id2uuid[vnfd["mgmt-interface"]["vdu-id"]]
+                mgmt_access["vdu-id"] = vnfd["mgmt-interface"]["vdu-id"]
+                # if only one cp is defined by this VDU, mark this interface as of type "mgmt"
+                if vdu_id2cp_name.get(mgmt_vdu_id):
+                    if cp_name2db_interface[vdu_id2cp_name[mgmt_vdu_id]]:
+                        cp_name2db_interface[vdu_id2cp_name[mgmt_vdu_id]]["type"] = "mgmt"
+
             if vnfd["mgmt-interface"].get("ip-address"):
                 mgmt_access["ip-address"] = str(vnfd["mgmt-interface"].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:
                 if vnfd["mgmt-interface"]["cp"] not in cp_name2iface_uuid:
-                    raise KeyError(
-                        "Error at vnfd['{vnf}']:'mgmt-interface':'cp':{cp} reference a non existing connection-point".
-                            format(vnf=vnfd["id"], cp=vnfd["mgmt-interface"]["cp"]))
+                    raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp'['{cp}']. "
+                                        "Reference to a non-existing connection-point".format(
+                                            vnf=vnfd_id, cp=vnfd["mgmt-interface"]["cp"]),
+                                        httperrors.Bad_Request)
                 mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]]
                 mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]]
                 mgmt_access["vm_id"] = cp_name2vm_uuid[vnfd["mgmt-interface"]["cp"]]
                 mgmt_access["interface_id"] = cp_name2iface_uuid[vnfd["mgmt-interface"]["cp"]]
+                mgmt_access["vdu-id"] = cp_name2vdu_id[vnfd["mgmt-interface"]["cp"]]
+                # mark this interface as of type mgmt
+                if cp_name2db_interface[vnfd["mgmt-interface"]["cp"]]:
+                    cp_name2db_interface[vnfd["mgmt-interface"]["cp"]]["type"] = "mgmt"
+
             default_user = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
                                     "default-user", 64)
             default_user = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
                                     "default-user", 64)
-
             if default_user:
                 mgmt_access["default_user"] = default_user
             if default_user:
                 mgmt_access["default_user"] = default_user
+
             required = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
                                    "required", 6)
             if required:
                 mgmt_access["required"] = required
 
             required = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
                                    "required", 6)
             if required:
                 mgmt_access["required"] = required
 
+            password_ = get_str(vnfd.get("vnf-configuration", {}).get("config-access", {}),
+                                   "password", 64)
+            if password_:
+                mgmt_access["password"] = password_
+
             if mgmt_access:
                 db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256)
 
             if mgmt_access:
                 db_vnf["mgmt_access"] = yaml.safe_dump(mgmt_access, default_flow_style=True, width=256)
 
-
-
             db_vnfs.append(db_vnf)
         db_tables=[
             {"vnfs": db_vnfs},
             {"nets": db_nets},
             {"images": db_images},
             {"flavors": db_flavors},
             db_vnfs.append(db_vnf)
         db_tables=[
             {"vnfs": db_vnfs},
             {"nets": db_nets},
             {"images": db_images},
             {"flavors": db_flavors},
+            {"ip_profiles": db_ip_profiles},
             {"vms": db_vms},
             {"interfaces": db_interfaces},
         ]
             {"vms": db_vms},
             {"interfaces": db_interfaces},
         ]
@@ -1104,11 +1398,14 @@ def new_vnfd_v3(mydb, tenant_id, vnf_descriptor):
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return vnfd_uuid_list
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return vnfd_uuid_list
+    except NfvoException:
+        raise
     except Exception as e:
         logger.error("Exception {}".format(e))
     except Exception as e:
         logger.error("Exception {}".format(e))
-        raise  # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
+        raise  # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
 
 
 
 
+@deprecated("Use new_vnfd_v3")
 def new_vnf(mydb, tenant_id, vnf_descriptor):
     global global_config
 
 def new_vnf(mydb, tenant_id, vnf_descriptor):
     global global_config
 
@@ -1121,12 +1418,12 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
         if "tenant_id" in vnf_descriptor["vnf"]:
             if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor["vnf"]["tenant_id"], tenant_id),
         if "tenant_id" in vnf_descriptor["vnf"]:
             if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor["vnf"]["tenant_id"], tenant_id),
-                                    HTTP_Unauthorized)
+                                    httperrors.Unauthorized)
         else:
             vnf_descriptor['vnf']['tenant_id'] = tenant_id
         # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
         if global_config["auto_push_VNF_to_VIMs"]:
         else:
             vnf_descriptor['vnf']['tenant_id'] = tenant_id
         # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
         if global_config["auto_push_VNF_to_VIMs"]:
-            vims = get_vim(mydb, tenant_id)
+            vims = get_vim(mydb, tenant_id, ignore_errors=True)
 
     # Step 4. Review the descriptor and add missing  fields
     #print vnf_descriptor
 
     # Step 4. Review the descriptor and add missing  fields
     #print vnf_descriptor
@@ -1159,7 +1456,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
             myflavorDict["description"] = VNFCitem["description"]
             myflavorDict["ram"] = vnfc.get("ram", 0)
             myflavorDict["vcpus"] = vnfc.get("vcpus", 0)
             myflavorDict["description"] = VNFCitem["description"]
             myflavorDict["ram"] = vnfc.get("ram", 0)
             myflavorDict["vcpus"] = vnfc.get("vcpus", 0)
-            myflavorDict["disk"] = vnfc.get("disk", 1)
+            myflavorDict["disk"] = vnfc.get("disk", 0)
             myflavorDict["extended"] = {}
 
             devices = vnfc.get("devices")
             myflavorDict["extended"] = {}
 
             devices = vnfc.get("devices")
@@ -1179,9 +1476,9 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
             #    result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
             #    if result2:
             #        print "Error creating flavor: unknown processor model. Rollback successful."
             #    result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
             #    if result2:
             #        print "Error creating flavor: unknown processor model. Rollback successful."
-            #        return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
+            #        return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
             #    else:
             #    else:
-            #        return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
+            #        return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
             myflavorDict['extended']['processor_ranking'] = 100  #Hardcoded value, while we decide when the mapping is done
 
             if 'numas' in vnfc and len(vnfc['numas'])>0:
             myflavorDict['extended']['processor_ranking'] = 100  #Hardcoded value, while we decide when the mapping is done
 
             if 'numas' in vnfc and len(vnfc['numas'])>0:
@@ -1238,7 +1535,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
             error_text = "Exception at database"
         elif isinstance(e, KeyError):
             error_text = "KeyError exception "
             error_text = "Exception at database"
         elif isinstance(e, KeyError):
             error_text = "KeyError exception "
-            e.http_code = HTTP_Internal_Server_Error
+            e.http_code = httperrors.Internal_Server_Error
         else:
             error_text = "Exception at VIM"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
         else:
             error_text = "Exception at VIM"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
@@ -1246,6 +1543,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
         raise NfvoException(error_text, e.http_code)
 
 
         raise NfvoException(error_text, e.http_code)
 
 
+@deprecated("Use new_vnfd_v3")
 def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
     global global_config
 
 def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
     global global_config
 
@@ -1258,12 +1556,12 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
         if "tenant_id" in vnf_descriptor["vnf"]:
             if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor["vnf"]["tenant_id"], tenant_id),
         if "tenant_id" in vnf_descriptor["vnf"]:
             if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor["vnf"]["tenant_id"], tenant_id),
-                                    HTTP_Unauthorized)
+                                    httperrors.Unauthorized)
         else:
             vnf_descriptor['vnf']['tenant_id'] = tenant_id
         # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
         if global_config["auto_push_VNF_to_VIMs"]:
         else:
             vnf_descriptor['vnf']['tenant_id'] = tenant_id
         # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
         if global_config["auto_push_VNF_to_VIMs"]:
-            vims = get_vim(mydb, tenant_id)
+            vims = get_vim(mydb, tenant_id, ignore_errors=True)
 
     # Step 4. Review the descriptor and add missing  fields
     #print vnf_descriptor
 
     # Step 4. Review the descriptor and add missing  fields
     #print vnf_descriptor
@@ -1295,7 +1593,7 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
             myflavorDict["description"] = VNFCitem["description"]
             myflavorDict["ram"] = vnfc.get("ram", 0)
             myflavorDict["vcpus"] = vnfc.get("vcpus", 0)
             myflavorDict["description"] = VNFCitem["description"]
             myflavorDict["ram"] = vnfc.get("ram", 0)
             myflavorDict["vcpus"] = vnfc.get("vcpus", 0)
-            myflavorDict["disk"] = vnfc.get("disk", 1)
+            myflavorDict["disk"] = vnfc.get("disk", 0)
             myflavorDict["extended"] = {}
 
             devices = vnfc.get("devices")
             myflavorDict["extended"] = {}
 
             devices = vnfc.get("devices")
@@ -1315,9 +1613,9 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
             #    result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
             #    if result2:
             #        print "Error creating flavor: unknown processor model. Rollback successful."
             #    result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
             #    if result2:
             #        print "Error creating flavor: unknown processor model. Rollback successful."
-            #        return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
+            #        return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
             #    else:
             #    else:
-            #        return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
+            #        return -httperrors.Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
             myflavorDict['extended']['processor_ranking'] = 100  #Hardcoded value, while we decide when the mapping is done
 
             if 'numas' in vnfc and len(vnfc['numas'])>0:
             myflavorDict['extended']['processor_ranking'] = 100  #Hardcoded value, while we decide when the mapping is done
 
             if 'numas' in vnfc and len(vnfc['numas'])>0:
@@ -1373,7 +1671,7 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
             error_text = "Exception at database"
         elif isinstance(e, KeyError):
             error_text = "KeyError exception "
             error_text = "Exception at database"
         elif isinstance(e, KeyError):
             error_text = "KeyError exception "
-            e.http_code = HTTP_Internal_Server_Error
+            e.http_code = httperrors.Internal_Server_Error
         else:
             error_text = "Exception at VIM"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
         else:
             error_text = "Exception at VIM"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
@@ -1401,15 +1699,15 @@ def get_vnf_id(mydb, tenant_id, vnf_id):
             SELECT=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
                     'boot_data'),
             WHERE={'vnfs.uuid': vnf_id} )
             SELECT=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
                     'boot_data'),
             WHERE={'vnfs.uuid': vnf_id} )
-    if len(content)==0:
-        raise NfvoException("vnf '{}' not found".format(vnf_id), HTTP_Not_Found)
+    if len(content) != 0:
+        #raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
     # change boot_data into boot-data
     # change boot_data into boot-data
-    for vm in content:
-        if vm.get("boot_data"):
-            vm["boot-data"] = yaml.safe_load(vm["boot_data"])
-            del vm["boot_data"]
+        for vm in content:
+            if vm.get("boot_data"):
+                vm["boot-data"] = yaml.safe_load(vm["boot_data"])
+                del vm["boot_data"]
 
 
-    data['vnf']['VNFC'] = content
+        data['vnf']['VNFC'] = content
     #TODO: GET all the information from a VNFC and include it in the output.
 
     #GET NET
     #TODO: GET all the information from a VNFC and include it in the output.
 
     #GET NET
@@ -1426,7 +1724,7 @@ def get_vnf_id(mydb, tenant_id, vnf_id):
         if len(ipprofiles)==1:
             net["ip_profile"] = ipprofiles[0]
         elif len(ipprofiles)>1:
         if len(ipprofiles)==1:
             net["ip_profile"] = ipprofiles[0]
         elif len(ipprofiles)>1:
-            raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net['uuid']), HTTP_Bad_Request)
+            raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net['uuid']), httperrors.Bad_Request)
 
 
     #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
 
 
     #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
@@ -1435,8 +1733,7 @@ def get_vnf_id(mydb, tenant_id, vnf_id):
     content = mydb.get_rows(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
                                     SELECT=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
                                             'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
     content = mydb.get_rows(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
                                     SELECT=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
                                             'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
-                                    WHERE={'vnfs.uuid': vnf_id},
-                                    WHERE_NOT={'interfaces.external_name': None} )
+                                    WHERE={'vnfs.uuid': vnf_id, 'interfaces.external_name<>': None} )
     #print content
     data['vnf']['external-connections'] = content
 
     #print content
     data['vnf']['external-connections'] = content
 
@@ -1448,7 +1745,7 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
     if tenant_id != "any":
         check_tenant(mydb, tenant_id)
         # Get the URL of the VIM from the nfvo_tenant and the datacenter
     if tenant_id != "any":
         check_tenant(mydb, tenant_id)
         # Get the URL of the VIM from the nfvo_tenant and the datacenter
-        vims = get_vim(mydb, tenant_id)
+        vims = get_vim(mydb, tenant_id, ignore_errors=True)
     else:
         vims={}
 
     else:
         vims={}
 
@@ -1471,7 +1768,7 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
 
     deleted = mydb.delete_row_by_id('vnfs', vnf_id)
     if deleted == 0:
 
     deleted = mydb.delete_row_by_id('vnfs', vnf_id)
     if deleted == 0:
-        raise NfvoException("vnf '{}' not found".format(vnf_id), HTTP_Not_Found)
+        raise NfvoException("vnf '{}' not found".format(vnf_id), httperrors.Not_Found)
 
     undeletedItems = []
     for flavor in flavorList:
 
     undeletedItems = []
     for flavor in flavorList:
@@ -1483,32 +1780,39 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
                 continue
             #flavor not used, must be deleted
             #delelte at VIM
                 continue
             #flavor not used, must be deleted
             #delelte at VIM
-            c = mydb.get_rows(FROM='datacenters_flavors', WHERE={'flavor_id':flavor})
+            c = mydb.get_rows(FROM='datacenters_flavors', WHERE={'flavor_id': flavor})
             for flavor_vim in c:
             for flavor_vim in c:
-                if flavor_vim["datacenter_vim_id"] not in vims:   # TODO change to datacenter_tenant_id
+                if not flavor_vim['created']:  # skip this flavor because not created by openmano
                     continue
                     continue
-                if flavor_vim['created']=='false': #skip this flavor because not created by openmano
+                # look for vim
+                myvim = None
+                for vim in vims.values():
+                    if vim["config"]["datacenter_tenant_id"] == flavor_vim["datacenter_vim_id"]:
+                        myvim = vim
+                        break
+                if not myvim:
                     continue
                     continue
-                myvim=vims[ flavor_vim["datacenter_id"] ]
                 try:
                     myvim.delete_flavor(flavor_vim["vim_id"])
                 try:
                     myvim.delete_flavor(flavor_vim["vim_id"])
-                except vimconn.vimconnNotFoundException as e:
-                    logger.warn("VIM flavor %s not exist at datacenter %s", flavor_vim["vim_id"], flavor_vim["datacenter_id"] )
+                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:
                     logger.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
                 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_id"], type(e).__name__, str(e))
-                    undeletedItems.append("flavor {} from VIM {}".format(flavor_vim["vim_id"], flavor_vim["datacenter_id"] ))
-            #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
+                            flavor_vim["vim_id"], flavor_vim["datacenter_vim_id"], type(e).__name__, str(e))
+                    undeletedItems.append("flavor {} from VIM {}".format(flavor_vim["vim_id"],
+                                                                         flavor_vim["datacenter_vim_id"]))
+            # delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
             mydb.delete_row_by_id('flavors', flavor)
         except db_base_Exception as e:
             logger.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor, str(e))
             mydb.delete_row_by_id('flavors', flavor)
         except db_base_Exception as e:
             logger.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor, str(e))
-            undeletedItems.append("flavor %s" % flavor)
+            undeletedItems.append("flavor {}".format(flavor))
 
 
     for image in imageList:
         try:
             #check if image is used by other vnf
 
 
     for image in imageList:
         try:
             #check if image is used by other vnf
-            c = mydb.get_rows(FROM='vms', WHERE={'image_id':image} )
+            c = mydb.get_rows(FROM='vms', WHERE=[{'image_id': image}, {'image_list LIKE ': '%' + image + '%'}])
             if len(c) > 0:
                 logger.debug("Image '%s' not deleted because it is being used by another VNF", image)
                 continue
             if len(c) > 0:
                 logger.debug("Image '%s' not deleted because it is being used by another VNF", image)
                 continue
@@ -1540,12 +1844,13 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
     #    return "delete_vnf. Undeleted: %s" %(undeletedItems)
 
 
     #    return "delete_vnf. Undeleted: %s" %(undeletedItems)
 
 
+@deprecated("Not used")
 def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
     result, vims = get_vim(mydb, nfvo_tenant_id, None, datacenter_name)
     if result < 0:
         return result, vims
     elif result == 0:
 def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
     result, vims = get_vim(mydb, nfvo_tenant_id, None, datacenter_name)
     if result < 0:
         return result, vims
     elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % datacenter_name
+        return -httperrors.Not_Found, "datacenter '%s' not found" % datacenter_name
     myvim = vims.values()[0]
     result,servers =  myvim.get_hosts_info()
     if result < 0:
     myvim = vims.values()[0]
     result,servers =  myvim.get_hosts_info()
     if result < 0:
@@ -1557,10 +1862,10 @@ def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
 def get_hosts(mydb, nfvo_tenant_id):
     vims = get_vim(mydb, nfvo_tenant_id)
     if len(vims) == 0:
 def get_hosts(mydb, nfvo_tenant_id):
     vims = get_vim(mydb, nfvo_tenant_id)
     if len(vims) == 0:
-        raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id)), HTTP_Not_Found)
+        raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id)), httperrors.Not_Found)
     elif len(vims)>1:
         #print "nfvo.datacenter_action() error. Several datacenters found"
     elif len(vims)>1:
         #print "nfvo.datacenter_action() error. Several datacenters found"
-        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
+        raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict)
     myvim = vims.values()[0]
     try:
         hosts =  myvim.get_hosts()
     myvim = vims.values()[0]
     try:
         hosts =  myvim.get_hosts()
@@ -1590,6 +1895,7 @@ def get_hosts(mydb, nfvo_tenant_id):
         raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e)), e.http_code)
 
 
         raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e)), e.http_code)
 
 
+@deprecated("Use new_nsd_v3")
 def new_scenario(mydb, tenant_id, topo):
 
 #    result, vims = get_vim(mydb, tenant_id)
 def new_scenario(mydb, tenant_id, topo):
 
 #    result, vims = get_vim(mydb, tenant_id)
@@ -1601,7 +1907,7 @@ def new_scenario(mydb, tenant_id, topo):
         if "tenant_id" in topo:
             if topo["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo["tenant_id"], tenant_id),
         if "tenant_id" in topo:
             if topo["tenant_id"] != tenant_id:
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo["tenant_id"], tenant_id),
-                                    HTTP_Unauthorized)
+                                    httperrors.Unauthorized)
     else:
         tenant_id=None
 
     else:
         tenant_id=None
 
@@ -1623,8 +1929,7 @@ def new_scenario(mydb, tenant_id, topo):
 
 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
     for name,vnf in vnfs.items():
 
 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
     for name,vnf in vnfs.items():
-        where={}
-        where_or={"tenant_id": tenant_id, 'public': "true"}
+        where = {"OR": {"tenant_id": tenant_id, 'public': "true"}}
         error_text = ""
         error_pos = "'topology':'nodes':'" + name + "'"
         if 'vnf_id' in vnf:
         error_text = ""
         error_pos = "'topology':'nodes':'" + name + "'"
         if 'vnf_id' in vnf:
@@ -1633,24 +1938,22 @@ def new_scenario(mydb, tenant_id, topo):
         if 'VNF model' in vnf:
             error_text += " 'VNF model' " +  vnf['VNF model']
             where['name'] = vnf['VNF model']
         if 'VNF model' in vnf:
             error_text += " 'VNF model' " +  vnf['VNF model']
             where['name'] = vnf['VNF model']
-        if len(where) == 0:
-            raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos, HTTP_Bad_Request)
+        if len(where) == 1:
+            raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos, httperrors.Bad_Request)
 
         vnf_db = mydb.get_rows(SELECT=('uuid','name','description'),
                                FROM='vnfs',
 
         vnf_db = mydb.get_rows(SELECT=('uuid','name','description'),
                                FROM='vnfs',
-                               WHERE=where,
-                               WHERE_OR=where_or,
-                               WHERE_AND_OR="AND")
+                               WHERE=where)
         if len(vnf_db)==0:
         if len(vnf_db)==0:
-            raise NfvoException("unknown" + error_text + " at " + error_pos, HTTP_Not_Found)
+            raise NfvoException("unknown" + error_text + " at " + error_pos, httperrors.Not_Found)
         elif len(vnf_db)>1:
         elif len(vnf_db)>1:
-            raise NfvoException("more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", HTTP_Conflict)
+            raise NfvoException("more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", httperrors.Conflict)
         vnf['uuid']=vnf_db[0]['uuid']
         vnf['description']=vnf_db[0]['description']
         #get external interfaces
         ext_ifaces = mydb.get_rows(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
             FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
         vnf['uuid']=vnf_db[0]['uuid']
         vnf['description']=vnf_db[0]['description']
         #get external interfaces
         ext_ifaces = mydb.get_rows(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
             FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
-            WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name':None} )
+            WHERE={'vnfs.uuid':vnf['uuid'], 'external_name<>': None} )
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
 
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
 
@@ -1670,7 +1973,7 @@ def new_scenario(mydb, tenant_id, topo):
         con_type = conections[k].get("type", "link")
         if con_type != "link":
             if k in other_nets:
         con_type = conections[k].get("type", "link")
         if con_type != "link":
             if k in other_nets:
-                raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k)), HTTP_Bad_Request)
+                raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k)), httperrors.Bad_Request)
             other_nets[k] = {'external': False}
             if conections[k].get("graph"):
                 other_nets[k]["graph"] =   conections[k]["graph"]
             other_nets[k] = {'external': False}
             if conections[k].get("graph"):
                 other_nets[k]["graph"] =   conections[k]["graph"]
@@ -1693,10 +1996,10 @@ def new_scenario(mydb, tenant_id, topo):
         for iface in ifaces_list:
             if iface[0] not in vnfs and iface[0] not in other_nets :
                 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
         for iface in ifaces_list:
             if iface[0] not in vnfs and iface[0] not in other_nets :
                 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
-                                                                                        str(k), iface[0]), HTTP_Not_Found)
+                                                                                        str(k), iface[0]), httperrors.Not_Found)
             if iface[0] in vnfs and iface[1] not in vnfs[ iface[0] ]['ifaces']:
                 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
             if iface[0] in vnfs and iface[1] not in vnfs[ iface[0] ]['ifaces']:
                 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
-                                                                                        str(k), iface[0], iface[1]), HTTP_Not_Found)
+                                                                                        str(k), iface[0], iface[1]), httperrors.Not_Found)
 
 #1.5 unify connections from the pair list to a consolidated list
     index=0
 
 #1.5 unify connections from the pair list to a consolidated list
     index=0
@@ -1733,13 +2036,13 @@ def new_scenario(mydb, tenant_id, topo):
             if 'name' not in net:
                 net['name']=k
             if 'model' not in net:
             if 'name' not in net:
                 net['name']=k
             if 'model' not in net:
-                raise NfvoException("needed a 'model' at " + error_pos, HTTP_Bad_Request)
+                raise NfvoException("needed a 'model' at " + error_pos, httperrors.Bad_Request)
             if net['model']=='bridge_net':
                 net['type']='bridge';
             elif net['model']=='dataplane_net':
                 net['type']='data';
             else:
             if net['model']=='bridge_net':
                 net['type']='bridge';
             elif net['model']=='dataplane_net':
                 net['type']='data';
             else:
-                raise NfvoException("unknown 'model' '"+ net['model'] +"' at " + error_pos, HTTP_Not_Found)
+                raise NfvoException("unknown 'model' '"+ net['model'] +"' at " + error_pos, httperrors.Not_Found)
         else: #external
 #IF we do not want to check that external network exist at datacenter
             pass
         else: #external
 #IF we do not want to check that external network exist at datacenter
             pass
@@ -1753,17 +2056,17 @@ def new_scenario(mydb, tenant_id, topo):
 #                 error_text += " 'model' " +  net['model']
 #                 WHERE_['name'] = net['model']
 #             if len(WHERE_) == 0:
 #                 error_text += " 'model' " +  net['model']
 #                 WHERE_['name'] = net['model']
 #             if len(WHERE_) == 0:
-#                 return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
+#                 return -httperrors.Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
 #             r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
 #                 FROM='datacenter_nets', WHERE=WHERE_ )
 #             if r<0:
 #                 print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
 #             elif r==0:
 #                 print "nfvo.new_scenario Error" +error_text+ " is not present at database"
 #             r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
 #                 FROM='datacenter_nets', WHERE=WHERE_ )
 #             if r<0:
 #                 print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
 #             elif r==0:
 #                 print "nfvo.new_scenario Error" +error_text+ " is not present at database"
-#                 return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
+#                 return -httperrors.Bad_Request, "unknown " +error_text+ " at " + error_pos
 #             elif r>1:
 #                 print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
 #             elif r>1:
 #                 print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
-#                 return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
+#                 return -httperrors.Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
 #             other_nets[k].update(net_db[0])
 #ENDIF
     net_list={}
 #             other_nets[k].update(net_db[0])
 #ENDIF
     net_list={}
@@ -1780,7 +2083,7 @@ def new_scenario(mydb, tenant_id, topo):
                     if other_net_index>=0:
                         error_text="There is some interface connected both to net '%s' and net '%s'" % (con[other_net_index][0], net_key)
                         #print "nfvo.new_scenario " + error_text
                     if other_net_index>=0:
                         error_text="There is some interface connected both to net '%s' and net '%s'" % (con[other_net_index][0], net_key)
                         #print "nfvo.new_scenario " + error_text
-                        raise NfvoException(error_text, HTTP_Bad_Request)
+                        raise NfvoException(error_text, httperrors.Bad_Request)
                     else:
                         other_net_index = index
                         net_target = net_key
                     else:
                         other_net_index = index
                         net_target = net_key
@@ -1804,7 +2107,7 @@ def new_scenario(mydb, tenant_id, topo):
 #                     if type_=='data' and other_nets[net_target]['type']=="ptp":
 #                         error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
 #                         print "nfvo.new_scenario " + error_text
 #                     if type_=='data' and other_nets[net_target]['type']=="ptp":
 #                         error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
 #                         print "nfvo.new_scenario " + error_text
-#                         return -HTTP_Bad_Request, error_text
+#                         return -httperrors.Bad_Request, error_text
 #ENDIF
                 for iface in con:
                     vnfs[ iface[0] ]['ifaces'][ iface[1] ]['net_key'] = net_target
 #ENDIF
                 for iface in con:
                     vnfs[ iface[0] ]['ifaces'][ iface[1] ]['net_key'] = net_target
@@ -1826,7 +2129,7 @@ def new_scenario(mydb, tenant_id, topo):
                 if net_type_bridge and net_type_data:
                     error_text = "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface[0], iface[1])
                     #print "nfvo.new_scenario " + error_text
                 if net_type_bridge and net_type_data:
                     error_text = "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface[0], iface[1])
                     #print "nfvo.new_scenario " + error_text
-                    raise NfvoException(error_text, HTTP_Bad_Request)
+                    raise NfvoException(error_text, httperrors.Bad_Request)
                 elif net_type_bridge:
                     type_='bridge'
                 else:
                 elif net_type_bridge:
                     type_='bridge'
                 else:
@@ -1837,7 +2140,7 @@ def new_scenario(mydb, tenant_id, topo):
             error_text = "Error connection node %s : %s does not match any VNF or interface" % (iface[0], iface[1])
             #print "nfvo.new_scenario " + error_text
             #raise e
             error_text = "Error connection node %s : %s does not match any VNF or interface" % (iface[0], iface[1])
             #print "nfvo.new_scenario " + error_text
             #raise e
-            raise NfvoException(error_text, HTTP_Bad_Request)
+            raise NfvoException(error_text, httperrors.Bad_Request)
 
 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
     #1.8.1 obtain management net
 
 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
     #1.8.1 obtain management net
@@ -1874,6 +2177,7 @@ def new_scenario(mydb, tenant_id, topo):
     return c
 
 
     return c
 
 
+@deprecated("Use new_nsd_v3")
 def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
     """ This creates a new scenario for version 0.2 and 0.3"""
     scenario = scenario_dict["scenario"]
 def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
     """ This creates a new scenario for version 0.2 and 0.3"""
     scenario = scenario_dict["scenario"]
@@ -1883,14 +2187,13 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
             if scenario["tenant_id"] != tenant_id:
                 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
             if scenario["tenant_id"] != tenant_id:
                 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
                 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
-                                                    scenario["tenant_id"], tenant_id), HTTP_Unauthorized)
+                                                    scenario["tenant_id"], tenant_id), httperrors.Unauthorized)
     else:
         tenant_id=None
 
     # 1: Check that VNF are present at database table vnfs and update content into scenario dict
     for name,vnf in scenario["vnfs"].iteritems():
     else:
         tenant_id=None
 
     # 1: Check that VNF are present at database table vnfs and update content into scenario dict
     for name,vnf in scenario["vnfs"].iteritems():
-        where={}
-        where_or={"tenant_id": tenant_id, 'public': "true"}
+        where = {"OR": {"tenant_id": tenant_id, 'public': "true"}}
         error_text = ""
         error_pos = "'scenario':'vnfs':'" + name + "'"
         if 'vnf_id' in vnf:
         error_text = ""
         error_pos = "'scenario':'vnfs':'" + name + "'"
         if 'vnf_id' in vnf:
@@ -1899,24 +2202,22 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
         if 'vnf_name' in vnf:
             error_text += " 'vnf_name' " + vnf['vnf_name']
             where['name'] = vnf['vnf_name']
         if 'vnf_name' in vnf:
             error_text += " 'vnf_name' " + vnf['vnf_name']
             where['name'] = vnf['vnf_name']
-        if len(where) == 0:
-            raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos, HTTP_Bad_Request)
+        if len(where) == 1:
+            raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos, httperrors.Bad_Request)
         vnf_db = mydb.get_rows(SELECT=('uuid', 'name', 'description'),
                                FROM='vnfs',
         vnf_db = mydb.get_rows(SELECT=('uuid', 'name', 'description'),
                                FROM='vnfs',
-                               WHERE=where,
-                               WHERE_OR=where_or,
-                               WHERE_AND_OR="AND")
+                               WHERE=where)
         if len(vnf_db) == 0:
         if len(vnf_db) == 0:
-            raise NfvoException("Unknown" + error_text + " at " + error_pos, HTTP_Not_Found)
+            raise NfvoException("Unknown" + error_text + " at " + error_pos, httperrors.Not_Found)
         elif len(vnf_db) > 1:
         elif len(vnf_db) > 1:
-            raise NfvoException("More than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", HTTP_Conflict)
+            raise NfvoException("More than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", httperrors.Conflict)
         vnf['uuid'] = vnf_db[0]['uuid']
         vnf['description'] = vnf_db[0]['description']
         vnf['ifaces'] = {}
         # get external interfaces
         ext_ifaces = mydb.get_rows(SELECT=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
                                    FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
         vnf['uuid'] = vnf_db[0]['uuid']
         vnf['description'] = vnf_db[0]['description']
         vnf['ifaces'] = {}
         # get external interfaces
         ext_ifaces = mydb.get_rows(SELECT=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
                                    FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
-                                   WHERE={'vnfs.uuid':vnf['uuid']}, WHERE_NOT={'external_name': None} )
+                                   WHERE={'vnfs.uuid':vnf['uuid'], 'external_name<>': None} )
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type': ext_iface['type']}
         # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type': ext_iface['type']}
         # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
@@ -1937,17 +2238,17 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
                     error_text = "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
                         net_name, vnf)
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
                     error_text = "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
                         net_name, vnf)
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
-                    raise NfvoException(error_text, HTTP_Not_Found)
+                    raise NfvoException(error_text, httperrors.Not_Found)
                 if iface not in scenario["vnfs"][vnf]['ifaces']:
                     error_text = "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
                         .format(net_name, iface)
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
                 if iface not in scenario["vnfs"][vnf]['ifaces']:
                     error_text = "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
                         .format(net_name, iface)
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
-                    raise NfvoException(error_text, HTTP_Bad_Request)
+                    raise NfvoException(error_text, httperrors.Bad_Request)
                 if "net_key" in scenario["vnfs"][vnf]['ifaces'][iface]:
                     error_text = "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
                                  "'{}'".format(net_name, iface,scenario["vnfs"][vnf]['ifaces'][iface]['net_key'])
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
                 if "net_key" in scenario["vnfs"][vnf]['ifaces'][iface]:
                     error_text = "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
                                  "'{}'".format(net_name, iface,scenario["vnfs"][vnf]['ifaces'][iface]['net_key'])
                     # logger.debug("nfvo.new_scenario_v02 " + error_text)
-                    raise NfvoException(error_text, HTTP_Bad_Request)
+                    raise NfvoException(error_text, httperrors.Bad_Request)
                 scenario["vnfs"][vnf]['ifaces'][ iface ]['net_key'] = net_name
                 scenario["vnfs"][vnf]['ifaces'][iface]['ip_address'] = ip_address
                 iface_type = scenario["vnfs"][vnf]['ifaces'][iface]['type']
                 scenario["vnfs"][vnf]['ifaces'][ iface ]['net_key'] = net_name
                 scenario["vnfs"][vnf]['ifaces'][iface]['ip_address'] = ip_address
                 iface_type = scenario["vnfs"][vnf]['ifaces'][iface]['type']
@@ -1960,7 +2261,7 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
             error_text = "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
                 .format(net_name)
             # logger.debug("nfvo.new_scenario " + error_text)
             error_text = "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
                 .format(net_name)
             # logger.debug("nfvo.new_scenario " + error_text)
-            raise NfvoException(error_text, HTTP_Bad_Request)
+            raise NfvoException(error_text, httperrors.Bad_Request)
         elif net_type_bridge:
             type_ = 'bridge'
         else:
         elif net_type_bridge:
             type_ = 'bridge'
         else:
@@ -1971,19 +2272,19 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict, version):
                 error_text = "Error connecting interfaces of data type to a network declared as 'underlay' at "\
                              "'network':'{}'".format(net_name)
                 # logger.debug(error_text)
                 error_text = "Error connecting interfaces of data type to a network declared as 'underlay' at "\
                              "'network':'{}'".format(net_name)
                 # logger.debug(error_text)
-                raise NfvoException(error_text, HTTP_Bad_Request)
+                raise NfvoException(error_text, httperrors.Bad_Request)
             elif type_ != "bridge" and net["implementation"] == "overlay":
                 error_text = "Error connecting interfaces of data type to a network declared as 'overlay' at "\
                              "'network':'{}'".format(net_name)
                 # logger.debug(error_text)
             elif type_ != "bridge" and net["implementation"] == "overlay":
                 error_text = "Error connecting interfaces of data type to a network declared as 'overlay' at "\
                              "'network':'{}'".format(net_name)
                 # logger.debug(error_text)
-                raise NfvoException(error_text, HTTP_Bad_Request)
+                raise NfvoException(error_text, httperrors.Bad_Request)
             net.pop("implementation")
         if "type" in net and version == "0.3":   # for v0.3
             if type_ == "data" and net["type"] == "e-line":
                 error_text = "Error connecting more than 2 interfaces of data type to a network declared as type "\
                              "'e-line' at 'network':'{}'".format(net_name)
                 # logger.debug(error_text)
             net.pop("implementation")
         if "type" in net and version == "0.3":   # for v0.3
             if type_ == "data" and net["type"] == "e-line":
                 error_text = "Error connecting more than 2 interfaces of data type to a network declared as type "\
                              "'e-line' at 'network':'{}'".format(net_name)
                 # logger.debug(error_text)
-                raise NfvoException(error_text, HTTP_Bad_Request)
+                raise NfvoException(error_text, httperrors.Bad_Request)
             elif type_ == "ptp" and net["type"] == "e-lan":
                 type_ = "data"
 
             elif type_ == "ptp" and net["type"] == "e-lan":
                 type_ = "data"
 
@@ -2004,26 +2305,31 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
     :param mydb:
     :param tenant_id:
     :param nsd_descriptor:
     :param mydb:
     :param tenant_id:
     :param nsd_descriptor:
-    :return: The list of cretated NSD ids
+    :return: The list of created NSD ids
     """
     try:
         mynsd = nsd_catalog.nsd()
         try:
     """
     try:
         mynsd = nsd_catalog.nsd()
         try:
-            pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd)
+            pybindJSONDecoder.load_ietf_json(nsd_descriptor, None, None, obj=mynsd, skip_unknown=True)
         except Exception as e:
         except Exception as e:
-            raise NfvoException("Invalid yang descriptor format " + str(e), HTTP_Bad_Request)
+            raise NfvoException("Error. Invalid NS descriptor format: " + str(e), httperrors.Bad_Request)
         db_scenarios = []
         db_sce_nets = []
         db_sce_vnfs = []
         db_sce_interfaces = []
         db_scenarios = []
         db_sce_nets = []
         db_sce_vnfs = []
         db_sce_interfaces = []
+        db_sce_vnffgs = []
+        db_sce_rsps = []
+        db_sce_rsp_hops = []
+        db_sce_classifiers = []
+        db_sce_classifier_matches = []
         db_ip_profiles = []
         db_ip_profiles_index = 0
         uuid_list = []
         nsd_uuid_list = []
         db_ip_profiles = []
         db_ip_profiles_index = 0
         uuid_list = []
         nsd_uuid_list = []
-        for rift_nsd in mynsd.nsd_catalog.nsd.itervalues():
-            nsd = rift_nsd.get()
+        for nsd_yang in mynsd.nsd_catalog.nsd.itervalues():
+            nsd = nsd_yang.get()
 
 
-            # table sceanrios
+            # table scenarios
             scenario_uuid = str(uuid4())
             uuid_list.append(scenario_uuid)
             nsd_uuid_list.append(scenario_uuid)
             scenario_uuid = str(uuid4())
             uuid_list.append(scenario_uuid)
             nsd_uuid_list.append(scenario_uuid)
@@ -2046,21 +2352,23 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                 existing_vnf = mydb.get_rows(FROM="vnfs", WHERE={'osm_id': str(vnf["vnfd-id-ref"])[:255],
                                                                       'tenant_id': tenant_id})
                 if not existing_vnf:
                 existing_vnf = mydb.get_rows(FROM="vnfs", WHERE={'osm_id': str(vnf["vnfd-id-ref"])[:255],
                                                                       'tenant_id': tenant_id})
                 if not existing_vnf:
-                    raise KeyError("Error at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':'{}' references a "
-                                   "non existing VNFD in the catalog".format(str(nsd["id"]),
-                                                                             str(vnf["vnfd-id-ref"])[:255]))
+                    raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
+                                        "'{}'. Reference to a non-existing VNFD in the catalog".format(
+                                            str(nsd["id"]), str(vnf["vnfd-id-ref"])[:255]),
+                                        httperrors.Bad_Request)
                 sce_vnf_uuid = str(uuid4())
                 uuid_list.append(sce_vnf_uuid)
                 db_sce_vnf = {
                     "uuid": sce_vnf_uuid,
                     "scenario_id": scenario_uuid,
                 sce_vnf_uuid = str(uuid4())
                 uuid_list.append(sce_vnf_uuid)
                 db_sce_vnf = {
                     "uuid": sce_vnf_uuid,
                     "scenario_id": scenario_uuid,
-                    "name": existing_vnf[0]["name"][:200] + "." + get_str(vnf, "member-vnf-index", 5),
+                    # "name": get_str(vnf, "member-vnf-index", 255),
+                    "name": existing_vnf[0]["name"][:200] + "." + get_str(vnf, "member-vnf-index", 50),
                     "vnf_id": existing_vnf[0]["uuid"],
                     "vnf_id": existing_vnf[0]["uuid"],
-                    "member_vnf_index": int(vnf["member-vnf-index"]),
+                    "member_vnf_index": str(vnf["member-vnf-index"]),
                     # TODO 'start-by-default': True
                 }
                     # TODO 'start-by-default': True
                 }
-                vnf_index2scevnf_uuid[int(vnf['member-vnf-index'])] = sce_vnf_uuid
-                vnf_index2vnf_uuid[int(vnf['member-vnf-index'])] = existing_vnf[0]["uuid"]
+                vnf_index2scevnf_uuid[str(vnf['member-vnf-index'])] = sce_vnf_uuid
+                vnf_index2vnf_uuid[str(vnf['member-vnf-index'])] = existing_vnf[0]["uuid"]
                 db_sce_vnfs.append(db_sce_vnf)
 
             # table ip_profiles (ip-profiles)
                 db_sce_vnfs.append(db_sce_vnf)
 
             # table ip_profiles (ip-profiles)
@@ -2094,6 +2402,7 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                     "scenario_id": scenario_uuid,
                     # "type": #TODO
                     "multipoint": not vld.get("type") == "ELINE",
                     "scenario_id": scenario_uuid,
                     # "type": #TODO
                     "multipoint": not vld.get("type") == "ELINE",
+                    "osm_id":  get_str(vld, "id", 255),
                     # "external": #TODO
                     "description": get_str(vld, "description", 255),
                 }
                     # "external": #TODO
                     "description": get_str(vld, "description", 255),
                 }
@@ -2104,49 +2413,200 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
                 elif vld.get("provider-network").get("overlay-type") == "VLAN":
                     db_sce_net["type"] = "data"
                 else:
                 elif vld.get("provider-network").get("overlay-type") == "VLAN":
                     db_sce_net["type"] = "data"
                 else:
-                    db_sce_net["type"] = "bridge"
+                    # later on it will be fixed to bridge or data depending on the type of interfaces attached to it
+                    db_sce_net["type"] = None
                 db_sce_nets.append(db_sce_net)
 
                 # ip-profile, link db_ip_profile with db_sce_net
                 if vld.get("ip-profile-ref"):
                     ip_profile_name = vld.get("ip-profile-ref")
                     if ip_profile_name not in ip_profile_name2db_table_index:
                 db_sce_nets.append(db_sce_net)
 
                 # ip-profile, link db_ip_profile with db_sce_net
                 if vld.get("ip-profile-ref"):
                     ip_profile_name = vld.get("ip-profile-ref")
                     if ip_profile_name not in ip_profile_name2db_table_index:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}' references a non existing "
-                                       "'ip_profiles'".format(
-                                            str(nsd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])))
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
+                                            " Reference to a non-existing 'ip_profiles'".format(
+                                                str(nsd["id"]), str(vld["id"]), str(vld["ip-profile-ref"])),
+                                            httperrors.Bad_Request)
                     db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["sce_net_id"] = sce_net_uuid
                     db_ip_profiles[ip_profile_name2db_table_index[ip_profile_name]]["sce_net_id"] = sce_net_uuid
+                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").itervalues():
                 # table sce_interfaces (vld:vnfd-connection-point-ref)
                 for iface in vld.get("vnfd-connection-point-ref").itervalues():
-                    vnf_index = int(iface['member-vnf-index-ref'])
-                    # check correct parameters
-                    if vnf_index not in vnf_index2vnf_uuid:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'member-vnf-index-ref'"
-                                       ":'{}' references a non existing index at 'nsd':'constituent-vnfd'".format(
-                                            str(nsd["id"]), str(vld["id"]), str(iface["member-vnf-index-ref"])))
+                    # Check if there are VDUs in the descriptor
+                    vnf_index = str(iface['member-vnf-index-ref'])
+                    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").itervalues():
+                sce_vnffg_uuid = str(uuid4())
+                uuid_list.append(sce_vnffg_uuid)
+                db_sce_vnffg = {
+                    "uuid": sce_vnffg_uuid,
+                    "name": get_str(vnffg, "name", 255),
+                    "scenario_id": scenario_uuid,
+                    "vendor": get_str(vnffg, "vendor", 255),
+                    "description": get_str(vld, "description", 255),
+                }
+                db_sce_vnffgs.append(db_sce_vnffg)
+
+                # deal with rsps
+                for rsp in vnffg.get("rsp").itervalues():
+                    sce_rsp_uuid = str(uuid4())
+                    uuid_list.append(sce_rsp_uuid)
+                    db_sce_rsp = {
+                        "uuid": sce_rsp_uuid,
+                        "name": get_str(rsp, "name", 255),
+                        "sce_vnffg_id": sce_vnffg_uuid,
+                        "id": get_str(rsp, "id", 255), # only useful to link with classifiers; will be removed later in the code
+                    }
+                    db_sce_rsps.append(db_sce_rsp)
+                    for iface in rsp.get("vnfd-connection-point-ref").itervalues():
+                        vnf_index = str(iface['member-vnf-index-ref'])
+                        if_order = int(iface['order'])
+                        # check correct parameters
+                        if vnf_index not in vnf_index2vnf_uuid:
+                            raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
+                                                "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
+                                                "'nsd':'constituent-vnfd'".format(
+                                                    str(nsd["id"]), str(rsp["id"]), str(iface["member-vnf-index-ref"])),
+                                                httperrors.Bad_Request)
+
+                        ingress_existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
+                                                                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-ingress-connection-point-ref",
+                                                                                             255)})
+                        if not ingress_existing_ifaces:
+                            raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
+                                                "-ref':'vnfd-ingress-connection-point-ref':'{}'. Reference to a non-existing "
+                                                "connection-point name at VNFD '{}'".format(
+                                str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-ingress-connection-point-ref"]),
+                                str(iface.get("vnfd-id-ref"))[:255]), httperrors.Bad_Request)
+
+                        egress_existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
+                                                               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-egress-connection-point-ref",
+                                                                                            255)})
+                        if not egress_existing_ifaces:
+                            raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
+                                                "-ref':'vnfd-egress-connection-point-ref':'{}'. Reference to a non-existing "
+                                                "connection-point name at VNFD '{}'".format(
+                                str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-egress-connection-point-ref"]),
+                                str(iface.get("vnfd-id-ref"))[:255]), HTTP_Bad_Request)
+
+                        ingress_interface_uuid = ingress_existing_ifaces[0]["uuid"]
+                        egress_interface_uuid = egress_existing_ifaces[0]["uuid"]
+                        sce_rsp_hop_uuid = str(uuid4())
+                        uuid_list.append(sce_rsp_hop_uuid)
+                        db_sce_rsp_hop = {
+                            "uuid": sce_rsp_hop_uuid,
+                            "if_order": if_order,
+                            "ingress_interface_id": ingress_interface_uuid,
+                            "egress_interface_id": egress_interface_uuid,
+                            "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
+                            "sce_rsp_id": sce_rsp_uuid,
+                        }
+                        db_sce_rsp_hops.append(db_sce_rsp_hop)
 
 
+                # deal with classifiers
+                for classifier in vnffg.get("classifier").itervalues():
+                    sce_classifier_uuid = str(uuid4())
+                    uuid_list.append(sce_classifier_uuid)
+
+                    # source VNF
+                    vnf_index = str(classifier['member-vnf-index-ref'])
+                    if vnf_index not in vnf_index2vnf_uuid:
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'classifier[{}]':'vnfd-connection-point"
+                                            "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
+                                            "'nsd':'constituent-vnfd'".format(
+                                                str(nsd["id"]), str(classifier["id"]), str(classifier["member-vnf-index-ref"])),
+                                            httperrors.Bad_Request)
                     existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
                                                     FROM="interfaces as i join vms on i.vm_id=vms.uuid",
                                                     WHERE={'vnf_id': vnf_index2vnf_uuid[vnf_index],
                     existing_ifaces = mydb.get_rows(SELECT=('i.uuid as uuid',),
                                                     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",
+                                                           'external_name': get_str(classifier, "vnfd-connection-point-ref",
                                                                                     255)})
                     if not existing_ifaces:
                                                                                     255)})
                     if not existing_ifaces:
-                        raise KeyError("Error at 'nsd[{}]':'vld[{}]':'vnfd-connection-point-ref':'vnfd-connection-point"
-                                       "-ref':'{}' references a non existing interface at VNFD '{}'".format(
-                            str(nsd["id"]), str(vld["id"]), str(iface["vnfd-connection-point-ref"]),
-                            str(iface.get("vnfd-id-ref"))[:255]))
-
+                        raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'rsp[{}]':'vnfd-connection-point"
+                                            "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
+                                            "connection-point name at VNFD '{}'".format(
+                                                str(nsd["id"]), str(rsp["id"]), str(iface["vnfd-connection-point-ref"]),
+                                                str(iface.get("vnfd-id-ref"))[:255]),
+                                            httperrors.Bad_Request)
                     interface_uuid = existing_ifaces[0]["uuid"]
                     interface_uuid = existing_ifaces[0]["uuid"]
-                    sce_interface_uuid = str(uuid4())
-                    uuid_list.append(sce_net_uuid)
-                    db_sce_interface = {
-                        "uuid": sce_interface_uuid,
+
+                    db_sce_classifier = {
+                        "uuid": sce_classifier_uuid,
+                        "name": get_str(classifier, "name", 255),
+                        "sce_vnffg_id": sce_vnffg_uuid,
                         "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
                         "sce_vnf_id": vnf_index2scevnf_uuid[vnf_index],
-                        "sce_net_id": sce_net_uuid,
                         "interface_id": interface_uuid,
                         "interface_id": interface_uuid,
-                        # "ip_address": #TODO
                     }
                     }
-                    db_sce_interfaces.append(db_sce_interface)
+                    rsp_id = get_str(classifier, "rsp-id-ref", 255)
+                    rsp = next((item for item in db_sce_rsps if item["id"] == rsp_id), None)
+                    db_sce_classifier["sce_rsp_id"] = rsp["uuid"]
+                    db_sce_classifiers.append(db_sce_classifier)
+
+                    for match in classifier.get("match-attributes").itervalues():
+                        sce_classifier_match_uuid = str(uuid4())
+                        uuid_list.append(sce_classifier_match_uuid)
+                        db_sce_classifier_match = {
+                            "uuid": sce_classifier_match_uuid,
+                            "ip_proto": get_str(match, "ip-proto", 2),
+                            "source_ip": get_str(match, "source-ip-address", 16),
+                            "destination_ip": get_str(match, "destination-ip-address", 16),
+                            "source_port": get_str(match, "source-port", 5),
+                            "destination_port": get_str(match, "destination-port", 5),
+                            "sce_classifier_id": sce_classifier_uuid,
+                        }
+                        db_sce_classifier_matches.append(db_sce_classifier_match)
+                    # TODO: vnf/cp keys
+
+        # remove unneeded id's in sce_rsps
+        for rsp in db_sce_rsps:
+            rsp.pop('id')
 
         db_tables = [
             {"scenarios": db_scenarios},
 
         db_tables = [
             {"scenarios": db_scenarios},
@@ -2154,15 +2614,22 @@ def new_nsd_v3(mydb, tenant_id, nsd_descriptor):
             {"ip_profiles": db_ip_profiles},
             {"sce_vnfs": db_sce_vnfs},
             {"sce_interfaces": db_sce_interfaces},
             {"ip_profiles": db_ip_profiles},
             {"sce_vnfs": db_sce_vnfs},
             {"sce_interfaces": db_sce_interfaces},
+            {"sce_vnffgs": db_sce_vnffgs},
+            {"sce_rsps": db_sce_rsps},
+            {"sce_rsp_hops": db_sce_rsp_hops},
+            {"sce_classifiers": db_sce_classifiers},
+            {"sce_classifier_matches": db_sce_classifier_matches},
         ]
 
         ]
 
-        logger.debug("create_vnf Deployment done vnfDict: %s",
+        logger.debug("new_nsd_v3 done: %s",
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return nsd_uuid_list
                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
         mydb.new_rows(db_tables, uuid_list)
         return nsd_uuid_list
+    except NfvoException:
+        raise
     except Exception as e:
         logger.error("Exception {}".format(e))
     except Exception as e:
         logger.error("Exception {}".format(e))
-        raise  # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
+        raise  # NfvoException("Exception {}".format(e), httperrors.Bad_Request)
 
 
 def edit_scenario(mydb, tenant_id, scenario_id, data):
 
 
 def edit_scenario(mydb, tenant_id, scenario_id, data):
@@ -2172,6 +2639,7 @@ def edit_scenario(mydb, tenant_id, scenario_id, data):
     return c
 
 
     return c
 
 
+@deprecated("Use create_instance")
 def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instance_scenario_description, datacenter=None,vim_tenant=None, startvms=True):
     #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter, vim_tenant=vim_tenant)
 def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instance_scenario_description, datacenter=None,vim_tenant=None, startvms=True):
     #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter, vim_tenant=vim_tenant)
@@ -2207,11 +2675,12 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
             myNetDict["type"] = myNetType
             myNetDict["tenant_id"] = myvim_tenant
             myNetIPProfile = sce_net.get('ip_profile', None)
             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"]:
             #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
                 #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
@@ -2222,7 +2691,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                     error_text = "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name, sce_net['name'])
                     _, message = rollback(mydb, vims, rollbackList)
                     logger.error("nfvo.start_scenario: %s", error_text)
                     error_text = "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name, sce_net['name'])
                     _, message = rollback(mydb, vims, rollbackList)
                     logger.error("nfvo.start_scenario: %s", error_text)
-                    raise NfvoException(error_text, HTTP_Bad_Request)
+                    raise NfvoException(error_text, httperrors.Bad_Request)
                 logger.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict['name'],sce_net['vim_id'])
                 auxNetDict['scenario'][sce_net['uuid']] = sce_net['vim_id']
 
                 logger.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict['name'],sce_net['vim_id'])
                 auxNetDict['scenario'][sce_net['uuid']] = sce_net['vim_id']
 
@@ -2241,10 +2710,11 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 myNetDict["type"] = myNetType
                 myNetDict["tenant_id"] = myvim_tenant
                 myNetIPProfile = net.get('ip_profile', None)
                 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
                 #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:
                 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
                 net['vim_id'] = network_id
                 if sce_vnf['uuid'] not in auxNetDict:
@@ -2269,7 +2739,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
             # 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):
             # 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)
+                    raise NfvoException('No enough availability zones at VIM for this deployment', httperrors.Bad_Request)
 
             for vm in sce_vnf['vms']:
                 i += 1
 
             for vm in sce_vnf['vms']:
                 i += 1
@@ -2325,9 +2795,9 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                         e_text = "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(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. \
                         e_text = "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(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)
+                                    Try to delete and create the scenarios and VNFs again", httperrors.Conflict)
                         else:
                         else:
-                            raise NfvoException(e_text, HTTP_Internal_Server_Error)
+                            raise NfvoException(e_text, httperrors.Internal_Server_Error)
                     if netDict["use"]=="mgmt" or netDict["use"]=="bridge":
                         netDict["type"]="virtual"
                     if "vpci" in iface and iface["vpci"] is not None:
                     if netDict["use"]=="mgmt" or netDict["use"]=="bridge":
                         netDict["type"]="virtual"
                     if "vpci" in iface and iface["vpci"] is not None:
@@ -2363,7 +2833,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 else:
                     av_index = None
 
                 else:
                     av_index = None
 
-                vm_id = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None),
+                vm_id, _ = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None),
                                              myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'],
                                              availability_zone_index=av_index,
                                              availability_zone_list=vnf_availability_zones)
                                              myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'],
                                              availability_zone_index=av_index,
                                              availability_zone_list=vnf_availability_zones)
@@ -2504,17 +2974,39 @@ def get_vim_thread(mydb, tenant_id, datacenter_id_name=None, datacenter_tenant_i
                      "join datacenters as d on d.uuid=dt.datacenter_id",
                 WHERE=where_)
             if len(datacenters) > 1:
                      "join datacenters as d on d.uuid=dt.datacenter_id",
                 WHERE=where_)
             if len(datacenters) > 1:
-                raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
+                raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict)
             elif datacenters:
                 thread_id = datacenters[0]["datacenter_tenant_id"]
                 thread = vim_threads["running"].get(thread_id)
         if not thread:
             elif datacenters:
                 thread_id = datacenters[0]["datacenter_tenant_id"]
                 thread = vim_threads["running"].get(thread_id)
         if not thread:
-            raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), HTTP_Not_Found)
+            raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), httperrors.Not_Found)
         return thread_id, thread
     except db_base_Exception as e:
         raise NfvoException("{} {}".format(type(e).__name__ , str(e)), e.http_code)
 
 
         return thread_id, thread
     except db_base_Exception as e:
         raise NfvoException("{} {}".format(type(e).__name__ , str(e)), e.http_code)
 
 
+def get_datacenter_uuid(mydb, tenant_id, datacenter_id_name):
+    WHERE_dict={}
+    if utils.check_valid_uuid(datacenter_id_name):
+        WHERE_dict['d.uuid'] = datacenter_id_name
+    else:
+        WHERE_dict['d.name'] = datacenter_id_name
+
+    if tenant_id:
+        WHERE_dict['nfvo_tenant_id'] = tenant_id
+        from_= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
+               " 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 )
+    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"
+        raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict)
+    return vimaccounts[0]["uuid"], vimaccounts[0]["name"]
+
+
 def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extra_filter):
     datacenter_id = None
     datacenter_name = None
 def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extra_filter):
     datacenter_id = None
     datacenter_name = None
@@ -2525,16 +3017,16 @@ def get_datacenter_by_name_uuid(mydb, tenant_id, datacenter_id_name=None, **extr
             datacenter_name = datacenter_id_name
     vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, **extra_filter)
     if len(vims) == 0:
             datacenter_name = datacenter_id_name
     vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, **extra_filter)
     if len(vims) == 0:
-        raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), HTTP_Not_Found)
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name)), httperrors.Not_Found)
     elif len(vims)>1:
         #print "nfvo.datacenter_action() error. Several datacenters found"
     elif len(vims)>1:
         #print "nfvo.datacenter_action() error. Several datacenters found"
-        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
+        raise NfvoException("More than one datacenters found, try to identify with uuid", httperrors.Conflict)
     return vims.keys()[0], vims.values()[0]
 
 
 def update(d, u):
     return vims.keys()[0], vims.values()[0]
 
 
 def update(d, u):
-    '''Takes dict d and updates it with the values in dict u.'''
-    '''It merges all depth levels'''
+    """Takes dict d and updates it with the values in dict u.
+       It merges all depth levels"""
     for k, v in u.iteritems():
         if isinstance(v, collections.Mapping):
             r = update(d.get(k, {}), v)
     for k, v in u.iteritems():
         if isinstance(v, collections.Mapping):
             r = update(d.get(k, {}), v)
@@ -2543,26 +3035,32 @@ def update(d, u):
             d[k] = u[k]
     return d
 
             d[k] = u[k]
     return d
 
+
 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...")
 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
     myvims = {}
     myvim_threads_id = {}
     datacenter = instance_dict.get("datacenter")
     scenario = instance_dict["scenario"]
 
     # find main datacenter
     myvims = {}
     myvim_threads_id = {}
     datacenter = instance_dict.get("datacenter")
+    default_wim_account = instance_dict.get("wim_account")
     default_datacenter_id, vim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
     myvims[default_datacenter_id] = vim
     myvim_threads_id[default_datacenter_id], _ = get_vim_thread(mydb, tenant_id, default_datacenter_id)
     tenant = mydb.get_rows_by_id('nfvo_tenants', tenant_id)
     # myvim_tenant = myvim['tenant_id']
     default_datacenter_id, vim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
     myvims[default_datacenter_id] = vim
     myvim_threads_id[default_datacenter_id], _ = get_vim_thread(mydb, tenant_id, default_datacenter_id)
     tenant = mydb.get_rows_by_id('nfvo_tenants', tenant_id)
     # myvim_tenant = myvim['tenant_id']
-
-    rollbackList=[]
+    rollbackList = []
 
     # print "Checking that the scenario exists and getting the scenario dictionary"
 
     # print "Checking that the scenario exists and getting the scenario dictionary"
-    scenarioDict = mydb.get_scenario(scenario, tenant_id, datacenter_vim_id=myvim_threads_id[default_datacenter_id],
-                                     datacenter_id=default_datacenter_id)
+    if isinstance(scenario, str):
+        scenarioDict = mydb.get_scenario(scenario, tenant_id, datacenter_vim_id=myvim_threads_id[default_datacenter_id],
+                                         datacenter_id=default_datacenter_id)
+    else:
+        scenarioDict = scenario
+        scenarioDict["uuid"] = None
 
     # logger.debug(">>>>>> Dictionaries before merging")
     # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
 
     # logger.debug(">>>>>> Dictionaries before merging")
     # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
@@ -2571,6 +3069,10 @@ def create_instance(mydb, tenant_id, instance_dict):
     db_instance_vnfs = []
     db_instance_vms = []
     db_instance_interfaces = []
     db_instance_vnfs = []
     db_instance_vms = []
     db_instance_interfaces = []
+    db_instance_sfis = []
+    db_instance_sfs = []
+    db_instance_classifications = []
+    db_instance_sfps = []
     db_ip_profiles = []
     db_vim_actions = []
     uuid_list = []
     db_ip_profiles = []
     db_vim_actions = []
     uuid_list = []
@@ -2599,28 +3101,47 @@ def create_instance(mydb, tenant_id, instance_dict):
     }
 
     # Auxiliary dictionaries from x to y
     }
 
     # Auxiliary dictionaries from x to y
-    vnf_net2instance = {}
     sce_net2instance = {}
     net2task_id = {'scenario': {}}
     sce_net2instance = {}
     net2task_id = {'scenario': {}}
+    # Mapping between local networks and WIMs
+    wim_usage = {}
+
+    def ip_profile_IM2RO(ip_profile_im):
+        # translate from input format to database format
+        ip_profile_ro = {}
+        if 'subnet-address' in ip_profile_im:
+            ip_profile_ro['subnet_address'] = ip_profile_im['subnet-address']
+        if 'ip-version' in ip_profile_im:
+            ip_profile_ro['ip_version'] = ip_profile_im['ip-version']
+        if 'gateway-address' in ip_profile_im:
+            ip_profile_ro['gateway_address'] = ip_profile_im['gateway-address']
+        if 'dns-address' in ip_profile_im:
+            ip_profile_ro['dns_address'] = ip_profile_im['dns-address']
+            if isinstance(ip_profile_ro['dns_address'], (list, tuple)):
+                ip_profile_ro['dns_address'] = ";".join(ip_profile_ro['dns_address'])
+        if 'dhcp' in ip_profile_im:
+            ip_profile_ro['dhcp_start_address'] = ip_profile_im['dhcp'].get('start-address')
+            ip_profile_ro['dhcp_enabled'] = ip_profile_im['dhcp'].get('enabled', True)
+            ip_profile_ro['dhcp_count'] = ip_profile_im['dhcp'].get('count')
+        return ip_profile_ro
 
     # logger.debug("Creating instance from scenario-dict:\n%s",
     #               yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
     try:
         # 0 check correct parameters
         for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems():
 
     # logger.debug("Creating instance from scenario-dict:\n%s",
     #               yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
     try:
         # 0 check correct parameters
         for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems():
-            found = False
             for scenario_net in scenarioDict['nets']:
             for scenario_net in scenarioDict['nets']:
-                if net_name == scenario_net["name"]:
-                    found = True
+                if net_name == scenario_net.get("name") or net_name == scenario_net.get("osm_id") or net_name == scenario_net.get("uuid"):
                     break
                     break
-            if not found:
-                raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name),
-                                    HTTP_Bad_Request)
+            else:
+                raise NfvoException("Invalid scenario network name or id '{}' at instance:networks".format(net_name),
+                                    httperrors.Bad_Request)
             if "sites" not in net_instance_desc:
                 net_instance_desc["sites"] = [ {} ]
             site_without_datacenter_field = False
             for site in net_instance_desc["sites"]:
                 if site.get("datacenter"):
             if "sites" not in net_instance_desc:
                 net_instance_desc["sites"] = [ {} ]
             site_without_datacenter_field = False
             for site in net_instance_desc["sites"]:
                 if site.get("datacenter"):
+                    site["datacenter"], _ = get_datacenter_uuid(mydb, tenant_id, site["datacenter"])
                     if site["datacenter"] not in myvims:
                         # Add this datacenter to myvims
                         d, v = get_datacenter_by_name_uuid(mydb, tenant_id, site["datacenter"])
                     if site["datacenter"] not in myvims:
                         # Add this datacenter to myvims
                         d, v = get_datacenter_by_name_uuid(mydb, tenant_id, site["datacenter"])
@@ -2630,158 +3151,286 @@ def create_instance(mydb, tenant_id, instance_dict):
                 else:
                     if site_without_datacenter_field:
                         raise NfvoException("Found more than one entries without datacenter field at "
                 else:
                     if site_without_datacenter_field:
                         raise NfvoException("Found more than one entries without datacenter field at "
-                                            "instance:networks:{}:sites".format(net_name), HTTP_Bad_Request)
+                                            "instance:networks:{}:sites".format(net_name), httperrors.Bad_Request)
                     site_without_datacenter_field = True
                     site["datacenter"] = default_datacenter_id   # change name to id
 
         for vnf_name, vnf_instance_desc in instance_dict.get("vnfs",{}).iteritems():
                     site_without_datacenter_field = True
                     site["datacenter"] = default_datacenter_id   # change name to id
 
         for vnf_name, vnf_instance_desc in instance_dict.get("vnfs",{}).iteritems():
-            found = False
             for scenario_vnf in scenarioDict['vnfs']:
             for scenario_vnf in scenarioDict['vnfs']:
-                if vnf_name == scenario_vnf['name']:
-                    found = True
+                if vnf_name == scenario_vnf['member_vnf_index'] or vnf_name == scenario_vnf['uuid'] or vnf_name == scenario_vnf['name']:
                     break
                     break
-            if not found:
-                raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc), HTTP_Bad_Request)
+            else:
+                raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_name), httperrors.Bad_Request)
             if "datacenter" in vnf_instance_desc:
                 # Add this datacenter to myvims
             if "datacenter" in vnf_instance_desc:
                 # Add this datacenter to myvims
+                vnf_instance_desc["datacenter"], _ = get_datacenter_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"])
                 if vnf_instance_desc["datacenter"] not in myvims:
                     d, v = get_datacenter_by_name_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"])
                     myvims[d] = v
                     myvim_threads_id[d], _ = get_vim_thread(mydb, tenant_id, vnf_instance_desc["datacenter"])
                 scenario_vnf["datacenter"] = vnf_instance_desc["datacenter"]
 
                 if vnf_instance_desc["datacenter"] not in myvims:
                     d, v = get_datacenter_by_name_uuid(mydb, tenant_id, vnf_instance_desc["datacenter"])
                     myvims[d] = v
                     myvim_threads_id[d], _ = get_vim_thread(mydb, tenant_id, vnf_instance_desc["datacenter"])
                 scenario_vnf["datacenter"] = vnf_instance_desc["datacenter"]
 
+            for net_id, net_instance_desc in vnf_instance_desc.get("networks", {}).iteritems():
+                for scenario_net in scenario_vnf['nets']:
+                    if net_id == scenario_net['osm_id'] or net_id == scenario_net['uuid'] or net_id == scenario_net["name"]:
+                        break
+                else:
+                    raise NfvoException("Invalid net id or name '{}' at instance:vnfs:networks".format(net_id), httperrors.Bad_Request)
+                if net_instance_desc.get("vim-network-name"):
+                    scenario_net["vim-network-name"] = net_instance_desc["vim-network-name"]
+                if net_instance_desc.get("vim-network-id"):
+                    scenario_net["vim-network-id"] = net_instance_desc["vim-network-id"]
+                if net_instance_desc.get("name"):
+                    scenario_net["name"] = net_instance_desc["name"]
+                if 'ip-profile' in net_instance_desc:
+                    ipprofile_db = ip_profile_IM2RO(net_instance_desc['ip-profile'])
+                    if 'ip_profile' not in scenario_net:
+                        scenario_net['ip_profile'] = ipprofile_db
+                    else:
+                        update(scenario_net['ip_profile'], ipprofile_db)
+
+                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 vdu_id, vdu_instance_desc in vnf_instance_desc.get("vdus", {}).iteritems():
+                for scenario_vm in scenario_vnf['vms']:
+                    if vdu_id == scenario_vm['osm_id'] or vdu_id == scenario_vm["name"]:
+                        break
+                else:
+                    raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id), httperrors.Bad_Request)
+                scenario_vm["instance_parameters"] = vdu_instance_desc
+                for iface_id, iface_instance_desc in vdu_instance_desc.get("interfaces", {}).iteritems():
+                    for scenario_interface in scenario_vm['interfaces']:
+                        if iface_id == scenario_interface['internal_name'] or iface_id == scenario_interface["external_name"]:
+                            scenario_interface.update(iface_instance_desc)
+                            break
+                    else:
+                        raise NfvoException("Invalid vdu id or name '{}' at instance:vnfs:vdus".format(vdu_id), httperrors.Bad_Request)
+
         # 0.1 parse cloud-config parameters
         cloud_config = unify_cloud_config(instance_dict.get("cloud-config"), scenarioDict.get("cloud-config"))
         # 0.1 parse cloud-config parameters
         cloud_config = unify_cloud_config(instance_dict.get("cloud-config"), scenarioDict.get("cloud-config"))
-        # We add the RO key to cloud_config
-        if tenant[0].get('RO_pub_key'):
-            RO_key = {"key-pairs": [tenant[0]['RO_pub_key']]}
-            cloud_config = unify_cloud_config(cloud_config, RO_key)
 
         # 0.2 merge instance information into scenario
         # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
         # However, this is not possible yet.
 
         # 0.2 merge instance information into scenario
         # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
         # However, this is not possible yet.
-        for net_name, net_instance_desc in instance_dict.get("networks",{}).iteritems():
+        for net_name, net_instance_desc in instance_dict.get("networks", {}).iteritems():
+
             for scenario_net in scenarioDict['nets']:
             for scenario_net in scenarioDict['nets']:
-                if net_name == scenario_net["name"]:
+                if net_name == scenario_net.get("name") or net_name == scenario_net.get("osm_id") or net_name == scenario_net.get("uuid"):
+                    if "wim_account" in net_instance_desc and net_instance_desc["wim_account"] is not None:
+                        scenario_net["wim_account"] = net_instance_desc["wim_account"]
                     if 'ip-profile' in net_instance_desc:
                     if 'ip-profile' in net_instance_desc:
-                        # translate from input format to database format
-                        ipprofile_in = net_instance_desc['ip-profile']
-                        ipprofile_db = {}
-                        ipprofile_db['subnet_address'] = ipprofile_in.get('subnet-address')
-                        ipprofile_db['ip_version'] = ipprofile_in.get('ip-version', 'IPv4')
-                        ipprofile_db['gateway_address'] = ipprofile_in.get('gateway-address')
-                        ipprofile_db['dns_address'] = ipprofile_in.get('dns-address')
-                        if isinstance(ipprofile_db['dns_address'], (list, tuple)):
-                            ipprofile_db['dns_address'] = ";".join(ipprofile_db['dns_address'])
-                        if 'dhcp' in ipprofile_in:
-                            ipprofile_db['dhcp_start_address'] = ipprofile_in['dhcp'].get('start-address')
-                            ipprofile_db['dhcp_enabled'] = ipprofile_in['dhcp'].get('enabled', True)
-                            ipprofile_db['dhcp_count'] = ipprofile_in['dhcp'].get('count' )
+                        ipprofile_db = ip_profile_IM2RO(net_instance_desc['ip-profile'])
                         if 'ip_profile' not in scenario_net:
                             scenario_net['ip_profile'] = ipprofile_db
                         else:
                             update(scenario_net['ip_profile'], ipprofile_db)
                         if 'ip_profile' not in scenario_net:
                             scenario_net['ip_profile'] = ipprofile_db
                         else:
                             update(scenario_net['ip_profile'], ipprofile_db)
-            for interface in net_instance_desc.get('interfaces', () ):
-                if 'ip_address' in interface:
+                    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']:
                         if interface['vnf'] == vnf['name']:
                             for vnf_interface in vnf['interfaces']:
                                 if interface['vnf_interface'] == vnf_interface['external_name']:
                     for vnf in scenarioDict['vnfs']:
                         if interface['vnf'] == vnf['name']:
                             for vnf_interface in vnf['interfaces']:
                                 if interface['vnf_interface'] == vnf_interface['external_name']:
-                                    vnf_interface['ip_address']=interface['ip_address']
+                                    vnf_interface['ip_address'] = interface['ip_address']
 
         # logger.debug(">>>>>>>> Merged dictionary")
         # logger.debug("Creating instance scenario-dict MERGED:\n%s",
         #              yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
 
 
         # logger.debug(">>>>>>>> Merged dictionary")
         # 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"
         # 1. Creating new nets (sce_nets) in the VIM"
+        number_mgmt_networks = 0
         db_instance_nets = []
         for sce_net in scenarioDict['nets']:
         db_instance_nets = []
         for sce_net in scenarioDict['nets']:
-            descriptor_net = instance_dict.get("networks", {}).get(sce_net["name"], {})
-            net_name = descriptor_net.get("vim-network-name")
-            sce_net2instance[sce_net['uuid']] = {}
-            net2task_id['scenario'][sce_net['uuid']] = {}
 
 
-            sites = descriptor_net.get("sites", [ {} ])
-            for site in sites:
-                if site.get("datacenter"):
-                    vim = myvims[ site["datacenter"] ]
-                    datacenter_id = site["datacenter"]
-                    myvim_thread_id = myvim_threads_id[ site["datacenter"] ]
+            sce_net_uuid = sce_net.get('uuid', sce_net["name"])
+            # get involved datacenters where this network need to be created
+            involved_datacenters = []
+            for sce_vnf in scenarioDict.get("vnfs", ()):
+                vnf_datacenter = sce_vnf.get("datacenter", default_datacenter_id)
+                if vnf_datacenter in involved_datacenters:
+                    continue
+                if sce_vnf.get("interfaces"):
+                    for sce_vnf_ifaces in sce_vnf["interfaces"]:
+                        if sce_vnf_ifaces.get("sce_net_id") == sce_net["uuid"]:
+                            involved_datacenters.append(vnf_datacenter)
+                            break
+            if not 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"]:
+                    descriptor_net = instance_dict["networks"][sce_net["uuid"]]
+                    descriptor_net_name = sce_net["uuid"]
+                elif sce_net.get("osm_id") in instance_dict["networks"]:
+                    descriptor_net = instance_dict["networks"][sce_net["osm_id"]]
+                    descriptor_net_name = sce_net["osm_id"]
+                elif sce_net["name"] in instance_dict["networks"]:
+                    descriptor_net = instance_dict["networks"][sce_net["name"]]
+                    descriptor_net_name = sce_net["name"]
+            net_name = descriptor_net.get("vim-network-name")
+            # add datacenters from instantiation parameters
+            if descriptor_net.get("sites"):
+                for site in descriptor_net["sites"]:
+                    if site.get("datacenter") and site["datacenter"] not in involved_datacenters:
+                        involved_datacenters.append(site["datacenter"])
+            sce_net2instance[sce_net_uuid] = {}
+            net2task_id['scenario'][sce_net_uuid] = {}
+
+            use_network = None
+            related_network = None
+            if descriptor_net.get("use-network"):
+                target_instance_nets = mydb.get_rows(
+                    SELECT="related",
+                    FROM="instance_nets",
+                    WHERE={"instance_scenario_id": descriptor_net["use-network"]["instance_scenario_id"],
+                           "osm_id":  descriptor_net["use-network"]["osm_id"]},
+                )
+                if not target_instance_nets:
+                    raise NfvoException(
+                        "Cannot find the target network at instance:networks[{}]:use-network".format(descriptor_net_name),
+                        httperrors.Bad_Request)
                 else:
                 else:
-                    vim = myvims[ default_datacenter_id ]
-                    datacenter_id = default_datacenter_id
-                    myvim_thread_id = myvim_threads_id[default_datacenter_id]
+                    use_network = target_instance_nets[0]["related"]
+
+            if sce_net["external"]:
+                number_mgmt_networks += 1
+
+            for datacenter_id in involved_datacenters:
+                netmap_use = None
+                netmap_create = None
+                if descriptor_net.get("sites"):
+                    for site in descriptor_net["sites"]:
+                        if site.get("datacenter") == datacenter_id:
+                            netmap_use = site.get("netmap-use")
+                            netmap_create = site.get("netmap-create")
+                            break
+
+                vim = myvims[datacenter_id]
+                myvim_thread_id = myvim_threads_id[datacenter_id]
+
                 net_type = sce_net['type']
                 net_type = sce_net['type']
+                net_vim_name = None
                 lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'}  # 'shared': True
 
                 if not net_name:
                     if sce_net["external"]:
                         net_name = sce_net["name"]
                     else:
                 lookfor_filter = {'admin_state_up': True, 'status': 'ACTIVE'}  # 'shared': True
 
                 if not net_name:
                     if sce_net["external"]:
                         net_name = sce_net["name"]
                     else:
-                        net_name = "{}.{}".format(instance_name, sce_net["name"])
+                        net_name = "{}-{}".format(instance_name, sce_net["name"])
                         net_name = net_name[:255]     # limit length
 
                         net_name = net_name[:255]     # limit length
 
-                if "netmap-use" in site or "netmap-create" in site:
+                if netmap_use or netmap_create:
                     create_network = False
                     lookfor_network = False
                     create_network = False
                     lookfor_network = False
-                    if "netmap-use" in site:
+                    if netmap_use:
                         lookfor_network = True
                         lookfor_network = True
-                        if utils.check_valid_uuid(site["netmap-use"]):
-                            filter_text = "scenario id '%s'" % site["netmap-use"]
-                            lookfor_filter["id"] = site["netmap-use"]
+                        if utils.check_valid_uuid(netmap_use):
+                            lookfor_filter["id"] = netmap_use
                         else:
                         else:
-                            filter_text = "scenario name '%s'" % site["netmap-use"]
-                            lookfor_filter["name"] = site["netmap-use"]
-                    if "netmap-create" in site:
+                            lookfor_filter["name"] = netmap_use
+                    if netmap_create:
                         create_network = True
                         net_vim_name = net_name
                         create_network = True
                         net_vim_name = net_name
-                        if site["netmap-create"]:
-                            net_vim_name = site["netmap-create"]
+                        if isinstance(netmap_create, str):
+                            net_vim_name = netmap_create
+                elif sce_net.get("vim_network_name"):
+                    create_network = False
+                    lookfor_network = True
+                    lookfor_filter["name"] = sce_net.get("vim_network_name")
                 elif sce_net["external"]:
                 elif sce_net["external"]:
-                    if sce_net['vim_id'] != None:
+                    if sce_net.get('vim_id'):
                         # there is a netmap at datacenter_nets database   # TODO REVISE!!!!
                         create_network = False
                         lookfor_network = True
                         lookfor_filter["id"] = sce_net['vim_id']
                         # there is a netmap at datacenter_nets database   # TODO REVISE!!!!
                         create_network = False
                         lookfor_network = True
                         lookfor_filter["id"] = sce_net['vim_id']
-                        filter_text = "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
-                                      "datacenter-net-update".format(sce_net['vim_id'], sce_net["name"])
-                        # look for network at datacenter and return error
+                    elif vim["config"].get("management_network_id") or vim["config"].get("management_network_name"):
+                        if number_mgmt_networks > 1:
+                            raise NfvoException("Found several VLD of type mgmt. "
+                                                "You must concrete what vim-network must be use for each one",
+                                                httperrors.Bad_Request)
+                        create_network = False
+                        lookfor_network = True
+                        if vim["config"].get("management_network_id"):
+                            lookfor_filter["id"] = vim["config"]["management_network_id"]
+                        else:
+                            lookfor_filter["name"] = vim["config"]["management_network_name"]
                     else:
                         # There is not a netmap, look at datacenter for a net with this name and create if not found
                         create_network = True
                         lookfor_network = True
                         lookfor_filter["name"] = sce_net["name"]
                         net_vim_name = sce_net["name"]
                     else:
                         # There is not a netmap, look at datacenter for a net with this name and create if not found
                         create_network = True
                         lookfor_network = True
                         lookfor_filter["name"] = sce_net["name"]
                         net_vim_name = sce_net["name"]
-                        filter_text = "scenario name '%s'" % sce_net["name"]
                 else:
                     net_vim_name = net_name
                     create_network = True
                     lookfor_network = False
 
                 else:
                     net_vim_name = net_name
                     create_network = True
                     lookfor_network = False
 
-                if lookfor_network and create_network:
-                    # TODO create two tasks FIND + CREATE with their relationship
-                    task_action = "FIND_CREATE"
-                    task_params = (lookfor_filter, (net_vim_name, net_type, sce_net.get('ip_profile', None)))
+                task_extra = {}
+                if create_network:
+                    task_action = "CREATE"
+                    task_extra["params"] = (net_vim_name, net_type, sce_net.get('ip_profile', None), None, sce_net.get('provider_network', None), wim_account_name)
+
+                    if lookfor_network:
+                        task_extra["find"] = (lookfor_filter,)
                 elif lookfor_network:
                     task_action = "FIND"
                 elif lookfor_network:
                     task_action = "FIND"
-                    task_params = (lookfor_filter,)
-                elif create_network:
-                    task_action = "CREATE"
-                    task_params = (net_vim_name, net_type, sce_net.get('ip_profile', None))
+                    task_extra["params"] = (lookfor_filter,)
 
                 # fill database content
                 net_uuid = str(uuid4())
                 uuid_list.append(net_uuid)
 
                 # fill database content
                 net_uuid = str(uuid4())
                 uuid_list.append(net_uuid)
-                sce_net2instance[sce_net['uuid']][datacenter_id] = net_uuid
+                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
                 db_net = {
                     "uuid": net_uuid,
                 db_net = {
                     "uuid": net_uuid,
+                    "osm_id": sce_net.get("osm_id") or sce_net["name"],
+                    "related": related_network,
                     'vim_net_id': None,
                     'vim_net_id': None,
+                    "vim_name": net_vim_name,
                     "instance_scenario_id": instance_uuid,
                     "instance_scenario_id": instance_uuid,
-                    "sce_net_id": sce_net["uuid"],
+                    "sce_net_id": sce_net.get("uuid"),
                     "created": create_network,
                     'datacenter_id': datacenter_id,
                     'datacenter_tenant_id': myvim_thread_id,
                     "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"
                 }
                 db_instance_nets.append(db_net)
                 db_vim_action = {
                 }
                 db_instance_nets.append(db_net)
                 db_vim_action = {
@@ -2792,9 +3441,10 @@ def create_instance(mydb, tenant_id, instance_dict):
                     "action": task_action,
                     "item": "instance_nets",
                     "item_id": net_uuid,
                     "action": task_action,
                     "item": "instance_nets",
                     "item_id": net_uuid,
-                    "extra": yaml.safe_dump({"params": task_params}, default_flow_style=True, width=256)
+                    "related": related_network,
+                    "extra": yaml.safe_dump(task_extra, default_flow_style=True, width=256)
                 }
                 }
-                net2task_id['scenario'][sce_net['uuid']][datacenter_id] = task_index
+                net2task_id['scenario'][sce_net_uuid][datacenter_id] = task_index
                 task_index += 1
                 db_vim_actions.append(db_vim_action)
 
                 task_index += 1
                 db_vim_actions.append(db_vim_action)
 
@@ -2811,300 +3461,212 @@ def create_instance(mydb, tenant_id, instance_dict):
                 }
                 db_ip_profiles.append(db_ip_profile)
 
                 }
                 db_ip_profiles.append(db_ip_profile)
 
-        # 2. Creating new nets (vnf internal nets) in the VIM"
-        # For each vnf net, we create it and we add it to instanceNetlist.
-        for sce_vnf in scenarioDict['vnfs']:
-            for net in sce_vnf['nets']:
-                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]
-                descriptor_net = instance_dict.get("vnfs", {}).get(sce_vnf["name"], {})
-                net_name = descriptor_net.get("name")
-                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,
+        # Create VNFs
+        vnf_params = {
+            "default_datacenter_id": default_datacenter_id,
+            "myvim_threads_id": myvim_threads_id,
+            "instance_uuid": instance_uuid,
+            "instance_name": instance_name,
+            "instance_action_id": instance_action_id,
+            "myvims": myvims,
+            "cloud_config": cloud_config,
+            "RO_pub_key": tenant[0].get('RO_pub_key'),
+            "instance_parameters": instance_dict,
+        }
+        vnf_params_out = {
+            "task_index": task_index,
+            "uuid_list": uuid_list,
+            "db_instance_nets": db_instance_nets,
+            "db_vim_actions": db_vim_actions,
+            "db_ip_profiles": db_ip_profiles,
+            "db_instance_vnfs": db_instance_vnfs,
+            "db_instance_vms": db_instance_vms,
+            "db_instance_interfaces": db_instance_interfaces,
+            "net2task_id": net2task_id,
+            "sce_net2instance": sce_net2instance,
+        }
+        # sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name'])
+        for sce_vnf in scenarioDict.get('vnfs', ()):  # sce_vnf_list:
+            instantiate_vnf(mydb, sce_vnf, vnf_params, vnf_params_out, rollbackList)
+        task_index = vnf_params_out["task_index"]
+        uuid_list = vnf_params_out["uuid_list"]
+
+        # Create VNFFGs
+        # task_depends_on = []
+        for vnffg in scenarioDict.get('vnffgs', ()):
+            for rsp in vnffg['rsps']:
+                sfs_created = []
+                for cp in rsp['connection_points']:
+                    count = mydb.get_rows(
+                            SELECT='vms.count',
+                            FROM="vms join interfaces on vms.uuid=interfaces.vm_id join sce_rsp_hops as h "
+                                 "on interfaces.uuid=h.ingress_interface_id",
+                            WHERE={'h.uuid': cp['uuid']})[0]['count']
+                    instance_vnf = next((item for item in db_instance_vnfs if item['sce_vnf_id'] == cp['sce_vnf_id']), None)
+                    instance_vms = [item for item in db_instance_vms if item['instance_vnf_id'] == instance_vnf['uuid']]
+                    dependencies = []
+                    for instance_vm in instance_vms:
+                        action = next((item for item in db_vim_actions if item['item_id'] == instance_vm['uuid']), None)
+                        if action:
+                            dependencies.append(action['task_index'])
+                        # TODO: throw exception if count != len(instance_vms)
+                        # TODO: and action shouldn't ever be None
+                    sfis_created = []
+                    for i in range(count):
+                        # create sfis
+                        sfi_uuid = str(uuid4())
+                        extra_params = {
+                            "ingress_interface_id": cp["ingress_interface_id"],
+                            "egress_interface_id": cp["egress_interface_id"]
+                        }
+                        uuid_list.append(sfi_uuid)
+                        db_sfi = {
+                            "uuid": sfi_uuid,
+                            "related": sfi_uuid,
+                            "instance_scenario_id": instance_uuid,
+                            'sce_rsp_hop_id': cp['uuid'],
+                            'datacenter_id': datacenter_id,
+                            'datacenter_tenant_id': myvim_thread_id,
+                            "vim_sfi_id": None, # vim thread will populate
+                        }
+                        db_instance_sfis.append(db_sfi)
+                        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_sfis",
+                            "item_id": sfi_uuid,
+                            "related": sfi_uuid,
+                            "extra": yaml.safe_dump({"params": extra_params, "depends_on": [dependencies[i]]},
+                                                    default_flow_style=True, width=256)
+                        }
+                        sfis_created.append(task_index)
+                        task_index += 1
+                        db_vim_actions.append(db_vim_action)
+                    # create sfs
+                    sf_uuid = str(uuid4())
+                    uuid_list.append(sf_uuid)
+                    db_sf = {
+                        "uuid": sf_uuid,
+                        "related": sf_uuid,
+                        "instance_scenario_id": instance_uuid,
+                        'sce_rsp_hop_id': cp['uuid'],
+                        'datacenter_id': datacenter_id,
+                        'datacenter_tenant_id': myvim_thread_id,
+                        "vim_sf_id": None, # vim thread will populate
+                    }
+                    db_instance_sfs.append(db_sf)
+                    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_sfs",
+                        "item_id": sf_uuid,
+                        "related": sf_uuid,
+                        "extra": yaml.safe_dump({"params": "", "depends_on": sfis_created},
+                                                default_flow_style=True, width=256)
+                    }
+                    sfs_created.append(task_index)
+                    task_index += 1
+                    db_vim_actions.append(db_vim_action)
+                classifier = rsp['classifier']
+
+                # TODO the following ~13 lines can be reused for the sfi case
+                count = mydb.get_rows(
+                        SELECT=('vms.count'),
+                        FROM="vms join interfaces on vms.uuid=interfaces.vm_id join sce_classifiers as c on interfaces.uuid=c.interface_id",
+                        WHERE={'c.uuid': classifier['uuid']})[0]['count']
+                instance_vnf = next((item for item in db_instance_vnfs if item['sce_vnf_id'] == classifier['sce_vnf_id']), None)
+                instance_vms = [item for item in db_instance_vms if item['instance_vnf_id'] == instance_vnf['uuid']]
+                dependencies = []
+                for instance_vm in instance_vms:
+                    action = next((item for item in db_vim_actions if item['item_id'] == instance_vm['uuid']), None)
+                    if action:
+                        dependencies.append(action['task_index'])
+                    # TODO: throw exception if count != len(instance_vms)
+                    # TODO: and action shouldn't ever be None
+                classifications_created = []
+                for i in range(count):
+                    for match in classifier['matches']:
+                        # create classifications
+                        classification_uuid = str(uuid4())
+                        uuid_list.append(classification_uuid)
+                        db_classification = {
+                            "uuid": classification_uuid,
+                            "related": classification_uuid,
+                            "instance_scenario_id": instance_uuid,
+                            'sce_classifier_match_id': match['uuid'],
+                            'datacenter_id': datacenter_id,
+                            'datacenter_tenant_id': myvim_thread_id,
+                            "vim_classification_id": None, # vim thread will populate
+                        }
+                        db_instance_classifications.append(db_classification)
+                        classification_params = {
+                            "ip_proto": match["ip_proto"],
+                            "source_ip": match["source_ip"],
+                            "destination_ip": match["destination_ip"],
+                            "source_port": match["source_port"],
+                            "destination_port": match["destination_port"]
+                        }
+                        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_classifications",
+                            "item_id": classification_uuid,
+                            "related": classification_uuid,
+                            "extra": yaml.safe_dump({"params": classification_params, "depends_on": [dependencies[i]]},
+                                                    default_flow_style=True, width=256)
+                        }
+                        classifications_created.append(task_index)
+                        task_index += 1
+                        db_vim_actions.append(db_vim_action)
+
+                # create sfps
+                sfp_uuid = str(uuid4())
+                uuid_list.append(sfp_uuid)
+                db_sfp = {
+                    "uuid": sfp_uuid,
+                    "related": sfp_uuid,
                     "instance_scenario_id": instance_uuid,
                     "instance_scenario_id": instance_uuid,
-                    "net_id": net["uuid"],
-                    "created": True,
+                    'sce_rsp_id': rsp['uuid'],
                     'datacenter_id': datacenter_id,
                     'datacenter_tenant_id': myvim_thread_id,
                     'datacenter_id': datacenter_id,
                     'datacenter_tenant_id': myvim_thread_id,
+                    "vim_sfp_id": None, # vim thread will populate
                 }
                 }
-                db_instance_nets.append(db_net)
-
+                db_instance_sfps.append(db_sfp)
                 db_vim_action = {
                     "instance_action_id": instance_action_id,
                     "task_index": task_index,
                     "datacenter_vim_id": myvim_thread_id,
                 db_vim_action = {
                     "instance_action_id": instance_action_id,
                     "task_index": task_index,
                     "datacenter_vim_id": myvim_thread_id,
-                    "status": "SCHEDULED",
                     "action": "CREATE",
                     "action": "CREATE",
-                    "item": "instance_nets",
-                    "item_id": net_uuid,
-                    "extra": yaml.safe_dump({"params": (net_name, net_type, net.get('ip_profile',None))},
+                    "status": "SCHEDULED",
+                    "item": "instance_sfps",
+                    "item_id": sfp_uuid,
+                    "related": sfp_uuid,
+                    "extra": yaml.safe_dump({"params": "", "depends_on": sfs_created + classifications_created},
                                             default_flow_style=True, width=256)
                 }
                 task_index += 1
                 db_vim_actions.append(db_vim_action)
                                             default_flow_style=True, width=256)
                 }
                 task_index += 1
                 db_vim_actions.append(db_vim_action)
+        db_instance_action["number_tasks"] = task_index
 
 
-                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)
-        sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name']) 
-        for sce_vnf in sce_vnf_list:
-            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 = {}
-                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"
-                myVMDict['name'] = myVMDict['name'][0:255]   # limit name length
-                #create image at vim in case it not exist
-                image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
-                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)
-                    return
-
-                # 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']
-
-                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 '%s' VM '%s' iface '%s'" %(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 "vpci" in iface and iface["vpci"] is not None:
-                        netDict['vpci'] = iface['vpci']
-                    if "mac" in iface and iface["mac"] is not None:
-                        netDict['mac_address'] = iface['mac']
-                    if "port-security" in iface and iface["port-security"] is not None:
-                        netDict['port_security'] = iface['port-security']
-                    if "floating-ip" in iface and iface["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'),
-                        '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 ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
-                if vm.get("boot_data"):
-                    cloud_config_vm = unify_cloud_config(vm["boot_data"], cloud_config)
-                else:
-                    cloud_config_vm = cloud_config
-                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_index_name = ""
-                    if vm.get('count', 1) > 1:
-                        vm_index_name += "." + chr(97 + vm_index)
-                    task_params = (myVMDict['name']+vm_index_name, myVMDict['description'], myVMDict.get('start', None),
-                                   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"],
-                        # "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)
+        # --> WIM
+        logger.debug('wim_usage:\n%s\n\n', pformat(wim_usage))
+        wan_links = wim_engine.derive_wan_links(wim_usage, db_instance_nets, tenant_id)
+        wim_actions = wim_engine.create_actions(wan_links)
+        wim_actions, db_instance_action = (
+            wim_engine.incorporate_actions(wim_actions, db_instance_action))
+        # <-- WIM
 
         scenarioDict["datacenter2tenant"] = myvim_threads_id
 
 
         scenarioDict["datacenter2tenant"] = myvim_threads_id
 
-        db_instance_action["number_tasks"] = task_index
         db_instance_scenario['datacenter_tenant_id'] = myvim_threads_id[default_datacenter_id]
         db_instance_scenario['datacenter_id'] = default_datacenter_id
         db_tables=[
         db_instance_scenario['datacenter_tenant_id'] = myvim_threads_id[default_datacenter_id]
         db_instance_scenario['datacenter_id'] = default_datacenter_id
         db_tables=[
@@ -3115,7 +3677,12 @@ def create_instance(mydb, tenant_id, instance_dict):
             {"instance_vms": db_instance_vms},
             {"instance_interfaces": db_instance_interfaces},
             {"instance_actions": db_instance_action},
             {"instance_vms": db_instance_vms},
             {"instance_interfaces": db_instance_interfaces},
             {"instance_actions": db_instance_action},
-            {"vim_actions": db_vim_actions}
+            {"instance_sfis": db_instance_sfis},
+            {"instance_sfs": db_instance_sfs},
+            {"instance_classifications": db_instance_classifications},
+            {"instance_sfps": db_instance_sfps},
+            {"instance_wim_nets": wan_links},
+            {"vim_wim_actions": db_vim_actions + wim_actions}
         ]
 
         logger.debug("create_instance done DB tables: %s",
         ]
 
         logger.debug("create_instance done DB tables: %s",
@@ -3124,29 +3691,415 @@ def create_instance(mydb, tenant_id, instance_dict):
         for myvim_thread_id in myvim_threads_id.values():
             vim_threads["running"][myvim_thread_id].insert_task(db_vim_actions)
 
         for myvim_thread_id in myvim_threads_id.values():
             vim_threads["running"][myvim_thread_id].insert_task(db_vim_actions)
 
+        wim_engine.dispatch(wim_actions)
+
         returned_instance = mydb.get_instance_scenario(instance_uuid)
         returned_instance["action_id"] = instance_action_id
         return returned_instance
         returned_instance = mydb.get_instance_scenario(instance_uuid)
         returned_instance["action_id"] = instance_action_id
         return returned_instance
-    except (NfvoException, vimconn.vimconnException, db_base_Exception) as e:
+    except (NfvoException, vimconn.vimconnException, wimconn.WimConnectorError, 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):
             error_text = "VIM Exception"
         message = rollback(mydb, myvims, rollbackList)
         if isinstance(e, db_base_Exception):
             error_text = "database Exception"
         elif isinstance(e, vimconn.vimconnException):
             error_text = "VIM Exception"
+        elif isinstance(e, wimconn.WimConnectorError):
+            error_text = "WIM Exception"
         else:
             error_text = "Exception"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
         # logger.error("create_instance: %s", error_text)
         else:
             error_text = "Exception"
         error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
         # logger.error("create_instance: %s", error_text)
+        logger.exception(e)
         raise NfvoException(error_text, e.http_code)
 
 
         raise NfvoException(error_text, e.http_code)
 
 
+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,
+            "related": net_uuid,
+            'vim_net_id': None,
+            "vim_name": net_name,
+            "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)
+
+        lookfor_filter = {}
+        if net.get("vim-network-name"):
+            lookfor_filter["name"] = net["vim-network-name"]
+        if net.get("vim-network-id"):
+            lookfor_filter["id"] = net["vim-network-id"]
+        if lookfor_filter:
+            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,
+            "related": 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.get('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', httperrors.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']:
+        # skip PDUs
+        if vm.get("pdu_type"):
+            continue
+
+        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), httperrors.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
+        is_management_vm = False
+        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", httperrors.Conflict)
+                else:
+                    raise NfvoException(e_text, httperrors.Internal_Server_Error)
+            if netDict["use"] == "mgmt":
+                is_management_vm = True
+                netDict["type"] = "virtual"
+            if netDict["use"] == "bridge":
+                netDict["type"] = "virtual"
+            if iface.get("vpci"):
+                netDict['vpci'] = iface['vpci']
+            if iface.get("mac"):
+                netDict['mac_address'] = iface['mac']
+            if iface.get("mac_address"):
+                netDict['mac_address'] = iface['mac_address']
+            if iface.get("ip_address"):
+                netDict['ip_address'] = iface['ip_address']
+            if iface.get("port-security") is not None:
+                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 is_management_vm and params["instance_parameters"].get("mgmt_keys"):
+            cloud_config_vm = unify_cloud_config({"key-pairs": params["instance_parameters"]["mgmt_keys"]},
+                                                  cloud_config_vm)
+
+        if vm.get("instance_parameters") and "mgmt_keys" in vm["instance_parameters"]:
+            if vm["instance_parameters"]["mgmt_keys"]:
+                cloud_config_vm = unify_cloud_config({"key-pairs": vm["instance_parameters"]["mgmt_keys"]},
+                                                     cloud_config_vm)
+            if RO_pub_key:
+                cloud_config_vm = unify_cloud_config(cloud_config_vm, {"key-pairs": [RO_pub_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,
+                "related": 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,
+                "related": 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
+
+
 def delete_instance(mydb, tenant_id, instance_id):
     # print "Checking that the instance_id exists and getting the instance dictionary"
     instanceDict = mydb.get_instance_scenario(instance_id, tenant_id)
     # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
     tenant_id = instanceDict["tenant_id"]
 def delete_instance(mydb, tenant_id, instance_id):
     # print "Checking that the instance_id exists and getting the instance dictionary"
     instanceDict = mydb.get_instance_scenario(instance_id, tenant_id)
     # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
     tenant_id = instanceDict["tenant_id"]
-    # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
 
 
+    # --> WIM
+    # We need to retrieve the WIM Actions now, before the instance_scenario is
+    # deleted. The reason for that is that: ON CASCADE rules will delete the
+    # instance_wim_nets record in the database
+    wim_actions = wim_engine.delete_actions(instance_scenario_id=instance_id)
+    # <-- WIM
+
+    # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     # 1. Delete from Database
     message = mydb.delete_instance_scenario(instance_id, tenant_id)
 
     # 1. Delete from Database
     message = mydb.delete_instance_scenario(instance_id, tenant_id)
 
@@ -3155,6 +4108,7 @@ def delete_instance(mydb, tenant_id, instance_id):
     myvims = {}
     myvim_threads = {}
     vimthread_affected = {}
     myvims = {}
     myvim_threads = {}
     vimthread_affected = {}
+    net2vm_dependencies = {}
 
     task_index = 0
     instance_action_id = get_task_id()
 
     task_index = 0
     instance_action_id = get_task_id()
@@ -3167,67 +4121,221 @@ def delete_instance(mydb, tenant_id, instance_id):
         # "number_tasks": 0 # filled bellow
     }
 
         # "number_tasks": 0 # filled bellow
     }
 
-    # 2.1 deleting VMs
+    # 2.1 deleting VNFFGs
+    for sfp in instanceDict.get('sfps', ()):
+        vimthread_affected[sfp["datacenter_tenant_id"]] = None
+        datacenter_key = (sfp["datacenter_id"], sfp["datacenter_tenant_id"])
+        if datacenter_key not in myvims:
+            try:
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sfp["datacenter_id"], sfp["datacenter_tenant_id"])
+            except NfvoException as e:
+                logger.error(str(e))
+                myvim_thread = None
+            myvim_threads[datacenter_key] = myvim_thread
+            vims = get_vim(mydb, tenant_id, datacenter_id=sfp["datacenter_id"],
+                           datacenter_tenant_id=sfp["datacenter_tenant_id"])
+            if len(vims) == 0:
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfp["datacenter_id"], sfp["datacenter_tenant_id"]))
+                myvims[datacenter_key] = None
+            else:
+                myvims[datacenter_key] = vims.values()[0]
+        myvim = myvims[datacenter_key]
+        myvim_thread = myvim_threads[datacenter_key]
+
+        if not myvim:
+            error_msg += "\n    vim_sfp_id={} cannot be deleted because datacenter={} not found".format(sfp['vim_sfp_id'], sfp["datacenter_id"])
+            continue
+        extra = {"params": (sfp['vim_sfp_id'])}
+        db_vim_action = {
+            "instance_action_id": instance_action_id,
+            "task_index": task_index,
+            "datacenter_vim_id": sfp["datacenter_tenant_id"],
+            "action": "DELETE",
+            "status": "SCHEDULED",
+            "item": "instance_sfps",
+            "item_id": sfp["uuid"],
+            "related": sfp["related"],
+            "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
+        }
+        task_index += 1
+        db_vim_actions.append(db_vim_action)
+
+    for classification in instanceDict['classifications']:
+        vimthread_affected[classification["datacenter_tenant_id"]] = None
+        datacenter_key = (classification["datacenter_id"], classification["datacenter_tenant_id"])
+        if datacenter_key not in myvims:
+            try:
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, classification["datacenter_id"], classification["datacenter_tenant_id"])
+            except NfvoException as e:
+                logger.error(str(e))
+                myvim_thread = None
+            myvim_threads[datacenter_key] = myvim_thread
+            vims = get_vim(mydb, tenant_id, datacenter_id=classification["datacenter_id"],
+                           datacenter_tenant_id=classification["datacenter_tenant_id"])
+            if len(vims) == 0:
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(classification["datacenter_id"],
+                                                                                               classification["datacenter_tenant_id"]))
+                myvims[datacenter_key] = None
+            else:
+                myvims[datacenter_key] = vims.values()[0]
+        myvim = myvims[datacenter_key]
+        myvim_thread = myvim_threads[datacenter_key]
+
+        if not myvim:
+            error_msg += "\n    vim_classification_id={} cannot be deleted because datacenter={} not found".format(classification['vim_classification_id'],
+                                                                                                                   classification["datacenter_id"])
+            continue
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"]
+        extra = {"params": (classification['vim_classification_id']), "depends_on": depends_on}
+        db_vim_action = {
+            "instance_action_id": instance_action_id,
+            "task_index": task_index,
+            "datacenter_vim_id": classification["datacenter_tenant_id"],
+            "action": "DELETE",
+            "status": "SCHEDULED",
+            "item": "instance_classifications",
+            "item_id": classification["uuid"],
+            "related": classification["related"],
+            "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
+        }
+        task_index += 1
+        db_vim_actions.append(db_vim_action)
+
+    for sf in instanceDict.get('sfs', ()):
+        vimthread_affected[sf["datacenter_tenant_id"]] = None
+        datacenter_key = (sf["datacenter_id"], sf["datacenter_tenant_id"])
+        if datacenter_key not in myvims:
+            try:
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sf["datacenter_id"], sf["datacenter_tenant_id"])
+            except NfvoException as e:
+                logger.error(str(e))
+                myvim_thread = None
+            myvim_threads[datacenter_key] = myvim_thread
+            vims = get_vim(mydb, tenant_id, datacenter_id=sf["datacenter_id"],
+                           datacenter_tenant_id=sf["datacenter_tenant_id"])
+            if len(vims) == 0:
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sf["datacenter_id"], sf["datacenter_tenant_id"]))
+                myvims[datacenter_key] = None
+            else:
+                myvims[datacenter_key] = vims.values()[0]
+        myvim = myvims[datacenter_key]
+        myvim_thread = myvim_threads[datacenter_key]
+
+        if not myvim:
+            error_msg += "\n    vim_sf_id={} cannot be deleted because datacenter={} not found".format(sf['vim_sf_id'], sf["datacenter_id"])
+            continue
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfps"]
+        extra = {"params": (sf['vim_sf_id']), "depends_on": depends_on}
+        db_vim_action = {
+            "instance_action_id": instance_action_id,
+            "task_index": task_index,
+            "datacenter_vim_id": sf["datacenter_tenant_id"],
+            "action": "DELETE",
+            "status": "SCHEDULED",
+            "item": "instance_sfs",
+            "item_id": sf["uuid"],
+            "related": sf["related"],
+            "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
+        }
+        task_index += 1
+        db_vim_actions.append(db_vim_action)
+
+    for sfi in instanceDict.get('sfis', ()):
+        vimthread_affected[sfi["datacenter_tenant_id"]] = None
+        datacenter_key = (sfi["datacenter_id"], sfi["datacenter_tenant_id"])
+        if datacenter_key not in myvims:
+            try:
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sfi["datacenter_id"], sfi["datacenter_tenant_id"])
+            except NfvoException as e:
+                logger.error(str(e))
+                myvim_thread = None
+            myvim_threads[datacenter_key] = myvim_thread
+            vims = get_vim(mydb, tenant_id, datacenter_id=sfi["datacenter_id"],
+                           datacenter_tenant_id=sfi["datacenter_tenant_id"])
+            if len(vims) == 0:
+                logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sfi["datacenter_id"], sfi["datacenter_tenant_id"]))
+                myvims[datacenter_key] = None
+            else:
+                myvims[datacenter_key] = vims.values()[0]
+        myvim = myvims[datacenter_key]
+        myvim_thread = myvim_threads[datacenter_key]
+
+        if not myvim:
+            error_msg += "\n    vim_sfi_id={} cannot be deleted because datacenter={} not found".format(sfi['vim_sfi_id'], sfi["datacenter_id"])
+            continue
+        depends_on = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfs"]
+        extra = {"params": (sfi['vim_sfi_id']), "depends_on": depends_on}
+        db_vim_action = {
+            "instance_action_id": instance_action_id,
+            "task_index": task_index,
+            "datacenter_vim_id": sfi["datacenter_tenant_id"],
+            "action": "DELETE",
+            "status": "SCHEDULED",
+            "item": "instance_sfis",
+            "item_id": sfi["uuid"],
+            "related": sfi["related"],
+            "extra": yaml.safe_dump(extra, default_flow_style=True, width=256)
+        }
+        task_index += 1
+        db_vim_actions.append(db_vim_action)
+
+    # 2.2 deleting VMs
     # vm_fail_list=[]
     # vm_fail_list=[]
-    for sce_vnf in instanceDict['vnfs']:
+    for sce_vnf in instanceDict.get('vnfs', ()):
         datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
         vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None
         if datacenter_key not in myvims:
             try:
         datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
         vimthread_affected[sce_vnf["datacenter_tenant_id"]] = None
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
+                _, myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             myvim_threads[datacenter_key] = myvim_thread
             vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"],
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             myvim_threads[datacenter_key] = myvim_thread
             vims = get_vim(mydb, tenant_id, datacenter_id=sce_vnf["datacenter_id"],
-                       datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
+                           datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
             if len(vims) == 0:
                 logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"],
             if len(vims) == 0:
                 logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"],
-                                                                                        sce_vnf["datacenter_tenant_id"]))
+                                                                                               sce_vnf["datacenter_tenant_id"]))
                 myvims[datacenter_key] = None
             else:
                 myvims[datacenter_key] = vims.values()[0]
         myvim = myvims[datacenter_key]
         myvim_thread = myvim_threads[datacenter_key]
                 myvims[datacenter_key] = None
             else:
                 myvims[datacenter_key] = vims.values()[0]
         myvim = myvims[datacenter_key]
         myvim_thread = myvim_threads[datacenter_key]
+
         for vm in sce_vnf['vms']:
             if not myvim:
                 error_msg += "\n    VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"])
                 continue
         for vm in sce_vnf['vms']:
             if not myvim:
                 error_msg += "\n    VM id={} cannot be deleted because datacenter={} not found".format(vm['vim_vm_id'], sce_vnf["datacenter_id"])
                 continue
-            try:
-                db_vim_action = {
-                    "instance_action_id": instance_action_id,
-                    "task_index": task_index,
-                    "datacenter_vim_id": sce_vnf["datacenter_tenant_id"],
-                    "action": "DELETE",
-                    "status": "SCHEDULED",
-                    "item": "instance_vms",
-                    "item_id": vm["uuid"],
-                    "extra": yaml.safe_dump({"params": vm["interfaces"]},
-                                            default_flow_style=True, width=256)
-                }
-                task_index += 1
-                db_vim_actions.append(db_vim_action)
-
-            except vimconn.vimconnNotFoundException as e:
-                error_msg+="\n    VM VIM_id={} not found at datacenter={}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"])
-                logger.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
-                    vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'])
-            except vimconn.vimconnException as e:
-                error_msg+="\n    VM VIM_id={} at datacenter={} Error: {} {}".format(vm['vim_vm_id'], sce_vnf["datacenter_id"], e.http_code, str(e))
-                logger.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
-                    e.http_code, vm['name'], vm['uuid'], vm['vim_vm_id'], sce_vnf['vnf_id'], str(e))
+            sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"]
+            db_vim_action = {
+                "instance_action_id": instance_action_id,
+                "task_index": task_index,
+                "datacenter_vim_id": sce_vnf["datacenter_tenant_id"],
+                "action": "DELETE",
+                "status": "SCHEDULED",
+                "item": "instance_vms",
+                "item_id": vm["uuid"],
+                "related": vm["related"],
+                "extra": yaml.safe_dump({"params": vm["interfaces"], "depends_on": sfi_dependencies},
+                                        default_flow_style=True, width=256)
+            }
+            db_vim_actions.append(db_vim_action)
+            for interface in vm["interfaces"]:
+                if not interface.get("instance_net_id"):
+                    continue
+                if interface["instance_net_id"] not in net2vm_dependencies:
+                    net2vm_dependencies[interface["instance_net_id"]] = []
+                net2vm_dependencies[interface["instance_net_id"]].append(task_index)
+            task_index += 1
 
 
-    # 2.2 deleting NETS
+    # 2.3 deleting NETS
     # net_fail_list=[]
     for net in instanceDict['nets']:
     # net_fail_list=[]
     for net in instanceDict['nets']:
-        # TODO if not net['created']:
-        # TODO    continue #skip not created nets
-
         vimthread_affected[net["datacenter_tenant_id"]] = None
         datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
         vimthread_affected[net["datacenter_tenant_id"]] = None
         datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
         if datacenter_key not in myvims:
             try:
-                _,myvim_thread = get_vim_thread(mydb, tenant_id, sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
+                _,myvim_thread = get_vim_thread(mydb, tenant_id, net["datacenter_id"], net["datacenter_tenant_id"])
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
             except NfvoException as e:
                 logger.error(str(e))
                 myvim_thread = None
@@ -3245,36 +4353,39 @@ def delete_instance(mydb, tenant_id, instance_id):
         if not myvim:
             error_msg += "\n    Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"])
             continue
         if not myvim:
             error_msg += "\n    Net VIM_id={} cannot be deleted because datacenter={} not found".format(net['vim_net_id'], net["datacenter_id"])
             continue
-        try:
-            db_vim_action = {
-                "instance_action_id": instance_action_id,
-                "task_index": task_index,
-                "datacenter_vim_id": net["datacenter_tenant_id"],
-                "action": "DELETE",
-                "status": "SCHEDULED",
-                "item": "instance_nets",
-                "item_id": net["uuid"],
-                "extra": yaml.safe_dump({"params": (net['vim_net_id'], net['sdn_net_id'])},
-                                        default_flow_style=True, width=256)
-            }
-            task_index += 1
-            db_vim_actions.append(db_vim_action)
-
-        except vimconn.vimconnNotFoundException as e:
-            error_msg += "\n    NET VIM_id={} not found at datacenter={}".format(net['vim_net_id'], net["datacenter_id"])
-            logger.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
-                        net['uuid'], net['vim_net_id'], str(net['vnf_net_id']))
-        except vimconn.vimconnException as e:
-            error_msg += "\n    NET VIM_id={} at datacenter={} Error: {} {}".format(net['vim_net_id'],
-                                                                                    net["datacenter_id"],
-                                                                                    e.http_code, str(e))
-            logger.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
-                         e.http_code, net['uuid'], net['vim_net_id'], str(net['vnf_net_id']), str(e))
+        extra = {"params": (net['vim_net_id'], net['sdn_net_id'])}
+        if net2vm_dependencies.get(net["uuid"]):
+            extra["depends_on"] = net2vm_dependencies[net["uuid"]]
+        sfi_dependencies = [action["task_index"] for action in db_vim_actions if action["item"] == "instance_sfis"]
+        if len(sfi_dependencies) > 0:
+            if "depends_on" in extra:
+                extra["depends_on"] += sfi_dependencies
+            else:
+                extra["depends_on"] = sfi_dependencies
+        db_vim_action = {
+            "instance_action_id": instance_action_id,
+            "task_index": task_index,
+            "datacenter_vim_id": net["datacenter_tenant_id"],
+            "action": "DELETE",
+            "status": "SCHEDULED",
+            "item": "instance_nets",
+            "item_id": net["uuid"],
+            "related": 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
 
     db_instance_action["number_tasks"] = task_index
+
+    # --> WIM
+    wim_actions, db_instance_action = (
+        wim_engine.incorporate_actions(wim_actions, db_instance_action))
+    # <-- WIM
+
     db_tables = [
         {"instance_actions": db_instance_action},
     db_tables = [
         {"instance_actions": db_instance_action},
-        {"vim_actions": db_vim_actions}
+        {"vim_wim_actions": db_vim_actions + wim_actions}
     ]
 
     logger.debug("delete_instance done DB tables: %s",
     ]
 
     logger.debug("delete_instance done DB tables: %s",
@@ -3283,13 +4394,36 @@ def delete_instance(mydb, tenant_id, instance_id):
     for myvim_thread_id in vimthread_affected.keys():
         vim_threads["running"][myvim_thread_id].insert_task(db_vim_actions)
 
     for myvim_thread_id in vimthread_affected.keys():
         vim_threads["running"][myvim_thread_id].insert_task(db_vim_actions)
 
+    wim_engine.dispatch(wim_actions)
+
     if len(error_msg) > 0:
         return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
                '(error: 404) from VIM: {}'.format(instance_action_id, message, error_msg)
     else:
         return "action_id={} instance {} deleted".format(instance_action_id, message)
 
     if len(error_msg) > 0:
         return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
                '(error: 404) from VIM: {}'.format(instance_action_id, message, error_msg)
     else:
         return "action_id={} instance {} deleted".format(instance_action_id, message)
 
+def get_instance_id(mydb, tenant_id, instance_id):
+    global ovim
+    #check valid tenant_id
+    check_tenant(mydb, tenant_id)
+    #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"),
+            }
+    return instance_dict
 
 
+@deprecated("Instance is automatically refreshed by vim_threads")
 def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenant=None):
     '''Refreshes a scenario instance. It modifies instanceDict'''
     '''Returns:
 def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenant=None):
     '''Refreshes a scenario instance. It modifies instanceDict'''
     '''Returns:
@@ -3462,54 +4596,245 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
     #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
     if len(vims) == 0:
     #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
     vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
     if len(vims) == 0:
-        raise NfvoException("datacenter '{}' not found".format(str(instanceDict['datacenter_id'])), HTTP_Not_Found)
+        raise NfvoException("datacenter '{}' not found".format(str(instanceDict['datacenter_id'])), httperrors.Not_Found)
     myvim = vims.values()[0]
     myvim = vims.values()[0]
+    vm_result = {}
+    vm_error = 0
+    vm_ok = 0
 
 
-    if action_dict.get("create-vdu"):
-        for vdu in action_dict["create-vdu"]:
+    myvim_threads_id = {}
+    if action_dict.get("vdu-scaling"):
+        db_instance_vms = []
+        db_vim_actions = []
+        db_instance_interfaces = []
+        instance_action_id = get_task_id()
+        db_instance_action = {
+            "uuid": instance_action_id,   # same uuid for the instance and the action on create
+            "tenant_id": nfvo_tenant,
+            "instance_id": instance_id,
+            "description": "SCALE",
+        }
+        vm_result["instance_action_id"] = instance_action_id
+        vm_result["created"] = []
+        vm_result["deleted"] = []
+        task_index = 0
+        for vdu in action_dict["vdu-scaling"]:
             vdu_id = vdu.get("vdu-id")
             vdu_id = vdu.get("vdu-id")
+            osm_vdu_id = vdu.get("osm_vdu_id")
+            member_vnf_index = vdu.get("member-vnf-index")
             vdu_count = vdu.get("count", 1)
             vdu_count = vdu.get("count", 1)
-            # get from database TODO
-            # insert tasks TODO
-            pass
+            if vdu_id:
+                target_vms = mydb.get_rows(
+                    FROM="instance_vms as vms join instance_vnfs as vnfs on vms.instance_vnf_id=vnfs.uuid",
+                    WHERE={"vms.uuid": vdu_id},
+                    ORDER_BY="vms.created_at"
+                )
+                if not target_vms:
+                    raise NfvoException("Cannot find the vdu with id {}".format(vdu_id), httperrors.Not_Found)
+            else:
+                if not osm_vdu_id and not member_vnf_index:
+                    raise NfvoException("Invalid input vdu parameters. Must supply either 'vdu-id' of 'osm_vdu_id','member-vnf-index'")
+                target_vms = mydb.get_rows(
+                    # SELECT=("ivms.uuid", "ivnfs.datacenter_id", "ivnfs.datacenter_tenant_id"),
+                    FROM="instance_vms as ivms join instance_vnfs as ivnfs on ivms.instance_vnf_id=ivnfs.uuid"\
+                         " join sce_vnfs as svnfs on ivnfs.sce_vnf_id=svnfs.uuid"\
+                         " join vms on ivms.vm_id=vms.uuid",
+                    WHERE={"vms.osm_id": osm_vdu_id, "svnfs.member_vnf_index": member_vnf_index,
+                           "ivnfs.instance_scenario_id": instance_id},
+                    ORDER_BY="ivms.created_at"
+                )
+                if not target_vms:
+                    raise NfvoException("Cannot find the vdu with osm_vdu_id {} and member-vnf-index {}".format(osm_vdu_id, member_vnf_index), httperrors.Not_Found)
+                vdu_id = target_vms[-1]["uuid"]
+            target_vm = target_vms[-1]
+            datacenter = target_vm["datacenter_id"]
+            myvim_threads_id[datacenter], _ = get_vim_thread(mydb, nfvo_tenant, datacenter)
+
+            if vdu["type"] == "delete":
+                for index in range(0, vdu_count):
+                    target_vm = target_vms[-1-index]
+                    vdu_id = target_vm["uuid"]
+                    # look for nm
+                    vm_interfaces = None
+                    for sce_vnf in instanceDict['vnfs']:
+                        for vm in sce_vnf['vms']:
+                            if vm["uuid"] == vdu_id:
+                                # TODO revise this should not be vm["uuid"]   instance_vms["vm_id"]
+                                vm_interfaces = vm["interfaces"]
+                                break
+
+                    db_vim_action = {
+                        "instance_action_id": instance_action_id,
+                        "task_index": task_index,
+                        "datacenter_vim_id": target_vm["datacenter_tenant_id"],
+                        "action": "DELETE",
+                        "status": "SCHEDULED",
+                        "item": "instance_vms",
+                        "item_id": vdu_id,
+                        "related": target_vm["related"],
+                        "extra": yaml.safe_dump({"params": vm_interfaces},
+                                                default_flow_style=True, width=256)
+                    }
+                    task_index += 1
+                    db_vim_actions.append(db_vim_action)
+                    vm_result["deleted"].append(vdu_id)
+                    # delete from database
+                    db_instance_vms.append({"TO-DELETE": vdu_id})
+
+            else:  # vdu["type"] == "create":
+                iface2iface = {}
+                where = {"item": "instance_vms", "item_id": target_vm["uuid"], "action": "CREATE"}
+
+                vim_action_to_clone = mydb.get_rows(FROM="vim_wim_actions", WHERE=where)
+                if not vim_action_to_clone:
+                    raise NfvoException("Cannot find the vim_action at database with {}".format(where), httperrors.Internal_Server_Error)
+                vim_action_to_clone = vim_action_to_clone[0]
+                extra = yaml.safe_load(vim_action_to_clone["extra"])
+
+                # generate a new depends_on. Convert format TASK-Y into new format TASK-ACTION-XXXX.XXXX.Y
+                # TODO do the same for flavor and image when available
+                task_depends_on = []
+                task_params = extra["params"]
+                task_params_networks = deepcopy(task_params[5])
+                for iface in task_params[5]:
+                    if iface["net_id"].startswith("TASK-"):
+                        if "." not in iface["net_id"]:
+                            task_depends_on.append("{}.{}".format(vim_action_to_clone["instance_action_id"],
+                                                             iface["net_id"][5:]))
+                            iface["net_id"] = "TASK-{}.{}".format(vim_action_to_clone["instance_action_id"],
+                                                                  iface["net_id"][5:])
+                        else:
+                            task_depends_on.append(iface["net_id"][5:])
+                    if "mac_address" in iface:
+                        del iface["mac_address"]
+
+                vm_ifaces_to_clone = mydb.get_rows(FROM="instance_interfaces", WHERE={"instance_vm_id": target_vm["uuid"]})
+                for index in range(0, vdu_count):
+                    vm_uuid = str(uuid4())
+                    vm_name = target_vm.get('vim_name')
+                    try:
+                        suffix = vm_name.rfind("-")
+                        vm_name = vm_name[:suffix+1] + str(index + 1 + int(vm_name[suffix+1:]))
+                    except Exception:
+                        pass
+                    db_instance_vm = {
+                        "uuid": vm_uuid,
+                        'related': vm_uuid,
+                        'instance_vnf_id': target_vm['instance_vnf_id'],
+                        'vm_id': target_vm['vm_id'],
+                        'vim_name': vm_name,
+                    }
+                    db_instance_vms.append(db_instance_vm)
+
+                    for vm_iface in vm_ifaces_to_clone:
+                        iface_uuid = str(uuid4())
+                        iface2iface[vm_iface["uuid"]] = iface_uuid
+                        db_vm_iface = {
+                            "uuid": iface_uuid,
+                            'instance_vm_id': vm_uuid,
+                            "instance_net_id": vm_iface["instance_net_id"],
+                            'interface_id': vm_iface['interface_id'],
+                            'type': vm_iface['type'],
+                            'floating_ip': vm_iface['floating_ip'],
+                            'port_security': vm_iface['port_security']
+                        }
+                        db_instance_interfaces.append(db_vm_iface)
+                    task_params_copy = deepcopy(task_params)
+                    for iface in task_params_copy[5]:
+                        iface["uuid"] = iface2iface[iface["uuid"]]
+                        # increment ip_address
+                        if "ip_address" in iface:
+                            ip = iface.get("ip_address")
+                            i = ip.rfind(".")
+                            if i > 0:
+                                try:
+                                    i += 1
+                                    ip = ip[i:] + str(int(ip[:i]) + 1)
+                                    iface["ip_address"] = ip
+                                except:
+                                    iface["ip_address"] = None
+                    if vm_name:
+                        task_params_copy[0] = vm_name
+                    db_vim_action = {
+                        "instance_action_id": instance_action_id,
+                        "task_index": task_index,
+                        "datacenter_vim_id": vim_action_to_clone["datacenter_vim_id"],
+                        "action": "CREATE",
+                        "status": "SCHEDULED",
+                        "item": "instance_vms",
+                        "item_id": vm_uuid,
+                        "related": vm_uuid,
+                        # ALF
+                        # ALF
+                        # TODO examinar parametros, quitar MAC o incrementar. Incrementar IP y colocar las dependencias con ACTION-asdfasd.
+                        # ALF
+                        # ALF
+                        "extra": yaml.safe_dump({"params": task_params_copy, "depends_on": task_depends_on}, default_flow_style=True, width=256)
+                    }
+                    task_index += 1
+                    db_vim_actions.append(db_vim_action)
+                    vm_result["created"].append(vm_uuid)
+
+        db_instance_action["number_tasks"] = task_index
+        db_tables = [
+            {"instance_vms": db_instance_vms},
+            {"instance_interfaces": db_instance_interfaces},
+            {"instance_actions": db_instance_action},
+            # TODO revise sfps
+            # {"instance_sfis": db_instance_sfis},
+            # {"instance_sfs": db_instance_sfs},
+            # {"instance_classifications": db_instance_classifications},
+            # {"instance_sfps": db_instance_sfps},
+            {"vim_wim_actions": db_vim_actions}
+        ]
+        logger.debug("create_vdu done DB tables: %s",
+                     yaml.safe_dump(db_tables, indent=4, default_flow_style=False))
+        mydb.new_rows(db_tables, [])
+        for myvim_thread in myvim_threads_id.values():
+            vim_threads["running"][myvim_thread].insert_task(db_vim_actions)
+
+        return vm_result
 
     input_vnfs = action_dict.pop("vnfs", [])
     input_vms = action_dict.pop("vms", [])
 
     input_vnfs = action_dict.pop("vnfs", [])
     input_vms = action_dict.pop("vms", [])
-    action_over_all = True if len(input_vnfs)==0 and len (input_vms)==0 else False
-    vm_result = {}
-    vm_error = 0
-    vm_ok = 0
+    action_over_all = True if not input_vnfs and not input_vms else False
     for sce_vnf in instanceDict['vnfs']:
         for vm in sce_vnf['vms']:
     for sce_vnf in instanceDict['vnfs']:
         for vm in sce_vnf['vms']:
-            if not action_over_all:
-                if sce_vnf['uuid'] not in input_vnfs and sce_vnf['vnf_name'] not in input_vnfs and \
-                                vm['uuid'] not in input_vms and vm['name'] not in input_vms:
-                    continue
+            if not action_over_all and sce_vnf['uuid'] not in input_vnfs and sce_vnf['vnf_name'] not in input_vnfs and \
+                    sce_vnf['member_vnf_index'] not in input_vnfs and \
+                    vm['uuid'] not in input_vms and vm['name'] not in input_vms and \
+                    sce_vnf['member_vnf_index'] + "-" + vm['vdu_osm_id'] not in input_vms:  # TODO conside vm_count_index
+                continue
             try:
                 if "add_public_key" in action_dict:
             try:
                 if "add_public_key" in action_dict:
-                    mgmt_access = {}
                     if sce_vnf.get('mgmt_access'):
                         mgmt_access = yaml.load(sce_vnf['mgmt_access'])
                     if sce_vnf.get('mgmt_access'):
                         mgmt_access = yaml.load(sce_vnf['mgmt_access'])
-                        ssh_access = mgmt_access['config-access']['ssh-access']
+                        if not input_vms and mgmt_access.get("vdu-id") != vm['vdu_osm_id']:
+                            continue
+                        default_user = mgmt_access.get("default-user")
+                        password = mgmt_access.get("password")
+                        if mgmt_access.get(vm['vdu_osm_id']):
+                            default_user = mgmt_access[vm['vdu_osm_id']].get("default-user", default_user)
+                            password = mgmt_access[vm['vdu_osm_id']].get("password", password)
+
                         tenant = mydb.get_rows_by_id('nfvo_tenants', nfvo_tenant)
                         try:
                         tenant = mydb.get_rows_by_id('nfvo_tenants', nfvo_tenant)
                         try:
-                            if ssh_access['required'] and ssh_access['default-user']:
-                                if 'ip_address' in vm:
+                            if 'ip_address' in vm:
                                     mgmt_ip = vm['ip_address'].split(';')
                                     mgmt_ip = vm['ip_address'].split(';')
-                                    password = mgmt_access['config-access'].get('password')
                                     priv_RO_key = decrypt_key(tenant[0]['encrypted_RO_priv_key'], tenant[0]['uuid'])
                                     priv_RO_key = decrypt_key(tenant[0]['encrypted_RO_priv_key'], tenant[0]['uuid'])
-                                    myvim.inject_user_key(mgmt_ip[0], ssh_access['default-user'],
+                                    data  = myvim.inject_user_key(mgmt_ip[0], action_dict.get('user', default_user),
                                                           action_dict['add_public_key'],
                                                           password=password, ro_key=priv_RO_key)
                                                           action_dict['add_public_key'],
                                                           password=password, ro_key=priv_RO_key)
-                            else:
-                                raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
-                                                    HTTP_Internal_Server_Error)
+                                    vm_result[ vm['uuid'] ] = {"vim_result": 200,
+                                                    "description": "Public key injected",
+                                                    "name":vm['name']
+                                                    }
                         except KeyError:
                             raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
                         except KeyError:
                             raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
-                                                HTTP_Internal_Server_Error)
+                                                httperrors.Internal_Server_Error)
                     else:
                         raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
                     else:
                         raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm['uuid']),
-                                            HTTP_Internal_Server_Error)
+                                            httperrors.Internal_Server_Error)
                 else:
                     data = myvim.action_vminstance(vm['vim_vm_id'], action_dict)
                     if "console" in action_dict:
                 else:
                     data = myvim.action_vminstance(vm['vim_vm_id'], action_dict)
                     if "console" in action_dict:
@@ -3524,7 +4849,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                                                     }
                             vm_ok +=1
                         elif data["server"]=="127.0.0.1" or data["server"]=="localhost":
                                                     }
                             vm_ok +=1
                         elif data["server"]=="127.0.0.1" or data["server"]=="localhost":
-                            vm_result[ vm['uuid'] ] = {"vim_result": -HTTP_Unauthorized,
+                            vm_result[ vm['uuid'] ] = {"vim_result": -httperrors.Unauthorized,
                                                        "description": "this console is only reachable by local interface",
                                                        "name":vm['name']
                                                     }
                                                        "description": "this console is only reachable by local interface",
                                                        "name":vm['name']
                                                     }
@@ -3559,7 +4884,7 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
         return vm_result
 
 def instance_action_get(mydb, nfvo_tenant, instance_id, action_id):
         return vm_result
 
 def instance_action_get(mydb, nfvo_tenant, instance_id, action_id):
-    filter={}
+    filter = {}
     if nfvo_tenant and nfvo_tenant != "any":
         filter["tenant_id"] = nfvo_tenant
     if instance_id and instance_id != "any":
     if nfvo_tenant and nfvo_tenant != "any":
         filter["tenant_id"] = nfvo_tenant
     if instance_id and instance_id != "any":
@@ -3567,9 +4892,14 @@ def instance_action_get(mydb, nfvo_tenant, instance_id, action_id):
     if action_id:
         filter["uuid"] = action_id
     rows = mydb.get_rows(FROM="instance_actions", WHERE=filter)
     if action_id:
         filter["uuid"] = action_id
     rows = mydb.get_rows(FROM="instance_actions", WHERE=filter)
-    if not rows and action_id:
-        raise NfvoException("Not found any action with this criteria", HTTP_Not_Found)
-    return {"ations": rows}
+    if action_id:
+        if not rows:
+            raise NfvoException("Not found any action with this criteria", httperrors.Not_Found)
+        vim_wim_actions = mydb.get_rows(FROM="vim_wim_actions", WHERE={"instance_action_id": action_id})
+        rows[0]["vim_wim_actions"] = vim_wim_actions
+        # for backward compatibility set vim_actions = vim_wim_actions
+        rows[0]["vim_actions"] = vim_wim_actions
+    return {"actions": rows}
 
 
 def create_or_use_console_proxy_thread(console_server, console_port):
 
 
 def create_or_use_console_proxy_thread(console_server, console_port):
@@ -3593,15 +4923,15 @@ def create_or_use_console_proxy_thread(console_server, console_port):
             #port used, try with onoher
             continue
         except cli.ConsoleProxyException as e:
             #port used, try with onoher
             continue
         except cli.ConsoleProxyException as e:
-            raise NfvoException(str(e), HTTP_Bad_Request)
-    raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict)
+            raise NfvoException(str(e), httperrors.Bad_Request)
+    raise NfvoException("Not found any free 'http_console_ports'", httperrors.Conflict)
 
 
 def check_tenant(mydb, tenant_id):
     '''check that tenant exists at database'''
     tenant = mydb.get_rows(FROM='nfvo_tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id})
     if not tenant:
 
 
 def check_tenant(mydb, tenant_id):
     '''check that tenant exists at database'''
     tenant = mydb.get_rows(FROM='nfvo_tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id})
     if not tenant:
-        raise NfvoException("tenant '{}' not found".format(tenant_id), HTTP_Not_Found)
+        raise NfvoException("tenant '{}' not found".format(tenant_id), httperrors.Not_Found)
     return
 
 def new_tenant(mydb, tenant_dict):
     return
 
 def new_tenant(mydb, tenant_dict):
@@ -3612,9 +4942,9 @@ def new_tenant(mydb, tenant_dict):
         pub_key, priv_key = create_RO_keypair(tenant_uuid)
         tenant_dict['RO_pub_key'] = pub_key
         tenant_dict['encrypted_RO_priv_key'] = priv_key
         pub_key, priv_key = create_RO_keypair(tenant_uuid)
         tenant_dict['RO_pub_key'] = pub_key
         tenant_dict['encrypted_RO_priv_key'] = priv_key
-        mydb.new_row("nfvo_tenants", tenant_dict)
+        mydb.new_row("nfvo_tenants", tenant_dict, confidential_data=True)
     except db_base_Exception as e:
     except db_base_Exception as e:
-        raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict['name']) + str(e), HTTP_Internal_Server_Error)
+        raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict['name']) + str(e), e.http_code)
     return tenant_uuid
 
 def delete_tenant(mydb, tenant):
     return tenant_uuid
 
 def delete_tenant(mydb, tenant):
@@ -3626,22 +4956,33 @@ def delete_tenant(mydb, tenant):
 
 
 def new_datacenter(mydb, datacenter_descriptor):
 
 
 def new_datacenter(mydb, datacenter_descriptor):
+    sdn_port_mapping = None
     if "config" in 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
+        sdn_port_mapping = datacenter_descriptor["config"].pop("sdn-port-mapping", None)
+        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");
     datacenter_type = datacenter_descriptor.get("type", "openvim");
-    module_info = None
+    module_info = None
     try:
         module = "vimconn_" + datacenter_type
         pkg = __import__("osm_ro." + module)
     try:
         module = "vimconn_" + datacenter_type
         pkg = __import__("osm_ro." + module)
-        vim_conn = getattr(pkg, module)
+        vim_conn = getattr(pkg, module)
         # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
     except (IOError, ImportError):
         # if module_info and module_info[0]:
         #    file.close(module_info[0])
         # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
     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)
+        raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}.py' not installed".format(datacenter_type,
+                                                                                                  module),
+                            httperrors.Bad_Request)
 
 
-    datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True)
+    datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True, confidential_data=True)
+    if sdn_port_mapping:
+        try:
+            datacenter_sdn_port_mapping_set(mydb, None, datacenter_id, sdn_port_mapping)
+        except Exception as e:
+            mydb.delete_row_by_id("datacenters", datacenter_id)   # Rollback
+            raise e
     return datacenter_id
 
 
     return datacenter_id
 
 
@@ -3651,16 +4992,20 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
 
     # edit data
     datacenter_id = datacenter['uuid']
 
     # edit data
     datacenter_id = datacenter['uuid']
-    where={'uuid': datacenter['uuid']}
+    where = {'uuid': datacenter['uuid']}
     remove_port_mapping = False
     remove_port_mapping = False
+    new_sdn_port_mapping = None
     if "config" in datacenter_descriptor:
         if datacenter_descriptor['config'] != None:
             try:
                 new_config_dict = datacenter_descriptor["config"]
     if "config" in datacenter_descriptor:
         if datacenter_descriptor['config'] != None:
             try:
                 new_config_dict = datacenter_descriptor["config"]
-                #delete null fields
-                to_delete=[]
+                if "sdn-port-mapping" in new_config_dict:
+                    remove_port_mapping = True
+                    new_sdn_port_mapping = new_config_dict.pop("sdn-port-mapping")
+                # delete null fields
+                to_delete = []
                 for k in new_config_dict:
                 for k in new_config_dict:
-                    if new_config_dict[k] == None:
+                    if new_config_dict[k] is None:
                         to_delete.append(k)
                         if k == 'sdn-controller':
                             remove_port_mapping = True
                         to_delete.append(k)
                         if k == 'sdn-controller':
                             remove_port_mapping = True
@@ -3670,11 +5015,11 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
                     config_text = '{}'
                 config_dict = yaml.load(config_text)
                 config_dict.update(new_config_dict)
                     config_text = '{}'
                 config_dict = yaml.load(config_text)
                 config_dict.update(new_config_dict)
-                #delete null fields
+                # delete null fields
                 for k in to_delete:
                     del config_dict[k]
             except Exception as e:
                 for k in to_delete:
                     del config_dict[k]
             except Exception as e:
-                raise NfvoException("Bad format at datacenter:config " + str(e), HTTP_Bad_Request)
+                raise NfvoException("Bad format at datacenter:config " + str(e), httperrors.Bad_Request)
         if config_dict:
             datacenter_descriptor["config"] = yaml.safe_dump(config_dict, default_flow_style=True, width=256)
         else:
         if config_dict:
             datacenter_descriptor["config"] = yaml.safe_dump(config_dict, default_flow_style=True, width=256)
         else:
@@ -3683,9 +5028,16 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
             try:
                 datacenter_sdn_port_mapping_delete(mydb, None, datacenter_id)
             except ovimException as e:
             try:
                 datacenter_sdn_port_mapping_delete(mydb, None, datacenter_id)
             except ovimException as e:
-                logger.error("Error deleting datacenter-port-mapping " + str(e))
+                raise NfvoException("Error deleting datacenter-port-mapping " + str(e), httperrors.Conflict)
 
     mydb.update_rows('datacenters', datacenter_descriptor, where)
 
     mydb.update_rows('datacenters', datacenter_descriptor, where)
+    if new_sdn_port_mapping:
+        try:
+            datacenter_sdn_port_mapping_set(mydb, None, datacenter_id, new_sdn_port_mapping)
+        except ovimException as e:
+            # Rollback
+            mydb.update_rows('datacenters', datacenter, where)
+            raise NfvoException("Error adding datacenter-port-mapping " + str(e), httperrors.Conflict)
     return datacenter_id
 
 
     return datacenter_id
 
 
@@ -3696,122 +5048,134 @@ def delete_datacenter(mydb, datacenter):
     try:
         datacenter_sdn_port_mapping_delete(mydb, None, datacenter_dict['uuid'])
     except ovimException as e:
     try:
         datacenter_sdn_port_mapping_delete(mydb, None, datacenter_dict['uuid'])
     except ovimException as e:
-        logger.error("Error deleting datacenter-port-mapping " + str(e))
+        raise NfvoException("Error deleting datacenter-port-mapping " + str(e))
     return datacenter_dict['uuid'] + " " + datacenter_dict['name']
 
 
     return datacenter_dict['uuid'] + " " + datacenter_dict['name']
 
 
-def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=None, vim_tenant_name=None, vim_username=None, vim_password=None, config=None):
-    #get datacenter info
-    datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, None, datacenter, vim_user=vim_username, vim_passwd=vim_password)
-    datacenter_name = myvim["name"]
-
-    create_vim_tenant = True if not vim_tenant_id and not vim_tenant_name else False
-
-    # get nfvo_tenant info
-    tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant)
-    if vim_tenant_name==None:
-        vim_tenant_name=tenant_dict['name']
-
-    #check that this association does not exist before
-    tenants_datacenter_dict={"nfvo_tenant_id":tenant_dict['uuid'], "datacenter_id":datacenter_id }
-    tenants_datacenters = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
-    if len(tenants_datacenters)>0:
-        raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id, tenant_dict['uuid']), HTTP_Conflict)
-
-    vim_tenant_id_exist_atdb=False
-    if not create_vim_tenant:
-        where_={"datacenter_id": datacenter_id}
-        if vim_tenant_id!=None:
-            where_["vim_tenant_id"] = vim_tenant_id
-        if vim_tenant_name!=None:
-            where_["vim_tenant_name"] = vim_tenant_name
-        #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:
-            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
+def create_vim_account(mydb, nfvo_tenant, datacenter_id, name=None, vim_id=None, vim_tenant=None, vim_tenant_name=None,
+                       vim_username=None, vim_password=None, config=None):
+    # get datacenter info
+    try:
+        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)
+
+        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']
+
+        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)
+
+        vim_tenant_id_exist_atdb=False
+        if not create_vim_tenant:
+            where_={"datacenter_id": datacenter_id}
+            if vim_tenant!=None:
+                where_["vim_tenant_id"] = vim_tenant
+            if vim_tenant_name!=None:
+                where_["vim_tenant_name"] = vim_tenant_name
+            #check if vim_tenant_id is already at database
+            datacenter_tenants_dict = mydb.get_rows(FROM='datacenter_tenants', WHERE=where_)
+            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
+                datacenter_tenants_dict = {}
+                #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)
+                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 = {}
-            #insert at table datacenter_tenants
-    else: #if vim_tenant_id==None:
-        #create tenant at VIM if not provided
-        try:
-            vim_tenant_id = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name)
-        except vimconn.vimconnException as e:
-            raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id, str(e)), HTTP_Internal_Server_Error)
-        datacenter_tenants_dict = {}
-        datacenter_tenants_dict["created"]="true"
-
-    #fill datacenter_tenants table
-    if not vim_tenant_id_exist_atdb:
-        datacenter_tenants_dict["vim_tenant_id"] = vim_tenant_id
-        datacenter_tenants_dict["vim_tenant_name"] = vim_tenant_name
-        datacenter_tenants_dict["user"] = vim_username
-        datacenter_tenants_dict["passwd"] = vim_password
-        datacenter_tenants_dict["datacenter_id"] = datacenter_id
-        if config:
-            datacenter_tenants_dict["config"] = yaml.safe_dump(config, default_flow_style=True, width=256)
-        id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, add_uuid=True)
-        datacenter_tenants_dict["uuid"] = id_
-
-    #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
-    datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_dict['uuid'], datacenter_id)  # reload data
-    thread_name = get_non_used_vim_name(datacenter_name, datacenter_id, tenant_dict['name'], tenant_dict['uuid'])
-    new_thread = vim_thread.vim_thread(myvim, task_lock, thread_name, datacenter_name, datacenter_tenant_id,
-                                       db=db, db_lock=db_lock, ovim=ovim)
-    new_thread.start()
-    thread_id = datacenter_tenants_dict["uuid"]
-    vim_threads["running"][thread_id] = new_thread
-    return datacenter_id
-
-
-def edit_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=None, vim_tenant_name=None,
-                              vim_username=None, vim_password=None, config=None):
-    #Obtain the data of this datacenter_tenant_id
-    vim_data = mydb.get_rows(
-        SELECT=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
-                "datacenter_tenants.passwd", "datacenter_tenants.config"),
-        FROM="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
-        WHERE={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant,
-               "tenants_datacenters.datacenter_id": datacenter_id})
-
-    logger.debug(str(vim_data))
-    if len(vim_data) < 1:
-        raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id, nfvo_tenant), HTTP_Conflict)
-
-    v = vim_data[0]
-    if v['config']:
-        v['config'] = yaml.load(v['config'])
-
-    if vim_tenant_id:
-        v['vim_tenant_id'] = vim_tenant_id
+            datacenter_tenants_dict["created"]="true"
+
+        #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
+            datacenter_tenants_dict["user"] = vim_username
+            datacenter_tenants_dict["passwd"] = vim_password
+            datacenter_tenants_dict["datacenter_id"] = datacenter_id
+            if name:
+                datacenter_tenants_dict["name"] = name
+            else:
+                datacenter_tenants_dict["name"] = datacenter_name
+            if config:
+                datacenter_tenants_dict["config"] = yaml.safe_dump(config, default_flow_style=True, width=256)
+            id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, add_uuid=True, confidential_data=True)
+            datacenter_tenants_dict["uuid"] = id_
+
+        #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.vim_thread(task_lock, thread_name, datacenter_name, datacenter_tenant_id,
+                                           db=db, db_lock=db_lock, ovim=ovim)
+        new_thread.start()
+        thread_id = datacenter_tenants_dict["uuid"]
+        vim_threads["running"][thread_id] = new_thread
+        return thread_id
+    except vimconn.vimconnException as e:
+        raise NfvoException(str(e), httperrors.Bad_Request)
+
+
+def edit_vim_account(mydb, nfvo_tenant, datacenter_tenant_id, datacenter_id=None, name=None, vim_tenant=None,
+                              vim_tenant_name=None, vim_username=None, vim_password=None, config=None):
+
+    # get vim_account; check is valid for this tenant
+    from_ = "datacenter_tenants as dt JOIN tenants_datacenters as td ON dt.uuid=td.datacenter_tenant_id"
+    where_ = {"td.nfvo_tenant_id": nfvo_tenant}
+    if datacenter_tenant_id:
+        where_["dt.uuid"] = datacenter_tenant_id
+    if datacenter_id:
+        where_["dt.datacenter_id"] = datacenter_id
+    vim_accounts = mydb.get_rows(SELECT="dt.uuid as uuid, config", FROM=from_, WHERE=where_)
+    if not vim_accounts:
+        raise NfvoException("vim_account not found for this tenant", http_code=httperrors.Not_Found)
+    elif len(vim_accounts) > 1:
+        raise NfvoException("found more than one vim_account for this tenant", http_code=httperrors.Conflict)
+    datacenter_tenant_id = vim_accounts[0]["uuid"]
+    original_config = vim_accounts[0]["config"]
+
+    update_ = {}
+    if config:
+        original_config_dict = yaml.load(original_config)
+        original_config_dict.update(config)
+        update["config"] = yaml.safe_dump(original_config_dict, default_flow_style=True, width=256)
+    if name:
+        update_['name'] = name
+    if vim_tenant:
+        update_['vim_tenant_id'] = vim_tenant
     if vim_tenant_name:
     if vim_tenant_name:
-        v['vim_tenant_name'] = vim_tenant_name
+        update_['vim_tenant_name'] = vim_tenant_name
     if vim_username:
     if vim_username:
-        v['user'] = vim_username
+        update_['user'] = vim_username
     if vim_password:
     if vim_password:
-        v['passwd'] = vim_password
-    if config:
-        if not v['config']:
-            v['config'] = {}
-        v['config'].update(config)
-
-    logger.debug(str(v))
-    deassociate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=v['vim_tenant_id'])
-    associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter_id, vim_tenant_id=v['vim_tenant_id'], vim_tenant_name=v['vim_tenant_name'],
-                                   vim_username=v['user'], vim_password=v['passwd'], config=v['config'])
+        update_['passwd'] = vim_password
+    if update_:
+        mydb.update_rows("datacenter_tenants", UPDATE=update_, WHERE={"uuid": datacenter_tenant_id})
 
 
-    return datacenter_id
-
-def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=None):
-    #get datacenter info
-    datacenter_id, myvim = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
+    vim_threads["running"][datacenter_tenant_id].insert_task("reload")
+    return datacenter_tenant_id
 
 
+def delete_vim_account(mydb, tenant_id, vim_account_id, datacenter=None):
     #get nfvo_tenant info
     if not tenant_id or tenant_id=="any":
         tenant_uuid = None
     #get nfvo_tenant info
     if not tenant_id or tenant_id=="any":
         tenant_uuid = None
@@ -3820,12 +5184,17 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=
         tenant_uuid = tenant_dict['uuid']
 
     #check that this association exist before
         tenant_uuid = tenant_dict['uuid']
 
     #check that this association exist before
-    tenants_datacenter_dict={"datacenter_id":datacenter_id }
+    tenants_datacenter_dict = {}
+    if datacenter:
+        datacenter_id, _ = get_datacenter_uuid(mydb, tenant_uuid, datacenter)
+        tenants_datacenter_dict["datacenter_id"] = datacenter_id
+    elif vim_account_id:
+        tenants_datacenter_dict["datacenter_tenant_id"] = vim_account_id
     if tenant_uuid:
         tenants_datacenter_dict["nfvo_tenant_id"] = tenant_uuid
     tenant_datacenter_list = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
     if len(tenant_datacenter_list)==0 and tenant_uuid:
     if tenant_uuid:
         tenants_datacenter_dict["nfvo_tenant_id"] = tenant_uuid
     tenant_datacenter_list = mydb.get_rows(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
     if len(tenant_datacenter_list)==0 and tenant_uuid:
-        raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id, tenant_dict['uuid']), HTTP_Not_Found)
+        raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id, tenant_dict['uuid']), httperrors.Not_Found)
 
     #delete this association
     mydb.delete_row(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
 
     #delete this association
     mydb.delete_row(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
@@ -3840,6 +5209,7 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=
             if vim_tenant_dict['created']=='true':
                 #delete tenant at VIM if created by NFVO
                 try:
             if vim_tenant_dict['created']=='true':
                 #delete tenant at VIM if created by NFVO
                 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:
                     warning = "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict['vim_tenant_id'], str(e))
                     myvim.delete_tenant(vim_tenant_dict['vim_tenant_id'])
                 except vimconn.vimconnException as e:
                     warning = "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict['vim_tenant_id'], str(e))
@@ -3848,9 +5218,10 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=
             logger.error("Cannot delete datacenter_tenants " + str(e))
             pass  # the error will be caused because dependencies, vim_tenant can not be deleted
         thread_id = tenant_datacenter_item["datacenter_tenant_id"]
             logger.error("Cannot delete datacenter_tenants " + str(e))
             pass  # the error will be caused because dependencies, vim_tenant can not be deleted
         thread_id = tenant_datacenter_item["datacenter_tenant_id"]
-        thread = vim_threads["running"][thread_id]
-        thread.insert_task("exit")
-        vim_threads["deleting"][thread_id] = thread
+        thread = vim_threads["running"].get(thread_id)
+        if thread:
+            thread.insert_task("exit")
+            vim_threads["deleting"][thread_id] = thread
     return "datacenter {} detached. {}".format(datacenter_id, warning)
 
 
     return "datacenter {} detached. {}".format(datacenter_id, warning)
 
 
@@ -3859,13 +5230,19 @@ def datacenter_action(mydb, tenant_id, datacenter, action_dict):
     #get datacenter info
     datacenter_id, myvim  = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
 
     #get datacenter info
     datacenter_id, myvim  = get_datacenter_by_name_uuid(mydb, tenant_id, datacenter)
 
-    if 'net-update' in action_dict:
+    if 'check-connectivity' in action_dict:
+        try:
+            myvim.check_vim_connectivity()
+        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:
             #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
         try:
             nets = myvim.get_network_list(filter_dict={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
             #print content
         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), HTTP_Internal_Server_Error)
+            raise NfvoException(str(e), httperrors.Internal_Server_Error)
         #update nets Change from VIM format to NFVO format
         net_list=[]
         for net in nets:
         #update nets Change from VIM format to NFVO format
         net_list=[]
         for net in nets:
@@ -3894,7 +5271,7 @@ def datacenter_action(mydb, tenant_id, datacenter, action_dict):
         return result
 
     else:
         return result
 
     else:
-        raise NfvoException("Unknown action " + str(action_dict), HTTP_Bad_Request)
+        raise NfvoException("Unknown action " + str(action_dict), httperrors.Bad_Request)
 
 
 def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict):
 
 
 def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict):
@@ -3924,11 +5301,11 @@ def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None):
         vim_nets = myvim.get_network_list(filter_dict=filter_dict)
     except vimconn.vimconnException as e:
         #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
         vim_nets = myvim.get_network_list(filter_dict=filter_dict)
     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), HTTP_Internal_Server_Error)
+        raise NfvoException(str(e), httperrors.Internal_Server_Error)
     if len(vim_nets)>1 and action_dict:
     if len(vim_nets)>1 and action_dict:
-        raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict)
+        raise NfvoException("more than two networks found, specify with vim_id", httperrors.Conflict)
     elif len(vim_nets)==0: # and action_dict:
     elif len(vim_nets)==0: # and action_dict:
-        raise NfvoException("Not found a network at VIM with " + str(filter_dict), HTTP_Not_Found)
+        raise NfvoException("Not found a network at VIM with " + str(filter_dict), httperrors.Not_Found)
     net_list=[]
     for net in vim_nets:
         net_nfvo={'datacenter_id': datacenter_id}
     net_list=[]
     for net in vim_nets:
         net_nfvo={'datacenter_id': datacenter_id}
@@ -3969,11 +5346,11 @@ def get_sdn_net_id(mydb, tenant_id, datacenter, network_id):
     # ensure the network is defined
     if len(network) == 0:
         raise NfvoException("Network {} is not present in the system".format(network_id),
     # ensure the network is defined
     if len(network) == 0:
         raise NfvoException("Network {} is not present in the system".format(network_id),
-                            HTTP_Bad_Request)
+                            httperrors.Bad_Request)
 
     # ensure there is only one network with the provided name
     if len(network) > 1:
 
     # ensure there is only one network with the provided name
     if len(network) > 1:
-        raise NfvoException("Multiple networks present in vim identified by {}".format(network_id), HTTP_Bad_Request)
+        raise NfvoException("Multiple networks present in vim identified by {}".format(network_id), httperrors.Bad_Request)
 
     # ensure it is a dataplane network
     if network[0]['type'] != 'data':
 
     # ensure it is a dataplane network
     if network[0]['type'] != 'data':
@@ -3992,7 +5369,7 @@ def get_sdn_net_id(mydb, tenant_id, datacenter, network_id):
         result =  mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)
     except db_base_Exception as e:
         raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
         result =  mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)
     except db_base_Exception as e:
         raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
-            network_id) + str(e), HTTP_Internal_Server_Error)
+            network_id) + str(e), e.http_code)
 
     sdn_net_counter = 0
     for net in result:
 
     sdn_net_counter = 0
     for net in result:
@@ -4006,7 +5383,7 @@ def get_sdn_net_id(mydb, tenant_id, datacenter, network_id):
         return sdn_net_id
     else:
         raise NfvoException("More than one SDN network is associated to vim network {}".format(
         return sdn_net_id
     else:
         raise NfvoException("More than one SDN network is associated to vim network {}".format(
-            network_id), HTTP_Internal_Server_Error)
+            network_id), httperrors.Internal_Server_Error)
 
 def get_sdn_controller_id(mydb, datacenter):
     # Obtain sdn controller id
 
 def get_sdn_controller_id(mydb, datacenter):
     # Obtain sdn controller id
@@ -4020,12 +5397,12 @@ def vim_net_sdn_attach(mydb, tenant_id, datacenter, network_id, descriptor):
     try:
         sdn_network_id = get_sdn_net_id(mydb, tenant_id, datacenter, network_id)
         if not sdn_network_id:
     try:
         sdn_network_id = get_sdn_net_id(mydb, tenant_id, datacenter, network_id)
         if not sdn_network_id:
-            raise NfvoException("No SDN network is associated to vim-network {}".format(network_id), HTTP_Internal_Server_Error)
+            raise NfvoException("No SDN network is associated to vim-network {}".format(network_id), httperrors.Internal_Server_Error)
 
         #Obtain sdn controller id
         controller_id = get_sdn_controller_id(mydb, datacenter)
         if not controller_id:
 
         #Obtain sdn controller id
         controller_id = get_sdn_controller_id(mydb, datacenter)
         if not controller_id:
-            raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter), HTTP_Internal_Server_Error)
+            raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter), httperrors.Internal_Server_Error)
 
         #Obtain sdn controller info
         sdn_controller = ovim.show_of_controller(controller_id)
 
         #Obtain sdn controller info
         sdn_controller = ovim.show_of_controller(controller_id)
@@ -4046,10 +5423,10 @@ def vim_net_sdn_attach(mydb, tenant_id, datacenter, network_id, descriptor):
         result = ovim.new_port(port_data)
     except ovimException as e:
         raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
         result = ovim.new_port(port_data)
     except ovimException as e:
         raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
-            sdn_network_id, network_id) + str(e), HTTP_Internal_Server_Error)
+            sdn_network_id, network_id) + str(e), httperrors.Internal_Server_Error)
     except db_base_Exception as e:
         raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
     except db_base_Exception as e:
         raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
-            network_id) + str(e), HTTP_Internal_Server_Error)
+            network_id) + str(e), e.http_code)
 
     return 'Port uuid: '+ result
 
 
     return 'Port uuid: '+ result
 
@@ -4060,7 +5437,7 @@ def vim_net_sdn_detach(mydb, tenant_id, datacenter, network_id, port_id=None):
         sdn_network_id = get_sdn_net_id(mydb, tenant_id, datacenter, network_id)
         if not sdn_network_id:
             raise NfvoException("No SDN network is associated to vim-network {}".format(network_id),
         sdn_network_id = get_sdn_net_id(mydb, tenant_id, datacenter, network_id)
         if not sdn_network_id:
             raise NfvoException("No SDN network is associated to vim-network {}".format(network_id),
-                                HTTP_Internal_Server_Error)
+                                httperrors.Internal_Server_Error)
         #in case no port_id is specified only ports marked as 'external_port' will be detached
         filter = {'name': 'external_port', 'net_id': sdn_network_id}
 
         #in case no port_id is specified only ports marked as 'external_port' will be detached
         filter = {'name': 'external_port', 'net_id': sdn_network_id}
 
@@ -4068,11 +5445,11 @@ def vim_net_sdn_detach(mydb, tenant_id, datacenter, network_id, port_id=None):
         port_list = ovim.get_ports(columns={'uuid'}, filter=filter)
     except ovimException as e:
         raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id) + str(e),
         port_list = ovim.get_ports(columns={'uuid'}, filter=filter)
     except ovimException as e:
         raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id) + str(e),
-                            HTTP_Internal_Server_Error)
+                            httperrors.Internal_Server_Error)
 
     if len(port_list) == 0:
         raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id),
 
     if len(port_list) == 0:
         raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id),
-                            HTTP_Bad_Request)
+                            httperrors.Bad_Request)
 
     port_uuid_list = []
     for port in port_list:
 
     port_uuid_list = []
     for port in port_list:
@@ -4080,7 +5457,7 @@ def vim_net_sdn_detach(mydb, tenant_id, datacenter, network_id, port_id=None):
             port_uuid_list.append(port['uuid'])
             ovim.delete_port(port['uuid'])
         except ovimException as e:
             port_uuid_list.append(port['uuid'])
             ovim.delete_port(port['uuid'])
         except ovimException as e:
-            raise NfvoException("ovimException deleting port {} for net {}. ".format(port['uuid'], network_id) + str(e), HTTP_Internal_Server_Error)
+            raise NfvoException("ovimException deleting port {} for net {}. ".format(port['uuid'], network_id) + str(e), httperrors.Internal_Server_Error)
 
     return 'Detached ports uuid: {}'.format(','.join(port_uuid_list))
 
 
     return 'Detached ports uuid: {}'.format(','.join(port_uuid_list))
 
@@ -4100,7 +5477,7 @@ def vim_action_get(mydb, tenant_id, datacenter, item, name):
 
             if len(content) == 0:
                 raise NfvoException("Network {} is not present in the system. ".format(name),
 
             if len(content) == 0:
                 raise NfvoException("Network {} is not present in the system. ".format(name),
-                                    HTTP_Bad_Request)
+                                    httperrors.Bad_Request)
 
             #Update the networks with the attached ports
             for net in content:
 
             #Update the networks with the attached ports
             for net in content:
@@ -4110,7 +5487,7 @@ def vim_action_get(mydb, tenant_id, datacenter, item, name):
                         #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
                         port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id})
                     except ovimException as e:
                         #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
                         port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id})
                     except ovimException as e:
-                        raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id) + str(e), HTTP_Internal_Server_Error)
+                        raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id) + str(e), httperrors.Internal_Server_Error)
                     #Remove field name and if port name is external_port save it as 'type'
                     for port in port_list:
                         if port['name'] == 'external_port':
                     #Remove field name and if port name is external_port save it as 'type'
                     for port in port_list:
                         if port['name'] == 'external_port':
@@ -4125,7 +5502,7 @@ def vim_action_get(mydb, tenant_id, datacenter, item, name):
 
             content = myvim.get_image_list(filter_dict=filter_dict)
         else:
 
             content = myvim.get_image_list(filter_dict=filter_dict)
         else:
-            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
+            raise NfvoException(item + "?", httperrors.Method_Not_Allowed)
         logger.debug("vim_action response %s", content) #update nets Change from VIM format to NFVO format
         if name and len(content)==1:
             return {item[:-1]: content[0]}
         logger.debug("vim_action response %s", content) #update nets Change from VIM format to NFVO format
         if name and len(content)==1:
             return {item[:-1]: content[0]}
@@ -4150,9 +5527,9 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
     logger.debug("vim_action_delete vim response: " + str(content))
     items = content.values()[0]
     if type(items)==list and len(items)==0:
     logger.debug("vim_action_delete vim response: " + str(content))
     items = content.values()[0]
     if type(items)==list and len(items)==0:
-        raise NfvoException("Not found " + item, HTTP_Not_Found)
+        raise NfvoException("Not found " + item, httperrors.Not_Found)
     elif type(items)==list and len(items)>1:
     elif type(items)==list and len(items)>1:
-        raise NfvoException("Found more than one {} with this name. Use uuid.".format(item), HTTP_Not_Found)
+        raise NfvoException("Found more than one {} with this name. Use uuid.".format(item), httperrors.Not_Found)
     else: # it is a dict
         item_id = items["id"]
         item_name = str(items.get("name"))
     else: # it is a dict
         item_id = items["id"]
         item_name = str(items.get("name"))
@@ -4168,7 +5545,7 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
                 except ovimException as e:
                     raise NfvoException(
                         "ovimException obtaining external ports for net {}. ".format(network_id) + str(e),
                 except ovimException as e:
                     raise NfvoException(
                         "ovimException obtaining external ports for net {}. ".format(network_id) + str(e),
-                        HTTP_Internal_Server_Error)
+                        httperrors.Internal_Server_Error)
 
                 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
                 for port in port_list:
 
                 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
                 for port in port_list:
@@ -4179,7 +5556,7 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
                     mydb.delete_row(FROM='instance_nets', WHERE={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id, 'vim_net_id': item_id})
                 except db_base_Exception as e:
                     raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence) +
                     mydb.delete_row(FROM='instance_nets', WHERE={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id, 'vim_net_id': item_id})
                 except db_base_Exception as e:
                     raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence) +
-                                        str(e), HTTP_Internal_Server_Error)
+                                        str(e), e.http_code)
 
                 #Delete the SDN network
                 try:
 
                 #Delete the SDN network
                 try:
@@ -4187,7 +5564,7 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
                 except ovimException as e:
                     logger.error("ovimException deleting SDN network={} ".format(sdn_network_id) + str(e), exc_info=True)
                     raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id) + str(e),
                 except ovimException as e:
                     logger.error("ovimException deleting SDN network={} ".format(sdn_network_id) + str(e), exc_info=True)
                     raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id) + str(e),
-                                        HTTP_Internal_Server_Error)
+                                        httperrors.Internal_Server_Error)
 
             content = myvim.delete_network(item_id)
         elif item=="tenants":
 
             content = myvim.delete_network(item_id)
         elif item=="tenants":
@@ -4195,7 +5572,7 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
         elif item == "images":
             content = myvim.delete_image(item_id)
         else:
         elif item == "images":
             content = myvim.delete_image(item_id)
         else:
-            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
+            raise NfvoException(item + "?", httperrors.Method_Not_Allowed)
     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)
     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)
@@ -4217,38 +5594,47 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
             net_public = net.pop("shared", False)
             net_ipprofile = net.pop("ip_profile", None)
             net_vlan = net.pop("vlan", None)
             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'):
 
             #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'):
+                #obtain datacenter_tenant_id
+                datacenter_tenant_id = mydb.get_rows(SELECT=('uuid',),
+                                                     FROM='datacenter_tenants',
+                                                     WHERE={'datacenter_id': datacenter})[0]['uuid']
                 try:
                     sdn_network = {}
                     sdn_network['vlan'] = net_vlan
                     sdn_network['type'] = net_type
                     sdn_network['name'] = net_name
                 try:
                     sdn_network = {}
                     sdn_network['vlan'] = net_vlan
                     sdn_network['type'] = net_type
                     sdn_network['name'] = net_name
-                    ovim_content = ovim.new_network(sdn_network)
+                    sdn_network['region'] = datacenter_tenant_id
+                    ovim_content  = ovim.new_network(sdn_network)
                 except ovimException as e:
                 except ovimException as e:
-                    self.logger.error("ovimException creating SDN network={} ".format(
+                    logger.error("ovimException creating SDN network={} ".format(
                         sdn_network) + str(e), exc_info=True)
                     raise NfvoException("ovimException creating SDN network={} ".format(sdn_network) + str(e),
                         sdn_network) + str(e), exc_info=True)
                     raise NfvoException("ovimException creating SDN network={} ".format(sdn_network) + str(e),
-                                        HTTP_Internal_Server_Error)
+                                        httperrors.Internal_Server_Error)
 
                 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary  vim_net_id <->sdn_net_id
                 # use instance_scenario_id=None to distinguish from real instaces of nets
 
                 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary  vim_net_id <->sdn_net_id
                 # use instance_scenario_id=None to distinguish from real instaces of nets
-                correspondence = {'instance_scenario_id': None, 'sdn_net_id': ovim_content, 'vim_net_id': content}
-                #obtain datacenter_tenant_id
-                correspondence['datacenter_tenant_id'] = mydb.get_rows(SELECT=('uuid',), FROM='datacenter_tenants', WHERE={'datacenter_id': datacenter})[0]['uuid']
-
+                correspondence = {'instance_scenario_id': None,
+                                  'sdn_net_id': ovim_content,
+                                  'vim_net_id': content,
+                                  'datacenter_tenant_id': datacenter_tenant_id
+                                  }
                 try:
                     mydb.new_row('instance_nets', correspondence, add_uuid=True)
                 except db_base_Exception as e:
                 try:
                     mydb.new_row('instance_nets', correspondence, add_uuid=True)
                 except db_base_Exception as e:
-                    raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence) +
-                                        str(e), HTTP_Internal_Server_Error)
+                    raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: {}".format(
+                        correspondence, e), e.http_code)
         elif item=="tenants":
             tenant = descriptor["tenant"]
             content = myvim.new_tenant(tenant["name"], tenant.get("description"))
         else:
         elif item=="tenants":
             tenant = descriptor["tenant"]
             content = myvim.new_tenant(tenant["name"], tenant.get("description"))
         else:
-            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
+            raise NfvoException(item + "?", httperrors.Method_Not_Allowed)
     except vimconn.vimconnException as e:
         raise NfvoException("Not possible to create {} at VIM: {}".format(item, str(e)), e.http_code)
 
     except vimconn.vimconnException as e:
         raise NfvoException("Not possible to create {} at VIM: {}".format(item, str(e)), e.http_code)
 
@@ -4282,7 +5668,7 @@ def sdn_controller_delete(mydb, tenant_id, controller_id):
         if datacenter['config']:
             config = yaml.load(datacenter['config'])
             if 'sdn-controller' in config and config['sdn-controller'] == controller_id:
         if datacenter['config']:
             config = yaml.load(datacenter['config'])
             if 'sdn-controller' in config and config['sdn-controller'] == controller_id:
-                raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id, datacenter['uuid']), HTTP_Conflict)
+                raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id, datacenter['uuid']), httperrors.Conflict)
 
     data = ovim.delete_of_controller(controller_id)
     msg = 'SDN controller {} deleted'.format(data)
 
     data = ovim.delete_of_controller(controller_id)
     msg = 'SDN controller {} deleted'.format(data)
@@ -4292,12 +5678,12 @@ def sdn_controller_delete(mydb, tenant_id, controller_id):
 def datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, sdn_port_mapping):
     controller = mydb.get_rows(FROM="datacenters", SELECT=("config",), WHERE={"uuid":datacenter_id})
     if len(controller) < 1:
 def datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, sdn_port_mapping):
     controller = mydb.get_rows(FROM="datacenters", SELECT=("config",), WHERE={"uuid":datacenter_id})
     if len(controller) < 1:
-        raise NfvoException("Datacenter {} not present in the database".format(datacenter_id), HTTP_Not_Found)
+        raise NfvoException("Datacenter {} not present in the database".format(datacenter_id), httperrors.Not_Found)
 
     try:
         sdn_controller_id = yaml.load(controller[0]["config"])["sdn-controller"]
     except:
 
     try:
         sdn_controller_id = yaml.load(controller[0]["config"])["sdn-controller"]
     except:
-        raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id), HTTP_Bad_Request)
+        raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id), httperrors.Bad_Request)
 
     sdn_controller = ovim.show_of_controller(sdn_controller_id)
     switch_dpid = sdn_controller["dpid"]
 
     sdn_controller = ovim.show_of_controller(sdn_controller_id)
     switch_dpid = sdn_controller["dpid"]
@@ -4308,13 +5694,14 @@ def datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, sdn_port_map
         element = dict()
         element["compute_node"] = compute_node["compute_node"]
         for port in compute_node["ports"]:
         element = dict()
         element["compute_node"] = compute_node["compute_node"]
         for port in compute_node["ports"]:
-            element["pci"] = port.get("pci")
+            pci = port.get("pci")
             element["switch_port"] = port.get("switch_port")
             element["switch_mac"] = port.get("switch_mac")
             element["switch_port"] = port.get("switch_port")
             element["switch_mac"] = port.get("switch_mac")
-            if not element["pci"] or not (element["switch_port"] or element["switch_mac"]):
-                raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
-                                     " or 'switch_mac'", HTTP_Bad_Request)
-            maps.append(dict(element))
+            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)
 
 
     return ovim.set_of_port_mapping(maps, ofc_id=sdn_controller_id, switch_dpid=switch_dpid, region=datacenter_id)
 
@@ -4338,10 +5725,10 @@ def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id):
             result["dpid"] = sdn_controller["dpid"]
 
     if result["sdn-controller"] == None:
             result["dpid"] = sdn_controller["dpid"]
 
     if result["sdn-controller"] == None:
-        raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id), HTTP_Bad_Request)
+        raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id), httperrors.Bad_Request)
     if result["dpid"] == None:
         raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result["sdn-controller"]),
     if result["dpid"] == None:
         raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result["sdn-controller"]),
-                        HTTP_Internal_Server_Error)
+                        httperrors.Internal_Server_Error)
 
     if len(maps) == 0:
         return result
 
     if len(maps) == 0:
         return result
@@ -4349,9 +5736,9 @@ def datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id):
     ports_correspondence_dict = dict()
     for link in maps:
         if result["sdn-controller"] != link["ofc_id"]:
     ports_correspondence_dict = dict()
     for link in maps:
         if result["sdn-controller"] != link["ofc_id"]:
-            raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error)
+            raise NfvoException("The sdn-controller specified for different port mappings differ", httperrors.Internal_Server_Error)
         if result["dpid"] != link["switch_dpid"]:
         if result["dpid"] != link["switch_dpid"]:
-            raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error)
+            raise NfvoException("The dpid specified for different port mappings differ", httperrors.Internal_Server_Error)
         element = dict()
         element["pci"] = link["pci"]
         if link["switch_port"]:
         element = dict()
         element["pci"] = link["pci"]
         if link["switch_port"]:
@@ -4390,10 +5777,10 @@ def create_RO_keypair(tenant_id):
     try:
         public_key = key.publickey().exportKey('OpenSSH')
         if isinstance(public_key, ValueError):
     try:
         public_key = key.publickey().exportKey('OpenSSH')
         if isinstance(public_key, ValueError):
-            raise NfvoException("Unable to create public key: {}".format(public_key), HTTP_Internal_Server_Error)
+            raise NfvoException("Unable to create public key: {}".format(public_key), httperrors.Internal_Server_Error)
         private_key = key.exportKey(passphrase=tenant_id, pkcs=8)
     except (ValueError, NameError) as e:
         private_key = key.exportKey(passphrase=tenant_id, pkcs=8)
     except (ValueError, NameError) as e:
-        raise NfvoException("Unable to create private key: {}".format(e), HTTP_Internal_Server_Error)
+        raise NfvoException("Unable to create private key: {}".format(e), httperrors.Internal_Server_Error)
     return public_key, private_key
 
 def decrypt_key (key, tenant_id):
     return public_key, private_key
 
 def decrypt_key (key, tenant_id):
@@ -4409,7 +5796,7 @@ def decrypt_key (key, tenant_id):
         key = RSA.importKey(key,tenant_id)
         unencrypted_key = key.exportKey('PEM')
         if isinstance(unencrypted_key, ValueError):
         key = RSA.importKey(key,tenant_id)
         unencrypted_key = key.exportKey('PEM')
         if isinstance(unencrypted_key, ValueError):
-            raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key), HTTP_Internal_Server_Error)
+            raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key), httperrors.Internal_Server_Error)
     except ValueError as e:
     except ValueError as e:
-        raise NfvoException("Unable to decrypt the private key: {}".format(e), HTTP_Internal_Server_Error)
+        raise NfvoException("Unable to decrypt the private key: {}".format(e), httperrors.Internal_Server_Error)
     return unencrypted_key
     return unencrypted_key