示例#1
0
def lvm_populate(device):
    """ Create vg and lv entries for devices with dm attributes """
    vg_name, vg_size, lv_name, lv_uuid, vg_uuid, lv_size, lv_mm, lv_slave_mms = \
        map(device.get,
            ('dm_vg', 'dm_vg_size', 'dm_lv', 'lv_uuid', 'vg_uuid', 'size', 'major_minor', 'dm_slave_mms'))

    vg = {
        'name': vg_name,
        'uuid': vg_uuid,
        'size': int(vg_size),
        'pvs_major_minor': []
    }

    [
        vg['pvs_major_minor'].append(mm) for mm in lv_slave_mms
        if mm not in vg['pvs_major_minor']
    ]

    # Do this to cache the device, type see blockdevice and filesystem for info.
    BlockDevice('lvm_volume', '/dev/mapper/%s-%s' % (vg_name, lv_name))

    lv = {
        'name': lv_name,
        'uuid': lv_uuid,
        'size': lv_size,
        'block_device': lv_mm
    }

    return vg, lv
示例#2
0
    def __init__(self, local_targets):
        super(MgsTargets, self).__init__()
        self.filesystems = {}

        mgs_target = None

        for t in local_targets:
            if t["name"] == "MGS" and t['mounted']:
                mgs_target = t

        if mgs_target:
            daemon_log.info("Searching Lustre logs for filesystems")

            block_device = BlockDevice(mgs_target["type"], mgs_target["device_paths"][0])

            self.filesystems = block_device.mgs_targets(daemon_log)
def _get_zpool_zvols(pool_name, drives, block_devices):
    """
    Each zfs pool may have zvol entries in it. This will parse those zvols and create
    device entries for them
    """
    zpool_vols = {}

    for zvol_path in glob.glob("/dev/%s/*" % pool_name):
        major_minor = block_devices.path_to_major_minor(zvol_path)

        if major_minor is None:
            continue

        uuid = zvol_path

        zpool_vols[uuid] = {
            "name": zvol_path,
            "path": zvol_path,
            "block_device": major_minor,
            "uuid": uuid,
            "size": block_devices.block_device_nodes[major_minor]["size"],
            "drives": drives
        }

        # Do this to cache the device, type see blockdevice and filesystem for info.
        BlockDevice('zfs', zvol_path)
        FileSystem('zfs', zvol_path)

    return zpool_vols
示例#4
0
    def __init__(self, target_devices):
        # Working set: accumulate device paths for each (uuid, name).  This is
        # necessary because in multipathed environments we will see the same
        # lustre target on more than one block device.  The reason we use name
        # as well as UUID is that two logical targets can have the same UUID
        # when we see a combined MGS+MDT
        uuid_name_to_target = {}

        for device in target_devices:
            block_device = BlockDevice(device["type"], device["path"])

            # If the target_device has no uuid then it doesn't have a filesystem and is of no use to use, but
            # for now let's fill it in an see what happens.
            if device['uuid'] == None:
                try:
                    device['uuid'] = block_device.uuid
                except AgentShell.CommandExecutionError:
                    pass

            # OK, so we really don't have a uuid for this, so we won't find a lustre filesystem on it.
            if device['uuid'] == None:
                daemon_log.info("Device %s had no UUID and so will not be examined for Lustre" % device['path'])
                continue

            targets = block_device.targets(uuid_name_to_target, device, daemon_log)

            ndp = get_normalized_device_table()

            mounted = ndp.normalized_device_path(device['path']) in set([ndp.normalized_device_path(path)
                                                                         for path, _, _ in get_local_mounts()])

            for name in targets.names:
                daemon_log.info("Device %s contained name:%s and is %smounted" % (device['path'], name, "" if mounted else "un"))

                try:
                    target_dict = uuid_name_to_target[(device['uuid'], name)]
                    target_dict['devices'].append(device)
                except KeyError:
                    target_dict = {"name": name,
                                   "uuid": device['uuid'],
                                   "params": targets.params,
                                   "device_paths": [device['path']],
                                   "mounted": mounted,
                                   'type': device['type']}
                    uuid_name_to_target[(device['uuid'], name)] = target_dict

        self.targets = uuid_name_to_target.values()
