def test_att_parser(self):
        parser = LVMAttributeParser()
        attributes = parser.pv_attributes(PV)
        self.assertEquals(attributes, PV_EXPECTED)
        attributes = parser.vg_attributes(EL6_VG)
        self.assertEquals(attributes, EL6_VG_EXPECTED)
        attributes = parser.lv_attributes(RHEL63_LV)
        self.assertEquals(attributes, RHEL63_LV_EXPECTED)
        attributes = parser.lv_attributes(RHEL68_LV)
        self.assertEquals(attributes, RHEL68_LV_EXPECTED)
        attributes = parser.lv_attributes(UBUNTU_LV)
        self.assertEquals(attributes, UBUNTU_LV_EXPECTED)
        attributes = parser.lv_attributes(SKIP_ACTIVATION)
        self.assertEquals(attributes, SKIP_ACTIVATION_EXPECTED)

        for k, v in VG_PERMISSIONS.items():
            self.assertEquals(parser.vg_permissions(k), v)
        for k, v in VG_ALLOCATION_POLICY.items():
            self.assertEquals(parser.vg_allocation_policy(k), v)
        for k, v in VG_CLUSTER.items():
            self.assertEquals(parser.vg_cluster(k), v)

        for k, v in LV_VOLUME_TYPE.items():
            self.assertEquals(parser.lv_volume_type(k), v)
        for k, v in LV_PERMISSIONS.items():
            self.assertEquals(parser.lv_permissions(k), v)
        for k, v in LV_ALLOCATION_POLICY.items():
            self.assertEquals(parser.lv_allocation_policy(k), v)
        for k, v in LV_STATE.items():
            self.assertEquals(parser.lv_state(k), v)
        for k, v in LV_DEVICE.items():
            self.assertEquals(parser.lv_device(k), v)
        for k, v in LV_TARGET_TYPE.items():
            self.assertEquals(parser.lv_target_type(k), v)
        for k, v in LV_HEALTH.items():
            self.assertEquals(parser.lv_health(k), v)
    def test_att_parser(self):
        parser = LVMAttributeParser()
        attributes = parser.pv_attributes(PV)
        self.assertEquals(attributes, PV_EXPECTED)
        attributes = parser.vg_attributes(EL6_VG)
        self.assertEquals(attributes, EL6_VG_EXPECTED)
        attributes = parser.lv_attributes(RHEL63_LV)
        self.assertEquals(attributes, RHEL63_LV_EXPECTED)
        attributes = parser.lv_attributes(RHEL68_LV)
        self.assertEquals(attributes, RHEL68_LV_EXPECTED)
        attributes = parser.lv_attributes(UBUNTU_LV)
        self.assertEquals(attributes, UBUNTU_LV_EXPECTED)
        attributes = parser.lv_attributes(SKIP_ACTIVATION)
        self.assertEquals(attributes, SKIP_ACTIVATION_EXPECTED)

        for k, v in VG_PERMISSIONS.items():
            self.assertEquals(parser.vg_permissions(k), v)
        for k, v in VG_ALLOCATION_POLICY.items():
            self.assertEquals(parser.vg_allocation_policy(k), v)
        for k, v in VG_CLUSTER.items():
            self.assertEquals(parser.vg_cluster(k), v)

        for k, v in LV_VOLUME_TYPE.items():
            self.assertEquals(parser.lv_volume_type(k), v)
        for k, v in LV_PERMISSIONS.items():
            self.assertEquals(parser.lv_permissions(k), v)
        for k, v in LV_ALLOCATION_POLICY.items():
            self.assertEquals(parser.lv_allocation_policy(k), v)
        for k, v in LV_STATE.items():
            self.assertEquals(parser.lv_state(k), v)
        for k, v in LV_DEVICE.items():
            self.assertEquals(parser.lv_device(k), v)
        for k, v in LV_TARGET_TYPE.items():
            self.assertEquals(parser.lv_target_type(k), v)
        for k, v in LV_HEALTH.items():
            self.assertEquals(parser.lv_health(k), v)
