def setUp(self): """ Setup run before each test """ logging.debug("VMDKAttachDetachTest setUp path =%s", path) self.cleanup() if (not self.datastore_name): datastores = vmdk_utils.get_datastores() datastore = datastores[0] if (not datastore): logging.error("Cannot find a valid datastore") self.assertFalse(True) self.datastore_name = datastore[0] self.datastore_path = datastore[2] logging.debug("datastore_name=%s datastore_path=%s", self.datastore_name, self.datastore_path) # get service_instance, and create a VM si = vmdk_ops.get_si() self.create_vm(si, self.vm_name, self.datastore_name) # create max_vol_count+1 VMDK files for id in range(1, self.max_vol_count+2): volName = 'VmdkAttachDetachTestVol' + str(id) fullpath = os.path.join(self.datastore_path, volName + '.vmdk') self.assertEqual(None, vmdk_ops.createVMDK(vm_name=self.vm_name, vmdk_path=fullpath, vol_name=volName))
def get_datastore_name(config_path): """Returns datastore NAME in config_path (not url-name which may be used in path)""" # path is always /vmfs/volumes/<datastore>/... , so extract datastore: config_ds_name = config_path.split("/")[3] ds_name = [x[0] for x in vmdk_utils.get_datastores() \ if x[0] == config_ds_name or x[1] == config_ds_name ] if len(ds_name) != 1: logging.error("get_datastore_name: found more than one match: %s" % ds_name) logging.debug("get_datastore_name: path=%s name=%s" % (config_ds_name, ds_name)) return ds_name[0]
def setUp(self): """ Setup run before each test """ self.vol_count = 0 self.cleanup() for (datastore, url, path) in vmdk_utils.get_datastores(): if not self.mkdir(path): continue for id in range(5): volName = 'testvol' + str(id) fullpath = os.path.join(path, volName + '.vmdk') self.assertEqual(None, vmdk_ops.createVMDK(vm_name='test-vm', vmdk_path=fullpath, vol_name=volName)) self.vol_count += 1
def setUp(self): """ Setup run before each test """ if (not self.datastore_name): datastores = vmdk_utils.get_datastores() if datastores: datastore = datastores[0] self.datastore_name = datastore[0] self.datastore_path = datastore[2] if len(datastores) > 1: datastore1 = datastores[1] self.datastore1_name = datastore1[0] self.datastoer1_path = datastore[2] else: self.assertFalse(True) self.cleanup() # get service_instance, and create VMs si = vmdk_ops.get_si() error, self.vm1 = test_utils.create_vm(si=si, vm_name=self.vm1_name, datastore_name=self.datastore_name) if error: self.assertFalse(True) self.vm1_config_path = vmdk_utils.get_vm_config_path(self.vm1_name) logging.info("TestTenant: create vm1 name=%s Done", self.vm1_name) error, self.vm2 = test_utils.create_vm(si=si, vm_name=self.vm2_name, datastore_name=self.datastore_name) if error: self.assertFalse(True) self.vm2_config_path = vmdk_utils.get_vm_config_path(self.vm2_name) logging.info("TestTenant: create vm2 name=%s Done", self.vm2_name)
def main(): """ This code updates ESX with vSphere Docker Volume Service 0.11 (and earlier) to 0.11.1 and further, by moving _DEFAULT tenant ID to well known and static UUID, and then correcting directories layout and auth_db tables to comply with new UUID. Specifically, it does the following: - Checks if AUTH_DB exists. If it does not, exit with a message - it means nothing to patch on this ESX - Gets uuid (aka "old_uuid') for _DEFAULT tenant from DB. If it already STATIC_UUID , exit with a message - nothing to patch - Stops the service - backs up the DB - scans through all <datastore>/volumes/dockvols and - mkdir STATIC_UUID, if it does not exist - move all from old_uuid to STATIC_UUID - symlinks "_DEFAULT" to STATIC_UUID In single DB transcation - replaces old_uuid with STATIC UUID in tenant_id field for all tables: (privileges, vms, tenants, volumes) starts the service , and if all good removes backup DB NOTE: this does not delete any data, so the Docker volumes will stay around no matter if the code succeeds or fails """ dbfile = auth_data.AUTH_DB_PATH # STEP: check DB presense and fetch old_uuid if not os.path.isfile(dbfile): print("Config DB", dbfile, "is not found, nothing to update - exiting.") sys.exit(0) cursor = sqlite3.connect(dbfile).cursor() cursor.execute("select * from tenants where name='{0}'".format(STATIC_NAME)) try: tenant_id, tenant_name, tenant_desr, tenant_def_ds = cursor.fetchone() except TypeError: print("Can't find '{0}' tenant, exiting".format(STATIC_NAME)) sys.exit(ERROR) print("Found default tenant: {0} {1} {2} {3}".format(tenant_id, tenant_name, tenant_desr, tenant_def_ds)) old_uuid = tenant_id if old_uuid == STATIC_UUID: print("*** DB seems to have been already migrated, exiting ***") sys.exit(OK) # STEP: Stop the service and back up the DB backup = dbfile + ".bck" if os.path.isfile(backup): print("Backup file '{0}' already exists - skipping DB backup".format(backup)) else: print("Backing up Config DB to '{0}'".format(backup)) shutil.copy(dbfile, backup) if STOP_SERVICE: print("Stopping vmdk-opsd service") os.system("/etc/init.d/vmdk-opsd stop") # STEP : patch a datastore - convert dir names to new UUID if needed and move files print("Starting conversion of _DEFAULT tenant directory names. old_uid is {0}".format(old_uuid)) stores = vmdk_utils.get_datastores() if not stores: print("Docker volume storage is not initialized - skipping directories patching") else: for datastore in stores: ds_path = datastore[2] patch_a_store(ds_path, old_uuid) # STEP: patch database print("Working on DB patch...") # sql for update the DB # note that: # {0} is old_uuid (default tenant uuid pre-upgrade) # {1} is new_uuid (default tenant uuid post-upgrade) # {2} is tmp name - we need it to comply with DB constraints # {3} is default tenant description (from DB) # {4} is default DB for default tenant (from DB) # {5} is the name ("_DEFAULT") for default tenant # TBD - use named params in formatting sql_query_template = \ """ -- insert temp record to make foreign key happy INSERT INTO tenants VALUES ( '{1}', '{2}', '{3}', '{4}' ) ; -- update the tables UPDATE vms SET tenant_id = '{1}' WHERE tenant_id = '{0}'; UPDATE volumes SET tenant_id = '{1}' WHERE tenant_id = '{0}'; UPDATE privileges SET tenant_id = '{1}' WHERE tenant_id = '{0}'; -- recover _DEFAULT tenant record DELETE FROM tenants WHERE id = '{0}'; UPDATE tenants SET name = '{5}' WHERE name = '{2}'; UPDATE versions SET major_ver=1, minor_ver=1; """ tmp_tenant_name = "__tmp_name_upgrade_0_11" sql_query = sql_query_template.format(old_uuid, STATIC_UUID, tmp_tenant_name, tenant_desr, tenant_def_ds, STATIC_NAME) cursor.executescript(sql_query) # STEP: restart the service if STOP_SERVICE: print("Starting vmdk-opsd service") os.system("/etc/init.d/vmdk-opsd start") # TBD: remove backup ? print ("*** ALL DONE ***")
def known_datastores(): """returns names of know datastores""" return [i[0] for i in vmdk_utils.get_datastores()]
def _remove_volumes_for_tenant(self, tenant_id): """ Delete all volumes belongs to this tenant. Do not use it outside of removing a tenant. """ try: cur = self.conn.execute("SELECT name FROM tenants WHERE id = ?", (tenant_id, )) result = cur.fetchone() except sqlite3.Error as e: logging.error("Error %s when querying from tenants table", e) return str(e) error_msg = "" if result: logging.debug("remove_volumes_for_tenant: %s %s", tenant_id, result) tenant_name = result[0] vmdks = vmdk_utils.get_volumes(tenant_name) # Delete all volumes for this tenant. dir_paths = set() for vmdk in vmdks: vmdk_path = os.path.join(vmdk['path'], "{0}".format(vmdk['filename'])) dir_paths.add(vmdk['path']) logging.debug("path=%s filename=%s", vmdk['path'], vmdk['filename']) logging.debug("Deleting volume path%s", vmdk_path) datastore_url = vmdk_utils.get_datastore_url(vmdk['datastore']) err = vmdk_ops.removeVMDK( vmdk_path=vmdk_path, vol_name=vmdk_utils.strip_vmdk_extension(vmdk['filename']), vm_name=None, tenant_uuid=tenant_id, datastore_url=datastore_url) if err: logging.error("remove vmdk %s failed with error %s", vmdk_path, err) error_msg += str(err) VOL_RM_LOG_PREFIX = "Tenant <name> %s removal: " # delete the symlink /vmfs/volume/datastore_name/tenant_name # which point to /vmfs/volumes/datastore_name/tenant_uuid for (datastore, url, path) in vmdk_utils.get_datastores(): dockvol_path, tenant_path = get_dockvol_path_tenant_path( datastore_name=datastore, tenant_id=tenant_id) logging.debug( VOL_RM_LOG_PREFIX + "try to remove symlink to %s", tenant_name, tenant_path) if os.path.isdir(tenant_path): exist_symlink_path = os.path.join(dockvol_path, tenant_name) if os.path.isdir(exist_symlink_path): os.remove(exist_symlink_path) logging.debug( VOL_RM_LOG_PREFIX + "removing symlink %s", tenant_name, exist_symlink_path) # Delete path /vmfs/volumes/datastore_name/tenant_uuid logging.debug("Deleting dir paths %s", dir_paths) for path in list(dir_paths): try: os.rmdir(path) except os.error as e: msg = "remove dir {0} failed with error {1}".format( path, e) logging.error(msg) error_msg += str(err) err = self.remove_volumes_from_volumes_table(tenant_id) if err: logging.error("Failed to remove volumes from database %s", err) error_msg += str(err) if error_msg: return error_msg return None
def main(): """ This code updates ESX with vSphere Docker Volume Service 0.11 (and earlier) to 0.11.1 and further, by moving _DEFAULT tenant ID to well known and static UUID, and then correcting directories layout and auth_db tables to comply with new UUID. Specifically, it does the following: - Checks if AUTH_DB exists. If it does not, exit with a message - it means nothing to patch on this ESX - Gets uuid (aka "old_uuid') for _DEFAULT tenant from DB. If it already STATIC_UUID , exit with a message - nothing to patch - Stops the service - backs up the DB - scans through all <datastore>/volumes/dockvols and - mkdir STATIC_UUID, if it does not exist - move all from old_uuid to STATIC_UUID - symlinks "_DEFAULT" to STATIC_UUID In single DB transcation - replaces old_uuid with STATIC UUID in tenant_id field for all tables: (privileges, vms, tenants, volumes) starts the service , and if all good removes backup DB NOTE: this does not delete any data, so the Docker volumes will stay around no matter if the code succeeds or fails """ dbfile = auth_data.AUTH_DB_PATH # STEP: check DB presense and fetch old_uuid if not os.path.isfile(dbfile): print("Config DB", dbfile, "is not found, nothing to update - exiting.") sys.exit(0) cursor = sqlite3.connect(dbfile).cursor() cursor.execute( "select * from tenants where name='{0}'".format(STATIC_NAME)) try: tenant_id, tenant_name, tenant_desr, tenant_def_ds = cursor.fetchone() except TypeError: print("Can't find '{0}' tenant, exiting".format(STATIC_NAME)) sys.exit(ERROR) print("Found default tenant: {0} {1} {2} {3}".format( tenant_id, tenant_name, tenant_desr, tenant_def_ds)) old_uuid = tenant_id if old_uuid == STATIC_UUID: print("*** DB seems to have been already migrated, exiting ***") sys.exit(OK) # STEP: Stop the service and back up the DB backup = dbfile + ".bck" if os.path.isfile(backup): print("Backup file '{0}' already exists - skipping DB backup".format( backup)) else: print("Backing up Config DB to '{0}'".format(backup)) shutil.copy(dbfile, backup) if STOP_SERVICE: print("Stopping vmdk-opsd service") os.system("/etc/init.d/vmdk-opsd stop") # STEP : patch a datastore - convert dir names to new UUID if needed and move files print( "Starting conversion of _DEFAULT tenant directory names. old_uid is {0}" .format(old_uuid)) stores = vmdk_utils.get_datastores() if not stores: print( "Docker volume storage is not initialized - skipping directories patching" ) else: for datastore in stores: ds_path = datastore[2] patch_a_store(ds_path, old_uuid) # STEP: patch database print("Working on DB patch...") # sql for update the DB # note that: # {0} is old_uuid (default tenant uuid pre-upgrade) # {1} is new_uuid (default tenant uuid post-upgrade) # {2} is tmp name - we need it to comply with DB constraints # {3} is default tenant description (from DB) # {4} is default DB for default tenant (from DB) # {5} is the name ("_DEFAULT") for default tenant # TBD - use named params in formatting sql_query_template = \ """ -- insert temp record to make foreign key happy INSERT INTO tenants VALUES ( '{1}', '{2}', '{3}', '{4}' ) ; -- update the tables UPDATE vms SET tenant_id = '{1}' WHERE tenant_id = '{0}'; UPDATE volumes SET tenant_id = '{1}' WHERE tenant_id = '{0}'; UPDATE privileges SET tenant_id = '{1}' WHERE tenant_id = '{0}'; -- recover _DEFAULT tenant record DELETE FROM tenants WHERE id = '{0}'; UPDATE tenants SET name = '{5}' WHERE name = '{2}'; UPDATE versions SET major_ver=1, minor_ver=1; """ tmp_tenant_name = "__tmp_name_upgrade_0_11" sql_query = sql_query_template.format(old_uuid, STATIC_UUID, tmp_tenant_name, tenant_desr, tenant_def_ds, STATIC_NAME) cursor.executescript(sql_query) # STEP: restart the service if STOP_SERVICE: print("Starting vmdk-opsd service") os.system("/etc/init.d/vmdk-opsd start") # TBD: remove backup ? print("*** ALL DONE ***")