def list_asds(): """ List all ASDs """ asds = {} mountpoints = FSTab.read() for disk, mountpoint in mountpoints.iteritems(): asds[disk] = ASDController.list_asds(mountpoint) return asds
def add_asd_disk(disk_id): """ Adds an ASD to a disk :param disk_id: Identifier of the disk :type disk_id: str """ mountpoints = FSTab.read() if disk_id not in mountpoints: raise BadRequest('Disk {0} is not yet initialized'.format(disk_id)) with file_mutex('add_asd'): ASDController.create_asd(disk_id)
def list_asds_disk(disk_id): """ Lists all ASDs on a given disk :param disk_id: Identifier of the disk :type disk_id: str """ mountpoints = FSTab.read() if disk_id not in mountpoints: raise BadRequest('Disk {0} is not yet initialized'.format(disk_id)) mountpoint = mountpoints[disk_id] return ASDController.list_asds(mountpoint)
def list_asds_disk(disk_id): """ Lists all ASDs on a given disk :param disk_id: Identifier of the disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :return: ASD information for the specified disk :rtype: dict """ disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) for partition_alias, mountpoint in FSTab.read().iteritems(): if partition_alias in disk_data['partition_aliases']: return ASDController.list_asds(mountpoint=mountpoint) raise BadRequest('Disk {0} is not yet initialized'.format(disk_data['aliases'][0]))
def add_asd_disk(disk_id): """ Adds an ASD to a disk :param disk_id: Identifier of the disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :return: None """ disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) for partition_alias, mountpoint in FSTab.read().iteritems(): if partition_alias in disk_data['partition_aliases']: with file_mutex('add_asd'): ASDController.create_asd(partition_alias=partition_alias) return raise BadRequest('Disk {0} is not yet initialized'.format(disk_data['aliases'][0]))
def get_asd(disk_id, asd_id): """ Gets an ASD :param disk_id: Identifier of the disk :type disk_id: str :param asd_id: Identifier of the ASD :type asd_id: str """ mountpoints = FSTab.read() if disk_id not in mountpoints: raise BadRequest('Disk {0} is not yet initialized'.format(disk_id)) mountpoint = mountpoints[disk_id] asds = ASDController.list_asds(mountpoint) if asd_id not in asds: raise BadRequest('ASD {0} could not be found on disk'.format(disk_id)) return asds[asd_id]
def get_asd(disk_id, asd_id): """ Gets an ASD :param disk_id: Identifier of the disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :param asd_id: Identifier of the ASD (eg: bnAWEXuPHN5YJceCeZo7KxaQW86ixXd4, found under /mnt/alba-asd/WDCztMxmRqi6Hx21/) :type asd_id: str :return: ASD information :rtype: dict """ disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) alias = disk_data['aliases'][0] for partition_alias, mountpoint in FSTab.read().iteritems(): if partition_alias in disk_data['partition_aliases']: asds = ASDController.list_asds(mountpoint=mountpoint) if asd_id not in asds: raise BadRequest('ASD {0} could not be found on disk'.format(alias)) return asds[asd_id] raise BadRequest('Disk {0} is not yet initialized'.format(alias))
def delete_disk(disk_id): """ Delete a disk :param disk_id: Identifier of the disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :return: None """ try: disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) except DiskNotFoundError: API._logger.warning('Disk with ID {0} is no longer detected on the filesystem'.format(disk_id)) disk_data = {} if disk_data.get('available') is True: raise BadRequest('Disk not yet configured') if disk_data: alias = disk_data['aliases'][0] mountpoint = disk_data['mountpoint'] or None partition_aliases = disk_data['partition_aliases'] API._logger.info('Deleting disk {0}'.format(alias)) else: # Disk is most likely missing from filesystem alias = None mountpoint = None partition_aliases = json.loads(request.form['partition_aliases']) API._logger.info('Deleting unknown disk with partition aliases "{0}"'.format('", "'.join(partition_aliases))) if mountpoint is None: # 'lsblk' did not return mountpoint for the device, but perhaps it's still mounted according to FSTab for partition_alias, mtpt in FSTab.read().iteritems(): if partition_alias in partition_aliases: API._logger.warning('Disk with ID {0} is still mounted on {1} according to FSTab'.format(disk_id, mountpoint)) mountpoint = mtpt break with file_mutex('disk_{0}'.format(disk_id)): if mountpoint is not None: for asd_id in ASDController.list_asds(mountpoint=mountpoint): ASDController.remove_asd(asd_id=asd_id, mountpoint=mountpoint) DiskController.clean_disk(device_alias=alias, mountpoint=mountpoint, partition_aliases=partition_aliases)
def asd_delete(disk_id, asd_id): """ Deletes an ASD on a given disk :param disk_id: Identifier of the Disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :param asd_id: Identifier of the ASD (eg: bnAWEXuPHN5YJceCeZo7KxaQW86ixXd4, found under /mnt/alba-asd/WDCztMxmRqi6Hx21/) :type asd_id: str :return: None """ disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) alias = disk_data['aliases'][0] API._logger.info('Removing services for disk {0}'.format(alias)) for partition_alias, mountpoint in FSTab.read().iteritems(): if partition_alias in disk_data['partition_aliases']: if asd_id not in ASDController.list_asds(mountpoint=mountpoint): raise BadRequest('Could not find ASD {0} on disk {1}'.format(asd_id, alias)) ASDController.remove_asd(asd_id=asd_id, mountpoint=mountpoint) return raise BadRequest('Disk {0} is not yet initialized'.format(alias))
def delete_disk(disk_id): """ Delete a disk :param disk_id: Identifier of the disk :type disk_id: str """ API._log('Deleting disk {0}'.format(disk_id)) all_disks = DiskController.list_disks() if disk_id not in all_disks: raise BadRequest('Disk not available') if all_disks[disk_id]['available'] is True: raise BadRequest('Disk not yet configured') with file_mutex('disk_{0}'.format(disk_id)): mountpoints = FSTab.read() if disk_id in mountpoints: mountpoint = mountpoints[disk_id] asds = ASDController.list_asds(mountpoint) for asd_id in asds: ASDController.remove_asd(asd_id, mountpoint) DiskController.clean_disk(disk_id, mountpoint)
def asd_delete(disk_id, asd_id): """ Deletes an ASD on a given Disk :param disk_id: Identifier of the Disk :type disk_id: str :param asd_id: The ASD ID of the ASD to be removed :type asd_id: str """ # Stop and remove service API._log('Removing services for disk {0}'.format(disk_id)) mountpoints = FSTab.read() if disk_id not in mountpoints: raise BadRequest('Disk {0} is not yet initialized'.format(disk_id)) all_asds = {} for mountpoint in mountpoints.values(): all_asds.update(ASDController.list_asds(mountpoint)) if asd_id not in all_asds: raise BadRequest('Could not find ASD {0} on disk {1}'.format(asd_id, disk_id)) mountpoint = mountpoints[disk_id] ASDController.remove_asd(asd_id, mountpoint)
def restart_disk(disk_id): """ Restart a disk :param disk_id: Identifier of the disk (eg: '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0' or 'pci-0000:03:00.0-sas-0x5000c29f4cf04566-lun-0') :type disk_id: str :return: None """ API._logger.info('Restarting disk {0}'.format(disk_id)) disk_data = DiskController.get_disk_data_by_alias(device_alias=disk_id) alias = disk_data['aliases'][0] with file_mutex('disk_{0}'.format(disk_id)): API._logger.info('Got lock for restarting disk {0}'.format(alias)) for partition_alias, mountpoint in FSTab.read().iteritems(): if partition_alias in disk_data['partition_aliases']: asds = ASDController.list_asds(mountpoint=mountpoint) for asd_id in asds: ASDController.stop_asd(asd_id=asd_id) DiskController.remount_disk(device_alias=alias, mountpoint=mountpoint) asds = ASDController.list_asds(mountpoint=mountpoint) for asd_id in asds: ASDController.start_asd(asd_id=asd_id) break
def restart_disk(disk_id): """ Restart a disk :param disk_id: Identifier of the disk :type disk_id: str """ API._log('Restarting disk {0}'.format(disk_id)) all_disks = DiskController.list_disks() if disk_id not in all_disks: raise BadRequest('Disk not available') if all_disks[disk_id]['available'] is False: raise BadRequest('Disk already configured') with file_mutex('disk_{0}'.format(disk_id)): API._log('Got lock for restarting disk {0}'.format(disk_id)) mountpoints = FSTab.read() if disk_id in mountpoints: mountpoint = mountpoints[disk_id] asds = ASDController.list_asds(mountpoint) for asd_id in asds: ASDController.stop_asd(asd_id) DiskController.remount_disk(disk_id, mountpoint) asds = ASDController.list_asds(mountpoint) for asd_id in asds: ASDController.start_asd(asd_id)
def list_asds(): """ List all ASDs :return: Information about all ASDs on local node :rtype: dict """ return dict((partition_alias, ASDController.list_asds(mountpoint=mountpoint)) for partition_alias, mountpoint in FSTab.read().iteritems())
def create_asd(partition_alias): """ Creates and starts an ASD on a given disk :param partition_alias: Alias of the partition of a disk (eg: /dev/disk/by-id/scsi-1ATA_TOSHIBA_MK2002TSKB_92M1KDMHF-part1) :type partition_alias: str :return: None """ all_asds = {} mountpoint = None for alias, mtpt in FSTab.read().iteritems(): all_asds.update(ASDController.list_asds(mtpt)) if alias == partition_alias: mountpoint = mtpt if mountpoint is None: raise RuntimeError('Failed to retrieve the mountpoint for partition with alias: {0}'.format(partition_alias)) # Fetch disk information disk_size = int(ASDController._local_client.run(['df', '-B', '1', '--output=size', mountpoint]).splitlines()[1]) # Find out appropriate disk size asds = 1.0 for asd_id in os.listdir(mountpoint): if os.path.isdir('/'.join([mountpoint, asd_id])) and Configuration.exists(ASDController.ASD_CONFIG.format(asd_id)): asds += 1 asd_size = int(math.floor(disk_size / asds)) for asd_id in os.listdir(mountpoint): if os.path.isdir('/'.join([mountpoint, asd_id])) and Configuration.exists(ASDController.ASD_CONFIG.format(asd_id)): config = json.loads(Configuration.get(ASDController.ASD_CONFIG.format(asd_id), raw=True)) config['capacity'] = asd_size config['rocksdb_block_cache_size'] = int(asd_size / 1024 / 4) Configuration.set(ASDController.ASD_CONFIG.format(asd_id), json.dumps(config, indent=4), raw=True) try: ServiceManager.send_signal(ASDController.ASD_SERVICE_PREFIX.format(asd_id), signal.SIGUSR1, ASDController._local_client) except Exception as ex: ASDController._logger.info('Could not send signal to ASD for reloading the quota: {0}'.format(ex)) # Prepare & start service asd_id = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32)) ASDController._logger.info('Setting up service for disk {0}'.format(partition_alias)) homedir = '{0}/{1}'.format(mountpoint, asd_id) base_port = Configuration.get('{0}/network|port'.format(ASDController.CONFIG_ROOT)) ips = Configuration.get('{0}/network|ips'.format(ASDController.CONFIG_ROOT)) used_ports = [] for asd in all_asds.itervalues(): used_ports.append(asd['port']) if 'rora_port' in asd: used_ports.append(asd['rora_port']) asd_port = base_port rora_port = base_port + 1 while asd_port in used_ports: asd_port += 1 used_ports.append(asd_port) while rora_port in used_ports: rora_port += 1 asd_config = {'home': homedir, 'node_id': ASDController.NODE_ID, 'asd_id': asd_id, 'capacity': asd_size, 'log_level': 'info', 'port': asd_port, 'transport': 'tcp', 'rocksdb_block_cache_size': int(asd_size / 1024 / 4)} if Configuration.get('/ovs/framework/rdma'): asd_config['rora_port'] = rora_port asd_config['rora_transport'] = 'rdma' if ips is not None and len(ips) > 0: asd_config['ips'] = ips if Configuration.exists('{0}/extra'.format(ASDController.CONFIG_ROOT)): data = Configuration.get('{0}/extra'.format(ASDController.CONFIG_ROOT)) asd_config.update(data) Configuration.set(ASDController.ASD_CONFIG.format(asd_id), json.dumps(asd_config, indent=4), raw=True) service_name = ASDController.ASD_SERVICE_PREFIX.format(asd_id) params = {'CONFIG_PATH': Configuration.get_configuration_path('/ovs/alba/asds/{0}/config'.format(asd_id)), 'SERVICE_NAME': service_name, 'LOG_SINK': LogHandler.get_sink_path('alba_asd')} os.mkdir(homedir) ASDController._local_client.run(['chown', '-R', 'alba:alba', homedir]) ServiceManager.add_service('alba-asd', ASDController._local_client, params, service_name) ASDController.start_asd(asd_id)
def list_disks(): disks = {} # Find used disks # 1. Mounted disks all_mounts = check_output('mount', shell=True).splitlines() used_disks = [] for mount in all_mounts: mount = mount.strip() match = re.search('/dev/(.+?) on (/.*?) type.*', mount) if match is not None and not match.groups()[1].startswith('/mnt/alba-asd/'): used_disks.append(match.groups()[0]) # 2. Disks used in a software raid mdstat = check_output('cat /proc/mdstat', shell=True) for md_match in re.findall('([a-z]+\d+ : (in)?active raid\d+(( [a-z]+\d?\[\d+\])+))', mdstat): for disk_match in re.findall('( ([a-z]+\d?)\[\d+\])', md_match[2]): used_disks.append(disk_match[1].strip()) # Find all disks all_disks = check_output('ls -al /dev/disk/by-id/', shell=True).split('\n') for disk in all_disks: disk = disk.strip() match = re.search('.+?(((scsi-)|(ata-)).+?) -> ../../(sd.+)', disk) if match is not None: disk_id, disk_name = match.groups()[0], match.groups()[-1] if re.search('-part\d+', disk_id) is None: if not any(used_disk for used_disk in used_disks if disk_name in used_disk): disks[disk_id] = {'device': '/dev/disk/by-id/{0}'.format(disk_id), 'available': True, 'state': {'state': 'ok'}} # Load information about mount configuration (detect whether the disks are configured) fstab_disks = FSTab.read() for device in fstab_disks.keys(): for disk_id in disks: if disks[disk_id]['device'] == '/dev/disk/by-id/{0}'.format(device): disks[disk_id].update({'available': False, 'mountpoint': fstab_disks[device], 'asd_id': fstab_disks[device].split('/')[-1]}) del fstab_disks[device] for device in fstab_disks.keys(): disks[device] = {'device': '/dev/disk/by-id/{0}'.format(device), 'available': False, 'mountpoint': fstab_disks[device], 'asd_id': fstab_disks[device].split('/')[-1], 'state': {'state': 'error', 'detail': 'missing'}} # Load statistical information about the disk df_info = check_output('df -k /mnt/alba-asd/* || true', shell=True).strip().split('\n') for disk_id in disks: if 'asd_id' in disks[disk_id]: for df in df_info: match = re.search('\S+?\s+?(\d+?)\s+?(\d+?)\s+?(\d+?)\s.+?/mnt/alba-asd/{0}'.format(disks[disk_id]['asd_id']), df) if match is not None: disks[disk_id].update({'usage': {'size': int(match.groups()[0]) * 1024, 'used': int(match.groups()[1]) * 1024, 'available': int(match.groups()[2]) * 1024}}) # Execute some checkups on the disks for disk_id in disks: if disks[disk_id]['available'] is False and disks[disk_id]['state']['state'] == 'ok': output = check_output('ls {0}/ 2>&1 || true'.format(disks[disk_id]['mountpoint']), shell=True) if 'Input/output error' in output: disks[disk_id]['state'] = {'state': 'error', 'detail': 'ioerror'} return disks
def list_disks(): """ List the disks :return: Information about the disks """ disks = {} # Find used disks # 1. Mounted disks all_mounts = check_output('mount', shell=True).splitlines() all_mounted_asds = [] used_disks = [] for mount in all_mounts: mount = mount.strip() match = re.search('/dev/(.+?) on (/.*?) type.*', mount) if match is not None: if not match.groups()[1].startswith('/mnt/alba-asd/'): used_disks.append(match.groups()[0]) else: all_mounted_asds.append(match.groups()[0]) # 2. Disks used in a software raid mdstat = check_output('cat /proc/mdstat', shell=True) for md_match in re.findall('([a-z]+\d+ : (in)?active raid\d+(( [a-z]+\d?\[\d+\])+))', mdstat): for disk_match in re.findall('( ([a-z]+\d?)\[\d+\])', md_match[2]): used_disks.append(disk_match[1].strip()) # Find all disks all_disks = check_output('ls -al /dev/disk/by-id/', shell=True).split('\n') for disk in all_disks: disk = disk.strip() match = re.search('.+?(((scsi-)|(ata-)|(virtio-)).+?) -> ../../([sv]d.+)', disk) if match is not None: disk_id, disk_name = match.groups()[0], match.groups()[-1] if disk_name in all_mounted_asds: all_mounted_asds.remove(disk_name) all_mounted_asds.append(disk_id.replace('-part1', '')) if re.search('-part\d+', disk_id) is None: if not any(used_disk for used_disk in used_disks if disk_name in used_disk): disks[disk_id] = {'device': '/dev/disk/by-id/{0}'.format(disk_id), 'available': True, 'state': 'ok'} # Load information about mount configuration (detect whether the disks are configured) fstab_disks = FSTab.read() for device in fstab_disks.keys(): for disk_id in disks: if disk_id == device: disks[disk_id].update({'available': False, 'mountpoint': fstab_disks[device]}) del fstab_disks[device] if device not in all_mounted_asds: disks[device].update({'state': 'error', 'state_detail': 'notmounted'}) for device in fstab_disks.keys(): disks[device] = {'device': '/dev/disk/by-id/{0}'.format(device), 'available': False, 'mountpoint': fstab_disks[device], 'state': 'error', 'state_detail': 'missing'} # Load statistical information about the disk root_directory = '/mnt/alba-asd' if DiskController._local_client.dir_exists(root_directory) and DiskController._local_client.dir_list(root_directory): df_info = check_output('df -B 1 --output=size,used,avail,target /mnt/alba-asd/*', shell=True).strip().splitlines()[1:] for disk_id in disks: if disks[disk_id]['available'] is False and disks[disk_id]['state'] == 'ok': for df in df_info: params = df.split() if params[-1] == disks[disk_id]['mountpoint']: disks[disk_id].update({'usage': {'size': int(params[0]), 'used': int(params[1]), 'available': int(params[2])}}) # Execute some checkups on the disks for disk_id in disks: if disks[disk_id]['available'] is False and disks[disk_id]['state'] == 'ok': output = check_output('ls {0}/ 2>&1 || true'.format(disks[disk_id]['mountpoint']), shell=True) if 'Input/output error' in output: disks[disk_id].update({'state': 'error', 'state_detail': 'ioerror'}) # Extra information for disk_id, disk in disks.iteritems(): disk['name'] = disk_id disk['node_id'] = DiskController.NODE_ID return disks
def list_disks(): """ List the disks CHANGES MADE TO THIS CODE SHOULD BE REFLECTED IN THE FRAMEWORK sync_with_reality CALL TOO. :return: Information about the disks :rtype: dict """ # Retrieve all symlinks for all devices # Example of name_alias_mapping: # {'/dev/md0': ['/dev/disk/by-id/md-uuid-ad2de634:26d97253:5eda0a23:96986b76', '/dev/disk/by-id/md-name-OVS-1:0'], # '/dev/sda': ['/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0'], # '/dev/sda1': ['/dev/disk/by-uuid/e3e0bc62-4edc-4c6b-a6ce-1f39e8f27e41', '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0-part1']} name_alias_mapping = {} alias_name_mapping = {} partition_device_map = {} for path_type in DiskController._local_client.dir_list(directory='/dev/disk'): if path_type in ['by-uuid', 'by-partuuid']: # UUIDs can change after creating a filesystem on a partition continue directory = '/dev/disk/{0}'.format(path_type) for symlink in DiskController._local_client.dir_list(directory=directory): symlink_path = '{0}/{1}'.format(directory, symlink) link = DiskController._local_client.file_read_link(path=symlink_path) if link not in name_alias_mapping: name_alias_mapping[link] = [] name_alias_mapping[link].append(symlink_path) alias_name_mapping[symlink_path] = link # Parse 'lsblk' output # --exclude 1 for RAM devices, 2 for floppy devices, 11 for CD-ROM devices (See https://www.kernel.org/doc/Documentation/devices.txt) devices = DiskController._local_client.run(['lsblk', '--pairs', '--bytes', '--noheadings', '--exclude', '1,2,11', '--output=KNAME,FSTYPE,TYPE,MOUNTPOINT']).splitlines() device_regex = re.compile('^KNAME="(?P<name>.*)" FSTYPE="(?P<fstype>.*)" TYPE="(?P<type>.*)" MOUNTPOINT="(?P<mtpt>.*)"$') configuration = {} parsed_devices = [] for device in devices: match = re.match(device_regex, device) if match is None: DiskController._logger.error('Device regex did not match for {0}. Please investigate'.format(device)) raise Exception('Failed to parse \'lsblk\' output') groupdict = match.groupdict() name = groupdict['name'].strip() fs_type = groupdict['fstype'].strip() dev_type = groupdict['type'].strip() mount_point = groupdict['mtpt'].strip() if dev_type == 'rom': continue link = DiskController._local_client.file_read_link(path='/sys/block/{0}'.format(name)) friendly_path = '/dev/{0}'.format(name) system_aliases = sorted(name_alias_mapping.get(friendly_path, [friendly_path])) device_is_also_partition = False if link is not None: # If this returns, it means its a device and not a partition device_is_also_partition = mount_point != '' # LVM, RAID1, ... have the tendency to be a device with a partition on it, but the partition is not reported by 'lsblk' parsed_devices.append(name) configuration[name] = {'name': name, 'aliases': system_aliases, 'partitions': []} if link is None or device_is_also_partition is True: current_device = None if device_is_also_partition is True: current_device = name else: for device_name in reversed(parsed_devices): try: current_device = device_name DiskController._local_client.file_read(filename='/sys/block/{0}/{1}/start'.format(current_device, name)) break except Exception: pass if current_device is None: raise RuntimeError('Failed to retrieve the device information for current partition') mount_point = mount_point if mount_point != '' else None partition_device_map[friendly_path] = current_device configuration[current_device]['partitions'].append({'aliases': system_aliases, 'filesystem': fs_type if fs_type != '' else None, 'mountpoint': mount_point}) # Parse 'configuration' to see which devices can be used as ASD disks = {} for device_name, device_info in configuration.iteritems(): availability = True usable_device = True partition_mtpt = None partition_aliases = [] for partition in device_info['partitions']: partition_mtpt = partition['mountpoint'] partition_filesystem = partition['filesystem'] partition_aliases.extend(partition['aliases']) if partition_mtpt is not None: if partition_mtpt.startswith('/mnt/alba-asd/'): availability = False else: usable_device = False break if partition_filesystem in ['swap', 'linux_raid_member', 'LVM2_member']: usable_device = False break if usable_device is True: usage = {} state = 'ok' state_detail = '' if availability is False: # Check partition usage information df_info = DiskController._local_client.run("df -B 1 --output=size,used,avail '{0}' | tail -1 || true".format(partition_mtpt.replace(r"'", r"'\''")), allow_insecure=True).strip().splitlines() if len(df_info) != 1: DiskController._logger.warning('Verifying usage information for mountpoint {0} failed. Information retrieved: {1}'.format(partition_mtpt, df_info)) continue size, used, available = df_info[0].split() usage = {'size': int(size), 'used': int(used), 'available': int(available)} # Check mountpoint validation output, error = DiskController._local_client.run(['ls', '{0}/'.format(partition_mtpt)], allow_nonzero=True, return_stderr=True) output += error if 'Input/output error' in output: state = 'error' state_detail = 'io_error' aliases = device_info['aliases'] disks[aliases[0]] = {'usage': usage, 'state': state, 'device': '/dev/{0}'.format(device_name), 'aliases': aliases, 'node_id': DiskController.NODE_ID, 'available': availability, 'mountpoint': partition_mtpt, 'state_detail': state_detail, 'partition_amount': len(device_info['partitions']), 'partition_aliases': partition_aliases} # Verify FStab entries are present in 'disks' fstab_disks = FSTab.read() for device_info in disks.itervalues(): for partition_alias, mountpoint in fstab_disks.items(): if partition_alias in device_info['partition_aliases']: fstab_disks.pop(partition_alias) # FSTab entries which are not present in disks (missing disks) are not returned. return disks