Пример #3
0
class lvm(CommandPlugin):

    deviceProperties = CommandPlugin.deviceProperties + (
        'zIgnoreUnmounted',
    )

    """
    /usr/bin/fdisk -l  | grep '^Disk' | grep -v 'mapper\|identifier\|label' | awk '{gsub(":","");print $2" "$5}'
    /usr/bin/sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name;
    /usr/bin/sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid;
    /usr/bin/sudo lvs --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin

    sample output:
    HD
    /dev/sda 21474836480
    /dev/sdb 21474836480
    /dev/sdc 21474836480
    /dev/sdd 21474836480
    PV         Fmt  Attr PSize       PFree       PV UUID                                VG
    /dev/sda2  lvm2 a--  20946354176    41943040 hctl0n-t76R-AdMs-FG1x-IUxG-hbTi-FZlhXG centos
    /dev/sdb1  lvm2 a--  21470642176           0 KN4g1e-iko0-Zn9E-8jkZ-q7oE-cHZO-dEhGM2 fileserver
    /dev/sdc1  lvm2 a--  21470642176  9655287808 ee1vfJ-qMiy-td19-p8re-lrqj-WSGB-xXRUky fileserver
    /dev/sdd1  lvm2 ---  10737418240 10737418240 vgg70r-2swz-iOiy-L8V7-PITB-e4Gy-DkUlMe
    /dev/sdd2  lvm2 ---  10736369664 10736369664 d2FDsD-Y5nV-w7rU-nJL7-qPk0-dskC-3vLOJ0
    VG         #PV #LV #SN Attr   VSize       VFree
    centos       1   2   0 wz--n- 20946354176    41943040
    fileserver   2   3   0 wz--n- 42941284352 15023996928
    LV     VG         Attr       LSize       Active
    root   centos     -wi-ao---- 18756927488 active
    swap   centos     -wi-ao----  2147483648 active
    backup fileserver -wi-ao----  5368709120 active
    media  fileserver -wi-ao----  1073741824 active
    share  fileserver -wi-ao---- 21474836480 active
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    fd0 2:0 1 4096 0 disk
    sda 8:0 0 21474836480 0 disk
    sda1 8:1 0 524288000 0 part /boot
    sda2 8:2 0 20949499904 0 part
    centos-root 253:0 0 18756927488 0 lvm /
    centos-swap 253:1 0 2147483648 0 lvm [SWAP]
    sdb 8:16 0 21474836480 0 disk
    sdb1 8:17 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    sdc 8:32 0 21474836480 0 disk
    sdc1 8:33 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-snap-cow 253:4 0 5368709120 0 lvm
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-backup 253:6 0 5368709120 0 lvm /var/backup
    fileserver-media 253:7 0 1073741824 0 lvm /var/media
    fileserver-inactive 253:8 0 5368709120 0 lvm
    sdd 8:48 0 21474836480 0 disk
    sdd1 8:49 0 21473787904 0 part
    sr0 11:0 1 63019008 0 rom

    MAJ:MIN can be used for diskstats
    """

    command = ('export PATH=/bin:/sbin:/usr/bin:/usr/sbin; '
               'lsblk -rb 2>&1; '
               'sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name 2>&1; '
               'sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid 2>&1; '
               'if command -v thin_check >/dev/null 2>&1; then '
               '''sudo lvs --separator ' '  --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin,lv_metadata_size,pool_lv; else '''
               '''sudo lvs --separator ' '  --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin; fi; '''
               'echo "DISK_BY_ID  LINK" 2>&1; '
               'find /dev/disk/by-id -type l ! -name "*-part*" -printf "%P %l\\n" 2>&1'
               )

    def process(self, device, results, log):
        ignore_unmounted = getattr(device, 'zIgnoreUnmounted', None)
        hd_maps = []
        pv_maps = []
        vg_maps = []
        lv_maps = []
        sv_maps = []
        lsblk_dict = {}
        self.lvm_parser = LVMAttributeParser()
        section = ''
        hd_re = re.compile('(?P<disk>\S+) (?P<size>\d+)')
        dev_blk_re = re.compile(
            '(?P<device_block>.*)'        # Block Devices
            '\s+(?P<major_minor>\d+:\d+)' # Blk Major/Minor
            '\s+\d+\s+'                   # RM number
            '(?P<size>\d+)'               # Size
            '\s+\d+\s+'                   # RO number
            '(?P<type>\w+)'               # Block Type
            '\s*'                         # Unlimited space
            '(?P<mount>\S*)')             # Mount point
        pv_re = re.compile(
            '(?P<pv_name>\S+)'
            '\s*(?P<pv_fmt>\S+)'
            '\s*(?P<pv_attr>\S+)'
            '\s*(?P<pv_size>\d+)'
            '\s*(?P<pv_free>\d+)'
            '\s*(?P<pv_uuid>\S+)'
            '\s*(?P<vg_name>\S*)')
        vg_re = re.compile(
            '(?P<vg_name>\S+)'
            '\s*(?P<vg_attr>\S+)'
            '\s*(?P<vg_size>\d+)'
            '\s*(?P<vg_free>\d+)'
            '\s*(?P<vg_uuid>\S+)')
        lv_re = re.compile(
            '(?P<lv_name>\S+)'
            '\s*(?P<vg_name>\S+)'
            '\s*(?P<lv_attr>\S+)'
            '\s*(?P<lv_size>\d+)'
            '\s*(?P<lv_uuid>\S+)'
            '\s?(?P<origin>\S*)'
            '\s?(?P<lv_metadata_size>\d*)'
            '\s?(?P<pool_lv>\S*)')
        by_id_re = re.compile(
            '(?P<disk_id>\S+)'            # the id label
            '\s*\.\./\.\./'               # the ../../ prefix to the link
            '\s*(?P<disk_name>\S*)')      # the block device name

        parse_re = {'HD': hd_re,
                    'PV': pv_re,
                    'VG': vg_re,
                    'LV': lv_re,
                    'NAME': dev_blk_re,
                    'DISK_BY_ID': by_id_re}

        disk_by_id_map = defaultdict(list)
        for line in results.split('\n'):
            if self.checkErr(line):
                return []
            res = line.split()
            if not res:
                continue
            if res[0] in parse_re.keys():
                section = res[0]
                continue
            try:
                columns = parse_re[section].match(line.strip()).groupdict()
            except (AttributeError, Exception):
                continue

            if section == 'PV':
                pv_om = self.makePVMap(columns)
                pv_maps.append(pv_om)
                for hd_om in hd_maps:
                    if hd_om.title == pv_om.title.split('/')[-1]:
                        pv_om.harddisk_id = hd_om.id
            elif section == 'VG':
                vg_maps.append(self.makeVGMap(columns))
            elif section == 'LV':
                lv_om = self.makeLVMap(columns)
                if lv_om.relname == 'snapshotVolumes':
                    sv_maps.append(lv_om)
                else:
                    lv_maps.append(lv_om)
            elif section == 'NAME':
                # device block can be 'vg_name-lv_name' or 'vg_name-lv_name (DM-X)' format
                # depending on linux flavor
                columns = {col[0]: col[1].strip() for col in columns.items()}
                device_block = columns['device_block'].split()[0]
                lsblk_dict[device_block] = {}
                lsblk_dict[device_block]['mount'] = columns['mount']
                lsblk_dict[device_block]['major_minor'] = columns['major_minor']
                if any(columns['device_block'] == om.title for om in hd_maps):
                    continue
                if columns['type'] in ('disk', 'lvm', 'part', 'raid1'):
                    if columns['mount'] or not ignore_unmounted:
                        hd_maps.append(self.makeHDMap(columns))
            elif section == 'DISK_BY_ID':
                # Collect the disk_by_id map first. Process outside of loop.
                device_block = columns.get('disk_name')
                disk_by_id_map[device_block].append(columns.get('disk_id'))

        # disk-id's to the disk assocations
        plain_disk_re = re.compile('disk-'
                                   '(?P<disk_name>[a-z]{3})'
                                   '$'
                                   )
        dm_disk_re = re.compile('disk-'
                                '[\w_.\-]*'
                                '\('
                                '(?P<disk_name>dm-[\d]+)'
                                '\)$'
                                )
        # Set disk-id's here on hd_maps
        for hd_om in hd_maps:
            match = plain_disk_re.match(hd_om.id)
            if match:
                hd_om.disk_ids = disk_by_id_map[match.group('disk_name')]
            else:
                match = dm_disk_re.match(hd_om.id)
                if match:
                    hd_om.disk_ids = disk_by_id_map[match.group('disk_name')]


            if hasattr(hd_om, 'disk_ids'):
                for id in hd_om.disk_ids:
                    if id.startswith('wwn-0x') and len(id) == 38:
                        # add 30 bytes of likely uuid to disk_ids
                        # to simplify uuid search on CiscoUCS side
                        # because Windows hard disk would chop off
                        # the first 2 bytes
                        disk_id = id[8:]
                        if disk_id not in hd_om.disk_ids:
                            hd_om.disk_ids.append(disk_id)
                    elif id.find('_') > -1:
                        # add the likely disk serial number to disk_ids
                        # for serial number search on CiscoUCS side
                        # 'scsi-SATA_INTEL_SSDSC2BB1PHWA616003QY120CGN',
                        # 'ata-INTEL_SSDSC2BB120G6K_PHWA616003QY120CGN'
                        # add the part right of the last '_'
                        disk_id = id[id.rfind('_') + 1:].upper()
                        if disk_id not in hd_om.disk_ids:
                            hd_om.disk_ids.append(disk_id)

        maps = []
        maps.append(RelationshipMap(
            relname="volumeGroups",
            modname="ZenPacks.zenoss.LinuxMonitor.VolumeGroup",
            objmaps=vg_maps))

        maps.append(RelationshipMap(
            compname='hw',
            relname='harddisks',
            modname="ZenPacks.zenoss.LinuxMonitor.HardDisk",
            objmaps=hd_maps))

        maps.append(RelationshipMap(
            relname="physicalVolumes",
            modname="ZenPacks.zenoss.LinuxMonitor.PhysicalVolume",
            objmaps=pv_maps))

        for vg_om in vg_maps:
            lv_vg_oms = []
            tp_vg_oms = []
            compname = 'volumeGroups/' + vg_om.id
            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    # LVM delimits VG-LV with a hyphen. To unambiguously handle
                    # LVs and VGs with hyphens in their name, it doubles
                    # hypens in the LV and VG names. We have to do the same.
                    device_block = '{}-{}'.format(
                        lv_om.vgname.replace('-', '--'),
                        lv_om.title.replace('-', '--'))

                    try:
                        lv_om.mountpoint = lsblk_dict[device_block]['mount']
                        lv_om.major_minor = lsblk_dict[device_block]['major_minor']
                    except KeyError:
                        # device block not found
                        log.debug('device block {} not found for logical volume {} in volume group {}'
                                  .format(lv_om.vgname+'-'+lv_om.title, lv_om.title, lv_om.vgname))
                    if  lv_om.modname == 'ZenPacks.zenoss.LinuxMonitor.ThinPool':
                        tp_vg_oms.append(lv_om)
                    else:
                        lv_vg_oms.append(lv_om)
            maps.append(RelationshipMap(
                relname="logicalVolumes",
                compname=compname,
                modname="ZenPacks.zenoss.LinuxMonitor.LogicalVolume",
                objmaps=lv_vg_oms))
            maps.append(RelationshipMap(
                relname="thinPools",
                compname=compname,
                modname="ZenPacks.zenoss.LinuxMonitor.ThinPool",
                objmaps=tp_vg_oms))

            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    lv_sv_oms = []
                    for sv_om in sv_maps:
                        if sv_om.origin == lv_om.title:
                            device_block = '{}-{}'.format(
                                sv_om.vgname.replace('-', '--'),
                                sv_om.title.replace('-', '--'))
                            try:
                                sv_om.mountpoint = lsblk_dict[device_block]['mount']
                                sv_om.major_minor = lsblk_dict[device_block]['major_minor']
                            except KeyError:
                                # device block not found
                                log.debug('device block {} not found for snapshot volume {} in volume group {}'
                                          .format(sv_om.vgname+'-'+sv_om.title, sv_om.title, sv_om.vgname))
                            lv_sv_oms.append(sv_om)
                    maps.append(RelationshipMap(
                        relname="snapshotVolumes",
                        compname=compname + '/logicalVolumes/' + lv_om.id,
                        modname="ZenPacks.zenoss.LinuxMonitor.SnapshotVolume",
                        objmaps=lv_sv_oms))
        return maps

    def makeHDMap(self, columns):
        hd_om = ObjectMap()
        hd_om.title = columns['device_block']
        hd_om.id = 'disk-{}'.format(self.prepId(
            columns['device_block'].replace(' ', '_')))
        hd_om.major_minor = columns['major_minor']
        hd_om.mount = columns['mount']
        hd_om.size = int(columns['size'])
        hd_om.relname = 'harddisks'
        hd_om.modname = 'ZenPacks.zenoss.LinuxMonitor.HardDisk'
        return hd_om

    def makePVMap(self, columns):
        # pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name
        pv_om = ObjectMap()
        pv_om.title = columns['pv_name']
        pv_om.id = 'pv-{}'.format(self.prepId(columns['pv_name']))
        pv_om.format = columns['pv_fmt']
        pv_om.attributes = self.lvm_parser.pv_attributes(columns['pv_attr'])
        pv_om.uuid = columns['pv_uuid']
        pv_om.set_volumeGroup = 'vg-{}'.format(columns['vg_name']) if columns['vg_name'] else ''
        pv_om.relname = 'physicalVolumes'
        pv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.PhysicalVolume'
        return pv_om

    def makeVGMap(self, columns):
        # vg_name,vg_attr,vg_size,vg_free,vg_uuid
        vg_om = ObjectMap()
        vg_om.title = columns['vg_name']
        vg_om.id = 'vg-{}'.format(self.prepId(columns['vg_name']))
        vg_om.attributes = self.lvm_parser.vg_attributes(columns['vg_attr'])
        vg_om.uuid = columns['vg_uuid']
        vg_om.relname = 'volumeGroups'
        vg_om.modname = 'ZenPacks.zenoss.LinuxMonitor.VolumeGroup'
        return vg_om

    def makeLVMap(self, columns):
        # lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin
        lv_om = ObjectMap()
        lv_om.title = columns['lv_name']
        lv_om.vgname = columns['vg_name']
        lv_om.id = 'lv-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['lv_name']))
        lv_om.attributes = self.lvm_parser.lv_attributes(columns['lv_attr'])
        lv_om.lvsize = int(columns['lv_size'])
        lv_om.uuid = columns['lv_uuid']
        if columns['origin']:
            lv_om.origin = columns['origin']
            lv_om.relname = 'snapshotVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.SnapshotVolume'
        elif columns['lv_metadata_size']:
            lv_om.id = 'tp-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['lv_name']))
            lv_om.metadatasize = int(columns['lv_metadata_size'])
            lv_om.relname = 'thinPools'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.ThinPool'
        else:
            lv_om.set_thinPool = None
            if columns['pool_lv']:
                lv_om.set_thinPool = 'tp-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['pool_lv']))
            lv_om.relname = 'logicalVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.LogicalVolume'
        return lv_om

    def checkErr(self, line):
        if 'no tty present' in line or 'sudo: sorry, you must have a tty to run sudo' in line:
            log.warning('No tty present.  Ensure that user is sudo and change sudo settings to disable requiretty for your user account.')
            return True
        return False
