Source code for insights.parsers.systool

"""
Command ``systool`` outputs - Commands
======================================

Command systool uses APIs provided by libsysfs to gather information.

Parser included in this module is:

SystoolSCSIBus - command ``/bin/systool -b scsi -v``
----------------------------------------------------

"""
from insights.core import CommandParser, LegacyItemAccess
from insights.core.exceptions import ParseException
from insights.core.plugins import parser
from insights.specs import Specs


[docs] @parser(Specs.systool_b_scsi_v) class SystoolSCSIBus(LegacyItemAccess, CommandParser): """ Class for parsing ``/bin/systool -b scsi -v`` command output Typical command output:: Bus = "scsi" Device = "1:0:0:0" Device path = "/sys/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0" delete = <store method only> device_blocked = "0" device_busy = "0" dh_state = "detached" eh_timeout = "10" evt_capacity_change_reported= "0" evt_inquiry_change_reported= "0" evt_lun_change_reported= "0" evt_media_change = "0" evt_mode_parameter_change_reported= "0" evt_soft_threshold_reached= "0" iocounterbits = "32" iodone_cnt = "0x15b" ioerr_cnt = "0x3" iorequest_cnt = "0x16c" modalias = "scsi:t-0x05" model = "CD-ROM " queue_depth = "1" queue_type = "none" rescan = <store method only> rev = "1.0 " scsi_level = "6" state = "running" timeout = "30" type = "5" uevent = "DEVTYPE=scsi_device DRIVER=sr MODALIAS=scsi:t-0x05" unpriv_sgio = "0" vendor = "VBOX " Device = "2:0:0:0" ... Examples: >>> len(res.data) 2 >>> res.data.keys() ['1:0:0:0', '2:0:0:0'] >>> res.device_names ['1:0:0:0', '2:0:0:0'] >>> res.data['1:0:0:0'] == res.devices[0] True >>> res.get_device_state('1:0:0:0') 'running' >>> res.get_device_state('2:0:0:0') None """
[docs] def parse_content(self, content): content = [l for l in content if l] if content[0] and not all([v in content[0] for v in ("Bus", "=", "scsi")]): raise ParseException("Unparseable first line of input: %s" % content[0]) if len(content) <= 2: raise ParseException("Parsing Error for this almost empty input.") self.devices = [] self.device_names = [] multi_lines_str = None for _l in content[1:]: l = _l.strip() if not multi_lines_str: # Starter of a new logical line k, v = self._split_line(l) if v.startswith('"') and not v.endswith('"'): # Starter of a multi_lines line multi_lines_str = l + ' ' else: # fairly a normal line self._record_pair(k, v) else: # Continue that multi-lines line if l.endswith('"'): # End of a multi_lines line multi_lines_str += l k, v = self._split_line(multi_lines_str) multi_lines_str = None self._record_pair(k, v) else: # Mid of a multi_lines line multi_lines_str += l + ' ' data = {} for k, v in zip(self.device_names, self.devices): data[k] = v self.data = data
def _split_line(self, line): if '=' not in line: raise ParseException("Unparseable line without = : %s", line) _k, _v = line.split('=', 1) k = _k.strip() v = _v.strip() if not k: raise ParseException("Unparseable line without key : %s" % line) return k, v def _record_pair(self, k, _v): v = _v.strip(' "') if k == 'Device': self.device_names.append(v) self.devices.append({k: v}) else: try: self.devices[-1][k] = v except IndexError: raise ParseException("Parsing Error for no heading Device-name \ of (key, value) pair: (%s, %s)" % (k, v))
[docs] def get_device_state(self, device_name): """ Return the state value of the given device_name. Return None for unexist device_name or no state value. """ device_info = self.data.get(device_name) return device_info.get('state') if device_info else None