예제 #1
0
def get_vol_fs_type(vol_name):
    """
    The argument need to be a full path lvm name i.e. /dev/vg0/var
    or a disk partition like /dev/sda1. The returnet value is the
    file system type
    """
    if os.path.exists(vol_name) is False:
        err = 'Provided volume name not found: {0} '.format(vol_name)
        LOG.exception(err)
        raise Exception(err)

    file_cmd = '{0} -0 -bLs --no-pad --no-buffer --preserve-date \
    {1}'.format(utils.find_executable("file"), vol_name)
    file_process = subprocess.Popen(
        file_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable("bash"))
    (file_out, file_err) = file_process.communicate()
    file_match = re.search(r'(\S+?) filesystem data', file_out, re.I)
    if file_match is None:
        err = 'File system type not guessable: {0}'.format(file_err)
        LOG.exception(err)
        raise Exception(err)
    else:
        filesys_type = file_match.group(1)
        LOG.info('File system {0} found for volume {1}'.format(
            filesys_type, vol_name))
        return filesys_type.lower().strip()
예제 #2
0
파일: lvm.py 프로젝트: openstack/freezer
def get_vol_fs_type(vol_name):
    """
    The argument need to be a full path lvm name i.e. /dev/vg0/var
    or a disk partition like /dev/sda1. The returnet value is the
    file system type
    """
    if os.path.exists(vol_name) is False:
        err = 'Provided volume name not found: {0} '.format(vol_name)
        LOG.exception(err)
        raise Exception(err)

    file_cmd = '{0} -0 -bLs --no-pad --no-buffer --preserve-date \
    {1}'.format(utils.find_executable("file"), vol_name)
    file_process = subprocess.Popen(
        file_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable("bash"))
    (file_out, file_err) = file_process.communicate()
    file_match = re.search(r'(\S+?) filesystem data', file_out, re.I)
    if file_match is None:
        err = 'File system type not guessable: {0}'.format(file_err)
        LOG.exception(err)
        raise Exception(err)
    else:
        filesys_type = file_match.group(1)
        LOG.info('File system {0} found for volume {1}'.format(
            filesys_type, vol_name))
        return filesys_type.lower().strip()
