Beispiel #1
0
class LFSZFS(LFS):
    def __init__(self, conf, srvdir):
        LFS.__init__(self, conf, srvdir)
        self.fs = "zfs"
        self.topfs = conf.get('topfs')
        self.check_interval = int(conf.get('check_interval', '30'))
        mkdirs(self.root)
        devs = ring.Ring(os.path.join(conf.get('swift_dir', '/etc/swift'),
            'object.ring.gz')).get_devs()
        my_ips = whataremyips()

        # pools is a list of tuple => (<pool name>, <pool mirrorr_count>)
        self.pools = \
                [ (dev['device'], dev['mirror_copies']) for dev in devs \
                if dev['ip'] in my_ips]

        # Create the Top level ZFS.
        for pool, mr_count in self.pools:
            zfs_create(pool, self.topfs, '%s/%s' %(self.root, pool))

        self.degraded_pools = []
        self.faulted_pools = []
        self.misconfigured_pools = []
        if not self.topfs:
            sys.stderr.write(
                "Cannot locate ZFS filesystem for the Server. Exiting..\n")
            sys.exit(1)

        self.fs_per_part = False
        self.fs_per_obj = False
        if self.conf.get('fs_per_obj', 'false') == 'true':
            self.fs_per_part = True
            self.fs_per_obj = True
        elif self.conf.get('fs_per_part', 'false') == 'true': 
            self.fs_per_part = True

        self.status_checker = LFSStatus(self.check_interval,
                self.check_pools, ())
        self.status_checker.start()

    def check_pools(self, args):
        need_cb = False

        for pool, mr_count in self.pools:
            pool_config = nspyzfs.zpool_status(pool)[0]

            if pool_config.get_mirrorcount() > mr_count:
                # TODO: Actual corrective and recovery measures needs to
                # be implemented.
                self.misconfigured_pools.append(pool)
            else:
                if pool in self.misconfigured_pools:
                    self.misconfigured_pools.remove(pool)

            ret = pool_config.get_state()
            if ret == nspyzfs.ZPOOL_STATE_DEGRADED:
                if not pool in self.degraded_pools:
                    self.degraded_pools.append(pool)
                    need_cb = True
            elif ret == nspyzfs.ZPOOL_STATE_FAULTED:
                if not pool in self.faulted_pools:
                    self.faulted_pools.append(pool)
                    need_cb = True
            elif ret == nspyzfs.ZPOOL_STATE_UNKNOWN:
                    need_cb = True
                    # TODO: Need to handle ZPOOL_UNKNOWN state.
            else:
                if pool in self.faulted_pools:
                    self.faulted_pools.remove(pool)
                elif pool in self.degraded_pools:
                    self.degraded_pools.remove(pool)

        if need_cb:
            return (self.zfs_error_callback, ())

        return None 

    def zfs_error_callback(self, args):
        # TODO: Let Object server know about this situation
        # so that object server can take recovery actions.
        # This function can be worked upon only after recovery
        # semantics for object server is designed and implemented

        print "DEGARDED pools: %s" %degraded_pools
        print "FAULTED pools: %s" %faulted_pools

        # We will clear the faults, but maintain the faults
        # internally in degraded_pools and fault_pools.
        # THIS CODE WILL BE REPLACED BY recovery semantics 
        # to be implemented in object server.
        self.status_checker.clear_fault()


    def tmp_dir(self, pool, partition, name_hash):
        if self.fs_per_obj:
            return os.path.join(self.root, pool, 
                storage_directory(self.srvdir, partition, name_hash), 'tmp')
        elif self.fs_per_part:
            return os.path.join(self.root, pool, self.srvdir, partition, 'tmp')
        else:
            return os.path.join(self.root, pool, self.srvdir, 'tmp')

    def setup_partition(self, pool, partition):
        path = os.path.join(self.root, pool, self.srvdir, partition)
        if self.fs_per_part:
            fs = '%s/%s/%s' %(self.topfs, self.srvdir, partition)
            zfs_create(pool, fs, path)
        else:
            mkdirs(path)

    def setup_objdir(self, pool, partition, name_hash):
        path = os.path.join(self.root, pool, 
                storage_directory(self.srvdir, partition, name_hash))
        if not os.path.exists(path) and self.fs_per_obj:
            fs = '%s/%s/%s/%s' %(self.topfs, self.srvdir, partition, name_hash)
            zfs_create(pool, fs, path)