示例#5
0
    def _scan_mounts(self):
        mounts = {}

        for device, mntpnt, fstype in Mounts().all():
            if fstype != 'lustre':
                continue

            # Assume that while a filesystem is mounted, its UUID and LABEL don't change.
            # Therefore we can avoid repeated blkid calls with a little caching.
            if device in self._mount_cache:
                fs_uuid = self._mount_cache[device]['fs_uuid']
                fs_label = self._mount_cache[device]['fs_label']
            else:
                # Sending none as the type means BlockDevice will use it's local cache to work the type.
                # This is not a good method, and we should work on a way of not storing such state but for the
                # present it is the best we have.
                try:
                    fs_uuid = BlockDevice(None, device).uuid
                    fs_label = FileSystem(None, device).label

                    # If we have scanned the devices then it is safe to cache the values.
                    if LinuxDevicePlugin.devices_scanned:
                        self._mount_cache[device]['fs_uuid'] = fs_uuid
                        self._mount_cache[device]['fs_label'] = fs_label
                except AgentShell.CommandExecutionError:
                    continue

            dev_normalized = ndp.normalized_device_path(device)

            recovery_status = {}
            try:
                recovery_file = glob.glob(
                    "/proc/fs/lustre/*/%s/recovery_status" % fs_label)[0]
                recovery_status_text = open(recovery_file).read()
                for line in recovery_status_text.split("\n"):
                    tokens = line.split(":")
                    if len(tokens) != 2:
                        continue
                    k = tokens[0].strip()
                    v = tokens[1].strip()
                    recovery_status[k] = v
            except IndexError:
                # If the recovery_status file doesn't exist,
                # we will return an empty dict for recovery info
                pass

            mounts[device] = {
                'device': dev_normalized,
                'fs_uuid': fs_uuid,
                'mount_point': mntpnt,
                'recovery_status': recovery_status
            }

        # Drop cached info about anything that is no longer mounted
        for k in self._mount_cache.keys():
            if not k in mounts:
                del self._mount_cache[k]

        return mounts.values()
示例#6
0
def export_target(device_type, path):
    """
    Passed a device type and a path export the device if such an operation make sense. For example a jbod scsi
    disk does not have the concept of export whilst zfs does.
    :param path: path of device to export
    :param device_type: the type of device to export
    :return: None or an Error message
    """

    blockdevice = BlockDevice(device_type, path)

    error = blockdevice.export()

    if error:
        console_log.error("Error exporting pool: '%s'" % error)

    return agent_ok_or_error(error)
示例#7
0
def check_block_device(path, device_type):
    """
    Precursor to formatting a device: check if there is already a filesystem on it.

    :param path: Path to a block device
    :param device_type: The type of device the path references
    :return The filesystem type of the filesystem on the device, or None if unoccupied.
    """
    return agent_ok_or_error(BlockDevice(device_type, path).filesystem_info)
示例#8
0
    def _update_pool_or_datasets(self, block_devices, pool, datasets, zvols):
        if (datasets == {}) and (zvols == {}):
            name = pool['name']
            block_devices.block_device_nodes[pool['block_device']] = {
                'major_minor': pool['block_device'],
                'path': name,
                'paths': [name],
                'serial_80': None,
                'serial_83': None,
                'size': pool['size'],
                'filesystem_type': None,
                'parent': None
            }

            # Do this to cache the device, type see blockdevice and filesystem for info.
            BlockDevice('zfs', name)
            FileSystem('zfs', name)

            self._zpools[pool['uuid']] = pool

        if datasets != {}:
            for info in datasets.itervalues():
                major_minor = info['block_device']
                name = info['name']
                block_devices.block_device_nodes[major_minor] = {
                    'major_minor': major_minor,
                    'path': name,
                    'paths': [name],
                    'serial_80': None,
                    'serial_83': None,
                    'size': info['size'],
                    'filesystem_type': 'zfs',
                    'parent': None
                }

                # Do this to cache the device, type see blockdevice and filesystem for info.
                BlockDevice('zfs', name)
                FileSystem('zfs', name)

            self._datasets.update(datasets)

        if zvols != {}:
            self._zvols.update(zvols)
示例#9
0
def import_target(device_type, path, pacemaker_ha_operation):
    """
    Passed a device type and a path import the device if such an operation make sense. For example a jbod scsi
    disk does not have the concept of import whilst zfs does.
    :param device_type: the type of device to import
    :param path: path of device to import
    :param pacemaker_ha_operation: This import is at the request of pacemaker. In HA operations the device may
               often have not have been cleanly exported because the previous mounted node failed in operation.
    :return: None or an Error message
    """
    blockdevice = BlockDevice(device_type, path)

    error = blockdevice.import_(False)
    if error:
        if '-f' in error and pacemaker_ha_operation:
            error = blockdevice.import_(True)

    if error:
        console_log.error("Error importing pool: '%s'" % error)

    return agent_ok_or_error(error)