Пример #4
0
class lvm(CommandPlugin):

    deviceProperties = CommandPlugin.deviceProperties + ('zIgnoreUnmounted', )
    """
    /usr/bin/fdisk -l  | grep '^Disk' | grep -v 'mapper\|identifier\|label' | awk '{gsub(":","");print $2" "$5}'
    /usr/bin/sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name;
    /usr/bin/sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid;
    /usr/bin/sudo lvs --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin

    sample output:
    HD
    /dev/sda 21474836480
    /dev/sdb 21474836480
    /dev/sdc 21474836480
    /dev/sdd 21474836480
    PV         Fmt  Attr PSize       PFree       PV UUID                                VG
    /dev/sda2  lvm2 a--  20946354176    41943040 hctl0n-t76R-AdMs-FG1x-IUxG-hbTi-FZlhXG centos
    /dev/sdb1  lvm2 a--  21470642176           0 KN4g1e-iko0-Zn9E-8jkZ-q7oE-cHZO-dEhGM2 fileserver
    /dev/sdc1  lvm2 a--  21470642176  9655287808 ee1vfJ-qMiy-td19-p8re-lrqj-WSGB-xXRUky fileserver
    /dev/sdd1  lvm2 ---  10737418240 10737418240 vgg70r-2swz-iOiy-L8V7-PITB-e4Gy-DkUlMe
    /dev/sdd2  lvm2 ---  10736369664 10736369664 d2FDsD-Y5nV-w7rU-nJL7-qPk0-dskC-3vLOJ0
    VG         #PV #LV #SN Attr   VSize       VFree
    centos       1   2   0 wz--n- 20946354176    41943040
    fileserver   2   3   0 wz--n- 42941284352 15023996928
    LV     VG         Attr       LSize       Active
    root   centos     -wi-ao---- 18756927488 active
    swap   centos     -wi-ao----  2147483648 active
    backup fileserver -wi-ao----  5368709120 active
    media  fileserver -wi-ao----  1073741824 active
    share  fileserver -wi-ao---- 21474836480 active
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    fd0 2:0 1 4096 0 disk
    sda 8:0 0 21474836480 0 disk
    sda1 8:1 0 524288000 0 part /boot
    sda2 8:2 0 20949499904 0 part
    centos-root 253:0 0 18756927488 0 lvm /
    centos-swap 253:1 0 2147483648 0 lvm [SWAP]
    sdb 8:16 0 21474836480 0 disk
    sdb1 8:17 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    sdc 8:32 0 21474836480 0 disk
    sdc1 8:33 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-snap-cow 253:4 0 5368709120 0 lvm
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-backup 253:6 0 5368709120 0 lvm /var/backup
    fileserver-media 253:7 0 1073741824 0 lvm /var/media
    fileserver-inactive 253:8 0 5368709120 0 lvm
    sdd 8:48 0 21474836480 0 disk
    sdd1 8:49 0 21473787904 0 part
    sr0 11:0 1 63019008 0 rom

    MAJ:MIN can be used for diskstats
    """

    command = (
        'export PATH=/bin:/sbin:/usr/bin:/usr/sbin;'
        'lsblk -rb 2>&1; '
        'sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name 2>&1; '
        'sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid 2>&1; '
        'sudo lvs --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin 2>&1 '
    )

    def process(self, device, results, log):
        ignore_unmounted = getattr(device, 'zIgnoreUnmounted', None)
        hd_maps = []
        pv_maps = []
        vg_maps = []
        lv_maps = []
        sv_maps = []
        lsblk_dict = {}
        self.lvm_parser = LVMAttributeParser()
        section = ''
        hd_re = re.compile('(?P<disk>\S+) (?P<size>\d+)')
        dev_blk_re = re.compile(
            '(?P<device_block>.*)\s+(?P<major_minor>\d+:\d+)\s+\d+\s+(?P<size>\d+)\s+\d+\s+(?P<type>\w+)\s*(?P<mount>\S*)'
        )
        pv_re = re.compile(
            '\s*(?P<pv_name>\S+)\s*(?P<pv_fmt>\S+)\s*(?P<pv_attr>\S+)\s*(?P<pv_size>\S+)'
            '\s*(?P<pv_free>\S+)\s*(?P<pv_uuid>\S+)\s*(?P<vg_name>\S*)')
        vg_re = re.compile(
            '\s*(?P<vg_name>\S+)\s*(?P<vg_attr>\S+)\s*(?P<vg_size>\S+)\s*(?P<vg_free>\S+)\s*(?P<vg_uuid>\S+)'
        )
        lv_re = re.compile(
            '\s*(?P<lv_name>\S+)\s*(?P<vg_name>\S+)\s*(?P<lv_attr>\S+)\s*(?P<lv_size>\S+)\s*(?P<lv_uuid>\S+)\s*(?P<origin>\S*)'
        )
        parse_re = {
            'HD': hd_re,
            'PV': pv_re,
            'VG': vg_re,
            'LV': lv_re,
            'NAME': dev_blk_re
        }
        for line in results.split('\n'):
            if self.checkErr(line):
                return []
            res = line.split()
            if not res:
                continue
            if res[0] in parse_re.keys():
                section = res[0]
                continue
            try:
                columns = parse_re[section].match(line).groupdict()
            except (AttributeError, Exception):
                continue

            if section == 'PV':
                pv_om = self.makePVMap(columns)
                pv_maps.append(pv_om)
                for hd_om in hd_maps:
                    if hd_om.title == pv_om.title.split('/')[-1]:
                        pv_om.harddisk_id = hd_om.id
            elif section == 'VG':
                vg_maps.append(self.makeVGMap(columns))
            elif section == 'LV':
                lv_om = self.makeLVMap(columns)
                if lv_om.relname == 'snapshotVolumes':
                    sv_maps.append(lv_om)
                else:
                    lv_maps.append(lv_om)
            elif section == 'NAME':
                # device block can be 'vg_name-lv_name' or 'vg_name-lv_name (DM-X)' format
                # depending on linux flavor
                columns = {col[0]: col[1].strip() for col in columns.items()}
                device_block = columns['device_block'].split()[0]
                lsblk_dict[device_block] = {}
                lsblk_dict[device_block]['mount'] = columns['mount']
                lsblk_dict[device_block]['major_minor'] = columns[
                    'major_minor']
                if any(columns['device_block'] == om.title for om in hd_maps):
                    continue
                if columns['type'] in ('disk', 'lvm', 'part', 'raid1'):
                    if columns['mount'] or not ignore_unmounted:
                        hd_maps.append(self.makeHDMap(columns))

        maps = []
        maps.append(
            RelationshipMap(relname="volumeGroups",
                            modname="ZenPacks.zenoss.LinuxMonitor.VolumeGroup",
                            objmaps=vg_maps))

        maps.append(
            RelationshipMap(compname='hw',
                            relname='harddisks',
                            modname="ZenPacks.zenoss.LinuxMonitor.HardDisk",
                            objmaps=hd_maps))

        maps.append(
            RelationshipMap(
                relname="physicalVolumes",
                modname="ZenPacks.zenoss.LinuxMonitor.PhysicalVolume",
                objmaps=pv_maps))

        for vg_om in vg_maps:
            lv_vg_oms = []
            compname = 'volumeGroups/' + vg_om.id
            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    # LVM delimits VG-LV with a hyphen. To unambiguously handle
                    # LVs and VGs with hyphens in their name, it doubles
                    # hypens in the LV and VG names. We have to do the same.
                    device_block = '{}-{}'.format(
                        lv_om.vgname.replace('-', '--'),
                        lv_om.title.replace('-', '--'))

                    try:
                        lv_om.mountpoint = lsblk_dict[device_block]['mount']
                        lv_om.major_minor = lsblk_dict[device_block][
                            'major_minor']
                    except KeyError:
                        # device block not found
                        log.debug(
                            'device block {} not found for logical volume {} in volume group {}'
                            .format(lv_om.vgname + '-' + lv_om.title,
                                    lv_om.title, lv_om.vgname))
                    lv_vg_oms.append(lv_om)
            maps.append(
                RelationshipMap(
                    relname="logicalVolumes",
                    compname=compname,
                    modname="ZenPacks.zenoss.LinuxMonitor.LogicalVolume",
                    objmaps=lv_vg_oms))

            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    lv_sv_oms = []
                    for sv_om in sv_maps:
                        if sv_om.origin == lv_om.title:
                            device_block = '{}-{}'.format(
                                sv_om.vgname.replace('-', '--'),
                                sv_om.title.replace('-', '--'))
                            try:
                                sv_om.mountpoint = lsblk_dict[device_block][
                                    'mount']
                                sv_om.major_minor = lsblk_dict[device_block][
                                    'major_minor']
                            except KeyError:
                                # device block not found
                                log.debug(
                                    'device block {} not found for snapshot volume {} in volume group {}'
                                    .format(sv_om.vgname + '-' + sv_om.title,
                                            sv_om.title, sv_om.vgname))
                            lv_sv_oms.append(sv_om)
                    maps.append(
                        RelationshipMap(
                            relname="snapshotVolumes",
                            compname=compname + '/logicalVolumes/' + lv_om.id,
                            modname=
                            "ZenPacks.zenoss.LinuxMonitor.SnapshotVolume",
                            objmaps=lv_sv_oms))
        return maps

    def makeHDMap(self, columns):
        hd_om = ObjectMap()
        hd_om.title = columns['device_block']
        hd_om.id = 'disk-{}'.format(
            self.prepId(columns['device_block'].replace(' ', '_')))
        hd_om.major_minor = columns['major_minor']
        hd_om.mount = columns['mount']
        hd_om.size = int(columns['size'])
        hd_om.relname = 'harddisks'
        hd_om.modname = 'ZenPacks.zenoss.LinuxMonitor.HardDisk'
        return hd_om

    def makePVMap(self, columns):
        # pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name
        pv_om = ObjectMap()
        pv_om.title = columns['pv_name']
        pv_om.id = 'pv-{}'.format(self.prepId(columns['pv_name']))
        pv_om.format = columns['pv_fmt']
        pv_om.attributes = self.lvm_parser.pv_attributes(columns['pv_attr'])
        pv_om.uuid = columns['pv_uuid']
        pv_om.set_volumeGroup = 'vg-{}'.format(
            columns['vg_name']) if columns['vg_name'] else ''
        pv_om.relname = 'physicalVolumes'
        pv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.PhysicalVolume'
        return pv_om

    def makeVGMap(self, columns):
        # vg_name,vg_attr,vg_size,vg_free,vg_uuid
        vg_om = ObjectMap()
        vg_om.title = columns['vg_name']
        vg_om.id = 'vg-{}'.format(self.prepId(columns['vg_name']))
        vg_om.attributes = self.lvm_parser.vg_attributes(columns['vg_attr'])
        vg_om.uuid = columns['vg_uuid']
        vg_om.relname = 'volumeGroups'
        vg_om.modname = 'ZenPacks.zenoss.LinuxMonitor.VolumeGroup'
        return vg_om

    def makeLVMap(self, columns):
        # lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin
        lv_om = ObjectMap()
        lv_om.title = columns['lv_name']
        lv_om.vgname = columns['vg_name']
        lv_om.id = 'lv-{}'.format(
            self.prepId(columns['vg_name']) + '_' +
            self.prepId(columns['lv_name']))
        lv_om.attributes = self.lvm_parser.lv_attributes(columns['lv_attr'])
        lv_om.lvsize = int(columns['lv_size'])
        lv_om.uuid = columns['lv_uuid']
        if columns['origin']:
            lv_om.origin = columns['origin']
            lv_om.relname = 'snapshotVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.SnapshotVolume'
        else:
            lv_om.relname = 'logicalVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.LogicalVolume'
        return lv_om

    def checkErr(self, line):
        if 'no tty present' in line or 'sudo: sorry, you must have a tty to run sudo' in line:
            log.warning(
                'No tty present.  Ensure that user is sudo and change sudo settings to disable requiretty for your user account.'
            )
            return True
        return False
