v0.4.41 logging added. Split database into a base class db_base with general methods...
authortierno <alfonso.tiernosepulveda@telefonica.com>
Mon, 11 Jul 2016 12:32:37 +0000 (14:32 +0200)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Mon, 11 Jul 2016 12:32:37 +0000 (14:32 +0200)
Change-Id: Iad677a18e96692b3eab28e73c2fc5cd36a13ae1f
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
db_base.py [new file with mode: 0644]
httpserver.py
nfvo.py
nfvo_db.py
openmano_schemas.py
openmanod.cfg
openmanod.py
scripts/install-openmano.sh

diff --git a/db_base.py b/db_base.py
new file mode 100644 (file)
index 0000000..265752f
--- /dev/null
@@ -0,0 +1,650 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# This file is part of openmano
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+'''
+Base class for openmano database manipulation
+'''
+__author__="Alfonso Tierno"
+__date__ ="$4-Apr-2016 10:05:01$"
+
+import MySQLdb as mdb
+import uuid as myUuid
+import  utils as af
+import json
+#import yaml
+import time
+import logging
+import datetime
+from jsonschema import validate as js_v, exceptions as js_e
+
+HTTP_Bad_Request = 400
+HTTP_Unauthorized = 401 
+HTTP_Not_Found = 404 
+HTTP_Method_Not_Allowed = 405 
+HTTP_Request_Timeout = 408
+HTTP_Conflict = 409
+HTTP_Service_Unavailable = 503 
+HTTP_Internal_Server_Error = 500 
+
+def _check_valid_uuid(uuid):
+    id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
+    id_schema2 = {"type" : "string", "pattern": "^[a-fA-F0-9]{32}$"}
+    try:
+        js_v(uuid, id_schema)
+        return True
+    except js_e.ValidationError:
+        try:
+            js_v(uuid, id_schema2)
+            return True
+        except js_e.ValidationError:
+            return False
+    return False
+
+def _convert_datetime2str(var):
+    '''Converts a datetime variable to a string with the format '%Y-%m-%dT%H:%i:%s'
+    It enters recursively in the dict var finding this kind of variables
+    '''
+    if type(var) is dict:
+        for k,v in var.items():
+            if type(v) is datetime.datetime:
+                var[k]= v.strftime('%Y-%m-%dT%H:%M:%S')
+            elif type(v) is dict or type(v) is list or type(v) is tuple: 
+                _convert_datetime2str(v)
+        if len(var) == 0: return True
+    elif type(var) is list or type(var) is tuple:
+        for v in var:
+            _convert_datetime2str(v)
+
+def _convert_bandwidth(data, reverse=False):
+    '''Check the field bandwidth recursivelly and when found, it removes units and convert to number 
+    It assumes that bandwidth is well formed
+    Attributes:
+        'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
+        'reverse': by default convert form str to int (Mbps), if True it convert from number to units
+    Return:
+        None
+    '''
+    if type(data) is dict:
+        for k in data.keys():
+            if type(data[k]) is dict or type(data[k]) is tuple or type(data[k]) is list:
+                _convert_bandwidth(data[k], reverse)
+        if "bandwidth" in data:
+            try:
+                value=str(data["bandwidth"])
+                if not reverse:
+                    pos = value.find("bps")
+                    if pos>0:
+                        if value[pos-1]=="G": data["bandwidth"] =  int(data["bandwidth"][:pos-1]) * 1000
+                        elif value[pos-1]=="k": data["bandwidth"]= int(data["bandwidth"][:pos-1]) / 1000
+                        else: data["bandwidth"]= int(data["bandwidth"][:pos-1])
+                else:
+                    value = int(data["bandwidth"])
+                    if value % 1000 == 0: data["bandwidth"]=str(value/1000) + " Gbps"
+                    else: data["bandwidth"]=str(value) + " Mbps"
+            except:
+                print "convert_bandwidth exception for type", type(data["bandwidth"]), " data", data["bandwidth"]
+                return
+    if type(data) is tuple or type(data) is list:
+        for k in data:
+            if type(k) is dict or type(k) is tuple or type(k) is list:
+                _convert_bandwidth(k, reverse)
+
+def _convert_str2boolean(data, items):
+    '''Check recursively the content of data, and if there is an key contained in items, convert value from string to boolean 
+    Done recursively
+    Attributes:
+        'data': dictionary variable to be checked. None or empty is considered valid
+        'items': tuple of keys to convert
+    Return:
+        None
+    '''
+    if type(data) is dict:
+        for k in data.keys():
+            if type(data[k]) is dict or type(data[k]) is tuple or type(data[k]) is list:
+                _convert_str2boolean(data[k], items)
+            if k in items:
+                if type(data[k]) is str:
+                    if   data[k]=="false" or data[k]=="False": data[k]=False
+                    elif data[k]=="true"  or data[k]=="True":  data[k]=True
+    if type(data) is tuple or type(data) is list:
+        for k in data:
+            if type(k) is dict or type(k) is tuple or type(k) is list:
+                _convert_str2boolean(k, items)
+
+class db_base_Exception(Exception):
+    '''Common Exception for all database exceptions'''
+    
+    def __init__(self, message, http_code=HTTP_Bad_Request):
+        Exception.__init__(self, message)
+        self.http_code = http_code
+
+class db_base():
+    tables_with_created_field=()
+    
+    def __init__(self, host=None, user=None, passwd=None, database=None, log_name='db', log_level="ERROR"):
+        self.host = host
+        self.user = user
+        self.passwd = passwd
+        self.database = database
+        self.con = None
+        self.log_level=log_level
+        self.logger = logging.getLogger(log_name)
+        self.logger.setLevel( getattr(logging, log_level) )
+        
+    def connect(self, host=None, user=None, passwd=None, database=None):
+        '''Connect to specific data base. 
+        The first time a valid host, user, passwd and database must be provided,
+        Following calls can skip this parameters
+        '''
+        try:
+            if host:        self.host = host
+            if user:        self.user = user
+            if passwd:      self.passwd = passwd
+            if database:    self.database = database
+
+            self.con = mdb.connect(self.host, self.user, self.passwd, self.database)
+            print "DB: connected to %s@%s -> %s" % (self.user, self.host, self.database)
+        except mdb.Error, e:
+            raise db_base_Exception("Cannot connect to DB {}@{} -> {} Error {}: {}".format(self.user, self.host, self.database, e.args[0], e.args[1]),
+                                    code = HTTP_Internal_Server_Error )
+        
+    def get_db_version(self):
+        ''' Obtain the database schema version.
+        Return: (negative, text) if error or version 0.0 where schema_version table is missing
+                (version_int, version_text) if ok
+        '''
+        cmd = "SELECT version_int,version FROM schema_version"
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor()
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    rows = self.cur.fetchall()
+                    highest_version_int=0
+                    highest_version=""
+                    for row in rows: #look for the latest version
+                        if row[0]>highest_version_int:
+                            highest_version_int, highest_version = row[0:2]
+                    return highest_version_int, highest_version
+            except (mdb.Error, AttributeError) as e:
+                #self.logger.error("get_db_version DB Exception %d: %s. Command %s",e.args[0], e.args[1], cmd)
+                self._format_error(e, tries)
+            tries -= 1
+
+    def disconnect(self):
+        '''disconnect from specific data base'''
+        try:
+            self.con.close()
+            self.con = None
+        except mdb.Error as e:
+            self.logger.error("while disconnecting from DB: Error %d: %s",e.args[0], e.args[1])
+            return
+        except AttributeError as e: #self.con not defined
+            if e[0][-5:] == "'con'":
+                self.logger.warn("while disconnecting from DB: Error %d: %s",e.args[0], e.args[1])
+                return
+            else: 
+                raise
+
+    def _format_error(self, e, tries=1, command=None, extra=None): 
+        '''Creates a text error base on the produced exception
+            Params:
+                e: mdb exception
+                retry: in case of timeout, if reconnecting to database and retry, or raise and exception
+                cmd: database command that produce the exception
+                command: if the intention is update or delete
+                extra: extra information to add to some commands
+            Return
+                HTTP error in negative, formatted error text
+        '''
+        if isinstance(e,AttributeError ):
+            raise db_base_Exception("DB Exception " + str(e), HTTP_Internal_Server_Error)
+        if e.args[0]==2006 or e.args[0]==2013 : #MySQL server has gone away (((or)))    Exception 2013: Lost connection to MySQL server during query
+            if tries>1:
+                self.logger.warn("DB Exception '%s'. Retry", str(e))
+                #reconnect
+                self.connect()
+                return
+            else:
+                raise db_base_Exception("Database connection timeout Try Again", HTTP_Request_Timeout)
+        
+        fk=e.args[1].find("foreign key constraint fails")
+        if fk>=0:
+            if command=="update":
+                raise db_base_Exception("tenant_id '{}' not found.".format(extra), HTTP_Not_Found)
+            elif command=="delete":
+                raise db_base_Exception("Resource is not free. There are {} that prevent deleting it.".format(extra), HTTP_Conflict)
+        de = e.args[1].find("Duplicate entry")
+        fk = e.args[1].find("for key")
+        uk = e.args[1].find("Unknown column")
+        wc = e.args[1].find("in 'where clause'")
+        fl = e.args[1].find("in 'field list'")
+        #print de, fk, uk, wc,fl
+        if de>=0:
+            if fk>=0: #error 1062
+                raise db_base_Exception("Value {} already in use for {}".format(e.args[1][de+15:fk], e.args[1][fk+7:]), HTTP_Conflict)
+        if uk>=0:
+            if wc>=0:
+                raise db_base_Exception("Field {} can not be used for filtering".format(e.args[1][uk+14:wc]), HTTP_Bad_Request)
+            if fl>=0:
+                raise db_base_Exception("Field {} does not exist".format(e.args[1][uk+14:wc]), HTTP_Bad_Request)
+        raise db_base_Exception("Database internal Error {}: {}".format(e.args[0], e.args[1]), HTTP_Internal_Server_Error)
+    
+    def __str2db_format(self, data):
+        '''Convert string data to database format. 
+        If data is None it returns the 'Null' text,
+        otherwise it returns the text surrounded by quotes ensuring internal quotes are escaped.
+        '''
+        if data==None:
+            return 'Null'
+        else:
+            return json.dumps(str(data))
+    
+    def __tuple2db_format_set(self, data):
+        '''Compose the needed text for a SQL SET, parameter 'data' is a pair tuple (A,B),
+        and it returns the text 'A="B"', where A is a field of a table and B is the value 
+        If B is None it returns the 'A=Null' text, without surrounding Null by quotes
+        If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
+        and it ensures internal quotes of B are escaped.
+        '''
+        if data[1]==None:
+            return str(data[0]) + "=Null"
+        else:
+            return str(data[0]) + '=' + json.dumps(str(data[1]))
+    
+    def __tuple2db_format_where(self, data):
+        '''Compose the needed text for a SQL WHERE, parameter 'data' is a pair tuple (A,B),
+        and it returns the text 'A="B"', where A is a field of a table and B is the value 
+        If B is None it returns the 'A is Null' text, without surrounding Null by quotes
+        If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
+        and it ensures internal quotes of B are escaped.
+        '''
+        if data[1]==None:
+            return str(data[0]) + " is Null"
+        
+#         if type(data[1]) is tuple:  #this can only happen in a WHERE_OR clause
+#             text =[]
+#             for d in data[1]:
+#                 if d==None:
+#                     text.append(str(data[0]) + " is Null")
+#                     continue
+#                 out=str(d)
+#                 if "'" not in out:
+#                     text.append( str(data[0]) + "='" + out + "'" )
+#                 elif '"' not in out:
+#                     text.append( str(data[0]) + '="' + out + '"' )
+#                 else:
+#                     text.append( str(data[0]) + '=' + json.dumps(out) )
+#             return " OR ".join(text)
+
+        out=str(data[1])
+        return str(data[0]) + '=' + json.dumps(out)
+
+    def __tuple2db_format_where_not(self, data):
+        '''Compose the needed text for a SQL WHERE(not). parameter 'data' is a pair tuple (A,B),
+        and it returns the text 'A<>"B"', where A is a field of a table and B is the value 
+        If B is None it returns the 'A is not Null' text, without surrounding Null by quotes
+        If B is not None it returns the text "A<>'B'" or 'A<>"B"' where B is surrounded by quotes,
+        and it ensures internal quotes of B are escaped.
+        '''
+        if data[1]==None:
+            return str(data[0]) + " is not Null"
+        out=str(data[1])
+        return str(data[0]) + '<>' + json.dumps(out)
+    
+    def __remove_quotes(self, data):
+        '''remove single quotes ' of any string content of data dictionary'''
+        for k,v in data.items():
+            if type(v) == str:
+                if "'" in v: 
+                    data[k] = data[k].replace("'","_")
+    
+    def _update_rows(self, table, UPDATE, WHERE, modified_time=0):
+        ''' Update one or several rows into a table.
+        Atributes
+            UPDATE: dictionary with the key: value to change
+            table: table where to update
+            WHERE: dictionary of elements to update
+        Return: the number of updated rows, exception if error
+        '''
+                #gettting uuid 
+        values = ",".join(map(self.__tuple2db_format_set, UPDATE.iteritems() ))
+        if modified_time:
+            values += ",modified_at={:f}".format(modified_time)
+        cmd= "UPDATE " + table +" SET " + values +\
+            " WHERE " + " and ".join(map(self.__tuple2db_format_where, WHERE.iteritems() ))
+        self.logger.debug(cmd)
+        self.cur.execute(cmd) 
+        return self.cur.rowcount
+    
+    def _new_row_internal(self, table, INSERT, add_uuid=False, root_uuid=None, created_time=0):
+        ''' Add one row into a table. It DOES NOT begin or end the transaction, so self.con.cursor must be created
+        Attribute 
+            INSERT: dictionary with the key:value to insert
+            table: table where to insert
+            add_uuid: if True, it will create an uuid key entry at INSERT if not provided
+            created_time: time to add to the created_time column
+        It checks presence of uuid and add one automatically otherwise
+        Return: uuid
+        '''
+
+        if add_uuid:
+            #create uuid if not provided
+            if 'uuid' not in INSERT:
+                uuid = INSERT['uuid'] = str(myUuid.uuid1()) # create_uuid
+            else: 
+                uuid = str(INSERT['uuid'])
+        else:
+            uuid=None
+        if add_uuid:
+            #defining root_uuid if not provided
+            if root_uuid is None:
+                root_uuid = uuid
+            if created_time:
+                created_at = created_time
+            else:
+                created_at=time.time()
+            #inserting new uuid
+            cmd = "INSERT INTO uuids (uuid, root_uuid, used_at, created_at) VALUES ('{:s}','{:s}','{:s}', {:f})".format(uuid, root_uuid, table, created_at)
+            self.logger.debug(cmd)
+            self.cur.execute(cmd)
+        #insertion
+        cmd= "INSERT INTO " + table +" SET " + \
+            ",".join(map(self.__tuple2db_format_set, INSERT.iteritems() )) 
+        if created_time:
+            cmd += ",created_at=%f" % created_time
+        self.logger.debug(cmd)
+        self.cur.execute(cmd)
+        self.cur.rowcount
+        return uuid
+
+    def _get_rows(self,table,uuid):
+        cmd = "SELECT * FROM {} WHERE uuid='{}'".format(str(table), str(uuid))
+        self.logger.debug(cmd)
+        self.cur.execute(cmd)
+        rows = self.cur.fetchall()
+        return rows
+    
+    def new_row(self, table, INSERT, add_uuid=False, created_time=0):
+        ''' Add one row into a table.
+        Attribute 
+            INSERT: dictionary with the key: value to insert
+            table: table where to insert
+            tenant_id: only useful for logs. If provided, logs will use this tenant_id
+            add_uuid: if True, it will create an uuid key entry at INSERT if not provided
+        It checks presence of uuid and add one automatically otherwise
+        Return: (result, uuid) where result can be 0 if error, or 1 if ok
+        '''
+        if table in self.tables_with_created_field and created_time==0:
+            created_time=time.time()
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor()
+                    return self._new_row_internal(table, INSERT, add_uuid, None, created_time)
+                    
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
+    def update_rows(self, table, UPDATE, WHERE, modified_time=0):
+        ''' Update one or several rows into a table.
+        Atributes
+            UPDATE: dictionary with the key: value to change
+            table: table where to update
+            WHERE: dictionary of elements to update
+        Return: (result, descriptive text) where result indicates the number of updated files
+        '''
+        if table in self.tables_with_created_field and modified_time==0:
+            modified_time=time.time()
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor()
+                    return self._update_rows(table, UPDATE, WHERE)
+                    
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
+    def delete_row_by_id(self, table, uuid):
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    #delete host
+                    self.cur = self.con.cursor()
+                    cmd = "DELETE FROM {} WHERE uuid = '{}'".format(table, uuid)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    deleted = self.cur.rowcount
+                    if deleted:
+                        #delete uuid
+                        self.cur = self.con.cursor()
+                        cmd = "DELETE FROM uuids WHERE root_uuid = '{}'".format(uuid)
+                        self.logger.debug(cmd)
+                        self.cur.execute(cmd)
+                return deleted
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries, "delete", "dependencies")
+            tries -= 1
+
+    def delete_row(self, **sql_dict):
+        ''' Deletes rows from a table.
+        Attribute sql_dir: dictionary with the following key: value
+            'FROM': string of table name (Mandatory)
+            'WHERE': dict of key:values, translated to key=value AND ... (Optional)
+            'WHERE_NOT': dict of key:values, translated to key<>value AND ... (Optional) 
+                if value is None, it is translated to key is not null
+            'LIMIT': limit of number of rows (Optional)
+        Return: the number of deleted or exception if error
+        '''
+        #print sql_dict
+        from_  = "FROM " + str(sql_dict['FROM'])
+        #print 'from_', from_
+        if 'WHERE' in sql_dict and len(sql_dict['WHERE']) > 0:
+            w=sql_dict['WHERE']
+            where_ = "WHERE " + " AND ".join(map(self.__tuple2db_format_where, w.iteritems())) 
+        else: where_ = ""
+        if 'WHERE_NOT' in sql_dict and len(sql_dict['WHERE_NOT']) > 0: 
+            w=sql_dict['WHERE_NOT']
+            where_2 = " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems()))
+            if len(where_)==0:   where_ = "WHERE " + where_2
+            else:                where_ = where_ + " AND " + where_2
+        #print 'where_', where_
+        limit_ = "LIMIT " + str(sql_dict['LIMIT']) if 'LIMIT' in sql_dict else ""
+        #print 'limit_', limit_
+        cmd =  " ".join( ("DELETE", from_, where_, limit_) )
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor()
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    deleted = self.cur.rowcount
+                return deleted
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
+    def get_rows_by_id(self, table, uuid):
+        '''get row from a table based on uuid'''
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                    cmd="SELECT * FROM {} where uuid='{}'".format(str(table), str(uuid))
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    rows = self.cur.fetchall()
+                    return rows
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+    
+    def get_rows(self, **sql_dict):
+        ''' Obtain rows from a table.
+        Attribute sql_dir: dictionary with the following key: value
+            'SELECT':    list or tuple of fields to retrieve) (by default all)
+            'FROM':      string of table name (Mandatory)
+            'WHERE':     dict of key:values, translated to key=value (key is null) AND ... (Optional)
+            'WHERE_NOT': dict of key:values, translated to key<>value (key is not null) AND ... (Optional)
+            'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
+            'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional)
+            'LIMIT':     limit of number of rows (Optional)
+            'ORDER_BY':  list or tuple of fields to order
+        Return: a list with dictionaries at each row
+        '''
+        #print sql_dict
+        select_= "SELECT " + ("*" if 'SELECT' not in sql_dict else ",".join(map(str,sql_dict['SELECT'])) )
+        #print 'select_', select_
+        from_  = "FROM " + str(sql_dict['FROM'])
+        #print 'from_', from_
+        where_and = ""
+        where_or = ""
+        w=sql_dict.get('WHERE')
+        if w:
+            where_and = " AND ".join(map(self.__tuple2db_format_where, w.iteritems() ))
+        w=sql_dict.get('WHERE_NOT')
+        if w: 
+            if where_and: where_and += " AND "
+            where_and += " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems() ) )
+        w=sql_dict.get('WHERE_OR')
+        if w:
+            where_or =  " OR ".join(map(self.__tuple2db_format_where, w.iteritems() ))
+        if where_and and where_or:
+            if sql_dict.get("WHERE_AND_OR") == "AND":
+                where_ = "WHERE " + where_and + " AND (" + where_or + ")"
+            else:
+                where_ = "WHERE (" + where_and + ") OR " + where_or
+        elif where_and and not where_or:
+            where_ = "WHERE " + where_and
+        elif not where_and and where_or:
+            where_ = "WHERE " + where_or
+        else:
+            where_ = ""
+        #print 'where_', where_
+        limit_ = "LIMIT " + str(sql_dict['LIMIT']) if 'LIMIT' in sql_dict else ""
+        order_ = "ORDER BY " + ",".join(map(str,sql_dict['SELECT'])) if 'ORDER_BY' in sql_dict else ""
+        
+        #print 'limit_', limit_
+        cmd =  " ".join( (select_, from_, where_, limit_, order_) )
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    rows = self.cur.fetchall()
+                    return rows
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
+    def get_table_by_uuid_name(self, table, uuid_name, error_item_text=None, allow_serveral=False, WHERE_OR={}, WHERE_AND_OR="OR"):
+        ''' Obtain One row from a table based on name or uuid.
+        Attribute:
+            table: string of table name
+            uuid_name: name or uuid. If not uuid format is found, it is considered a name
+            allow_severeral: if False return ERROR if more than one row are founded 
+            error_item_text: in case of error it identifies the 'item' name for a proper output text 
+            'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
+            'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional  
+        Return: if allow_several==False, a dictionary with this row, or error if no item is found or more than one is found
+                if allow_several==True, a list of dictionaries with the row or rows, error if no item is found
+        '''
+
+        if error_item_text==None:
+            error_item_text = table
+        what = 'uuid' if af.check_valid_uuid(uuid_name) else 'name'
+        cmd =  " SELECT * FROM {} WHERE {}='{}'".format(table, what, uuid_name)
+        if WHERE_OR:
+            where_or =  " OR ".join(map(self.__tuple2db_format_where, WHERE_OR.iteritems() ))
+            if WHERE_AND_OR == "AND":
+                cmd += " AND (" + where_or + ")"
+            else:
+                cmd += " OR " + where_or
+
+        
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
+                    number = self.cur.rowcount
+                    if number==0:
+                        return -HTTP_Not_Found, "No %s found with %s '%s'" %(error_item_text, what, uuid_name)
+                    elif number>1 and not allow_serveral: 
+                        return -HTTP_Bad_Request, "More than one %s found with %s '%s'" %(error_item_text, what, uuid_name)
+                    if allow_serveral:
+                        rows = self.cur.fetchall()
+                    else:
+                        rows = self.cur.fetchone()
+                    return rows
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
+    def get_uuid(self, uuid):
+        '''check in the database if this uuid is already present'''
+        for retry_ in range(0,2):
+            try:
+                with self.con:
+                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                    self.cur.execute("SELECT * FROM uuids where uuid='" + str(uuid) + "'")
+                    rows = self.cur.fetchall()
+                    return self.cur.rowcount, rows
+            except (mdb.Error, AttributeError) as e:
+                print "nfvo_db.get_uuid DB Exception %d: %s" % (e.args[0], e.args[1])
+                r,c = self._format_error(e)
+                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+
+    def get_uuid_from_name(self, table, name):
+        '''Searchs in table the name and returns the uuid
+        ''' 
+        tries = 2
+        while tries:
+            try:
+                with self.con:
+                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                    where_text = "name='" + name +"'"
+                    self.cur.execute("SELECT * FROM " + table + " WHERE "+ where_text)
+                    rows = self.cur.fetchall()
+                    if self.cur.rowcount==0:
+                        return 0, "Name %s not found in table %s" %(name, table)
+                    elif self.cur.rowcount>1:
+                        return self.cur.rowcount, "More than one VNF with name %s found in table %s" %(name, table)
+                    return self.cur.rowcount, rows[0]["uuid"]
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
index 7e4a82c..680fddf 100644 (file)
@@ -34,6 +34,7 @@ import yaml
 import json
 import threading
 import time
+import logging
 
 from jsonschema import validate as js_v, exceptions as js_e
 from openmano_schemas import vnfd_schema_v01, vnfd_schema_v02, \
@@ -44,9 +45,12 @@ from openmano_schemas import vnfd_schema_v01, vnfd_schema_v02, \
                             object_schema, netmap_new_schema, netmap_edit_schema
 import nfvo
 import utils
+from db_base import db_base_Exception
+from functools import wraps
 
 global mydb
 global url_base
+global logger
 url_base="/openmano"
 
 HTTP_Bad_Request =          400
@@ -86,12 +90,29 @@ def convert_datetime2str(var):
         for v in var:
             convert_datetime2str(v)
 
+def log_to_logger(fn):
+    '''
+    Wrap a Bottle request so that a log line is emitted after it's handled.
+    (This decorator can be extended to take the desired logger as a param.)
+    '''
+    @wraps(fn)
+    def _log_to_logger(*args, **kwargs):
+        actual_response = fn(*args, **kwargs)
+        # modify this to log exactly what you need:
+        logger.info('FROM %s %s %s %s' % (bottle.request.remote_addr,
+                                        bottle.request.method,
+                                        bottle.request.url,
+                                        bottle.response.status))
+        return actual_response
+    return _log_to_logger
 
 class httpserver(threading.Thread):
     def __init__(self, db, admin=False, host='localhost', port=9090):
         #global url_base
         global mydb
+        global logger
         #initialization
+        logger = logging.getLogger('openmano.http')
         threading.Thread.__init__(self)
         self.host = host
         self.port = port   #Port where the listen service must be started
@@ -108,7 +129,8 @@ class httpserver(threading.Thread):
         self.setDaemon(True)
          
     def run(self):
-        bottle.run(host=self.host, port=self.port, debug=True) #quiet=True
+        bottle.install(log_to_logger)
+        bottle.run(host=self.host, port=self.port, debug=False, quiet=True)
            
 def run_bottle(db, host_='localhost', port_=9090):
     '''used for launching in main thread, so that it can be debugged'''
@@ -148,9 +170,9 @@ def change_keys_http2db(data, http_db, reverse=False):
 
 def format_out(data):
     '''return string of dictionary data according to requested json, yaml, xml. By default json'''
+    logger.debug(yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) )
     if 'application/yaml' in bottle.request.headers.get('Accept'):
         bottle.response.content_type='application/yaml'
-        print yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) 
         return yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) #, canonical=True, default_style='"'
     else: #by default json
         bottle.response.content_type='application/json'
@@ -242,26 +264,25 @@ def filter_query_string(qs, http2db, allowed):
     where={}
     limit=100
     select=[]
-    if type(qs) is not bottle.FormsDict:
-        print '!!!!!!!!!!!!!!invalid query string not a dictionary'
-        #bottle.abort(HTTP_Internal_Server_Error, "call programmer")
-    else:
-        for k in qs:
-            if k=='field':
-                select += qs.getall(k)
-                for v in select:
-                    if v not in allowed:
-                        bottle.abort(HTTP_Bad_Request, "Invalid query string at 'field="+v+"'")
-            elif k=='limit':
-                try:
-                    limit=int(qs[k])
-                except:
-                    bottle.abort(HTTP_Bad_Request, "Invalid query string at 'limit="+qs[k]+"'")
-            else:
-                if k not in allowed:
-                    bottle.abort(HTTP_Bad_Request, "Invalid query string at '"+k+"="+qs[k]+"'")
-                if qs[k]!="null":  where[k]=qs[k]
-                else: where[k]=None 
+    #if type(qs) is not bottle.FormsDict:
+    #    bottle.abort(HTTP_Internal_Server_Error, '!!!!!!!!!!!!!!invalid query string not a dictionary')
+    #    #bottle.abort(HTTP_Internal_Server_Error, "call programmer")
+    for k in qs:
+        if k=='field':
+            select += qs.getall(k)
+            for v in select:
+                if v not in allowed:
+                    bottle.abort(HTTP_Bad_Request, "Invalid query string at 'field="+v+"'")
+        elif k=='limit':
+            try:
+                limit=int(qs[k])
+            except:
+                bottle.abort(HTTP_Bad_Request, "Invalid query string at 'limit="+qs[k]+"'")
+        else:
+            if k not in allowed:
+                bottle.abort(HTTP_Bad_Request, "Invalid query string at '"+k+"="+qs[k]+"'")
+            if qs[k]!="null":  where[k]=qs[k]
+            else: where[k]=None 
     if len(select)==0: select += allowed
     #change from http api to database naming
     for i in range(0,len(select)):