示例#10
0
    def _add_zfs_pool(self, line, block_devices):
        pool, size_str, uuid, health = line.split()

        if health in self.acceptable_health:
            size = util.human_to_bytes(size_str)

            drive_mms = block_devices.paths_to_major_minors(
                self._get_all_zpool_devices(pool))

            if drive_mms is None:
                daemon_log.warn("Could not find major minors for zpool '%s'" %
                                pool)
                return

            # This will need discussion, but for now fabricate a major:minor. Do we ever use them as numbers?
            block_device = "zfspool:%s" % pool

            datasets = self._get_zpool_datasets(pool, uuid, drive_mms,
                                                block_devices)
            zvols = self._get_zpool_zvols(pool, drive_mms, uuid, block_devices)

            if (datasets == {}) and (zvols == {}):
                block_devices.block_device_nodes[block_device] = {
                    'major_minor': block_device,
                    'path': pool,
                    'serial_80': None,
                    'serial_83': None,
                    'size': size,
                    'filesystem_type': None,
                    'parent': None
                }

                # Do this to cache the device, type see blockdevice and filesystem for info.
                BlockDevice('zfs', pool)
                FileSystem('zfs', pool)

                self._zpools[uuid] = {
                    "name": pool,
                    "path": pool,
                    "block_device": block_device,
                    "uuid": uuid,
                    "size": size,
                    "drives": drive_mms,
                }

            if datasets != {}:
                self._datasets.update(datasets)

            if zvols != {}:
                self._zvols.update(zvols)
示例#11
0
    def _get_zpool_datasets(self, pool_name, zpool_uuid, drives,
                            block_devices):
        out = AgentShell.try_run(
            ['zfs', 'list', '-H', '-o', 'name,avail,guid'])

        zpool_datasets = {}

        if out.strip() != "no datasets available":
            for line in filter(None, out.split('\n')):
                name, size_str, uuid = line.split()
                size = util.human_to_bytes(size_str)

                if name.startswith("%s/" % pool_name):
                    # This will need discussion, but for now fabricate a major:minor. Do we ever use them as numbers?
                    major_minor = "zfsset:%s" % (len(self.datasets) + 1)
                    block_devices.block_device_nodes[major_minor] = {
                        'major_minor': major_minor,
                        'path': name,
                        'serial_80': None,
                        'serial_83': None,
                        'size': size,
                        'filesystem_type': 'zfs',
                        'parent': None
                    }

                    # Do this to cache the device, type see blockdevice and filesystem for info.
                    BlockDevice('zfs', name)
                    FileSystem('zfs', name)

                    zpool_datasets[uuid] = {
                        "name": name,
                        "path": name,
                        "block_device": major_minor,
                        "uuid": uuid,
                        "size": size,
                        "drives": drives
                    }

                    daemon_log.debug("zfs mount '%s'" % name)

        return zpool_datasets
示例#12
0
def lvm_populate(device):
    """ Create vg and lv entries for devices with dm attributes """
    vg_name, vg_size, lv_name, lv_uuid, vg_uuid, lv_size, lv_mm, lv_slave_mms = map(
        device.get,
        (
            "dm_vg",
            "dm_vg_size",
            "dm_lv",
            "lv_uuid",
            "vg_uuid",
            "size",
            "major_minor",
            "dm_slave_mms",
        ),
    )

    vg = {
        "name": vg_name,
        "uuid": vg_uuid,
        "size": int(vg_size),
        "pvs_major_minor": []
    }

    [
        vg["pvs_major_minor"].append(mm) for mm in lv_slave_mms
        if mm not in vg["pvs_major_minor"]
    ]

    # Do this to cache the device, type see blockdevice and filesystem for info.
    BlockDevice("lvm_volume", "/dev/mapper/%s-%s" % (vg_name, lv_name))

    lv = {
        "name": lv_name,
        "uuid": lv_uuid,
        "size": lv_size,
        "block_device": lv_mm
    }

    return vg, lv
    def __init__(self, block_devices):
        self.block_devices = block_devices
        self.mpaths = {}
        self.vgs = {}
        self.lvs = {}

        for vg_name, vg_uuid, vg_size in self._get_vgs():
            self.vgs[vg_name] = {
                'name': vg_name,
                'uuid': vg_uuid,
                'size': vg_size,
                'pvs_major_minor': []}
            self.lvs[vg_name] = {}
            for lv_name, lv_uuid, lv_size, lv_path in self._get_lvs(vg_name):
                # Do this to cache the device, type see blockdevice and filesystem for info.
                BlockDevice('lvm_volume', '/dev/mapper/%s-%s' % (vg_name, lv_name))

                self.lvs[vg_name][lv_name] = {
                    'name': lv_name,
                    'uuid': lv_uuid,
                    'size': lv_size}

        stdout = AgentShell.try_run(['dmsetup', 'table'])
        self._parse_dm_table(stdout)
