def test_get_vol_fs_type(self, monkeypatch):
        pytest.raises(Exception, utils.get_vol_fs_type, "test")

        fakeos = Os()
        monkeypatch.setattr(os.path, 'exists', fakeos.exists)
        #fakesubprocess = FakeSubProcess()
        pytest.raises(Exception, utils.get_vol_fs_type, "test")

        fakere = FakeRe()
        monkeypatch.setattr(re, 'search', fakere.search)
        assert type(utils.get_vol_fs_type("test")) is str
Exemple #2
0
    def test_get_vol_fs_type(self, monkeypatch):

        backup_opt = BackupOpt1()
        pytest.raises(Exception, get_vol_fs_type, backup_opt)

        fakeos = Os()
        monkeypatch.setattr(os.path, 'exists', fakeos.exists)
        #fakesubprocess = FakeSubProcess()
        pytest.raises(Exception, get_vol_fs_type, backup_opt)

        fakere = FakeRe()
        monkeypatch.setattr(re, 'search', fakere.search)
        assert type(get_vol_fs_type(backup_opt)) is str
Exemple #3
0
def lvm_snap(backup_opt_dict):
    """
    Implement checks on lvm volumes availability. According to these checks
    we might create an lvm snapshot and mount it or use an existing one
    """
    if lvm_eval(backup_opt_dict) is not True:
        return True
    # Setting lvm snapsize to 5G is not set
    if backup_opt_dict.lvm_snapsize is False:
        backup_opt_dict.lvm_snapsize = '5G'
        logging.warning('[*] lvm_snapsize not configured. Setting the \
        lvm snapshot size to 5G')

    # Setting lvm snapshot name to freezer_backup_snap it not set
    if backup_opt_dict.lvm_snapname is False:
        backup_opt_dict.lvm_snapname = 'freezer_backup_snap'
        logging.warning('[*] lvm_snapname not configured. Setting default \
        name "freezer_backup_snap" for the lvm backup snap session')

    logging.info('[*] Source LVM Volume: {0}'.format(
        backup_opt_dict.lvm_srcvol))
    logging.info('[*] LVM Volume Group: {0}'.format(
        backup_opt_dict.lvm_volgroup))
    logging.info('[*] Snapshot name: {0}'.format(
        backup_opt_dict.lvm_snapname))
    logging.info('[*] Snapshot size: {0}'.format(
        backup_opt_dict.lvm_snapsize))
    logging.info('[*] Directory where the lvm snaphost will be mounted on:\
        {0}'.format(backup_opt_dict.lvm_dirmount.strip()))

    if backup_opt_dict.lvm_snapperm not in ('ro', 'rw'):
        raise ValueError('[*] Error: Please set a valid mount option\
               for lvm snapshot: {}'.format(backup_opt_dict.lvm_snapperm))
    # Create the snapshot according the values passed from command line
    lvm_create_snap = '{0} --size {1} --snapshot --permission {2} --name {3} {4}\
    '.format(
        backup_opt_dict.lvcreate_path,
        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)

    # If backup mode is mysql, then the db will be flushed and read locked
    # before the creation of the lvm snap
    if backup_opt_dict.mode == 'mysql':
        cursor = backup_opt_dict.mysql_db_inst.cursor()
        cursor.execute('FLUSH TABLES WITH READ LOCK')
        backup_opt_dict.mysql_db_inst.commit()

    lvm_process = subprocess.Popen(
        lvm_create_snap, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=backup_opt_dict.bash_path)
    (lvm_out, lvm_err) = lvm_process.communicate()
    if lvm_err is False:
        raise Exception('lvm snapshot creation error: {0}'.format(lvm_err))
    else:
        logging.warning('[*] {0}'.format(lvm_out))

    # Unlock MySQL Tables if backup is == mysql
    if backup_opt_dict.mode == 'mysql':
        cursor.execute('UNLOCK TABLES')
        backup_opt_dict.mysql_db_inst.commit()
        cursor.close()
        backup_opt_dict.mysql_db_inst.close()

    # Guess the file system of the provided source volume and st mount
    # options accordingly
    filesys_type = get_vol_fs_type(backup_opt_dict)
    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_snap = '{0} {1} {2} {3}'.format(
        backup_opt_dict.mount_path,
        mount_options,
        abs_snap_name,
        backup_opt_dict.lvm_dirmount)
    mount_process = subprocess.Popen(
        mount_snap, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=backup_opt_dict.bash_path)
    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:
        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