@@ -270,7 +291,7 @@ def filter_query_string(qs, http2db, allowed):
             select[i] = http2db[k]
     if http2db:
         change_keys_http2db(where, http2db)
-    print "filter_query_string", select,where,limit
+    #print "filter_query_string", select,where,limit
     
     return select,where,limit
 
@@ -285,492 +306,495 @@ def enable_cors():
 
 @bottle.route(url_base + '/tenants', method='GET')
 def http_get_tenants():
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     select_,where_,limit_ = filter_query_string(bottle.request.query, None,
             ('uuid','name','description','created_at') )
-    result, content = mydb.get_table(FROM='nfvo_tenants', SELECT=select_,WHERE=where_,LIMIT=limit_)
-    if result < 0:
-        print "http_get_tenants Error", content
-        bottle.abort(-result, content)
-    else:
+    try:
+        tenants = mydb.get_rows(FROM='nfvo_tenants', SELECT=select_,WHERE=where_,LIMIT=limit_)
         #change_keys_http2db(content, http2db_tenant, reverse=True)
-        convert_datetime2str(content)
-        data={'tenants' : content}
+        convert_datetime2str(tenants)
+        data={'tenants' : tenants}
         return format_out(data)
+    except db_base_Exception as e:
+        logger.error("http_get_tenants error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/tenants/<tenant_id>', method='GET')
 def http_get_tenant_id(tenant_id):
     '''get tenant details, can use both uuid or name'''
     #obtain data
-    result, content = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id, "tenant") 
-    if result < 0:
-        print "http_get_tenant_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    #change_keys_http2db(content, http2db_tenant, reverse=True)
-    convert_datetime2str(content)
-    print content
-    data={'tenant' : content}
-    return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        tenant = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id, "tenant") 
+        #change_keys_http2db(content, http2db_tenant, reverse=True)
+        convert_datetime2str(tenant)
+        data={'tenant' : tenant}
+        return format_out(data)
+    except db_base_Exception as e:
+        logger.error("http_get_tenant_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/tenants', method='POST')
 def http_post_tenants():
     '''insert a tenant into the catalogue. '''
     #parse input data
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content,_ = format_in( tenant_schema )
     r = utils.remove_extra_items(http_content, tenant_schema)
     if r is not None: print "http_post_tenants: Warning: remove extra items ", r
-    result, data = nfvo.new_tenant(mydb, http_content['tenant'])
-    if result < 0:
-        print "http_post_tenants error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    try: 
+        data = nfvo.new_tenant(mydb, http_content['tenant'])
         return http_get_tenant_id(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_tenants error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/tenants/<tenant_id>', method='PUT')
 def http_edit_tenant_id(tenant_id):
     '''edit tenant details, can use both uuid or name'''
     #parse input data
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content,_ = format_in( tenant_edit_schema )
     r = utils.remove_extra_items(http_content, tenant_edit_schema)
     if r is not None: print "http_edit_tenant_id: Warning: remove extra items ", r
     
     #obtain data, check that only one exist
-    result, content = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
-    if result < 0:
-        print "http_edit_tenant_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    
-    #edit data 
-    tenant_id = content['uuid']
-    where={'uuid': content['uuid']}
-    result, content = mydb.update_rows('nfvo_tenants', http_content['tenant'], where)
-    if result < 0:
-        print "http_edit_tenant_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-
-    return http_get_tenant_id(tenant_id)
+    try: 
+        tenant = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
+        #edit data 
+        tenant_id = tenant['uuid']
+        where={'uuid': tenant['uuid']}
+        mydb.update_rows('nfvo_tenants', http_content['tenant'], where)
+        return http_get_tenant_id(tenant_id)
+    except db_base_Exception as e:
+        logger.error("http_edit_tenant_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/tenants/<tenant_id>', method='DELETE')
 def http_delete_tenant_id(tenant_id):
     '''delete a tenant from database, can use both uuid or name'''
-    
-    result, data = nfvo.delete_tenant(mydb, tenant_id)
-    if result < 0:
-        print "http_delete_tenant_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        #print json.dumps(data, indent=4)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        data = nfvo.delete_tenant(mydb, tenant_id)
         return format_out({"result":"tenant " + data + " deleted"})
+    except db_base_Exception as e:
+        logger.error("http_delete_tenant_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
     
 
 @bottle.route(url_base + '/<tenant_id>/datacenters', method='GET')
 def http_get_datacenters(tenant_id):
-    #check valid tenant_id
-    if tenant_id != 'any':
-        if not nfvo.check_tenant(mydb, tenant_id): 
-            print 'httpserver.http_get_datacenters () tenant %s not found' % tenant_id
-            bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-            return
-    select_,where_,limit_ = filter_query_string(bottle.request.query, None,
-            ('uuid','name','vim_url','type','created_at') )
-    if tenant_id != 'any':
-        where_['nfvo_tenant_id'] = tenant_id
-        if 'created_at' in select_:
-            select_[ select_.index('created_at') ] = 'd.created_at as created_at'
-        if 'created_at' in where_:
-            where_['d.created_at'] = where_.pop('created_at')
-        result, content = mydb.get_table(FROM='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id',
-                                      SELECT=select_,WHERE=where_,LIMIT=limit_)
-    else:
-        result, content = mydb.get_table(FROM='datacenters',
-                                      SELECT=select_,WHERE=where_,LIMIT=limit_)
-    if result < 0:
-        print "http_get_datacenters Error", content
-        bottle.abort(-result, content)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        if tenant_id != 'any':
+            #check valid tenant_id
+            nfvo.check_tenant(mydb, tenant_id)
+        select_,where_,limit_ = filter_query_string(bottle.request.query, None,
+                ('uuid','name','vim_url','type','created_at') )
+        if tenant_id != 'any':
+            where_['nfvo_tenant_id'] = tenant_id
+            if 'created_at' in select_:
+                select_[ select_.index('created_at') ] = 'd.created_at as created_at'
+            if 'created_at' in where_:
+                where_['d.created_at'] = where_.pop('created_at')
+            datacenters = mydb.get_rows(FROM='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id',
+                                          SELECT=select_,WHERE=where_,LIMIT=limit_)
+        else:
+            datacenters = mydb.get_rows(FROM='datacenters',
+                                          SELECT=select_,WHERE=where_,LIMIT=limit_)
         #change_keys_http2db(content, http2db_tenant, reverse=True)
-        convert_datetime2str(content)
-        data={'datacenters' : content}
+        convert_datetime2str(datacenters)
+        data={'datacenters' : datacenters}
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_datacenters error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='GET')
 def http_get_datacenter_id(tenant_id, datacenter_id):
     '''get datacenter details, can use both uuid or name'''
-    #check valid tenant_id
-    if tenant_id != 'any':
-        if not nfvo.check_tenant(mydb, tenant_id): 
-            print 'httpserver.http_get_datacenter_id () tenant %s not found' % tenant_id
-            bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-            return
-    #obtain data
-    what = 'uuid' if utils.check_valid_uuid(datacenter_id) else 'name'
-    where_={}
-    where_[what] = datacenter_id
-    select_=['uuid', 'name','vim_url', 'vim_url_admin', 'type', 'config', 'description', 'd.created_at as created_at']
-    if tenant_id != 'any':
-        select_.append("datacenter_tenant_id")
-        where_['td.nfvo_tenant_id']= tenant_id
-        from_='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id'
-    else:
-        from_='datacenters as d'
-    result, content = mydb.get_table(
-                SELECT=select_,
-                FROM=from_,
-                WHERE=where_)
-
-    if result < 0:
-        print "http_get_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    elif result==0:
-        bottle.abort( HTTP_Not_Found, "No datacenter found for tenant with %s '%s'" %(what, datacenter_id) )
-    elif result>1: 
-        bottle.abort( HTTP_Bad_Request, "More than one datacenter found for tenant with %s '%s'" %(what, datacenter_id) )
-
-    if tenant_id != 'any':
-        #get vim tenant info
-        result, content2 = mydb.get_table(
-                SELECT=("vim_tenant_name", "vim_tenant_id", "user"),
-                FROM="datacenter_tenants",
-                WHERE={"uuid": content[0]["datacenter_tenant_id"]},
-                ORDER_BY=("created", ) )
-        del content[0]["datacenter_tenant_id"]
-        if result < 0:
-            print "http_get_datacenter_id vim_tenant_info error %d %s" % (result, content2)
-            bottle.abort(-result, content2)
-        content[0]["vim_tenants"] = content2
-
-    print content
-    if content[0]['config'] != None:
-        try:
-            config_dict = yaml.load(content[0]['config'])
-            content[0]['config'] = config_dict
-        except Exception, e:
-            print "Exception '%s' while trying to load config information" % str(e)
-    #change_keys_http2db(content, http2db_datacenter, reverse=True)
-    convert_datetime2str(content[0])
-    data={'datacenter' : content[0]}
-    return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        if tenant_id != 'any':
+            #check valid tenant_id
+            nfvo.check_tenant(mydb, tenant_id)
+        #obtain data
+        what = 'uuid' if utils.check_valid_uuid(datacenter_id) else 'name'
+        where_={}
+        where_[what] = datacenter_id
+        select_=['uuid', 'name','vim_url', 'vim_url_admin', 'type', 'config', 'description', 'd.created_at as created_at']
+        if tenant_id != 'any':
+            select_.append("datacenter_tenant_id")
+            where_['td.nfvo_tenant_id']= tenant_id
+            from_='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id'
+        else:
+            from_='datacenters as d'
+        datacenters = mydb.get_rows(
+                    SELECT=select_,
+                    FROM=from_,
+                    WHERE=where_)
+    
+        if len(datacenters)==0:
+            bottle.abort( HTTP_Not_Found, "No datacenter found for tenant with {} '{}'".format(what, datacenter_id) )
+        elif len(datacenters)>1: 
+            bottle.abort( HTTP_Bad_Request, "More than one datacenter found for tenant with {} '{}'".format(what, datacenter_id) )
+        datacenter = datacenters[0]
+        if tenant_id != 'any':
+            #get vim tenant info
+            vim_tenants = mydb.get_rows(
+                    SELECT=("vim_tenant_name", "vim_tenant_id", "user"),
+                    FROM="datacenter_tenants",
+                    WHERE={"uuid": datacenters[0]["datacenter_tenant_id"]},
+                    ORDER_BY=("created", ) )
+            del datacenter["datacenter_tenant_id"]
+            datacenter["vim_tenants"] = vim_tenants
+    
+        if datacenter['config'] != None:
+            try:
+                config_dict = yaml.load(datacenter['config'])
+                datacenter['config'] = config_dict
+            except Exception, e:
+                print "Exception '%s' while trying to load config information" % str(e)
+        #change_keys_http2db(content, http2db_datacenter, reverse=True)
+        convert_datetime2str(datacenter)
+        data={'datacenter' : datacenter}
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/datacenters', method='POST')
 def http_post_datacenters():
     '''insert a tenant into the catalogue. '''
     #parse input data
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content,_ = format_in( datacenter_schema )
     r = utils.remove_extra_items(http_content, datacenter_schema)
-    if r is not None: print "http_post_tenants: Warning: remove extra items ", r
-    result, data = nfvo.new_datacenter(mydb, http_content['datacenter'])
-    if result < 0:
-        print "http_post_datacenters error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    if r is not None: print "http_post_datacenters: Warning: remove extra items ", r
+    try:
+        data = nfvo.new_datacenter(mydb, http_content['datacenter'])
         return http_get_datacenter_id('any', data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_datacenters error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/datacenters/<datacenter_id_name>', method='PUT')
 def http_edit_datacenter_id(datacenter_id_name):
     '''edit datacenter details, can use both uuid or name'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #parse input data
     http_content,_ = format_in( datacenter_edit_schema )
     r = utils.remove_extra_items(http_content, datacenter_edit_schema)
     if r is not None: print "http_edit_datacenter_id: Warning: remove extra items ", r
     
-    
-    result, datacenter_id = nfvo.edit_datacenter(mydb, datacenter_id_name, http_content['datacenter'])
-    if result < 0:
-        print "http_edit_datacenter_id error %d %s" % (-result, datacenter_id)
-        bottle.abort(-result, datacenter_id)
-    else:
+    try:
+        datacenter_id = nfvo.edit_datacenter(mydb, datacenter_id_name, http_content['datacenter'])
         return http_get_datacenter_id('any', datacenter_id)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_edit_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/networks', method='GET')  #deprecated
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='GET')
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='GET')
 def http_getnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None):
     '''get datacenter networks, can use both uuid or name'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #obtain data
-    result, datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter") 
-    if result < 0:
-        print "http_getnetwork_datacenter_id error %d %s" % (result, datacenter_dict)
-        bottle.abort(-result, datacenter_dict)
-    where_= {"datacenter_id":datacenter_dict['uuid']}
-    if netmap_id:
-        if utils.check_valid_uuid(netmap_id):
-            where_["uuid"] = netmap_id
+    try:
+        datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter") 
+        where_= {"datacenter_id":datacenter_dict['uuid']}
+        if netmap_id:
+            if utils.check_valid_uuid(netmap_id):
+                where_["uuid"] = netmap_id
+            else:
+                where_["name"] = netmap_id
+        netmaps =mydb.get_rows(FROM='datacenter_nets',
+                                        SELECT=('name','vim_net_id as vim_id', 'uuid', 'type','multipoint','shared','description', 'created_at'),
+                                        WHERE=where_ ) 
+        convert_datetime2str(netmaps)
+        utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
+        if netmap_id and len(netmaps)==1:
+            data={'netmap' : netmaps[0]}
+        elif netmap_id and len(netmaps)==0:
+            bottle.abort(HTTP_Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
+            return 
         else:
-            where_["name"] = netmap_id
-    result, content =mydb.get_table(FROM='datacenter_nets',
-                                    SELECT=('name','vim_net_id as vim_id', 'uuid', 'type','multipoint','shared','description', 'created_at'),
-                                    WHERE=where_ ) 
-    if result < 0:
-        print "http_getnetwork_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-
-    convert_datetime2str(content)
-    utils.convert_str2boolean(content, ('shared', 'multipoint') )
-    if netmap_id and len(content)==1:
-        data={'netmap' : content[0]}
-    elif netmap_id and len(content)==0:
-        bottle.abort(HTTP_Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
-        return 
-    else:
-        data={'netmaps' : content}
-    return format_out(data)
+            data={'netmaps' : netmaps}
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_getnetwork_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='DELETE')
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='DELETE')
 def http_delnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None):
     '''get datacenter networks, can use both uuid or name'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #obtain data
-    result, datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter") 
-    if result < 0:
-        print "http_delnetmap_datacenter_id error %d %s" % (result, datacenter_dict)
-        bottle.abort(-result, datacenter_dict)
-    where_= {"datacenter_id":datacenter_dict['uuid']}
-    if netmap_id:
-        if utils.check_valid_uuid(netmap_id):
-            where_["uuid"] = netmap_id
+    try:
+        datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter") 
+        where_= {"datacenter_id":datacenter_dict['uuid']}
+        if netmap_id:
+            if utils.check_valid_uuid(netmap_id):
+                where_["uuid"] = netmap_id
+            else:
+                where_["name"] = netmap_id
+        #change_keys_http2db(content, http2db_tenant, reverse=True)
+        deleted = mydb.delete_row(FROM='datacenter_nets', WHERE= where_) 
+        if deleted == 0 and netmap_id :
+            bottle.abort(HTTP_Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
+        if netmap_id:
+            return format_out({"result": "netmap %s deleted" % netmap_id})
         else:
-            where_["name"] = netmap_id
-    #change_keys_http2db(content, http2db_tenant, reverse=True)
-    result, content =mydb.delete_row_by_dict(FROM='datacenter_nets', WHERE= where_) 
-    if result < 0:
-        print "http_delnetmap_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    elif result == 0 and netmap_id :
-        bottle.abort(HTTP_Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
-    if netmap_id:
-        return format_out({"result": "netmap %s deleted" % netmap_id})
-    else:
-        return format_out({"result": "%d netmap deleted" % result})
+            return format_out({"result": "%d netmap deleted" % deleted})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_delnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/upload', method='POST')
 def http_uploadnetmap_datacenter_id(tenant_id, datacenter_id):
-    result, content = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, None)
-    if result < 0:
-        print "http_postnetmap_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    convert_datetime2str(content)
-    utils.convert_str2boolean(content, ('shared', 'multipoint') )
-    print content
-    data={'netmaps' : content}
-    return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        netmaps = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, None)
+        convert_datetime2str(netmaps)
+        utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
+        data={'netmaps' : netmaps}
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_uploadnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='POST')
 def http_postnetmap_datacenter_id(tenant_id, datacenter_id):
     '''creates a new netmap'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #parse input data
     http_content,_ = format_in( netmap_new_schema )
     r = utils.remove_extra_items(http_content, netmap_new_schema)
-    if r is not None: print "http_action_datacenter_id: Warning: remove extra items ", r
+    if r is not None: print "http_postnetmap_datacenter_id: Warning: remove extra items ", r
     
-    #obtain data, check that only one exist
-    result, content = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, http_content)
-    if result < 0:
-        print "http_postnetmap_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    convert_datetime2str(content)
-    utils.convert_str2boolean(content, ('shared', 'multipoint') )
-    print content
-    data={'netmaps' : content}
-    return format_out(data)
+    try:
+        #obtain data, check that only one exist
+        netmaps = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, http_content)
+        convert_datetime2str(netmaps)
+        utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
+        data={'netmaps' : netmaps}
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_postnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='PUT')
 def http_putnettmap_datacenter_id(tenant_id, datacenter_id, netmap_id):
     '''edit a  netmap'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #parse input data
     http_content,_ = format_in( netmap_edit_schema )
     r = utils.remove_extra_items(http_content, netmap_edit_schema)
     if r is not None: print "http_putnettmap_datacenter_id: Warning: remove extra items ", r
     
     #obtain data, check that only one exist
-    result, content = nfvo.datacenter_edit_netmap(mydb, tenant_id, datacenter_id, netmap_id, http_content)
-    if result < 0:
-        print "http_putnettmap_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    else:
+    try:
+        nfvo.datacenter_edit_netmap(mydb, tenant_id, datacenter_id, netmap_id, http_content)
         return http_getnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_putnettmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
     
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/action', method='POST')
 def http_action_datacenter_id(tenant_id, datacenter_id):
     '''perform an action over datacenter, can use both uuid or name'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #parse input data
     http_content,_ = format_in( datacenter_action_schema )
     r = utils.remove_extra_items(http_content, datacenter_action_schema)
     if r is not None: print "http_action_datacenter_id: Warning: remove extra items ", r
     
-    #obtain data, check that only one exist
-    result, content = nfvo.datacenter_action(mydb, tenant_id, datacenter_id, http_content)
-    if result < 0:
-        print "http_action_datacenter_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    if 'net-update' in http_content:
-        return http_getnetmap_datacenter_id(datacenter_id)
-    else:
-        return format_out(content)
+    try:
+        #obtain data, check that only one exist
+        result = nfvo.datacenter_action(mydb, tenant_id, datacenter_id, http_content)
+        if 'net-update' in http_content:
+            return http_getnetmap_datacenter_id(datacenter_id)
+        else:
+            return format_out(result)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_action_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 
 @bottle.route(url_base + '/datacenters/<datacenter_id>', method='DELETE')
 def http_delete_datacenter_id( datacenter_id):
     '''delete a tenant from database, can use both uuid or name'''
     
-    result, data = nfvo.delete_datacenter(mydb, datacenter_id)
-    if result < 0:
-        print "http_delete_datacenter_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        #print json.dumps(data, indent=4)
-        return format_out({"result":"datacenter " + data + " deleted"})
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        data = nfvo.delete_datacenter(mydb, datacenter_id)
+        return format_out({"result":"datacenter '" + data + "' deleted"})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_delete_datacenter_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='POST')
 def http_associate_datacenters(tenant_id, datacenter_id):
     '''associate an existing datacenter to a this tenant. '''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #parse input data
     http_content,_ = format_in( datacenter_associate_schema )
     r = utils.remove_extra_items(http_content, datacenter_associate_schema)
     if r != None: print "http_associate_datacenters: Warning: remove extra items ", r
-    result, data = nfvo.associate_datacenter_to_tenant(mydb, tenant_id, datacenter_id, 
-                                http_content['datacenter'].get('vim_tenant'),
-                                http_content['datacenter'].get('vim_tenant_name'),
-                                http_content['datacenter'].get('vim_username'),
-                                http_content['datacenter'].get('vim_password')
-                     )
-    if result < 0:
-        print "http_associate_datacenters error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        print "http_associate_datacenters data" , data 
-        return http_get_datacenter_id(tenant_id, data)
+    try:
+        id_ = nfvo.associate_datacenter_to_tenant(mydb, tenant_id, datacenter_id, 
+                                    http_content['datacenter'].get('vim_tenant'),
+                                    http_content['datacenter'].get('vim_tenant_name'),
+                                    http_content['datacenter'].get('vim_username'),
+                                    http_content['datacenter'].get('vim_password')
+                         )
+        return http_get_datacenter_id(tenant_id, id_)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_associate_datacenters error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='DELETE')
 def http_deassociate_datacenters(tenant_id, datacenter_id):
     '''deassociate an existing datacenter to a this tenant. '''
-    result, data = nfvo.deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter_id)
-    if result < 0:
-        print "http_deassociate_datacenters error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        return format_out({"result":data})
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        data = nfvo.deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter_id)
+        return format_out({"result": data})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_deassociate_datacenters error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
        
-
-
 @bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>', method='GET')
 @bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>/<name>', method='GET')
 def http_get_vim_items(tenant_id, datacenter_id, item, name=None):
-    result, data = nfvo.vim_action_get(mydb, tenant_id, datacenter_id, item, name)
-    if result < 0:
-        print "http_get_vim_items error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        data = nfvo.vim_action_get(mydb, tenant_id, datacenter_id, item, name)
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_vim_items error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>/<name>', method='DELETE')
 def http_del_vim_items(tenant_id, datacenter_id, item, name):
-    result, data = nfvo.vim_action_delete(mydb, tenant_id, datacenter_id, item, name)
-    if result < 0:
-        print "http_get_vim_items error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        data = nfvo.vim_action_delete(mydb, tenant_id, datacenter_id, item, name)
         return format_out({"result":data})
-
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_del_vim_items error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 @bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>', method='POST')
 def http_post_vim_items(tenant_id, datacenter_id, item):
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content,_ = format_in( object_schema )
-    result, data = nfvo.vim_action_create(mydb, tenant_id, datacenter_id, item, http_content)
-    if result < 0:
-        print "http_post_vim_items error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    try:
+        data = nfvo.vim_action_create(mydb, tenant_id, datacenter_id, item, http_content)
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_vim_items error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/vnfs', method='GET')
 def http_get_vnfs(tenant_id):
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_get_vnf_id() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    select_,where_,limit_ = filter_query_string(bottle.request.query, None,
-            ('uuid','name','description','public', "tenant_id", "created_at") )
-    where_or = {}
-    if tenant_id != "any":
-        where_or["tenant_id"] = tenant_id
-        where_or["public"] = True
-    result, content = mydb.get_table(FROM='vnfs', SELECT=select_,WHERE=where_,WHERE_OR=where_or, WHERE_AND_OR="AND",LIMIT=limit_)
-    if result < 0:
-        print "http_get_vnfs Error", content
-        bottle.abort(-result, content)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        if tenant_id != 'any':
+            #check valid tenant_id
+            nfvo.check_tenant(mydb, tenant_id)
+        select_,where_,limit_ = filter_query_string(bottle.request.query, None,
+                ('uuid','name','description','public', "tenant_id", "created_at") )
+        where_or = {}
+        if tenant_id != "any":
+            where_or["tenant_id"] = tenant_id
+            where_or["public"] = True
+        vnfs = mydb.get_rows(FROM='vnfs', SELECT=select_,WHERE=where_,WHERE_OR=where_or, WHERE_AND_OR="AND",LIMIT=limit_)
         #change_keys_http2db(content, http2db_vnf, reverse=True)
-        utils.convert_str2boolean(content, ('public',))
-        convert_datetime2str(content)
-        data={'vnfs' : content}
+        utils.convert_str2boolean(vnfs, ('public',))
+        convert_datetime2str(vnfs)
+        data={'vnfs' : vnfs}
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_vnfs error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/vnfs/<vnf_id>', method='GET')
 def http_get_vnf_id(tenant_id,vnf_id):
     '''get vnf details, can use both uuid or name'''
-    result, data = nfvo.get_vnf_id(mydb,tenant_id,vnf_id)
-    if result < 0:
-        print "http_post_vnfs error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-
-    utils.convert_str2boolean(data, ('public',))
-    convert_datetime2str(data)
-    return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        vnf = nfvo.get_vnf_id(mydb,tenant_id,vnf_id)
+        utils.convert_str2boolean(vnf, ('public',))
+        convert_datetime2str(vnf)
+        return format_out(vnf)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_vnf_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/vnfs', method='POST')
 def http_post_vnfs(tenant_id):
     '''insert a vnf into the catalogue. Creates the flavor and images in the VIM, and creates the VNF and its internal structure in the OPENMANO DB'''
-    print "Parsing the YAML file of the VNF"
+    #print "Parsing the YAML file of the VNF"
     #parse input data
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content, used_schema = format_in( vnfd_schema_v01, ("version",), {"v0.2": vnfd_schema_v02})
     r = utils.remove_extra_items(http_content, used_schema)
     if r is not None: print "http_post_vnfs: Warning: remove extra items ", r