示例#14
0
    def _scan_mounts(self):
        mounts = {}

        data = scanner_cmd("Stream")
        local_mounts = parse_local_mounts(data["localMounts"])
        zfs_mounts = [(d, m, f) for d, m, f in local_mounts if f == "zfs"]
        lustre_mounts = [(d, m, f) for d, m, f in local_mounts
                         if f == "lustre"]

        for device, mntpnt, _ in lustre_mounts:
            fs_label, fs_uuid = process_zfs_mount(device, data, zfs_mounts)

            if not fs_label:
                fs_label, fs_uuid = process_lvm_mount(device, data)

                if not fs_label:
                    # todo: derive information directly from device-scanner output for ldiskfs
                    # Assume that while a filesystem is mounted, its UUID and LABEL don't change.
                    # Therefore we can avoid repeated blkid calls with a little caching.
                    if device in self._mount_cache:
                        fs_uuid = self._mount_cache[device]["fs_uuid"]
                        fs_label = self._mount_cache[device]["fs_label"]
                    else:
                        # Sending none as the type means BlockDevice will use it's local
                        # cache to work the type.  This is not a good method, and we
                        # should work on a way of not storing such state but for the
                        # present it is the best we have.
                        try:
                            fs_uuid = BlockDevice(None, device).uuid
                            fs_label = FileSystem(None, device).label

                            # If we have scanned the devices then it is safe to cache the values.
                            if LinuxDevicePlugin.devices_scanned:
                                self._mount_cache[device]["fs_uuid"] = fs_uuid
                                self._mount_cache[device][
                                    "fs_label"] = fs_label
                        except AgentShell.CommandExecutionError:
                            continue

            recovery_status = {}
            try:
                lines = AgentShell.try_run([
                    "lctl", "get_param", "-n",
                    "*.%s.recovery_status" % fs_label
                ])
                for line in lines.split("\n"):
                    tokens = line.split(":")
                    if len(tokens) != 2:
                        continue
                    k = tokens[0].strip()
                    v = tokens[1].strip()
                    recovery_status[k] = v
            except Exception:
                # If the recovery_status file doesn't exist,
                # we will return an empty dict for recovery info
                pass

            mounts[device] = {
                "fs_uuid": fs_uuid,
                "mount_point": mntpnt,
                "recovery_status": recovery_status,
            }

        # Drop cached info about anything that is no longer mounted
        for k in self._mount_cache.keys():
            if k not in mounts:
                del self._mount_cache[k]

        return mounts.values()
