Empty disk support added to openvim 18/1918/2
authormirabal <leonardo.mirabal@altran.com>
Wed, 31 May 2017 15:52:22 +0000 (10:52 -0500)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Fri, 2 Jun 2017 10:16:45 +0000 (11:16 +0100)
Change-Id: Ib54e4da5bfdeb4b974e8b8e0d260977fa7793fdc
Signed-off-by: mirabal <leonardo.mirabal@altran.com>
database_utils/migrate_vim_db.sh
osm_openvim/host_thread.py
osm_openvim/httpserver.py
osm_openvim/ovim.py
osm_openvim/vim_db.py
osm_openvim/vim_schema.py

index 27a5d92..aded5a0 100755 (executable)
@@ -33,7 +33,7 @@ DBPORT="3306"
 DBNAME="vim_db"
 QUIET_MODE=""
 #TODO update it with the last database version
-LAST_DB_VERSION=19
+LAST_DB_VERSION=20
 
 # Detect paths
 MYSQL=$(which mysql)
@@ -187,6 +187,7 @@ fi
 #[ $OPENVIM_VER_NUM -ge 5010 ] && DATABASE_TARGET_VER_NUM=17  #0.5.10  => 17
 #[ $OPENVIM_VER_NUM -ge 5013 ] && DATABASE_TARGET_VER_NUM=18  #0.5.13  => 18
 #[ $OPENVIM_VER_NUM -ge 5015 ] && DATABASE_TARGET_VER_NUM=19  #0.5.15  => 19