-    result, data = nfvo.new_vnf(mydb,tenant_id,http_content)
-    if result < 0:
-        print "http_post_vnfs error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        return http_get_vnf_id(tenant_id,data)
+    try:
+        vnf_id = nfvo.new_vnf(mydb,tenant_id,http_content)
+        return http_get_vnf_id(tenant_id, vnf_id)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
             
 @bottle.route(url_base + '/<tenant_id>/vnfs/<vnf_id>', method='DELETE')
 def http_delete_vnf_id(tenant_id,vnf_id):
     '''delete a vnf from database, and images and flavors in VIM when appropriate, can use both uuid or name'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #check valid tenant_id and deletes the vnf, including images, 
-    result, data = nfvo.delete_vnf(mydb,tenant_id,vnf_id)
-    if result < 0:
-        print "http_delete_vnf_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    try:
+        data = nfvo.delete_vnf(mydb,tenant_id,vnf_id)
         #print json.dumps(data, indent=4)
         return format_out({"result":"VNF " + data + " deleted"})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_delete_vnf_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 #@bottle.route(url_base + '/<tenant_id>/hosts/topology', method='GET')
 #@bottle.route(url_base + '/<tenant_id>/physicalview/Madrid-Alcantara', method='GET')
 @bottle.route(url_base + '/<tenant_id>/physicalview/<datacenter>', method='GET')
 def http_get_hosts(tenant_id, datacenter):
     '''get the tidvim host hopology from the vim.'''
-    global mydb
-    print "http_get_hosts received by tenant " + tenant_id + ' datacenter ' + datacenter
-    if datacenter == 'treeview':
-        result, data = nfvo.get_hosts(mydb, tenant_id)
-    else:
-        #openmano-gui is using a hardcoded value for the datacenter
-        result, data = nfvo.get_hosts_info(mydb, tenant_id) #, datacenter)
-    
-    if result < 0:
-        print "http_post_vnfs error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        convert_datetime2str(data)
-        print json.dumps(data, indent=4)
-        return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    #print "http_get_hosts received by tenant " + tenant_id + ' datacenter ' + datacenter
+    try:
+        if datacenter == 'treeview':
+            data = nfvo.get_hosts(mydb, tenant_id)
+        else:
+            #openmano-gui is using a hardcoded value for the datacenter
+            result, data = nfvo.get_hosts_info(mydb, tenant_id) #, datacenter)
+        
+        if result < 0:
+            print "http_post_vnfs error %d %s" % (-result, data)
+            bottle.abort(-result, data)
+        else:
+            convert_datetime2str(data)
+            print json.dumps(data, indent=4)
+            return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 
 @bottle.route(url_base + '/<path:path>', method='OPTIONS')
 def http_options_deploy(path):
     '''For some reason GUI web ask for OPTIONS that must be responded'''
     #TODO: check correct path, and correct headers request
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     bottle.response.set_header('Access-Control-Allow-Methods','POST, GET, PUT, DELETE, OPTIONS')
     bottle.response.set_header('Accept','application/yaml,application/json')
     bottle.response.set_header('Content-Type','application/yaml,application/json')
@@ -781,31 +805,28 @@ def http_options_deploy(path):
 @bottle.route(url_base + '/<tenant_id>/topology/deploy', method='POST')
 def http_post_deploy(tenant_id):
     '''post topology deploy.'''
-    print "http_post_deploy by tenant " + tenant_id 
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
 
     http_content, used_schema = format_in( nsd_schema_v01, ("schema_version",), {2: nsd_schema_v02})
     #r = utils.remove_extra_items(http_content, used_schema)
     #if r is not None: print "http_post_deploy: Warning: remove extra items ", r
-    print "http_post_deploy input: ",  http_content
+    #print "http_post_deploy input: ",  http_content
     
-    result, scenario_uuid = nfvo.new_scenario(mydb, tenant_id, http_content)
-    if result < 0:
-        print "http_post_deploy error creating the scenario %d %s" % (-result, scenario_uuid)
-        bottle.abort(-result, scenario_uuid)
-
-    result, data = nfvo.start_scenario(mydb, tenant_id, scenario_uuid, http_content['name'], http_content['name'])
-    if result < 0:
-        print "http_post_deploy error launching the scenario %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        print json.dumps(data, indent=4)
-        return format_out(data)
+    try:
+        scenario_id = nfvo.new_scenario(mydb, tenant_id, http_content)
+        instance = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['name'], http_content['name'])
+        #print json.dumps(data, indent=4)
+        return format_out(instance)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_deploy error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/topology/verify', method='POST')
 def http_post_verify(tenant_id):
     #TODO:
 #    '''post topology verify'''
 #    print "http_post_verify by tenant " + tenant_id + ' datacenter ' + datacenter
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     return 
 
 #
@@ -815,176 +836,151 @@ def http_post_verify(tenant_id):
 @bottle.route(url_base + '/<tenant_id>/scenarios', method='POST')
 def http_post_scenarios(tenant_id):
     '''add a scenario into the catalogue. Creates the scenario and its internal structure in the OPENMANO DB'''
-    print "http_post_scenarios by tenant " + tenant_id 
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content, used_schema = format_in( nsd_schema_v01, ("schema_version",), {2: nsd_schema_v02})
     #r = utils.remove_extra_items(http_content, used_schema)
     #if r is not None: print "http_post_scenarios: Warning: remove extra items ", r
-    print "http_post_scenarios input: ",  http_content
-    if http_content.get("schema_version") == None:
-        result, data = nfvo.new_scenario(mydb, tenant_id, http_content)
-    else:
-        result, data = nfvo.new_scenario_v02(mydb, tenant_id, http_content)
-    if result < 0:
-        print "http_post_scenarios error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    #print "http_post_scenarios input: ",  http_content
+    try:
+        if http_content.get("schema_version") == None:
+            scenario_id = nfvo.new_scenario(mydb, tenant_id, http_content)
+        else:
+            scenario_id = nfvo.new_scenario_v02(mydb, tenant_id, http_content)
         #print json.dumps(data, indent=4)
         #return format_out(data)
-        return http_get_scenario_id(tenant_id,data)
+        return http_get_scenario_id(tenant_id, scenario_id)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_scenarios error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>/action', method='POST')
 def http_post_scenario_action(tenant_id, scenario_id):
     '''take an action over a scenario'''
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     #check valid tenant_id
-    if not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_post_scenario_action() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    #parse input data
-    http_content,_ = format_in( scenario_action_schema )
-    r = utils.remove_extra_items(http_content, scenario_action_schema)
-    if r is not None: print "http_post_scenario_action: Warning: remove extra items ", r
-    if "start" in http_content:
-        result, data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['start']['instance_name'], \
-                    http_content['start'].get('description',http_content['start']['instance_name']),
-                    http_content['start'].get('datacenter') )
-        if result < 0:
-            print "http_post_scenario_action start error %d: %s" % (-result, data)
-            bottle.abort(-result, data)
-        else:
+    try:
+        nfvo.check_tenant(mydb, tenant_id) 
+        #parse input data
+        http_content,_ = format_in( scenario_action_schema )
+        r = utils.remove_extra_items(http_content, scenario_action_schema)
+        if r is not None: print "http_post_scenario_action: Warning: remove extra items ", r
+        if "start" in http_content:
+            data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['start']['instance_name'], \
+                        http_content['start'].get('description',http_content['start']['instance_name']),
+                        http_content['start'].get('datacenter') )
             return format_out(data)
-    elif "deploy" in http_content:   #Equivalent to start
-        result, data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['deploy']['instance_name'],
-                    http_content['deploy'].get('description',http_content['deploy']['instance_name']),
-                    http_content['deploy'].get('datacenter') )
-        if result < 0:
-            print "http_post_scenario_action deploy error %d: %s" % (-result, data)
-            bottle.abort(-result, data)
-        else:
+        elif "deploy" in http_content:   #Equivalent to start
+            data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['deploy']['instance_name'],
+                        http_content['deploy'].get('description',http_content['deploy']['instance_name']),
+                        http_content['deploy'].get('datacenter') )
             return format_out(data)
-    elif "reserve" in http_content:   #Reserve resources
-        result, data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['reserve']['instance_name'],
-                    http_content['reserve'].get('description',http_content['reserve']['instance_name']),
-                    http_content['reserve'].get('datacenter'),  startvms=False )
-        if result < 0:
-            print "http_post_scenario_action reserve error %d: %s" % (-result, data)
-            bottle.abort(-result, data)
-        else:
+        elif "reserve" in http_content:   #Reserve resources
+            data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['reserve']['instance_name'],
+                        http_content['reserve'].get('description',http_content['reserve']['instance_name']),
+                        http_content['reserve'].get('datacenter'),  startvms=False )
             return format_out(data)
-    elif "verify" in http_content:   #Equivalent to start and then delete
-        result, data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['verify']['instance_name'],
-                    http_content['verify'].get('description',http_content['verify']['instance_name']),
-                    http_content['verify'].get('datacenter'), startvms=False )
-        if result < 0 or result!=1:
-            print "http_post_scenario_action verify error during start %d: %s" % (-result, data)
-            bottle.abort(-result, data)
-        instance_id = data['uuid']
-        result, message = nfvo.delete_instance(mydb, tenant_id,instance_id)
-        if result < 0:
-            print "http_post_scenario_action verify error during start delete_instance_id %d %s" % (-result, message)
-            bottle.abort(-result, message)
-        else:
-            #print json.dumps(data, indent=4)
+        elif "verify" in http_content:   #Equivalent to start and then delete
+            data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['verify']['instance_name'],
+                        http_content['verify'].get('description',http_content['verify']['instance_name']),
+                        http_content['verify'].get('datacenter'), startvms=False )
+            instance_id = data['uuid']
+            nfvo.delete_instance(mydb, tenant_id,instance_id)
             return format_out({"result":"Verify OK"})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_scenario_action error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/scenarios', method='GET')
 def http_get_scenarios(tenant_id):
     '''get scenarios list'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print "httpserver.http_get_scenarios() tenant '%s' not found" % tenant_id
-        bottle.abort(HTTP_Not_Found, "Tenant '%s' not found" % tenant_id)
-        return
-    #obtain data
-    s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'description', 'tenant_id', 'created_at', 'public'))
-    where_or={}
-    if tenant_id != "any":
-        where_or["tenant_id"] = tenant_id
-        where_or["public"] = True
-    result, data = mydb.get_table(SELECT=s, WHERE=w, WHERE_OR=where_or, WHERE_AND_OR="AND", LIMIT=l, FROM='scenarios')
-    if result < 0:
-        print "http_get_scenarios error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        convert_datetime2str(data)
-        utils.convert_str2boolean(data, ('public',) )
-        scenarios={'scenarios':data}
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        #obtain data
+        s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'description', 'tenant_id', 'created_at', 'public'))
+        where_or={}
+        if tenant_id != "any":
+            where_or["tenant_id"] = tenant_id
+            where_or["public"] = True
+        scenarios = mydb.get_rows(SELECT=s, WHERE=w, WHERE_OR=where_or, WHERE_AND_OR="AND", LIMIT=l, FROM='scenarios')
+        convert_datetime2str(scenarios)
+        utils.convert_str2boolean(scenarios, ('public',) )
+        data={'scenarios':scenarios}
         #print json.dumps(scenarios, indent=4)
-        return format_out(scenarios)
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='GET')
 def http_get_scenario_id(tenant_id, scenario_id):
     '''get scenario details, can use both uuid or name'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print "httpserver.http_get_scenario_id() tenant '%s' not found" % tenant_id
-        bottle.abort(HTTP_Not_Found, "Tenant '%s' not found" % tenant_id)
-        return
-    #obtain data
-    result, content = mydb.get_scenario(scenario_id, tenant_id)
-    if result < 0:
-        print "http_get_scenario_id error %d %s" % (-result, content)
-        bottle.abort(-result, content)
-    else:
-        #print json.dumps(content, indent=4)
-        convert_datetime2str(content)
-        data={'scenario' : content}
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        #obtain data
+        scenario = mydb.get_scenario(scenario_id, tenant_id)
+        convert_datetime2str(scenario)
+        data={'scenario' : scenario}
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='DELETE')
 def http_delete_scenario_id(tenant_id, scenario_id):
     '''delete a scenario from database, can use both uuid or name'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print "httpserver.http_delete_scenario_id() tenant '%s' not found" % tenant_id
-        bottle.abort(HTTP_Not_Found, "Tenant '%s' not found" % tenant_id)
-        return
-    #obtain data
-    result, data = mydb.delete_scenario(scenario_id, tenant_id)
-    if result < 0:
-        print "http_delete_scenario_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        #obtain data
+        data = mydb.delete_scenario(scenario_id, tenant_id)
         #print json.dumps(data, indent=4)
         return format_out({"result":"scenario " + data + " deleted"})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_delete_scenario_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 
 @bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='PUT')
 def http_put_scenario_id(tenant_id, scenario_id):
     '''edit an existing scenario id'''
-    print "http_put_scenarios by tenant " + tenant_id 
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
     http_content,_ = format_in( scenario_edit_schema )
     #r = utils.remove_extra_items(http_content, scenario_edit_schema)
     #if r is not None: print "http_put_scenario_id: Warning: remove extra items ", r
-    print "http_put_scenario_id input: ",  http_content
-    
-    result, data = nfvo.edit_scenario(mydb, tenant_id, scenario_id, http_content)
-    if result < 0:
-        print "http_put_scenarios error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    #print "http_put_scenario_id input: ",  http_content
+    try:
+        nfvo.edit_scenario(mydb, tenant_id, scenario_id, http_content)
         #print json.dumps(data, indent=4)
         #return format_out(data)
-        return http_get_scenario_id(tenant_id,data)
+        return http_get_scenario_id(tenant_id, scenario_id)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_put_scenario_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/instances', method='POST')
 def http_post_instances(tenant_id):
     '''take an action over a scenario'''
-    #check valid tenant_id
-    if not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_post_scenario_action() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    #parse input data
-    http_content,used_schema = format_in( instance_scenario_create_schema)
-    r = utils.remove_extra_items(http_content, used_schema)
-    if r is not None: print "http_post_instances: Warning: remove extra items ", r
-    result, data = nfvo.create_instance(mydb, tenant_id, http_content["instance"])
-    if result < 0:
-        print "http_post_instances start error %d: %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        #parse input data
+        http_content,used_schema = format_in( instance_scenario_create_schema)
+        r = utils.remove_extra_items(http_content, used_schema)
+        if r is not None: print "http_post_instances: Warning: remove extra items ", r
+        data = nfvo.create_instance(mydb, tenant_id, http_content["instance"])
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_instances error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 #
 # INSTANCES
@@ -992,103 +988,88 @@ def http_post_instances(tenant_id):
 @bottle.route(url_base + '/<tenant_id>/instances', method='GET')
 def http_get_instances(tenant_id):
     '''get instance list'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_get_instances() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    #obtain data
-    s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'scenario_id', 'tenant_id', 'description', 'created_at'))
-    where_or={}
-    if tenant_id != "any":
-        w['tenant_id'] = tenant_id
-    result, data = mydb.get_table(SELECT=s, WHERE=w, LIMIT=l, FROM='instance_scenarios')
-    if result < 0:
-        print "http_get_instances error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
-        convert_datetime2str(data)
-        utils.convert_str2boolean(data, ('public',) )
-        instances={'instances':data}
-        print json.dumps(instances, indent=4)
-        return format_out(instances)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        #obtain data
+        s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'scenario_id', 'tenant_id', 'description', 'created_at'))
+        if tenant_id != "any":
+            w['tenant_id'] = tenant_id
+        instances = mydb.get_rows(SELECT=s, WHERE=w, LIMIT=l, FROM='instance_scenarios')
+        convert_datetime2str(instances)
+        utils.convert_str2boolean(instances, ('public',) )
+        data={'instances':instances}
+        return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_instances error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/instances/<instance_id>', method='GET')
 def http_get_instance_id(tenant_id, instance_id):
     '''get instances details, can use both uuid or name'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_get_instance_id() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    if tenant_id == "any":
-        tenant_id = None
-  
-    #obtain data (first time is only to check that the instance exists)
-    result, data = mydb.get_instance_scenario(instance_id, tenant_id, verbose=True)
-    if result < 0:
-        print "http_get_instance_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-        return
-    
-    r,c = nfvo.refresh_instance(mydb, tenant_id, data)
-    if r<0:
-        print "WARNING: nfvo.refresh_instance couldn't refresh the status of the instance: %s" %c
-    #obtain data with results upated
-    result, data = mydb.get_instance_scenario(instance_id, tenant_id)
-    if result < 0:
-        print "http_get_instance_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-        return
-    convert_datetime2str(data)
-    print json.dumps(data, indent=4)
-    return format_out(data)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        if tenant_id == "any":
+            tenant_id = None
+        #obtain data (first time is only to check that the instance exists)
+        instance_dict = mydb.get_instance_scenario(instance_id, tenant_id, verbose=True)
+        try:
+            nfvo.refresh_instance(mydb, tenant_id, instance_dict)
+        except (nfvo.NfvoException, db_base_Exception) as e:
+            logger.warn("nfvo.refresh_instance couldn't refresh the status of the instance: %s" % str(e))
+        #obtain data with results upated
+        instance = mydb.get_instance_scenario(instance_id, tenant_id)
+        convert_datetime2str(instance)
+        #print json.dumps(instance, indent=4)
+        return format_out(instance)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_get_instance_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/instances/<instance_id>', method='DELETE')
 def http_delete_instance_id(tenant_id, instance_id):
     '''delete instance from VIM and from database, can use both uuid or name'''
-    #check valid tenant_id
-    if tenant_id != "any" and not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_delete_instance_id() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    if tenant_id == "any":
-        tenant_id = None
-    #obtain data
-    result, message = nfvo.delete_instance(mydb, tenant_id,instance_id)
-    if result < 0:
-        print "http_delete_instance_id error %d %s" % (-result, message)
-        bottle.abort(-result, message)
-    else:
-        #print json.dumps(data, indent=4)
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+        if tenant_id == "any":
+            tenant_id = None
+        #obtain data
+        message = nfvo.delete_instance(mydb, tenant_id,instance_id)
         return format_out({"result":message})
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_delete_instance_id error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 @bottle.route(url_base + '/<tenant_id>/instances/<instance_id>/action', method='POST')
 def http_post_instance_scenario_action(tenant_id, instance_id):
     '''take an action over a scenario instance'''
-    #check valid tenant_id
-    if not nfvo.check_tenant(mydb, tenant_id): 
-        print 'httpserver.http_post_instance_scenario_action() tenant %s not found' % tenant_id
-        bottle.abort(HTTP_Not_Found, 'Tenant %s not found' % tenant_id)
-        return
-    #parse input data
-    http_content,_ = format_in( instance_scenario_action_schema )
-    r = utils.remove_extra_items(http_content, instance_scenario_action_schema)
-    if r is not None: print "http_post_instance_scenario_action: Warning: remove extra items ", r
-    print "http_post_instance_scenario_action input: ", http_content
-    #obtain data
-    result, data = mydb.get_instance_scenario(instance_id, tenant_id)
-    if result < 0:
-        print "http_get_instance_id error %d %s" % (-result, data)
-        bottle.abort(-result, data)
-    instance_id = data["uuid"]
-    
-    result, data = nfvo.instance_action(mydb, tenant_id, instance_id, http_content)
-    if result < 0:
-        print "http_post_scenario_action error %d: %s" % (-result, data)
-        bottle.abort(-result, data)
-    else:
+    logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
+    try:
+        #check valid tenant_id
+        if tenant_id != "any":
+            nfvo.check_tenant(mydb, tenant_id) 
+
+        #parse input data
+        http_content,_ = format_in( instance_scenario_action_schema )
+        r = utils.remove_extra_items(http_content, instance_scenario_action_schema)
+        if r is not None: print "http_post_instance_scenario_action: Warning: remove extra items ", r
+        #print "http_post_instance_scenario_action input: ", http_content
+        #obtain data
+        instance = mydb.get_instance_scenario(instance_id, tenant_id)
+        instance_id = instance["uuid"]
+        
+        data = nfvo.instance_action(mydb, tenant_id, instance_id, http_content)
         return format_out(data)
+    except (nfvo.NfvoException, db_base_Exception) as e:
+        logger.error("http_post_instance_scenario_action error {}: {}".format(e.http_code, str(e)))
+        bottle.abort(e.http_code, str(e))
 
 
 @bottle.error(400)
diff --git a/nfvo.py b/nfvo.py
index 5289ba9..13d5c9e 100644 (file)
--- a/nfvo.py
+++ b/nfvo.py
@@ -31,11 +31,12 @@ import imp
 #import json
 import yaml
 import utils
-from nfvo_db import HTTP_Unauthorized, HTTP_Bad_Request, HTTP_Internal_Server_Error, HTTP_Not_Found,\
+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
+from db_base import db_base_Exception
 
 global global_config
 global vimconn_imported
@@ -63,16 +64,13 @@ def get_flavorlist(mydb, vnf_id, nfvo_tenant=None):
     
     #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
     #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
-    result, content = mydb.get_table(FROM='vms join flavors on vms.flavor_id=flavors.uuid',SELECT=('flavor_id',),WHERE=WHERE_dict )
-    if result < 0:
-        print "nfvo.get_flavorlist error %d %s" % (result, content)
-        return -result, content
-    print "get_flavor_list result:", result
-    print "get_flavor_list content:", content
+    flavors = mydb.get_rows(FROM='vms join flavors on vms.flavor_id=flavors.uuid',SELECT=('flavor_id',),WHERE=WHERE_dict )
+    #print "get_flavor_list result:", result
+    #print "get_flavor_list content:", content
     flavorList=[]
-    for flavor in content:
+    for flavor in flavors:
         flavorList.append(flavor['flavor_id'])