示例#15
0
class TestFormatTarget(CommandCaptureTestCase):
    block_device_list = [
        BlockDevice('linux', '/dev/foo'),
        BlockDevice('zfs', 'lustre1')
    ]

    def setUp(self):
        super(TestFormatTarget, self).setUp()

        mock.patch(
            'iml_common.blockdevices.blockdevice_zfs.ZfsDevice.lock_pool'
        ).start()
        mock.patch(
            'iml_common.blockdevices.blockdevice_zfs.ZfsDevice.unlock_pool'
        ).start()

        self.addCleanup(mock.patch.stopall)

    def _mkfs_path(self, block_device, target_name):
        """ The mkfs path could be different for different block_device types. Today it isn't but it was when this
        method was added and so rather than remove the method I've made it return the same value for both cases and
        perhaps in the future it will be called into use again
        """
        if block_device.device_type == 'linux':
            return block_device.device_path
        elif block_device.device_type == 'zfs':
            return "%s/%s" % (block_device.device_path, target_name)
            # TODO: when BlockDevice and FileSystem merge
            # return block_device.mount_path(target_name)

        assert "Unknown device type %s" % block_device.device_type

    def _setup_run_exceptions(self, block_device, run_args):
        self._run_command = CommandCaptureCommand(tuple(filter(None,
                                                               run_args)))

        self.add_commands(
            CommandCaptureCommand(
                ("zpool", "set", "failmode=panic", "lustre1")),
            CommandCaptureCommand(
                ("dumpe2fs", "-h", "/dev/foo"),
                stdout="Inode size: 1024\nInode count: 1024\n"),
            CommandCaptureCommand(
                ("blkid", "-p", "-o", "value", "-s", "TYPE", "/dev/foo"),
                stdout="%s\n" % block_device.preferred_fstype),
            CommandCaptureCommand(
                ("blkid", "-p", "-o", "value", "-s", "UUID", "/dev/foo"),
                stdout="123456789\n"),
            CommandCaptureCommand(("zpool", "list", "-H", "-o", "name"),
                                  stdout='lustre1'),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/OST0000"),
                stdout="9845118046416187754"),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/MDT0000"),
                stdout="9845118046416187755"),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/MGS0000"),
                stdout="9845118046416187756"),
            CommandCaptureCommand(
                ("zfs", "list", "-H", "-o", "name", "-r", "lustre1")),
            CommandCaptureCommand(
                ("modprobe", "%s" % block_device.preferred_fstype)),
            CommandCaptureCommand(
                ("modprobe", "osd_%s" % block_device.preferred_fstype)),
            self._run_command)

    def test_mdt_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--mdt",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MDT0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MDT0000",
                backfstype=block_device.preferred_fstype,
                target_types=['mdt'])

            self.assertRanCommand(self._run_command)

    def test_mgs_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--mgs",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                target_types=['mgs'])

            self.assertRanCommand(self._run_command)

    def test_ost_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--ost",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MDT0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MDT0000",
                backfstype=block_device.preferred_fstype,
                target_types=['ost'])

            self.assertRanCommand(self._run_command)

    def test_single_mgs_one_nid(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--ost", "--mgsnode=1.2.3.4@tcp",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "OST0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                target_types=['ost'],
                mgsnode=[['1.2.3.4@tcp']])

            self.assertRanCommand(self._run_command)

    def test_mgs_pair_one_nid(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--ost", "--mgsnode=1.2.3.4@tcp",
                 "--mgsnode=1.2.3.5@tcp",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "OST0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                target_types=['ost'],
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                device_type=block_device.device_type,
                mgsnode=[['1.2.3.4@tcp'], ['1.2.3.5@tcp']])

            self.assertRanCommand(self._run_command)

    def test_single_mgs_multiple_nids(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--ost", "--mgsnode=1.2.3.4@tcp0,4.3.2.1@tcp1",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "OST0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                target_types=['ost'],
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                device_type=block_device.device_type,
                mgsnode=[['1.2.3.4@tcp0', '4.3.2.1@tcp1']])

            self.assertRanCommand(self._run_command)

    def test_mgs_pair_multiple_nids(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--ost", "--mgsnode=1.2.3.4@tcp0,4.3.2.1@tcp1",
                 "--mgsnode=1.2.3.5@tcp0,4.3.2.2@tcp1",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "OST0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                target_types=['ost'],
                device_type=block_device.device_type,
                mgsnode=[['1.2.3.4@tcp0', '4.3.2.1@tcp1'],
                         ['1.2.3.5@tcp0', '4.3.2.2@tcp1']])

            self.assertRanCommand(self._run_command)

    # this test does double-duty in testing tuple opts and also
    # the multiple target_types special case
    def test_tuple_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--mgs", "--mdt",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                target_types=['mgs', 'mdt'])

            self.assertRanCommand(self._run_command)

    def test_dict_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--param", "foo=bar", "--param",
                 "baz=qux thud",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                param={
                    'foo': 'bar',
                    'baz': 'qux thud'
                })

            self.assertRanCommand(self._run_command)

    def test_flag_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--dryrun",
                 "--backfstype=%s" % block_device.preferred_fstype,
                 '--mkfsoptions="mountpoint=none"' if block_device.device_type
                 == 'zfs' else '', self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                dryrun=True)

            self.assertRanCommand(self._run_command)

    def test_zero_opt(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--index=0", '--mkfsoptions=%s' %
                 ('-x 30 --y --z=83' if block_device.device_type == 'linux'
                  else '"mountpoint=none"'),
                 "--backfstype=%s" % block_device.preferred_fstype,
                 self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                index=0,
                mkfsoptions='-x 30 --y --z=83' if block_device.device_type
                == 'linux' else '"mountpoint=none"')
            self.assertRanCommand(self._run_command)

    def test_other_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                ("mkfs.lustre", "--index=42", '--mkfsoptions=%s' %
                 ('-x 30 --y --z=83' if block_device.device_type == 'linux'
                  else '"mountpoint=none"'),
                 "--backfstype=%s" % block_device.preferred_fstype,
                 self._mkfs_path(block_device, "MGS0000")))

            manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                index=42,
                mkfsoptions='-x 30 --y --z=83' if block_device.device_type
                == 'linux' else '"mountpoint=none"')

            self.assertRanCommand(self._run_command)

    def test_unknown_opt(self):
        self.assertRaises(TypeError,
                          manage_targets.format_target,
                          unknown='whatever')
