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 ***")
Exemple #6
0
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 known_datastores():
    """returns names of know datastores"""
    return [i[0] for i in vmdk_utils.get_datastores()]
Exemple #9
0
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 ***")