-    return result, flavorList
+    return flavorList
 
 def get_imagelist(mydb, vnf_id, nfvo_tenant=None):
     '''Obtain imageList
@@ -86,16 +84,11 @@ def get_imagelist(mydb, vnf_id, nfvo_tenant=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 )
-    result, content = mydb.get_table(FROM='vms join images on vms.image_id=images.uuid',SELECT=('image_id',),WHERE=WHERE_dict )
-    if result < 0:
-        print "nfvo.get_imagelist error %d %s" % (result, content)
-        return -result, content
-    print "get_image_list result:", result
-    print "get_image_list content:", content
+    images = mydb.get_rows(FROM='vms join images on vms.image_id=images.uuid',SELECT=('image_id',),WHERE=WHERE_dict )
     imageList=[]
-    for image in content:
+    for image in images:
         imageList.append(image['image_id'])
-    return result, imageList
+    return imageList
 
 def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vim_tenant=None):
     '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
@@ -117,46 +110,42 @@ def get_vim(mydb, nfvo_tenant=None, datacenter_id=None, datacenter_name=None, vi
     else:
         from_ = 'datacenters as d'
         select_ = ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
-    result, content = mydb.get_table(FROM=from_, SELECT=select_, WHERE=WHERE_dict )
-    if result < 0:
-        print "nfvo.get_vim error %d %s" % (result, content)
-        return result, content
-    #elif result==0:
-    #    print "nfvo.get_vim not found a valid VIM with the input params " + str(WHERE_dict)
-    #    return -HTTP_Not_Found, "datacenter not found for " +  str(WHERE_dict)
-    #print content
-    vim_dict={}
-    for vim in content:
-        extra={'datacenter_tenant_id': vim.get('datacenter_tenant_id')}
-        if vim["config"] != None:
-            extra.update(yaml.load(vim["config"]))
-        if vim["type"] not in vimconn_imported:
-            module_info=None
+    try:
+        vims = mydb.get_rows(FROM=from_, SELECT=select_, WHERE=WHERE_dict )
+        vim_dict={}
+        for vim in vims:
+            extra={'datacenter_tenant_id': vim.get('datacenter_tenant_id')}
+            if vim["config"] != None:
+                extra.update(yaml.load(vim["config"]))
+            if vim["type"] not in vimconn_imported:
+                module_info=None
+                try:
+                    module = "vimconn_" + vim["type"]
+                    module_info = imp.find_module(module)
+                    vim_conn = imp.load_module(vim["type"], *module_info)
+                    vimconn_imported[vim["type"]] = vim_conn
+                except (IOError, ImportError) as e:
+                    if module_info and module_info[0]:
+                        file.close(module_info[0])
+                    raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
+                                            vim["type"], module, type(e).__name__, str(e)), HTTP_Bad_Request)
+    
             try:
-                module = "vimconn_" + vim["type"]
-                module_info = imp.find_module(module)
-                vim_conn = imp.load_module(vim["type"], *module_info)
-                vimconn_imported[vim["type"]] = vim_conn
-            except (IOError, ImportError) as e:
-                if module_info and module_info[0]:
-                    file.close(module_info[0])
-                print "Cannot open VIM module '%s.py'; %s: %s" % ( module, type(e).__name__, str(e))
-                return -HTTP_Bad_Request, "Unknown vim type %s" % vim["type"]
-
-        try:
-            #if not tenant:
-            #    return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
-            vim_dict[ vim['datacenter_id'] ] = vimconn_imported[ vim["type"] ].vimconnector(
-                            uuid=vim['datacenter_id'], name=vim['datacenter_name'],
-                            tenant_id=vim.get('vim_tenant_id'), tenant_name=vim.get('vim_tenant_name'),
-                            url=vim['vim_url'], url_admin=vim['vim_url_admin'], 
-                            user=vim.get('user'), passwd=vim.get('passwd'),
-                            config=extra
-                    )
-        except Exception as e:
-            return -HTTP_Internal_Server_Error, "Error at VIM  %s; %s: %s" % ( vim["type"], type(e).__name__, str(e))
-    return len(vim_dict), vim_dict
-
+                #if not tenant:
+                #    return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM  %s" % ( vim["type"])
+                vim_dict[ vim['datacenter_id'] ] = vimconn_imported[ vim["type"] ].vimconnector(
+                                uuid=vim['datacenter_id'], name=vim['datacenter_name'],
+                                tenant_id=vim.get('vim_tenant_id'), tenant_name=vim.get('vim_tenant_name'),
+                                url=vim['vim_url'], url_admin=vim['vim_url_admin'], 
+                                user=vim.get('user'), passwd=vim.get('passwd'),
+                                config=extra
+                        )
+            except Exception as e:
+                raise NfvoException("Error at VIM  {}; {}: {}".format(vim["type"], type(e).__name__, str(e)), HTTP_Internal_Server_Error)
+        return vim_dict
+    except db_base_Exception as e:
+        raise NfvoException(str(e) + " at nfvo.get_vim", e.http_code)
+    
 def rollback(mydb,  vims, rollback_list):
     undeleted_items=[]
     #delete things by reverse order 
@@ -169,14 +158,10 @@ def rollback(mydb,  vims, rollback_list):
             try:
                 if item["what"]=="image":
                     vim.delete_image(item["uuid"])
-                    result, message = mydb.delete_row_by_dict(FROM="datacenters_images", WEHRE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
-                    if result < 0:
-                        logger.error("Error in rollback. Not possible to delete image '%s' from DB.dacenters_images. Message: %s", item["uuid"],message)
+                    mydb.delete_row(FROM="datacenters_images", WHERE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
                 elif item["what"]=="flavor":
                     vim.delete_flavor(item["uuid"])
-                    result, message = mydb.delete_row_by_dict(FROM="datacenters_flavos", WEHRE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
-                    if result < 0:
-                        logger.error("Error in rollback. Not possible to delete flavor '%s' from DB.dacenters_flavors. Message: %s", item["uuid"],message)
+                    mydb.delete_row(FROM="datacenters_flavos", WHERE={"datacenter_id": vim["id"], "vim_id":item["uuid"]})
                 elif item["what"]=="network":
                     vim.delete_network(item["uuid"])
                 elif item["what"]=="vm":
@@ -184,18 +169,18 @@ def rollback(mydb,  vims, rollback_list):
             except vimconn.vimconnException as e:
                 logger.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item['what'], item["uuid"], str(e))
                 undeleted_items.append("{} {} from VIM {}".format(item['what'], item["uuid"], vim["name"]))
+            except db_base_Exception as e:
+                logger.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item['what'], item["uuid"], str(e))
                         
         else: # where==mano
-            if item["what"]=="image":
-                result, message = mydb.delete_row_by_dict(FROM="images", WEHRE={"uuid": item["uuid"]})
-                if result < 0:
-                    logger.error("Error in rollback. Not possible to delete image '%s' from DB.images. Message: %s", item["uuid"], message)
-                    undeleted_items.append("image %s" % (item["uuid"]))
-            elif item["what"]=="flavor":
-                result, message = mydb.delete_row_by_dict(FROM="flavors", WEHRE={"uuid": item["uuid"]})
-                if result < 0:
-                    logger.error("Error in rollback. Not possible to delete flavor '%s' from DB.flavors. Message: %s", item["uuid"], message)
-                    undeleted_items.append("flavor %s" % (item["uuid"]))
+            try:
+                if item["what"]=="image":
+                    mydb.delete_row(FROM="images", WHERE={"uuid": item["uuid"]})
+                elif item["what"]=="flavor":
+                    mydb.delete_row(FROM="flavors", WHERE={"uuid": item["uuid"]})
+            except db_base_Exception as e:
+                logger.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item['what'], item["uuid"], str(e))
+                undeleted_items.append("{} '{}'".format(item['what'], item["uuid"]))
     if len(undeleted_items)==0: 
         return True," Rollback successful."
     else:
@@ -211,12 +196,16 @@ def check_vnf_descriptor(vnf_descriptor):
         for numa in vnfc.get("numas",() ):
             for interface in numa.get("interfaces",()):
                 if interface["name"] in name_list:
-                    return -HTTP_Bad_Request, "Error at vnf:VNFC[name:'%s']:numas:interfaces:name, interface name '%s' already used in this VNFC" %(vnfc["name"], interface["name"])
-                name_list.append( 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) 
+                name_list.append( interface["name"] )
         #bridge interfaces
         for interface in vnfc.get("bridge-ifaces",() ):
             if interface["name"] in name_list:
-                return -HTTP_Bad_Request, "Error at vnf:VNFC[name:'%s']:bridge-ifaces:name, interface name '%s' already used in this VNFC" %(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)
             name_list.append( interface["name"] ) 
         vnfc_interfaces[ vnfc["name"] ] = name_list
     
@@ -224,59 +213,64 @@ def check_vnf_descriptor(vnf_descriptor):
     name_list=[]
     for external_connection in vnf_descriptor["vnf"].get("external-connections",() ):
         if external_connection["name"] in name_list:
-            return -HTTP_Bad_Request, "Error at vnf:external-connections:name, value '%s' already used as an external-connection" %(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)
         name_list.append(external_connection["name"])
         if external_connection["VNFC"] not in vnfc_interfaces:
-            return -HTTP_Bad_Request, "Error at vnf:external-connections[name:'%s']:VNFC, value '%s' does not match any VNFC" %(external_connection["name"], external_connection["VNFC"])
+            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)
+            
         if external_connection["local_iface_name"] not in vnfc_interfaces[ external_connection["VNFC"] ]:
-            return -HTTP_Bad_Request, "Error at vnf:external-connections[name:'%s']:local_iface_name, value '%s' does not match any interface of this VNFC" %(external_connection["name"], external_connection["local_iface_name"])
+            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 )
     
     #check if the info in internal_connections matches with the one in the vnfcs
     name_list=[]
     for internal_connection in vnf_descriptor["vnf"].get("internal-connections",() ):
         if internal_connection["name"] in name_list:
-            return -HTTP_Bad_Request, "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection" %(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)
         name_list.append(internal_connection["name"])
         #We should check that internal-connections of type "ptp" have only 2 elements
         if len(internal_connection["elements"])>2 and internal_connection["type"] == "ptp":
-            return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements, size must be 2 for a type:'ptp'" %(internal_connection["name"])
+            raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
+                                .format(internal_connection["name"]),
+                                HTTP_Bad_Request)
         for port in internal_connection["elements"]:
             if port["VNFC"] not in vnfc_interfaces:
-                return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements[]:VNFC, value '%s' does not match any VNFC" %(internal_connection["name"], port["VNFC"])
+                raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
+                                    .format(internal_connection["name"], port["VNFC"]),
+                                    HTTP_Bad_Request)
             if port["local_iface_name"] not in vnfc_interfaces[ port["VNFC"] ]:
-                return -HTTP_Bad_Request, "Error at vnf:internal-connections[name:'%s']:elements[]:local_iface_name, value '%s' does not match any interface of this VNFC" %(internal_connection["name"], port["local_iface_name"])
-
-    
-    return 200, None
+                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"], port["local_iface_name"]),
+                                    HTTP_Bad_Request)
+                return -HTTP_Bad_Request, 
 
 def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = False):
     #look if image exist
     if only_create_at_vim:
         image_mano_id = image_dict['uuid']
     else:
-        res,content = mydb.get_table(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']})
-        if res>=1:
-            image_mano_id = content[0]['uuid']
-        elif res<0:
-            return res, content
+        images = mydb.get_rows(FROM="images", WHERE={'location':image_dict['location'], 'metadata':image_dict['metadata']})
+        if len(images)>=1:
+            image_mano_id = images[0]['uuid']
         else:
             #create image
             temp_image_dict={'name':image_dict['name'],         'description':image_dict.get('description',None),
                             'location':image_dict['location'],  'metadata':image_dict.get('metadata',None)
                             }
-            res,content = mydb.new_row('images', temp_image_dict, tenant_id=None, add_uuid=True)
-            if res>0:
-                image_mano_id= content
-                rollback_list.append({"where":"mano", "what":"image","uuid":image_mano_id})
-            else:
-                return res if res<0 else -1, content
+            image_mano_id = mydb.new_row('images', temp_image_dict, add_uuid=True)
+            rollback_list.append({"where":"mano", "what":"image","uuid":image_mano_id})
     #create image at every vim
     for vim_id,vim in vims.iteritems():
         image_created="false"
         #look at database
-        res_db,image_db = mydb.get_table(FROM="datacenters_images", WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id})
-        if res_db<0:
-            return res_db, image_db
+        image_db = mydb.get_rows(FROM="datacenters_images", WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id})
         #look at VIM if this image exist
         try:
             image_vim_id = vim.get_image_id_from_path(image_dict['location'])
@@ -289,7 +283,7 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi
             except vimconn.vimconnException as e:
                 if return_on_error:
                     logger.error("Error creating image at VIM: %s", str(e))
-                    return -e.http_code, str(e)
+                    raise
                 image_vim_id = str(e)
                 logger.warn("Error creating image at VIM: %s", str(e))
                 continue
@@ -298,14 +292,14 @@ def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vi
             image_vim_id = str(e)
             continue    
         #if reach here the image has been create or exist
-        if res_db==0:
+        if len(image_db)==0:
             #add new vim_id at datacenters_images
             mydb.new_row('datacenters_images', {'datacenter_id':vim_id, 'image_id':image_mano_id, 'vim_id': image_vim_id, 'created':image_created})
         elif image_db[0]["vim_id"]!=image_vim_id:
             #modify existing vim_id at datacenters_images
             mydb.update_rows('datacenters_images', UPDATE={'vim_id':image_vim_id}, WHERE={'datacenter_id':vim_id, 'image_id':image_mano_id})
             
-    return 1, image_vim_id if only_create_at_vim else image_mano_id
+    return image_vim_id if only_create_at_vim else image_mano_id
 
 def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_vim=False, return_on_error = False):
     temp_flavor_dict= {'disk':flavor_dict.get('disk',1),
@@ -321,11 +315,9 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
     if only_create_at_vim:
         flavor_mano_id = flavor_dict['uuid']
     else:
-        res,content = mydb.get_table(FROM="flavors", WHERE=temp_flavor_dict)
-        if res>=1:
-            flavor_mano_id = content[0]['uuid']
-        elif res<0:
-            return res, content
+        flavors = mydb.get_rows(FROM="flavors", WHERE=temp_flavor_dict)
+        if len(flavors)>=1:
+            flavor_mano_id = flavors[0]['uuid']
         else:
             #create flavor
             #create one by one the images of aditional disks
@@ -341,20 +333,15 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
                     if image_metadata_dict != None: 
                         image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
                     image_dict['metadata']=image_metadata_str
-                    res, image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
-                    if res < 0:
-                        return res, image_id + rollback(mydb, vims, rollback_list)[1]
-                    print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
+                    image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
+                    #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
                     dev_image_list.append(image_id)
                     dev_nb += 1                
             temp_flavor_dict['name'] = flavor_dict['name']
             temp_flavor_dict['description'] = flavor_dict.get('description',None)
-            res,content = mydb.new_row('flavors', temp_flavor_dict, tenant_id=None, add_uuid=True)
-            if res>0:
-                flavor_mano_id= content
-                rollback_list.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id})
-            else:
-                return res if res<0 else -1, content
+            content = mydb.new_row('flavors', temp_flavor_dict, add_uuid=True)
+            flavor_mano_id= content
+            rollback_list.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id})
     #create flavor at every vim
     if 'uuid' in flavor_dict:
         del flavor_dict['uuid']
@@ -362,9 +349,7 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
     for vim_id,vim in vims.items():
         flavor_created="false"
         #look at database
-        res_db,flavor_db = mydb.get_table(FROM="datacenters_flavors", WHERE={'datacenter_id':vim_id, 'flavor_id':flavor_mano_id})
-        if res_db<0:
-            return res_db, flavor_db
+        flavor_db = mydb.get_rows(FROM="datacenters_flavors", WHERE={'datacenter_id':vim_id, 'flavor_id':flavor_mano_id})
         #look at VIM if this flavor exist  SKIPPED
         #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
         #if res_vim < 0:
@@ -374,7 +359,6 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
     
         #Create the flavor in VIM
         #Translate images at devices from MANO id to VIM id
-        error=False
         if 'extended' in flavor_dict and flavor_dict['extended']!=None and "devices" in flavor_dict['extended']:
             #make a copy of original devices
             devices_original=[]
@@ -397,26 +381,12 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
                 if image_metadata_dict != None: 
                     image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
                 image_dict['metadata']=image_metadata_str
-                r,image_mano_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False)
-                if r<0:
-                    print "Error creating device image for flavor: %s." %image_mano_id
-                    error_text = image_mano_id
-                    error=True
-                    break
+                image_mano_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error=return_on_error )
                 image_dict["uuid"]=image_mano_id
-                r,image_vim_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=True)
-                if r<0:
-                    print "Error creating device image for flavor at VIM: %s." %image_vim_id
-                    error_text = image_vim_id
-                    error=True
-                    break
+                image_vim_id=create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=True, return_on_error=return_on_error)
                 flavor_dict["extended"]["devices"][index]['imageRef']=image_vim_id
                 dev_nb += 1
-        if error:
-            if return_on_error:
-                return r, error_text
-            continue
-        if res_db>0:
+        if len(flavor_db)>0:
             #check that this vim_id exist in VIM, if not create
             flavor_vim_id=flavor_db[0]["vim_id"]
             try:
@@ -433,50 +403,41 @@ def create_or_use_flavor(mydb, vims, flavor_dict, rollback_list, only_create_at_
         except vimconn.vimconnException as e:
             if return_on_error:
                 logger.error("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
-                return -e.http_code, str(e)
+                raise
             logger.warn("Error creating flavor at VIM %s: %s.", vim["name"], str(e))
             continue
         #if reach here the flavor has been create or exist
-        if res_db==0:
+        if len(flavor_db)==0:
             #add new vim_id at datacenters_flavors
             mydb.new_row('datacenters_flavors', {'datacenter_id':vim_id, 'flavor_id':flavor_mano_id, 'vim_id': flavor_vim_id, 'created':flavor_created})
         elif flavor_db[0]["vim_id"]!=flavor_vim_id:
             #modify existing vim_id at datacenters_flavors
             mydb.update_rows('datacenters_flavors', UPDATE={'vim_id':flavor_vim_id}, WHERE={'datacenter_id':vim_id, 'flavor_id':flavor_mano_id})
             
-    return 1, flavor_vim_id if only_create_at_vim else flavor_mano_id
+    return flavor_vim_id if only_create_at_vim else flavor_mano_id
 
 def new_vnf(mydb, tenant_id, vnf_descriptor):
     global global_config
     
     # Step 1. Check the VNF descriptor
-    result, message = check_vnf_descriptor(vnf_descriptor)
-    if result < 0:
-        print "new_vnf error: %s" %message
-        return result, message
-
+    check_vnf_descriptor(vnf_descriptor)
     # Step 2. Check tenant exist
     if tenant_id != "any":
-        if not check_tenant(mydb, tenant_id): 
-            print 'nfvo.new_vnf() tenant %s not found' % tenant_id
-            return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
+        check_tenant(mydb, tenant_id) 
         if "tenant_id" in vnf_descriptor["vnf"]:
             if vnf_descriptor["vnf"]["tenant_id"] != tenant_id:
-                print "nfvo.new_vnf() tenant '%s' not found" % tenant_id
-                return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(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)
         else:
             vnf_descriptor['vnf']['tenant_id'] = tenant_id
         # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
-        result, vims = get_vim(mydb, tenant_id)
-        if result < 0:
-            print "nfvo.new_vnf() error. Datacenter not found"
-            return result, vims
+        vims = get_vim(mydb, tenant_id)
     else:
         vims={}
 
     # Step 4. Review the descriptor and add missing  fields
     #print vnf_descriptor
-    print "Refactoring VNF descriptor with fields: description, public (default: true)"
+    #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
     vnf_name = vnf_descriptor['vnf']['name']
     vnf_descriptor['vnf']['description'] = vnf_descriptor['vnf'].get("description", vnf_name)
     if "physical" in vnf_descriptor['vnf']:
@@ -487,26 +448,27 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
     internal_connections=vnf_descriptor['vnf'].get('internal_connections',[])
     for ic in internal_connections:
         if len(ic['elements'])>2 and ic['type']=='ptp':
-            return -HTTP_Bad_Request, "Mismatch 'type':'ptp' with %d elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'data'" %(len(ic), ic['name'])
+            raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic), ic['name']), 
+                                HTTP_Bad_Request)
         elif len(ic['elements'])==2 and ic['type']=='data':
-            return -HTTP_Bad_Request, "Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'ptp'" %(ic['name'])
-    
+            raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic['name']),
+                                 HTTP_Bad_Request)
+        
     # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM 
-    print 'BEGIN creation of VNF "%s"' % vnf_name
-    print "VNF %s: consisting of %d VNFC(s)" % (vnf_name,len(vnf_descriptor['vnf']['VNFC']))
+    logger.debug('BEGIN creation of VNF "%s"' % vnf_name)
+    logger.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name,len(vnf_descriptor['vnf']['VNFC'])))
     
     #For each VNFC, we add it to the VNFCDict and we  create a flavor.
     VNFCDict = {}     # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
     rollback_list = []    # It will contain the new images created in mano. It is used for rollback
-
     try:
-        print "Creating additional disk images and new flavors in the VIM for each VNFC"
+        logger.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
         for vnfc in vnf_descriptor['vnf']['VNFC']:
             VNFCitem={}
             VNFCitem["name"] = vnfc['name']
             VNFCitem["description"] = vnfc.get("description", 'VM %s of the VNF %s' %(vnfc['name'],vnf_name))
             
-            print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
+            #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
             
             myflavorDict = {}
             myflavorDict["name"] = vnfc['name']+"-flv"
@@ -544,21 +506,19 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
             #print myflavorDict
     
             # Step 6.2 New flavors are created in the VIM
-            res, flavor_id = create_or_use_flavor(mydb, vims, myflavorDict, rollback_list)
-            if res < 0:
-                return res, flavor_id + rollback(mydb, vims, rollback_list)[1]
+            flavor_id = create_or_use_flavor(mydb, vims, myflavorDict, rollback_list)
 
-            print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
+            #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
             VNFCitem["flavor_id"] = flavor_id
             VNFCDict[vnfc['name']] = VNFCitem
             
-        print "Creating new images in the VIM for each VNFC"
+        logger.debug("Creating new images in the VIM for each VNFC")
         # Step 6.3 New images are created in the VIM
         #For each VNFC, we must create the appropriate image.
         #This "for" loop might be integrated with the previous one 
         #In case this integration is made, the VNFCDict might become a VNFClist.
         for vnfc in vnf_descriptor['vnf']['VNFC']:
-            print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
+            #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
             image_dict={'location':vnfc['VNFC image'], 'name':vnfc['name']+"-img", 'description':VNFCDict[vnfc['name']]['description']}
             image_metadata_dict = vnfc.get('image metadata', None)
             image_metadata_str = None
@@ -566,110 +526,77 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
                 image_metadata_str = yaml.safe_dump(image_metadata_dict,default_flow_style=True,width=256)
             image_dict['metadata']=image_metadata_str
             #print "create_or_use_image", mydb, vims, image_dict, rollback_list
-            res, image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
-            if res < 0:
-                return res, image_id + rollback(mydb, vims, rollback_list)[1]
-            print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
+            image_id = create_or_use_image(mydb, vims, image_dict, rollback_list)
+            #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
             VNFCDict[vnfc['name']]["image_id"] = image_id
             VNFCDict[vnfc['name']]["image_path"] = vnfc['VNFC image']
 
-    except KeyError as e:
-        print "Error while creating a VNF. KeyError: " + str(e)
-        _, message = rollback(mydb, vims, rollback_list)
-        return -HTTP_Internal_Server_Error, "Error while creating a VNF. KeyError " + str(e) + "." + message
-        
-    # Step 7. Storing the VNF descriptor in the repository
-    if "descriptor" not in vnf_descriptor["vnf"]:
-        vnf_descriptor["vnf"]["descriptor"] = yaml.safe_dump(vnf_descriptor, indent=4, explicit_start=True, default_flow_style=False)
-
-    # Step 8. Adding the VNF to the NFVO DB
-    try:
-        result, vnf_id = mydb.new_vnf_as_a_whole(tenant_id,vnf_name,vnf_descriptor,VNFCDict)
-    except KeyError as e:
-        print "Error while creating a VNF. KeyError: " + str(e)
-        _, message = rollback(mydb, vims, rollback_list)
-        return -HTTP_Internal_Server_Error, "Error while creating a VNF. KeyError " + str(e) + "." + message
+            
+        # Step 7. Storing the VNF descriptor in the repository
+        if "descriptor" not in vnf_descriptor["vnf"]:
+            vnf_descriptor["vnf"]["descriptor"] = yaml.safe_dump(vnf_descriptor, indent=4, explicit_start=True, default_flow_style=False)
     
-    if result < 0:
+        # Step 8. Adding the VNF to the NFVO DB
+        vnf_id = mydb.new_vnf_as_a_whole(tenant_id,vnf_name,vnf_descriptor,VNFCDict)
+        return vnf_id
+    except (db_base_Exception, vimconn.vimconnException, KeyError) as e:
         _, message = rollback(mydb, vims, rollback_list)
-        return result, vnf_id + "." + message
-
-    return 200,vnf_id
-
+        if isinstance(e, db_base_Exception):
+            error_text = "Exception at database"
+        elif isinstance(e, KeyError):
+            error_text = "KeyError exception "
+            e.http_code = HTTP_Internal_Server_Error
+        else:
+            error_text = "Exception at VIM"
+        error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
+        #logger.error("start_scenario %s", error_text)
+        raise NfvoException(error_text, e.http_code)
+        
 def get_vnf_id(mydb, tenant_id, vnf_id):
     #check valid tenant_id
-    if tenant_id != "any" and not check_tenant(mydb, tenant_id): 
-        print 'nfvo.get_vnf_id() tenant %s not found' % tenant_id
-        return -HTTP_Not_Found, "Tenant '%s' not found" % tenant_id
+    check_tenant(mydb, tenant_id) 
     #obtain data
     where_or = {}
     if tenant_id != "any":
         where_or["tenant_id"] = tenant_id
         where_or["public"] = True
-    result, content = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND") 
-    if result < 0:
-        print "nfvo.get_vnf_id() error %d %s" % (result, content)
-        return (result, content)
-
+    vnf = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND") 
     
-    vnf_id=content["uuid"]
+    vnf_id=vnf["uuid"]
     filter_keys = ('uuid','name','description','public', "tenant_id", "created_at")
-    filtered_content = dict( (k,v) for k,v in content.iteritems() if k in filter_keys )
+    filtered_content = dict( (k,v) for k,v in vnf.iteritems() if k in filter_keys )
     #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
     data={'vnf' : filtered_content}
     #GET VM
-    result,content = mydb.get_table(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id',
+    content = mydb.get_rows(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id',
             SELECT=('vms.uuid as uuid','vms.name as name', 'vms.description as description'), 
             WHERE={'vnfs.uuid': vnf_id} )
-    if result < 0:
-        print "nfvo.get_vnf_id error %d %s" % (result, content)
-        return (result, content)
-    elif result==0:
-        print "nfvo.get_vnf_id vnf '%s' not found" % vnf_id
-        return (-HTTP_Not_Found, "vnf %s not found" % vnf_id)
+    if len(content)==0:
+        raise NfvoException("vnf '{}' not found".format(vnf_id), HTTP_Not_Found)
 
     data['vnf']['VNFC'] = content
     #GET NET
-    result,content = mydb.get_table(FROM='vnfs join nets on vnfs.uuid=nets.vnf_id', 
+    content = mydb.get_rows(FROM='vnfs join nets on vnfs.uuid=nets.vnf_id', 
                                     SELECT=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
                                     WHERE={'vnfs.uuid': vnf_id} )
-    if result < 0:
-        print "nfvo.get_vnf_id error %d %s" % (result, content)
-        return (result, content)
-    else:
-        if result==0:
-            data['vnf']['nets'] = []
-        else:
-            data['vnf']['nets'] = content
+    data['vnf']['nets'] = content
     #GET Interfaces
-    result,content = mydb.get_table(FROM='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_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'),\
                                     WHERE={'vnfs.uuid': vnf_id}, 
                                     WHERE_NOT={'interfaces.external_name': None} )
     #print content
-    if result < 0:
-        print "nfvo.get_vnf_id error %d %s" % (result, content)
-        return (result, content)
-    else:
-        if result==0:
-            data['vnf']['external-connections'] = []
-        else:
-            data['vnf']['external-connections'] = content
-    return 0, data
+    data['vnf']['external-connections'] = content
+    return data
 
 
 def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
     # Check tenant exist
     if tenant_id != "any":
-        if not check_tenant(mydb, tenant_id): 
-            print 'nfvo.delete_vnf() tenant %s not found' % tenant_id
-            return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
+        check_tenant(mydb, tenant_id)
         # Get the URL of the VIM from the nfvo_tenant and the datacenter
-        result, vims = get_vim(mydb, tenant_id)
-        if result < 0:
-            print "nfvo.delete_vnf() error. Datacenter not found"
-            return result, vims
+        vims = get_vim(mydb, tenant_id)
     else:
         vims={}
 
@@ -678,48 +605,33 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
     if tenant_id != "any":
         where_or["tenant_id"] = tenant_id
         where_or["public"] = True
-    result, content = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND") 
-    if result < 0: 
-        return result, content
-    vnf_id = content["uuid"]
+    vnf = mydb.get_table_by_uuid_name('vnfs', vnf_id, "VNF", WHERE_OR=where_or, WHERE_AND_OR="AND") 
+    vnf_id = vnf["uuid"]
     
     # "Getting the list of flavors and tenants of the VNF"
-    result,flavorList = get_flavorlist(mydb, vnf_id) 
-    if result < 0:
-        print flavorList
-    elif result==0:
-        print "delete_vnf error. No flavors found for the VNF id '%s'" % vnf_id
+    flavorList = get_flavorlist(mydb, vnf_id) 
+    if len(flavorList)==0:
+        logger.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id)
     
-    result,imageList = get_imagelist(mydb, vnf_id)
-    print "imageList", imageList
-    if result < 0:
-        print imageList
-    elif result==0:
-        print "delete_vnf error. No images found for the VNF id '%s'" % vnf_id
+    imageList = get_imagelist(mydb, vnf_id)
+    if len(imageList)==0:
+        logger.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id)
     
-    result, content = mydb.delete_row('vnfs', vnf_id, tenant_id)
-    if result == 0:
-        return -HTTP_Not_Found, content
-    elif result >0:
-        print content
-    else:
-        print "delete_vnf error",result, content
-        return result, content
+    deleted = mydb.delete_row_by_id('vnfs', vnf_id)
+    if deleted == 0:
+        raise NfvoException("vnf '{}' not found".format(vnf_id), HTTP_Not_Found)
     
     undeletedItems = []
     for flavor in flavorList:
         #check if flavor is used by other vnf
-        r,c = mydb.get_table(FROM='vms', WHERE={'flavor_id':flavor} )
-        if r < 0:
-            print 'delete_vnf_error. Not possible to delete VIM flavor "%s". %s' % (flavor,c)
-            undeletedItems.append("flavor "+ flavor["flavor_id"])
-        elif r > 0:
-            print 'Flavor %s not deleted because it is being used by another VNF %s' %(flavor,str(c))
-            continue
-        #flavor not used, must be deleted
-        #delelte at VIM
-        r,c = mydb.get_table(FROM='datacenters_flavors', WHERE={'flavor_id':flavor})
-        if r>0:
+        try:
+            c = mydb.get_rows(FROM='vms', WHERE={'flavor_id':flavor} )
+            if len(c) > 0:
+                logger.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor)
+                continue
+            #flavor not used, must be deleted
+            #delelte at VIM
+            c = mydb.get_rows(FROM='datacenters_flavors', WHERE={'flavor_id':flavor})
             for flavor_vim in c:
                 if flavor_vim["datacenter_id"] not in vims:
                     continue
@@ -734,24 +646,23 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
                     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
-        result, content = mydb.delete_row('flavors', flavor)
-        if result <0:
+            #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))
             undeletedItems.append("flavor %s" % flavor)
+
         
     for image in imageList:
-        #check if image is used by other vnf
-        r,c = mydb.get_table(FROM='vms', WHERE={'image_id':image} )
-        if r < 0:
-            print 'delete_vnf_error. Not possible to delete VIM image "%s". %s' % (image,c)
-            undeletedItems.append("image "+ image["image_id"])
-        elif r > 0:
-            print 'Image %s not deleted because it is being used by another VNF %s' %(image,str(c))
-            continue
-        #image not used, must be deleted
-        #delelte at VIM
-        r,c = mydb.get_table(FROM='datacenters_images', WHERE={'image_id':image})
-        if r>0:
+        try:
+            #check if image is used by other vnf
+            c = mydb.get_rows(FROM='vms', WHERE={'image_id':image} )
+            if len(c) > 0:
+                logger.debug("Image '%s' not deleted because it is being used by another VNF", image)
+                continue
+            #image not used, must be deleted
+            #delelte at VIM
+            c = mydb.get_rows(FROM='datacenters_images', WHERE={'image_id':image})
             for image_vim in c:
                 if image_vim["datacenter_id"] not in vims:
                     continue
@@ -766,15 +677,15 @@ def delete_vnf(mydb,tenant_id,vnf_id,datacenter=None,vim_tenant=None):
                     logger.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
                             image_vim["vim_id"], image_vim["datacenter_id"], type(e).__name__, str(e))
                     undeletedItems.append("image {} from VIM {}".format(image_vim["vim_id"], image_vim["datacenter_id"] ))
-        #delete image from Database, using table images and with cascade foreign key also at datacenters_images
-        result, content = mydb.delete_row('images', image)
-        if result <0:
+            #delete image from Database, using table images and with cascade foreign key also at datacenters_images
+            mydb.delete_row_by_id('images', image)
+        except db_base_Exception as e:
+            logger.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image, str(e))
             undeletedItems.append("image %s" % image)
 
-    if undeletedItems: 
-        return 200, "delete_vnf error. Undeleted: %s" %(undeletedItems)
-    
-    return 200,vnf_id
+    return vnf_id + " " + vnf["name"]
+    #if undeletedItems: 
+    #    return "delete_vnf. Undeleted: %s" %(undeletedItems)
 
 def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
     result, vims = get_vim(mydb, nfvo_tenant_id, None, datacenter_name)
@@ -790,37 +701,39 @@ def get_hosts_info(mydb, nfvo_tenant_id, datacenter_name=None):
     return result, topology
 
 def get_hosts(mydb, nfvo_tenant_id):
-    result, vims = get_vim(mydb, nfvo_tenant_id)
-    if result < 0:
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "No datacenter found"
+    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)
+    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)
     myvim = vims.values()[0]
-    result,hosts =  myvim.get_hosts()
-    if result < 0:
-        return result, hosts
-    print '==================='
-    print 'hosts '+ yaml.safe_dump(hosts, indent=4, default_flow_style=False)
-
-    datacenter = {'Datacenters': [ {'name':myvim['name'],'servers':[]} ] }
-    for host in hosts:
-        server={'name':host['name'], 'vms':[]}
-        for vm in host['instances']:
-            #get internal name and model
-            r,c = mydb.get_table(SELECT=('name',), FROM='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
-                WHERE={'vim_vm_id':vm['id']} )
-            if r==0:
-                print "nfvo.get_hosts virtual machine at VIM (%s) not found at tidnfvo" % vm['id']
-                continue
-            if r<0:
-                print "nfvo.get_hosts virtual machine at VIM (%s) error %d %s" % (vm['id'], r, c)
-                continue
-            server['vms'].append( {'name':vm['name'] , 'model':c[0]['name']} )
-        datacenter['Datacenters'][0]['servers'].append(server)
-    #return -400, "en construccion"
+    try:
+        hosts =  myvim.get_hosts()
+        logger.debug('VIM hosts response: '+ yaml.safe_dump(hosts, indent=4, default_flow_style=False))
+
+        datacenter = {'Datacenters': [ {'name':myvim['name'],'servers':[]} ] }
+        for host in hosts:
+            server={'name':host['name'], 'vms':[]}
+            for vm in host['instances']:
+                #get internal name and model
+                try: 
+                    c = mydb.get_rows(SELECT=('name',), FROM='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
+                        WHERE={'vim_vm_id':vm['id']} )
+                    if len(c) == 0:
+                        logger.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm['id']))
+                        continue
+                    server['vms'].append( {'name':vm['name'] , 'model':c[0]['name']} )
+                        
+                except db_base_Exception as e:
+                    logger.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm['id'], str(e)))
+            datacenter['Datacenters'][0]['servers'].append(server)
+        #return -400, "en construccion"
     
-    #print 'datacenters '+ json.dumps(datacenter, indent=4)
-    return result, datacenter
+        #print 'datacenters '+ json.dumps(datacenter, indent=4)
+        return datacenter
+    except vimconn.vimconnException as e:
+        raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e)), e.http_code)
 
 def new_scenario(mydb, tenant_id, topo):
 
@@ -829,13 +742,11 @@ def new_scenario(mydb, tenant_id, topo):
 #        return result, vims
 #1: parse input
     if tenant_id != "any":
-        if not check_tenant(mydb, tenant_id): 
-            print 'nfvo.new_scenario() tenant %s not found' % tenant_id
-            return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
+        check_tenant(mydb, tenant_id) 
         if "tenant_id" in topo:
             if topo["tenant_id"] != tenant_id:
-                print "nfvo.new_scenario() tenant '%s' not found" % tenant_id
-                return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(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)
     else:
         tenant_id=None
 
@@ -867,25 +778,19 @@ def new_scenario(mydb, tenant_id, topo):
             error_text += " 'VNF model' " +  vnf['VNF model']
             WHERE_['name'] = vnf['VNF model']
         if len(WHERE_) == 0:
-            return -HTTP_Bad_Request, "needed a 'vnf_id' or 'VNF model' at " + error_pos
-        r,vnf_db = mydb.get_table(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
-        if r<0:
-            print "nfvo.new_scenario Error getting vnfs",r,vnf_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
-        elif r>1:
-            print "nfvo.new_scenario Error more than one" + error_text + " are present at database"
-            return -HTTP_Bad_Request, "more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'"
+            raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos, HTTP_Bad_Request)
+        
+        vnf_db = mydb.get_rows(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
+        if len(vnf_db)==0:
+            raise NfvoException("unknown" + error_text + " at " + error_pos, HTTP_Not_Found)
+        elif len(vnf_db)>1:
+            raise NfvoException("more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", HTTP_Conflict)
         vnf['uuid']=vnf_db[0]['uuid']
         vnf['description']=vnf_db[0]['description']
         #get external interfaces
-        r,ext_ifaces = mydb.get_table(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'), 
+        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} )
-        if r<0:
-            print "nfvo.new_scenario Error getting external interfaces of vnfs",r,ext_ifaces
-            return -HTTP_Internal_Server_Error, "Error getting external interfaces of vnfs: " + ext_ifaces
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
 
@@ -904,7 +809,7 @@ def new_scenario(mydb, tenant_id, topo):
         con_type = conections[k].get("type", "link")
         if con_type != "link":
             if k in other_nets:
-                return -HTTP_Bad_Request, "format error. Reapeted network name at 'topology':'connections':'%s'" % (str(k))
+                raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k)), HTTP_Bad_Request)
             other_nets[k] = {'external': False}
             if conections[k].get("graph"):
                 other_nets[k]["graph"] =   conections[k]["graph"]
@@ -926,9 +831,11 @@ def new_scenario(mydb, tenant_id, topo):
     #check valid VNF and iface names
         for iface in ifaces_list:
             if iface[0] not in vnfs and iface[0] not in other_nets :
-                return -HTTP_Bad_Request, "format error. Invalid VNF name at 'topology':'connections':'%s':'nodes':'%s'" % (str(k), iface[0])
+                raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
+                                                                                        str(k), iface[0]), HTTP_Not_Found)
             if iface[0] in vnfs and iface[1] not in vnfs[ iface[0] ]['ifaces']:
-                return -HTTP_Bad_Request, "format error. Invalid interface name at 'topology':'connections':'%s':'nodes':'%s':'%s'" % (str(k), iface[0], iface[1])
+                raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
+                                                                                        str(k), iface[0], iface[1]), HTTP_Not_Found)
 
 #1.5 unify connections from the pair list to a consolidated list
     index=0
@@ -964,13 +871,13 @@ def new_scenario(mydb, tenant_id, topo):
             if 'name' not in net:
                 net['name']=k
             if 'model' not in net:
-                return -HTTP_Bad_Request, "needed a 'model' at " + error_pos
+                raise NfvoException("needed a 'model' at " + error_pos, HTTP_Bad_Request)
             if net['model']=='bridge_net':
                 net['type']='bridge';
             elif net['model']=='dataplane_net':
                 net['type']='data';
             else:
-                return -HTTP_Bad_Request, "unknown 'model' '"+ net['model'] +"' at " + error_pos
+                raise NfvoException("unknown 'model' '"+ net['model'] +"' at " + error_pos, HTTP_Not_Found)
         else: #external
 #IF we do not want to check that external network exist at datacenter
             pass
@@ -1010,8 +917,8 @@ def new_scenario(mydb, tenant_id, topo):
                 if con[index][0]==net_key:
                     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
-                        return -HTTP_Bad_Request, error_text
+                        #print "nfvo.new_scenario " + error_text
+                        raise NfvoException(error_text, HTTP_Bad_Request)
                     else:
                         other_net_index = index
                         net_target = net_key
@@ -1055,8 +962,8 @@ def new_scenario(mydb, tenant_id, topo):
                         net_type_data = True
                 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
-                    return -HTTP_Bad_Request, error_text
+                    #print "nfvo.new_scenario " + error_text
+                    raise NfvoException(error_text, HTTP_Bad_Request)
                 elif net_type_bridge:
                     type_='bridge'
                 else:
@@ -1065,16 +972,16 @@ def new_scenario(mydb, tenant_id, topo):
                 net_nb+=1
         except Exception:
             error_text = "Error connection node %s : %s does not match any VNF or interface" % (iface[0], iface[1])
-            print "nfvo.new_scenario " + error_text
+            #print "nfvo.new_scenario " + error_text
             #raise e
-            return -HTTP_Bad_Request, error_text
+            raise NfvoException(error_text, HTTP_Bad_Request)
 
 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
     #1.8.1 obtain management net 
-    r,mgmt_net = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
+    mgmt_net = mydb.get_rows(SELECT=('uuid','name','description','type','shared'),
         FROM='datacenter_nets', WHERE={'name':'mgmt'} )
     #1.8.2 check all interfaces from all vnfs 
-    if r>0:
+    if len(mgmt_net)>0:
         add_mgmt_net = False
         for vnf in vnfs.values():
             for iface in vnf['ifaces'].values():
@@ -1088,31 +995,30 @@ def new_scenario(mydb, tenant_id, topo):
             net_list['mgmt']['graph']={'visible':False}
 
     net_list.update(other_nets)
-    print
-    print 'net_list', net_list
-    print
-    print 'vnfs', vnfs
-    print
+    #print
+    #print 'net_list', net_list
+    #print
+    #print 'vnfs', vnfs
+    #print
 
 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
-    r,c = mydb.new_scenario( { 'vnfs':vnfs, 'nets':net_list,
+    c = mydb.new_scenario( { 'vnfs':vnfs, 'nets':net_list,
         'tenant_id':tenant_id, 'name':topo['name'],
          'description':topo.get('description',topo['name']),
          'public': topo.get('public', False)
          })
     
-    return r,c
+    return c
 
 def new_scenario_v02(mydb, tenant_id, scenario_dict):
     scenario = scenario_dict["scenario"]
     if tenant_id != "any":
-        if not check_tenant(mydb, tenant_id): 
-            print 'nfvo.new_scenario_v02() tenant %s not found' % tenant_id
-            return -HTTP_Not_Found, 'Tenant %s not found' % tenant_id
+        check_tenant(mydb, tenant_id) 
         if "tenant_id" in scenario:
             if scenario["tenant_id"] != tenant_id:
                 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
-                return -HTTP_Unauthorized, "VNF can not have a different tenant owner '%s', must be '%s'" %(scenario["tenant_id"], tenant_id)
+                raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
+                                                    scenario["tenant_id"], tenant_id), HTTP_Unauthorized)
     else:
         tenant_id=None
 
@@ -1128,26 +1034,19 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
             error_text += " 'vnf_name' " +  vnf['vnf_name']
             WHERE_['name'] = vnf['vnf_name']
         if len(WHERE_) == 0:
-            return -HTTP_Bad_Request, "needed a 'vnf_id' or 'VNF model' at " + error_pos
-        r,vnf_db = mydb.get_table(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
-        if r<0:
-            print "nfvo.new_scenario Error getting vnfs",r,vnf_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
-        elif r>1:
-            print "nfvo.new_scenario Error more than one" + error_text + " are present at database"
-            return -HTTP_Bad_Request, "more than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'"
+            raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos, HTTP_Bad_Request)
+        vnf_db = mydb.get_rows(SELECT=('uuid','name','description'), FROM='vnfs', WHERE=WHERE_)
+        if len(vnf_db)==0:
+            raise NfvoException("Unknown" + error_text + " at " + error_pos, HTTP_Not_Found)
+        elif len(vnf_db)>1:
+            raise NfvoException("More than one" + error_text + " at " + error_pos + " Concrete with 'vnf_id'", HTTP_Conflict)
         vnf['uuid']=vnf_db[0]['uuid']
         vnf['description']=vnf_db[0]['description']
         vnf['ifaces'] = {}
         #get external interfaces
-        r,ext_ifaces = mydb.get_table(SELECT=('external_name as name','i.uuid as iface_uuid', 'i.type as type'), 
+        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} )
-        if r<0:
-            print "nfvo.new_scenario Error getting external interfaces of vnfs",r,ext_ifaces
-            return -HTTP_Internal_Server_Error, "Error getting external interfaces of vnfs: " + ext_ifaces
         for ext_iface in ext_ifaces:
             vnf['ifaces'][ ext_iface['name'] ] = {'uuid':ext_iface['iface_uuid'], 'type':ext_iface['type']}
 
@@ -1159,17 +1058,17 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
             for vnf,iface in iface_dict.iteritems():
                 if vnf not in scenario["vnfs"]:
                     error_text = "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name, vnf)
-                    print "nfvo.new_scenario_v02 " + error_text
-                    return -HTTP_Bad_Request, error_text
+                    #print "nfvo.new_scenario_v02 " + error_text
+                    raise NfvoException(error_text, HTTP_Not_Found)
                 if iface not in scenario["vnfs"][vnf]['ifaces']:
                     error_text = "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name, iface)
-                    print "nfvo.new_scenario_v02 " + error_text
-                    return -HTTP_Bad_Request, error_text
+                    #print "nfvo.new_scenario_v02 " + error_text
+                    raise NfvoException(error_text, HTTP_Bad_Request)
                 if "net_key" in scenario["vnfs"][vnf]['ifaces'][iface]:
                     error_text = "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
                                     % (net_name, iface,scenario["vnfs"][vnf]['ifaces'][iface]['net_key'])
-                    print "nfvo.new_scenario_v02 " + error_text
-                    return -HTTP_Bad_Request, error_text
+                    #print "nfvo.new_scenario_v02 " + error_text
+                    raise NfvoException(error_text, HTTP_Bad_Request)
                 scenario["vnfs"][vnf]['ifaces'][ iface ]['net_key'] = net_name
                 iface_type = scenario["vnfs"][vnf]['ifaces'][iface]['type']
                 if iface_type=='mgmt' or iface_type=='bridge':
@@ -1178,8 +1077,8 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
                     net_type_data = True
         if net_type_bridge and net_type_data:
             error_text = "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name)
-            print "nfvo.new_scenario " + error_text
-            return -HTTP_Bad_Request, error_text
+            #print "nfvo.new_scenario " + error_text
+            raise NfvoException(error_text, HTTP_Bad_Request)
         elif net_type_bridge:
             type_='bridge'
         else:
@@ -1191,15 +1090,14 @@ def new_scenario_v02(mydb, tenant_id, scenario_dict):
 #3: insert at database
     scenario["nets"] = scenario["networks"]
     scenario['tenant_id'] = tenant_id
-    r,c = mydb.new_scenario( scenario)
-    
-    return r,c
+    scenario_id = mydb.new_scenario( scenario)
+    return scenario_id
 
 def edit_scenario(mydb, tenant_id, scenario_id, data):
     data["uuid"] = scenario_id
     data["tenant_id"] = tenant_id
-    r,c = mydb.edit_scenario( data )
-    return r,c
+    c = mydb.edit_scenario( data )
+    return c
 
 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"
@@ -1210,15 +1108,12 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
             datacenter_id = datacenter
         else:
             datacenter_name = datacenter
-    result, vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant)
-    if result < 0:
-        logger.error("start_scenario error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result > 1:
-        logger.error("start_scenario error. Several datacenters available, you must concrete")
-        return -HTTP_Bad_Request, "Several datacenters available, you must concrete"
+    vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found)
+    elif len(vims)>1:
+        #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
+        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
     myvim = vims.values()[0]
     myvim_tenant = myvim['tenant_id']
     datacenter_id = myvim['id']
@@ -1227,14 +1122,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
     rollbackList=[]
     try:
         #print "Checking that the scenario_id exists and getting the scenario dictionary"
-        result, scenarioDict = mydb.get_scenario(scenario_id, tenant_id, datacenter_id)
-        if result < 0:
-            logger.error("start_scenario error. Error interacting with NFVO DB")
-            return result, scenarioDict
-        elif result == 0:
-            logger.error("start_scenario error. Scenario not found")
-            return result, scenarioDict
-    
+        scenarioDict = mydb.get_scenario(scenario_id, tenant_id, datacenter_id)
         scenarioDict['datacenter_tenant_id'] = datacenter_tenant_id
         scenarioDict['datacenter_id'] = datacenter_id
         #print '================scenarioDict======================='
@@ -1260,7 +1148,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
             myNetDict["tenant_id"] = myvim_tenant
             #TODO:
             #We should use the dictionary as input parameter for new_network
-            print myNetDict
+            #print myNetDict
             if not sce_net["external"]:
                 network_id = myvim.new_network(myNetName, myNetType)
                 #print "New VIM network created for scenario %s. Network id:  %s" % (scenarioDict['name'],network_id)
@@ -1272,7 +1160,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)
-                    return -HTTP_Bad_Request, error_text
+                    raise NfvoException(error_text, HTTP_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']
         
@@ -1292,7 +1180,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 #print myNetDict
                 #TODO:
                 #We should use the dictionary as input parameter for new_network
-                result, network_id = myvim.new_network(myNetName, myNetType)
+                network_id = myvim.new_network(myNetName, myNetType)
                 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
                 net['vim_id'] = network_id
                 if sce_vnf['uuid'] not in auxNetDict:
@@ -1320,27 +1208,15 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
                 
                 #create image at vim in case it not exist
-                res, image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
-                if res<0:
-                    logger.error("start_scenario error getting image %s", str(image_dict))
-                    return res, image_dict
-                res, image_id = create_or_use_image(mydb, vims, image_dict, [], True)                
-                if res < 0:
-                    logger.error("start_scenario error adding image to VIM: %s", str(image_dict))
-                    return res, image_id
+                image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
+                image_id = create_or_use_image(mydb, vims, image_dict, [], True)                
                 vm['vim_image_id'] = image_id
                     
                 #create flavor at vim in case it not exist
-                res, flavor_dict = mydb.get_table_by_uuid_name("flavors", vm['flavor_id'])
-                if res<0:
-                    logger.error("start_scenario error getting flavor: %s", str(flavor_dict))
-                    return res, flavor_dict
+                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'])
-                res, flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, [], True)                
-                if res < 0:
-                    logger.error("start_scenario error adding flavor to VIM: ", str(flavor_dict))
-                    return res, flavor_id
+                flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, [], True)                
                 vm['vim_flavor_id'] = flavor_id
     
                 
@@ -1372,10 +1248,10 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                         #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:
-                            return -HTTP_Conflict, e_text + "After database migration some information is not available. \
-                                    Try to delete and create the scenarios and VNFs again"
+                            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:
-                            return -HTTP_Internal_Server_Error, e_text
+                            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:
@@ -1385,8 +1261,8 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                     netDict['name'] = iface['internal_name']
                     if iface['net_id'] is None:
                         for vnf_iface in sce_vnf["interfaces"]:
-                            print iface
-                            print vnf_iface
+                            #print iface
+                            #print vnf_iface
                             if vnf_iface['interface_id']==iface['uuid']:
                                 netDict['net_id'] = auxNetDict['scenario'][ vnf_iface['sce_net_id'] ]
                                 break
@@ -1417,20 +1293,18 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
         logger.debug("start scenario Deployment done")
         #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
         #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
-        result,c = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_scenario_name, instance_scenario_description, scenarioDict)
-        if result <0:
-            error_text = c + "." 
-            _, message = rollback(mydb, vims, rollbackList)
-            error_text += message
-            print "start_scenario: " + error_text
-            return result, error_text
-            
-        return mydb.get_instance_scenario(c)
-    except vimconn.vimconnException as e:
+        instance_id = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_scenario_name, instance_scenario_description, scenarioDict)
+        return mydb.get_instance_scenario(instance_id)
+    
+    except (db_base_Exception, vimconn.vimconnException) as e:
         _, message = rollback(mydb, vims, rollbackList)
-        error_text = "VIM exception {} {}. {}".format(type(e).__name__, str(e), message)
-        logger.error("start_scenario %s", error_text)
-        return -e.http_code, error_text
+        if isinstance(e, db_base_Exception):
+            error_text = "Exception at database"
+        else:
+            error_text = "Exception at VIM"
+        error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
+        #logger.error("start_scenario %s", error_text)
+        raise NfvoException(error_text, e.http_code)
 
 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"
@@ -1443,15 +1317,12 @@ def create_instance(mydb, tenant_id, instance_dict):
             datacenter_id = datacenter
         else:
             datacenter_name = datacenter
-    result, vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant=None)
-    if result < 0:
-        logger.error("create_instance error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result > 1:
-        logger.error("create_instance error. Several datacenters available, you must concrete")
-        return -HTTP_Bad_Request, "Several datacenters available, you must concrete"
+    vims = get_vim(mydb, tenant_id, datacenter_id, datacenter_name, vim_tenant=None)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_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)
     myvim = vims.values()[0]
     #myvim_tenant = myvim['tenant_id']
     datacenter_id = myvim['id']
@@ -1460,17 +1331,10 @@ def create_instance(mydb, tenant_id, instance_dict):
     rollbackList=[]
     
     #print "Checking that the scenario exists and getting the scenario dictionary"
-    result, scenarioDict = mydb.get_scenario(scenario, tenant_id, datacenter_id)
-    if result < 0:
-        logger.error("create_instance error. Error interacting with NFVO DB")
-        return result, scenarioDict
-    elif result == 0:
-        logger.error("create_instance error. Scenario not found")
-        return result, scenarioDict
-
+    scenarioDict = mydb.get_scenario(scenario, tenant_id, datacenter_id)
     scenarioDict['datacenter_tenant_id'] = datacenter_tenant_id
     scenarioDict['datacenter_id'] = datacenter_id
-    
+   
     auxNetDict = {}   #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
     auxNetDict['scenario'] = {}
     
@@ -1595,23 +1459,15 @@ def create_instance(mydb, tenant_id, instance_dict):
 #                    myVMDict['start'] = "no"
                 myVMDict['name'] = myVMDict['name'][0:255] #limit name length
                 #create image at vim in case it not exist
-                res, image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
-                if res<0:
-                    raise NfvoException("Error getting VIM image "+ image_dict, -result)
-                res, image_id = create_or_use_image(mydb, vims, image_dict, [], True)                
-                if res < 0:
-                    raise NfvoException("Error adding image to VIM " + image_dict, -result)
+                image_dict = mydb.get_table_by_uuid_name("images", vm['image_id'])
+                image_id = create_or_use_image(mydb, vims, image_dict, [], True)                
                 vm['vim_image_id'] = image_id
                     
                 #create flavor at vim in case it not exist
-                res, flavor_dict = mydb.get_table_by_uuid_name("flavors", vm['flavor_id'])
-                if res<0:
-                    raise NfvoException("Error getting VIM flavor "+ flavor_dict, -result)
+                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'])
-                res, flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, [], True)                
-                if res < 0:
-                    raise NfvoException("Error adding flavor to VIM" + flavor_dict, -result)
+                flavor_id = create_or_use_flavor(mydb, vims, flavor_dict, rollbackList, True)                
                 vm['vim_flavor_id'] = flavor_id
                 
                 myVMDict['imageRef'] = vm['vim_image_id']
@@ -1656,8 +1512,8 @@ def create_instance(mydb, tenant_id, instance_dict):
                     netDict['name'] = iface['internal_name']
                     if iface['net_id'] is None:
                         for vnf_iface in sce_vnf["interfaces"]:
-                            print iface
-                            print vnf_iface
+                            #print iface
+                            #print vnf_iface
                             if vnf_iface['interface_id']==iface['uuid']:
                                 netDict['net_id'] = auxNetDict['scenario'][ vnf_iface['sce_net_id'] ]
                                 break
@@ -1686,51 +1542,42 @@ def create_instance(mydb, tenant_id, instance_dict):
         logger.debug("create_instance Deployment done")
         #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
         #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
-        result,c = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_name, instance_description, scenarioDict)
-        if result <0:
-            raise NfvoException(c, -result)
-            
-        return mydb.get_instance_scenario(c)
-    except NfvoException as e:
-        _, message = rollback(mydb, vims, rollbackList)
-        error_text = "{} {}. {}".format(type(e).__name__, str(e), message)
-        logger.error("create_instance: %s", error_text)
-        return -e.http_code, error_text
-    except vimconn.vimconnException as e:
-        _, message = rollback(mydb, vims, rollbackList)
-        error_text = "VIM exception {} {}. {}".format(type(e).__name__, str(e), message)
-        logger.error("create_instance: %s", error_text)
-        return -e.http_code, error_text        
+        instance_id = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_name, instance_description, scenarioDict)
+        return mydb.get_instance_scenario(instance_id)
+    except (NfvoException, vimconn.vimconnException,db_base_Exception)  as e:
+        message = rollback(mydb, vims, rollbackList)
+        if isinstance(e, db_base_Exception):
+            error_text = "database Exception"
+        elif isinstance(e, vimconn.vimconnException):
+            error_text = "VIM Exception"
+        else:
+            error_text = "Exception"
+        error_text += " {} {}. {}".format(type(e).__name__, str(e), message)
+        #logger.error("create_instance: %s", error_text)
+        raise NfvoException(error_text, e.http_code)
     
 def delete_instance(mydb, tenant_id, instance_id):
     #print "Checking that the instance_id exists and getting the instance dictionary"
-    result, instanceDict = mydb.get_instance_scenario(instance_id, tenant_id)
-    if result < 0:
-        logger.error("nfvo.delete_instance() error. Error getting info from database")
-        return result, instanceDict
-    elif result == 0:
-        logger.error("delete_instance error. Instance not found")
-        return result, instanceDict
+    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"
-    result, vims = get_vim(mydb, tenant_id, instanceDict['datacenter_id'])
-    if result < 0:
-        logger.error("nfvo.delete_instance() error. Datacenter error %s %s", result, vims)
-        return result, vims
-    elif result == 0:
-        logger.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
+    try: 
+        vims = get_vim(mydb, tenant_id, instanceDict['datacenter_id'])
+        if len(vims) == 0:
+            logger.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
+            myvim = None
+        else:
+            myvim = vims.values()[0]
+    except NfvoException as e:
+        logger.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e))
         myvim = None
-    else:
-        myvim = vims.values()[0]
     
     
     #1. Delete from Database
 
-    #result,c = mydb.delete_row('instance_scenarios', instance_id, nfvo_tenant)
-    result,c = mydb.delete_instance_scenario(instance_id, tenant_id)
-    if result<0:
-        return result, c
+    #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
+    message = mydb.delete_instance_scenario(instance_id, tenant_id)
 
     #2. delete from VIM
     if not myvim:
@@ -1773,9 +1620,9 @@ def delete_instance(mydb, tenant_id, instance_id):
             logger.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
                 e.http_code, net['uuid'], net['vim_net_id'], sce_vnf['vnf_id'], str(e))
     if len(error_msg)>0:
-        return 1, 'instance ' + instance_id + ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
+        return 'instance ' + message + ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
     else:
-        return 1, 'instance ' + instance_id + ' deleted'
+        return 'instance ' + message + ' deleted'
 
 def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenant=None):
     '''Refreshes a scenario instance. It modifies instanceDict'''
@@ -1788,12 +1635,9 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
     #print json.dumps(instanceDict, indent=4)
     
     #print "Getting the VIM URL and the VIM tenant_id"
-    result, vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
-    if result < 0:
-        logger.error("nfvo.refresh_instance() error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(instanceDict['datacenter_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)
     myvim = vims.values()[0]
      
     # 1. Getting VIM vm and net list
@@ -1833,13 +1677,13 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
                     vm['error_msg'] = vm_dict[vm_id].get('error_msg')
                     vm['vim_info']  = vm_dict[vm_id].get('vim_info')
                     # 2.1. Update in openmano DB the VMs whose status changed
-                    result2, _ = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
-                    if result2<0:
-                        logger.error("nfvo.refresh_instance error database update: %s", result2)
-                    else:
+                    try: 
+                        updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
                         vms_notupdated.remove(vm["uuid"])
-                        if result2>0:
+                        if updates>0:
                             vms_updated.append(vm["uuid"])  
+                    except db_base_Exception as e:
+                        logger.error("nfvo.refresh_instance error database update: %s", str(e))
                 # 2.2. Update in openmano DB the interface VMs
                 for interface in interfaces:
                     #translate from vim_net_id to instance_net_id
@@ -1851,8 +1695,9 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
                     if not network_id:
                         continue
                     del interface["vim_net_id"]
-                    result2, _ = mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
-                    if result2<0:
+                    try: 
+                        mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
+                    except db_base_Exception as e:
                         logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)        
         
         # 3. Getting the status of all nets
@@ -1867,16 +1712,16 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
                 net['error_msg'] = net_dict[net_id].get('error_msg')
                 net['vim_info']  = net_dict[net_id].get('vim_info')
                 # 5.1. Update in openmano DB the nets whose status changed
-                result2, _ = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
-                if result2<0:
-                    logger.error("nfvo.refresh_instance error database update: %s", result2)
-                else:
+                try:
+                    updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
                     nets_notupdated.remove(net["uuid"])
-                    if result2>0:
+                    if updated>0:
                         nets_updated.append(net["uuid"])  
+                except db_base_Exception as e:
+                    logger.error("nfvo.refresh_instance error database update: %s", str(e))
     except vimconn.vimconnException as e:
-        logger.error("VIM exception %s %s", type(e).__name__, str(e))
-        return -e.http_code, str(e)
+        #logger.error("VIM exception %s %s", type(e).__name__, str(e))
+        raise NfvoException(str(e), e.http_code)
 
     # Returns appropriate output
     #print "nfvo.refresh_instance finishes"
@@ -1891,22 +1736,13 @@ def refresh_instance(mydb, nfvo_tenant, instanceDict, datacenter=None, vim_tenan
 
 def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
     #print "Checking that the instance_id exists and getting the instance dictionary"
-    result, instanceDict = mydb.get_instance_scenario(instance_id, nfvo_tenant)
-    if result < 0:
-        logger.error("nfvo.instance_action() error. Error getting info from database")
-        return result, instanceDict
-    elif result == 0:
-        logger.error("instance_action error. Instance not found")
-        return -HTTP_Not_Found, "instance {} not found".format(instance_id)
+    instanceDict = mydb.get_instance_scenario(instance_id, nfvo_tenant)
     #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
 
     #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
-    result, vims = get_vim(mydb, nfvo_tenant, instanceDict['datacenter_id'])
-    if result < 0:
-        logger.error("nfvo.instance_action() error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '{}' not found".format(str(instanceDict['datacenter_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)
     myvim = vims.values()[0]
     
 
@@ -1933,17 +1769,17 @@ def instance_action(mydb,nfvo_tenant,instance_id, action_dict):
                         vm_error+=1
                         continue
                     #print "console data", data
-                    r2, console_thread = create_or_use_console_proxy_thread(data["server"], data["port"])
-                    if r2<0:
-                        vm_result[ vm['uuid'] ] = {"vim_result": -r2, "name":vm['name'], "description": console_thread}
-                    else:
-                        vm_result[ vm['uuid'] ] = {"vim_result": result,
+                    try: 
+                        console_thread = create_or_use_console_proxy_thread(data["server"], data["port"])
+                        vm_result[ vm['uuid'] ] = {"vim_result": 200,
                                                    "description": "%s//%s:%d/%s" %(data["protocol"], console_thread.host, console_thread.port, data["suffix"]),
                                                    "name":vm['name']
                                                 }
                         vm_ok +=1
+                    except NfvoException as e:
+                        vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
                 else:
-                    vm_result[ vm['uuid'] ] = {"vim_result": result, "description": "ok", "name":vm['name']}
+                    vm_result[ vm['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm['name']}
                     vm_ok +=1
             except vimconn.vimconnException as e:
                 vm_result[ vm['uuid'] ] = {"vim_result": e.http_code, "name":vm['name'], "description": str(e)}
@@ -1959,7 +1795,7 @@ def create_or_use_console_proxy_thread(console_server, console_port):
     console_thread_key = console_server + ":" + str(console_port)
     if console_thread_key in global_config["console_thread"]:
         #global_config["console_thread"][console_thread_key].start_timeout()
-        return 1, global_config["console_thread"][console_thread_key]
+        return global_config["console_thread"][console_thread_key]
     
     for port in  global_config["console_port_iterator"]():
         print "create_or_use_console_proxy_thread() port:", port
@@ -1970,53 +1806,44 @@ def create_or_use_console_proxy_thread(console_server, console_port):
             clithread.start()
             global_config["console_thread"][console_thread_key] = clithread
             global_config["console_ports"][port] = console_thread_key
-            return 1, clithread
+            return clithread
         except cli.ConsoleProxyExceptionPortUsed as e:
             #port used, try with onoher
             continue
         except cli.ConsoleProxyException as e:
-            return -1, str(e)
-    return -1, "Not found any free 'http_console_ports'"
+            raise NfvoException(str(e), HTTP_Bad_Request)
+    raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict)
 
 def check_tenant(mydb, tenant_id):
     '''check that tenant exists at database'''
-    result, _ = mydb.get_table(FROM='nfvo_tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id})
-    if result<=0: return False
-    return True
+    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)
+    return
 
 def new_tenant(mydb, tenant_dict):
-    result, tenant_id = mydb.new_row("nfvo_tenants", tenant_dict, None, add_uuid=True, log=True)
-    if result < 0:
-        return result, tenant_id
-    return 200,tenant_id
+    tenant_id = mydb.new_row("nfvo_tenants", tenant_dict, add_uuid=True)
+    return tenant_id
 
 def delete_tenant(mydb, tenant):
     #get nfvo_tenant info
-    result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant, 'tenant')
-    if result < 0:
-        return result, tenant_dict
-
-    result, tenant_id = mydb.delete_row("nfvo_tenants", tenant_dict['uuid'], None)
-    if result < 0:
-        return result, tenant_id
-    return 200, tenant_dict['uuid']
+    
+    tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant, 'tenant')
+    mydb.delete_row_by_id("nfvo_tenants", tenant_dict['uuid'])
+    return tenant_dict['uuid'] + " " + tenant_dict["name"]
 
 def new_datacenter(mydb, datacenter_descriptor):
     if "config" in datacenter_descriptor:
         datacenter_descriptor["config"]=yaml.safe_dump(datacenter_descriptor["config"],default_flow_style=True,width=256)
-    result, datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, None, add_uuid=True, log=True)
-    if result < 0:
-        return result, datacenter_id
-    return 200,datacenter_id
+    datacenter_id = mydb.new_row("datacenters", datacenter_descriptor, add_uuid=True)
+    return datacenter_id
 
 def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
     #obtain data, check that only one exist
-    result, content = mydb.get_table_by_uuid_name('datacenters', datacenter_id_name)
-    if result < 0:
-        return result, content
+    datacenter = mydb.get_table_by_uuid_name('datacenters', datacenter_id_name)
     #edit data 
-    datacenter_id = content['uuid']
-    where={'uuid': content['uuid']}
+    datacenter_id = datacenter['uuid']
+    where={'uuid': datacenter['uuid']}
     if "config" in datacenter_descriptor:
         if datacenter_descriptor['config']!=None:
             try:
@@ -2027,45 +1854,35 @@ def edit_datacenter(mydb, datacenter_id_name, datacenter_descriptor):
                     if new_config_dict[k]==None:
                         to_delete.append(k)
                 
-                config_dict = yaml.load(content["config"])
+                config_dict = yaml.load(datacenter["config"])
                 config_dict.update(new_config_dict)
                 #delete null fields
                 for k in to_delete:
                     del config_dict[k]
-            except Exception,e:
-                return -HTTP_Bad_Request, "Bad format at datacenter:config " + str(e)
+            except Exception as e:
+                raise NfvoException("Bad format at datacenter:config " + str(e), HTTP_Bad_Request)
         datacenter_descriptor["config"]= yaml.safe_dump(config_dict,default_flow_style=True,width=256) if len(config_dict)>0 else None
-    result, content = mydb.update_rows('datacenters', datacenter_descriptor, where)
-    if result < 0:
-        return result, datacenter_id
-    return 200, datacenter_id
+    mydb.update_rows('datacenters', datacenter_descriptor, where)
+    return datacenter_id
 
 def delete_datacenter(mydb, datacenter):
     #get nfvo_tenant info
-    result,datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter, 'datacenter')
-    if result < 0:
-        return result, datacenter_dict
-
-    result, datacenter_id = mydb.delete_row("datacenters", datacenter_dict['uuid'], None)
-    if result < 0:
-        return result, datacenter_id
-    return 200, datacenter_dict['uuid']
+    datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter, 'datacenter')
+    mydb.delete_row_by_id("datacenters", datacenter_dict['uuid'])
+    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):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, datacenter_id=datacenter)
+        vims = get_vim(mydb, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.associate_datacenter_to_tenant() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.associate_datacenter_to_tenant() error. Several datacenters found"
-        #print result, vims
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_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)
+
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
     datacenter_name=myvim["name"]
@@ -2073,19 +1890,15 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=
     create_vim_tenant=True if vim_tenant_id==None and vim_tenant_name==None else False
 
     #get nfvo_tenant info
-    result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant)
-    if result < 0:
-        return result, tenant_dict
+    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 }
-    result,content = mydb.get_table(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
-    if result>0:
-        return -HTTP_Conflict, "datacenter %s and tenant %s are already attached" %(datacenter_id, tenant_dict['uuid'])
-    elif result<0:
-        return result, content
+    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:
@@ -2095,10 +1908,8 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=
         if vim_tenant_name!=None:
             where_["vim_tenant_name"] = vim_tenant_name
         #check if vim_tenant_id is already at database
-        result,datacenter_tenants_dict = mydb.get_table(FROM='datacenter_tenants', WHERE=where_)
-        if result < 0:
-            return result, datacenter_tenants_dict
-        elif result>=1:
+        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
@@ -2110,7 +1921,7 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=
         try:
             vim_tenant_id = myvim.new_tenant(vim_tenant_name, "created by openmano for datacenter "+datacenter_name)
         except vimconn.vimconnException as e:
-            return -HTTP_Internal_Server_Error, "Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id, str(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"
     
@@ -2121,32 +1932,25 @@ def associate_datacenter_to_tenant(mydb, nfvo_tenant, datacenter, vim_tenant_id=
         datacenter_tenants_dict["user"]            = vim_username
         datacenter_tenants_dict["passwd"]          = vim_password
         datacenter_tenants_dict["datacenter_id"]   = datacenter_id
-        res,id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, tenant_dict['uuid'], True, True)
-        if res<1:
-            return -HTTP_Bad_Request, "Not possible to add %s to database datacenter_tenants table %s " %(vim_tenant_id, id_)
+        id_ = mydb.new_row('datacenter_tenants', datacenter_tenants_dict, add_uuid=True)
         datacenter_tenants_dict["uuid"] = id_
     
     #fill tenants_datacenters table
     tenants_datacenter_dict["datacenter_tenant_id"]=datacenter_tenants_dict["uuid"]
-    res,id_ = mydb.new_row('tenants_datacenters', tenants_datacenter_dict, tenant_dict['uuid'], False, True)
-    if res<1:
-        return -HTTP_Bad_Request, "Not possible to create an entry at database table datacenter_tenants: " + id_
-    return 200, datacenter_id
+    mydb.new_row('tenants_datacenters', tenants_datacenter_dict)
+    return datacenter_id
 
 def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=None):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, datacenter_id=datacenter)
+        vims = get_vim(mydb, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.deassociate_datacenter_to_tenant() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.deassociate_datacenter_to_tenant() error. Several datacenters found"
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_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)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
 
@@ -2154,73 +1958,65 @@ def deassociate_datacenter_to_tenant(mydb, tenant_id, datacenter, vim_tenant_id=
     if not tenant_id or tenant_id=="any":
         tenant_uuid = None
     else:
-        result,tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
-        if result < 0:
-            return result, tenant_dict
+        tenant_dict = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
         tenant_uuid = tenant_dict['uuid']
 
     #check that this association exist before
     tenants_datacenter_dict={"datacenter_id":datacenter_id }
     if tenant_uuid:
         tenants_datacenter_dict["nfvo_tenant_id"] = tenant_uuid
-    result,tenant_datacenter_list = mydb.get_table(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
-    if result==0 and tenant_uuid:
-        return -HTTP_Not_Found, "datacenter %s and tenant %s are not  attached" %(datacenter_id, tenant_dict['uuid'])
-    elif result<0:
-        return result, tenant_datacenter_list
+    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)
 
     #delete this association
-    result,data = mydb.delete_row_by_dict(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
-    if result<0:
-        return result,data
+    mydb.delete_row(FROM='tenants_datacenters', WHERE=tenants_datacenter_dict)
 
     #get vim_tenant info and deletes
     warning=''
     for tenant_datacenter_item in tenant_datacenter_list:
-        result,vim_tenant_dict = mydb.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'])
-        if result > 0:
-            #try to delete vim:tenant
-            result,data = mydb.delete_row('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'], tenant_uuid)
-            if result<0:
-                pass #the error will be caused because dependencies, vim_tenant can not be deleted
-            elif vim_tenant_dict['created']=='true':
+        vim_tenant_dict = mydb.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'])
+        #try to delete vim:tenant
+        try:
+            mydb.delete_row_by_id('datacenter_tenants', tenant_datacenter_item['datacenter_tenant_id'])
+            if vim_tenant_dict['created']=='true':
                 #delete tenant at VIM if created by NFVO
                 try: 
                     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))
                     logger.warn(warning)
+        except db_base_Exception as e:
+            logger.error("Cannot delete datacenter_tenants " + str(e))
+            pass #the error will be caused because dependencies, vim_tenant can not be deleted
 
-    return 200, "datacenter %s detached.%s" %(datacenter_id, warning)
+    return "datacenter {} detached. {}".format(datacenter_id, warning)
 
 def datacenter_action(mydb, tenant_id, datacenter, action_dict):
     #DEPRECATED
     #get datacenter info    
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        logger.error("nfvo.datacenter_action() error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        logger.error("nfvo.datacenter_action() error. Several datacenters found")
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_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)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
 
     if 'net-update' in action_dict:
         try:
-            content = myvim.get_network_list(filter_dict={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
+            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))
-            return -HTTP_Internal_Server_Error, str(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)
         #update nets Change from VIM format to NFVO format
         net_list=[]
-        for net in content:
+        for net in nets:
             net_nfvo={'datacenter_id': datacenter_id}
             net_nfvo['name']       = net['name']
             #net_nfvo['description']= net['name']
@@ -2229,63 +2025,54 @@ def datacenter_action(mydb, tenant_id, datacenter, action_dict):
             net_nfvo['shared']     = net['shared']
             net_nfvo['multipoint'] = False if net['type']=='ptp' else True
             net_list.append(net_nfvo)
-        result, content = mydb.update_datacenter_nets(datacenter_id, net_list)
-        if result < 0:
-            return -HTTP_Internal_Server_Error, content
-        logger.info("Inserted %d nets, deleted %d old nets", result, content)
-                
-        return 200, result
+        inserted, deleted = mydb.update_datacenter_nets(datacenter_id, net_list)
+        logger.info("Inserted %d nets, deleted %d old nets", inserted, deleted)
+        return inserted
     elif 'net-edit' in action_dict:
         net = action_dict['net-edit'].pop('net')
         what = 'vim_net_id' if utils.check_valid_uuid(net) else 'name'
-        result, content = mydb.update_rows('datacenter_nets', action_dict['net-edit'], 
+        result = mydb.update_rows('datacenter_nets', action_dict['net-edit'], 
                                 WHERE={'datacenter_id':datacenter_id, what: net})
-        return result, content
+        return result
     elif 'net-delete' in action_dict:
         net = action_dict['net-deelte'].get('net')
         what = 'vim_net_id' if utils.check_valid_uuid(net) else 'name'
-        result, content = mydb.delete_row_by_dict(FROM='datacenter_nets', 
+        result = mydb.delete_row(FROM='datacenter_nets', 
                                 WHERE={'datacenter_id':datacenter_id, what: net})
-        return result, content
+        return result
 
     else:
-        return -HTTP_Bad_Request, "Unknown action " + str(action_dict)
+        raise NfvoException("Unknown action " + str(action_dict), HTTP_Bad_Request)
 
 def datacenter_edit_netmap(mydb, tenant_id, datacenter, netmap, action_dict):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.datacenter_action() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.datacenter_action() error. Several datacenters found"
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(str(datacenter)), HTTP_Not_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)
     datacenter_id=vims.keys()[0]
 
     what = 'uuid' if utils.check_valid_uuid(netmap) else 'name'
-    result, content = mydb.update_rows('datacenter_nets', action_dict['netmap'], 
+    result = mydb.update_rows('datacenter_nets', action_dict['netmap'], 
                             WHERE={'datacenter_id':datacenter_id, what: netmap})
-    return result, content
+    return result
 
 def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        logger.error("nfvo.datacenter_new_netmap() error. Datacenter not found")
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found)
+    elif len(vims)>1:
+        #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
+        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
     filter_dict={}
@@ -2299,16 +2086,16 @@ def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None):
         filter_dict["shared"] = True
     
     try:
-        content = myvim.get_network_list(filter_dict=filter_dict)
+        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))
-        return -HTTP_Internal_Server_Error, str(e)
-    if len(content)>1 and action_dict:
-        return -HTTP_Conflict, "more than two networks found, specify with vim_id"
-    elif len(content)==0: # and action_dict:
-        return -HTTP_Not_Found, "Not found a network at VIM with " + str(filter_dict)
+        #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)
+    if len(vim_nets)>1 and action_dict:
+        raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict)
+    elif len(vim_nets)==0: # and action_dict:
+        raise NfvoException("Not found a network at VIM with " + str(filter_dict), HTTP_Not_Found)
     net_list=[]
-    for net in content:
+    for net in vim_nets:
         net_nfvo={'datacenter_id': datacenter_id}
         if action_dict and "name" in action_dict:
             net_nfvo['name']       = action_dict['name']
@@ -2319,31 +2106,29 @@ def datacenter_new_netmap(mydb, tenant_id, datacenter, action_dict=None):
         net_nfvo['type']       = net['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man')  to ('bridge','data','ptp')
         net_nfvo['shared']     = net['shared']
         net_nfvo['multipoint'] = False if net['type']=='ptp' else True
-        result, content = mydb.new_row("datacenter_nets", net_nfvo, add_uuid=True)
-        if action_dict and result < 0 :
-            return result, content
-        if result < 0:
-            net_nfvo["status"] = "FAIL: " + content
-        else:
+        try:
+            net_id = mydb.new_row("datacenter_nets", net_nfvo, add_uuid=True)
             net_nfvo["status"] = "OK"
-            net_nfvo["uuid"] = content
+            net_nfvo["uuid"] = net_id
+        except db_base_Exception as e:
+            if action_dict:
+                raise
+            else:
+                net_nfvo["status"] = "FAIL: " + str(e)
         net_list.append(net_nfvo)                         
-    return 200, net_list        
+    return net_list        
 
 def vim_action_get(mydb, tenant_id, datacenter, item, name):
     #get datacenter info
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.datacenter_action() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.datacenter_action() error. Several datacenters found"
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found)
+    elif len(vims)>1:
+        #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
+        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
     filter_dict={}
@@ -2359,17 +2144,18 @@ def vim_action_get(mydb, tenant_id, datacenter, item, name):
         elif item=="tenants":
             content = myvim.get_tenant_list(filter_dict=filter_dict)
         else:
-            return -HTTP_Method_Not_Allowed, item + "?"
-        print "vim_action response ", content #update nets Change from VIM format to NFVO format
+            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)
+        logger.debug("vim_action response ", content) #update nets Change from VIM format to NFVO format
         if name and len(content)==1:
-            return 200, {item[:-1]: content[0]}
+            return {item[:-1]: content[0]}
         elif name and len(content)==0:
-            return -HTTP_Not_Found, "No %s found with %s" % (item[:-1], " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), filter_dict.iteritems())))
+            raise NfvoException("No {} found with ".format(item[:-1]) + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), filter_dict.iteritems())),
+                 -HTTP_Not_Found)
         else:
-            return 200, {item: content}
+            return {item: content}
     except vimconn.vimconnException as e:
         print "vim_action Not possible to get_%s_list from VIM: %s " % (item, str(e))
-        return -e.http_code, "Not possible to get_{}_list from VIM: {}".format(item, str(e))
+        raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item, str(e)), e.http_code)
     
 def vim_action_delete(mydb, tenant_id, datacenter, item, name):
     #get datacenter info
@@ -2377,29 +2163,24 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
         tenant_id=None
 
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.datacenter_action() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.datacenter_action() error. Several datacenters found"
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found)
+    elif len(vims)>1:
+        #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
+        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
     #get uuid name
-    result, content = vim_action_get(mydb, tenant_id, datacenter, item, name)
-    print content
-    if result < 0:
-        return result, content
+    content = vim_action_get(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:
-        return -HTTP_Not_Found, "Not found " + item
+        raise NfvoException("Not found " + item, HTTP_Not_Found)
     elif type(items)==list and len(items)>1:
-        return -HTTP_Not_Found, "Found more than one %s with this name. Use uuid." % item
+        raise NfvoException("Found more than one {} with this name. Use uuid.".format(item), HTTP_Not_Found)
     else: # it is a dict
         item_id = items["id"]
         item_name = str(items.get("name"))
@@ -2410,15 +2191,12 @@ def vim_action_delete(mydb, tenant_id, datacenter, item, name):
         elif item=="tenants":
             content = myvim.delete_tenant(item_id)
         else:
-            return -HTTP_Method_Not_Allowed, item + "?"    
+            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)    
     except vimconn.vimconnException as e:
-        print "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e))
-        return -e.http_code, "Not possible to delete_{} {} from VIM: {}".format(item, name, str(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)
 
-    if result < 0:
-        print "vim_action Not possible to delete %s %s from VIM: %s " % (item, name, content)
-        return result, content
-    return 200, "{} {} {} deleted".format(item[:-1], item_id,item_name)
+    return "{} {} {} deleted".format(item[:-1], item_id,item_name)
     
 def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
     #get datacenter info
@@ -2427,17 +2205,14 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
         tenant_id=None
 
     if utils.check_valid_uuid(datacenter): 
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_id=datacenter)
     else:
-        result, vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
-    if result < 0:
-        print "nfvo.datacenter_action() error. Datacenter not found"
-        return result, vims
-    elif result == 0:
-        return -HTTP_Not_Found, "datacenter '%s' not found" % str(datacenter)
-    elif result>1:
-        print "nfvo.datacenter_action() error. Several datacenters found"
-        return -HTTP_Conflict, "More than one datacenters found, try to identify with uuid"
+        vims = get_vim(mydb, nfvo_tenant=tenant_id, datacenter_name=datacenter)
+    if len(vims) == 0:
+        raise NfvoException("datacenter '{}' not found".format(datacenter), HTTP_Not_Found)
+    elif len(vims)>1:
+        #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
+        raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict)
     datacenter_id=vims.keys()[0]
     myvim=vims[datacenter_id]
     
@@ -2452,10 +2227,9 @@ def vim_action_create(mydb, tenant_id, datacenter, item, descriptor):
             tenant = descriptor["tenant"]
             content = myvim.new_tenant(tenant["name"], tenant.get("description"))
         else:
-            return -HTTP_Method_Not_Allowed, item + "?"    
+            raise NfvoException(item + "?", HTTP_Method_Not_Allowed)    
     except vimconn.vimconnException as e:
-        print "vim_action Not possible to create {} at VIM: {} ".format(item, str(e))
-        return -e.http_code, "Not possible to create {} at VIM: {}".format(item, str(e))
+        raise NfvoException("Not possible to create {} at VIM: {}".format(item, str(e)), e.http_code)
 
     return vim_action_get(mydb, tenant_id, datacenter, item, content)
 
index 28317ec..3ff11ad 100644 (file)
@@ -27,542 +27,28 @@ NFVO DB engine. It implements all the methods to interact with the Openmano Data
 __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
 __date__ ="$28-aug-2014 10:05:01$"
 
+import db_base
 import MySQLdb as mdb
-import uuid as myUuid
-import utils
 import json
-import yaml
+#import yaml
 import time
 
-HTTP_Bad_Request = 400
-HTTP_Unauthorized = 401 
-HTTP_Not_Found = 404 
-HTTP_Method_Not_Allowed = 405 
-HTTP_Request_Timeout = 408
-HTTP_Conflict = 409
-HTTP_Service_Unavailable = 503 
-HTTP_Internal_Server_Error = 500 
 
-tables_with_created_field=["datacenters","instance_nets","instance_scenarios","instance_vms","instance_vnfs",
+tables_with_createdat_field=["datacenters","instance_nets","instance_scenarios","instance_vms","instance_vnfs",
                            "interfaces","nets","nfvo_tenants","scenarios","sce_interfaces","sce_nets",
                            "sce_vnfs","tenants_datacenters","datacenter_tenants","vms","vnfs"]
 
-class nfvo_db():
-    def __init__(self):
-        #initialization
+class nfvo_db(db_base.db_base):
+    def __init__(self, host=None, user=None, passwd=None, database=None, log_name='openmano.db', log_level="ERROR"):
+        db_base.db_base.__init__(self, host, user, passwd, database, log_name, log_level)
+        db_base.db_base.tables_with_created_field=tables_with_createdat_field
         return
 
-    def connect(self, host=None, user=None, passwd=None, database=None):
-        '''Connect to specific data base. 
-        The first time a valid host, user, passwd and database must be provided,
-        Following calls can skip this parameters
-        '''
-        try:
-            if host     is not None: self.host = host
-            if user     is not None: self.user = user
-            if passwd   is not None: self.passwd = passwd
-            if database is not None: self.database = database
-
-            self.con = mdb.connect(self.host, self.user, self.passwd, self.database)
-            print "DB: connected to %s@%s -> %s" % (self.user, self.host, self.database)
-            return 0
-        except mdb.Error, e:
-            print "nfvo_db.connect Error connecting to DB %s@%s -> %s Error %d: %s" % (self.user, self.host, self.database, e.args[0], e.args[1])
-            return -1
-        
-    def get_db_version(self):
-        ''' Obtain the database schema version.
-        Return: (negative, text) if error or version 0.0 where schema_version table is missing
-                (version_int, version_text) if ok
-        '''
-        cmd = "SELECT version_int,version,openmano_ver FROM schema_version"
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor()
-                    #print cmd
-                    self.cur.execute(cmd)
-                    rows = self.cur.fetchall()
-                    highest_version_int=0
-                    highest_version=""
-                    #print rows
-                    for row in rows: #look for the latest version
-                        if row[0]>highest_version_int:
-                            highest_version_int, highest_version = row[0:2]
-                    return highest_version_int, highest_version
-            except (mdb.Error, AttributeError), e:
-                #print cmd
-                print "get_db_version DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def disconnect(self):
-        '''disconnect from specific data base'''
-        try:
-            self.con.close()
-            del self.con
-        except mdb.Error, e:
-            print "Error disconnecting from DB: Error %d: %s" % (e.args[0], e.args[1])
-            return -1
-        except AttributeError, e: #self.con not defined
-            if e[0][-5:] == "'con'": return -1, "Database internal error, no connection."
-            else: raise
-
-    def format_error(self, e, command=None, extra=None): 
-        if type(e[0]) is str:
-            if e[0][-5:] == "'con'": return -HTTP_Internal_Server_Error, "DB Exception, no connection."
-            else: raise
-        if e.args[0]==2006 or e.args[0]==2013 : #MySQL server has gone away (((or)))    Exception 2013: Lost connection to MySQL server during query
-            #reconnect
-            self.connect()
-            return -HTTP_Request_Timeout,"Database reconnection. Try Again"
-        
-        fk=e.args[1].find("foreign key constraint fails")
-        if fk>=0:
-            if command=="update": return -HTTP_Bad_Request, "tenant_id %s not found." % extra
-            elif command=="delete":  return -HTTP_Bad_Request, "Resource is not free. There are %s that prevent deleting it." % extra
-        de = e.args[1].find("Duplicate entry")
-        fk = e.args[1].find("for key")
-        uk = e.args[1].find("Unknown column")
-        wc = e.args[1].find("in 'where clause'")
-        fl = e.args[1].find("in 'field list'")
-        #print de, fk, uk, wc,fl
-        if de>=0:
-            if fk>=0: #error 1062
-                return -HTTP_Conflict, "Value %s already in use for %s" % (e.args[1][de+15:fk], e.args[1][fk+7:])
-        if uk>=0:
-            if wc>=0:
-                return -HTTP_Bad_Request, "Field %s can not be used for filtering" % e.args[1][uk+14:wc]
-            if fl>=0:
-                return -HTTP_Bad_Request, "Field %s does not exist" % e.args[1][uk+14:wc]
-        return -HTTP_Internal_Server_Error, "Database internal Error %d: %s" % (e.args[0], e.args[1])
-    
-    def __str2db_format(self, data):
-        '''Convert string data to database format. 
-        If data is None it returns the 'Null' text,
-        otherwise it returns the text surrounded by quotes ensuring internal quotes are escaped.
-        '''
-        if data==None:
-            return 'Null'
-        out=str(data)
-        if "'" not in out:
-            return "'" + out + "'"
-        elif '"' not in out:
-            return '"' + out + '"'
-        else:
-            return json.dumps(out)
-    
-    def __tuple2db_format_set(self, data):
-        '''Compose the needed text for a SQL SET, parameter 'data' is a pair tuple (A,B),
-        and it returns the text 'A="B"', where A is a field of a table and B is the value 
-        If B is None it returns the 'A=Null' text, without surrounding Null by quotes
-        If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
-        and it ensures internal quotes of B are escaped.
-        '''
-        if data[1]==None:
-            return str(data[0]) + "=Null"
-        out=str(data[1])
-        if "'" not in out:
-            return str(data[0]) + "='" + out + "'"
-        elif '"' not in out:
-            return str(data[0]) + '="' + out + '"'
-        else:
-            return str(data[0]) + '=' + json.dumps(out)
-    
-    def __tuple2db_format_where(self, data):
-        '''Compose the needed text for a SQL WHERE, parameter 'data' is a pair tuple (A,B),
-        and it returns the text 'A="B"', where A is a field of a table and B is the value 
-        If B is None it returns the 'A is Null' text, without surrounding Null by quotes
-        If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
-        and it ensures internal quotes of B are escaped.
-        '''
-        if data[1]==None:
-            return str(data[0]) + " is Null"
-        
-#         if type(data[1]) is tuple:  #this can only happen in a WHERE_OR clause
-#             text =[]
-#             for d in data[1]:
-#                 if d==None:
-#                     text.append(str(data[0]) + " is Null")
-#                     continue
-#                 out=str(d)
-#                 if "'" not in out:
-#                     text.append( str(data[0]) + "='" + out + "'" )
-#                 elif '"' not in out:
-#                     text.append( str(data[0]) + '="' + out + '"' )
-#                 else:
-#                     text.append( str(data[0]) + '=' + json.dumps(out) )
-#             return " OR ".join(text)
-
-        out=str(data[1])
-        if "'" not in out:
-            return str(data[0]) + "='" + out + "'"
-        elif '"' not in out:
-            return str(data[0]) + '="' + out + '"'
-        else:
-            return str(data[0]) + '=' + json.dumps(out)
-
-    def __tuple2db_format_where_not(self, data):
-        '''Compose the needed text for a SQL WHERE(not). parameter 'data' is a pair tuple (A,B),
-        and it returns the text 'A<>"B"', where A is a field of a table and B is the value 
-        If B is None it returns the 'A is not Null' text, without surrounding Null by quotes
-        If B is not None it returns the text "A<>'B'" or 'A<>"B"' where B is surrounded by quotes,
-        and it ensures internal quotes of B are escaped.
-        '''
-        if data[1]==None:
-            return str(data[0]) + " is not Null"
-        out=str(data[1])
-        if "'" not in out:
-            return str(data[0]) + "<>'" + out + "'"
-        elif '"' not in out:
-            return str(data[0]) + '<>"' + out + '"'
-        else:
-            return str(data[0]) + '<>' + json.dumps(out)
-    
-    def __remove_quotes(self, data):
-        '''remove single quotes ' of any string content of data dictionary'''
-        for k,v in data.items():
-            if type(v) == str:
-                if "'" in v: 
-                    data[k] = data[k].replace("'","_")
-    
-    def __update_rows(self, table, UPDATE, WHERE, log=False, modified_time=0):
-        ''' Update one or several rows into a table.
-        Atributes
-            UPDATE: dictionary with the key: value to change
-            table: table where to update
-            WHERE: dictionary of elements to update
-        Return: (result, descriptive text) where result indicates the number of updated files, negative if error
-        '''
-                #gettting uuid 
-        uuid = WHERE['uuid'] if 'uuid' in WHERE else None
-        values = ",".join(map(self.__tuple2db_format_set, UPDATE.iteritems() ))
-        if modified_time:
-            values += ",modified_at=%f" % modified_time
-        cmd= "UPDATE " + table +" SET " + values +\
-            " WHERE " + " and ".join(map(self.__tuple2db_format_where, WHERE.iteritems() ))
-        print cmd
-        self.cur.execute(cmd) 
-        nb_rows = self.cur.rowcount
-        if nb_rows > 0 and log:                
-            #inserting new log
-            if uuid is None: uuid_k = uuid_v = ""
-            else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
-            cmd = "INSERT INTO logs (related,level%s,description) VALUES ('%s','debug'%s,\"updating %d entry %s\")" \
-                % (uuid_k, table, uuid_v, nb_rows, (str(UPDATE)).replace('"','-')  )
-            print cmd
-            self.cur.execute(cmd)                    
-        return nb_rows, "%d updated from %s" % (nb_rows, table[:-1] )
-    
-    def _new_row_internal(self, table, INSERT, tenant_id=None, add_uuid=False, root_uuid=None, log=False, created_time=0):
-        ''' Add one row into a table. It DOES NOT begin or end the transaction, so self.con.cursor must be created
-        Attribute 
-            INSERT: dictionary with the key: value to insert
-            table: table where to insert
-            tenant_id: only useful for logs. If provided, logs will use this tenant_id
-            add_uuid: if True, it will create an uuid key entry at INSERT if not provided
-        It checks presence of uuid and add one automatically otherwise
-        Return: (result, uuid) where result can be 0 if error, or 1 if ok
-        '''
-
-        if add_uuid:
-            #create uuid if not provided
-            if 'uuid' not in INSERT:
-                uuid = INSERT['uuid'] = str(myUuid.uuid1()) # create_uuid
-            else: 
-                uuid = str(INSERT['uuid'])
-        else:
-            uuid=None
-        if add_uuid:
-            #defining root_uuid if not provided
-            if root_uuid is None:
-                root_uuid = uuid
-            if created_time:
-                created_at = created_time
-            else:
-                created_at=time.time()
-            #inserting new uuid
-            cmd = "INSERT INTO uuids (uuid, root_uuid, used_at, created_at) VALUES ('%s','%s','%s', %f)" % (uuid, root_uuid, table, created_at)
-            print cmd
-            self.cur.execute(cmd)
-        #insertion
-        cmd= "INSERT INTO " + table +" SET " + \
-            ",".join(map(self.__tuple2db_format_set, INSERT.iteritems() )) 
-        if created_time:
-            cmd += ",created_at=%f" % created_time
-        print cmd
-        self.cur.execute(cmd)
-        nb_rows = self.cur.rowcount
-        #inserting new log
-        if nb_rows > 0 and log:                
-            if add_uuid: del INSERT['uuid']
-            if uuid is None: uuid_k = uuid_v = ""
-            else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
-            if tenant_id is None: tenant_k = tenant_v = ""
-            else: tenant_k=",nfvo_tenant_id"; tenant_v=",'" + str(tenant_id) + "'"
-            cmd = "INSERT INTO logs (related,level%s%s,description) VALUES ('%s','debug'%s%s,\"new %s %s\")" \
-                % (uuid_k, tenant_k, table, uuid_v, tenant_v, table[:-1], str(INSERT).replace('"','-'))
-            print cmd
-            self.cur.execute(cmd)                    
-        return nb_rows, uuid
-
-    def __get_rows(self,table,uuid):
-        self.cur.execute("SELECT * FROM " + str(table) +" where uuid='" + str(uuid) + "'")
-        rows = self.cur.fetchall()
-        return self.cur.rowcount, rows
-    
-    def new_row(self, table, INSERT, tenant_id=None, add_uuid=False, log=False, created_time=0):
-        ''' Add one row into a table.
-        Attribute 
-            INSERT: dictionary with the key: value to insert
-            table: table where to insert
-            tenant_id: only useful for logs. If provided, logs will use this tenant_id
-            add_uuid: if True, it will create an uuid key entry at INSERT if not provided
-        It checks presence of uuid and add one automatically otherwise
-        Return: (result, uuid) where result can be 0 if error, or 1 if ok
-        '''
-        if table in tables_with_created_field and created_time==0:
-            created_time=time.time()
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor()
-                    return self._new_row_internal(table, INSERT, tenant_id, add_uuid, None, log, created_time)
-                    
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.new_row DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def update_rows(self, table, UPDATE, WHERE, log=False, modified_time=0):
-        ''' Update one or several rows into a table.
-        Atributes
-            UPDATE: dictionary with the key: value to change
-            table: table where to update
-            WHERE: dictionary of elements to update
-        Return: (result, descriptive text) where result indicates the number of updated files
-        '''
-        if table in tables_with_created_field and modified_time==0:
-            modified_time=time.time()
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor()
-                    return self.__update_rows(table, UPDATE, WHERE, log)
-                    
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.update_rows DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def delete_row(self, table, uuid, tenant_id=None, log=True):
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    #delete host
-                    self.cur = self.con.cursor()
-                    cmd = "DELETE FROM %s WHERE uuid = '%s'" % (table, uuid)
-                    print cmd
-                    self.cur.execute(cmd)
-                    deleted = self.cur.rowcount
-                    if deleted == 1:
-                        #delete uuid
-                        if table == 'tenants': tenant_str=uuid
-                        elif tenant_id:
-                            tenant_str = tenant_id
-                        else: 
-                            tenant_str = 'Null'
-                        self.cur = self.con.cursor()
-                        cmd = "DELETE FROM uuids WHERE root_uuid = '%s'" % uuid
-                        print cmd
-                        self.cur.execute(cmd)
-                        #inserting new log
-                        if log:
-                            cmd = "INSERT INTO logs (related,level,uuid,nfvo_tenant_id,description) VALUES ('%s','debug','%s','%s','delete %s')" % (table, uuid, tenant_str, table[:-1])
-                            print cmd
-                            self.cur.execute(cmd)                    
-                return deleted, table[:-1] + " '%s' %s" %(uuid, "deleted" if deleted==1 else "not found")
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.delete_row DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c =  self.format_error(e, "delete", 'instances' if table=='hosts' or table=='tenants' else 'dependencies')
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def delete_row_by_dict(self, **sql_dict):
-        ''' Deletes rows from a table.
-        Attribute sql_dir: dictionary with the following key: value
-            'FROM': string of table name (Mandatory)
-            'WHERE': dict of key:values, translated to key=value AND ... (Optional)
-            'WHERE_NOT': dict of key:values, translated to key<>value AND ... (Optional)
-            'LIMIT': limit of number of rows (Optional)
-        Return: the (number of items deleted, descriptive test) if ok; (negative, descriptive text) if error
-        '''
-        #print sql_dict
-        from_  = "FROM " + str(sql_dict['FROM'])
-        #print 'from_', from_
-        if 'WHERE' in sql_dict and len(sql_dict['WHERE']) > 0:
-            w=sql_dict['WHERE']
-            where_ = "WHERE " + " AND ".join(map(self.__tuple2db_format_where, w.iteritems())) 
-        else: where_ = ""
-        if 'WHERE_NOT' in sql_dict and len(sql_dict['WHERE_NOT']) > 0: 
-            w=sql_dict['WHERE_NOT']
-            where_2 = " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems()))
-            if len(where_)==0:   where_ = "WHERE " + where_2
-            else:                where_ = where_ + " AND " + where_2
-        #print 'where_', where_
-        limit_ = "LIMIT " + str(sql_dict['LIMIT']) if 'LIMIT' in sql_dict else ""
-        #print 'limit_', limit_
-        cmd =  " ".join( ("DELETE", from_, where_, limit_) )
-        print cmd
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    #delete host
-                    self.cur = self.con.cursor()
-                    self.cur.execute(cmd)
-                    deleted = self.cur.rowcount
-                return deleted, "%d deleted from %s" % (deleted, sql_dict['FROM'][:-1] )
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.delete_row DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c =  self.format_error(e, "delete", 'dependencies')
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def get_rows(self,table,uuid):
-        '''get row from a table based on uuid'''
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    self.cur.execute("SELECT * FROM " + str(table) +" where uuid='" + str(uuid) + "'")
-                    rows = self.cur.fetchall()
-                    return self.cur.rowcount, rows
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_rows DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-    
-    def get_table(self, **sql_dict):
-        ''' Obtain rows from a table.
-        Attribute sql_dir: dictionary with the following key: value
-            'SELECT':    list or tuple of fields to retrieve) (by default all)
-            'FROM':      string of table name (Mandatory)
-            'WHERE':     dict of key:values, translated to key=value (key is null) AND ... (Optional)
-            'WHERE_NOT': dict of key:values, translated to key<>value (key is not null) AND ... (Optional)
-            'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
-            'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional  
-            'LIMIT':     limit of number of rows (Optional)
-            'ORDER_BY':  list or tuple of fields to order
-        Return: a list with dictionaries at each row
-        '''
-        #print sql_dict
-        select_= "SELECT " + ("*" if 'SELECT' not in sql_dict else ",".join(map(str,sql_dict['SELECT'])) )
-        #print 'select_', select_
-        from_  = "FROM " + str(sql_dict['FROM'])
-        #print 'from_', from_
-        where_and = ""
-        where_or = ""
-        w=sql_dict.get('WHERE')
-        if w:
-            where_and = " AND ".join(map(self.__tuple2db_format_where, w.iteritems() ))
-        w=sql_dict.get('WHERE_NOT')
-        if w: 
-            if where_and: where_and += " AND "
-            where_and += " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems() ) )
-        w=sql_dict.get('WHERE_OR')
-        if w:
-            where_or =  " OR ".join(map(self.__tuple2db_format_where, w.iteritems() ))
-        if where_and and where_or:
-            if sql_dict.get("WHERE_AND_OR") == "AND":
-                where_ = "WHERE " + where_and + " AND (" + where_or + ")"
-            else:
-                where_ = "WHERE (" + where_and + ") OR " + where_or
-        elif where_and and not where_or:
-            where_ = "WHERE " + where_and
-        elif not where_and and where_or:
-            where_ = "WHERE " + where_or
-        else:
-            where_ = ""
-        #print 'where_', where_
-        limit_ = "LIMIT " + str(sql_dict['LIMIT']) if 'LIMIT' in sql_dict else ""
-        order_ = "ORDER BY " + ",".join(map(str,sql_dict['SELECT'])) if 'ORDER_BY' in sql_dict else ""
-        
-        #print 'limit_', limit_
-        cmd =  " ".join( (select_, from_, where_, limit_, order_) )
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    print cmd
-                    self.cur.execute(cmd)
-                    rows = self.cur.fetchall()
-                    return self.cur.rowcount, rows
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_table DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def get_table_by_uuid_name(self, table, uuid_name, error_item_text=None, allow_serveral=False, WHERE_OR={}, WHERE_AND_OR="OR"):
-        ''' Obtain One row from a table based on name or uuid.
-        Attribute:
-            table: string of table name
-            uuid_name: name or uuid. If not uuid format is found, it is considered a name
-            allow_severeral: if False return ERROR if more than one row are founded 
-            error_item_text: in case of error it identifies the 'item' name for a proper output text 
-            'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
-            'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional  
-        Return: if allow_several==False, a dictionary with this row, or error if no item is found or more than one is found
-                if allow_several==True, a list of dictionaries with the row or rows, error if no item is found
-        '''
-
-        if error_item_text==None:
-            error_item_text = table
-        what = 'uuid' if utils.check_valid_uuid(uuid_name) else 'name'
-        cmd =  " SELECT * FROM %s WHERE %s='%s'" % (table, what, uuid_name)
-        if WHERE_OR:
-            where_or =  " OR ".join(map(self.__tuple2db_format_where, WHERE_OR.iteritems() ))
-            if WHERE_AND_OR == "AND":
-                cmd += " AND (" + where_or + ")"
-            else:
-                cmd += " OR " + where_or
-
-        
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    print cmd
-                    self.cur.execute(cmd)
-                    number = self.cur.rowcount
-                    if number==0:
-                        return -HTTP_Not_Found, "No %s found with %s '%s'" %(error_item_text, what, uuid_name)
-                    elif number>1 and not allow_serveral: 
-                        return -HTTP_Bad_Request, "More than one %s found with %s '%s'" %(error_item_text, what, uuid_name)
-                    if allow_serveral:
-                        rows = self.cur.fetchall()
-                    else:
-                        rows = self.cur.fetchone()
-                    return number, rows
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_table_by_uuid_name DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
-
-    def get_uuid(self, uuid):
-        '''check in the database if this uuid is already present'''
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    self.cur.execute("SELECT * FROM uuids where uuid='" + str(uuid) + "'")
-                    rows = self.cur.fetchall()
-                    return self.cur.rowcount, rows
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_uuid DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
 
     def new_vnf_as_a_whole(self,nfvo_tenant,vnf_name,vnf_descriptor,VNFCDict):