class TestFormatTarget(CommandCaptureTestCase):
    block_device_list = [
        BlockDevice("linux", "/dev/foo"),
        BlockDevice("zfs", "lustre1"),
    ]

    def setUp(self):
        super(TestFormatTarget, self).setUp()

        from chroma_agent.action_plugins import manage_targets

        self.manage_targets = manage_targets
        mock.patch(
            "iml_common.blockdevices.blockdevice_zfs.BlockDeviceZfs._check_module"
        ).start()
        mock.patch(
            "iml_common.blockdevices.blockdevice_linux.BlockDeviceLinux._check_module"
        ).start()

        self.addCleanup(mock.patch.stopall)

    def _mkfs_path(self, block_device, target_name):
        """ The mkfs path could be different for different block_device types. Today it isn't but it was when this
        method was added and so rather than remove the method I've made it return the same value for both cases and
        perhaps in the future it will be called into use again
        """
        if block_device.device_type == "linux":
            return block_device.device_path
        elif block_device.device_type == "zfs":
            return "%s/%s" % (block_device.device_path, target_name)

        assert "Unknown device type %s" % block_device.device_type

    def _setup_run_exceptions(self, block_device, run_args):
        self._run_command = CommandCaptureCommand(tuple(filter(None, run_args)))

        self.add_commands(
            CommandCaptureCommand(("/usr/sbin/udevadm", "info", "--path=/module/zfs")),
            CommandCaptureCommand(("zpool", "set", "failmode=panic", "lustre1")),
            CommandCaptureCommand(
                ("dumpe2fs", "-h", "/dev/foo"),
                stdout="Inode size: 1024\nInode count: 1024\n",
            ),
            CommandCaptureCommand(
                ("blkid", "-p", "-o", "value", "-s", "TYPE", "/dev/foo"),
                stdout="%s\n" % block_device.preferred_fstype,
            ),
            CommandCaptureCommand(
                ("blkid", "-p", "-o", "value", "-s", "UUID", "/dev/foo"),
                stdout="123456789\n",
            ),
            CommandCaptureCommand(
                ("zpool", "list", "-H", "-o", "name"), stdout="lustre1"
            ),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/OST0000"),
                stdout="9845118046416187754",
            ),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/MDT0000"),
                stdout="9845118046416187755",
            ),
            CommandCaptureCommand(
                ("zfs", "get", "-H", "-o", "value", "guid", "lustre1/MGS0000"),
                stdout="9845118046416187756",
            ),
            CommandCaptureCommand(("zfs", "list", "-H", "-o", "name", "-r", "lustre1")),
            CommandCaptureCommand(("modprobe", "%s" % block_device.preferred_fstype)),
            CommandCaptureCommand(
                ("modprobe", "osd_%s" % block_device.preferred_fstype)
            ),
            self._run_command,
        )

    def test_mdt_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--mdt",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MDT0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MDT0000",
                backfstype=block_device.preferred_fstype,
                target_types=["mdt"],
            )

            self.assertRanCommand(self._run_command)

    def test_mgs_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--mgs",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                target_types=["mgs"],
            )

            self.assertRanCommand(self._run_command)

    def test_ost_mkfs(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--ost",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MDT0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MDT0000",
                backfstype=block_device.preferred_fstype,
                target_types=["ost"],
            )

            self.assertRanCommand(self._run_command)

    def test_single_mgs_one_nid(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--ost",
                    "--mgsnode=1.2.3.4@tcp",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "OST0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                target_types=["ost"],
                mgsnode=[["1.2.3.4@tcp"]],
            )

            self.assertRanCommand(self._run_command)

    def test_mgs_pair_one_nid(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--ost",
                    "--mgsnode=1.2.3.4@tcp",
                    "--mgsnode=1.2.3.5@tcp",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "OST0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                target_types=["ost"],
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                device_type=block_device.device_type,
                mgsnode=[["1.2.3.4@tcp"], ["1.2.3.5@tcp"]],
            )

            self.assertRanCommand(self._run_command)

    def test_single_mgs_multiple_nids(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--ost",
                    "--mgsnode=1.2.3.4@tcp0,4.3.2.1@tcp1",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "OST0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                target_types=["ost"],
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                device_type=block_device.device_type,
                mgsnode=[["1.2.3.4@tcp0", "4.3.2.1@tcp1"]],
            )

            self.assertRanCommand(self._run_command)

    def test_mgs_pair_multiple_nids(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--ost",
                    "--mgsnode=1.2.3.4@tcp0,4.3.2.1@tcp1",
                    "--mgsnode=1.2.3.5@tcp0,4.3.2.2@tcp1",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "OST0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                target_name="OST0000",
                backfstype=block_device.preferred_fstype,
                target_types=["ost"],
                device_type=block_device.device_type,
                mgsnode=[
                    ["1.2.3.4@tcp0", "4.3.2.1@tcp1"],
                    ["1.2.3.5@tcp0", "4.3.2.2@tcp1"],
                ],
            )

            self.assertRanCommand(self._run_command)

    # this test does double-duty in testing tuple opts and also
    # the multiple target_types special case
    def test_tuple_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--mgs",
                    "--mdt",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                target_types=["mgs", "mdt"],
            )

            self.assertRanCommand(self._run_command)

    def test_dict_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--param",
                    "foo=bar",
                    "--param",
                    "baz=qux thud",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                param={"foo": "bar", "baz": "qux thud"},
            )

            self.assertRanCommand(self._run_command)

    def test_flag_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--dryrun",
                    "--backfstype=%s" % block_device.preferred_fstype,
                    '--mkfsoptions="mountpoint=none"'
                    if block_device.device_type == "zfs"
                    else "",
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                dryrun=True,
            )

            self.assertRanCommand(self._run_command)

    def test_zero_opt(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--index=0",
                    "--mkfsoptions=%s"
                    % (
                        "-x 30 --y --z=83"
                        if block_device.device_type == "linux"
                        else '"mountpoint=none"'
                    ),
                    "--backfstype=%s" % block_device.preferred_fstype,
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                index=0,
                mkfsoptions="-x 30 --y --z=83"
                if block_device.device_type == "linux"
                else '"mountpoint=none"',
            )
            self.assertRanCommand(self._run_command)

    def test_other_opts(self):
        for block_device in self.block_device_list:
            self._setup_run_exceptions(
                block_device,
                (
                    "mkfs.lustre",
                    "--index=42",
                    "--mkfsoptions=%s"
                    % (
                        "-x 30 --y --z=83"
                        if block_device.device_type == "linux"
                        else '"mountpoint=none"'
                    ),
                    "--backfstype=%s" % block_device.preferred_fstype,
                    self._mkfs_path(block_device, "MGS0000"),
                ),
            )

            self.manage_targets.format_target(
                device=block_device.device_path,
                device_type=block_device.device_type,
                target_name="MGS0000",
                backfstype=block_device.preferred_fstype,
                index=42,
                mkfsoptions="-x 30 --y --z=83"
                if block_device.device_type == "linux"
                else '"mountpoint=none"',
            )

            self.assertRanCommand(self._run_command)

    def test_unknown_opt(self):
        self.assertRaises(
            TypeError, self.manage_targets.format_target, unknown="whatever"
        )