예제 #3
0
파일: lvm.py 프로젝트: popawu/freezer
def _lvremove(lv):
    lvremove_proc = subprocess.Popen(
        '{0} -f {1}'.format(utils.find_executable('lvremove'), lv),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    output, error = lvremove_proc.communicate()
    if lvremove_proc.returncode:
        raise Exception(
            'unable to remove snapshot {0}. {1}'.format(lv, error))
예제 #4
0
def _lvremove(lv):
    lvremove_proc = subprocess.Popen('{0} -f {1}'.format(
        utils.find_executable('lvremove'), lv),
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     shell=True,
                                     executable=utils.find_executable('bash'))
    output, error = lvremove_proc.communicate()
    if lvremove_proc.returncode:
        raise Exception('unable to remove snapshot {0}. {1}'.format(lv, error))
예제 #5
0
파일: lvm.py 프로젝트: BakerWang/freezer
def _umount(path):
    # TODO: check if cwd==path and change working directory to unmount ?
    umount_proc = subprocess.Popen('{0} -l -f {1}'.format(
        utils.find_executable('umount'), path),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        shell=True, executable=utils.find_executable('bash'))
    (umount_out, mount_err) = umount_proc.communicate()

    if umount_proc.returncode:
        raise Exception('impossible to umount {0}. {1}'
                        .format(path, mount_err))

    logging.info('[*] Volume {0} unmounted'.format(path))
예제 #6
0
def _umount(path):
    if os.getcwd().startswith(path):
        os.chdir('/')
    umount_proc = subprocess.Popen('{0} -l -f {1}'.format(
        utils.find_executable('umount'), path),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        shell=True, executable=utils.find_executable('bash'))
    (umount_out, mount_err) = umount_proc.communicate()

    if umount_proc.returncode:
        raise Exception('Impossible to umount {0}. {1}'
                        .format(path, mount_err))
    os.rmdir(path)
    LOG.info('Volume {0} unmounted'.format(path))
예제 #7
0
def log_volume_holding_process(lv):
    try:
        # Let's try to provide more information on the failure
        devices = [i.split("\t") for i in subprocess.check_output([
            utils.find_executable('dmsetup'), "ls"]).splitlines()]
        dev_id = [i[1].strip("()").split(":") for i in devices if
                  lv.split("/").pop() in i[0] and
                  not i[0].endswith("cow")][0]
        command = "{} | grep {},{}".format(
            # lsof is quite long, so no need to add a sleep here
            utils.find_executable('lsof'), dev_id[0], dev_id[1])
        process = subprocess.check_output([command], shell=True)
        LOG.warning("Process holding the volume is '{}'".format(process))
    except Exception as e:
        LOG.warning("Could not get informations on the process holding the"
                    " volume: {}".format(str(e)))
예제 #8
0
파일: lvm.py 프로젝트: openstack/freezer
def log_volume_holding_process(lv):
    try:
        # Let's try to provide more information on the failure
        devices = [i.split("\t") for i in subprocess.check_output([
            utils.find_executable('dmsetup'), "ls"]).splitlines()]
        dev_id = [i[1].strip("()").split(":") for i in devices if
                  lv.split("/").pop() in i[0] and
                  not i[0].endswith("cow")][0]
        command = "{} | grep {},{}".format(
            # lsof is quite long, so no need to add a sleep here
            utils.find_executable('lsof'), dev_id[0], dev_id[1])
        process = subprocess.check_output([command], shell=True)
        LOG.warning("Process holding the volume is '{}'".format(process))
    except Exception as e:
        LOG.warning("Could not get informations on the process holding the"
                    " volume: {}".format(str(e)))
예제 #9
0
파일: lvm.py 프로젝트: openstack/freezer
def _umount(path):
    # Change dir if we are within the mount point to be removed.
    if os.getcwd().startswith(os.path.normpath(path)):
        os.chdir('/')
    umount_proc = subprocess.Popen('{0} -l -f {1}'.format(
        utils.find_executable('umount'), path),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        shell=True, executable=utils.find_executable('bash'))
    (umount_out, mount_err) = umount_proc.communicate()

    if umount_proc.returncode:
        raise Exception('Impossible to umount {0}. {1}'
                        .format(path, mount_err))
    os.rmdir(path)
    LOG.info('Volume {0} unmounted'.format(path))
예제 #10
0
파일: lvm.py 프로젝트: paperandsoap/freezer
def _umount(path):
    # TODO: check if cwd==path and change working directory to unmount ?
    umount_proc = subprocess.Popen('{0} -l -f {1}'.format(
        utils.find_executable('umount'), path),
                                   stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   shell=True,
                                   executable=utils.find_executable('bash'))
    (umount_out, mount_err) = umount_proc.communicate()

    if umount_proc.returncode:
        raise Exception('impossible to umount {0}. {1}'.format(
            path, mount_err))

    logging.info('[*] Volume {0} unmounted'.format(path))
예제 #11
0
def _lvremove(lv):
    for attempt in range(5):
        lvremove_proc = subprocess.Popen(
            '{0} -f {1}'.format(utils.find_executable('lvremove'), lv),
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE, shell=True,
            executable=utils.find_executable('bash'))
        output, error = lvremove_proc.communicate()
        if lvremove_proc.returncode:
            if "contains a filesystem in use" in error:
                LOG.warning("Couldn't remove volume {0}. "
                            "It is still in use.".format(lv))
                log_volume_holding_process(lv)
            else:
                break
        else:
            return
    # Raise if five attempts made or different error than fs in use
    raise Exception('Unable to remove snapshot {0}. {1}'.format(lv, error))
예제 #12
0
파일: lvm.py 프로젝트: openstack/freezer
def _lvremove(lv):
    for attempt in range(5):
        lvremove_proc = subprocess.Popen(
            '{0} -f {1}'.format(utils.find_executable('lvremove'), lv),
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE, shell=True,
            executable=utils.find_executable('bash'))
        output, error = lvremove_proc.communicate()
        if lvremove_proc.returncode:
            if "contains a filesystem in use" in error:
                LOG.warning("Couldn't remove volume {0}. "
                            "It is still in use.".format(lv))
                log_volume_holding_process(lv)
            else:
                break
        else:
            return
    # Raise if five attempts made or different error than fs in use
    raise Exception('Unable to remove snapshot {0}. {1}'.format(lv, error))
예제 #13
0
def lvm_snap(backup_opt_dict):
    """
    Checks the provided parameters and create the lvm snapshot if requested

    The path_to_backup might be adjusted in case the user requested
    a lvm snapshot without specifying an exact path for the snapshot).
    The assumption in this case is that the user wants to use the lvm snapshot
    capability to backup the specified filesystem path, leaving out all
    the rest of the parameters which will guessed and set by freezer.

    :param backup_opt_dict: the configuration dict
    :return: True if the snapshot has been taken, False otherwise
    """
    lvm_uuid = uuidutils.generate_uuid(dashed=False)

    if not backup_opt_dict.lvm_snapname:
        backup_opt_dict.lvm_snapname = \
            "{0}_{1}".format(freezer_config.DEFAULT_LVM_SNAP_BASENAME,
                             lvm_uuid)

    # adjust/check lvm parameters according to provided path_to_backup
    lvm_info = get_lvm_info(backup_opt_dict.path_to_backup)

    if not backup_opt_dict.lvm_volgroup:
        backup_opt_dict.lvm_volgroup = lvm_info['volgroup']

    if not backup_opt_dict.lvm_srcvol:
        backup_opt_dict.lvm_srcvol = lvm_info['srcvol']

    if not backup_opt_dict.lvm_dirmount:
        utils.create_dir(freezer_config.DEFAULT_LVM_MOUNT_BASEDIR)
        backup_opt_dict.lvm_dirmount = \
            "{0}/mount_{1}".format(freezer_config.DEFAULT_LVM_MOUNT_BASEDIR,
                                   lvm_uuid)

    backup_opt_dict.path_to_backup = os.path.join(backup_opt_dict.lvm_dirmount,
                                                  lvm_info['snap_path'])

    if not validate_lvm_params(backup_opt_dict):
        LOG.info('No LVM requested/configured')
        return False

    utils.create_dir(backup_opt_dict.lvm_dirmount)

    if '%' in backup_opt_dict.lvm_snapsize:
        lvm_size_option = "--extents"
    else:
        lvm_size_option = "--size"

    lvm_create_command = (
        '{0} {1} {2} --snapshot --permission {3} '
        '--name {4} {5}'.format(
            utils.find_executable('lvcreate'),
            lvm_size_option,
            backup_opt_dict.lvm_snapsize,
            ('r' if backup_opt_dict.lvm_snapperm == 'ro'
             else backup_opt_dict.lvm_snapperm),
            backup_opt_dict.lvm_snapname,
            backup_opt_dict.lvm_srcvol))

    lvm_process = subprocess.Popen(
        lvm_create_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    (lvm_out, lvm_err) = lvm_process.communicate()

    if lvm_process.returncode:
        raise Exception('lvm snapshot creation error: {0}'.format(lvm_err))

    LOG.debug('{0}'.format(lvm_out))
    LOG.warning('Logical volume "{0}" created'.
                format(backup_opt_dict.lvm_snapname))

    # Guess the file system of the provided source volume and st mount
    # options accordingly
    filesys_type = get_vol_fs_type(backup_opt_dict.lvm_srcvol)
    mount_options = '-o {}'.format(backup_opt_dict.lvm_snapperm)
    if 'xfs' == filesys_type:
        mount_options = ' -onouuid '
    # Mount the newly created snapshot to dir_mount
    abs_snap_name = '/dev/{0}/{1}'.format(
        backup_opt_dict.lvm_volgroup,
        backup_opt_dict.lvm_snapname)
    mount_command = '{0} {1} {2} {3}'.format(
        utils.find_executable('mount'),
        mount_options,
        abs_snap_name,
        backup_opt_dict.lvm_dirmount)
    mount_process = subprocess.Popen(
        mount_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    mount_err = mount_process.communicate()[1]
    if 'already mounted' in mount_err:
        LOG.warning('Volume {0} already mounted on {1}\
        '.format(abs_snap_name, backup_opt_dict.lvm_dirmount))
        return True
    if mount_err:
        LOG.error("Snapshot mount error. Removing snapshot")
        lvm_snap_remove(backup_opt_dict)
        raise Exception('lvm snapshot mounting error: {0}'.format(mount_err))
    else:
        LOG.warning(
            'Volume {0} successfully mounted on {1}'.format(
                abs_snap_name, backup_opt_dict.lvm_dirmount))

    return True
예제 #14
0
파일: lvm.py 프로젝트: openstack/freezer
def lvm_snap(backup_opt_dict):
    """
    Checks the provided parameters and create the lvm snapshot if requested

    The path_to_backup might be adjusted in case the user requested
    a lvm snapshot without specifying an exact path for the snapshot).
    The assumption in this case is that the user wants to use the lvm snapshot
    capability to backup the specified filesystem path, leaving out all
    the rest of the parameters which will guessed and set by freezer.

    :param backup_opt_dict: the configuration dict
    :return: True if the snapshot has been taken, False otherwise
    """
    lvm_uuid = uuidutils.generate_uuid(dashed=False)

    if not backup_opt_dict.lvm_snapname:
        backup_opt_dict.lvm_snapname = \
            "{0}_{1}".format(freezer_config.DEFAULT_LVM_SNAP_BASENAME,
                             lvm_uuid)

    # adjust/check lvm parameters according to provided path_to_backup
    lvm_info = get_lvm_info(backup_opt_dict.path_to_backup)

    if not backup_opt_dict.lvm_volgroup:
        backup_opt_dict.lvm_volgroup = lvm_info['volgroup']

    if not backup_opt_dict.lvm_srcvol:
        backup_opt_dict.lvm_srcvol = lvm_info['srcvol']

    if not backup_opt_dict.lvm_dirmount:
        utils.create_dir(freezer_config.DEFAULT_LVM_MOUNT_BASEDIR)
        backup_opt_dict.lvm_dirmount = \
            "{0}/mount_{1}".format(freezer_config.DEFAULT_LVM_MOUNT_BASEDIR,
                                   lvm_uuid)

    if not validate_lvm_params(backup_opt_dict):
        LOG.info('No LVM requested/configured')
        return False

    utils.create_dir(backup_opt_dict.lvm_dirmount)

    if '%' in backup_opt_dict.lvm_snapsize:
        lvm_size_option = "--extents"
    else:
        lvm_size_option = "--size"

    lvm_create_command = (
        '{0} {1} {2} --snapshot --permission {3} '
        '--name {4} {5}'.format(
            utils.find_executable('lvcreate'),
            lvm_size_option,
            backup_opt_dict.lvm_snapsize,
            ('r' if backup_opt_dict.lvm_snapperm == 'ro'
             else backup_opt_dict.lvm_snapperm),
            backup_opt_dict.lvm_snapname,
            backup_opt_dict.lvm_srcvol))

    lvm_process = subprocess.Popen(
        lvm_create_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    (lvm_out, lvm_err) = lvm_process.communicate()

    if lvm_process.returncode:
        raise Exception('lvm snapshot creation error: {0}'.format(lvm_err))

    LOG.debug('{0}'.format(lvm_out))
    LOG.warning('Logical volume "{0}" created'.
                format(backup_opt_dict.lvm_snapname))

    # Guess the file system of the provided source volume and st mount
    # options accordingly
    filesys_type = get_vol_fs_type(backup_opt_dict.lvm_srcvol)
    mount_options = '-o {}'.format(backup_opt_dict.lvm_snapperm)
    if 'xfs' == filesys_type:
        mount_options = ' -onouuid '
    # Mount the newly created snapshot to dir_mount
    abs_snap_name = '/dev/{0}/{1}'.format(
        backup_opt_dict.lvm_volgroup,
        backup_opt_dict.lvm_snapname)
    mount_command = '{0} {1} {2} {3}'.format(
        utils.find_executable('mount'),
        mount_options,
        abs_snap_name,
        backup_opt_dict.lvm_dirmount)
    mount_process = subprocess.Popen(
        mount_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    mount_err = mount_process.communicate()[1]
    if 'already mounted' in mount_err:
        LOG.warning('Volume {0} already mounted on {1}\
        '.format(abs_snap_name, backup_opt_dict.lvm_dirmount))
        return True
    if mount_err:
        LOG.error("Snapshot mount error. Removing snapshot")
        lvm_snap_remove(backup_opt_dict)
        raise Exception('lvm snapshot mounting error: {0}'.format(mount_err))
    else:
        LOG.warning(
            'Volume {0} successfully mounted on {1}'.format(
                abs_snap_name, backup_opt_dict.lvm_dirmount))

    # After snapshot is mounted, adjust path_to_backup according the mount
    # point and relative path of the snapshot volume.
    lvm_info = get_lvm_info(backup_opt_dict.path_to_backup)
    backup_opt_dict.path_to_backup = os.path.join(backup_opt_dict.lvm_dirmount,
                                                  lvm_info['snap_path'])

    return True
예제 #15
0
파일: lvm.py 프로젝트: gongwayne/Openstack
def lvm_snap(backup_opt_dict):
    """
    Checks the provided parameters and create the lvm snapshot if requested

    The path_to_backup might be adjusted in case the user requested
    a lvm snapshot without specifying an exact path for the snapshot
    (lvm_auto_snap).
    The assumption in this case is that the user wants to use the lvm snapshot
    capability to backup the specified filesystem path, leaving out all
    the rest of the parameters which will guessed and set by freezer.

    if a snapshot is requested using the --snapshot flag, but lvm_auto_snap
    is not provided, then path_to_backup is supposed to be the path to backup
    *before* any information about the snapshot is added and will be
    adjusted.

    :param backup_opt_dict: the configuration dict
    :return: True if the snapshot has been taken, False otherwise
    """
    if backup_opt_dict.snapshot:
        if not backup_opt_dict.lvm_auto_snap:
            # 1) the provided path_to_backup has the meaning of
            #    the lvm_auto_snap and is therefore copied into it
            # 2) the correct value of path_to_backup, which takes into
            #    consideration the snapshot mount-point, is cleared
            #    and will be calculated by freezer
            backup_opt_dict.lvm_auto_snap =\
                backup_opt_dict.path_to_backup
            backup_opt_dict.path_to_backup = ''

    if not backup_opt_dict.lvm_snapname:
        backup_opt_dict.lvm_snapname = \
            "{0}_{1}".format(freezer_config.DEFAULT_LVM_SNAP_BASENAME,
                             uuid.uuid4().hex)

    if backup_opt_dict.lvm_auto_snap:
        # adjust/check lvm parameters according to provided lvm_auto_snap
        lvm_info = get_lvm_info(backup_opt_dict.lvm_auto_snap)

        if not backup_opt_dict.lvm_volgroup:
            backup_opt_dict.lvm_volgroup = lvm_info['volgroup']

        if not backup_opt_dict.lvm_srcvol:
            backup_opt_dict.lvm_srcvol = lvm_info['srcvol']

        if not backup_opt_dict.lvm_dirmount:
            backup_opt_dict.lvm_dirmount = \
                "{0}_{1}".format(freezer_config.DEFAULT_LVM_MOUNT_BASENAME,
                                 uuid.uuid4().hex)

        path_to_backup = os.path.join(backup_opt_dict.lvm_dirmount,
                                      lvm_info['snap_path'])
        if backup_opt_dict.path_to_backup:
            # path_to_backup is user-provided, check if consistent
            if backup_opt_dict.path_to_backup != path_to_backup:
                raise Exception('Path to backup mismatch. '
                                'provided: {0}, should be LVM-mounted: {1}'.
                                format(backup_opt_dict.path_to_backup,
                                       path_to_backup))
        else:
            # path_to_backup not provided: use the one calculated above
            backup_opt_dict.path_to_backup = path_to_backup

    if not validate_lvm_params(backup_opt_dict):
        logging.info('[*] No LVM requested/configured')
        return False

    utils.create_dir(backup_opt_dict.lvm_dirmount)

    lvm_create_command = (
        '{0} --size {1} --snapshot --permission {2} '
        '--name {3} {4}'.format(
            utils.find_executable('lvcreate'),
            backup_opt_dict.lvm_snapsize,
            ('r' if backup_opt_dict.lvm_snapperm == 'ro'
             else backup_opt_dict.lvm_snapperm),
            backup_opt_dict.lvm_snapname,
            backup_opt_dict.lvm_srcvol))

    lvm_process = subprocess.Popen(
        lvm_create_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    (lvm_out, lvm_err) = lvm_process.communicate()

    if lvm_process.returncode:
        raise Exception('lvm snapshot creation error: {0}'.format(lvm_err))

    logging.debug('[*] {0}'.format(lvm_out))
    logging.warning('[*] Logical volume "{0}" created'.
                    format(backup_opt_dict.lvm_snapname))

    # Guess the file system of the provided source volume and st mount
    # options accordingly
    filesys_type = get_vol_fs_type(backup_opt_dict.lvm_srcvol)
    mount_options = '-o {}'.format(backup_opt_dict.lvm_snapperm)
    if 'xfs' == filesys_type:
        mount_options = ' -onouuid '
    # Mount the newly created snapshot to dir_mount
    abs_snap_name = '/dev/{0}/{1}'.format(
        backup_opt_dict.lvm_volgroup,
        backup_opt_dict.lvm_snapname)
    mount_command = '{0} {1} {2} {3}'.format(
        utils.find_executable('mount'),
        mount_options,
        abs_snap_name,
        backup_opt_dict.lvm_dirmount)
    mount_process = subprocess.Popen(
        mount_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=utils.find_executable('bash'))
    mount_err = mount_process.communicate()[1]
    if 'already mounted' in mount_err:
        logging.warning('[*] Volume {0} already mounted on {1}\
        '.format(abs_snap_name, backup_opt_dict.lvm_dirmount))
        return True
    if mount_err:
        logging.error("[*] Snapshot mount error. Removing snapshot")
        lvm_snap_remove(backup_opt_dict)
        raise Exception('lvm snapshot mounting error: {0}'.format(mount_err))
    else:
        logging.warning(
            '[*] Volume {0} succesfully mounted on {1}'.format(
                abs_snap_name, backup_opt_dict.lvm_dirmount))

    return True