-        print "Adding new vnf to the NFVO database"
-        for retry_ in range(0,2):
+        self.logger.debug("Adding new vnf to the NFVO database")
+        tries = 2
+        while tries:
             created_time = time.time()
             try:
                 with self.con:
@@ -575,27 +61,19 @@ class nfvo_db():
                     myVNFDict["class"] = vnf_descriptor['vnf'].get('class',"MISC")
                     myVNFDict["tenant_id"] = vnf_descriptor['vnf'].get("tenant_id")
                     
-                    result, vnf_id = self._new_vnf(myVNFDict,nfvo_tenant,created_time)
-                    if result < 0:
-                        return result, "Error creating vnf in NFVO database: %s" %vnf_id
-                        
-                    print "VNF %s added to NFVO DB. VNF id: %s" % (vnf_name,vnf_id)
-                    
-                    print "Adding new vms to the NFVO database"
+                    vnf_id = self._new_row_internal('vnfs', myVNFDict, add_uuid=True, root_uuid=None, created_time=created_time)
+                    #print "Adding new vms to the NFVO database"
                     #For each vm, we must create the appropriate vm in the NFVO database.
                     vmDict = {}
                     for _,vm in VNFCDict.iteritems():
                         #This code could make the name of the vms grow and grow.
                         #If we agree to follow this convention, we should check with a regex that the vnfc name is not including yet the vnf name  
                         #vm['name'] = "%s-%s" % (vnf_name,vm['name'])