+#[ $OPENVIM_VER_NUM -ge 5017 ] && DATABASE_TARGET_VER_NUM20   #0.5.17  => 20
 # TODO ... put next versions here
 
 function upgrade_to_1(){
@@ -687,6 +688,20 @@ function downgrade_from_19(){
     echo "DELETE FROM schema_version WHERE version_int = '19';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
 }
 
+function upgrade_to_20(){
+    echo "    Add 'image_size' to 'instance_devices'"
+    echo "ALTER TABLE instance_devices ADD COLUMN image_size INT NULL DEFAULT NULL AFTER dev;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "INSERT INTO schema_version (version_int, version, openvim_ver, comments, date) VALUES (20, '0.20', '0.5.17', 'Add image_size to instance_devices', '2017-06-01');"\
+         | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+
+
+}
+
+function downgrade_from_20(){
+    echo "    Delete 'image_size' from 'instance_devices'"
+    echo "ALTER TABLE instance_devices DROP COLUMN image_size;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "DELETE FROM schema_version WHERE version_int = '20';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
 
 #TODO ... put funtions here
 
index 620f25c..00d253e 100644 (file)
@@ -85,6 +85,7 @@ class host_thread(threading.Thread):
         self.develop_mode = develop_mode
         self.develop_bridge_iface = develop_bridge_iface
         self.image_path = image_path
+        self.empty_image_path = image_path
         self.host_id = host_id
         self.version = version
         
@@ -222,13 +223,14 @@ class host_thread(threading.Thread):
             tries-=1
             
             try:
-                command = 'cat > ' +  self.image_path + '/.openvim.yaml'
+                command = 'cat > ' + self.image_path + '/.openvim.yaml'
                 self.logger.debug("command:" + command)
                 (stdin, _, _) = self.ssh_conn.exec_command(command)
                 yaml.safe_dump(self.localinfo, stdin, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
+
                 self.localinfo_dirty = False
                 break #while tries
-    
+
             except paramiko.ssh_exception.SSHException as e:
                 text = e.args[0]
                 self.logger.error("save_localinfo ssh Exception: " + text)
@@ -574,7 +576,7 @@ class host_thread(threading.Thread):
                 #else:
                 #    return -1, 'Unknown disk type ' + v['type']
                 vpci = dev.get('vpci',None)
-                if vpci == None:
+                if vpci == None and 'metadata' in dev:
                     vpci = dev['metadata'].get('vpci',None)
                 text += self.pci2xml(vpci)
                
@@ -1357,6 +1359,24 @@ class host_thread(threading.Thread):
         else:
             self.logger.error("qemu_change_backing error: " + content)
             return -1
+
+    def qemu_create_empty_disk(self, dev):
+
+        if not dev and 'source' not in dev and 'file format' not in dev and 'image_size' not in dev:
+            self.logger.error("qemu_create_empty_disk error: missing image parameter")
+            return -1
+
+        empty_disk_path = dev['source file']
+
+        command = 'qemu-img create -f qcow2 ' + empty_disk_path + ' ' + str(dev['image_size']) + 'G'
+        self.logger.debug("command: " + command)
+        (_, _, stderr) = self.ssh_conn.exec_command(command)
+        content = stderr.read()
+        if len(content) == 0:
+            return 0
+        else:
+            self.logger.error("qemu_create_empty_disk error: " + content)
+            return -1
     
     def get_notused_filename(self, proposed_name, suffix=''):
         '''Look for a non existing file_name in the host
@@ -1528,31 +1548,45 @@ class host_thread(threading.Thread):
             devices = [  {"type":"disk", "image_id":server['image_id'], "vpci":server_metadata.get('vpci', None) } ] 
             if 'extended' in server_data and server_data['extended']!=None and "devices" in server_data['extended']:
                 devices += server_data['extended']['devices']
-
+            empty_path = None
             for dev in devices:
-                if dev['image_id'] == None:
+                image_id = dev.get('image_id')
+                if not image_id:
+                    import uuid
+                    uuid_empty = str(uuid.uuid4())
+                    empty_path = self.empty_image_path + uuid_empty + '.qcow2' # local path for empty disk
+
+                    dev['source file'] = empty_path
+                    dev['file format'] = 'qcow2'
+                    self.qemu_create_empty_disk(dev)
+                    server_host_files[uuid_empty] = {'source file': empty_path,
+                                                     'file format': dev['file format']}
+
                     continue
-                
-                self.db_lock.acquire()
-                result, content = self.db.get_table(FROM='images', SELECT=('path', 'metadata'),
-                                                    WHERE={'uuid': dev['image_id']})
-                self.db_lock.release()
-                if result <= 0:
-                    error_text = "ERROR", result, content, "when getting image", dev['image_id']
-                    self.logger.error("launch_server " + error_text)
-                    return -1, error_text
-                if content[0]['metadata'] is not None:
-                    dev['metadata'] = json.loads(content[0]['metadata'])
                 else:
-                    dev['metadata'] = {}
-                
-                if dev['image_id'] in server_host_files:
-                    dev['source file'] = server_host_files[ dev['image_id'] ] ['source file'] #local path
-                    dev['file format'] = server_host_files[ dev['image_id'] ] ['file format'] # raw or qcow2
-                    continue
+                    self.db_lock.acquire()
+                    result, content = self.db.get_table(FROM='images', SELECT=('path', 'metadata'),
+                                                        WHERE={'uuid': image_id})
+                    self.db_lock.release()
+                    if result <= 0:
+                        error_text = "ERROR", result, content, "when getting image", dev['image_id']
+                        self.logger.error("launch_server " + error_text)
+                        return -1, error_text
+                    if content[0]['metadata'] is not None:
+                        dev['metadata'] = json.loads(content[0]['metadata'])
+                    else:
+                        dev['metadata'] = {}
+
+                    if image_id in server_host_files:
+                        dev['source file'] = server_host_files[image_id]['source file'] #local path
+                        dev['file format'] = server_host_files[image_id]['file format'] # raw or qcow2
+                        continue
                 
             #2: copy image to host
-                remote_file = content[0]['path']
+                if image_id:
+                    remote_file = content[0]['path']
+                else:
+                    remote_file = empty_path
                 use_incremental_image = use_incremental
                 if dev['metadata'].get("use_incremental") == "no":
                     use_incremental_image = False
index 8232df5..aa23d89 100644 (file)
@@ -150,7 +150,7 @@ def check_extended(extended, allow_net_attach=False):
 http2db_id={'id':'uuid'}
 http2db_host={'id':'uuid'}
 http2db_tenant={'id':'uuid'}
-http2db_flavor={'id':'uuid','imageRef':'image_id'}
+http2db_flavor={'id':'uuid','imageRef':'image_id', 'size': 'image_size'}
 http2db_image={'id':'uuid', 'created':'created_at', 'updated':'modified_at', 'public': 'public'}
 http2db_server={'id':'uuid','hostId':'host_id','flavorRef':'flavor_id','imageRef':'image_id','created':'created_at'}
 http2db_network={'id':'uuid','provider:vlan':'vlan', 'provider:physical': 'provider'}
index fba2320..82d06ce 100755 (executable)
@@ -42,9 +42,9 @@ import openflow_conn
 
 __author__ = "Alfonso Tierno, Leonardo Mirabal"
 __date__ = "$06-Feb-2017 12:07:15$"
-__version__ = "0.5.16-r532"
-version_date = "May 2017"
-database_version = 19      #needed database schema version
+__version__ = "0.5.17-r533"
+version_date = "Jun 2017"
+database_version = 20      #needed database schema version
 
 HTTP_Bad_Request =          400
 HTTP_Unauthorized =         401
index 31d4a0f..5fc7c91 100644 (file)
@@ -1070,7 +1070,7 @@ class vim_db():
                     #get extended
                     extended = {}
                     #get devices
-                    cmd = "SELECT type, vpci, image_id, xml,dev FROM instance_devices WHERE instance_id = '%s' " %  str(instance_id)
+                    cmd = "SELECT type, vpci, image_id, xml, dev, image_size FROM instance_devices WHERE instance_id = '%s' " %  str(instance_id)
                     self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     if self.cur.rowcount > 0 :
@@ -1520,8 +1520,10 @@ class vim_db():
                             else:                    xml = 'Null'
                             if 'dev' in device: dev = "'" + device['dev'] + "'"
                             else:                    dev = 'Null'
-                            cmd = "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev) VALUES ('%s','%s', %s, %s, %s, %s)" % \
-                                (device['type'], uuid, image_id, vpci, xml, dev)
+                            if 'image_size' in device: size = device['image_size']
+                            else:                    size = 0
+                            cmd = "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev, image_size) VALUES ('%s','%s', %s, %s, %s, %s, %s)" % \
+                                (device['type'], uuid, image_id, vpci, xml, dev, str(size))
                             self.logger.debug(cmd)
                             self.cur.execute(cmd)
                     ##inserting new log
index a296083..1925f05 100644 (file)
@@ -220,7 +220,8 @@ extended_schema={
                     "vpci":pci_schema,
                     "imageRef":id_schema,
                     "xml":xml_text_schema,
-                    "dev":nameshort_schema
+                    "dev":nameshort_schema,
+                    "size":integer1_schema,
                 },
                 "additionalProperties": False,
                 "required": ["type"]