Example #1
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 sorted(target_devices, cmp=LocalTargets.comparator):
            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"] is 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"] is 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()
Example #2
0
 def get_patched_ndt(self, fixture):
     with patch(
             "chroma_agent.device_plugins.block_devices.scanner_cmd",
             return_value=fixture,
     ):
         return get_normalized_device_table()
Example #3
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, fstype in lustre_mounts:
            fs_label, fs_uuid, new_device = process_zfs_mount(device, data, zfs_mounts)

            if not fs_label:
                fs_label, fs_uuid, new_device = 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

            ndt = get_normalized_device_table()
            dev_normalized = ndt.normalized_device_path(device if not new_device else new_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 k not in mounts:
                del self._mount_cache[k]

        return mounts.values()