-                        print "VM name: %s. Description: %s" % (vm['name'], vm['description'])
+                        #print "VM name: %s. Description: %s" % (vm['name'], vm['description'])
                         vm["vnf_id"] = vnf_id
                         created_time += 0.00001
-                        result, vm_id = self._new_vm(vm,nfvo_tenant,vnf_id,created_time)
-                        if result < 0:
-                            return result, "Error creating vm in NFVO database: %s" %vm_id
-                        
-                        print "Internal vm id in NFVO DB: %s" % vm_id
+                        vm_id = self._new_row_internal('vms', vm, add_uuid=True, root_uuid=vnf_id, created_time=created_time) 
+                        #print "Internal vm id in NFVO DB: %s" % vm_id
                         vmDict[vm['name']] = vm_id
                 
                     #Collect the data interfaces of each VM/VNFC under the 'numas' field
@@ -604,7 +82,7 @@ class nfvo_db():
                         dataifacesDict[vm['name']] = {}
                         for numa in vm.get('numas', []):
                             for dataiface in numa.get('interfaces',[]):
-                                utils.convert_bandwidth(dataiface)
+                                db_base._convert_bandwidth(dataiface)
                                 dataifacesDict[vm['name']][dataiface['name']] = {}
                                 dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface['vpci']
                                 dataifacesDict[vm['name']][dataiface['name']]['bw'] = dataiface['bandwidth']