示例#17
0
def purge_configuration(mgs_device_path, mgs_device_type, filesystem_name):
    mgs_blockdevice = BlockDevice(mgs_device_type, mgs_device_path)

    return agent_ok_or_error(
        mgs_blockdevice.purge_filesystem_configuration(filesystem_name,
                                                       console_log))
示例#18
0
def format_target(device_type,
                  target_name,
                  device,
                  backfstype,
                  target_types=(),
                  mgsnode=(),
                  fsname=None,
                  failnode=(),
                  servicenode=(),
                  param={},
                  index=None,
                  comment=None,
                  mountfsoptions=None,
                  network=(),
                  device_size=None,
                  mkfsoptions=None,
                  reformat=False,
                  stripe_count_hint=None,
                  iam_dir=False,
                  dryrun=False,
                  verbose=False,
                  quiet=False):
    """Perform a mkfs.lustre operation on a target device.
       Device may be a number of devices, block"""

    # freeze a view of the namespace before we start messing with it
    args = dict(locals())
    options = []

    # Now remove the locals that are not parameters for mkfs.
    del args['device_type']
    del args['target_name']

    tuple_options = [
        "target_types", "mgsnode", "failnode", "servicenode", "network"
    ]
    for name in tuple_options:
        arg = args[name]
        # ensure that our tuple arguments are always tuples, and not strings
        if not hasattr(arg, "__iter__"):
            arg = (arg, )

        if name == "target_types":
            for type in arg:
                options.append("--%s" % type)
        elif name == 'mgsnode':
            for mgs_nids in arg:
                options.append("--%s=%s" % (name, ",".join(mgs_nids)))
        else:
            if len(arg) > 0:
                options.append("--%s=%s" % (name, ",".join(arg)))

    flag_options = {
        'dryrun': '--dryrun',
        'reformat': '--reformat',
        'iam_dir': '--iam-dir',
        'verbose': '--verbose',
        'quiet': '--quiet',
    }

    for arg in flag_options:
        if args[arg]:
            options.append("%s" % flag_options[arg])

    dict_options = ["param"]
    for name in dict_options:
        for key, value in args[name].items():
            if value is not None:
                options.extend(["--%s" % name, "%s=%s" % (key, value)])

    # everything else
    handled = set(flag_options.keys() + tuple_options + dict_options)
    for name in set(args.keys()) - handled:
        if name == "device":
            continue
        value = args[name]
        if value is not None:
            options.append("--%s=%s" % (name, value))

    # cache BlockDevice to store knowledge of the device_type at this path
    BlockDevice(device_type, device)
    filesystem = FileSystem(backfstype, device)

    return filesystem.mkfs(target_name, options)