Exemple #4
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
    (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 = utils.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
Exemple #5
0
def lvm_snap(backup_opt_dict):
    """
    Implement checks on lvm volumes availability. According to these checks
    we might create an lvm snapshot and mount it or use an existing one
    """

    if lvm_eval(backup_opt_dict) is not True:
        return True
    # Setting lvm snapsize to 5G is not set
    if backup_opt_dict.lvm_snapsize is False:
        backup_opt_dict.lvm_snapsize = '5G'
        logging.warning('[*] lvm_snapsize not configured. Setting the \
        lvm snapshot size to 5G')

    # Setting lvm snapshot name to freezer_backup_snap it not set
    if backup_opt_dict.lvm_snapname is False:
        backup_opt_dict.lvm_snapname = 'freezer_backup_snap'
        logging.warning('[*] lvm_snapname not configured. Setting default \
        name "freezer_backup_snap" for the lvm backup snap session')

    logging.info('[*] Source LVM Volume: {0}'.format(
        backup_opt_dict.lvm_srcvol))
    logging.info('[*] LVM Volume Group: {0}'.format(
        backup_opt_dict.lvm_volgroup))
    logging.info('[*] Snapshot name: {0}'.format(
        backup_opt_dict.lvm_snapname))
    logging.info('[*] Snapshot size: {0}'.format(
        backup_opt_dict.lvm_snapsize))
    logging.info('[*] Directory where the lvm snaphost will be mounted on:\
        {0}'.format(backup_opt_dict.lvm_dirmount.strip()))

    # Create the snapshot according the values passed from command line
    lvm_create_snap = '{0} --size {1} --snapshot --name {2} {3}\
    '.format(
        backup_opt_dict.lvcreate_path,
        backup_opt_dict.lvm_snapsize,
        backup_opt_dict.lvm_snapname,
        backup_opt_dict.lvm_srcvol)

    # If backup mode is mysql, then the db will be flushed and read locked
    # before the creation of the lvm snap
    if backup_opt_dict.mode == 'mysql':
        cursor = backup_opt_dict.mysql_db_inst.cursor()
        cursor.execute('FLUSH TABLES WITH READ LOCK')
        backup_opt_dict.mysql_db_inst.commit()

    lvm_process = subprocess.Popen(
        lvm_create_snap, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=backup_opt_dict.bash_path)
    (lvm_out, lvm_err) = lvm_process.communicate()
    if lvm_err is False:
        raise Exception('lvm snapshot creation error: {0}'.format(lvm_err))
    else:
        logging.warning('[*] {0}'.format(lvm_out))

    # Unlock MySQL Tables if backup is == mysql
    if backup_opt_dict.mode == 'mysql':
        cursor.execute('UNLOCK TABLES')
        backup_opt_dict.mysql_db_inst.commit()
        cursor.close()
        backup_opt_dict.mysql_db_inst.close()

    # Guess the file system of the provided source volume and st mount
    # options accordingly
    filesys_type = get_vol_fs_type(backup_opt_dict)
    mount_options = ' '
    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_snap = '{0} {1} {2} {3}'.format(
        backup_opt_dict.mount_path,
        mount_options,
        abs_snap_name,
        backup_opt_dict.lvm_dirmount)
    mount_process = subprocess.Popen(
        mount_snap, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, shell=True,
        executable=backup_opt_dict.bash_path)
    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:
        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