@@ -616,7 +94,7 @@ class nfvo_db():
                         if 'bridge-ifaces' in  vm:
                             bridgeInterfacesDict[vm['name']] = {}
                             for bridgeiface in vm['bridge-ifaces']:
-                                utils.convert_bandwidth(bridgeiface)
+                                db_base._convert_bandwidth(bridgeiface)
                                 bridgeInterfacesDict[vm['name']][bridgeiface['name']] = {}
                                 bridgeInterfacesDict[vm['name']][bridgeiface['name']]['vpci'] = bridgeiface.get('vpci',None)
                                 bridgeInterfacesDict[vm['name']][bridgeiface['name']]['mac'] = bridgeiface.get('mac_address',None)
@@ -624,12 +102,11 @@ class nfvo_db():
                                 bridgeInterfacesDict[vm['name']][bridgeiface['name']]['model'] = bridgeiface.get('model', None)
                     
                     #For each internal connection, we add it to the interfaceDict and we  create the appropriate net in the NFVO database.
-                    print "Adding new nets (VNF internal nets) to the NFVO database (if any)"
+                    #print "Adding new nets (VNF internal nets) to the NFVO database (if any)"
                     internalconnList = []
                     if 'internal-connections' in vnf_descriptor['vnf']:
                         for net in vnf_descriptor['vnf']['internal-connections']:
-                            print "CODE TO BE CHECKED"
-                            print "Net name: %s. Description: %s" % (net['name'], net['description'])
+                            #print "Net name: %s. Description: %s" % (net['name'], net['description'])
                             
                             myNetDict = {}
                             myNetDict["name"] = net['name']
@@ -638,9 +115,7 @@ class nfvo_db():
                             myNetDict["vnf_id"] = vnf_id
                             
                             created_time += 0.00001
-                            result, net_id = self._new_net(myNetDict,nfvo_tenant,vnf_id, created_time)
-                            if result < 0:
-                                return result, "Error creating net in NFVO database: %s" %net_id
+                            net_id = self._new_row_internal('nets', myNetDict, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
                                 
                             for element in net['elements']:
                                 ifaceItem = {}
@@ -660,19 +135,16 @@ class nfvo_db():
                                     ifaceItem["bw"] =    bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['bw']
                                     ifaceItem["model"] = bridgeInterfacesDict[ element['VNFC'] ][ element['local_iface_name'] ]['model']
                                 internalconnList.append(ifaceItem)
-                            
-                            print "Internal net id in NFVO DB: %s" % net_id
+                            #print "Internal net id in NFVO DB: %s" % net_id
                     
-                    print "Adding internal interfaces to the NFVO database (if any)"
+                    #print "Adding internal interfaces to the NFVO database (if any)"
                     for iface in internalconnList:
                         print "Iface name: %s" % iface['internal_name']
                         created_time += 0.00001
-                        result, iface_id = self._new_interface(iface,nfvo_tenant,vnf_id,created_time)
-                        if result < 0:
-                            return result, "Error creating iface in NFVO database: %s" %iface_id
-                        print "Iface id in NFVO DB: %s" % iface_id
+                        iface_id = self._new_row_internal('interfaces', iface, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
+                        #print "Iface id in NFVO DB: %s" % iface_id
                     
-                    print "Adding external interfaces to the NFVO database"
+                    #print "Adding external interfaces to the NFVO database"
                     for iface in vnf_descriptor['vnf']['external-connections']:
                         myIfaceDict = {}
                         #myIfaceDict["internal_name"] = "%s-%s-%s" % (vnf_name,iface['VNFC'], iface['local_iface_name'])  
@@ -692,37 +164,19 @@ class nfvo_db():
                             myIfaceDict["mac"] = bridgeInterfacesDict[ iface['VNFC'] ][ iface['local_iface_name'] ]['mac']
                         print "Iface name: %s" % iface['name']
                         created_time += 0.00001
-                        result, iface_id = self._new_interface(myIfaceDict,nfvo_tenant,vnf_id,created_time)
-                        if result < 0:
-                            return result, "Error creating iface in NFVO database: %s" %iface_id
-                        print "Iface id in NFVO DB: %s" % iface_id
+                        iface_id = self._new_row_internal('interfaces', myIfaceDict, add_uuid=True, root_uuid=vnf_id, created_time=created_time)
+                        #print "Iface id in NFVO DB: %s" % iface_id
                     
-                    return 1,vnf_id
+                    return vnf_id
                 
-            except (mdb.Error, AttributeError), e:
-                print "new_vnf_as_a_whole DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
         
-    def _new_vnf(self, vnf_dict, tenant_id, created_time=0):
-        #return self.new_row('vnfs', vnf_dict, None, tenant_id, True, True)
-        return self._new_row_internal('vnfs', vnf_dict, tenant_id, add_uuid=True, root_uuid=None, log=True, created_time=created_time)
-
-    def _new_vm(self, vm_dict, tenant_id, vnf_id = None, created_time=0):
-        #return self.new_row('vms', vm_dict, tenant_id, True, True)
-        return self._new_row_internal('vms', vm_dict, tenant_id, add_uuid=True, root_uuid=vnf_id, log=True, created_time=created_time)
-
-
-    def _new_net(self, net_dict, tenant_id, vnf_id = None, created_time=0):
-        #return self.new_row('nets', net_dict, tenant_id, True, True)
-        return self._new_row_internal('nets', net_dict, tenant_id, add_uuid=True, root_uuid=vnf_id, log=True, created_time=created_time)
-    
-    def _new_interface(self, interface_dict, tenant_id, vnf_id = None, created_time=0):
-        #return self.new_row('interfaces', interface_dict, tenant_id, True, True)
-        return self._new_row_internal('interfaces', interface_dict, tenant_id, add_uuid=True, root_uuid=vnf_id, log=True, created_time=created_time)
 
     def new_scenario(self, scenario_dict):
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             created_time = time.time()
             try:
                 with self.con:
@@ -730,14 +184,11 @@ class nfvo_db():
                     tenant_id = scenario_dict.get('tenant_id')
                     #scenario
                     INSERT_={'tenant_id': tenant_id,
-                    'name': scenario_dict['name'],
-                    'description': scenario_dict['description'],
-                    'public': scenario_dict.get('public', "false")}
+                             'name': scenario_dict['name'],
+                             'description': scenario_dict['description'],
+                             'public': scenario_dict.get('public', "false")}
                     
-                    r,scenario_uuid =  self._new_row_internal('scenarios', INSERT_, tenant_id, True, None, True,created_time)
-                    if r<0:
-                        print 'nfvo_db.new_scenario Error inserting at table scenarios: ' + scenario_uuid
-                        return r,scenario_uuid
+                    scenario_uuid =  self._new_row_internal('scenarios', INSERT_, add_uuid=True, root_uuid=None, created_time=created_time)
                     #sce_nets
                     for net in scenario_dict['nets'].values():
                         net_dict={'scenario_id': scenario_uuid}
@@ -750,10 +201,7 @@ class nfvo_db():
                             #TODO, must be json because of the GUI, change to yaml
                             net_dict["graph"]=json.dumps(net["graph"])
                         created_time += 0.00001
-                        r,net_uuid =  self._new_row_internal('sce_nets', net_dict, tenant_id, True, None, True, created_time)
-                        if r<0:
-                            print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + net_uuid
-                            return r, net_uuid
+                        net_uuid =  self._new_row_internal('sce_nets', net_dict, add_uuid=True, root_uuid=scenario_uuid, created_time=created_time)
                         net['uuid']=net_uuid
                     #sce_vnfs
                     for k,vnf in scenario_dict['vnfs'].items():
@@ -768,14 +216,11 @@ class nfvo_db():
                             #TODO, must be json because of the GUI, change to yaml
                             INSERT_["graph"]=json.dumps(vnf["graph"])
                         created_time += 0.00001
-                        r,scn_vnf_uuid =  self._new_row_internal('sce_vnfs', INSERT_, tenant_id, True, scenario_uuid, True, created_time)
-                        if r<0:
-                            print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + scn_vnf_uuid
-                            return r, scn_vnf_uuid
+                        scn_vnf_uuid =  self._new_row_internal('sce_vnfs', INSERT_, add_uuid=True, root_uuid=scenario_uuid, created_time=created_time)
                         vnf['scn_vnf_uuid']=scn_vnf_uuid
                         #sce_interfaces
                         for iface in vnf['ifaces'].values():
-                            print 'iface', iface
+                            #print 'iface', iface
                             if 'net_key' not in iface:
                                 continue
                             iface['net_id'] = scenario_dict['nets'][ iface['net_key'] ]['uuid']
@@ -784,21 +229,19 @@ class nfvo_db():
                                 'interface_id':  iface[ 'uuid' ]
                             }
                             created_time += 0.00001
-                            r,iface_uuid =  self._new_row_internal('sce_interfaces', INSERT_, tenant_id, True, scenario_uuid, True, created_time)
-                            if r<0:
-                                print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + iface_uuid
-                                return r, iface_uuid
+                            iface_uuid =  self._new_row_internal('sce_interfaces', INSERT_, add_uuid=True, root_uuid=scenario_uuid, created_time=created_time)
                             
-                    return 1, scenario_uuid
+                    return scenario_uuid
                     
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.new_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
 
     def edit_scenario(self, scenario_dict):
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             modified_time = time.time()
+            item_changed=0
             try:
                 with self.con:
                     self.cur = self.con.cursor()
@@ -806,15 +249,17 @@ class nfvo_db():
                     tenant_id = scenario_dict.get('tenant_id')
                     scenario_uuid = scenario_dict['uuid']
                     
-                    where_text = "uuid='%s'" % scenario_uuid
+                    where_text = "uuid='{}'".format(scenario_uuid)
                     if not tenant_id and tenant_id != "any":
-                        where_text += " AND (tenant_id='%s' OR public='True')" % (tenant_id)
-                    self.cur.execute("SELECT * FROM scenarios WHERE "+ where_text)
+                        where_text += " AND (tenant_id='{}' OR public='True')".format(tenant_id)
+                    cmd = "SELECT * FROM scenarios WHERE "+ where_text
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
                     self.cur.fetchall()
                     if self.cur.rowcount==0:
-                        return -HTTP_Bad_Request, "No scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("No scenario found with this criteria " + where_text, db_base.HTTP_Bad_Request)
                     elif self.cur.rowcount>1:
-                        return -HTTP_Bad_Request, "More than one scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("More than one scenario found with this criteria " + where_text, db_base.HTTP_Bad_Request)
 
                     #scenario
                     nodes = {}
@@ -826,10 +271,7 @@ class nfvo_db():
                     if "description" in scenario_dict: UPDATE_["description"] = scenario_dict["description"]
                     if len(UPDATE_)>0:
                         WHERE_={'tenant_id': tenant_id, 'uuid': scenario_uuid}
-                        r,c =  self.__update_rows('scenarios', UPDATE_, WHERE_, modified_time=modified_time)
-                        if r<0:
-                            print 'nfvo_db.edit_scenario Error ' + c + ' updating table scenarios: ' + scenario_uuid
-                            return r,scenario_uuid
+                        item_changed += self._update_rows('scenarios', UPDATE_, WHERE_, modified_time=modified_time)
                     #sce_nets
                     for node_id, node in nodes.items():
                         if "graph" in node:
@@ -837,18 +279,14 @@ class nfvo_db():
                             #TODO, must be json because of the GUI, change to yaml
                             node["graph"] = json.dumps(node["graph"])
                         WHERE_={'scenario_id': scenario_uuid, 'uuid': node_id}
-                        r,c =  self.__update_rows('sce_nets', node, WHERE_)
-                        if r<=0:
-                            r,c =  self.__update_rows('sce_vnfs', node, WHERE_, modified_time=modified_time)
-                            if r<0:
-                                print 'nfvo_db.edit_scenario Error updating table sce_nets,sce_vnfs: ' + scenario_uuid
-                                return r, scenario_uuid
-                    return 1, scenario_uuid
+                        #Try to change at sce_nets(version 0 API backward compatibility and sce_vnfs)
+                        item_changed += self._update_rows('sce_nets', node, WHERE_)
+                        item_changed += self._update_rows('sce_vnfs', node, WHERE_, modified_time=modified_time)
+                    return item_changed
                     
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.new_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
 
 #     def get_instance_scenario(self, instance_scenario_id, tenant_id=None):
 #         '''Obtain the scenario instance information, filtering by one or serveral of the tenant, uuid or name
@@ -862,7 +300,7 @@ class nfvo_db():
 #                 #scenario table
 #                 where_list=[]
 #                 if tenant_id is not None: where_list.append( "tenant_id='" + tenant_id +"'" )
-#                 if utils.check_valid_uuid(instance_scenario_id):
+#                 if db_base._check_valid_uuid(instance_scenario_id):
 #                     where_list.append( "uuid='" + instance_scenario_id +"'" )
 #                 else:
 #                     where_list.append( "name='" + instance_scenario_id +"'" )
@@ -893,13 +331,13 @@ class nfvo_db():
 #                 self.cur.execute("SELECT uuid, vim_interface_id, instance_vm_id, instance_net_id FROM instance_interfaces WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
 #                 instance_scenario_dict['instance_interfaces'] = self.cur.fetchall()
 #                 
-#                 utils.convert_datetime2str(instance_scenario_dict)
-#                 utils.convert_str2boolean(instance_scenario_dict, ('public','shared','external') )
+#                 db_base._convert_datetime2str(instance_scenario_dict)
+#                 db_base._convert_str2boolean(instance_scenario_dict, ('public','shared','external') )
 #                 print "2******************************************************************"
 #                 return 1, instance_scenario_dict
-#         except (mdb.Error, AttributeError), e:
+#         except (mdb.Error, AttributeError) as e:
 #             print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-#             return self.format_error(e)