示例#19
0
def format_target(device_type,
                  target_name,
                  device,
                  backfstype,
                  target_types=(),
                  mgsnode=(),
                  fsname=None,
                  failnode=(),
                  servicenode=(),
                  param=None,
                  index=None,
                  comment=None,
                  mountfsoptions=None,
                  network=(),
                  device_size=None,
                  mkfsoptions=None,
                  reformat=False,
                  stripe_count_hint=None,
                  iam_dir=False,
                  dryrun=False,
                  verbose=False,
                  quiet=False):
    """Perform a mkfs.lustre operation on a target device.
       Device may be a number of devices, block"""

    # freeze a view of the namespace before we start messing with it
    args = dict(locals())
    options = []

    # Now remove the locals that are not parameters for mkfs.
    del args['device_type']
    del args['target_name']

    single = "--{}".format
    double = "--{}={}".format

    tuple_options = [
        "target_types", "mgsnode", "failnode", "servicenode", "network"
    ]
    for name in tuple_options:
        arg = args[name]
        # ensure that our tuple arguments are always tuples, and not strings
        if not hasattr(arg, "__iter__"):
            arg = (arg, )

        if name == "target_types":
            options += [single(target) for target in arg]
        elif name == 'mgsnode':
            options += [double(name, ",".join(mgs_nids)) for mgs_nids in arg]
        elif len(arg) > 0:
            options.append(double(name, ",".join(arg)))

    flag_options = {
        'dryrun': '--dryrun',
        'reformat': '--reformat',
        'iam_dir': '--iam-dir',
        'verbose': '--verbose',
        'quiet': '--quiet',
    }
    options += [flag_options[arg] for arg in flag_options if args[arg]]

    dict_options = ["param"]
    for name in dict_options:
        arg = args[name]
        if arg:
            options += [
                x for key in arg if arg[key] is not None
                for x in [single(name), "{}={}".format(key, arg[key])]
            ]

    # everything else
    handled = set(flag_options.keys() + tuple_options + dict_options)
    options += [
        double(name, args[name]) for name in set(args.keys()) - handled
        if name != "device" and args[name] is not None
    ]

    # cache BlockDevice to store knowledge of the device_type at this path
    BlockDevice(device_type, device)
    filesystem = FileSystem(backfstype, device)

    return filesystem.mkfs(target_name, options)