Пример #5
0
class lvm(CommandPlugin):

    deviceProperties = CommandPlugin.deviceProperties + (
        'zIgnoreUnmounted',
    )

    """
    /usr/bin/fdisk -l  | grep '^Disk' | grep -v 'mapper\|identifier\|label' | awk '{gsub(":","");print $2" "$5}'
    /usr/bin/sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name;
    /usr/bin/sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid;
    /usr/bin/sudo lvs --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin

    sample output:
    HD
    /dev/sda 21474836480
    /dev/sdb 21474836480
    /dev/sdc 21474836480
    /dev/sdd 21474836480
    PV         Fmt  Attr PSize       PFree       PV UUID                                VG
    /dev/sda2  lvm2 a--  20946354176    41943040 hctl0n-t76R-AdMs-FG1x-IUxG-hbTi-FZlhXG centos
    /dev/sdb1  lvm2 a--  21470642176           0 KN4g1e-iko0-Zn9E-8jkZ-q7oE-cHZO-dEhGM2 fileserver
    /dev/sdc1  lvm2 a--  21470642176  9655287808 ee1vfJ-qMiy-td19-p8re-lrqj-WSGB-xXRUky fileserver
    /dev/sdd1  lvm2 ---  10737418240 10737418240 vgg70r-2swz-iOiy-L8V7-PITB-e4Gy-DkUlMe
    /dev/sdd2  lvm2 ---  10736369664 10736369664 d2FDsD-Y5nV-w7rU-nJL7-qPk0-dskC-3vLOJ0
    VG         #PV #LV #SN Attr   VSize       VFree
    centos       1   2   0 wz--n- 20946354176    41943040
    fileserver   2   3   0 wz--n- 42941284352 15023996928
    LV     VG         Attr       LSize       Active
    root   centos     -wi-ao---- 18756927488 active
    swap   centos     -wi-ao----  2147483648 active
    backup fileserver -wi-ao----  5368709120 active
    media  fileserver -wi-ao----  1073741824 active
    share  fileserver -wi-ao---- 21474836480 active
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    fd0 2:0 1 4096 0 disk
    sda 8:0 0 21474836480 0 disk
    sda1 8:1 0 524288000 0 part /boot
    sda2 8:2 0 20949499904 0 part
    centos-root 253:0 0 18756927488 0 lvm /
    centos-swap 253:1 0 2147483648 0 lvm [SWAP]
    sdb 8:16 0 21474836480 0 disk
    sdb1 8:17 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    sdc 8:32 0 21474836480 0 disk
    sdc1 8:33 0 21473787904 0 part
    fileserver-share-real 253:2 0 21474836480 0 lvm
    fileserver-share 253:3 0 21474836480 0 lvm /var/share
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-snap-cow 253:4 0 5368709120 0 lvm
    fileserver-snap 253:5 0 21474836480 0 lvm
    fileserver-backup 253:6 0 5368709120 0 lvm /var/backup
    fileserver-media 253:7 0 1073741824 0 lvm /var/media
    fileserver-inactive 253:8 0 5368709120 0 lvm
    sdd 8:48 0 21474836480 0 disk
    sdd1 8:49 0 21473787904 0 part
    sr0 11:0 1 63019008 0 rom

    MAJ:MIN can be used for diskstats
    """

    command = ('export PATH=/bin:/sbin:/usr/bin:/usr/sbin; '
               'lsblk -rb 2>&1; '
               'sudo pvs --units b --nosuffix -o pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name 2>&1; '
               'sudo vgs --units b --nosuffix -o vg_name,vg_attr,vg_size,vg_free,vg_uuid 2>&1; '
               'if command -v thin_check >/dev/null 2>&1; then '
               '''sudo lvs --separator ' ' --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin,lv_metadata_size,pool_lv 2>&1; else '''
               '''sudo lvs --separator ' ' --units b --nosuffix -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin 2>&1; fi; '''
               'echo "DISK_BY_ID  LINK" 2>&1; '
               'find /dev/disk/by-id -type l ! -name "*-part*" -printf "%P %l\\n" 2>&1'
               )

    def process(self, device, results, log):
        ignore_unmounted = getattr(device, 'zIgnoreUnmounted', None)
        hd_maps = []
        pv_maps = []
        vg_maps = []
        lv_maps = []
        sv_maps = []
        lsblk_dict = {}
        self.lvm_parser = LVMAttributeParser()
        section = ''
        hd_re = re.compile('(?P<disk>\S+) (?P<size>\d+)')
        dev_blk_re = re.compile(
            '(?P<device_block>.*)'        # Block Devices
            '\s+(?P<major_minor>\d+:\d+)' # Blk Major/Minor
            '\s+\d+\s+'                   # RM number
            '(?P<size>\d+)'               # Size
            '\s+\d+\s+'                   # RO number
            '(?P<type>\w+)'               # Block Type
            '\s*'                         # Unlimited space
            '(?P<mount>\S*)')             # Mount point
        pv_re = re.compile(
            '(?P<pv_name>\S+)'
            '\s*(?P<pv_fmt>\S+)'
            '\s*(?P<pv_attr>\S+)'
            '\s*(?P<pv_size>\d+)'
            '\s*(?P<pv_free>\d+)'
            '\s*(?P<pv_uuid>\S+)'
            '\s*(?P<vg_name>\S*)')
        vg_re = re.compile(
            '(?P<vg_name>\S+)'
            '\s*(?P<vg_attr>\S+)'
            '\s*(?P<vg_size>\d+)'
            '\s*(?P<vg_free>\d+)'
            '\s*(?P<vg_uuid>\S+)')
        lv_re = re.compile(
            '(?P<lv_name>\S+)'
            '\s*(?P<vg_name>\S+)'
            '\s*(?P<lv_attr>\S+)'
            '\s*(?P<lv_size>\d+)'
            '\s*(?P<lv_uuid>\S+)'
            '\s?(?P<origin>\S*)'
            '\s?(?P<lv_metadata_size>\d*)'
            '\s?(?P<pool_lv>\S*)')
        by_id_re = re.compile(
            '(?P<disk_id>\S+)'            # the id label
            '\s*\.\./\.\./'               # the ../../ prefix to the link
            '\s*(?P<disk_name>\S*)')      # the block device name

        parse_re = {'HD': hd_re,
                    'PV': pv_re,
                    'VG': vg_re,
                    'LV': lv_re,
                    'NAME': dev_blk_re,
                    'DISK_BY_ID': by_id_re}

        disk_by_id_map = defaultdict(list)
        for line in results.split('\n'):
            if self.checkErr(line):
                return []
            res = line.split()
            if not res:
                continue
            if res[0] in parse_re.keys():
                section = res[0]
                continue
            try:
                columns = parse_re[section].match(line.strip()).groupdict()
            except (AttributeError, Exception):
                continue

            if section == 'PV':
                pv_om = self.makePVMap(columns)
                pv_maps.append(pv_om)
                for hd_om in hd_maps:
                    if hd_om.title == pv_om.title.split('/')[-1]:
                        pv_om.harddisk_id = hd_om.id
            elif section == 'VG':
                vg_maps.append(self.makeVGMap(columns))
            elif section == 'LV':
                lv_om = self.makeLVMap(columns)
                if lv_om.relname == 'snapshotVolumes':
                    sv_maps.append(lv_om)
                else:
                    lv_maps.append(lv_om)
            elif section == 'NAME':
                # device block can be 'vg_name-lv_name' or 'vg_name-lv_name (DM-X)' format
                # depending on linux flavor
                columns = {col[0]: col[1].strip() for col in columns.items()}
                device_block = columns['device_block'].split()[0]
                lsblk_dict[device_block] = {}
                lsblk_dict[device_block]['mount'] = columns['mount']
                lsblk_dict[device_block]['major_minor'] = columns['major_minor']
                if any(columns['device_block'] == om.title for om in hd_maps):
                    continue
                if columns['type'] in ('disk', 'lvm', 'part', 'raid1'):
                    if columns['mount'] or not ignore_unmounted:
                        hd_maps.append(self.makeHDMap(columns))
            elif section == 'DISK_BY_ID':
                # Collect the disk_by_id map first. Process outside of loop.
                device_block = columns.get('disk_name')
                disk_by_id_map[device_block].append(columns.get('disk_id'))

        # disk-id's to the disk assocations
        plain_disk_re = re.compile('disk-'
                                   '(?P<disk_name>[a-z]{3})'
                                   '$'
                                   )
        dm_disk_re = re.compile('disk-'
                                '[\w_.\-]*'
                                '\('
                                '(?P<disk_name>dm-[\d]+)'
                                '\)$'
                                )
        # Set disk-id's here on hd_maps
        for hd_om in hd_maps:
            match = plain_disk_re.match(hd_om.id)
            if match:
                hd_om.disk_ids = disk_by_id_map[match.group('disk_name')]
            else:
                match = dm_disk_re.match(hd_om.id)
                if match:
                    hd_om.disk_ids = disk_by_id_map[match.group('disk_name')]


            if hasattr(hd_om, 'disk_ids'):
                for id in hd_om.disk_ids:
                    if id.startswith('wwn-0x') and len(id) == 38:
                        # add 30 bytes of likely uuid to disk_ids
                        # to simplify uuid search on CiscoUCS side
                        # because Windows hard disk would chop off
                        # the first 2 bytes
                        disk_id = id[8:]
                        if disk_id not in hd_om.disk_ids:
                            hd_om.disk_ids.append(disk_id)
                    elif id.find('_') > -1:
                        # add the likely disk serial number to disk_ids
                        # for serial number search on CiscoUCS side
                        # 'scsi-SATA_INTEL_SSDSC2BB1PHWA616003QY120CGN',
                        # 'ata-INTEL_SSDSC2BB120G6K_PHWA616003QY120CGN'
                        # add the part right of the last '_'
                        disk_id = id[id.rfind('_') + 1:].upper()
                        if disk_id not in hd_om.disk_ids:
                            hd_om.disk_ids.append(disk_id)

        maps = []
        maps.append(RelationshipMap(
            relname="volumeGroups",
            modname="ZenPacks.zenoss.LinuxMonitor.VolumeGroup",
            objmaps=vg_maps))

        maps.append(RelationshipMap(
            compname='hw',
            relname='harddisks',
            modname="ZenPacks.zenoss.LinuxMonitor.HardDisk",
            objmaps=hd_maps))

        maps.append(RelationshipMap(
            relname="physicalVolumes",
            modname="ZenPacks.zenoss.LinuxMonitor.PhysicalVolume",
            objmaps=pv_maps))

        for vg_om in vg_maps:
            lv_vg_oms = []
            tp_vg_oms = []
            compname = 'volumeGroups/' + vg_om.id
            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    # LVM delimits VG-LV with a hyphen. To unambiguously handle
                    # LVs and VGs with hyphens in their name, it doubles
                    # hypens in the LV and VG names. We have to do the same.
                    device_block = '{}-{}'.format(
                        lv_om.vgname.replace('-', '--'),
                        lv_om.title.replace('-', '--'))

                    try:
                        lv_om.mountpoint = lsblk_dict[device_block]['mount']
                        lv_om.major_minor = lsblk_dict[device_block]['major_minor']
                    except KeyError:
                        # device block not found
                        log.debug('device block {} not found for logical volume {} in volume group {}'
                                  .format(lv_om.vgname+'-'+lv_om.title, lv_om.title, lv_om.vgname))
                    if  lv_om.modname == 'ZenPacks.zenoss.LinuxMonitor.ThinPool':
                        tp_vg_oms.append(lv_om)
                    else:
                        lv_vg_oms.append(lv_om)
            maps.append(RelationshipMap(
                relname="logicalVolumes",
                compname=compname,
                modname="ZenPacks.zenoss.LinuxMonitor.LogicalVolume",
                objmaps=lv_vg_oms))
            maps.append(RelationshipMap(
                relname="thinPools",
                compname=compname,
                modname="ZenPacks.zenoss.LinuxMonitor.ThinPool",
                objmaps=tp_vg_oms))

            for lv_om in lv_maps:
                if lv_om.vgname == vg_om.title:
                    lv_sv_oms = []
                    for sv_om in sv_maps:
                        if sv_om.origin == lv_om.title:
                            device_block = '{}-{}'.format(
                                sv_om.vgname.replace('-', '--'),
                                sv_om.title.replace('-', '--'))
                            try:
                                sv_om.mountpoint = lsblk_dict[device_block]['mount']
                                sv_om.major_minor = lsblk_dict[device_block]['major_minor']
                            except KeyError:
                                # device block not found
                                log.debug('device block {} not found for snapshot volume {} in volume group {}'
                                          .format(sv_om.vgname+'-'+sv_om.title, sv_om.title, sv_om.vgname))
                            lv_sv_oms.append(sv_om)
                    maps.append(RelationshipMap(
                        relname="snapshotVolumes",
                        compname=compname + '/logicalVolumes/' + lv_om.id,
                        modname="ZenPacks.zenoss.LinuxMonitor.SnapshotVolume",
                        objmaps=lv_sv_oms))
        return maps

    def makeHDMap(self, columns):
        hd_om = ObjectMap()
        hd_om.title = columns['device_block']
        hd_om.id = 'disk-{}'.format(self.prepId(
            columns['device_block'].replace(' ', '_')))
        hd_om.major_minor = columns['major_minor']
        hd_om.mount = columns['mount']
        hd_om.size = int(columns['size'])
        hd_om.relname = 'harddisks'
        hd_om.modname = 'ZenPacks.zenoss.LinuxMonitor.HardDisk'
        return hd_om

    def makePVMap(self, columns):
        # pv_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid,vg_name
        pv_om = ObjectMap()
        pv_om.title = columns['pv_name']
        pv_om.id = 'pv-{}'.format(self.prepId(columns['pv_name']))
        pv_om.format = columns['pv_fmt']
        pv_om.attributes = self.lvm_parser.pv_attributes(columns['pv_attr'])
        pv_om.uuid = columns['pv_uuid']
        pv_om.set_volumeGroup = 'vg-{}'.format(columns['vg_name']) if columns['vg_name'] else ''
        pv_om.relname = 'physicalVolumes'
        pv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.PhysicalVolume'
        return pv_om

    def makeVGMap(self, columns):
        # vg_name,vg_attr,vg_size,vg_free,vg_uuid
        vg_om = ObjectMap()
        vg_om.title = columns['vg_name']
        vg_om.id = 'vg-{}'.format(self.prepId(columns['vg_name']))
        vg_om.attributes = self.lvm_parser.vg_attributes(columns['vg_attr'])
        vg_om.uuid = columns['vg_uuid']
        vg_om.relname = 'volumeGroups'
        vg_om.modname = 'ZenPacks.zenoss.LinuxMonitor.VolumeGroup'
        return vg_om

    def makeLVMap(self, columns):
        # lv_name,vg_name,lv_attr,lv_size,lv_uuid,origin
        lv_om = ObjectMap()
        lv_om.title = columns['lv_name']
        lv_om.vgname = columns['vg_name']
        lv_om.id = 'lv-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['lv_name']))
        lv_om.attributes = self.lvm_parser.lv_attributes(columns['lv_attr'])
        lv_om.lvsize = int(columns['lv_size'])
        lv_om.uuid = columns['lv_uuid']
        if columns['origin']:
            lv_om.origin = columns['origin']
            lv_om.relname = 'snapshotVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.SnapshotVolume'
        elif columns['lv_metadata_size']:
            lv_om.id = 'tp-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['lv_name']))
            lv_om.metadatasize = int(columns['lv_metadata_size'])
            lv_om.relname = 'thinPools'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.ThinPool'
        else:
            lv_om.set_thinPool = None
            if columns['pool_lv']:
                lv_om.set_thinPool = 'tp-{}'.format(self.prepId(columns['vg_name'])+'_'+self.prepId(columns['pool_lv']))
            lv_om.relname = 'logicalVolumes'
            lv_om.modname = 'ZenPacks.zenoss.LinuxMonitor.LogicalVolume'
        return lv_om

    def checkErr(self, line):
        if 'no tty present' in line or 'sudo: sorry, you must have a tty to run sudo' in line:
            log.warning('No tty present.  Ensure that user is sudo and change sudo settings to disable requiretty for your user account.')
            return True
        return False