Esempio n. 1
0
def backup_guard_recurse(pool, class_nr):
    """Recurse version tower of hanoi backup rotation scheme for ZFS:
    http://en.wikipedia.org/wiki/Backup_rotation_scheme#Tower_of_Hanoi
    Snapshots are taken atomically, so that all recursive snapshots corre-
    spond to the same moment in time.

    :param fs: zpool name to backup (snapshot make also for all child zfs)
    :type fs: str
    :param class_nr: number of class used for rotation
    :type class_nr: int
    :raises: zfswrapper.ZfsException
    """
    # tag for new snapshot
    snp_tag = _gen_snapshot_tag()
    unknown_label = 'unknown'
    unknown_control_nr = 'X'

    # make new recursive snapshot - if problem ZfsException is throw
    zfs.zfs_snapshot(fs=pool, tag=snp_tag, recurse=True, 
            properties={_backup_property:unknown_label, _backup_control_nr:unknown_control_nr})
    # get all filesystem given pool
    all_fs = zfs.zfs_list(fs=pool, types='filesystem') or []
    for fs in all_fs:
        print 'fs', fs
        ## Note: you can set class_num per filesystem, exclude some zfs filesystems, e.g. pool
        # get all snapshots given fs
        fs_snapshots = zfs.zfs_list(fs=fs, types='snapshot') or []
        # get list of snapshots and properties sorted by creation time. First is allready taken snapshot.
        srt_snapshots = _get_current_hanoi_state(fs, fs_snapshots)[1:]
        # get control number - useful for debuging and checking hanoi rotation scheme
        _hanoi_builder(fs, snp_tag, class_nr, srt_snapshots, recurse=True)
Esempio n. 2
0
def _hanoi_builder(fs, tag, class_nr, srt_snapshots, recurse=False):
    """Help function, take care for hanoi status
    
    :raises: zfswrapper.ZfsException
    """
    class_list = _get_class_list(class_nr) #e.g. ['A', 'B', 'C', 'D', 'E']
    modulov = 2**(class_nr-1) #useful to create control number
    next_control_nr = _get_next_control_number(srt_snapshots, modulov)

    for ptr in range(0, class_nr):
        # last must be replaced anyway;  snapshot has proper class
        last_class = (ptr == class_nr-1)
        has_proper_class = False
        if len(srt_snapshots) > ptr:
            has_proper_class = (srt_snapshots[ptr][_backup_property] == class_list[ptr])
        if not last_class and has_proper_class:
            continue
        else:
            # Hanoi rotation method has the drawback of overwriting
            # the very first backup (day 1 of the cycle) after only two days. 
            # However, this can easily be overcome by starting 
            # on the last day of a cycle.
            class_label = class_list[ptr]
            if not srt_snapshots:
                class_label = class_list[-1]

            # get all old snapshots same class
            old_snapshot = filter(lambda x: x[_backup_property]==class_label, srt_snapshots)

            print "to create: {'%s': '%s', '%s': '%s'}" % (_backup_property, class_label, _backup_control_nr, next_control_nr)
            if recurse:
                snp_already_taken = '%s@%s' % (fs, tag)
                # mark already taken snapshot with proper class and control_nr - if problem ZfsException is throw
                zfs.zfs_set(snp_already_taken, _backup_control_nr, next_control_nr)
                zfs.zfs_set(snp_already_taken, _backup_property, class_label)
            else:
                # make new snapshot - if problem ZfsException is throw
                zfs.zfs_snapshot(fs, tag, properties={_backup_property:class_label, _backup_control_nr:next_control_nr})
            # delete old snapshots same class, only if new snapshot was taken - if probelm ZfsException is throw
            for old in old_snapshot:
                print 'to destroy:', old
                zfs.zfs_destroy(old['name'])
            # job done
            break
Esempio n. 3
0
def replication_simulator():
    """Demo - send and receive snapshot.
    
    .. warning::
        recv_fs can't exist on recv_host, otherwise error is risen
    """

    send_fs = "galaxy01/fleet11"
    send_tag = "satellite-red01"
    to_send = "%s@%s" % (send_fs, send_tag)

    # create local snapshot to teleport if not exist
    if not zfs.zfs_list(fs=to_send):
        zfs.zfs_snapshot(send_fs, send_tag)

    # Remote repl. - using ssh
    recv_fs = "galaxy_slave01/fleet11_alfa"
    # recv_fs = 'galaxy_slave01/fleet11_beta'
    zfs.zfs_teleport_snapshot(to_send, recv_fs, recv_host="zepto")

    # Local repl.
    recv_fs = "galaxy02/fleet11_alfa"
    # recv_fs = 'galaxy02/fleet11_beta'
    zfs.zfs_teleport_snapshot(to_send, recv_fs)