Merge branch 'v2.0' 68/2268/1
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 19 Sep 2017 08:07:30 +0000 (10:07 +0200)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 19 Sep 2017 08:24:42 +0000 (10:24 +0200)
Change-Id: I2793984f7d0fe713fb61c39564c44e68c9494972

26 files changed:
Dockerfile
MANIFEST.in
Makefile
database_utils/migrate_mano_db.sh
devops-stages/stage-build.sh
openmanod
osm_ro/db_base.py
osm_ro/nfvo.py
osm_ro/nfvo_db.py
osm_ro/openmano_schemas.py
osm_ro/vim_thread.py
osm_ro/vimconn.py
osm_ro/vimconn_aws.py
osm_ro/vimconn_openstack.py
osm_ro/vimconn_openvim.py
osm_ro/vimconn_vmware.py
scripts/install-openmano.sh
setup.py
stdeb.cfg
test/RO_tests/afiinity_vnf/scenario_simple_2_vnf_afinnity.yaml [new file with mode: 0644]
test/RO_tests/afiinity_vnf/vnfd_linux_2_vnfc_affinity.yaml [new file with mode: 0644]
test/RO_tests/simple_count3/scenario_linux_count3.yaml [new file with mode: 0644]
test/RO_tests/simple_count3/vnfd_count3.yaml [new file with mode: 0644]
test/test_RO.py
tox.ini [new file with mode: 0644]
vnfs/vnf-template.yaml

index 254027c..f901e9e 100644 (file)
@@ -1,10 +1,17 @@
 FROM ubuntu:16.04
 
 RUN  apt-get update && \
-  DEBIAN_FRONTEND=noninteractive apt-get -y install git build-essential apt-utils && \
-  DEBIAN_FRONTEND=noninteractive apt-get -y install python python-dev python-all python-stdeb fakeroot pypi2deb && \
-  DEBIAN_FRONTEND=noninteractive apt-get -y install python-pip libmysqlclient-dev libssl-dev libffi-dev && \
-  DEBIAN_FRONTEND=noninteractive pip install --upgrade pip && \
-  DEBIAN_FRONTEND=noninteractive pip install --upgrade setuptools && \
-  DEBIAN_FRONTEND=noninteractive apt-get -y install python-argcomplete python-boto python-bottle python-jsonschema python-logutils python-cinderclient python-glanceclient python-keystoneclient python-neutronclient python-novaclient python-openstackclient python-mysqldb
+  DEBIAN_FRONTEND=noninteractive apt-get -y install git make python python-pip debhelper && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install wget tox && \
+  DEBIAN_FRONTEND=noninteractive pip install -U pip && \
+  DEBIAN_FRONTEND=noninteractive pip install -U setuptools setuptools-version-command stdeb && \
+  DEBIAN_FRONTEND=noninteractive pip install -U pyang pyangbind && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install python-yaml python-netaddr python-boto && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install software-properties-common && \
+  DEBIAN_FRONTEND=noninteractive add-apt-repository -y cloud-archive:ocata && \
+  DEBIAN_FRONTEND=noninteractive apt-get update && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install python-novaclient python-keystoneclient python-glanceclient python-cinderclient python-neutronclient && \
+  DEBIAN_FRONTEND=noninteractive pip install -U progressbar pyvmomi pyvcloud && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install python-argcomplete python-bottle python-cffi python-packaging python-paramiko python-pkgconfig libmysqlclient-dev libssl-dev libffi-dev python-mysqldb && \
+  DEBIAN_FRONTEND=noninteractive apt-get -y install python-logutils python-openstackclient python-openstacksdk
 
index 48790d4..483b709 100644 (file)
@@ -1,7 +1,6 @@
 #include MANIFEST.in
 #include requirements.txt
 include README.rst
-include RO_VERSION
 include openmano
 include openmanod
 recursive-include osm_ro *
index 41b265a..8330b74 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,29 @@
+.PHONY: all test clean
+
 SHELL := /bin/bash
-all: package install
 
-clean_deb:
-       rm -rf .build
+BRANCH ?= master
+
+all: lib-openvim osm-im
+       $(MAKE) clean_build build
+       $(MAKE) clean_build package
+
+clean: clean_build
+       rm -rf .build openvim IM
 
-clean:
+clean_build:
        rm -rf build
        find osm_ro -name '*.pyc' -delete
        find osm_ro -name '*.pyo' -delete
+
 prepare:
-       pip install --user --upgrade setuptools
+#      ip install --user --upgrade setuptools
        mkdir -p build/
-       VER1=$(shell git describe | sed -e 's/^v//' |cut -d- -f1); \
-       VER2=$(shell git describe | cut -d- -f2); \
-       VER3=$(shell git describe | cut -d- -f3); \
-       echo "$$VER1.dev$$VER2+$$VER3" > build/RO_VERSION
+#      VER1=$(shell git describe | sed -e 's/^v//' |cut -d- -f1); \
+#      VER2=$(shell git describe | cut -d- -f2); \
+#      VER3=$(shell git describe | cut -d- -f3); \
+#      echo "$$VER1.dev$$VER2+$$VER3" > build/RO_VERSION
+       cp tox.ini build/
        cp MANIFEST.in build/
        cp requirements.txt build/
        cp README.rst build/
@@ -36,14 +45,25 @@ connectors: prepare
        python build/osm_ro/openmanolinkervimconn.py
        rm -f build/osm_ro/openmanolinkervimconn.py
 
-build: clean connectors prepare
+build: connectors prepare
        python -m py_compile build/osm_ro/*.py
+#      cd build && tox -e flake8
+
+lib-openvim:
+       $(shell git clone https://osm.etsi.org/gerrit/osm/openvim)
+       LIB_BRANCH=$(shell git -C openvim branch -a|grep -oP 'remotes/origin/\K$(BRANCH)'); \
+       [ -z "$$LIB_BRANCH" ] && LIB_BRANCH='master'; \
+       echo "BRANCH: $(BRANCH)"; \
+       echo "LIB_OPENVIM_BRANCH: $$LIB_BRANCH"; \
+       git -C openvim checkout $$LIB_BRANCH
+       make -C openvim clean lite
 
-pip: prepare
-       cd build && ./setup.py sdist
+osm-im:
+       $(shell git clone https://osm.etsi.org/gerrit/osm/IM)
+       make -C IM clean all
 
-package: clean clean_deb prepare
-       #apt-get install -y python-stdeb
+package: prepare
+#      apt-get install -y python-stdeb
        cd build && python setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True
        cd build && cp osm_ro/scripts/python-osm-ro.postinst deb_dist/osm-ro*/debian/
        cd build/deb_dist/osm-ro* && dpkg-buildpackage -rfakeroot -uc -us
@@ -54,17 +74,25 @@ snap:
        echo "Nothing to be done yet"
 
 install:
-       DEBIAN_FRONTEND=noninteractive apt-get update && \
-       DEBIAN_FRONTEND=noninteractive apt-get install -y python-pip && \
-       pip install --upgrade pip && \
-       dpkg -i .build/*.deb
+       dpkg -i IM/deb_dist/python-osm-im*.deb
+       dpkg -i openvim/.build/python-lib-osm-openvim*.deb
+       dpkg -i .build/python-osm-ro*.deb
+       cd .. && \
+       OSMLIBOVIM_PATH=`python -c 'import lib_osm_openvim; print lib_osm_openvim.__path__[0]'` || FATAL "lib-osm-openvim was not properly installed" && \
+       OSMRO_PATH=`python -c 'import osm_ro; print osm_ro.__path__[0]'` || FATAL "osm-ro was not properly installed" && \
+       USER=root DEBIAN_FRONTEND=noninteractive $$OSMRO_PATH/database_utils/install-db-server.sh --updatedb || FATAL "osm-ro db installation failed" && \
+       USER=root DEBIAN_FRONTEND=noninteractive $$OSMLIBOVIM_PATH/database_utils/install-db-server.sh -u mano -p manopw -d mano_vim_db --updatedb || FATAL "lib-osm-openvim db installation failed"
+       service osm-ro restart
 
 develop: prepare
-       #pip install -r requirements.txt
+#      pip install -r requirements.txt
        cd build && ./setup.py develop
 
 test:
-       ./test/basictest.sh --force --insert-bashrc --install-openvim --init-openvim
+       . ./test/basictest.sh -f --insert-bashrc --install-openvim --init-openvim
+       . ./test/basictest.sh -f reset add-openvim
+       ./test/test_RO.py deploy -n mgmt -t osm -i cirros034 -d local-openvim --timeout=30 --failfast
+       ./test/test_RO.py vim  -t osm  -d local-openvim --timeout=30 --failfast
 
 build-docker-from-source:
        docker build -t osm/openmano -f docker/Dockerfile-local .
index 52d8cb1..1e3e5b6 100755 (executable)
@@ -33,7 +33,7 @@ DBPORT="3306"
 DBNAME="mano_db"
 QUIET_MODE=""
 #TODO update it with the last database version
-LAST_DB_VERSION=22
+LAST_DB_VERSION=24
  
 # Detect paths
 MYSQL=$(which mysql)
@@ -147,7 +147,7 @@ DBCMD="mysql $DEF_EXTRA_FILE_PARAM $DBNAME"
 if ! echo -e "show create table vnfs;\nshow create table scenarios" | $DBCMD >/dev/null 2>&1
 then
     echo "    database $DBNAME does not seem to be an openmano database" >&2
-    exit -1;
+    exit 1;
 fi
 
 if ! echo 'show create table schema_version;' | $DBCMD >/dev/null 2>&1
@@ -158,7 +158,7 @@ else
     DATABASE_VER_NUM=`echo "select max(version_int) from schema_version;" | $DBCMD | tail -n+2` 
     DATABASE_VER=`echo "select version from schema_version where version_int='$DATABASE_VER_NUM';" | $DBCMD | tail -n+2` 
     [ "$DATABASE_VER_NUM" -lt 0 -o "$DATABASE_VER_NUM" -gt 100 ] &&
-        echo "    Error can not get database version ($DATABASE_VER?)" >&2 && exit -1
+        echo "    Error can not get database version ($DATABASE_VER?)" >&2 && exit 1
     #echo "_${DATABASE_VER_NUM}_${DATABASE_VER}"
 fi
 
@@ -190,12 +190,14 @@ fi
 #[ $OPENMANO_VER_NUM -ge 5009 ] && DB_VERSION=20  #0.5.9 =>  20
 #[ $OPENMANO_VER_NUM -ge 5015 ] && DB_VERSION=21  #0.5.15 =>  21
 #[ $OPENMANO_VER_NUM -ge 5016 ] && DB_VERSION=22  #0.5.16 =>  22
+#[ $OPENMANO_VER_NUM -ge 5020 ] && DB_VERSION=23  #0.5.20 =>  23
+#[ $OPENMANO_VER_NUM -ge 5021 ] && DB_VERSION=24  #0.5.21 =>  24
 #TODO ... put next versions here
 
 function upgrade_to_1(){
     # echo "    upgrade database from version 0.0 to version 0.1"
     echo "      CREATE TABLE \`schema_version\`"
-    echo "CREATE TABLE \`schema_version\` (
+    sql "CREATE TABLE \`schema_version\` (
        \`version_int\` INT NOT NULL COMMENT 'version as a number. Must not contain gaps',
        \`version\` VARCHAR(20) NOT NULL COMMENT 'version as a text',
        \`openmano_ver\` VARCHAR(20) NOT NULL COMMENT 'openmano version',
@@ -205,22 +207,22 @@ function upgrade_to_1(){
        )
        COMMENT='database schema control version'
        COLLATE='utf8_general_ci'
-       ENGINE=InnoDB;" | $DBCMD  || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO \`schema_version\` (\`version_int\`, \`version\`, \`openmano_ver\`, \`comments\`, \`date\`)
-        VALUES (1, '0.1', '0.2.2', 'insert schema_version', '2015-05-08');" | $DBCMD
+       ENGINE=InnoDB;"
+    sql "INSERT INTO \`schema_version\` (\`version_int\`, \`version\`, \`openmano_ver\`, \`comments\`, \`date\`)
+        VALUES (1, '0.1', '0.2.2', 'insert schema_version', '2015-05-08');"
 }
 function downgrade_from_1(){
     # echo "    downgrade database from version 0.1 to version 0.0"
     echo "      DROP TABLE \`schema_version\`"
-    echo "DROP TABLE \`schema_version\`;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DROP TABLE \`schema_version\`;"
 }
 function upgrade_to_2(){
     # echo "    upgrade database from version 0.1 to version 0.2"
     echo "      Add columns user/passwd to table 'vim_tenants'"
-    echo "ALTER TABLE vim_tenants ADD COLUMN user VARCHAR(36) NULL COMMENT 'Credentials for vim' AFTER created,
-       ADD COLUMN passwd VARCHAR(50) NULL COMMENT 'Credentials for vim' AFTER user;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants ADD COLUMN user VARCHAR(36) NULL COMMENT 'Credentials for vim' AFTER created,
+       ADD COLUMN passwd VARCHAR(50) NULL COMMENT 'Credentials for vim' AFTER user;"
     echo "      Add table 'images' and 'datacenters_images'"
-    echo "CREATE TABLE images (
+    sql "CREATE TABLE images (
        uuid VARCHAR(36) NOT NULL,
        name VARCHAR(50) NOT NULL,
        location VARCHAR(200) NOT NULL,
@@ -229,8 +231,8 @@ function upgrade_to_2(){
        PRIMARY KEY (uuid),
        UNIQUE INDEX location (location)  )
         COLLATE='utf8_general_ci'
-        ENGINE=InnoDB;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "CREATE TABLE datacenters_images (
+        ENGINE=InnoDB;"
+    sql "CREATE TABLE datacenters_images (
        id INT NOT NULL AUTO_INCREMENT,
        image_id VARCHAR(36) NOT NULL,
        datacenter_id VARCHAR(36) NOT NULL,
@@ -239,13 +241,13 @@ function upgrade_to_2(){
        CONSTRAINT FK__images FOREIGN KEY (image_id) REFERENCES images (uuid) ON UPDATE CASCADE ON DELETE CASCADE,
        CONSTRAINT FK__datacenters_i FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE CASCADE ON DELETE CASCADE  )
         COLLATE='utf8_general_ci'
-        ENGINE=InnoDB;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        ENGINE=InnoDB;"
     echo "      migrate data from table 'vms' into 'images'"
-    echo "INSERT INTO images (uuid, name, location) SELECT DISTINCT vim_image_id, vim_image_id, image_path FROM vms;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO datacenters_images (image_id, datacenter_id, vim_id)
-          SELECT DISTINCT vim_image_id, datacenters.uuid, vim_image_id FROM vms JOIN datacenters;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "INSERT INTO images (uuid, name, location) SELECT DISTINCT vim_image_id, vim_image_id, image_path FROM vms;"
+    sql "INSERT INTO datacenters_images (image_id, datacenter_id, vim_id)
+          SELECT DISTINCT vim_image_id, datacenters.uuid, vim_image_id FROM vms JOIN datacenters;"
     echo "      Add table 'flavors' and 'datacenter_flavors'"
-    echo "CREATE TABLE flavors (
+    sql "CREATE TABLE flavors (
        uuid VARCHAR(36) NOT NULL,
        name VARCHAR(50) NOT NULL,
        description VARCHAR(100) NULL,
@@ -255,8 +257,8 @@ function upgrade_to_2(){
        extended VARCHAR(2000) NULL DEFAULT NULL COMMENT 'Extra description json format of needed resources and pining, orginized in sets per numa',
        PRIMARY KEY (uuid)  )
         COLLATE='utf8_general_ci'
-        ENGINE=InnoDB;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "CREATE TABLE datacenters_flavors (
+        ENGINE=InnoDB;"
+    sql "CREATE TABLE datacenters_flavors (
        id INT NOT NULL AUTO_INCREMENT,
        flavor_id VARCHAR(36) NOT NULL,
        datacenter_id VARCHAR(36) NOT NULL,
@@ -265,104 +267,104 @@ function upgrade_to_2(){
        CONSTRAINT FK__flavors FOREIGN KEY (flavor_id) REFERENCES flavors (uuid) ON UPDATE CASCADE ON DELETE CASCADE,
        CONSTRAINT FK__datacenters_f FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE CASCADE ON DELETE CASCADE  )
         COLLATE='utf8_general_ci'
-        ENGINE=InnoDB;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        ENGINE=InnoDB;"
     echo "      migrate data from table 'vms' into 'flavors'"
-    echo "INSERT INTO flavors (uuid, name) SELECT DISTINCT vim_flavor_id, vim_flavor_id FROM vms;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO datacenters_flavors (flavor_id, datacenter_id, vim_id)
-          SELECT DISTINCT vim_flavor_id, datacenters.uuid, vim_flavor_id FROM vms JOIN datacenters;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vms ALTER vim_flavor_id DROP DEFAULT, ALTER vim_image_id DROP DEFAULT;
+    sql "INSERT INTO flavors (uuid, name) SELECT DISTINCT vim_flavor_id, vim_flavor_id FROM vms;"
+    sql "INSERT INTO datacenters_flavors (flavor_id, datacenter_id, vim_id)
+          SELECT DISTINCT vim_flavor_id, datacenters.uuid, vim_flavor_id FROM vms JOIN datacenters;"
+    sql "ALTER TABLE vms ALTER vim_flavor_id DROP DEFAULT, ALTER vim_image_id DROP DEFAULT;
           ALTER TABLE vms CHANGE COLUMN vim_flavor_id flavor_id VARCHAR(36) NOT NULL COMMENT 'Link to flavor table' AFTER vnf_id,
           CHANGE COLUMN vim_image_id image_id VARCHAR(36) NOT NULL COMMENT 'Link to image table' AFTER flavor_id, 
           ADD CONSTRAINT FK_vms_images  FOREIGN KEY (image_id) REFERENCES  images (uuid),
-          ADD CONSTRAINT FK_vms_flavors FOREIGN KEY (flavor_id) REFERENCES flavors (uuid);
-         " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (2, '0.2', '0.2.5', 'new tables images,flavors', '2015-07-13');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+          ADD CONSTRAINT FK_vms_flavors FOREIGN KEY (flavor_id) REFERENCES flavors (uuid);"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (2, '0.2', '0.2.5', 'new tables images,flavors', '2015-07-13');"
 
 }   
      
 function downgrade_from_2(){
     # echo "    downgrade database from version 0.2 to version 0.1"
     echo "       migrate back data from 'datacenters_images' 'datacenters_flavors' into 'vms'"
-    echo "ALTER TABLE vms ALTER image_id DROP DEFAULT, ALTER flavor_id DROP DEFAULT;
+    sql "ALTER TABLE vms ALTER image_id DROP DEFAULT, ALTER flavor_id DROP DEFAULT;
           ALTER TABLE vms CHANGE COLUMN flavor_id vim_flavor_id VARCHAR(36) NOT NULL COMMENT 'Flavor ID in the VIM DB' AFTER vnf_id,
           CHANGE COLUMN image_id vim_image_id VARCHAR(36) NOT NULL COMMENT 'Image ID in the VIM DB' AFTER vim_flavor_id,
           DROP FOREIGN KEY FK_vms_flavors, DROP INDEX FK_vms_flavors,
-          DROP FOREIGN KEY FK_vms_images, DROP INDEX FK_vms_images;
-         " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+          DROP FOREIGN KEY FK_vms_images, DROP INDEX FK_vms_images;"
 #    echo "UPDATE v SET v.vim_image_id=di.vim_id
 #          FROM  vms as v INNER JOIN images as i ON v.vim_image_id=i.uuid 
-#          INNER JOIN datacenters_images as di ON i.uuid=di.image_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+#          INNER JOIN datacenters_images as di ON i.uuid=di.image_id;"
     echo "      Delete columns 'user/passwd' from 'vim_tenants'"
-    echo "ALTER TABLE vim_tenants DROP COLUMN user, DROP COLUMN passwd; " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants DROP COLUMN user, DROP COLUMN passwd; "
     echo "        delete tables 'datacenter_images', 'images'"
-    echo "DROP TABLE \`datacenters_images\`;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DROP TABLE \`images\`;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DROP TABLE \`datacenters_images\`;"
+    sql "DROP TABLE \`images\`;"
     echo "        delete tables 'datacenter_flavors', 'flavors'"
-    echo "DROP TABLE \`datacenters_flavors\`;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DROP TABLE \`flavors\`;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='2';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DROP TABLE \`datacenters_flavors\`;"
+    sql "DROP TABLE \`flavors\`;"
+    sql "DELETE FROM schema_version WHERE version_int='2';"
 }
 
 function upgrade_to_3(){
     # echo "    upgrade database from version 0.2 to version 0.3"
     echo "      Change table 'logs', 'uuids"
-    echo "ALTER TABLE logs CHANGE COLUMN related related VARCHAR(36) NOT NULL COMMENT 'Relevant element for the log' AFTER nfvo_tenant_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE uuids CHANGE COLUMN used_at used_at VARCHAR(36) NULL DEFAULT NULL COMMENT 'Table that uses this UUID' AFTER created_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE logs CHANGE COLUMN related related VARCHAR(36) NOT NULL COMMENT 'Relevant element for the log' AFTER nfvo_tenant_id;"
+    sql "ALTER TABLE uuids CHANGE COLUMN used_at used_at VARCHAR(36) NULL DEFAULT NULL COMMENT 'Table that uses this UUID' AFTER created_at;"
     echo "      Add column created to table 'datacenters_images' and 'datacenters_flavors'"
     for table in datacenters_images datacenters_flavors
     do
-        echo "ALTER TABLE $table ADD COLUMN created ENUM('true','false') NOT NULL DEFAULT 'false' 
-            COMMENT 'Indicates if it has been created by openmano, or already existed' AFTER vim_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE $table ADD COLUMN created ENUM('true','false') NOT NULL DEFAULT 'false' 
+            COMMENT 'Indicates if it has been created by openmano, or already existed' AFTER vim_id;"
     done
-    echo "ALTER TABLE images CHANGE COLUMN metadata metadata VARCHAR(2000) NULL DEFAULT NULL AFTER description;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE images CHANGE COLUMN metadata metadata VARCHAR(2000) NULL DEFAULT NULL AFTER description;"
     echo "      Allow null to column 'vim_interface_id' in 'instance_interfaces'"
-    echo "ALTER TABLE instance_interfaces CHANGE COLUMN vim_interface_id vim_interface_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'vim identity for that interface' AFTER interface_id; " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_interfaces CHANGE COLUMN vim_interface_id vim_interface_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'vim identity for that interface' AFTER interface_id; "
     echo "      Add column config to table 'datacenters'"
-    echo "ALTER TABLE datacenters ADD COLUMN config VARCHAR(4000) NULL DEFAULT NULL COMMENT 'extra config information in json' AFTER vim_url_admin;
-       " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters ADD COLUMN config VARCHAR(4000) NULL DEFAULT NULL COMMENT 'extra config information in json' AFTER vim_url_admin;
+       "
     echo "      Add column datacenter_id to table 'vim_tenants'"
-    echo "ALTER TABLE vim_tenants ADD COLUMN datacenter_id VARCHAR(36) NULL COMMENT 'Datacenter of this tenant' AFTER uuid,
-       DROP INDEX name, DROP INDEX vim_tenant_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN name vim_tenant_name VARCHAR(36) NULL DEFAULT NULL COMMENT 'tenant name at VIM' AFTER datacenter_id,
-       CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants ADD COLUMN datacenter_id VARCHAR(36) NULL COMMENT 'Datacenter of this tenant' AFTER uuid,
+       DROP INDEX name, DROP INDEX vim_tenant_id;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN name vim_tenant_name VARCHAR(36) NULL DEFAULT NULL COMMENT 'tenant name at VIM' AFTER datacenter_id,
+       CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;"
     echo "UPDATE vim_tenants as vt LEFT JOIN tenants_datacenters as td ON vt.uuid=td.vim_tenant_id
-       SET vt.datacenter_id=td.datacenter_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM vim_tenants WHERE datacenter_id is NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants ALTER datacenter_id DROP DEFAULT;
+       SET vt.datacenter_id=td.datacenter_id;"
+    sql "DELETE FROM vim_tenants WHERE datacenter_id is NULL;"
+    sql "ALTER TABLE vim_tenants ALTER datacenter_id DROP DEFAULT;
        ALTER TABLE vim_tenants
-       CHANGE COLUMN datacenter_id datacenter_id VARCHAR(36) NOT NULL COMMENT 'Datacenter of this tenant' AFTER uuid;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants ADD CONSTRAINT FK_vim_tenants_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid)
-       ON UPDATE CASCADE ON DELETE CASCADE;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+       CHANGE COLUMN datacenter_id datacenter_id VARCHAR(36) NOT NULL COMMENT 'Datacenter of this tenant' AFTER uuid;"
+    sql "ALTER TABLE vim_tenants ADD CONSTRAINT FK_vim_tenants_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid)
+       ON UPDATE CASCADE ON DELETE CASCADE;"
 
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (3, '0.3', '0.3.3', 'alter vim_tenant tables', '2015-07-28');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (3, '0.3', '0.3.3', 'alter vim_tenant tables', '2015-07-28');"
 }
 
 
 function downgrade_from_3(){
     # echo "    downgrade database from version 0.3 to version 0.2"
     echo "      Change back table 'logs', 'uuids'"
-    echo "ALTER TABLE logs CHANGE COLUMN related related ENUM('nfvo_tenants','datacenters','vim_tenants','tenants_datacenters','vnfs','vms','interfaces','nets','scenarios','sce_vnfs','sce_interfaces','sce_nets','instance_scenarios','instance_vnfs','instance_vms','instance_nets','instance_interfaces') NOT NULL COMMENT 'Relevant element for the log' AFTER nfvo_tenant_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE uuids CHANGE COLUMN used_at used_at ENUM('nfvo_tenants','datacenters','vim_tenants','vnfs','vms','interfaces','nets','scenarios','sce_vnfs','sce_interfaces','sce_nets','instance_scenarios','instance_vnfs','instance_vms','instance_nets','instance_interfaces') NULL DEFAULT NULL COMMENT 'Table that uses this UUID' AFTER created_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE logs CHANGE COLUMN related related ENUM('nfvo_tenants','datacenters','vim_tenants','tenants_datacenters','vnfs','vms','interfaces','nets','scenarios','sce_vnfs','sce_interfaces','sce_nets','instance_scenarios','instance_vnfs','instance_vms','instance_nets','instance_interfaces') NOT NULL COMMENT 'Relevant element for the log' AFTER nfvo_tenant_id;"
+    sql "ALTER TABLE uuids CHANGE COLUMN used_at used_at ENUM('nfvo_tenants','datacenters','vim_tenants','vnfs','vms','interfaces','nets','scenarios','sce_vnfs','sce_interfaces','sce_nets','instance_scenarios','instance_vnfs','instance_vms','instance_nets','instance_interfaces') NULL DEFAULT NULL COMMENT 'Table that uses this UUID' AFTER created_at;"
     echo "      Delete column created from table 'datacenters_images' and 'datacenters_flavors'"
     for table in datacenters_images datacenters_flavors
     do
-        echo "ALTER TABLE $table DROP COLUMN created;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE $table DROP COLUMN created;"
     done
-    echo "ALTER TABLE images CHANGE COLUMN metadata metadata VARCHAR(400) NULL DEFAULT NULL AFTER description;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE images CHANGE COLUMN metadata metadata VARCHAR(400) NULL DEFAULT NULL AFTER description;"
     echo "      Deny back null to column 'vim_interface_id' in 'instance_interfaces'"
-    echo "ALTER TABLE instance_interfaces CHANGE COLUMN vim_interface_id vim_interface_id VARCHAR(36) NOT NULL COMMENT 'vim identity for that interface' AFTER interface_id; " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_interfaces CHANGE COLUMN vim_interface_id vim_interface_id VARCHAR(36) NOT NULL COMMENT 'vim identity for that interface' AFTER interface_id; "
     echo "       Delete column config to table 'datacenters'"
-    echo "ALTER TABLE datacenters DROP COLUMN config;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters DROP COLUMN config;"
     echo "       Delete column datacenter_id to table 'vim_tenants'"
-    echo "ALTER TABLE vim_tenants DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_vim_tenants_datacenters;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name name VARCHAR(36) NULL DEFAULT NULL COMMENT '' AFTER uuid"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants ALTER name DROP DEFAULT;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN name name VARCHAR(36) NOT NULL AFTER uuid"| $DBCMD || ! echo "Warning changing column name at vim_tenants!"
-    echo "ALTER TABLE vim_tenants ADD UNIQUE INDEX name (name);" | $DBCMD || ! echo "Warning add unique index name at vim_tenants!"
-    echo "ALTER TABLE vim_tenants ALTER vim_tenant_id DROP DEFAULT;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NOT NULL COMMENT 'Tenant ID in the VIM DB' AFTER name;"| $DBCMD || ! echo "Warning changing column vim_tenant_id at vim_tenants!"
-    echo "ALTER TABLE vim_tenants ADD UNIQUE INDEX vim_tenant_id (vim_tenant_id);" | $DBCMD || ! echo "Warning add unique index vim_tenant_id at vim_tenants!"
-    echo "DELETE FROM schema_version WHERE version_int='3';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_vim_tenants_datacenters;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name name VARCHAR(36) NULL DEFAULT NULL COMMENT '' AFTER uuid"
+    sql "ALTER TABLE vim_tenants ALTER name DROP DEFAULT;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN name name VARCHAR(36) NOT NULL AFTER uuid" || ! echo "Warning changing column name at vim_tenants!"
+    sql "ALTER TABLE vim_tenants ADD UNIQUE INDEX name (name);" || ! echo "Warning add unique index name at vim_tenants!"
+    sql "ALTER TABLE vim_tenants ALTER vim_tenant_id DROP DEFAULT;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NOT NULL COMMENT 'Tenant ID in the VIM DB' AFTER name;" ||
+        ! echo "Warning changing column vim_tenant_id at vim_tenants!"
+    sql "ALTER TABLE vim_tenants ADD UNIQUE INDEX vim_tenant_id (vim_tenant_id);" ||
+        ! echo "Warning add unique index vim_tenant_id at vim_tenants!"
+    sql "DELETE FROM schema_version WHERE version_int='3';"
 }
 
 function upgrade_to_4(){
@@ -370,10 +372,10 @@ function upgrade_to_4(){
     echo "      Enlarge graph field at tables 'sce_vnfs', 'sce_nets'"
     for table in sce_vnfs sce_nets
     do
-        echo "ALTER TABLE $table CHANGE COLUMN graph graph VARCHAR(2000) NULL DEFAULT NULL AFTER modified_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE $table CHANGE COLUMN graph graph VARCHAR(2000) NULL DEFAULT NULL AFTER modified_at;"
     done
-    echo "ALTER TABLE datacenters CHANGE COLUMN type type VARCHAR(36) NOT NULL DEFAULT 'openvim' AFTER description;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (4, '0.4', '0.3.5', 'enlarge graph field at sce_vnfs/nets', '2015-10-20');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters CHANGE COLUMN type type VARCHAR(36) NOT NULL DEFAULT 'openvim' AFTER description;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (4, '0.4', '0.3.5', 'enlarge graph field at sce_vnfs/nets', '2015-10-20');"
 }
 
 function downgrade_from_4(){
@@ -381,72 +383,72 @@ function downgrade_from_4(){
     echo "      Shorten back graph field at tables 'sce_vnfs', 'sce_nets'"
     for table in sce_vnfs sce_nets
     do
-        echo "ALTER TABLE $table CHANGE COLUMN graph graph VARCHAR(2000) NULL DEFAULT NULL AFTER modified_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE $table CHANGE COLUMN graph graph VARCHAR(2000) NULL DEFAULT NULL AFTER modified_at;"
     done
-    echo "ALTER TABLE datacenters CHANGE COLUMN type type ENUM('openvim','openstack') NOT NULL DEFAULT 'openvim' AFTER description;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='4';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters CHANGE COLUMN type type ENUM('openvim','openstack') NOT NULL DEFAULT 'openvim' AFTER description;"
+    sql "DELETE FROM schema_version WHERE version_int='4';"
 }
 
 function upgrade_to_5(){
     # echo "    upgrade database from version 0.4 to version 0.5"
     echo "      Add 'mac' field for bridge interfaces in table 'interfaces'"
-    echo "ALTER TABLE interfaces ADD COLUMN mac CHAR(18) NULL DEFAULT NULL AFTER model;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (5, '0.5', '0.4.1', 'Add mac address for bridge interfaces', '2015-12-14');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces ADD COLUMN mac CHAR(18) NULL DEFAULT NULL AFTER model;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (5, '0.5', '0.4.1', 'Add mac address for bridge interfaces', '2015-12-14');"
 }
 function downgrade_from_5(){
     # echo "    downgrade database from version 0.5 to version 0.4"
     echo "      Remove 'mac' field for bridge interfaces in table 'interfaces'"
-    echo "ALTER TABLE interfaces DROP COLUMN mac;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='5';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces DROP COLUMN mac;"
+    sql "DELETE FROM schema_version WHERE version_int='5';"
 }
 
 function upgrade_to_6(){
     # echo "    upgrade database from version 0.5 to version 0.6"
     echo "      Add 'descriptor' field text to 'vnfd', 'scenarios'"
-    echo "ALTER TABLE vnfs ADD COLUMN descriptor TEXT NULL DEFAULT NULL COMMENT 'Original text descriptor used for create the VNF' AFTER class;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios ADD COLUMN descriptor TEXT NULL DEFAULT NULL COMMENT 'Original text descriptor used for create the scenario' AFTER modified_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vnfs ADD COLUMN descriptor TEXT NULL DEFAULT NULL COMMENT 'Original text descriptor used for create the VNF' AFTER class;"
+    sql "ALTER TABLE scenarios ADD COLUMN descriptor TEXT NULL DEFAULT NULL COMMENT 'Original text descriptor used for create the scenario' AFTER modified_at;"
     echo "      Add 'last_error', 'vim_info' to 'instance_vms', 'instance_nets'"
-    echo "ALTER TABLE instance_vms  ADD COLUMN error_msg VARCHAR(1024) NULL DEFAULT NULL AFTER status;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vms  ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER error_msg;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vms  CHANGE COLUMN status status ENUM('ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD' AFTER vim_vm_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets ADD COLUMN error_msg VARCHAR(1024) NULL DEFAULT NULL AFTER status;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER error_msg;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets CHANGE COLUMN status status ENUM('ACTIVE','DOWN','BUILD','ERROR','VIM_ERROR','INACTIVE','DELETED') NOT NULL DEFAULT 'BUILD' AFTER instance_scenario_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vms  ADD COLUMN error_msg VARCHAR(1024) NULL DEFAULT NULL AFTER status;"
+    sql "ALTER TABLE instance_vms  ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER error_msg;"
+    sql "ALTER TABLE instance_vms  CHANGE COLUMN status status ENUM('ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD' AFTER vim_vm_id;"
+    sql "ALTER TABLE instance_nets ADD COLUMN error_msg VARCHAR(1024) NULL DEFAULT NULL AFTER status;"
+    sql "ALTER TABLE instance_nets ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER error_msg;"
+    sql "ALTER TABLE instance_nets CHANGE COLUMN status status ENUM('ACTIVE','DOWN','BUILD','ERROR','VIM_ERROR','INACTIVE','DELETED') NOT NULL DEFAULT 'BUILD' AFTER instance_scenario_id;"
     echo "      Add 'mac_address', 'ip_address', 'vim_info' to 'instance_interfaces'"
-    echo "ALTER TABLE instance_interfaces ADD COLUMN mac_address VARCHAR(32) NULL DEFAULT NULL AFTER vim_interface_id, ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER mac_address, ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER ip_address;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_interfaces ADD COLUMN mac_address VARCHAR(32) NULL DEFAULT NULL AFTER vim_interface_id, ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER mac_address, ADD COLUMN vim_info TEXT NULL DEFAULT NULL AFTER ip_address;"
     echo "      Add 'sce_vnf_id','datacenter_id','vim_tenant_id' field to 'instance_vnfs'"
-    echo "ALTER TABLE instance_vnfs ADD COLUMN sce_vnf_id VARCHAR(36) NULL DEFAULT NULL AFTER vnf_id, ADD CONSTRAINT FK_instance_vnfs_sce_vnfs FOREIGN KEY (sce_vnf_id) REFERENCES sce_vnfs (uuid) ON UPDATE CASCADE ON DELETE SET NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vnfs ADD COLUMN vim_tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER sce_vnf_id, ADD CONSTRAINT FK_instance_vnfs_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vnfs ADD COLUMN datacenter_id VARCHAR(36) NULL DEFAULT NULL AFTER vim_tenant_id, ADD CONSTRAINT FK_instance_vnfs_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vnfs ADD COLUMN sce_vnf_id VARCHAR(36) NULL DEFAULT NULL AFTER vnf_id, ADD CONSTRAINT FK_instance_vnfs_sce_vnfs FOREIGN KEY (sce_vnf_id) REFERENCES sce_vnfs (uuid) ON UPDATE CASCADE ON DELETE SET NULL;"
+    sql "ALTER TABLE instance_vnfs ADD COLUMN vim_tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER sce_vnf_id, ADD CONSTRAINT FK_instance_vnfs_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;"
+    sql "ALTER TABLE instance_vnfs ADD COLUMN datacenter_id VARCHAR(36) NULL DEFAULT NULL AFTER vim_tenant_id, ADD CONSTRAINT FK_instance_vnfs_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;"
     echo "      Add 'sce_net_id','net_id','datacenter_id','vim_tenant_id' field to 'instance_nets'"
-    echo "ALTER TABLE instance_nets ADD COLUMN sce_net_id VARCHAR(36) NULL DEFAULT NULL AFTER instance_scenario_id, ADD CONSTRAINT FK_instance_nets_sce_nets FOREIGN KEY (sce_net_id) REFERENCES sce_nets (uuid) ON UPDATE CASCADE ON DELETE SET NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets ADD COLUMN net_id VARCHAR(36) NULL DEFAULT NULL AFTER sce_net_id, ADD CONSTRAINT FK_instance_nets_nets FOREIGN KEY (net_id) REFERENCES nets (uuid) ON UPDATE CASCADE ON DELETE SET NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets ADD COLUMN vim_tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER net_id, ADD CONSTRAINT FK_instance_nets_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets ADD COLUMN datacenter_id VARCHAR(36) NULL DEFAULT NULL AFTER vim_tenant_id, ADD CONSTRAINT FK_instance_nets_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (6, '0.6', '0.4.2', 'Adding VIM status info', '2015-12-22');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets ADD COLUMN sce_net_id VARCHAR(36) NULL DEFAULT NULL AFTER instance_scenario_id, ADD CONSTRAINT FK_instance_nets_sce_nets FOREIGN KEY (sce_net_id) REFERENCES sce_nets (uuid) ON UPDATE CASCADE ON DELETE SET NULL;"
+    sql "ALTER TABLE instance_nets ADD COLUMN net_id VARCHAR(36) NULL DEFAULT NULL AFTER sce_net_id, ADD CONSTRAINT FK_instance_nets_nets FOREIGN KEY (net_id) REFERENCES nets (uuid) ON UPDATE CASCADE ON DELETE SET NULL;"
+    sql "ALTER TABLE instance_nets ADD COLUMN vim_tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER net_id, ADD CONSTRAINT FK_instance_nets_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;"
+    sql "ALTER TABLE instance_nets ADD COLUMN datacenter_id VARCHAR(36) NULL DEFAULT NULL AFTER vim_tenant_id, ADD CONSTRAINT FK_instance_nets_datacenters FOREIGN KEY (datacenter_id) REFERENCES datacenters (uuid) ON UPDATE RESTRICT ON DELETE RESTRICT;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (6, '0.6', '0.4.2', 'Adding VIM status info', '2015-12-22');"
 }
 function downgrade_from_6(){
     # echo "    downgrade database from version 0.6 to version 0.5"
     echo "      Remove 'descriptor' field from 'vnfd', 'scenarios' tables"
-    echo "ALTER TABLE vnfs      DROP COLUMN descriptor;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios DROP COLUMN descriptor;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vnfs      DROP COLUMN descriptor;"
+    sql "ALTER TABLE scenarios DROP COLUMN descriptor;"
     echo "      Remove 'last_error', 'vim_info' from 'instance_vms', 'instance_nets'"
-    echo "ALTER TABLE instance_vms  DROP COLUMN error_msg, DROP COLUMN vim_info;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vms  CHANGE COLUMN status status ENUM('ACTIVE','PAUSED','INACTIVE','CREATING','ERROR','DELETING') NOT NULL DEFAULT 'CREATING' AFTER vim_vm_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets DROP COLUMN error_msg, DROP COLUMN vim_info;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets CHANGE COLUMN status status ENUM('ACTIVE','DOWN','BUILD','ERROR') NOT NULL DEFAULT 'BUILD' AFTER instance_scenario_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vms  DROP COLUMN error_msg, DROP COLUMN vim_info;"
+    sql "ALTER TABLE instance_vms  CHANGE COLUMN status status ENUM('ACTIVE','PAUSED','INACTIVE','CREATING','ERROR','DELETING') NOT NULL DEFAULT 'CREATING' AFTER vim_vm_id;"
+    sql "ALTER TABLE instance_nets DROP COLUMN error_msg, DROP COLUMN vim_info;"
+    sql "ALTER TABLE instance_nets CHANGE COLUMN status status ENUM('ACTIVE','DOWN','BUILD','ERROR') NOT NULL DEFAULT 'BUILD' AFTER instance_scenario_id;"
     echo "      Remove 'mac_address', 'ip_address', 'vim_info' from 'instance_interfaces'"
-    echo "ALTER TABLE instance_interfaces DROP COLUMN mac_address, DROP COLUMN ip_address, DROP COLUMN vim_info;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_interfaces DROP COLUMN mac_address, DROP COLUMN ip_address, DROP COLUMN vim_info;"
     echo "      Remove 'sce_vnf_id','datacenter_id','vim_tenant_id' field from 'instance_vnfs'"
-    echo "ALTER TABLE instance_vnfs DROP COLUMN sce_vnf_id, DROP FOREIGN KEY FK_instance_vnfs_sce_vnfs;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vnfs DROP COLUMN vim_tenant_id, DROP FOREIGN KEY FK_instance_vnfs_vim_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_vnfs DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_instance_vnfs_datacenters;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vnfs DROP COLUMN sce_vnf_id, DROP FOREIGN KEY FK_instance_vnfs_sce_vnfs;"
+    sql "ALTER TABLE instance_vnfs DROP COLUMN vim_tenant_id, DROP FOREIGN KEY FK_instance_vnfs_vim_tenants;"
+    sql "ALTER TABLE instance_vnfs DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_instance_vnfs_datacenters;"
     echo "      Remove 'sce_net_id','net_id','datacenter_id','vim_tenant_id' field from 'instance_nets'"
-    echo "ALTER TABLE instance_nets DROP COLUMN sce_net_id, DROP FOREIGN KEY FK_instance_nets_sce_nets;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets DROP COLUMN net_id, DROP FOREIGN KEY FK_instance_nets_nets;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets DROP COLUMN vim_tenant_id, DROP FOREIGN KEY FK_instance_nets_vim_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_instance_nets_datacenters;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='6';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets DROP COLUMN sce_net_id, DROP FOREIGN KEY FK_instance_nets_sce_nets;"
+    sql "ALTER TABLE instance_nets DROP COLUMN net_id, DROP FOREIGN KEY FK_instance_nets_nets;"
+    sql "ALTER TABLE instance_nets DROP COLUMN vim_tenant_id, DROP FOREIGN KEY FK_instance_nets_vim_tenants;"
+    sql "ALTER TABLE instance_nets DROP COLUMN datacenter_id, DROP FOREIGN KEY FK_instance_nets_datacenters;"
+    sql "DELETE FROM schema_version WHERE version_int='6';"
 }
 
 function upgrade_to_7(){
@@ -455,14 +457,14 @@ function upgrade_to_7(){
     for table in datacenters datacenter_nets instance_nets instance_scenarios instance_vms instance_vnfs interfaces nets nfvo_tenants scenarios sce_interfaces sce_nets sce_vnfs tenants_datacenters vim_tenants vms vnfs uuids
     do
          echo -en "        $table               \r"
-         echo "ALTER TABLE $table ADD COLUMN created_at_ DOUBLE NOT NULL after created_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "UPDATE $table SET created_at_=unix_timestamp(created_at);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "ALTER TABLE $table DROP COLUMN created_at, CHANGE COLUMN created_at_ created_at DOUBLE NOT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         [[ $table == uuids ]] || echo "ALTER TABLE $table CHANGE COLUMN modified_at modified_at DOUBLE NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+         sql "ALTER TABLE $table ADD COLUMN created_at_ DOUBLE NOT NULL after created_at;"
+         echo "UPDATE $table SET created_at_=unix_timestamp(created_at);"
+         sql "ALTER TABLE $table DROP COLUMN created_at, CHANGE COLUMN created_at_ created_at DOUBLE NOT NULL;"
+         [[ $table == uuids ]] || sql "ALTER TABLE $table CHANGE COLUMN modified_at modified_at DOUBLE NULL DEFAULT NULL;"
     done
     
     echo "      Add 'descriptor' field text to 'vnfd', 'scenarios'"
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (7, '0.7', '0.4.3', 'Changing created_at time at database', '2016-01-25');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (7, '0.7', '0.4.3', 'Changing created_at time at database', '2016-01-25');"
 }
 function downgrade_from_7(){
     # echo "    downgrade database from version 0.7 to version 0.6"
@@ -470,13 +472,13 @@ function downgrade_from_7(){
     for table in datacenters datacenter_nets instance_nets instance_scenarios instance_vms instance_vnfs interfaces nets nfvo_tenants scenarios sce_interfaces sce_nets sce_vnfs tenants_datacenters vim_tenants vms vnfs uuids
     do
          echo -en "        $table               \r"
-         echo "ALTER TABLE $table ADD COLUMN created_at_ TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP after created_at;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "UPDATE $table SET created_at_=from_unixtime(created_at);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "ALTER TABLE $table DROP COLUMN created_at, CHANGE COLUMN created_at_ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         [[ $table == uuids ]] || echo "ALTER TABLE $table CHANGE COLUMN modified_at modified_at TIMESTAMP NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+         sql "ALTER TABLE $table ADD COLUMN created_at_ TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP after created_at;"
+         echo "UPDATE $table SET created_at_=from_unixtime(created_at);"
+         sql "ALTER TABLE $table DROP COLUMN created_at, CHANGE COLUMN created_at_ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;"
+         [[ $table == uuids ]] || sql "ALTER TABLE $table CHANGE COLUMN modified_at modified_at TIMESTAMP NULL DEFAULT NULL;"
     done
     echo "      Remove 'descriptor' field from 'vnfd', 'scenarios' tables"
-    echo "DELETE FROM schema_version WHERE version_int='7';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DELETE FROM schema_version WHERE version_int='7';"
 }
 
 function upgrade_to_8(){
@@ -485,15 +487,15 @@ function upgrade_to_8(){
     for table in datacenters datacenter_nets flavors images instance_scenarios nets nfvo_tenants scenarios sce_nets sce_vnfs vms vnfs
     do
          echo -en "        $table               \r"
-         echo "ALTER TABLE $table CHANGE COLUMN name name VARCHAR(255) NOT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "ALTER TABLE $table CHANGE COLUMN description description VARCHAR(255) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+         sql "ALTER TABLE $table CHANGE COLUMN name name VARCHAR(255) NOT NULL;"
+         sql "ALTER TABLE $table CHANGE COLUMN description description VARCHAR(255) NULL DEFAULT NULL;"
     done
     echo -en "        interfaces           \r"
-    echo "ALTER TABLE interfaces CHANGE COLUMN internal_name internal_name VARCHAR(255) NOT NULL, CHANGE COLUMN external_name external_name VARCHAR(255) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(64) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces CHANGE COLUMN internal_name internal_name VARCHAR(255) NOT NULL, CHANGE COLUMN external_name external_name VARCHAR(255) NULL DEFAULT NULL;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(64) NULL DEFAULT NULL;"
     echo -en "        vim_tenants          \r"
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN user user VARCHAR(64) NULL DEFAULT NULL, CHANGE COLUMN passwd passwd VARCHAR(64) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (8, '0.8', '0.4.32', 'Enlarging name at database', '2016-02-01');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN user user VARCHAR(64) NULL DEFAULT NULL, CHANGE COLUMN passwd passwd VARCHAR(64) NULL DEFAULT NULL;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (8, '0.8', '0.4.32', 'Enlarging name at database', '2016-02-01');"
 }
 function downgrade_from_8(){
     # echo "    downgrade database from version 0.8 to version 0.7"
@@ -503,89 +505,89 @@ function downgrade_from_8(){
          name_length=50
          [[ $table == flavors ]] || [[ $table == images ]] || name_length=36 
          echo -en "        $table               \r"
-         echo "ALTER TABLE $table CHANGE COLUMN name name VARCHAR($name_length) NOT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-         echo "ALTER TABLE $table CHANGE COLUMN description description VARCHAR(100) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+         sql "ALTER TABLE $table CHANGE COLUMN name name VARCHAR($name_length) NOT NULL;"
+         sql "ALTER TABLE $table CHANGE COLUMN description description VARCHAR(100) NULL DEFAULT NULL;"
     done
     echo -en "        interfaces           \r"
-    echo "ALTER TABLE interfaces CHANGE COLUMN internal_name internal_name VARCHAR(25) NOT NULL, CHANGE COLUMN external_name external_name VARCHAR(25) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces CHANGE COLUMN internal_name internal_name VARCHAR(25) NOT NULL, CHANGE COLUMN external_name external_name VARCHAR(25) NULL DEFAULT NULL;"
     echo -en "        vim_tenants          \r"
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(36) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vim_tenants CHANGE COLUMN user user VARCHAR(36) NULL DEFAULT NULL, CHANGE COLUMN passwd passwd VARCHAR(50) NULL DEFAULT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='8';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(36) NULL DEFAULT NULL;"
+    sql "ALTER TABLE vim_tenants CHANGE COLUMN user user VARCHAR(36) NULL DEFAULT NULL, CHANGE COLUMN passwd passwd VARCHAR(50) NULL DEFAULT NULL;"
+    sql "DELETE FROM schema_version WHERE version_int='8';"
 }
 function upgrade_to_9(){
     # echo "    upgrade database from version 0.8 to version 0.9"
     echo "      Add more status to 'instance_vms'"
-    echo "ALTER TABLE instance_vms CHANGE COLUMN status status ENUM('ACTIVE:NoMgmtIP','ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (9, '0.9', '0.4.33', 'Add ACTIVE:NoMgmtIP to instance_vms table', '2016-02-05');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vms CHANGE COLUMN status status ENUM('ACTIVE:NoMgmtIP','ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD';"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (9, '0.9', '0.4.33', 'Add ACTIVE:NoMgmtIP to instance_vms table', '2016-02-05');"
 }
 function downgrade_from_9(){
     # echo "    downgrade database from version 0.9 to version 0.8"
     echo "      Add more status to 'instance_vms'"
-    echo "ALTER TABLE instance_vms CHANGE COLUMN status status ENUM('ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='9';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_vms CHANGE COLUMN status status ENUM('ACTIVE','INACTIVE','BUILD','ERROR','VIM_ERROR','PAUSED','SUSPENDED','DELETED') NOT NULL DEFAULT 'BUILD';"
+    sql "DELETE FROM schema_version WHERE version_int='9';"
 }
 function upgrade_to_10(){
     # echo "    upgrade database from version 0.9 to version 0.10"
     echo "      add tenant to 'vnfs'"
-    echo "ALTER TABLE vnfs ADD COLUMN tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER name, ADD CONSTRAINT FK_vnfs_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid) ON UPDATE CASCADE ON DELETE SET NULL, CHANGE COLUMN public public ENUM('true','false') NOT NULL DEFAULT 'false' AFTER physical, DROP INDEX name, DROP INDEX path, DROP COLUMN path;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios DROP FOREIGN KEY FK_scenarios_nfvo_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios CHANGE COLUMN nfvo_tenant_id tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_scenarios_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios DROP FOREIGN KEY FK_instance_scenarios_nfvo_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios CHANGE COLUMN nfvo_tenant_id tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_instance_scenarios_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vnfs ADD COLUMN tenant_id VARCHAR(36) NULL DEFAULT NULL AFTER name, ADD CONSTRAINT FK_vnfs_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid) ON UPDATE CASCADE ON DELETE SET NULL, CHANGE COLUMN public public ENUM('true','false') NOT NULL DEFAULT 'false' AFTER physical, DROP INDEX name, DROP INDEX path, DROP COLUMN path;"
+    sql "ALTER TABLE scenarios DROP FOREIGN KEY FK_scenarios_nfvo_tenants;"
+    sql "ALTER TABLE scenarios CHANGE COLUMN nfvo_tenant_id tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_scenarios_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid);"
+    sql "ALTER TABLE instance_scenarios DROP FOREIGN KEY FK_instance_scenarios_nfvo_tenants;"
+    sql "ALTER TABLE instance_scenarios CHANGE COLUMN nfvo_tenant_id tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_instance_scenarios_nfvo_tenants FOREIGN KEY (tenant_id) REFERENCES nfvo_tenants (uuid);"
     echo "      rename 'vim_tenants' table to 'datacenter_tenants'"
-    echo "RENAME TABLE vim_tenants TO datacenter_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "RENAME TABLE vim_tenants TO datacenter_tenants;"
     for table in tenants_datacenters instance_scenarios instance_vnfs instance_nets
     do
         NULL="NOT NULL"
         [[ $table == instance_vnfs ]] && NULL="NULL DEFAULT NULL"
-        echo "ALTER TABLE ${table} DROP FOREIGN KEY FK_${table}_vim_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-        echo "ALTER TABLE ${table} ALTER vim_tenant_id DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-        echo "ALTER TABLE ${table} CHANGE COLUMN vim_tenant_id datacenter_tenant_id VARCHAR(36)  ${NULL} AFTER datacenter_id, ADD CONSTRAINT FK_${table}_datacenter_tenants FOREIGN KEY (datacenter_tenant_id) REFERENCES datacenter_tenants (uuid); " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE ${table} DROP FOREIGN KEY FK_${table}_vim_tenants;"
+        sql "ALTER TABLE ${table} ALTER vim_tenant_id DROP DEFAULT;"
+        sql "ALTER TABLE ${table} CHANGE COLUMN vim_tenant_id datacenter_tenant_id VARCHAR(36)  ${NULL} AFTER datacenter_id, ADD CONSTRAINT FK_${table}_datacenter_tenants FOREIGN KEY (datacenter_tenant_id) REFERENCES datacenter_tenants (uuid); "
     done    
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (10, '0.10', '0.4.36', 'tenant management of vnfs,scenarios', '2016-03-08');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (10, '0.10', '0.4.36', 'tenant management of vnfs,scenarios', '2016-03-08');"
 }
 
 function downgrade_from_10(){
     # echo "    downgrade database from version 0.10 to version 0.9"
     echo "      remove tenant from 'vnfs'"
-    echo "ALTER TABLE vnfs DROP COLUMN tenant_id, DROP FOREIGN KEY FK_vnfs_nfvo_tenants, ADD UNIQUE INDEX name (name), ADD COLUMN path VARCHAR(100) NULL DEFAULT NULL COMMENT 'Path where the YAML descriptor of the VNF can be found. NULL if it is a physical network function.' AFTER name, ADD UNIQUE INDEX path (path), CHANGE COLUMN public public ENUM('true','false') NOT NULL DEFAULT 'true' AFTER physical;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios DROP FOREIGN KEY FK_scenarios_nfvo_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE scenarios CHANGE COLUMN tenant_id nfvo_tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_scenarios_nfvo_tenants FOREIGN KEY (nfvo_tenant_id) REFERENCES nfvo_tenants (uuid);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios DROP FOREIGN KEY FK_instance_scenarios_nfvo_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios CHANGE COLUMN tenant_id nfvo_tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_instance_scenarios_nfvo_tenants FOREIGN KEY (nfvo_tenant_id) REFERENCES nfvo_tenants (uuid);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vnfs DROP COLUMN tenant_id, DROP FOREIGN KEY FK_vnfs_nfvo_tenants, ADD UNIQUE INDEX name (name), ADD COLUMN path VARCHAR(100) NULL DEFAULT NULL COMMENT 'Path where the YAML descriptor of the VNF can be found. NULL if it is a physical network function.' AFTER name, ADD UNIQUE INDEX path (path), CHANGE COLUMN public public ENUM('true','false') NOT NULL DEFAULT 'true' AFTER physical;"
+    sql "ALTER TABLE scenarios DROP FOREIGN KEY FK_scenarios_nfvo_tenants;"
+    sql "ALTER TABLE scenarios CHANGE COLUMN tenant_id nfvo_tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_scenarios_nfvo_tenants FOREIGN KEY (nfvo_tenant_id) REFERENCES nfvo_tenants (uuid);"
+    sql "ALTER TABLE instance_scenarios DROP FOREIGN KEY FK_instance_scenarios_nfvo_tenants;"
+    sql "ALTER TABLE instance_scenarios CHANGE COLUMN tenant_id nfvo_tenant_id VARCHAR(36) NULL DEFAULT NULL after name, ADD CONSTRAINT FK_instance_scenarios_nfvo_tenants FOREIGN KEY (nfvo_tenant_id) REFERENCES nfvo_tenants (uuid);"
     echo "      rename back 'datacenter_tenants' table to 'vim_tenants'"
-    echo "RENAME TABLE datacenter_tenants TO vim_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "RENAME TABLE datacenter_tenants TO vim_tenants;"
     for table in tenants_datacenters instance_scenarios instance_vnfs instance_nets
     do
-        echo "ALTER TABLE ${table} DROP FOREIGN KEY FK_${table}_datacenter_tenants;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE ${table} DROP FOREIGN KEY FK_${table}_datacenter_tenants;"
         NULL="NOT NULL"
         [[ $table == instance_vnfs ]] && NULL="NULL DEFAULT NULL"
-        echo "ALTER TABLE ${table} ALTER datacenter_tenant_id DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-        echo "ALTER TABLE ${table} CHANGE COLUMN datacenter_tenant_id vim_tenant_id VARCHAR(36) $NULL AFTER datacenter_id, ADD CONSTRAINT FK_${table}_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid); " | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        sql "ALTER TABLE ${table} ALTER datacenter_tenant_id DROP DEFAULT;"
+        sql "ALTER TABLE ${table} CHANGE COLUMN datacenter_tenant_id vim_tenant_id VARCHAR(36) $NULL AFTER datacenter_id, ADD CONSTRAINT FK_${table}_vim_tenants FOREIGN KEY (vim_tenant_id) REFERENCES vim_tenants (uuid); "
     done    
-    echo "DELETE FROM schema_version WHERE version_int='10';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DELETE FROM schema_version WHERE version_int='10';"
 }
 
 function upgrade_to_11(){
     # echo "    upgrade database from version 0.10 to version 0.11"
     echo "      remove unique name at 'scenarios', 'instance_scenarios'"
-    echo "ALTER TABLE scenarios DROP INDEX name;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios DROP INDEX name;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (11, '0.11', '0.4.43', 'remove unique name at scenarios,instance_scenarios', '2016-07-18');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE scenarios DROP INDEX name;"
+    sql "ALTER TABLE instance_scenarios DROP INDEX name;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (11, '0.11', '0.4.43', 'remove unique name at scenarios,instance_scenarios', '2016-07-18');"
 }
 function downgrade_from_11(){
     # echo "    downgrade database from version 0.11 to version 0.10"
     echo "      add unique name at 'scenarios', 'instance_scenarios'"
-    echo "ALTER TABLE scenarios ADD UNIQUE INDEX name (name);"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios ADD UNIQUE INDEX name (name);"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='11';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE scenarios ADD UNIQUE INDEX name (name);"
+    sql "ALTER TABLE instance_scenarios ADD UNIQUE INDEX name (name);"
+    sql "DELETE FROM schema_version WHERE version_int='11';"
 }
 
 function upgrade_to_12(){
     # echo "    upgrade database from version 0.11 to version 0.12"
     echo "      create ip_profiles table, with foreign keys to all nets tables, and add ip_address column to 'interfaces' and 'sce_interfaces'"
-    echo "CREATE TABLE IF NOT EXISTS ip_profiles (
+    sql "CREATE TABLE IF NOT EXISTS ip_profiles (
        id INT(11) NOT NULL AUTO_INCREMENT,
        net_id VARCHAR(36) NULL DEFAULT NULL,
        sce_net_id VARCHAR(36) NULL DEFAULT NULL,
@@ -603,201 +605,248 @@ function upgrade_to_12(){
        CONSTRAINT FK_ipprofiles_instancenets FOREIGN KEY (instance_net_id) REFERENCES instance_nets (uuid) ON DELETE CASCADE  )
         COMMENT='Table containing the IP parameters of a network, either a net, a sce_net or and instance_net.'
         COLLATE='utf8_general_ci'
-        ENGINE=InnoDB;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE interfaces ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER mac;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE sce_interfaces ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER interface_id;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (12, '0.12', '0.4.46', 'create ip_profiles table, with foreign keys to all nets tables, and add ip_address column to interfaces and sce_interfaces', '2016-08-29');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+        ENGINE=InnoDB;"
+    sql "ALTER TABLE interfaces ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER mac;"
+    sql "ALTER TABLE sce_interfaces ADD COLUMN ip_address VARCHAR(64) NULL DEFAULT NULL AFTER interface_id;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (12, '0.12', '0.4.46', 'create ip_profiles table, with foreign keys to all nets tables, and add ip_address column to interfaces and sce_interfaces', '2016-08-29');"
 }
 function downgrade_from_12(){
     # echo "    downgrade database from version 0.12 to version 0.11"
     echo "      delete ip_profiles table, and remove ip_address column in 'interfaces' and 'sce_interfaces'"
-    echo "DROP TABLE ip_profiles;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE interfaces DROP COLUMN ip_address;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE sce_interfaces DROP COLUMN ip_address;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='12';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DROP TABLE ip_profiles;"
+    sql "ALTER TABLE interfaces DROP COLUMN ip_address;"
+    sql "ALTER TABLE sce_interfaces DROP COLUMN ip_address;"
+    sql "DELETE FROM schema_version WHERE version_int='12';"
 }
 
 function upgrade_to_13(){
     # echo "    upgrade database from version 0.12 to version 0.13"
     echo "      add cloud_config at 'scenarios', 'instance_scenarios'"
-    echo "ALTER TABLE scenarios ADD COLUMN cloud_config MEDIUMTEXT NULL DEFAULT NULL AFTER descriptor;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios ADD COLUMN cloud_config MEDIUMTEXT NULL DEFAULT NULL AFTER modified_at;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (13, '0.13', '0.4.47', 'insert cloud-config at scenarios,instance_scenarios', '2016-08-30');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE scenarios ADD COLUMN cloud_config MEDIUMTEXT NULL DEFAULT NULL AFTER descriptor;"
+    sql "ALTER TABLE instance_scenarios ADD COLUMN cloud_config MEDIUMTEXT NULL DEFAULT NULL AFTER modified_at;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (13, '0.13', '0.4.47', 'insert cloud-config at scenarios,instance_scenarios', '2016-08-30');"
 }
 function downgrade_from_13(){
     # echo "    downgrade database from version 0.13 to version 0.12"
     echo "      remove cloud_config at 'scenarios', 'instance_scenarios'"
-    echo "ALTER TABLE scenarios DROP COLUMN cloud_config;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_scenarios DROP COLUMN cloud_config;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='13';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE scenarios DROP COLUMN cloud_config;"
+    sql "ALTER TABLE instance_scenarios DROP COLUMN cloud_config;"
+    sql "DELETE FROM schema_version WHERE version_int='13';"
 }
 
 function upgrade_to_14(){
     # echo "    upgrade database from version 0.13 to version 0.14"
     echo "      remove unique index vim_net_id, instance_scenario_id at table 'instance_nets'"
-    echo "ALTER TABLE instance_nets DROP INDEX vim_net_id_instance_scenario_id;"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets CHANGE COLUMN external created ENUM('true','false') NOT NULL DEFAULT 'false' COMMENT 'Created or already exists at VIM' AFTER multipoint;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (14, '0.14', '0.4.57', 'remove unique index vim_net_id, instance_scenario_id', '2016-09-26');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets DROP INDEX vim_net_id_instance_scenario_id;"
+    sql "ALTER TABLE instance_nets CHANGE COLUMN external created ENUM('true','false') NOT NULL DEFAULT 'false' COMMENT 'Created or already exists at VIM' AFTER multipoint;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (14, '0.14', '0.4.57', 'remove unique index vim_net_id, instance_scenario_id', '2016-09-26');"
 }
 function downgrade_from_14(){
     # echo "    downgrade database from version 0.14 to version 0.13"
     echo "      remove cloud_config at 'scenarios', 'instance_scenarios'"
-    echo "ALTER TABLE instance_nets ADD UNIQUE INDEX vim_net_id_instance_scenario_id (vim_net_id, instance_scenario_id);"  | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets CHANGE COLUMN created external ENUM('true','false') NOT NULL DEFAULT 'false' COMMENT 'If external, means that it already exists at VIM' AFTER multipoint;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='14';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets ADD UNIQUE INDEX vim_net_id_instance_scenario_id (vim_net_id, instance_scenario_id);"
+    sql "ALTER TABLE instance_nets CHANGE COLUMN created external ENUM('true','false') NOT NULL DEFAULT 'false' COMMENT 'If external, means that it already exists at VIM' AFTER multipoint;"
+    sql "DELETE FROM schema_version WHERE version_int='14';"
 }
 
 function upgrade_to_15(){
     # echo "    upgrade database from version 0.14 to version 0.15"
     echo "      add columns 'universal_name' and 'checksum' at table 'images', add unique index universal_name_checksum, and change location to allow NULL; change column 'image_path' in table 'vms' to allow NULL"
-    echo "ALTER TABLE images ADD COLUMN checksum VARCHAR(32) NULL DEFAULT NULL AFTER name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images ALTER location DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images ADD COLUMN universal_name VARCHAR(255) NULL AFTER name, CHANGE COLUMN location location VARCHAR(200) NULL AFTER checksum, ADD UNIQUE INDEX universal_name_checksum (universal_name, checksum);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vms ALTER image_path DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (15, '0.15', '0.4.59', 'add columns universal_name and checksum at table images, add unique index universal_name_checksum, and change location to allow NULL; change column image_path in table vms to allow NULL', '2016-09-27');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE images ADD COLUMN checksum VARCHAR(32) NULL DEFAULT NULL AFTER name;"
+    sql "ALTER TABLE images ALTER location DROP DEFAULT;"
+    sql "ALTER TABLE images ADD COLUMN universal_name VARCHAR(255) NULL AFTER name, CHANGE COLUMN location location VARCHAR(200) NULL AFTER checksum, ADD UNIQUE INDEX universal_name_checksum (universal_name, checksum);"
+    sql "ALTER TABLE vms ALTER image_path DROP DEFAULT;"
+    sql "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (15, '0.15', '0.4.59', 'add columns universal_name and checksum at table images, add unique index universal_name_checksum, and change location to allow NULL; change column image_path in table vms to allow NULL', '2016-09-27');"
 }
 function downgrade_from_15(){
     # echo "    downgrade database from version 0.15 to version 0.14"
     echo "      remove columns 'universal_name' and 'checksum' from table 'images', remove index universal_name_checksum, change location NOT NULL; change column 'image_path' in table 'vms' to NOT NULL"
-    echo "ALTER TABLE images DROP INDEX universal_name_checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images ALTER location DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images CHANGE COLUMN location location VARCHAR(200) NOT NULL AFTER checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images DROP COLUMN universal_name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE images DROP COLUMN checksum;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vms ALTER image_path DROP DEFAULT;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NOT NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='15';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE images DROP INDEX universal_name_checksum;"
+    sql "ALTER TABLE images ALTER location DROP DEFAULT;"
+    sql "ALTER TABLE images CHANGE COLUMN location location VARCHAR(200) NOT NULL AFTER checksum;"
+    sql "ALTER TABLE images DROP COLUMN universal_name;"
+    sql "ALTER TABLE images DROP COLUMN checksum;"
+    sql "ALTER TABLE vms ALTER image_path DROP DEFAULT;"
+    sql "ALTER TABLE vms CHANGE COLUMN image_path image_path VARCHAR(100) NOT NULL COMMENT 'Path where the image of the VM is located' AFTER image_id;"
+    sql "DELETE FROM schema_version WHERE version_int='15';"
 }
 
 function upgrade_to_16(){
     # echo "    upgrade database from version 0.15 to version 0.16"
     echo "      add column 'config' at table 'datacenter_tenants', enlarge 'vim_tenant_name/id'"
-    echo "ALTER TABLE datacenter_tenants ADD COLUMN config VARCHAR(4000) NULL DEFAULT NULL AFTER passwd;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(256) NULL DEFAULT NULL AFTER datacenter_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(256) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (16, '0.16', '0.5.2', 'enlarge vim_tenant_name and id. New config at datacenter_tenants', '2016-10-11');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenter_tenants ADD COLUMN config VARCHAR(4000) NULL DEFAULT NULL AFTER passwd;"
+    sql "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(256) NULL DEFAULT NULL AFTER datacenter_id;"
+    sql "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(256) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (16, '0.16', '0.5.2', 'enlarge vim_tenant_name and id. New config at datacenter_tenants', '2016-10-11');"
 }
 function downgrade_from_16(){
     # echo "    downgrade database from version 0.16 to version 0.15"
     echo "      remove column 'config' at table 'datacenter_tenants', restoring lenght 'vim_tenant_name/id'"
-    echo "ALTER TABLE datacenter_tenants DROP COLUMN config;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(64) NULL DEFAULT NULL AFTER datacenter_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='16';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenter_tenants DROP COLUMN config;"
+    sql "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_name vim_tenant_name VARCHAR(64) NULL DEFAULT NULL AFTER datacenter_id;"
+    sql "ALTER TABLE datacenter_tenants CHANGE COLUMN vim_tenant_id vim_tenant_id VARCHAR(36) NULL DEFAULT NULL COMMENT 'Tenant ID at VIM' AFTER vim_tenant_name;"
+    sql "DELETE FROM schema_version WHERE version_int='16';"
 }
 
 function upgrade_to_17(){
     # echo "    upgrade database from version 0.16 to version 0.17"
     echo "      add column 'extended' at table 'datacenter_flavors'"
-    echo "ALTER TABLE datacenters_flavors ADD extended varchar(2000) NULL COMMENT 'Extra description json format of additional devices';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (17, '0.17', '0.5.3', 'Extra description json format of additional devices in datacenter_flavors', '2016-12-20');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters_flavors ADD extended varchar(2000) NULL COMMENT 'Extra description json format of additional devices';"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (17, '0.17', '0.5.3', 'Extra description json format of additional devices in datacenter_flavors', '2016-12-20');"
 }
 function downgrade_from_17(){
     # echo "    downgrade database from version 0.17 to version 0.16"
     echo "      remove column 'extended' from table 'datacenter_flavors'"
-    echo "ALTER TABLE datacenters_flavors DROP COLUMN extended;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='17';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenters_flavors DROP COLUMN extended;"
+    sql "DELETE FROM schema_version WHERE version_int='17';"
 }
 
 function upgrade_to_18(){
     # echo "    upgrade database from version 0.17 to version 0.18"
     echo "      add columns 'floating_ip' and 'port_security' at tables 'interfaces' and 'instance_interfaces'"
-    echo "ALTER TABLE interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (18, '0.18', '0.5.4', 'Add columns \'floating_ip\' and \'port_security\' at tables \'interfaces\' and \'instance_interfaces\'', '2017-01-09');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';"
+    sql "ALTER TABLE interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';"
+    sql "ALTER TABLE instance_interfaces ADD floating_ip BOOL DEFAULT 0 NOT NULL COMMENT 'Indicates if a floating_ip must be associated to this interface';"
+    sql "ALTER TABLE instance_interfaces ADD port_security BOOL DEFAULT 1 NOT NULL COMMENT 'Indicates if port security must be enabled or disabled. By default it is enabled';"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (18, '0.18', '0.5.4', 'Add columns \'floating_ip\' and \'port_security\' at tables \'interfaces\' and \'instance_interfaces\'', '2017-01-09');"
 }
 function downgrade_from_18(){
     # echo "    downgrade database from version 0.18 to version 0.17"
     echo "      remove columns 'floating_ip' and 'port_security' from tables 'interfaces' and 'instance_interfaces'"
-    echo "ALTER TABLE interfaces DROP COLUMN floating_ip;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE interfaces DROP COLUMN port_security;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN floating_ip;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN port_security;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='18';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE interfaces DROP COLUMN floating_ip;"
+    sql "ALTER TABLE interfaces DROP COLUMN port_security;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN floating_ip;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN port_security;"
+    sql "DELETE FROM schema_version WHERE version_int='18';"
 }
 
 function upgrade_to_19(){
     # echo "    upgrade database from version 0.18 to version 0.19"
     echo "      add column 'boot_data' at table 'vms'"
-    echo "ALTER TABLE vms ADD COLUMN boot_data TEXT NULL DEFAULT NULL AFTER image_path;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (19, '0.19', '0.5.5', 'Extra Boot-data content at VNFC (vms)', '2017-01-11');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vms ADD COLUMN boot_data TEXT NULL DEFAULT NULL AFTER image_path;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (19, '0.19', '0.5.5', 'Extra Boot-data content at VNFC (vms)', '2017-01-11');"
 }
 function downgrade_from_19(){
     # echo "    downgrade database from version 0.19 to version 0.18"
     echo "      remove column 'boot_data' from table 'vms'"
-    echo "ALTER TABLE vms DROP COLUMN boot_data;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='19';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE vms DROP COLUMN boot_data;"
+    sql "DELETE FROM schema_version WHERE version_int='19';"
 }
 
 function upgrade_to_20(){
     # echo "    upgrade database from version 0.19 to version 0.20"
     echo "      add column 'sdn_net_id' at table 'instance_nets' and columns 'sdn_port_id', 'compute_node', 'pci' and 'vlan' to table 'instance_interfaces'"
-    echo "ALTER TABLE instance_nets ADD sdn_net_id varchar(36) DEFAULT NULL NULL COMMENT 'Network id in ovim';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD sdn_port_id varchar(36) DEFAULT NULL NULL COMMENT 'Port id in ovim';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD compute_node varchar(100) DEFAULT NULL NULL COMMENT 'Compute node id used to specify the SDN port mapping';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD pci varchar(12) DEFAULT NULL NULL COMMENT 'PCI of the physical port in the host';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces ADD vlan SMALLINT UNSIGNED DEFAULT NULL NULL COMMENT 'VLAN tag used by the port';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (20, '0.20', '0.5.9', 'Added columns to store dataplane connectivity info', '2017-03-13');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets ADD sdn_net_id varchar(36) DEFAULT NULL NULL COMMENT 'Network id in ovim';"
+    sql "ALTER TABLE instance_interfaces ADD sdn_port_id varchar(36) DEFAULT NULL NULL COMMENT 'Port id in ovim';"
+    sql "ALTER TABLE instance_interfaces ADD compute_node varchar(100) DEFAULT NULL NULL COMMENT 'Compute node id used to specify the SDN port mapping';"
+    sql "ALTER TABLE instance_interfaces ADD pci varchar(12) DEFAULT NULL NULL COMMENT 'PCI of the physical port in the host';"
+    sql "ALTER TABLE instance_interfaces ADD vlan SMALLINT UNSIGNED DEFAULT NULL NULL COMMENT 'VLAN tag used by the port';"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (20, '0.20', '0.5.9', 'Added columns to store dataplane connectivity info', '2017-03-13');"
 }
 function downgrade_from_20(){
     # echo "    downgrade database from version 0.20 to version 0.19"
     echo "      remove column 'sdn_net_id' at table 'instance_nets' and columns 'sdn_port_id', 'compute_node', 'pci' and 'vlan' to table 'instance_interfaces'"
-    echo "ALTER TABLE instance_nets DROP COLUMN sdn_net_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN vlan;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN pci;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN compute_node;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_interfaces DROP COLUMN sdn_port_id;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='20';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets DROP COLUMN sdn_net_id;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN vlan;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN pci;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN compute_node;"
+    sql "ALTER TABLE instance_interfaces DROP COLUMN sdn_port_id;"
+    sql "DELETE FROM schema_version WHERE version_int='20';"
 }
 
 function upgrade_to_21(){
     # echo "    upgrade database from version 0.20 to version 0.21"
     echo "      edit 'instance_nets' to allow instance_scenario_id=None"
-    echo "ALTER TABLE instance_nets MODIFY COLUMN instance_scenario_id varchar(36) NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE instance_nets MODIFY COLUMN instance_scenario_id varchar(36) NULL;"
     echo "      enlarge column 'dns_address' at table 'ip_profiles'"
-    echo "ALTER TABLE ip_profiles MODIFY dns_address varchar(255) DEFAULT NULL NULL "\
-         "comment 'dns ip list separated by semicolon';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (21, '0.21', '0.5.15', 'Edit instance_nets to allow instance_scenario_id=None and enlarge column dns_address at table ip_profiles', '2017-06-02');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE ip_profiles MODIFY dns_address varchar(255) DEFAULT NULL NULL "\
+         "comment 'dns ip list separated by semicolon';"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (21, '0.21', '0.5.15', 'Edit instance_nets to allow instance_scenario_id=None and enlarge column dns_address at table ip_profiles', '2017-06-02');"
 }
 function downgrade_from_21(){
     # echo "    downgrade database from version 0.21 to version 0.20"
     echo "      edit 'instance_nets' to disallow instance_scenario_id=None"
     #Delete all lines with a instance_scenario_id=NULL in order to disable this option
-    echo "DELETE FROM instance_nets WHERE instance_scenario_id IS NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "ALTER TABLE instance_nets MODIFY COLUMN instance_scenario_id varchar(36) NOT NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "DELETE FROM instance_nets WHERE instance_scenario_id IS NULL;"
+    sql "ALTER TABLE instance_nets MODIFY COLUMN instance_scenario_id varchar(36) NOT NULL;"
     echo "      shorten column 'dns_address' at table 'ip_profiles'"
-    echo "ALTER TABLE ip_profiles MODIFY dns_address varchar(64) DEFAULT NULL NULL;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='21';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE ip_profiles MODIFY dns_address varchar(64) DEFAULT NULL NULL;"
+    sql "DELETE FROM schema_version WHERE version_int='21';"
 }
 
 function upgrade_to_22(){
     # echo "    upgrade database from version 0.21 to version 0.22"
     echo "      Changed type of ram in 'flavors' from SMALLINT to MEDIUMINT"
-    echo "ALTER TABLE flavors CHANGE COLUMN ram ram MEDIUMINT(7) UNSIGNED NULL DEFAULT NULL AFTER disk;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (22, '0.22', '0.5.16', 'Changed type of ram in flavors from SMALLINT to MEDIUMINT', '2017-06-02');" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE flavors CHANGE COLUMN ram ram MEDIUMINT(7) UNSIGNED NULL DEFAULT NULL AFTER disk;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (22, '0.22', '0.5.16', 'Changed type of ram in flavors from SMALLINT to MEDIUMINT', '2017-06-02');"
 }
 function downgrade_from_22(){
     # echo "    downgrade database from version 0.22 to version 0.21"
     echo "      Changed type of ram in 'flavors' from MEDIUMINT to SMALLINT"
-    echo "ALTER TABLE flavors CHANGE COLUMN ram ram SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER disk;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
-    echo "DELETE FROM schema_version WHERE version_int='22';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE flavors CHANGE COLUMN ram ram SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER disk;"
+    sql "DELETE FROM schema_version WHERE version_int='22';"
+}
+
+function upgrade_to_23(){
+    # echo "    upgrade database from version 0.22 to version 0.23"
+    echo "      add column 'availability_zone' at table 'vms'"
+    sql "ALTER TABLE mano_db.vms ADD COLUMN availability_zone VARCHAR(255) NULL AFTER modified_at;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) VALUES (23, '0.23', '0.5.20',"\
+        "'Changed type of ram in flavors from SMALLINT to MEDIUMINT', '2017-08-29');"
+}
+function downgrade_from_23(){
+    # echo "    downgrade database from version 0.23 to version 0.22"
+    echo "      remove column 'availability_zone' from table 'vms'"
+    sql "ALTER TABLE mano_db.vms DROP COLUMN availability_zone;"
+    sql "DELETE FROM schema_version WHERE version_int='23';"
+}
+
+function upgrade_to_24(){
+    # echo "    upgrade database from version 0.23 to version 0.24"
+    echo "      Add 'count' to table 'vms'"
+    sql "ALTER TABLE vms ADD COLUMN count SMALLINT NOT NULL DEFAULT '1' AFTER vnf_id;"
+    sql "INSERT INTO schema_version (version_int, version, openmano_ver, comments, date) "\
+         "VALUES (24, '0.24', '0.5.21', 'Added vnfd fields', '2017-08-29');"
+}
+function downgrade_from_24(){
+    # echo "    downgrade database from version 0.24 to version 0.23"
+    echo "      Remove 'count' from table 'vms'"
+    sql "ALTER TABLE vms DROP COLUMN count;"
+    sql "DELETE FROM schema_version WHERE version_int='24';"
 }
 
 function upgrade_to_X(){
     echo "      change 'datacenter_nets'"
-    echo "ALTER TABLE datacenter_nets ADD COLUMN vim_tenant_id VARCHAR(36) NOT NULL AFTER datacenter_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id, vim_tenant_id);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenter_nets ADD COLUMN vim_tenant_id VARCHAR(36) NOT NULL AFTER datacenter_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id, vim_tenant_id);"
 }
 function downgrade_from_X(){
     echo "      Change back 'datacenter_nets'"
-    echo "ALTER TABLE datacenter_nets DROP COLUMN vim_tenant_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id);" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    sql "ALTER TABLE datacenter_nets DROP COLUMN vim_tenant_id, DROP INDEX name_datacenter_id, ADD UNIQUE INDEX name_datacenter_id (name, datacenter_id);"
 }
-#TODO ... put funtions here
+#TODO ... put functions here
 
 # echo "db version = "${DATABASE_VER_NUM}
-[ $DB_VERSION -eq $DATABASE_VER_NUM ] && echo "    current database version '$DATABASE_VER_NUM' is ok"
+[ $DB_VERSION -eq $DATABASE_VER_NUM ] && echo "    current database version '$DATABASE_VER_NUM' is ok" && exit 0
+
+# Create a backup database content
+TEMPFILE2="$(mktemp -q --tmpdir "backupdb.XXXXXX.sql")"
+trap 'rm -f "$TEMPFILE2"' EXIT
+mysqldump $DEF_EXTRA_FILE_PARAM --add-drop-table --add-drop-database --routines --databases $DBNAME > $TEMPFILE2
+
+function rollback_db()
+{
+    cat $TEMPFILE2 | mysql $DEF_EXTRA_FILE_PARAM && echo "    Rollback database OK" ||
+        echo "    Rollback database FAIL"
+    exit 1
+}
+
+function sql()    # send a sql command
+{
+    echo "$*" | $DBCMD || ! echo "    ERROR. Aborted!" || rollback_db
+    return 0
+}
+
 #UPGRADE DATABASE step by step
 while [ $DB_VERSION -gt $DATABASE_VER_NUM ]
 do
index 8505499..25de71a 100755 (executable)
@@ -1,2 +1,4 @@
 #!/bin/sh
-make package
+make clean all BRANCH=master
+#make install && \
+#make test
index fbd8e2e..94924bd 100755 (executable)
--- a/openmanod
+++ b/openmanod
@@ -48,13 +48,14 @@ import osm_ro
 
 __author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
 __date__ = "$26-aug-2014 11:09:29$"
-__version__ = "0.5.17-r526"
-version_date = "Jul 2017"
-database_version = 22      #expected database schema version
+__version__ = "0.5.21-r531"
+version_date = "Aug 2017"
+database_version = 24      # expected database schema version
 
 global global_config
 global logger
 
+
 class LoadConfigurationException(Exception):
     pass
 
index 4a87721..26e4c00 100644 (file)
@@ -336,7 +336,31 @@ class db_base():
         self.logger.debug(cmd)
         self.cur.execute(cmd) 
         return self.cur.rowcount
-    
+
+    def _new_uuid(self, root_uuid=None, used_table=None, created_time=0):
+        """
+        Generate a new uuid. It DOES NOT begin or end the transaction, so self.con.cursor must be created
+        :param root_uuid: master uuid of the transaction
+        :param used_table: the table this uuid is intended for
+        :param created_time: time of creation
+        :return: the created uuid
+        """
+
+        uuid = str(myUuid.uuid1())
+        # 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, used_table, created_at)
+        self.logger.debug(cmd)
+        self.cur.execute(cmd)
+        return uuid
+
     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 
index a559941..fa87205 100644 (file)
@@ -38,6 +38,7 @@ import console_proxy_thread as cli
 import vimconn
 import logging
 import collections
+from uuid import uuid4
 from db_base import db_base_Exception
 
 import nfvo_db
@@ -334,7 +335,9 @@ def rollback(mydb,  vims, rollback_list):
         if item["where"]=="vim":
             if item["vim_id"] not in vims:
                 continue
-            vim=vims[ item["vim_id"] ]
+            if is_task_id(item["uuid"]):
+                continue
+            vim = vims[item["vim_id"]]
             try:
                 if item["what"]=="image":
                     vim.delete_image(item["uuid"])
@@ -392,12 +395,12 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
             name_dict[ interface["name"] ] = "overlay"
         vnfc_interfaces[ vnfc["name"] ] = name_dict
         # check bood-data info
-        if "boot-data" in vnfc:
-            # check that user-data is incompatible with users and config-files
-            if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
-                raise NfvoException(
-                    "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
-                    HTTP_Bad_Request)
+        if "boot-data" in vnfc:
+            # check that user-data is incompatible with users and config-files
+            if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
+                raise NfvoException(
+                    "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
+                    HTTP_Bad_Request)
 
     #check if the info in external_connections matches with the one in the vnfcs
     name_list=[]
@@ -481,7 +484,7 @@ def check_vnf_descriptor(vnf_descriptor, vnf_descriptor_version=1):
                     HTTP_Bad_Request)
 
 
-def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error = None):
+def create_or_use_image(mydb, vims, image_dict, rollback_list, only_create_at_vim=False, return_on_error=None):
     #look if image exist
     if only_create_at_vim:
         image_mano_id = image_dict['uuid']
@@ -757,6 +760,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
         for vnfc in vnf_descriptor['vnf']['VNFC']:
             VNFCitem={}
             VNFCitem["name"] = vnfc['name']
+            VNFCitem["availability_zone"] = vnfc.get('availability_zone')
             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"])
@@ -827,6 +831,7 @@ def new_vnf(mydb, tenant_id, vnf_descriptor):
             #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
             VNFCDict[vnfc['name']]["image_id"] = image_id
             VNFCDict[vnfc['name']]["image_path"] = vnfc.get('VNFC image')
+            VNFCDict[vnfc['name']]["count"] = vnfc.get('count', 1)
             if vnfc.get("boot-data"):
                 VNFCDict[vnfc['name']]["boot_data"] = yaml.safe_dump(vnfc["boot-data"], default_flow_style=True, width=256)
 
@@ -962,6 +967,7 @@ def new_vnf_v02(mydb, tenant_id, vnf_descriptor):
             #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
             VNFCDict[vnfc['name']]["image_id"] = image_id
             VNFCDict[vnfc['name']]["image_path"] = vnfc.get('VNFC image')
+            VNFCDict[vnfc['name']]["count"] = vnfc.get('count', 1)
             if vnfc.get("boot-data"):
                 VNFCDict[vnfc['name']]["boot_data"] = yaml.safe_dump(vnfc["boot-data"], default_flow_style=True, width=256)
 
@@ -1665,6 +1671,7 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
 
         logger.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
         #For each vnf net, we create it and we add it to instanceNetlist.
+
         for sce_vnf in scenarioDict['vnfs']:
             for net in sce_vnf['nets']:
                 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
@@ -1696,6 +1703,17 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
         #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
         i = 0
         for sce_vnf in scenarioDict['vnfs']:
+            vnf_availability_zones = []
+            for vm in sce_vnf['vms']:
+                vm_av = vm.get('availability_zone')
+                if vm_av and vm_av not in vnf_availability_zones:
+                    vnf_availability_zones.append(vm_av)
+
+            # check if there is enough availability zones available at vim level.
+            if myvims[datacenter_id].availability_zone and vnf_availability_zones:
+                if len(vnf_availability_zones) > len(myvims[datacenter_id].availability_zone):
+                    raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request)
+
             for vm in sce_vnf['vms']:
                 i += 1
                 myVMDict = {}
@@ -1782,8 +1800,16 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
                 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
                 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
                 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
-                vm_id = myvim.new_vminstance(myVMDict['name'],myVMDict['description'],myVMDict.get('start', None),
-                        myVMDict['imageRef'],myVMDict['flavorRef'],myVMDict['networks'])
+
+                if 'availability_zone' in myVMDict:
+                    av_index = vnf_availability_zones.index(myVMDict['availability_zone'])
+                else:
+                    av_index = None
+
+                vm_id = myvim.new_vminstance(myVMDict['name'], myVMDict['description'], myVMDict.get('start', None),
+                                             myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'],
+                                             availability_zone_index=av_index,
+                                             availability_zone_list=vnf_availability_zones)
                 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
                 vm['vim_id'] = vm_id
                 rollbackList.append({'what':'vm','where':'vim','vim_id':datacenter_id,'uuid':vm_id})
@@ -1813,10 +1839,10 @@ def start_scenario(mydb, tenant_id, scenario_id, instance_scenario_name, instanc
 
 
 def unify_cloud_config(cloud_config_preserve, cloud_config):
-    ''' join the cloud config information into cloud_config_preserve.
+    """ join the cloud config information into cloud_config_preserve.
     In case of conflict cloud_config_preserve preserves
-    None is admited
-    '''
+    None is allowed
+    """
     if not cloud_config_preserve and not cloud_config:
         return None
 
@@ -1866,10 +1892,19 @@ def unify_cloud_config(cloud_config_preserve, cloud_config):
         new_cloud_config["boot-data-drive"] = cloud_config_preserve["boot-data-drive"]
 
     # user-data
-    if cloud_config and cloud_config.get("user-data") != None:
-        new_cloud_config["user-data"] = cloud_config["user-data"]
-    if cloud_config_preserve and cloud_config_preserve.get("user-data") != None:
-        new_cloud_config["user-data"] = cloud_config_preserve["user-data"]
+    new_cloud_config["user-data"] = []
+    if cloud_config and cloud_config.get("user-data"):
+        if isinstance(cloud_config["user-data"], list):
+            new_cloud_config["user-data"] += cloud_config["user-data"]
+        else:
+            new_cloud_config["user-data"].append(cloud_config["user-data"])
+    if cloud_config_preserve and cloud_config_preserve.get("user-data"):
+        if isinstance(cloud_config_preserve["user-data"], list):
+            new_cloud_config["user-data"] += cloud_config_preserve["user-data"]
+        else:
+            new_cloud_config["user-data"].append(cloud_config_preserve["user-data"])
+    if not new_cloud_config["user-data"]:
+        del new_cloud_config["user-data"]
 
     # config files
     new_cloud_config["config-files"] = []
@@ -1979,14 +2014,30 @@ def create_instance(mydb, tenant_id, instance_dict):
     #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
     #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
 
-    scenarioDict['datacenter_id'] = default_datacenter_id
+    uuid_list = []
+    instance_name = instance_dict["name"]
+    instance_uuid = str(uuid4())
+    uuid_list.append(instance_uuid)
+    db_instance_scenario = {
+        "uuid": instance_uuid,
+        "name": instance_name,
+        "tenant_id": tenant_id,
+        "scenario_id": scenarioDict['uuid'],
+        "datacenter_id": default_datacenter_id,
+        # filled bellow 'datacenter_tenant_id'
+        "description": instance_dict.get("description"),
+    }
+    db_ip_profiles=[]
+    if scenarioDict.get("cloud-config"):
+        db_instance_scenario["cloud_config"] = yaml.safe_dump(scenarioDict["cloud-config"],
+                                                              default_flow_style=True, width=256)
 
+    vnf_net2instance = {}   #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
+    sce_net2instance = {}
     auxNetDict = {}   #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
     auxNetDict['scenario'] = {}
 
     logger.debug("Creating instance from scenario-dict:\n%s", yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))  #TODO remove
-    instance_name = instance_dict["name"]
-    instance_description = instance_dict.get("description")
     try:
         # 0 check correct parameters
         for net_name, net_instance_desc in instance_dict.get("networks",{}).iteritems():
@@ -2070,12 +2121,12 @@ def create_instance(mydb, tenant_id, instance_dict):
         #logger.debug(">>>>>>>> Merged dictionary")
         logger.debug("Creating instance scenario-dict MERGED:\n%s", yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
 
-
         # 1. Creating new nets (sce_nets) in the VIM"
+        db_instance_nets = []
         for sce_net in scenarioDict['nets']:
-            sce_net["vim_id_sites"]={}
-            descriptor_net =  instance_dict.get("networks",{}).get(sce_net["name"],{})
+            descriptor_net = instance_dict.get("networks",{}).get(sce_net["name"],{})
             net_name = descriptor_net.get("vim-network-name")
+            sce_net2instance[sce_net['uuid']] = {}
             auxNetDict['scenario'][sce_net['uuid']] = {}
 
             sites = descriptor_net.get("sites", [ {} ])
@@ -2140,7 +2191,7 @@ def create_instance(mydb, tenant_id, instance_dict):
                         if not create_network:
                             raise NfvoException("No candidate VIM network found for " + filter_text, HTTP_Bad_Request )
                     else:
-                        sce_net["vim_id_sites"][datacenter_id] = vim_nets[0]['id']
+                        vim_id = vim_nets[0]['id']
                         auxNetDict['scenario'][sce_net['uuid']][datacenter_id] = vim_nets[0]['id']
                         create_network = False
                 if create_network:
@@ -2150,13 +2201,41 @@ def create_instance(mydb, tenant_id, instance_dict):
                     instance_tasks[task_id] = task
                     tasks_to_launch[myvim_thread_id].append(task)
                     #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
-                    sce_net["vim_id_sites"][datacenter_id] = task_id
+                    vim_id = task_id
                     auxNetDict['scenario'][sce_net['uuid']][datacenter_id] = task_id
                     rollbackList.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id, 'uuid':task_id})
                     sce_net["created"] = True
 
+                # fill database content
+                net_uuid = str(uuid4())
+                uuid_list.append(net_uuid)
+                sce_net2instance[sce_net['uuid']][datacenter_id] = net_uuid
+                db_net = {
+                    "uuid": net_uuid,
+                    'vim_net_id': vim_id,
+                    "instance_scenario_id": instance_uuid,
+                    "sce_net_id": sce_net["uuid"],
+                    "created": create_network,
+                    'datacenter_id': datacenter_id,
+                    'datacenter_tenant_id': myvim_thread_id,
+                    'status': 'BUILD' if create_network else "ACTIVE"
+                }
+                db_instance_nets.append(db_net)
+            if 'ip_profile' in sce_net:
+                db_ip_profile={
+                    'instance_net_id': net_uuid,
+                    'ip_version': sce_net['ip_profile']['ip_version'],
+                    'subnet_address': sce_net['ip_profile']['subnet_address'],
+                    'gateway_address': sce_net['ip_profile']['gateway_address'],
+                    'dns_address': sce_net['ip_profile']['dns_address'],
+                    'dhcp_enabled': sce_net['ip_profile']['dhcp_enabled'],
+                    'dhcp_start_address': sce_net['ip_profile']['dhcp_start_address'],
+                    'dhcp_count': sce_net['ip_profile']['dhcp_count'],
+                }
+                db_ip_profiles.append(db_ip_profile)
+
         # 2. Creating new nets (vnf internal nets) in the VIM"
-        #For each vnf net, we create it and we add it to instanceNetlist.
+        # For each vnf net, we create it and we add it to instanceNetlist.
         for sce_vnf in scenarioDict['vnfs']:
             for net in sce_vnf['nets']:
                 if sce_vnf.get("datacenter"):
@@ -2178,20 +2257,65 @@ def create_instance(mydb, tenant_id, instance_dict):
                 instance_tasks[task_id] = task
                 tasks_to_launch[myvim_thread_id].append(task)
                 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
-                net['vim_id'] = task_id
+                vim_id = task_id
+                if sce_vnf['uuid'] not in vnf_net2instance:
+                    vnf_net2instance[sce_vnf['uuid']] = {}
+                vnf_net2instance[sce_vnf['uuid']][net['uuid']] = task_id
                 if sce_vnf['uuid'] not in auxNetDict:
                     auxNetDict[sce_vnf['uuid']] = {}
                 auxNetDict[sce_vnf['uuid']][net['uuid']] = task_id
                 rollbackList.append({'what':'network','where':'vim','vim_id':datacenter_id,'uuid':task_id})
                 net["created"] = True
 
-
-        #print "auxNetDict:"
-        #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
+                # fill database content
+                net_uuid = str(uuid4())
+                uuid_list.append(net_uuid)
+                vnf_net2instance[sce_vnf['uuid']][net['uuid']] = net_uuid
+                db_net = {
+                    "uuid": net_uuid,
+                    'vim_net_id': vim_id,
+                    "instance_scenario_id": instance_uuid,
+                    "net_id": net["uuid"],
+                    "created": True,
+                    'datacenter_id': datacenter_id,
+                    'datacenter_tenant_id': myvim_thread_id,
+                }
+                db_instance_nets.append(db_net)
+                if 'ip_profile' in net:
+                    db_ip_profile = {
+                        'instance_net_id': net_uuid,
+                        'ip_version': net['ip_profile']['ip_version'],
+                        'subnet_address': net['ip_profile']['subnet_address'],
+                        'gateway_address': net['ip_profile']['gateway_address'],
+                        'dns_address': net['ip_profile']['dns_address'],
+                        'dhcp_enabled': net['ip_profile']['dhcp_enabled'],
+                        'dhcp_start_address': net['ip_profile']['dhcp_start_address'],
+                        'dhcp_count': net['ip_profile']['dhcp_count'],
+                    }
+                    db_ip_profiles.append(db_ip_profile)
+
+        #print "vnf_net2instance:"
+        #print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
 
         # 3. Creating new vm instances in the VIM
+        db_instance_vnfs = []
+        db_instance_vms = []
+        db_instance_interfaces = []
         #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
-        for sce_vnf in scenarioDict['vnfs']:
+        sce_vnf_list = sorted(scenarioDict['vnfs'], key=lambda k: k['name']) 
+        #for sce_vnf in scenarioDict['vnfs']:
+        for sce_vnf in sce_vnf_list:
+            vnf_availability_zones = []
+            for vm in sce_vnf['vms']:
+                vm_av = vm.get('availability_zone')
+                if vm_av and vm_av not in vnf_availability_zones:
+                    vnf_availability_zones.append(vm_av)
+
+            # check if there is enough availability zones available at vim level.
+            if myvims[datacenter_id].availability_zone and vnf_availability_zones:
+                if len(vnf_availability_zones) > len(myvims[datacenter_id].availability_zone):
+                    raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request)
+
             if sce_vnf.get("datacenter"):
                 vim = myvims[ sce_vnf["datacenter"] ]
                 myvim_thread_id = myvim_threads_id[ sce_vnf["datacenter"] ]
@@ -2200,12 +2324,24 @@ def create_instance(mydb, tenant_id, instance_dict):
                 vim = myvims[ default_datacenter_id ]
                 myvim_thread_id = myvim_threads_id[ default_datacenter_id ]
                 datacenter_id = default_datacenter_id
-            sce_vnf["datacenter_id"] =  datacenter_id
+            sce_vnf["datacenter_id"] = datacenter_id
             i = 0
+
+            vnf_uuid = str(uuid4())
+            uuid_list.append(vnf_uuid)
+            db_instance_vnf = {
+                'uuid': vnf_uuid,
+                'instance_scenario_id': instance_uuid,
+                'vnf_id': sce_vnf['vnf_id'],
+                'sce_vnf_id': sce_vnf['uuid'],
+                'datacenter_id': datacenter_id,
+                'datacenter_tenant_id': myvim_thread_id,
+            }
+            db_instance_vnfs.append(db_instance_vnf)
+
             for vm in sce_vnf['vms']:
-                i += 1
                 myVMDict = {}
-                myVMDict['name'] = "{}.{}.{}".format(instance_name,sce_vnf['name'],chr(96+i))
+                myVMDict['name'] = "{}.{}.{}".format(instance_name[:64], sce_vnf['name'][:64], vm["name"][:64])
                 myVMDict['description'] = myVMDict['name'][0:99]
 #                if not startvms:
 #                    myVMDict['start'] = "no"
@@ -2238,9 +2374,11 @@ def create_instance(mydb, tenant_id, instance_dict):
                 vm['vim_flavor_id'] = flavor_id
                 myVMDict['imageRef'] = vm['vim_image_id']
                 myVMDict['flavorRef'] = vm['vim_flavor_id']
+                myVMDict['availability_zone'] = vm.get('availability_zone')
                 myVMDict['networks'] = []
                 task_depends = {}
                 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
+                db_vm_ifaces = []
                 for iface in vm['interfaces']:
                     netDict = {}
                     if iface['type']=="data":
@@ -2287,48 +2425,114 @@ def create_instance(mydb, tenant_id, instance_dict):
                             #print vnf_iface
                             if vnf_iface['interface_id']==iface['uuid']:
                                 netDict['net_id'] = auxNetDict['scenario'][ vnf_iface['sce_net_id'] ][datacenter_id]
+                                instance_net_id = sce_net2instance[ vnf_iface['sce_net_id'] ][datacenter_id]
                                 break
                     else:
                         netDict['net_id'] = auxNetDict[ sce_vnf['uuid'] ][ iface['net_id'] ]
+                        instance_net_id = vnf_net2instance[ sce_vnf['uuid'] ][ iface['net_id'] ]
                     if netDict.get('net_id') and is_task_id(netDict['net_id']):
                         task_depends[netDict['net_id']] = instance_tasks[netDict['net_id']]
                     #skip bridge ifaces not connected to any net
                     #if 'net_id' not in netDict or netDict['net_id']==None:
                     #    continue
                     myVMDict['networks'].append(netDict)
-                #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
-                #print myVMDict['name']
-                #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
-                #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
-                #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
+                    db_vm_iface={
+                        # "uuid"
+                        # 'instance_vm_id': instance_vm_uuid,
+                        "instance_net_id": instance_net_id,
+                        'interface_id': iface['uuid'],
+                        # 'vim_interface_id': ,
+                        'type': 'external' if iface['external_name'] is not None else 'internal',
+                        'ip_address': iface.get('ip_address'),
+                        'floating_ip': int(iface.get('floating-ip', False)),
+                        'port_security': int(iface.get('port-security', True))
+                    }
+                    db_vm_ifaces.append(db_vm_iface)
+                # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
+                # print myVMDict['name']
+                # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
+                # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
+                # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
                 if vm.get("boot_data"):
                     cloud_config_vm = unify_cloud_config(vm["boot_data"], cloud_config)
                 else:
                     cloud_config_vm = cloud_config
-                task = new_task("new-vm", (myVMDict['name'], myVMDict['description'], myVMDict.get('start', None),
-                                           myVMDict['imageRef'], myVMDict['flavorRef'], myVMDict['networks'],
-                                           cloud_config_vm, myVMDict['disks']), depends=task_depends)
-                instance_tasks[task["id"]] = task
-                tasks_to_launch[myvim_thread_id].append(task)
-                vm_id = task["id"]
-                vm['vim_id'] = vm_id
-                rollbackList.append({'what':'vm','where':'vim','vim_id':datacenter_id,'uuid':vm_id})
-                #put interface uuid back to scenario[vnfs][vms[[interfaces]
-                for net in myVMDict['networks']:
-                    if "vim_id" in net:
-                        for iface in vm['interfaces']:
-                            if net["name"]==iface["internal_name"]:
-                                iface["vim_id"]=net["vim_id"]
-                                break
+                if myVMDict.get('availability_zone'):
+                    av_index = vnf_availability_zones.index(myVMDict['availability_zone'])
+                else:
+                    av_index = None
+                for vm_index in range(0, vm.get('count', 1)):
+                    vm_index_name = ""
+                    if vm.get('count', 1) > 1:
+                        vm_index_name += "." + chr(97 + vm_index)
+                    task = new_task("new-vm", (myVMDict['name']+vm_index_name, myVMDict['description'],
+                                               myVMDict.get('start', None), myVMDict['imageRef'],
+                                               myVMDict['flavorRef'], myVMDict['networks'],
+                                               cloud_config_vm, myVMDict['disks'], av_index,
+                                               vnf_availability_zones), depends=task_depends)
+                    instance_tasks[task["id"]] = task
+                    tasks_to_launch[myvim_thread_id].append(task)
+                    vm_id = task["id"]
+                    vm['vim_id'] = vm_id
+                    rollbackList.append({'what':'vm','where':'vim','vim_id':datacenter_id,'uuid':vm_id})
+                    # put interface uuid back to scenario[vnfs][vms[[interfaces]
+                    for net in myVMDict['networks']:
+                        if "vim_id" in net:
+                            for iface in vm['interfaces']:
+                                if net["name"]==iface["internal_name"]:
+                                    iface["vim_id"]=net["vim_id"]
+                                    break
+                    vm_uuid = str(uuid4())
+                    uuid_list.append(vm_uuid)
+                    db_vm = {
+                        "uuid": vm_uuid,
+                        'instance_vnf_id': vnf_uuid,
+                        "vim_vm_id": vm_id,
+                        "vm_id": vm["uuid"],
+                        # "status":
+                    }
+                    db_instance_vms.append(db_vm)
+                    for db_vm_iface in db_vm_ifaces:
+                        iface_uuid = str(uuid4())
+                        uuid_list.append(iface_uuid)
+                        db_vm_iface_instance = {
+                            "uuid": iface_uuid,
+                            "instance_vm_id": vm_uuid
+                        }
+                        db_vm_iface_instance.update(db_vm_iface)
+                        if db_vm_iface_instance.get("ip_address"):  # increment ip_address
+                            ip = db_vm_iface_instance.get("ip_address")
+                            i = ip.rfind(".")
+                            if i > 0:
+                                try:
+                                    i += 1
+                                    ip = ip[i:] + str(int(ip[:i]) +1)
+                                    db_vm_iface_instance["ip_address"] = ip
+                                except:
+                                    db_vm_iface_instance["ip_address"] = None
+                        db_instance_interfaces.append(db_vm_iface_instance)
+
         scenarioDict["datacenter2tenant"] = myvim_threads_id
+
+        db_instance_scenario['datacenter_tenant_id'] = myvim_threads_id[default_datacenter_id]
+        db_instance_scenario['datacenter_id'] = default_datacenter_id
+        db_tables=[
+            {"instance_scenarios": db_instance_scenario},
+            {"instance_vnfs": db_instance_vnfs},
+            {"instance_nets": db_instance_nets},
+            {"ip_profiles": db_ip_profiles},
+            {"instance_vms": db_instance_vms},
+            {"instance_interfaces": db_instance_interfaces},
+        ]
+
         logger.debug("create_instance Deployment done scenarioDict: %s",
-                    yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False) )
-        instance_id = mydb.new_instance_scenario_as_a_whole(tenant_id,instance_name, instance_description, scenarioDict)
+                    yaml.safe_dump(db_tables, indent=4, default_flow_style=False) )
+        mydb.new_rows(db_tables, uuid_list)
         for myvim_thread_id,task_list in tasks_to_launch.items():
             for task in task_list:
                 vim_threads["running"][myvim_thread_id].insert_task(task)
 
-        global_instance_tasks[instance_id] = instance_tasks
+        global_instance_tasks[instance_uuid] = instance_tasks
         # Update database with those ended instance_tasks
         # for task in instance_tasks.values():
         #     if task["status"] == "ok":
@@ -2338,7 +2542,7 @@ def create_instance(mydb, tenant_id, instance_dict):
         #         elif task["name"] == "new-net":
         #             mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
         #                              WHERE={"vim_net_id": task["id"]})
-        return mydb.get_instance_scenario(instance_id)
+        return mydb.get_instance_scenario(instance_uuid)
     except (NfvoException, vimconn.vimconnException,db_base_Exception)  as e:
         message = rollback(mydb, myvims, rollbackList)
         if isinstance(e, db_base_Exception):
index ac392c6..071d03a 100644 (file)
@@ -38,6 +38,7 @@ tables_with_createdat_field=["datacenters","instance_nets","instance_scenarios",
                            "interfaces","nets","nfvo_tenants","scenarios","sce_interfaces","sce_nets",
                            "sce_vnfs","tenants_datacenters","datacenter_tenants","vms","vnfs", "datacenter_nets"]
 
+
 class nfvo_db(db_base.db_base):
     def __init__(self, host=None, user=None, passwd=None, database=None, log_name='openmano.db', log_level=None):
         db_base.db_base.__init__(self, host, user, passwd, database, log_name, log_level)
@@ -585,15 +586,19 @@ class nfvo_db(db_base.db_base):
                     scenario_dict['vnfs'] = self.cur.fetchall()
                     for vnf in scenario_dict['vnfs']:
                         #sce_interfaces
-                        cmd = "SELECT scei.uuid,scei.sce_net_id,scei.interface_id,i.external_name,scei.ip_address FROM sce_interfaces as scei join interfaces as i on scei.interface_id=i.uuid WHERE scei.sce_vnf_id='{}' ORDER BY scei.created_at".format(vnf['uuid'])
+                        cmd = "SELECT scei.uuid,scei.sce_net_id,scei.interface_id,i.external_name,scei.ip_address"\
+                              " FROM sce_interfaces as scei join interfaces as i on scei.interface_id=i.uuid"\
+                              " WHERE scei.sce_vnf_id='{}' ORDER BY scei.created_at".format(vnf['uuid'])
                         self.logger.debug(cmd)
                         self.cur.execute(cmd)
                         vnf['interfaces'] = self.cur.fetchall()
                         #vms
-                        cmd = "SELECT vms.uuid as uuid, flavor_id, image_id, vms.name as name, vms.description as description, vms.boot_data as boot_data " \
-                                " FROM vnfs join vms on vnfs.uuid=vms.vnf_id " \
-                                " WHERE vnfs.uuid='" + vnf['vnf_id'] +"'"  \
-                                " ORDER BY vms.created_at"
+                        cmd = "SELECT vms.uuid as uuid, flavor_id, image_id, vms.name as name," \
+                              " vms.description as description, vms.boot_data as boot_data, count," \
+                              " vms.availability_zone as availability_zone" \
+                              " 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()
@@ -720,6 +725,43 @@ class nfvo_db(db_base.db_base):
                 self._format_error(e, tries, "delete", "instances running")
             tries -= 1
 
+    def new_rows(self, tables, uuid_list=None):
+        """
+        Make a transactional insertion of rows at several tables
+        :param tables: list with dictionary where the keys are the table names and the values are a row or row list
+            with the values to be inserted at the table. Each row is a dictionary with the key values. E.g.:
+            tables = [
+                {"table1": [ {"column1": value, "column2: value, ... }, {"column1": value, "column2: value, ... }, ...],
+                {"table2": [ {"column1": value, "column2: value, ... }, {"column1": value, "column2: value, ... }, ...],
+                {"table3": {"column1": value, "column2: value, ... }
+            }
+        :param uuid_list: list of created uuids, first one is the root (#TODO to store at uuid table)
+        :return: None if success,  raise exception otherwise
+        """
+        tries = 2
+        while tries:
+            created_time = time.time()
+            try:
+                with self.con:
+                    self.cur = self.con.cursor()
+                    for table in tables:
+                        for table_name, row_list in table.items():
+                            index = 0
+                            if isinstance(row_list, dict):
+                                row_list = (row_list, )  #create a list with the single value
+                            for row in row_list:
+                                if table_name in self.tables_with_created_field:
+                                    created_time_param = created_time + index*0.00001
+                                else:
+                                    created_time_param=0
+                                self._new_row_internal(table_name, row, add_uuid=False, root_uuid=None,
+                                                               created_time=created_time_param)
+                                index += 1
+                    return
+            except (mdb.Error, AttributeError) as e:
+                self._format_error(e, tries)
+            tries -= 1
+
     def new_instance_scenario_as_a_whole(self,tenant_id,instance_scenario_name,instance_scenario_description,scenarioDict):
         tries = 2
         while tries:
index 7d218ec..fb12d9f 100644 (file)
@@ -386,7 +386,7 @@ internal_connection_schema = {
         "name": name_schema,
         "description":description_schema,
         "type":{"type":"string", "enum":["bridge","data","ptp"]},
-        "elements": {"type" : "array", "items": internal_connection_element_schema, "minItems":2}
+        "elements": {"type" : "array", "items": internal_connection_element_schema, "minItems":1}
     },
     "required": ["name", "type", "elements"],
     "additionalProperties": False
@@ -400,7 +400,7 @@ internal_connection_schema_v02 = {
         "type": {"type": "string", "enum":["e-line", "e-lan"]},
         "implementation": {"type": "string", "enum":["overlay", "underlay"]},
         "ip-profile": ip_profile_schema,
-        "elements": {"type" : "array", "items": internal_connection_element_schema_v02, "minItems":2}
+        "elements": {"type" : "array", "items": internal_connection_element_schema_v02, "minItems":1}
     },
     "required": ["name", "type", "implementation", "elements"],
     "additionalProperties": False
@@ -541,8 +541,10 @@ vnfc_schema = {
     "properties":{
         "name": name_schema,
         "description": description_schema,
-        "VNFC image": {"oneOf": [path_schema, http_schema]},
+        "count": integer1_schema,
         "image name": name_schema,
+        "availability_zone": name_schema,
+        "VNFC image": {"oneOf": [path_schema, http_schema]},
         "image checksum": checksum_schema,
         "image metadata": metadata_schema, 
         #"cloud-config": cloud_config_schema, #common for all vnfs in the scenario
@@ -592,6 +594,7 @@ vnfd_schema_v01 = {
             "properties":{
                 "name": name_schema,
                 "description": description_schema,
+
                 "class": nameshort_schema,
                 "public": {"type" : "boolean"},
                 "physical": {"type" : "boolean"},
index 9f396a2..0074dfe 100644 (file)
@@ -144,8 +144,9 @@ class vim_thread(threading.Thread):
                             #delete old port
                             if task_interface.get("sdn_port_id"):
                                 try:
-                                    self.ovim.delete_port(task_interface["sdn_port_id"])
-                                    task_interface["sdn_port_id"] = None
+                                    with self.db_lock:
+                                        self.ovim.delete_port(task_interface["sdn_port_id"])
+                                        task_interface["sdn_port_id"] = None
                                 except ovimException as e:
                                     self.logger.error("ovimException deleting external_port={} ".format(
                                         task_interface["sdn_port_id"]) + str(e), exc_info=True)
@@ -174,11 +175,15 @@ class vim_thread(threading.Thread):
                                 continue
                             else:
                                 db_iface = db_ifaces[0]
-                                #If there is no sdn_net_id, check if it is because an already created vim network is being used
-                                #in that case, the sdn_net_id will be in that entry of the instance_nets table
+                                # If there is no sdn_net_id, check if it is because an already created vim network is being used
+                                # in that case, the sdn_net_id will be in that entry of the instance_nets table
                                 if not db_iface.get("sdn_net_id"):
-                                    result = self.db.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets',
-                                                                  WHERE={'vim_net_id': db_iface.get("vim_net_id"), 'instance_scenario_id': None, "datacenter_tenant_id":  self.datacenter_tenant_id})
+                                    with self.db_lock:
+                                        result = self.db.get_rows(
+                                            SELECT=('sdn_net_id',), FROM='instance_nets',
+                                            WHERE={'vim_net_id': db_iface.get("vim_net_id"),
+                                                   'instance_scenario_id': None,
+                                                   'datacenter_tenant_id':  self.datacenter_tenant_id})
                                     if len(result) == 1:
                                         db_iface["sdn_net_id"] = result[0]['sdn_net_id']
 
@@ -187,15 +192,16 @@ class vim_thread(threading.Thread):
                                     sdn_port_name = sdn_net_id + "." + db_iface["vm_id"]
                                     sdn_port_name = sdn_port_name[:63]
                                     try:
-                                        sdn_port_id = self.ovim.new_external_port(
-                                            {"compute_node": interface["compute_node"],
-                                             "pci": interface["pci"],
-                                             "vlan": interface.get("vlan"),
-                                             "net_id": sdn_net_id,
-                                             "region": self.vim["config"]["datacenter_id"],
-                                             "name": sdn_port_name,
-                                             "mac": interface.get("mac_address")})
-                                        interface["sdn_port_id"] = sdn_port_id
+                                        with self.db_lock:
+                                            sdn_port_id = self.ovim.new_external_port(
+                                                {"compute_node": interface["compute_node"],
+                                                 "pci": interface["pci"],
+                                                 "vlan": interface.get("vlan"),
+                                                 "net_id": sdn_net_id,
+                                                 "region": self.vim["config"]["datacenter_id"],
+                                                 "name": sdn_port_name,
+                                                 "mac": interface.get("mac_address")})
+                                            interface["sdn_port_id"] = sdn_port_id
                                     except (ovimException, Exception) as e:
                                         self.logger.error(
                                             "ovimException creating new_external_port compute_node={} " \
@@ -248,7 +254,8 @@ class vim_thread(threading.Thread):
                         if db_net.get("sdn_net_id"):
                             # get ovim status
                             try:
-                                sdn_net = self.ovim.show_network(db_net["sdn_net_id"])
+                                with self.db_lock:
+                                    sdn_net = self.ovim.show_network(db_net["sdn_net_id"])
                                 if sdn_net["status"] == "ERROR":
                                     if not vim_info.get("error_msg"):
                                         vim_info["error_msg"] = sdn_net["error_msg"]
@@ -421,7 +428,8 @@ class vim_thread(threading.Thread):
                             net_name, net_type, vim_net['encapsulation']))
                 network["vlan"] = vim_net.get('segmentation_id')
                 try:
-                    sdn_net_id = self.ovim.new_network(network)
+                    with self.db_lock:
+                        sdn_net_id = self.ovim.new_network(network)
                 except (ovimException, Exception) as e:
                     self.logger.error("task=%s cannot create SDN network vim_net_id=%s input='%s' ovimException='%s'",
                                       str(task_id), net_id, str(network), str(e))
@@ -531,7 +539,8 @@ class vim_thread(threading.Thread):
             for iface in interfaces:
                 if iface.get("sdn_port_id"):
                     try:
-                        self.ovim.delete_port(iface["sdn_port_id"])
+                        with self.db_lock:
+                            self.ovim.delete_port(iface["sdn_port_id"])
                     except ovimException as e:
                         self.logger.error("ovimException deleting external_port={} at VM vim_id={} deletion ".format(
                             iface["sdn_port_id"], vm_id) + str(e), exc_info=True)
@@ -559,17 +568,19 @@ class vim_thread(threading.Thread):
             self._remove_refresh("get-net", net_id)
             result = self.vim.delete_network(net_id)
             if sdn_net_id:
-                #Delete any attached port to this sdn network
-                #At this point, there will be ports associated to this network in case it was manually done using 'openmano vim-net-sdn-attach'
+                # Delete any attached port to this sdn network
+                # At this point, there will be ports associated to this network in case it was manually done using 'openmano vim-net-sdn-attach'
                 try:
-                    port_list = self.ovim.get_ports(columns={'uuid'}, filter={'name': 'external_port', 'net_id': sdn_net_id})
+                    with self.db_lock:
+                        port_list = self.ovim.get_ports(columns={'uuid'}, filter={'name': 'external_port', 'net_id': sdn_net_id})
                 except ovimException as e:
                     raise vimconn.vimconnException(
                         "ovimException obtaining external ports for net {}. ".format(sdn_net_id) + str(e))
 
                 for port in port_list:
                     try:
-                        self.ovim.delete_port(port['uuid'])
+                        with self.db_lock:
+                            self.ovim.delete_port(port['uuid'])
                     except ovimException as e:
                         raise vimconn.vimconnException(
                             "ovimException deleting port {} for net {}. ".format(port['uuid'], sdn_net_id) + str(e))
index 18f4334..7adaa36 100644 (file)
@@ -82,6 +82,7 @@ class vimconnNotImplemented(vimconnException):
     def __init__(self, message, http_code=HTTP_Not_Implemented):
         vimconnException.__init__(self, message, http_code)
 
+
 class vimconnector():
     """Abstract base class for all the VIM connector plugins
     These plugins must implement a vimconnector class derived from this 
@@ -115,6 +116,7 @@ class vimconnector():
         self.user      = user
         self.passwd    = passwd
         self.config    = config
+        self.availability_zone = None
         self.logger = logging.getLogger('openmano.vim')
         if log_level:
             self.logger.setLevel( getattr(logging, log_level) )
@@ -353,8 +355,8 @@ class vimconnector():
         """
         raise vimconnNotImplemented( "Should have implemented this" )
 
-    def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None,
-                       disk_list=None):
+    def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
+        availability_zone_index=None, availability_zone_list=None):
         """Adds a VM instance to VIM
         Params:
             'start': (boolean) indicates if VM must start or created in pause mode.
@@ -385,7 +387,8 @@ class vimconnector():
                 'users': (optional) list of users to be inserted, each item is a dict with:
                     'name': (mandatory) user name,
                     'key-pairs': (optional) list of strings with the public key to be inserted to the user
-                'user-data': (optional) string is a text script to be passed directly to cloud-init
+                'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+                    or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
                 'config-files': (optional). List of files to be transferred. Each item is a dict with:
                     'dest': (mandatory) string with the destination absolute path
                     'encoding': (optional, by default text). Can be one of:
@@ -397,6 +400,9 @@ class vimconnector():
             'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
                 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
                 'size': (mandatory) string with the size of the disk in GB
+            availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
+            availability_zone_list: list of availability zones given by user in the VNFD descriptor.  Ignore if
+                availability_zone_index is None
         Returns the instance identifier or raises an exception on error
         """
         raise vimconnNotImplemented( "Should have implemented this" )
@@ -458,7 +464,7 @@ class vimconnector():
                 suffix:   extra text, e.g. the http path and query string   
         """
         raise vimconnNotImplemented( "Should have implemented this" )
-        
+
 #NOT USED METHODS in current version        
 
     def host_vim2gui(self, host, server_dict):
index 6621345..3cccbfc 100644 (file)
@@ -590,7 +590,7 @@ class vimconnector(vimconn.vimconnector):
             self.format_vimconn_exception(e)
 
     def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None,
-                       disk_list=None):
+                       disk_list=None, availability_zone_index=None, availability_zone_list=None):
         """Create a new VM/instance in AWS
         Params: name
                 decription
index bcb80ae..319f8c1 100644 (file)
@@ -35,6 +35,8 @@ import netaddr
 import time
 import yaml
 import random
+import sys
+import re
 
 from novaclient import client as nClient, exceptions as nvExceptions
 from keystoneauth1.identity import v2, v3
@@ -50,8 +52,11 @@ from httplib import HTTPException
 from neutronclient.neutron import client as neClient
 from neutronclient.common import exceptions as neExceptions
 from requests.exceptions import ConnectionError
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
 
-'''contain the openstack virtual machine status to openmano status'''
+
+"""contain the openstack virtual machine status to openmano status"""
 vmStatus2manoFormat={'ACTIVE':'ACTIVE',
                      'PAUSED':'PAUSED',
                      'SUSPENDED': 'SUSPENDED',
@@ -64,7 +69,7 @@ netStatus2manoFormat={'ACTIVE':'ACTIVE','PAUSED':'PAUSED','INACTIVE':'INACTIVE',
 
 #global var to have a timeout creating and deleting volumes
 volume_timeout = 60
-server_timeout = 60
+server_timeout = 300
 
 class vimconnector(vimconn.vimconnector):
     def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None,
@@ -77,6 +82,15 @@ class vimconnector(vimconn.vimconnector):
         if api_version and api_version not in ('v3.3', 'v2.0', '2', '3'):
             raise vimconn.vimconnException("Invalid value '{}' for config:APIversion. "
                                            "Allowed values are 'v3.3', 'v2.0', '2' or '3'".format(api_version))
+        vim_type = config.get('vim_type')
+        if vim_type and vim_type not in ('vio', 'VIO'):
+            raise vimconn.vimconnException("Invalid value '{}' for config:vim_type."
+                            "Allowed values are 'vio' or 'VIO'".format(vim_type))
+
+        if config.get('dataplane_net_vlan_range') is not None:
+            #validate vlan ranges provided by user
+            self._validate_vlan_ranges(config.get('dataplane_net_vlan_range'))
+
         vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
                                       config)
 
@@ -84,17 +98,31 @@ class vimconnector(vimconn.vimconnector):
         if not url:
             raise TypeError, 'url param can not be NoneType'
         self.persistent_info = persistent_info
+        self.availability_zone = persistent_info.get('availability_zone', None)
         self.session = persistent_info.get('session', {'reload_client': True})
         self.nova = self.session.get('nova')
         self.neutron = self.session.get('neutron')
         self.cinder = self.session.get('cinder')
         self.glance = self.session.get('glance')
+        self.glancev1 = self.session.get('glancev1')
         self.keystone = self.session.get('keystone')
         self.api_version3 = self.session.get('api_version3')
+        self.vim_type = self.config.get("vim_type")
+        if self.vim_type:
+            self.vim_type = self.vim_type.upper()
+        if self.config.get("use_internal_endpoint"):
+            self.endpoint_type = "internalURL"
+        else:
+            self.endpoint_type = None
 
         self.logger = logging.getLogger('openmano.vim.openstack')
+
+        ####### VIO Specific Changes #########
+        if self.vim_type == "VIO":
+            self.logger = logging.getLogger('openmano.vim.vio')
+
         if log_level:
-            self.logger.setLevel( getattr(logging, log_level) )
+            self.logger.setLevel( getattr(logging, log_level))
 
     def __getitem__(self, index):
         """Get individuals parameters.
@@ -144,16 +172,36 @@ class vimconnector(vimconn.vimconnector):
                                    tenant_id=self.tenant_id)
             sess = session.Session(auth=auth, verify=not self.insecure)
             if self.api_version3:
-                self.keystone = ksClient_v3.Client(session=sess)
+                self.keystone = ksClient_v3.Client(session=sess, endpoint_type=self.endpoint_type)
             else:
-                self.keystone = ksClient_v2.Client(session=sess)
+                self.keystone = ksClient_v2.Client(session=sess, endpoint_type=self.endpoint_type)
             self.session['keystone'] = self.keystone
-            self.nova = self.session['nova'] = nClient.Client("2.1", session=sess)
-            self.neutron = self.session['neutron'] = neClient.Client('2.0', session=sess)
-            self.cinder = self.session['cinder'] = cClient.Client(2, session=sess)
-            self.glance = self.session['glance'] = glClient.Client(2, session=sess)
+            # In order to enable microversion functionality an explicit microversion must be specified in 'config'.
+            # This implementation approach is due to the warning message in
+            # https://developer.openstack.org/api-guide/compute/microversions.html
+            # where it is stated that microversion backwards compatibility is not guaranteed and clients should
+            # always require an specific microversion.
+            # To be able to use 'device role tagging' functionality define 'microversion: 2.32' in datacenter config
+            version = self.config.get("microversion")
+            if not version:
+                version = "2.1"
+            self.nova = self.session['nova'] = nClient.Client(str(version), session=sess, endpoint_type=self.endpoint_type)
+            self.neutron = self.session['neutron'] = neClient.Client('2.0', session=sess, endpoint_type=self.endpoint_type)
+            self.cinder = self.session['cinder'] = cClient.Client(2, session=sess, endpoint_type=self.endpoint_type)
+            if self.endpoint_type == "internalURL":
+                glance_service_id = self.keystone.services.list(name="glance")[0].id
+                glance_endpoint = self.keystone.endpoints.list(glance_service_id, interface="internal")[0].url
+            else:
+                glance_endpoint = None
+            self.glance = self.session['glance'] = glClient.Client(2, session=sess, endpoint=glance_endpoint)
+            #using version 1 of glance client in new_image()
+            self.glancev1 = self.session['glancev1'] = glClient.Client('1', session=sess,
+                                                                       endpoint=glance_endpoint)
             self.session['reload_client'] = False
             self.persistent_info['session'] = self.session
+            # add availablity zone info inside  self.persistent_info
+            self._set_availablity_zones()
+            self.persistent_info['availability_zone'] = self.availability_zone
 
     def __net_os2mano(self, net_list_dict):
         '''Transform the net openstack format to mano format
@@ -255,6 +303,19 @@ class vimconnector(vimconn.vimconnector):
                 network_dict["provider:network_type"]     = "vlan"
                 if vlan!=None:
                     network_dict["provider:network_type"] = vlan
+
+                ####### VIO Specific Changes #########
+                if self.vim_type == "VIO":
+                    if vlan is not None:
+                        network_dict["provider:segmentation_id"] = vlan
+                    else:
+                        if self.config.get('dataplane_net_vlan_range') is None:
+                            raise vimconn.vimconnConflictException("You must provide "\
+                                "'dataplane_net_vlan_range' in format [start_ID - end_ID]"\
+                                "at config value before creating sriov network with vlan tag")
+
+                        network_dict["provider:segmentation_id"] = self._genrate_vlanID()
+
             network_dict["shared"]=shared
             new_net=self.neutron.create_network({'network':network_dict})
             #print new_net
@@ -484,7 +545,7 @@ class vimconnector(vimconn.vimconnector):
                     while name in fl_names:
                         name_suffix += 1
                         name = flavor_data['name']+"-" + str(name_suffix)
-                        
+
                 ram = flavor_data.get('ram',64)
                 vcpus = flavor_data.get('vcpus',1)
                 numa_properties=None
@@ -500,6 +561,9 @@ class vimconnector(vimconn.vimconnector):
                         numa_properties["hw:mem_page_size"] = "large"
                         numa_properties["hw:cpu_policy"] = "dedicated"
                         numa_properties["hw:numa_mempolicy"] = "strict"
+                        if self.vim_type == "VIO":
+                            numa_properties["vmware:extra_config"] = '{"numa.nodeAffinity":"0"}'
+                            numa_properties["vmware:latency_sensitivity_level"] = "high"
                         for numa in numas:
                             #overwrite ram and vcpus
                             ram = numa['memory']*1024
@@ -530,7 +594,7 @@ class vimconnector(vimconn.vimconnector):
                                 vcpus, 
                                 flavor_data.get('disk',1),
                                 is_public=flavor_data.get('is_public', True)
-                            ) 
+                            )
                 #add metadata
                 if numa_properties:
                     new_flavor.set_keys(numa_properties)
@@ -564,9 +628,6 @@ class vimconnector(vimconn.vimconnector):
             metadata: metadata of the image
         Returns the image_id
         '''
-        # ALF TODO: revise and change for the new method or session
-        #using version 1 of glance client
-        glancev1 = gl1Client.Client('1',self.glance_endpoint, token=self.keystone.auth_token, **self.k_creds)  #TODO check k_creds vs n_creds
         retry=0
         max_retries=3
         while retry<max_retries:
@@ -597,11 +658,11 @@ class vimconnector(vimconn.vimconnector):
                         disk_format="raw"
                 self.logger.debug("new_image: '%s' loading from '%s'", image_dict['name'], image_dict['location'])
                 if image_dict['location'][0:4]=="http":
-                    new_image = glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
+                    new_image = self.glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
                             container_format="bare", location=image_dict['location'], disk_format=disk_format)
                 else: #local path
                     with open(image_dict['location']) as fimage:
-                        new_image = glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
+                        new_image = self.glancev1.images.create(name=image_dict['name'], is_public=image_dict.get('public',"yes")=="yes",
                             container_format="bare", data=fimage, disk_format=disk_format)
                 #insert metadata. We cannot use 'new_image.properties.setdefault' 
                 #because nova and glance are "INDEPENDENT" and we are using nova for reading metadata
@@ -673,6 +734,41 @@ class vimconnector(vimconn.vimconnector):
         except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e:
             self._format_exception(e)
 
+    @staticmethod
+    def _create_mimemultipart(content_list):
+        """Creates a MIMEmultipart text combining the content_list
+        :param content_list: list of text scripts to be combined
+        :return: str of the created MIMEmultipart. If the list is empty returns None, if the list contains only one
+        element MIMEmultipart is not created and this content is returned
+        """
+        if not content_list:
+            return None
+        elif len(content_list) == 1:
+            return content_list[0]
+        combined_message = MIMEMultipart()
+        for content in content_list:
+            if content.startswith('#include'):
+                format = 'text/x-include-url'
+            elif content.startswith('#include-once'):
+                format = 'text/x-include-once-url'
+            elif content.startswith('#!'):
+                format = 'text/x-shellscript'
+            elif content.startswith('#cloud-config'):
+                format = 'text/cloud-config'
+            elif content.startswith('#cloud-config-archive'):
+                format = 'text/cloud-config-archive'
+            elif content.startswith('#upstart-job'):
+                format = 'text/upstart-job'
+            elif content.startswith('#part-handler'):
+                format = 'text/part-handler'
+            elif content.startswith('#cloud-boothook'):
+                format = 'text/cloud-boothook'
+            else:  # by default
+                format = 'text/x-shellscript'
+            sub_message = MIMEText(content, format, sys.getdefaultencoding())
+            combined_message.attach(sub_message)
+        return combined_message.as_string()
+
     def __wait_for_vm(self, vm_id, status):
         """wait until vm is in the desired status and return True.
         If the VM gets in ERROR status, return false.
@@ -692,7 +788,66 @@ class vimconnector(vimconn.vimconnector):
             raise vimconn.vimconnException('Timeout waiting for instance ' + vm_id + ' to get ' + status,
                                            http_code=vimconn.HTTP_Request_Timeout)
 
-    def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None,disk_list=None):
+    def _get_openstack_availablity_zones(self):
+        """
+        Get from openstack availability zones available
+        :return:
+        """
+        try:
+            openstack_availability_zone = self.nova.availability_zones.list()
+            openstack_availability_zone = [str(zone.zoneName) for zone in openstack_availability_zone
+                                           if zone.zoneName != 'internal']
+            return openstack_availability_zone
+        except Exception as e:
+            return None
+
+    def _set_availablity_zones(self):
+        """
+        Set vim availablity zone
+        :return:
+        """
+
+        if 'availability_zone' in self.config:
+            vim_availability_zones = self.config.get('availability_zone')
+            if isinstance(vim_availability_zones, str):
+                self.availability_zone = [vim_availability_zones]
+            elif isinstance(vim_availability_zones, list):
+                self.availability_zone = vim_availability_zones
+        else:
+            self.availability_zone = self._get_openstack_availablity_zones()
+
+    def _get_vm_availability_zone(self, availability_zone_index, availability_zone_list):
+        """
+        Return thge availability zone to be used by the created VM.
+        :return: The VIM availability zone to be used or None
+        """
+        if availability_zone_index is None:
+            if not self.config.get('availability_zone'):
+                return None
+            elif isinstance(self.config.get('availability_zone'), str):
+                return self.config['availability_zone']
+            else:
+                # TODO consider using a different parameter at config for default AV and AV list match
+                return self.config['availability_zone'][0]
+
+        vim_availability_zones = self.availability_zone
+        # check if VIM offer enough availability zones describe in the VNFD
+        if vim_availability_zones and len(availability_zone_list) <= len(vim_availability_zones):
+            # check if all the names of NFV AV match VIM AV names
+            match_by_index = False
+            for av in availability_zone_list:
+                if av not in vim_availability_zones:
+                    match_by_index = True
+                    break
+            if match_by_index:
+                return vim_availability_zones[availability_zone_index]
+            else:
+                return availability_zone_list[availability_zone_index]
+        else:
+            raise vimconn.vimconnConflictException("No enough availability zones at VIM for this deployment")
+
+    def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
+                       availability_zone_index=None, availability_zone_list=None):
         '''Adds a VM instance to VIM
         Params:
             start: indicates if VM must start or boot in pause mode. Ignored
@@ -707,6 +862,26 @@ class vimconnector(vimconn.vimconnector):
                 type: 'virtual', 'PF', 'VF', 'VFnotShared'
                 vim_id: filled/added by this function
                 floating_ip: True/False (or it can be None)
+                'cloud_config': (optional) dictionary with:
+                'key-pairs': (optional) list of strings with the public key to be inserted to the default user
+                'users': (optional) list of users to be inserted, each item is a dict with:
+                    'name': (mandatory) user name,
+                    'key-pairs': (optional) list of strings with the public key to be inserted to the user
+                'user-data': (optional) string is a text script to be passed directly to cloud-init
+                'config-files': (optional). List of files to be transferred. Each item is a dict with:
+                    'dest': (mandatory) string with the destination absolute path
+                    'encoding': (optional, by default text). Can be one of:
+                        'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
+                    'content' (mandatory): string with the content of the file
+                    'permissions': (optional) string with file permissions, typically octal notation '0644'
+                    'owner': (optional) file owner, string with the format 'owner:group'
+                'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
+            'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
+                'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
+                'size': (mandatory) string with the size of the disk in GB
+            availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
+            availability_zone_list: list of availability zones given by user in the VNFD descriptor.  Ignore if
+                availability_zone_index is None
                 #TODO ip, security groups
         Returns the instance identifier
         '''
@@ -738,7 +913,19 @@ class vimconnector(vimconn.vimconnector):
                             metadata_vpci["VF"]=[]
                         metadata_vpci["VF"].append([ net["vpci"], "" ])
                     port_dict["binding:vnic_type"]="direct"
-                else:  # For PT
+                    ########## VIO specific Changes #######
+                    if self.vim_type == "VIO":
+                        #Need to create port with port_security_enabled = False and no-security-groups
+                        port_dict["port_security_enabled"]=False
+                        port_dict["provider_security_groups"]=[]
+                        port_dict["security_groups"]=[]
+                else: #For PT
+                    ########## VIO specific Changes #######
+                    #Current VIO release does not support port with type 'direct-physical'
+                    #So no need to create virtual port in case of PCI-device.
+                    #Will update port_dict code when support gets added in next VIO release
+                    if self.vim_type == "VIO":
+                        raise vimconn.vimconnNotSupportedException("Current VIO release does not support full passthrough (PT)")
                     if "vpci" in net:
                         if "PF" not in metadata_vpci:
                             metadata_vpci["PF"]=[]
@@ -757,7 +944,11 @@ class vimconnector(vimconn.vimconnector):
                     net["ip"] = fixed_ips[0].get("ip_address")
                 else:
                     net["ip"] = None
-                net_list_vim.append({"port-id": new_port["port"]["id"]})
+
+                port = {"port-id": new_port["port"]["id"]}
+                if float(self.nova.api_version.get_string()) >= 2.32:
+                    port["tag"] = new_port["port"]["name"]
+                net_list_vim.append(port)
 
                 if net.get('floating_ip', False):
                     net['exit_on_floating_ip_error'] = True
@@ -788,14 +979,17 @@ class vimconnector(vimconn.vimconnector):
             #cloud config
             userdata=None
             config_drive = None
+            userdata_list = []
             if isinstance(cloud_config, dict):
                 if cloud_config.get("user-data"):
-                    userdata=cloud_config["user-data"]
+                    if isinstance(cloud_config["user-data"], str):
+                        userdata_list.append(cloud_config["user-data"])
+                    else:
+                        for u in cloud_config["user-data"]:
+                            userdata_list.append(u)
                 if cloud_config.get("boot-data-drive") != None:
                     config_drive = cloud_config["boot-data-drive"]
                 if cloud_config.get("config-files") or cloud_config.get("users") or cloud_config.get("key-pairs"):
-                    if userdata:
-                        raise vimconn.vimconnConflictException("Cloud-config cannot contain both 'userdata' and 'config-files'/'users'/'key-pairs'")
                     userdata_dict={}
                     #default user
                     if cloud_config.get("key-pairs"):
@@ -829,8 +1023,9 @@ class vimconnector(vimconn.vimconnector):
                             if file.get("owner"):
                                 file_info["owner"] = file["owner"]
                             userdata_dict["write_files"].append(file_info)
-                    userdata = "#cloud-config\n"
-                    userdata += yaml.safe_dump(userdata_dict, indent=4, default_flow_style=False)
+                    userdata_list.append("#cloud-config\n" + yaml.safe_dump(userdata_dict, indent=4,
+                                                                              default_flow_style=False))
+                    userdata = self._create_mimemultipart(userdata_list)
                 self.logger.debug("userdata: %s", userdata)
             elif isinstance(cloud_config, str):
                 userdata = cloud_config
@@ -874,15 +1069,17 @@ class vimconnector(vimconn.vimconnector):
 
                     raise vimconn.vimconnException('Timeout creating volumes for instance ' + name,
                                                    http_code=vimconn.HTTP_Request_Timeout)
-
-            self.logger.debug("nova.servers.create({}, {}, {}, nics={}, meta={}, security_groups={}," \
-                                              "availability_zone={}, key_name={}, userdata={}, config_drive={}, " \
-                                              "block_device_mapping={})".format(name, image_id, flavor_id, net_list_vim,
-                                                metadata, security_groups, self.config.get('availability_zone'),
-                                                self.config.get('keypair'), userdata, config_drive, block_device_mapping))
+            # get availability Zone
+            vm_av_zone = self._get_vm_availability_zone(availability_zone_index, availability_zone_list)
+
+            self.logger.debug("nova.servers.create({}, {}, {}, nics={}, meta={}, security_groups={}, "
+                              "availability_zone={}, key_name={}, userdata={}, config_drive={}, "
+                              "block_device_mapping={})".format(name, image_id, flavor_id, net_list_vim, metadata,
+                                                                security_groups, vm_av_zone, self.config.get('keypair'),
+                              userdata, config_drive, block_device_mapping))
             server = self.nova.servers.create(name, image_id, flavor_id, nics=net_list_vim, meta=metadata,
                                               security_groups=security_groups,
-                                              availability_zone=self.config.get('availability_zone'),
+                                              availability_zone=vm_av_zone,
                                               key_name=self.config.get('keypair'),
                                               userdata=userdata,
                                               config_drive=config_drive,
@@ -1263,6 +1460,67 @@ class vimconnector(vimconn.vimconnector):
             self._format_exception(e)
         #TODO insert exception vimconn.HTTP_Unauthorized
 
+    ####### VIO Specific Changes #########
+    def _genrate_vlanID(self):
+        """
+         Method to get unused vlanID
+            Args:
+                None
+            Returns:
+                vlanID
+        """
+        #Get used VLAN IDs
+        usedVlanIDs = []
+        networks = self.get_network_list()
+        for net in networks:
+            if net.get('provider:segmentation_id'):
+                usedVlanIDs.append(net.get('provider:segmentation_id'))
+        used_vlanIDs = set(usedVlanIDs)
+
+        #find unused VLAN ID
+        for vlanID_range in self.config.get('dataplane_net_vlan_range'):
+            try:
+                start_vlanid , end_vlanid = map(int, vlanID_range.replace(" ", "").split("-"))
+                for vlanID in xrange(start_vlanid, end_vlanid + 1):
+                    if vlanID not in used_vlanIDs:
+                        return vlanID
+            except Exception as exp:
+                raise vimconn.vimconnException("Exception {} occurred while generating VLAN ID.".format(exp))
+        else:
+            raise vimconn.vimconnConflictException("Unable to create the SRIOV VLAN network."\
+                " All given Vlan IDs {} are in use.".format(self.config.get('dataplane_net_vlan_range')))
+
+
+    def _validate_vlan_ranges(self, dataplane_net_vlan_range):
+        """
+        Method to validate user given vlanID ranges
+            Args:  None
+            Returns: None
+        """
+        for vlanID_range in dataplane_net_vlan_range:
+            vlan_range = vlanID_range.replace(" ", "")
+            #validate format
+            vlanID_pattern = r'(\d)*-(\d)*$'
+            match_obj = re.match(vlanID_pattern, vlan_range)
+            if not match_obj:
+                raise vimconn.vimconnConflictException("Invalid dataplane_net_vlan_range {}.You must provide "\
+                "'dataplane_net_vlan_range' in format [start_ID - end_ID].".format(vlanID_range))
+
+            start_vlanid , end_vlanid = map(int,vlan_range.split("-"))
+            if start_vlanid <= 0 :
+                raise vimconn.vimconnConflictException("Invalid dataplane_net_vlan_range {}."\
+                "Start ID can not be zero. For VLAN "\
+                "networks valid IDs are 1 to 4094 ".format(vlanID_range))
+            if end_vlanid > 4094 :
+                raise vimconn.vimconnConflictException("Invalid dataplane_net_vlan_range {}."\
+                "End VLAN ID can not be greater than 4094. For VLAN "\
+                "networks valid IDs are 1 to 4094 ".format(vlanID_range))
+
+            if start_vlanid > end_vlanid:
+                raise vimconn.vimconnConflictException("Invalid dataplane_net_vlan_range {}."\
+                    "You must provide a 'dataplane_net_vlan_range' in format start_ID - end_ID and "\
+                    "start_ID < end_ID ".format(vlanID_range))
+
 #NOT USED FUNCTIONS
     
     def new_external_port(self, port_data):
@@ -1376,3 +1634,4 @@ class vimconnector(vimconn.vimconnector):
         return error_value, error_text        
   
 
+
index e722dc8..abfffbe 100644 (file)
@@ -785,7 +785,8 @@ class vimconnector(vimconn.vimconnector):
             #print text
             return -vim_response.status_code,text
 
-    def new_vminstance(self,name,description,start,image_id,flavor_id,net_list, cloud_config=None, disk_list=None):
+    def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None, disk_list=None,
+                       availability_zone_index=None, availability_zone_list=None):
         '''Adds a VM instance to VIM
         Params:
             start: indicates if VM must start or boot in pause mode. Ignored
index d8ca463..0434900 100644 (file)
@@ -427,9 +427,61 @@ class vimconnector(vimconn.vimconnector):
             raise vimconn.vimconnException("Failed create tenant {}".format(tenant_name))
 
     def delete_tenant(self, tenant_id=None):
-        """Delete a tenant from VIM"""
-        'Returns the tenant identifier'
-        raise vimconn.vimconnNotImplemented("Should have implemented this")
+        """ Delete a tenant from VIM
+             Args:
+                tenant_id is tenant_id to be deleted.
+
+            Return:
+                returns the tenant identifier in UUID format.
+                If action is failed method will throw exception
+        """
+        vca = self.connect_as_admin()
+        if not vca:
+            raise vimconn.vimconnConnectionException("self.connect() is failed")
+
+        if tenant_id is not None:
+            if vca.vcloud_session and vca.vcloud_session.organization:
+                #Get OrgVDC
+                url_list = [self.vca.host, '/api/vdc/', tenant_id]
+                orgvdc_herf = ''.join(url_list)
+                response = Http.get(url=orgvdc_herf,
+                                headers=vca.vcloud_session.get_vcloud_headers(),
+                                verify=vca.verify,
+                                logger=vca.logger)
+
+                if response.status_code != requests.codes.ok:
+                    self.logger.debug("delete_tenant():GET REST API call {} failed. "\
+                                      "Return status code {}".format(orgvdc_herf,
+                                                                     response.status_code))
+                    raise vimconn.vimconnNotFoundException("Fail to get tenant {}".format(tenant_id))
+
+                lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+                namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+                namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
+                vdc_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
+                vdc_remove_href = vdc_remove_href + '?recursive=true&force=true'
+
+                #Delete OrgVDC
+                response = Http.delete(url=vdc_remove_href,
+                                    headers=vca.vcloud_session.get_vcloud_headers(),
+                                    verify=vca.verify,
+                                    logger=vca.logger)
+
+                if response.status_code == 202:
+                        delete_vdc_task = taskType.parseString(response.content, True)
+                        if type(delete_vdc_task) is GenericTask:
+                            self.vca.block_until_completed(delete_vdc_task)
+                            self.logger.info("Deleted tenant with ID {}".format(tenant_id))
+                            return tenant_id
+                else:
+                    self.logger.debug("delete_tenant(): DELETE REST API call {} failed. "\
+                                      "Return status code {}".format(vdc_remove_href,
+                                                                     response.status_code))
+                    raise vimconn.vimconnException("Fail to delete tenant with ID {}".format(tenant_id))
+        else:
+            self.logger.debug("delete_tenant():Incorrect tenant ID  {}".format(tenant_id))
+            raise vimconn.vimconnNotFoundException("Fail to get tenant {}".format(tenant_id))
+
 
     def get_tenant_list(self, filter_dict={}):
         """Obtain tenants of VIM
@@ -795,12 +847,81 @@ class vimconnector(vimconn.vimconnector):
 
     def delete_image(self, image_id):
         """
-
-        :param image_id:
-        :return:
+            Deletes a tenant image from VIM
+            Args:
+                image_id is ID of Image to be deleted
+            Return:
+                returns the image identifier in UUID format or raises an exception on error
         """
+        vca = self.connect_as_admin()
+        if not vca:
+            raise vimconn.vimconnConnectionException("self.connect() is failed")
+        # Get Catalog details
+        url_list = [self.vca.host, '/api/catalog/', image_id]
+        catalog_herf = ''.join(url_list)
+        response = Http.get(url=catalog_herf,
+                            headers=vca.vcloud_session.get_vcloud_headers(),
+                            verify=vca.verify,
+                            logger=vca.logger)
+
+        if response.status_code != requests.codes.ok:
+            self.logger.debug("delete_image():GET REST API call {} failed. "\
+                              "Return status code {}".format(catalog_herf,
+                                                             response.status_code))
+            raise vimconn.vimconnNotFoundException("Fail to get image {}".format(image_id))
+
+        lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+        namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+        namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
+
+        catalogItems_section = lxmlroot_respond.find("xmlns:CatalogItems",namespaces)
+        catalogItems = catalogItems_section.iterfind("xmlns:CatalogItem",namespaces)
+        for catalogItem in catalogItems:
+            catalogItem_href = catalogItem.attrib['href']
+
+            #GET details of catalogItem
+            response = Http.get(url=catalogItem_href,
+                            headers=vca.vcloud_session.get_vcloud_headers(),
+                            verify=vca.verify,
+                            logger=vca.logger)
+
+            if response.status_code != requests.codes.ok:
+                self.logger.debug("delete_image():GET REST API call {} failed. "\
+                                  "Return status code {}".format(catalog_herf,
+                                                                 response.status_code))
+                raise vimconn.vimconnNotFoundException("Fail to get catalogItem {} for catalog {}".format(
+                                                                                    catalogItem,
+                                                                                    image_id))
+
+            lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+            namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+            namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
+            catalogitem_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
+
+            #Remove catalogItem
+            response = Http.delete(url= catalogitem_remove_href,
+                                    headers=vca.vcloud_session.get_vcloud_headers(),
+                                    verify=vca.verify,
+                                    logger=vca.logger)
+            if response.status_code == requests.codes.no_content:
+                self.logger.debug("Deleted Catalog item {}".format(catalogItem))
+            else:
+                raise vimconn.vimconnException("Fail to delete Catalog Item {}".format(catalogItem))
+
+        #Remove catalog
+        url_list = [self.vca.host, '/api/admin/catalog/', image_id]
+        catalog_remove_herf = ''.join(url_list)
+        response = Http.delete(url= catalog_remove_herf,
+                                    headers=vca.vcloud_session.get_vcloud_headers(),
+                                    verify=vca.verify,
+                                    logger=vca.logger)
+
+        if response.status_code == requests.codes.no_content:
+            self.logger.debug("Deleted Catalog {}".format(image_id))
+            return image_id
+        else:
+            raise vimconn.vimconnException("Fail to delete Catalog {}".format(image_id))
 
-        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def catalog_exists(self, catalog_name, catalogs):
         """
@@ -1252,7 +1373,7 @@ class vimconnector(vimconn.vimconnector):
         return None
 
     def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list={},
-                       cloud_config=None, disk_list=None):
+                       cloud_config=None, disk_list=None, availability_zone_index=None, availability_zone_list=None):
         """Adds a VM instance to VIM
         Params:
             start: indicates if VM must start or boot in pause mode. Ignored
@@ -2892,8 +3013,7 @@ class vimconnector(vimconn.vimconnector):
                 # application/vnd.vmware.admin.providervdc+xml
                 # we need find a template from witch we instantiate VDC
                 if child.tag.split("}")[1] == 'VdcTemplate':
-                    if child.attrib.get('type') == 'application/vnd.vmware.admin.vdcTemplate+xml' and child.attrib.get(
-                            'name') == 'openmano':
+                    if child.attrib.get('type') == 'application/vnd.vmware.admin.vdcTemplate+xml':
                         vdc_template_ref = child.attrib.get('href')
         except:
             self.logger.debug("Failed parse respond for rest api call {}".format(vm_list_rest_call))
@@ -2916,6 +3036,11 @@ class vimconnector(vimconn.vimconnector):
             headers['Content-Type'] = 'application/vnd.vmware.vcloud.instantiateVdcTemplateParams+xml'
             response = Http.post(url=vm_list_rest_call, headers=headers, data=data, verify=vca.verify,
                                  logger=vca.logger)
+
+            vdc_task = taskType.parseString(response.content, True)
+            if type(vdc_task) is GenericTask:
+                self.vca.block_until_completed(vdc_task)
+
             # if we all ok we respond with content otherwise by default None
             if response.status_code >= 200 and response.status_code < 300:
                 return response.content
@@ -3889,7 +4014,6 @@ class vimconnector(vimconn.vimconnector):
                                                                            "affinity".format(exp))
 
 
-
     def cloud_init(self, vapp, cloud_config):
         """
         Method to inject ssh-key
@@ -3899,7 +4023,8 @@ class vimconnector(vimconn.vimconnector):
                 'users': (optional) list of users to be inserted, each item is a dict with:
                     'name': (mandatory) user name,
                     'key-pairs': (optional) list of strings with the public key to be inserted to the user
-                'user-data': (optional) string is a text script to be passed directly to cloud-init
+                'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+                    or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
                 'config-files': (optional). List of files to be transferred. Each item is a dict with:
                     'dest': (mandatory) string with the destination absolute path
                     'encoding': (optional, by default text). Can be one of:
@@ -3909,9 +4034,10 @@ class vimconnector(vimconn.vimconnector):
                     'owner': (optional) file owner, string with the format 'owner:group'
                 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk
         """
-
         try:
-            if isinstance(cloud_config, dict):
+            if not isinstance(cloud_config, dict):
+                raise Exception("cloud_init : parameter cloud_config is not a dictionary")
+            else:
                 key_pairs = []
                 userdata = []
                 if "key-pairs" in cloud_config:
@@ -3920,68 +4046,94 @@ class vimconnector(vimconn.vimconnector):
                 if "users" in cloud_config:
                     userdata = cloud_config["users"]
 
-            for key in key_pairs:
-                for user in userdata:
-                    if 'name' in user: user_name = user['name']
-                    if 'key-pairs' in user and len(user['key-pairs']) > 0:
-                        for user_key in user['key-pairs']:
-                            customize_script = """
-                        #!/bin/bash
-                        echo performing customization tasks with param $1 at `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
-                        if [ "$1" = "precustomization" ];then
-                            echo performing precustomization tasks   on `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
-                            if [ ! -d /root/.ssh ];then
-                                mkdir /root/.ssh
-                                chown root:root /root/.ssh
-                                chmod 700 /root/.ssh
-                                touch /root/.ssh/authorized_keys
-                                chown root:root /root/.ssh/authorized_keys
-                                chmod 600 /root/.ssh/authorized_keys
-                                # make centos with selinux happy
-                                which restorecon && restorecon -Rv /root/.ssh
-                                echo '{key}' >> /root/.ssh/authorized_keys
-                            else
-                                touch /root/.ssh/authorized_keys
-                                chown root:root /root/.ssh/authorized_keys
-                                chmod 600 /root/.ssh/authorized_keys
-                                echo '{key}' >> /root/.ssh/authorized_keys
-                            fi
-                            if [ -d /home/{user_name} ];then
-                                if [ ! -d /home/{user_name}/.ssh ];then
-                                    mkdir /home/{user_name}/.ssh
-                                    chown {user_name}:{user_name} /home/{user_name}/.ssh
-                                    chmod 700 /home/{user_name}/.ssh
-                                    touch /home/{user_name}/.ssh/authorized_keys
-                                    chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
-                                    chmod 600 /home/{user_name}/.ssh/authorized_keys
-                                    # make centos with selinux happy
-                                    which restorecon && restorecon -Rv /home/{user_name}/.ssh
-                                    echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
-                                else
-                                    touch /home/{user_name}/.ssh/authorized_keys
-                                    chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
-                                    chmod 600 /home/{user_name}/.ssh/authorized_keys
-                                    echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
-                                fi
-                            fi
-                        fi""".format(key=key, user_name=user_name, user_key=user_key)
-
-                            for vm in vapp._get_vms():
-                                vm_name = vm.name
-                                task = vapp.customize_guest_os(vm_name, customization_script=customize_script)
-                                if isinstance(task, GenericTask):
-                                    self.vca.block_until_completed(task)
-                                    self.logger.info("cloud_init : customized guest os task "\
-                                                        "completed for VM {}".format(vm_name))
-                                else:
-                                    self.logger.error("cloud_init : task for customized guest os"\
-                                                               "failed for VM {}".format(vm_name))
+                self.logger.debug("cloud_init : Guest os customization started..")
+                customize_script = self.format_script(key_pairs=key_pairs, users_list=userdata)
+                self.guest_customization(vapp, customize_script)
+
         except Exception as exp:
             self.logger.error("cloud_init : exception occurred while injecting "\
                                                                        "ssh-key")
             raise vimconn.vimconnException("cloud_init : Error {} failed to inject "\
                                                                "ssh-key".format(exp))
 
+    def format_script(self, key_pairs=[], users_list=[]):
+        bash_script = """
+        #!/bin/bash
+        echo performing customization tasks with param $1 at `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
+        if [ "$1" = "precustomization" ];then
+            echo performing precustomization tasks   on `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
+        """
+
+        keys = "\n".join(key_pairs)
+        if keys:
+            keys_data = """
+            if [ ! -d /root/.ssh ];then
+                mkdir /root/.ssh
+                chown root:root /root/.ssh
+                chmod 700 /root/.ssh
+                touch /root/.ssh/authorized_keys
+                chown root:root /root/.ssh/authorized_keys
+                chmod 600 /root/.ssh/authorized_keys
+                # make centos with selinux happy
+                which restorecon && restorecon -Rv /root/.ssh
+            else
+                touch /root/.ssh/authorized_keys
+                chown root:root /root/.ssh/authorized_keys
+                chmod 600 /root/.ssh/authorized_keys
+            fi
+            echo '{key}' >> /root/.ssh/authorized_keys
+            """.format(key=keys)
+
+            bash_script+= keys_data
+
+        for user in users_list:
+            if 'name' in user: user_name = user['name']
+            if 'key-pairs' in user:
+                user_keys = "\n".join(user['key-pairs'])
+            else:
+                user_keys = None
+
+            add_user_name = """
+                useradd -d /home/{user_name} -m -g users -s /bin/bash {user_name}
+                """.format(user_name=user_name)
+
+            bash_script+= add_user_name
+
+            if user_keys:
+                user_keys_data = """
+                mkdir /home/{user_name}/.ssh
+                chown {user_name}:{user_name} /home/{user_name}/.ssh
+                chmod 700 /home/{user_name}/.ssh
+                touch /home/{user_name}/.ssh/authorized_keys
+                chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
+                chmod 600 /home/{user_name}/.ssh/authorized_keys
+                # make centos with selinux happy
+                which restorecon && restorecon -Rv /home/{user_name}/.ssh
+                echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
+                """.format(user_name=user_name,user_key=user_keys)
+
+                bash_script+= user_keys_data
+
+        return bash_script+"\n\tfi"
+
+    def guest_customization(self, vapp, customize_script):
+        """
+        Method to customize guest os
+        vapp - Vapp object
+        customize_script - Customize script to be run at first boot of VM.
+        """
+        for vm in vapp._get_vms():
+            vm_name = vm.name
+            task = vapp.customize_guest_os(vm_name, customization_script=customize_script)
+            if isinstance(task, GenericTask):
+                self.vca.block_until_completed(task)
+                self.logger.info("guest_customization : customized guest os task "\
+                                             "completed for VM {}".format(vm_name))
+            else:
+                self.logger.error("guest_customization : task for customized guest os"\
+                                                    "failed for VM {}".format(vm_name))
+                raise vimconn.vimconnException("guest_customization : failed to perform"\
+                                       "guest os customization on VM {}".format(vm_name))
 
     def add_new_disk(self, vapp_uuid, disk_size):
         """
@@ -4921,7 +5073,7 @@ class vimconnector(vimconn.vimconnector):
             raise vimconn.vimconnException(message=exp)
 
 
-    def retry_rest(self, api, url, add_headers=None, data=None):
+    def retry_rest(self, method, url, add_headers=None, data=None):
         """ Method to get Token & retry respective REST request
             Args:
                 api - REST API - Can be one of 'GET' or 'PUT' or 'POST'
@@ -4941,25 +5093,30 @@ class vimconnector(vimconn.vimconnector):
         if add_headers:
             headers.update(add_headers)
 
-        if api == 'GET':
+        if method == 'GET':
             response = Http.get(url=url,
                                 headers=headers,
                                 verify=self.vca.verify,
                                 logger=self.vca.logger)
-            return response
-        elif api == 'PUT':
-            if headers:
-                headers.append
+        elif method == 'PUT':
             response = Http.put(url=url,
                                 data=data,
                                 headers=headers,
-                                verify=self.vca.verify, logger=self.logger)
-            return response
-        elif api == 'POST':
+                                verify=self.vca.verify,
+                                logger=self.logger)
+        elif method == 'POST':
             response = Http.post(url=url,
                                  headers=headers,
+                                 data=data,
                                  verify=self.vca.verify,
                                  logger=self.vca.logger)
+        elif method == 'DELETE':
+            response = Http.delete(url=url,
+                                 headers=headers,
+                                 verify=self.vca.verify,
+                                 logger=self.vca.logger)
+        return response
+
 
     def get_token(self):
         """ Generate a new token if expired
@@ -5012,3 +5169,4 @@ class vimconnector(vimconn.vimconnector):
 
         return vdc
 
+
index 624dce3..ac28f0d 100755 (executable)
@@ -283,7 +283,8 @@ echo -e "\n"\
     "#####        INSTALLING OVIM LIBRARY                        #####\n"\
     "#################################################################"
 su $SUDO_USER -c "git -C ${BASEFOLDER} clone ${GIT_OVIM_URL} openvim"
-[[ -z $DEVELOP ]] && su $SUDO_USER -c "git -C ${BASEFOLDER}/openvim checkout v2.0"
+LATEST_STABLE_TAG=`git -C "${BASEFOLDER}/openvim" tag -l v[0-9].* | tail -n1`
+[[ -z $DEVELOP ]] && su $SUDO_USER -c "git -C ${BASEFOLDER}/openvim checkout tags/${LATEST_STABLE_TAG}"
 
 # Install debian dependencies before setup.py
 [ "$_DISTRO" == "Ubuntu" ] && install_packages "libmysqlclient-dev"
index 303a652..70cefd4 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,6 @@ from os import system
 #import glob
 
 _name = 'osm_ro'
-_version = open('RO_VERSION').read().strip()
 _description = 'OSM Resource Orchestrator'
 _author = 'ETSI OSM'
 _author_email = 'alfonso.tiernosepulveda@telefonica.com'
@@ -18,7 +17,8 @@ _url = 'https://osm.etsi.org/gitweb/?p=osm/RO.git;a=summary'
 _requirements = [
     "PyYAML",
     "bottle",
-    "MySQL-python",
+    #"mysqlclient",
+    #"MySQLdb",
     "jsonschema",
     "paramiko",
     "argcomplete",
@@ -30,15 +30,17 @@ _requirements = [
     "python-glanceclient",
     "python-neutronclient",
     "python-cinderclient",
-    "pyvcloud",
-    "progressbar",
+    #"pyvcloud",
+    #"progressbar",
     "prettytable",
-    "pyvmomi",
+    #"pyvmomi",
     "boto",
+    #"lib_osm_openvim",
+    #"osm_im",
 ]
 
 setup(name=_name,
-      version = _version,
+      version_command=('git describe', 'pep440-git'),
       description = _description,
       long_description = open('README.rst').read(),
       author = _author,
@@ -60,5 +62,7 @@ setup(name=_name,
       scripts=['openmanod', 'openmano', 'osm_ro/scripts/service-openmano', 'osm_ro/scripts/openmano-report',],
       install_requires=_requirements,
       include_package_data=True,
+      setup_requires=['setuptools-version-command'],
+      #test_suite='nose.collector',
       )
 
index a0c20ec..8a4507e 100644 (file)
--- a/stdeb.cfg
+++ b/stdeb.cfg
@@ -2,5 +2,5 @@
 Suite: xenial
 XS-Python-Version: >= 2.7
 Maintainer: Gerardo Garcia <gerardo.garciadeblas@telefonica.com>
-Depends: python-pip, libmysqlclient-dev, libssl-dev, libffi-dev, python-argcomplete, python-boto, python-bottle, python-jsonschema, python-logutils, python-cinderclient, python-glanceclient, python-keystoneclient, python-neutronclient, python-novaclient, python-openstackclient, python-mysqldb
+Depends: python-pip, libmysqlclient-dev, libssl-dev, libffi-dev, python-argcomplete, python-boto, python-bottle, python-jsonschema, python-logutils, python-cinderclient, python-glanceclient, python-keystoneclient, python-neutronclient, python-novaclient, python-openstackclient, python-mysqldb, python-lib-osm-openvim
 
diff --git a/test/RO_tests/afiinity_vnf/scenario_simple_2_vnf_afinnity.yaml b/test/RO_tests/afiinity_vnf/scenario_simple_2_vnf_afinnity.yaml
new file mode 100644 (file)
index 0000000..deae332
--- /dev/null
@@ -0,0 +1,38 @@
+##
+# 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
+##
+---
+schema_version:  2
+scenario:
+  name:          simple_ha
+  description:   Simple network scenario consisting of two VNF connected to an external network
+  vnfs:
+    linux1:                   # vnf/net name in the scenario
+      vnf_name:  linux_test_2vms # VNF name as introduced in OPENMANO DB
+  networks:
+    mgmt:                   # provide a name for this net or connection
+      external:  true
+      interfaces:
+      - linux1:  control0       # Node and its interface
+      - linux1:  control1       # Node and its interface
+
+
+
+
diff --git a/test/RO_tests/afiinity_vnf/vnfd_linux_2_vnfc_affinity.yaml b/test/RO_tests/afiinity_vnf/vnfd_linux_2_vnfc_affinity.yaml
new file mode 100644 (file)
index 0000000..9ec7f60
--- /dev/null
@@ -0,0 +1,61 @@
+##
+# 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
+##
+---
+
+vnf:
+    name:        linux_test_2vms
+    description: Single-VM VNF with a traditional cloud VM based on generic Linux OS
+    external-connections:
+    -   name:              control0
+        type:              mgmt              # "mgmt" (autoconnect to management net), "bridge", "data"
+        VNFC:              linux-VM-HA-A  # Virtual Machine this interface belongs to
+        local_iface_name:  eth0             # interface name inside this Virtual Machine (must be defined in the VNFC section)
+        description:       Management interface 0
+    -   name:              control1
+        type:              mgmt              # "mgmt" (autoconnect to management net), "bridge", "data"
+        VNFC:              linux-VM-HA-B  # Virtual Machine this interface belongs to
+        local_iface_name:  eth0             # interface name inside this Virtual Machine (must be defined in the VNFC section)
+        description:       Management interface 1
+    VNFC:
+    -   name:        linux-VM-HA-A
+        description: Generic Linux Virtual Machine
+        availability_zone: A  # availanility zone A
+        #Copy the image to a compute path and edit this path
+        image name:  TestVM
+        vcpus: 1          # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed).
+        ram: 1024         # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed)
+        disk: 10
+        bridge-ifaces:
+        -   name:      eth0
+            vpci:      "0000:00:11.0"
+        numas: []
+    -   name:        linux-VM-HA-B
+        description: Generic Linux Virtual Machine
+        availability_zone: B # availanility zone B
+        #Copy the image to a compute path and edit this path
+        image name:  TestVM
+        vcpus: 1          # Only for traditional cloud VMs. Number of virtual CPUs (oversubscription is allowed).
+        ram: 1024         # Only for traditional cloud VMs. Memory in MBytes (not from hugepages, oversubscription is allowed)
+        disk: 10
+        bridge-ifaces:
+        -   name:      eth0
+            vpci:      "0000:00:12.0"
+        numas: []
diff --git a/test/RO_tests/simple_count3/scenario_linux_count3.yaml b/test/RO_tests/simple_count3/scenario_linux_count3.yaml
new file mode 100644 (file)
index 0000000..2362c02
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# 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
+##
+---
+schema_version:  2
+scenario:
+  name:          simple_count3
+  description:   Simple network scenario consisting of a multi VNFC VNF connected to an external network
+  vnfs: 
+    linux1:                   # vnf/net name in the scenario
+      vnf_name:  simple_linux_count3        # VNF name as introduced in OPENMANO DB
+  networks: 
+    mgmt:                   # provide a name for this net or connection
+      external:  true
+      interfaces: 
+      - linux1:  control0       # Node and its interface
+    internal1:                   # provide a name for this net or connection
+      external:  false
+      interfaces: 
+      - linux1:  data-eth1
+
+
diff --git a/test/RO_tests/simple_count3/vnfd_count3.yaml b/test/RO_tests/simple_count3/vnfd_count3.yaml
new file mode 100644 (file)
index 0000000..a4c7070
--- /dev/null
@@ -0,0 +1,68 @@
+##
+# 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
+##
+---
+schema_version: "0.2"
+vnf:
+    name:        simple_linux_count3
+    description: "Example of a linux VNF consisting of two VMs with one internal network"
+    # class: parent      # Optional. Used to organize VNFs
+    internal-connections:
+    -   name:        internal-eth2
+        description: internalnet
+        type:        e-lan
+        implementation: overlay
+        ip-profile:
+            ip-version:       IPv4
+            subnet-address:   192.168.1.0/24
+            gateway-address:  192.168.1.1
+            dns-address:      8.8.8.8
+            dhcp:
+                enabled: true
+                start-address: 192.168.1.100
+                count: 100
+        elements:
+        -   VNFC:             linux_3VMs
+            local_iface_name: eth2
+            ip_address:       192.168.1.2
+    external-connections:
+    -   name:              control0
+        type:              mgmt
+        VNFC:              linux_3VMs
+        local_iface_name:  eth0
+        description:       control interface VM1
+    -   name:              data-eth1
+        type:              bridge
+        VNFC:              linux_3VMs
+        local_iface_name:  eth1
+        description:       data interface input
+    VNFC:
+    -   name:        linux_3VMs
+        count:       3
+        description: "Linux VM1 2 CPUs, 2 GB RAM and 3 bridge interfaces"
+        #Copy the image to a compute path and edit this path
+        image name:  TestVM
+        disk: 10
+        vcpus: 2
+        ram: 2048
+        bridge-ifaces:
+        -   name:      eth0
+        -   name:      eth1
+        -   name:      eth2
index 21af36c..5b47182 100755 (executable)
@@ -280,24 +280,6 @@ class test_VIM_tenant_operations(test_base):
         assert ('deleted' in tenant.get('result', ""))
 
 class test_vimconn_connect(test_base):
-    # test_index = 1
-    # test_text = None
-
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
-
-    # def tearDown(self):
-    #     exec_info = sys.exc_info()
-    #     if exec_info == (None, None, None):
-    #         logger.info(self.__class__.test_text+" -> TEST OK")
-    #     else:
-    #         logger.warning(self.__class__.test_text+" -> TEST NOK")
-    #         logger.critical("Traceback error",exc_info=True)
 
     def test_000_connect(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
@@ -312,25 +294,7 @@ class test_vimconn_connect(test_base):
 
 
 class test_vimconn_new_network(test_base):
-    # test_index = 1
     network_name = None
-    # test_text = None
-
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
-
-    # def tearDown(self):
-    #     exec_info = sys.exc_info()
-    #     if exec_info == (None, None, None):
-    #         logger.info(self.__class__.test_text+" -> TEST OK")
-    #     else:
-    #         logger.warning(self.__class__.test_text+" -> TEST NOK")
-    #         logger.critical("Traceback error",exc_info=True)
 
     def test_000_new_network(self):
         self.__class__.network_name = _get_random_string(20)
@@ -345,7 +309,7 @@ class test_vimconn_new_network(test_base):
         self.__class__.network_id = network
         logger.debug("{}".format(network))
 
-        network_list = test_config["vim_conn"].get_vcd_network_list()
+        network_list = test_config["vim_conn"].get_network_list()
         for net in network_list:
             if self.__class__.network_name in net.get('name'):
                 self.assertIn(self.__class__.network_name, net.get('name'))
@@ -373,7 +337,7 @@ class test_vimconn_new_network(test_base):
             delete_net_ids.append(network_id)
             logger.debug("{}".format(network_id))
 
-            network_list = test_config["vim_conn"].get_vcd_network_list()
+            network_list = test_config["vim_conn"].get_network_list()
             for net in network_list:
                 if self.__class__.network_name in net.get('name'):
                     self.assertIn(self.__class__.network_name, net.get('name'))
@@ -425,7 +389,7 @@ class test_vimconn_new_network(test_base):
         self.__class__.network_id = network
         logger.debug("{}".format(network))
 
-        network_list = test_config["vim_conn"].get_vcd_network_list()
+        network_list = test_config["vim_conn"].get_network_list()
         for net in network_list:
             if self.__class__.network_name in net.get('name'):
                 self.assertIn(self.__class__.network_name, net.get('name'))
@@ -450,7 +414,7 @@ class test_vimconn_new_network(test_base):
         self.__class__.network_id = network
         logger.debug("{}".format(network))
 
-        network_list = test_config["vim_conn"].get_vcd_network_list()
+        network_list = test_config["vim_conn"].get_network_list()
         for net in network_list:
             if self.__class__.network_name in net.get('name'):
                 self.assertIn(self.__class__.network_name, net.get('name'))
@@ -473,7 +437,7 @@ class test_vimconn_new_network(test_base):
                                                                     net_type='unknowntype')
         self.__class__.network_id = network
         logger.debug("{}".format(network))
-        network_list = test_config["vim_conn"].get_vcd_network_list()
+        network_list = test_config["vim_conn"].get_network_list()
         for net in network_list:
             if self.__class__.network_name in net.get('name'):
                 self.assertIn(self.__class__.network_name, net.get('name'))
@@ -520,18 +484,8 @@ class test_vimconn_new_network(test_base):
         self.assertEqual(net_dict, {})
 
 class test_vimconn_get_network_list(test_base):
-    # test_index = 1
     network_name = None
 
-    # test_text = None
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
-
     def setUp(self):
         # creating new network
         self.__class__.network_name = _get_random_string(20)
@@ -543,12 +497,6 @@ class test_vimconn_get_network_list(test_base):
 
     def tearDown(self):
         test_base.tearDown(self)
-        # exec_info = sys.exc_info()
-        # if exec_info == (None, None, None):
-        #     logger.info(self.__class__.test_text+" -> TEST OK")
-        # else:
-        #     logger.warning(self.__class__.test_text+" -> TEST NOK")
-        #     logger.critical("Traceback error",exc_info=True)
 
         # Deleting created network
         result = test_config["vim_conn"].delete_network(self.__class__.network_id)
@@ -666,17 +614,7 @@ class test_vimconn_get_network_list(test_base):
         self.assertEqual(network_list, [])
 
 class test_vimconn_get_network(test_base):
-    # test_index = 1
     network_name = None
-    # test_text = None
-
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
 
     def setUp(self):
         # creating new network
@@ -689,12 +627,6 @@ class test_vimconn_get_network(test_base):
 
     def tearDown(self):
         test_base.tearDown(self)
-        # exec_info = sys.exc_info()
-        # if exec_info == (None, None, None):
-        #     logger.info(self.__class__.test_text+" -> TEST OK")
-        # else:
-        #     logger.warning(self.__class__.test_text+" -> TEST NOK")
-        #     logger.critical("Traceback error",exc_info=True)
 
         # Deleting created network
         result = test_config["vim_conn"].delete_network(self.__class__.network_id)
@@ -726,25 +658,7 @@ class test_vimconn_get_network(test_base):
         self.assertEqual(network_info, {})
 
 class test_vimconn_delete_network(test_base):
-    # test_index = 1
     network_name = None
-    # test_text = None
-
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
-
-    # def tearDown(self):
-    #     exec_info = sys.exc_info()
-    #     if exec_info == (None, None, None):
-    #         logger.info(self.__class__.test_text+" -> TEST OK")
-    #     else:
-    #         logger.warning(self.__class__.test_text+" -> TEST NOK")
-    #         logger.critical("Traceback error",exc_info=True)
 
     def test_000_delete_network(self):
         # Creating network
@@ -784,24 +698,6 @@ class test_vimconn_delete_network(test_base):
         self.assertEqual((context.exception).http_code, 400)
 
 class test_vimconn_get_flavor(test_base):
-    # test_index = 1
-    # test_text = None
-
-    # @classmethod
-    # def setUpClass(cls):
-    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    # @classmethod
-    # def tearDownClass(cls):
-    #     test_config["test_number"] += 1
-
-    # def tearDown(self):
-    #     exec_info = sys.exc_info()
-    #     if exec_info == (None, None, None):
-    #         logger.info(self.__class__.test_text+" -> TEST OK")
-    #     else:
-    #         logger.warning(self.__class__.test_text+" -> TEST NOK")
-    #         logger.critical("Traceback error",exc_info=True)
 
     def test_000_get_flavor(self):
         test_directory_content = os.listdir(test_config["test_directory"])
@@ -927,6 +823,7 @@ class test_vimconn_new_image(test_base):
         image_path = test_config['image_path']
         if image_path:
             image_id = test_config["vim_conn"].new_image({ 'name': 'TestImage', 'location' : image_path })
+            time.sleep(20)
             self.assertEqual(type(image_id),str)
             self.assertIsInstance(uuid.UUID(image_id),uuid.UUID)
         else:
@@ -945,6 +842,28 @@ class test_vimconn_new_image(test_base):
 
         self.assertEqual((context.exception).http_code, 400)
 
+    def test_020_delete_image(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        image_id = test_config["vim_conn"].delete_image(self.__class__.image_id)
+        self.assertEqual(type(image_id),str)
+
+    def test_030_delete_image_negative(self):
+        Non_exist_image_id = str(uuid.uuid4())
+
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        with self.assertRaises(Exception) as context:
+            test_config["vim_conn"].delete_image(Non_exist_image_id)
+
+        self.assertEqual((context.exception).http_code, 404)
+
 class test_vimconn_get_image_id_from_path(test_base):
 
     def test_000_get_image_id_from_path(self):
@@ -1333,6 +1252,127 @@ class test_vimconn_new_vminstance(test_base):
         test_config["vim_conn"].delete_vminstance(self.__class__.instance_id)
         time.sleep(10)
 
+class test_vimconn_get_tenant_list(test_base):
+    tenant_id = None
+
+    def test_000_get_tenant_list(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        # Getting tenant list
+        tenant_list = test_config["vim_conn"].get_tenant_list()
+
+        for item in tenant_list:
+            if test_config['tenant'] == item['name']:
+                self.__class__.tenant_id = item['id']
+                self.assertEqual(type(item['name']), str)
+                self.assertEqual(type(item['id']), str)
+
+    def test_010_get_tenant_list_by_id(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        # Getting filter tenant list by its id
+        filter_tenant_list = test_config["vim_conn"].get_tenant_list({'id': self.__class__.tenant_id})
+
+        for item in filter_tenant_list:
+            self.assertEqual(type(item['id']), str)
+            self.assertEqual(item['id'], self.__class__.tenant_id)
+
+    def test_020_get_tenant_list_by_name(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        # Getting filter tenant list by its name
+        filter_tenant_list = test_config["vim_conn"].get_tenant_list({'name': test_config['tenant']})
+
+        for item in filter_tenant_list:
+            self.assertEqual(type(item['name']), str)
+            self.assertEqual(item['name'], test_config['tenant'])
+
+    def test_030_get_tenant_list_by_name_and_id(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        # Getting filter tenant list by its name and id
+        filter_tenant_list = test_config["vim_conn"].get_tenant_list({'name': test_config['tenant'],
+                                                                    'id': self.__class__.tenant_id})
+
+        for item in filter_tenant_list:
+            self.assertEqual(type(item['name']), str)
+            self.assertEqual(type(item['id']), str)
+            self.assertEqual(item['name'], test_config['tenant'])
+            self.assertEqual(item['id'], self.__class__.tenant_id)
+
+    def test_040_get_tenant_list_negative(self):
+        non_exist_tenant_name = "Tenant_123"
+        non_exist_tenant_id = "kjhgrt456-45345kjhdfgnbdk-34dsfjdfg"
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        filter_tenant_list = test_config["vim_conn"].get_tenant_list({'name': non_exist_tenant_name,
+                                                                         'id': non_exist_tenant_id})
+
+        self.assertEqual(filter_tenant_list, [])
+
+class test_vimconn_new_tenant(test_base):
+    tenant_id = None
+
+    def test_000_new_tenant(self):
+        tenant_name = _get_random_string(20)
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        self.__class__.tenant_id = test_config["vim_conn"].new_tenant(tenant_name)
+        time.sleep(15)
+
+        self.assertEqual(type(self.__class__.tenant_id), str)
+
+    def test_010_new_tenant_negative(self):
+        Invalid_tenant_name = 10121
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        with self.assertRaises(Exception) as context:
+            test_config["vim_conn"].new_tenant(Invalid_tenant_name)
+
+        self.assertEqual((context.exception).http_code, 400)
+
+    def test_020_delete_tenant(self):
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        tenant_id = test_config["vim_conn"].delete_tenant(self.__class__.tenant_id)
+        self.assertEqual(type(tenant_id), str)
+
+    def test_030_delete_tenant_negative(self):
+        Non_exist_tenant_name = 'Test_30_tenant'
+        self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
+                                                            self.__class__.test_index,
+                                                inspect.currentframe().f_code.co_name)
+        self.__class__.test_index += 1
+
+        with self.assertRaises(Exception) as context:
+            test_config["vim_conn"].delete_tenant(Non_exist_tenant_name)
+
+        self.assertEqual((context.exception).http_code, 404)
+
 '''
 IMPORTANT NOTE
 The following unittest class does not have the 'test_' on purpose. This test is the one used for the
diff --git a/tox.ini b/tox.ini
new file mode 100644 (file)
index 0000000..025f4a0
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,22 @@
+[tox]
+#envlist = py27,py3
+envlist = py27
+toxworkdir={homedir}/.tox
+
+[testenv]
+deps=nose
+     mock
+commands=nosetests
+
+[testenv:flake8]
+basepython = python
+deps = flake8
+commands =
+    flake8 setup.py
+
+[testenv:build]
+basepython = python
+deps = stdeb
+       setuptools-version-command
+commands = python setup.py --command-packages=stdeb.command bdist_deb
+    
index 121c5ab..b57ebfd 100644 (file)
@@ -46,6 +46,7 @@ vnf:
         description:       Bridge interface
     VNFC:                              # Virtual machine array 
     -   name:        TEMPLATE-VM       # name of Virtual Machine
+        # count:       1                 #by default 1
         description: TEMPLATE description
         VNFC image: /path/to/imagefolder/TEMPLATE-VM.qcow2
         # image metadata: {"bus":"ide", "os_type":"windows", "use_incremental": "no" } #Optional