From caeb224da9840534e46ae0e8f5e194575521c668 Mon Sep 17 00:00:00 2001 From: mirabal Date: Wed, 31 May 2017 10:52:22 -0500 Subject: [PATCH] Empty disk support added to openvim Change-Id: Ib54e4da5bfdeb4b974e8b8e0d260977fa7793fdc Signed-off-by: mirabal --- database_utils/migrate_vim_db.sh | 17 ++++++- osm_openvim/host_thread.py | 80 +++++++++++++++++++++++--------- osm_openvim/httpserver.py | 2 +- osm_openvim/ovim.py | 6 +-- osm_openvim/vim_db.py | 8 ++-- osm_openvim/vim_schema.py | 3 +- 6 files changed, 84 insertions(+), 32 deletions(-) diff --git a/database_utils/migrate_vim_db.sh b/database_utils/migrate_vim_db.sh index 27a5d92..aded5a0 100755 --- a/database_utils/migrate_vim_db.sh +++ b/database_utils/migrate_vim_db.sh @@ -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 diff --git a/osm_openvim/host_thread.py b/osm_openvim/host_thread.py index 620f25c..00d253e 100644 --- a/osm_openvim/host_thread.py +++ b/osm_openvim/host_thread.py @@ -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 diff --git a/osm_openvim/httpserver.py b/osm_openvim/httpserver.py index 8232df5..aa23d89 100644 --- a/osm_openvim/httpserver.py +++ b/osm_openvim/httpserver.py @@ -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'} diff --git a/osm_openvim/ovim.py b/osm_openvim/ovim.py index fba2320..82d06ce 100755 --- a/osm_openvim/ovim.py +++ b/osm_openvim/ovim.py @@ -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 diff --git a/osm_openvim/vim_db.py b/osm_openvim/vim_db.py index 31d4a0f..5fc7c91 100644 --- a/osm_openvim/vim_db.py +++ b/osm_openvim/vim_db.py @@ -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 diff --git a/osm_openvim/vim_schema.py b/osm_openvim/vim_schema.py index a296083..1925f05 100644 --- a/osm_openvim/vim_schema.py +++ b/osm_openvim/vim_schema.py @@ -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"] -- 2.17.1