+#             return self._format_error(e)
 
     def get_scenario(self, scenario_id, tenant_id=None, datacenter_id=None):
         '''Obtain the scenario information, filtering by one or serveral of the tenant, uuid or name
@@ -907,34 +345,32 @@ class nfvo_db():
         if datacenter_id is provided, it supply aditional vim_id fields with the matching vim uuid 
         Only one scenario must mutch the filtering or an error is returned
         ''' 
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             try:
                 with self.con:
                     self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    #scenario table
-                    if utils.check_valid_uuid(scenario_id):
-                        where_text = "uuid='%s'" % scenario_id
-                    else:
-                        where_text = "name='%s'" % scenario_id
+                    where_text = "uuid='{}'".format(scenario_id)
                     if not tenant_id and tenant_id != "any":
-                        where_text += " AND (tenant_id='%s' OR public='True')" % (tenant_id)
-                    cmd = "SELECT * FROM scenarios WHERE "+ where_text
-                    print cmd
+                        where_text += " AND (tenant_id='{}' OR public='True')".format(tenant_id)
+                    cmd = "SELECT * FROM scenarios WHERE " + where_text
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     rows = self.cur.fetchall()
                     if self.cur.rowcount==0:
-                        return -HTTP_Bad_Request, "No scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("No scenario found with this criteria " + where_text, db_base.HTTP_Bad_Request)
                     elif self.cur.rowcount>1:
-                        return -HTTP_Bad_Request, "More than one scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("More than one scenario found with this criteria " + where_text, db_base.HTTP_Bad_Request)
                     scenario_dict = rows[0]
-                    
                     #sce_vnfs
-                    cmd = "SELECT uuid,name,vnf_id,description FROM sce_vnfs WHERE scenario_id='%s' ORDER BY created_at" % scenario_dict['uuid']
+                    cmd = "SELECT uuid,name,vnf_id,description FROM sce_vnfs WHERE scenario_id='{}' ORDER BY created_at".format(scenario_dict['uuid'])
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     scenario_dict['vnfs'] = self.cur.fetchall()
                     for vnf in scenario_dict['vnfs']:
                         #sce_interfaces
-                        cmd = "SELECT uuid,sce_net_id,interface_id FROM sce_interfaces WHERE sce_vnf_id='%s' ORDER BY created_at" %vnf['uuid']
+                        cmd = "SELECT uuid,sce_net_id,interface_id FROM sce_interfaces WHERE sce_vnf_id='{}' ORDER BY created_at".format(vnf['uuid'])
+                        self.logger.debug(cmd)
                         self.cur.execute(cmd)
                         vnf['interfaces'] = self.cur.fetchall()
                         #vms
@@ -942,15 +378,20 @@ class nfvo_db():
                                 " FROM vnfs join vms on vnfs.uuid=vms.vnf_id " \
                                 " WHERE vnfs.uuid='" + vnf['vnf_id'] +"'"  \
                                 " ORDER BY vms.created_at"
+                        self.logger.debug(cmd)
                         self.cur.execute(cmd)
                         vnf['vms'] = self.cur.fetchall()
                         for vm in vnf['vms']:
                             if datacenter_id!=None:
-                                self.cur.execute("SELECT vim_id FROM datacenters_images WHERE image_id='%s' AND datacenter_id='%s'" %(vm['image_id'],datacenter_id)) 
+                                cmd = "SELECT vim_id FROM datacenters_images WHERE image_id='{}' AND datacenter_id='{}'".format(vm['image_id'],datacenter_id)
+                                self.logger.debug(cmd)
+                                self.cur.execute(cmd) 
                                 if self.cur.rowcount==1:
                                     vim_image_dict = self.cur.fetchone()
                                     vm['vim_image_id']=vim_image_dict['vim_id']
-                                self.cur.execute("SELECT vim_id FROM datacenters_flavors WHERE flavor_id='%s' AND datacenter_id='%s'" %(vm['flavor_id'],datacenter_id)) 
+                                cmd = "SELECT vim_id FROM datacenters_flavors WHERE flavor_id='{}' AND datacenter_id='{}'".format(vm['flavor_id'],datacenter_id)
+                                self.logger.debug(cmd)
+                                self.cur.execute(cmd) 
                                 if self.cur.rowcount==1:
                                     vim_flavor_dict = self.cur.fetchone()
                                     vm['vim_flavor_id']=vim_flavor_dict['vim_id']
@@ -958,27 +399,33 @@ class nfvo_db():
                             #interfaces
                             cmd = "SELECT uuid,internal_name,external_name,net_id,type,vpci,mac,bw,model" \
                                     " FROM interfaces" \
-                                    " WHERE vm_id='%s'" \
-                                    " ORDER BY created_at" %   vm['uuid']
+                                    " WHERE vm_id='{}'" \
+                                    " ORDER BY created_at".format(vm['uuid'])
+                            self.logger.debug(cmd)
                             self.cur.execute(cmd)
                             vm['interfaces'] = self.cur.fetchall()
                         #nets    every net of a vms
-                        self.cur.execute("SELECT uuid,name,type,description FROM nets WHERE vnf_id='" + vnf['vnf_id'] +"'"  )
+                        cmd = "SELECT uuid,name,type,description FROM nets WHERE vnf_id='{}'".format(vnf['vnf_id'])  
+                        self.logger.debug(cmd)
+                        self.cur.execute(cmd)
                         vnf['nets'] = self.cur.fetchall()
                     #sce_nets
                     cmd = "SELECT uuid,name,type,external,description" \
-                          " FROM sce_nets  WHERE scenario_id='%s'" \
-                          " ORDER BY created_at " % scenario_dict['uuid']
+                          " FROM sce_nets  WHERE scenario_id='{}'" \
+                          " ORDER BY created_at ".format(scenario_dict['uuid'])
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     scenario_dict['nets'] = self.cur.fetchall()
                     #datacenter_nets
                     for net in scenario_dict['nets']:
                         if str(net['external']) == 'false':
                             continue
-                        WHERE_=" WHERE name='%s'" % net['name']
+                        WHERE_=" WHERE name='{}'".format(net['name'])
                         if datacenter_id!=None:
-                            WHERE_ += " AND datacenter_id='%s'" % datacenter_id
-                        self.cur.execute("SELECT vim_net_id FROM datacenter_nets" + WHERE_ ) 
+                            WHERE_ += " AND datacenter_id='{}'".format(datacenter_id)
+                        cmd = "SELECT vim_net_id FROM datacenter_nets" + WHERE_
+                        self.logger.debug(cmd)
+                        self.cur.execute(cmd) 
                         d_net = self.cur.fetchone()
                         if d_net==None or datacenter_id==None:
                             #print "nfvo_db.get_scenario() WARNING external net %s not found"  % net['name']
@@ -986,72 +433,53 @@ class nfvo_db():
                         else:
                             net['vim_id']=d_net['vim_net_id']
                     
-                    utils.convert_datetime2str(scenario_dict)
-                    utils.convert_str2boolean(scenario_dict, ('public','shared','external') )
-                    return 1, scenario_dict
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                    db_base._convert_datetime2str(scenario_dict)
+                    db_base._convert_str2boolean(scenario_dict, ('public','shared','external') )
+                    return scenario_dict
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
 
-    def get_uuid_from_name(self, table, name):
-        '''Searchs in table the name and returns the uuid
-        ''' 
-        for retry_ in range(0,2):
-            try:
-                with self.con:
-                    self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                    where_text = "name='" + name +"'"
-                    self.cur.execute("SELECT * FROM " + table + " WHERE "+ where_text)
-                    rows = self.cur.fetchall()
-                    if self.cur.rowcount==0:
-                        return 0, "Name %s not found in table %s" %(name, table)
-                    elif self.cur.rowcount>1:
-                        return self.cur.rowcount, "More than one VNF with name %s found in table %s" %(name, table)
-                    return self.cur.rowcount, rows[0]["uuid"]
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_uuid_from_name DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
 
     def delete_scenario(self, scenario_id, tenant_id=None):
         '''Deletes a scenario, filtering by one or several of the tenant, uuid or name
         scenario_id is the uuid or the name if it is not a valid uuid format
         Only one scenario must mutch the filtering or an error is returned
         ''' 
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             try:
                 with self.con:
                     self.cur = self.con.cursor(mdb.cursors.DictCursor)
     
                     #scenario table
-                    if utils.check_valid_uuid(scenario_id):
-                        where_text = "uuid='%s'" % scenario_id
-                    else:
-                        where_text = "name='%s'" % scenario_id
+                    where_text = "uuid='{}'".format(scenario_id)
                     if not tenant_id and tenant_id != "any":
-                        where_text += " AND (tenant_id='%s' OR public='True')" % tenant_id
-                    self.cur.execute("SELECT * FROM scenarios WHERE "+ where_text)
+                        where_text += " AND (tenant_id='{}' OR public='True')".format(tenant_id)
+                    cmd = "SELECT * FROM scenarios WHERE "+ where_text
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
                     rows = self.cur.fetchall()
                     if self.cur.rowcount==0:
-                        return -HTTP_Bad_Request, "No scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("No scenario found where " + where_text, db_base.HTTP_Bad_Request)
                     elif self.cur.rowcount>1:
-                        return -HTTP_Bad_Request, "More than one scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("More than one scenario found where " + where_text, db_base.HTTP_Bad_Request)
                     scenario_uuid = rows[0]["uuid"]
                     scenario_name = rows[0]["name"]
                     
                     #sce_vnfs
-                    self.cur.execute("DELETE FROM scenarios WHERE uuid='" + scenario_uuid + "'")
+                    cmd = "DELETE FROM scenarios WHERE uuid='{}'".format(scenario_uuid)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
     
-                    return 1, scenario_uuid + " " + scenario_name
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.delete_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c =  self.format_error(e, "delete", "instances running")
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                    return scenario_uuid + " " + scenario_name
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries, "delete", "instances running")
+            tries -= 1
 
     def new_instance_scenario_as_a_whole(self,tenant_id,instance_scenario_name,instance_scenario_description,scenarioDict):
-        print "Adding new instance scenario to the NFVO database"
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             created_time = time.time()
             try:
                 with self.con:
@@ -1066,10 +494,7 @@ class nfvo_db():
                         'scenario_id' : scenarioDict['uuid'],
                         'datacenter_id': datacenter_id
                     }
-                    r,instance_uuid =  self._new_row_internal('instance_scenarios', INSERT_, tenant_id, True, None, True, created_time)
-                    if r<0:
-                        print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_scenarios: ' + instance_uuid
-                        return r, instance_uuid                
+                    instance_uuid = self._new_row_internal('instance_scenarios', INSERT_, add_uuid=True, root_uuid=None, created_time=created_time)
                     
                     net_scene2instance={}
                     #instance_nets   #nets interVNF
@@ -1080,10 +505,7 @@ class nfvo_db():
                         if net.get("uuid"):
                             INSERT_['sce_net_id'] = net['uuid']
                         created_time += 0.00001
-                        r,instance_net_uuid =  self._new_row_internal('instance_nets', INSERT_, tenant_id, True, instance_uuid, True, created_time)
-                        if r<0:
-                            print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
-                            return r, instance_net_uuid                
+                        instance_net_uuid =  self._new_row_internal('instance_nets', INSERT_, True, instance_uuid, created_time)
                         net_scene2instance[ net['uuid'] ] = instance_net_uuid
                         net['uuid'] = instance_net_uuid  #overwrite scnario uuid by instance uuid
                     
@@ -1095,10 +517,7 @@ class nfvo_db():
                         if vnf.get("uuid"):
                             INSERT_['sce_vnf_id'] = vnf['uuid']
                         created_time += 0.00001
-                        r,instance_vnf_uuid =  self._new_row_internal('instance_vnfs', INSERT_, tenant_id, True, instance_uuid, True,created_time)
-                        if r<0:
-                            print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vnfs: ' + instance_vnf_uuid
-                            return r, instance_vnf_uuid                
+                        instance_vnf_uuid =  self._new_row_internal('instance_vnfs', INSERT_, True, instance_uuid, created_time)
                         vnf['uuid'] = instance_vnf_uuid  #overwrite scnario uuid by instance uuid
                         
                         #instance_nets   #nets intraVNF
@@ -1109,10 +528,7 @@ class nfvo_db():
                             if net.get("uuid"):
                                 INSERT_['net_id'] = net['uuid']
                             created_time += 0.00001
-                            r,instance_net_uuid =  self._new_row_internal('instance_nets', INSERT_, tenant_id, True, instance_uuid, True,created_time)
-                            if r<0:
-                                print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
-                                return r, instance_net_uuid                
+                            instance_net_uuid =  self._new_row_internal('instance_nets', INSERT_, True, instance_uuid, created_time)
                             net_scene2instance[ net['uuid'] ] = instance_net_uuid
                             net['uuid'] = instance_net_uuid  #overwrite scnario uuid by instance uuid
                         
@@ -1120,10 +536,7 @@ class nfvo_db():
                         for vm in vnf['vms']:
                             INSERT_={'instance_vnf_id': instance_vnf_uuid,  'vm_id': vm['uuid'], 'vim_vm_id': vm['vim_id']  }
                             created_time += 0.00001
-                            r,instance_vm_uuid =  self._new_row_internal('instance_vms', INSERT_, tenant_id, True, instance_uuid, True, created_time)
-                            if r<0:
-                                print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vms: ' + instance_vm_uuid
-                                return r, instance_vm_uuid                
+                            instance_vm_uuid =  self._new_row_internal('instance_vms', INSERT_, True, instance_uuid, created_time)
                             vm['uuid'] = instance_vm_uuid  #overwrite scnario uuid by instance uuid
                             
                             #instance_interfaces
@@ -1141,56 +554,52 @@ class nfvo_db():
                                 INSERT_={'instance_vm_id': instance_vm_uuid,  'instance_net_id': net_scene2instance[net_id],
                                     'interface_id': interface['uuid'], 'vim_interface_id': interface.get('vim_id'), 'type':  interface_type  }
                                 #created_time += 0.00001
-                                r,interface_uuid =  self._new_row_internal('instance_interfaces', INSERT_, tenant_id, True, instance_uuid, True) #, created_time)
-                                if r<0:
-                                    print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_interfaces: ' + interface_uuid
-                                    return r, interface_uuid                
+                                interface_uuid =  self._new_row_internal('instance_interfaces', INSERT_, True, instance_uuid) #, created_time)
                                 interface['uuid'] = interface_uuid  #overwrite scnario uuid by instance uuid
-                        
-    
-                
-                return 1, instance_uuid
-                
-            except (mdb.Error, AttributeError), e:
-                print "new_instance_scenario_as_a_whole DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                return instance_uuid
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
 
     def get_instance_scenario(self, instance_id, tenant_id=None, verbose=False):
         '''Obtain the instance information, filtering by one or several of the tenant, uuid or name
         instance_id is the uuid or the name if it is not a valid uuid format
         Only one instance must mutch the filtering or an error is returned
         ''' 
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             try:
                 with self.con:
                     self.cur = self.con.cursor(mdb.cursors.DictCursor)
                     #instance table
                     where_list=[]
                     if tenant_id is not None: where_list.append( "inst.tenant_id='" + tenant_id +"'" )
-                    if utils.check_valid_uuid(instance_id):
+                    if db_base._check_valid_uuid(instance_id):
                         where_list.append( "inst.uuid='" + instance_id +"'" )
                     else:
                         where_list.append( "inst.name='" + instance_id +"'" )
                     where_text = " AND ".join(where_list)
-                    command = "SELECT inst.uuid as uuid,inst.name as name,inst.scenario_id as scenario_id, datacenter_id" +\
+                    cmd = "SELECT inst.uuid as uuid,inst.name as name,inst.scenario_id as scenario_id, datacenter_id" +\
                                 " ,datacenter_tenant_id, s.name as scenario_name,inst.tenant_id as tenant_id" + \
                                 " ,inst.description as description,inst.created_at as created_at" +\
                             " FROM instance_scenarios as inst join scenarios as s on inst.scenario_id=s.uuid"+\
                             " WHERE " + where_text
-                    self.cur.execute(command)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
                     rows = self.cur.fetchall()
+                    
                     if self.cur.rowcount==0:
-                        return -HTTP_Bad_Request, "No instance found with this criteria " + where_text
+                        raise db_base.db_base_Exception("No instance found where " + where_text, db_base.HTTP_Not_Found)
                     elif self.cur.rowcount>1:
-                        return -HTTP_Bad_Request, "More than one instance found with this criteria " + where_text
+                        raise db_base.db_base_Exception("More than one instance found where " + where_text, db_base.HTTP_Bad_Request)
                     instance_dict = rows[0]
                     
                     #instance_vnfs
                     cmd = "SELECT iv.uuid as uuid,sv.vnf_id as vnf_id,sv.name as vnf_name, sce_vnf_id, datacenter_id, datacenter_tenant_id"\
                             " FROM instance_vnfs as iv join sce_vnfs as sv on iv.sce_vnf_id=sv.uuid" \
-                            " WHERE iv.instance_scenario_id='%s'" \
-                            " ORDER BY iv.created_at " % instance_dict['uuid']
+                            " WHERE iv.instance_scenario_id='{}'" \
+                            " ORDER BY iv.created_at ".format(instance_dict['uuid'])
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     instance_dict['vnfs'] = self.cur.fetchall()
                     for vnf in instance_dict['vnfs']:
@@ -1198,7 +607,8 @@ class nfvo_db():
                         #instance vms
                         cmd = "SELECT iv.uuid as uuid, vim_vm_id, status, error_msg, vim_info, iv.created_at as created_at, name "\
                                 " FROM instance_vms as iv join vms on iv.vm_id=vms.uuid "\
-                                " WHERE instance_vnf_id='%s' ORDER BY iv.created_at" % vnf['uuid']
+                                " WHERE instance_vnf_id='{}' ORDER BY iv.created_at".format(vnf['uuid'])
+                        self.logger.debug(cmd)
                         self.cur.execute(cmd)
                         vnf['vms'] = self.cur.fetchall()
                         for vm in vnf['vms']:
@@ -1206,7 +616,8 @@ class nfvo_db():
                             #instance_interfaces
                             cmd = "SELECT vim_interface_id, instance_net_id, internal_name,external_name, mac_address, ip_address, vim_info, i.type as type "\
                                     " FROM instance_interfaces as ii join interfaces as i on ii.interface_id=i.uuid "\
-                                    " WHERE instance_vm_id='%s' ORDER BY created_at" % vm['uuid']
+                                    " WHERE instance_vm_id='{}' ORDER BY created_at".format(vm['uuid'])
+                            self.logger.debug(cmd)
                             self.cur.execute(cmd )
                             vm['interfaces'] = self.cur.fetchall()
                             for iface in vm['interfaces']:
@@ -1225,24 +636,25 @@ class nfvo_db():
                     #where_text = "instance_nets.instance_scenario_id='"+ instance_dict['uuid'] + "'"
                     cmd = "SELECT uuid,vim_net_id,status,error_msg,vim_info,external, sce_net_id, net_id as vnf_net_id, datacenter_id, datacenter_tenant_id"\
                             " FROM instance_nets" \
-                            " WHERE instance_scenario_id='%s' ORDER BY created_at" % instance_dict['uuid']
+                            " WHERE instance_scenario_id='{}' ORDER BY created_at".format(instance_dict['uuid'])
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     instance_dict['nets'] = self.cur.fetchall()
                     
-                    utils.convert_datetime2str(instance_dict)
-                    utils.convert_str2boolean(instance_dict, ('public','shared','external') )
-                    return 1, instance_dict
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                    db_base._convert_datetime2str(instance_dict)
+                    db_base._convert_str2boolean(instance_dict, ('public','shared','external') )
+                    return instance_dict
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
         
     def delete_instance_scenario(self, instance_id, tenant_id=None):
         '''Deletes a instance_Scenario, filtering by one or serveral of the tenant, uuid or name
         instance_id is the uuid or the name if it is not a valid uuid format
         Only one instance_scenario must mutch the filtering or an error is returned
         ''' 
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             try:
                 with self.con:
                     self.cur = self.con.cursor(mdb.cursors.DictCursor)
@@ -1250,28 +662,32 @@ class nfvo_db():
                     #instance table
                     where_list=[]
                     if tenant_id is not None: where_list.append( "tenant_id='" + tenant_id +"'" )
-                    if utils.check_valid_uuid(instance_id):
+                    if db_base._check_valid_uuid(instance_id):
                         where_list.append( "uuid='" + instance_id +"'" )
                     else:
                         where_list.append( "name='" + instance_id +"'" )
                     where_text = " AND ".join(where_list)
-                    self.cur.execute("SELECT * FROM instance_scenarios WHERE "+ where_text)
+                    cmd = "SELECT * FROM instance_scenarios WHERE "+ where_text
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
                     rows = self.cur.fetchall()
+                    
                     if self.cur.rowcount==0:
-                        return -HTTP_Bad_Request, "No instance scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("No instance found where " + where_text, db_base.HTTP_Bad_Request)
                     elif self.cur.rowcount>1:
-                        return -HTTP_Bad_Request, "More than one instance scenario found with this criteria " + where_text
+                        raise db_base.db_base_Exception("More than one instance found where " + where_text, db_base.HTTP_Bad_Request)
                     instance_uuid = rows[0]["uuid"]
                     instance_name = rows[0]["name"]
                     
                     #sce_vnfs
-                    self.cur.execute("DELETE FROM instance_scenarios WHERE uuid='" + instance_uuid + "'")
+                    cmd = "DELETE FROM instance_scenarios WHERE uuid='{}'".format(instance_uuid)
+                    self.logger.debug(cmd)
+                    self.cur.execute(cmd)
     
-                    return 1, instance_uuid + " " + instance_name
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.delete_instance_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e, "delete", "No dependences can avoid deleting!!!!")
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                    return instance_uuid + " " + instance_name
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries, "delete", "No dependences can avoid deleting!!!!")
+            tries -= 1
     
     def new_instance_scenario(self, instance_scenario_dict, tenant_id):
         #return self.new_row('vnfs', vnf_dict, None, tenant_id, True, True)
@@ -1335,21 +751,24 @@ class nfvo_db():
             new_net_list: the new values to be inserted. If empty it only deletes the existing nets
         Return: (Inserted items, Deleted items) if OK, (-Error, text) if error
         '''
-        for retry_ in range(0,2):
+        tries = 2
+        while tries:
             created_time = time.time()
             try:
                 with self.con:
                     self.cur = self.con.cursor()
-                    cmd="DELETE FROM datacenter_nets WHERE datacenter_id='%s'" % datacenter_id
-                    print cmd
+                    cmd="DELETE FROM datacenter_nets WHERE datacenter_id='{}'".format(datacenter_id)
+                    self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     deleted = self.cur.rowcount
+                    inserted = 0
                     for new_net in new_net_list:
                         created_time += 0.00001
-                        self._new_row_internal('datacenter_nets', new_net, tenant_id=None, add_uuid=True, created_time=created_time)
-                    return len (new_net_list), deleted
-            except (mdb.Error, AttributeError), e:
-                print "nfvo_db.update_datacenter_nets DB Exception %d: %s" % (e.args[0], e.args[1])
-                r,c = self.format_error(e)
-                if r!=-HTTP_Request_Timeout or retry_==1: return r,c
+                        self._new_row_internal('datacenter_nets', new_net, add_uuid=True, created_time=created_time)
+                        inserted += 1
+                    return inserted, deleted
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
         
index 4ba38b5..0ac30a7 100644 (file)
@@ -97,7 +97,11 @@ config_schema = {
         },
         "log_level": log_level_schema,
         "log_level_db": log_level_schema,
-        "log_level_vimconn": log_level_schema
+        "log_level_vimconn": log_level_schema,
+        "log_level_nfvo": log_level_schema,
+        "log_host": nameshort_schema,
+        "log_port": port_schema,
+        "log_file": path_schema,
     },
     "required": ['db_host', 'db_user', 'db_passwd', 'db_name'],
     "additionalProperties": False
index e8aba16..ddf2b0f 100644 (file)
@@ -46,6 +46,16 @@ vnf_repository: "./vnfrepo"   # Use an absolute path to avoid misunderstandings
 
 
 #logging parameters       # DEBUG, INFO, WARNING, ERROR, CRITICAL
-log_level:       DEBUG
-log_level_db:    DEBUG
-log_level_vimconn:    DEBUG
+log_level:         DEBUG  #general log levels      
+log_level_db:      DEBUG  #database log levels
+log_level_vimconn: DEBUG  #VIM connection log levels
+log_level_nfvo:    DEBUG  #Main engine log levels
+
+#Uncomment to send logs via IP to an external host
+#log_host:         localhost
+#log_port:         1111
+
+#Uncomment to store in a file. Ensure path exists and to having write permissions
+#log_file:         /var/log/openmano/openmano.log
+
+
index 40dc246..f6436a6 100755 (executable)
@@ -33,8 +33,8 @@ It loads the configuration file and launches the http_server thread that will li
 '''
 __author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
 __date__ ="$26-aug-2014 11:09:29$"
-__version__="0.4.40-r476"
-version_date="Jun 2016"
+__version__="0.4.41-r478"
+version_date="Jul 2016"
 database_version="0.10"      #expected database schema version
 
 import httpserver
@@ -49,9 +49,11 @@ import utils
 from openmano_schemas import config_schema
 import nfvo
 import logging
+import logging.handlers as log_handlers
 
 global global_config
-logger = logging.getLogger('mano')
+global logger
+logger = logging.getLogger('openmano')
 
 class LoadConfigurationException(Exception):
     pass
@@ -62,6 +64,7 @@ def load_configuration(configuration_file):
                      'log_level': 'DEBUG',
                      'log_level_db': 'ERROR',
                      'log_level_vimconn': 'DEBUG',
+                     'log_level_nfvo': 'DEBUG',
                     }
     try:
         #Check config file exists
@@ -131,9 +134,11 @@ def usage():
     
 if __name__=="__main__":
     #streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s"
-    streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
-    logging.basicConfig(format=streamformat, level= logging.DEBUG)
+    logging_local_format = "%(asctime)s %(name)s %(levelname)s: %(message)s"
+    logging_complete_format = "%(asctime)s %(name)s %(levelname)s %(filename)s:%(lineno)d %(funcName)s %(process)d: %(message)s"
+    logging.basicConfig(format=logging_local_format, level= logging.DEBUG)
     logger.setLevel(logging.DEBUG)
+    file_handler = None
     # Read parameters and configuration file 
     try:
         opts, args = getopt.getopt(sys.argv[1:], "hvc:V:p:P:", ["config", "help", "version", "port", "vnf-repository", "adminport"])
@@ -166,7 +171,19 @@ if __name__=="__main__":
         #print global_config
         logging.basicConfig(level = getattr(logging, global_config.get('log_level',"debug")))
         logger.setLevel(getattr(logging, global_config['log_level']))
+        if "log_host" in global_config:
+            socket_handler= log_handlers.SocketHandler(global_config["log_host"], global_config["log_port"])
+            logger.addHandler(socket_handler)
+        logger.addHandler(log_handlers.SysLogHandler())
+        if "log_file" in global_config:
+            try:
+                file_handler= logging.handlers.RotatingFileHandler(global_config["log_file"], maxBytes=100e6, backupCount=9, delay=0)
+                file_handler.setFormatter(logging.Formatter(fmt=logging_complete_format))
+                logger.addHandler(file_handler)
+            except IOError as e:
+                print "Error opening logging file '{}': {}. Check folder exist and permissions".fomat(global_config["log_file"], str(e))
         # Override parameters obtained by command line
+        print logger.handlers
         if port is not None: global_config['http_port'] = port
         if port_admin is not None: global_config['http_admin_port'] = port_admin
         if vnf_repository is not None:
@@ -189,7 +206,7 @@ if __name__=="__main__":
         global_config["console_thread"]={}
         global_config["console_ports"]={}
         # Initialize DB connection
-        mydb = nfvo_db.nfvo_db();
+        mydb = nfvo_db.nfvo_db(log_level=global_config["log_level_db"]);
         if mydb.connect(global_config['db_host'], global_config['db_user'], global_config['db_passwd'], global_config['db_name']) == -1:
             logger.error("Error connecting to database %s at %s@%s", global_config['db_name'], global_config['db_user'], global_config['db_host'])
             exit(-1)
index 75bfe28..e9398b7 100755 (executable)
@@ -209,8 +209,8 @@ echo '
 #################################################################
 #####        INSTALL PYTHON PACKAGES                        #####
 #################################################################'
-[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests"
-[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests"
+[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests python-logutils"
+[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests python-logutils"
 
 #The only way to install python-bottle on Centos7 is with easy_install or pip
 [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && easy_install -U bottle