summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShubhendu Tripathi <shtripat@redhat.com>2014-04-01 15:12:50 +0530
committerBala.FA <barumuga@redhat.com>2014-04-28 16:20:46 +0530
commiteaf3d4136d6dd1ef00a7cef23f9338b03783dd43 (patch)
tree2b6b2933bda4ac5fd90505477a1336a45c1bc705
parent2873ff21e4f99b35ab88595a96c0ee45c83d26c3 (diff)
gluster-nagios-common: Added storage utils module
Introduced storage device utils module Change-Id: I738b46b0750deaf91b896a8edab07b5f1a692ddb Signed-off-by: Shubhendu Tripathi <shtripat@redhat.com> Reviewed-on: https://code.engineering.redhat.com/gerrit/22254 Reviewed-by: Sahina Bose <sabose@redhat.com> Tested-by: Sahina Bose <sabose@redhat.com>
-rw-r--r--glusternagios/Makefile.am1
-rwxr-xr-xglusternagios/storage.py253
-rw-r--r--glusternagios/utils.py11
-rw-r--r--tests/test_storage.py391
4 files changed, 645 insertions, 11 deletions
diff --git a/glusternagios/Makefile.am b/glusternagios/Makefile.am
index 7f46e08..6698600 100644
--- a/glusternagios/Makefile.am
+++ b/glusternagios/Makefile.am
@@ -2,5 +2,6 @@ dist_glusternagioscommonpylib_PYTHON = \
__init__.py \
glustercli.py \
hostname.py \
+ storage.py \
utils.py \
$(NULL)
diff --git a/glusternagios/storage.py b/glusternagios/storage.py
new file mode 100755
index 0000000..3371d4e
--- /dev/null
+++ b/glusternagios/storage.py
@@ -0,0 +1,253 @@
+# Copyright 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+import os
+
+import utils
+from utils import CommandPath
+import glustercli
+
+lvsCmdPath = CommandPath("lvs",
+ "/sbin/lvs",
+ )
+vgsCmdPath = CommandPath("vgs",
+ "/sbin/vgs",
+ )
+pvsCmdPath = CommandPath("pvs",
+ "/sbin/pvs")
+
+
+# Class for exception definition
+class ExecCmdFailedException(Exception):
+ message = "command execution failed"
+
+ def __init__(self, rc=0, out=(), err=()):
+ self.rc = rc
+ self.out = out
+ self.err = err
+
+ def __str__(self):
+ o = '\n'.join(self.out)
+ e = '\n'.join(self.err)
+ if o and e:
+ m = o + '\n' + e
+ else:
+ m = o or e
+
+ s = self.message
+ if m:
+ s += '\nerror: ' + m
+ if self.rc:
+ s += '\nreturn code: %s' % self.rc
+ return s
+
+
+# Creates a dict out of the given string
+def _reduceToDict(out):
+ for line in out:
+ yield dict(pair.split('=') for pair in line.strip().split('^'))
+
+
+# Parses the lvs command output and returns the required dictionary
+def _parseLvs(output):
+ return dict((x['LVM2_LV_PATH'], x) for x in _reduceToDict(output))
+
+
+def _getLvsCmd():
+ return [lvsCmdPath.cmd] + (" --unquoted --noheading " +
+ "--nameprefixes --separator ^ " +
+ "--nosuffix --units m -o " +
+ "lv_all,vg_name").split()
+
+
+def _getVgsCmd():
+ return [vgsCmdPath.cmd] + (" --unquoted --noheading " +
+ "--nameprefixes --separator ^ " +
+ "--nosuffix --units m -o " +
+ "vg_all,lv_path").split()
+
+
+def _getPvsCmd():
+ return [pvsCmdPath.cmd] + (" --unquoted --noheading " +
+ "--nameprefixes --separator ^ " +
+ "--nosuffix --units m -o " +
+ "pv_all,vg_name").split()
+
+
+def _getLvDetailsCmd():
+ return [pvsCmdPath.cmd] + (" --unquoted --noheading " +
+ "--nameprefixes --separator ^ " +
+ "--nosuffix --units m -o " +
+ "vg_name,pv_name,lv_name").split()
+
+
+# Gets the list of logical volumes
+def getLvs():
+ rc, out, err = utils.execCmd(_getLvsCmd())
+ if rc:
+ raise ExecCmdFailedException(err=[str(err)])
+
+ return _parseLvs(out)
+
+
+# Parses the vgs coammnd output and returns the required dictionary
+def _parseVgs(out):
+ def _makeVgDict(x, y):
+ y['LVM2_LV_PATH'] = [y['LVM2_LV_PATH']] if y['LVM2_LV_PATH'] else []
+ if y['LVM2_VG_NAME'] in x:
+ x[y['LVM2_VG_NAME']]['LVM2_LV_PATH'] += y['LVM2_LV_PATH']
+ else:
+ x[y['LVM2_VG_NAME']] = y
+ return x
+
+ return reduce(_makeVgDict, _reduceToDict(out), {})
+
+
+# Gets the list of volume groups
+def getVgs():
+ rc, out, err = utils.execCmd(_getVgsCmd())
+ if rc:
+ raise ExecCmdFailedException(err=[str(err)])
+
+ return _parseVgs(out)
+
+
+# Parses the output of pvs command and returns the required dictionary
+def _parsePvs(out):
+ return dict((x['LVM2_PV_NAME'], x) for x in _reduceToDict(out))
+
+
+# Gets the list of physical volumes
+def getPvs():
+ rc, out, err = utils.execCmd(_getPvsCmd())
+ if rc:
+ raise ExecCmdFailedException(err=[str(err)])
+
+ return _parsePvs(out)
+
+
+# Returns the mount point for the given path
+def _getMountPoint(path):
+ path = os.path.abspath(path)
+ while not os.path.ismount(path):
+ path = os.path.dirname(path)
+
+ return path
+
+
+# Gets the lv details
+def _getLvDetails():
+ rc, out, err = utils.execCmd(_getLvDetailsCmd())
+ if rc:
+ raise ExecCmdFailedException(err=[str(err)])
+
+ return dict((x['LVM2_LV_NAME'], x) for x in _reduceToDict(out))
+
+
+# Gets the brickwise mount points
+def _getBrickMountPoints():
+ mount_points = {}
+ volumeInfo = glustercli.volumeInfo()
+ for key in volumeInfo.keys():
+ volume = volumeInfo[key]
+ bricks = volume['bricks']
+ for brick in bricks:
+ mount_points[brick] = _getMountPoint(brick.split(":")[1])
+
+ return mount_points
+
+
+# Gets the list of all the proc mounts
+def _getProcMounts():
+ mounts = {}
+ with open('/proc/mounts') as f:
+ for line in f:
+ arr = line.split()
+ mounts[arr[0]] = arr[1]
+
+ return mounts
+
+
+# Gets the list of bricks for a given disk
+def getBricksForDisk(diskName):
+ # Get all the lv details
+ lv_dict = _getLvDetails()
+
+ # Reduce the LVs for the give device
+ validLvs = {}
+ for key in lv_dict.keys():
+ if lv_dict[key]['LVM2_PV_NAME'] == diskName:
+ validLvs[key] = lv_dict[key]
+
+ # Get the brickwise mount points
+ brick_mount_points = _getBrickMountPoints()
+
+ # Get the list of all the mount points
+ procmounts = _getProcMounts()
+
+ # Get the mount points to find bricks for
+ mount_points_to_check = []
+ for key in validLvs.keys():
+ searchname = "%s-%s" % (validLvs[key]['LVM2_VG_NAME'],
+ validLvs[key]['LVM2_LV_NAME'])
+ for mount in procmounts.keys():
+ if mount.endswith(searchname):
+ mount_points_to_check.append(procmounts[mount])
+
+ # Get the list of bricks
+ bricks_list = []
+ for key in brick_mount_points.keys():
+ if brick_mount_points[key] in mount_points_to_check:
+ bricks_list.append(key)
+
+ return bricks_list
+
+
+# Gets the brick's device name
+def _getBrickDeviceName(brickName):
+ brickDevices = {}
+ volStatus = glustercli.volumeStatus("all", option="detail")
+ bricks = volStatus['bricks']
+ for brick in bricks:
+ brick_dir = brick['brick']
+ brickDevices[brick_dir] = brick['device']
+
+ if brickName in brickDevices.keys():
+ return brickDevices[brickName]
+ else:
+ return ""
+
+
+# Gets the list of disks participating in the given brick
+def getDisksForBrick(brickName, deviceName=None):
+ # Get the brick device name
+ if deviceName is None:
+ deviceName = _getBrickDeviceName(brickName)
+
+ # Get the lv details
+ lv_dict = _getLvDetails()
+
+ # Get the disk name for the brick
+ for key in lv_dict.keys():
+ tmp_str = "%s-%s" % (lv_dict[key]['LVM2_VG_NAME'],
+ lv_dict[key]['LVM2_LV_NAME'])
+ if deviceName.endswith(tmp_str):
+ return lv_dict[key]['LVM2_PV_NAME']
+
+ return ""
diff --git a/glusternagios/utils.py b/glusternagios/utils.py
index 047fccf..a46811d 100644
--- a/glusternagios/utils.py
+++ b/glusternagios/utils.py
@@ -105,17 +105,6 @@ setsidCmdPath = CommandPath("setsid",
sudoCmdPath = CommandPath("sudo",
"/usr/bin/sudo",
)
-lvsCmdPath = CommandPath("lvs",
- "/sbin/lvs",
- )
-vgsCmdPath = CommandPath("vgs",
- "/sbin/vgs",
- )
-pvsCmdPath = CommandPath("pvs",
- "/sbin/pvs",
- )
-hostnameCmdPath = CommandPath("hostname", "/bin/hostname", )
-glusterCmdPath = CommandPath("gluster", "/usr/sbin/gluster")
# Buffsize is 1K because I tested it on some use cases and 1K was fastest. If
# you find this number to be a bottleneck in any way you are welcome to change
# it
diff --git a/tests/test_storage.py b/tests/test_storage.py
new file mode 100644
index 0000000..3a15cf1
--- /dev/null
+++ b/tests/test_storage.py
@@ -0,0 +1,391 @@
+#
+# Copyright 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+import mock
+
+from testrunner import GlusterNagiosTestCase as TestCaseBase
+from glusternagios import storage
+import glusternagios
+
+
+class TestStorageUtils(TestCaseBase):
+ @mock.patch('glusternagios.storage.utils')
+ def testGetLvs(self, mock_utils):
+ tmp_str = ["LVM2_LV_UUID=zjuuHG-HajL-PXxm-fjlL-5i00-EUnV-Wd2qL3^"
+ "LVM2_LV_NAME=lv_root^"
+ "LVM2_LV_PATH=/dev/vg_shubhnd/lv_root^"
+ "LVM2_LV_ATTR=-wi-ao---^"
+ "LVM2_LV_MAJOR=-1^"
+ "LVM2_LV_MINOR=-1^"
+ "LVM2_LV_READ_AHEAD=auto^"
+ "LVM2_LV_KERNEL_MAJOR=253^"
+ "LVM2_LV_KERNEL_MINOR=0^"
+ "LVM2_LV_KERNEL_READ_AHEAD=0.12^"
+ "LVM2_LV_SIZE=46728.00^"
+ "LVM2_LV_METADATA_SIZE=^"
+ "LVM2_SEG_COUNT=1^"
+ "LVM2_ORIGIN=^"
+ "LVM2_ORIGIN_SIZE=0^"
+ "LVM2_DATA_PERCENT=^"
+ "LVM2_SNAP_PERCENT=^"
+ "LVM2_METADATA_PERCENT=^"
+ "LVM2_COPY_PERCENT=^"
+ "LVM2_SYNC_PERCENT=^"
+ "LVM2_MOVE_PV=^"
+ "LVM2_CONVERT_LV=^"
+ "LVM2_MIRROR_LOG=^"
+ "LVM2_DATA_LV=^"
+ "LVM2_METADATA_LV=^"
+ "LVM2_POOL_LV=^"
+ "LVM2_LV_TAGS=^"
+ "LVM2_LV_TIME=2014-03-14 04:27:56 +0530^"
+ "LVM2_LV_HOST=shubh-nd.redhat.com^"
+ "LVM2_MODULES=^"
+ "LVM2_VG_NAME=vg_shubhnd",
+ "LVM2_LV_UUID=klTthp-BXN8-9loo-UUo9-Y2lB-6azb-X9fFdH^"
+ "LVM2_LV_NAME=lv_swap^"
+ "LVM2_LV_PATH=/dev/vg_shubhnd/lv_swap^"
+ "LVM2_LV_ATTR=-wi-ao---^"
+ "LVM2_LV_MAJOR=-1^"
+ "LVM2_LV_MINOR=-1^"
+ "LVM2_LV_READ_AHEAD=auto^"
+ "LVM2_LV_KERNEL_MAJOR=253^"
+ "LVM2_LV_KERNEL_MINOR=1^"
+ "LVM2_LV_KERNEL_READ_AHEAD=0.12^"
+ "LVM2_LV_SIZE=3968.00^"
+ "LVM2_LV_METADATA_SIZE=^"
+ "LVM2_SEG_COUNT=1^"
+ "LVM2_ORIGIN=^"
+ "LVM2_ORIGIN_SIZE=0^"
+ "LVM2_DATA_PERCENT=^"
+ "LVM2_SNAP_PERCENT=^"
+ "LVM2_METADATA_PERCENT=^"
+ "LVM2_COPY_PERCENT=^"
+ "LVM2_SYNC_PERCENT=^"
+ "LVM2_MOVE_PV=^"
+ "LVM2_CONVERT_LV=^"
+ "LVM2_MIRROR_LOG=^"
+ "LVM2_DATA_LV=^"
+ "LVM2_METADATA_LV=^"
+ "LVM2_POOL_LV=^"
+ "LVM2_LV_TAGS=^"
+ "LVM2_LV_TIME=2014-03-14 04:28:01 +0530^"
+ "LVM2_LV_HOST=shubh-nd.redhat.com^"
+ "LVM2_MODULES=^"
+ "LVM2_VG_NAME=vg_shubhnd"]
+ mock_utils.execCmd.return_value = (0, tmp_str, "")
+ ret_val = glusternagios.storage.getLvs()
+ value_to_verify = {'/dev/vg_shubhnd/lv_root':
+ {'LVM2_SYNC_PERCENT': '',
+ 'LVM2_LV_METADATA_SIZE': '',
+ 'LVM2_LV_ATTR': '-wi-ao---',
+ 'LVM2_MIRROR_LOG': '',
+ 'LVM2_LV_KERNEL_MINOR': '0',
+ 'LVM2_LV_SIZE': '46728.00',
+ 'LVM2_LV_MAJOR': '-1',
+ 'LVM2_ORIGIN_SIZE': '0',
+ 'LVM2_LV_TIME': '2014-03-14 04:27:56 +0530',
+ 'LVM2_METADATA_PERCENT': '',
+ 'LVM2_POOL_LV': '',
+ 'LVM2_COPY_PERCENT': '',
+ 'LVM2_CONVERT_LV': '',
+ 'LVM2_LV_KERNEL_READ_AHEAD': '0.12',
+ 'LVM2_LV_NAME': 'lv_root',
+ 'LVM2_LV_HOST': 'shubh-nd.redhat.com',
+ 'LVM2_LV_UUID':
+ 'zjuuHG-HajL-PXxm-fjlL-5i00-EUnV-Wd2qL3',
+ 'LVM2_LV_MINOR': '-1',
+ 'LVM2_DATA_PERCENT': '',
+ 'LVM2_LV_KERNEL_MAJOR': '253',
+ 'LVM2_LV_TAGS': '',
+ 'LVM2_MODULES': '',
+ 'LVM2_VG_NAME': 'vg_shubhnd',
+ 'LVM2_METADATA_LV': '',
+ 'LVM2_LV_PATH': '/dev/vg_shubhnd/lv_root',
+ 'LVM2_DATA_LV': '',
+ 'LVM2_LV_READ_AHEAD': 'auto',
+ 'LVM2_SNAP_PERCENT': '',
+ 'LVM2_MOVE_PV': '',
+ 'LVM2_ORIGIN': '',
+ 'LVM2_SEG_COUNT': '1'},
+ '/dev/vg_shubhnd/lv_swap':
+ {'LVM2_SYNC_PERCENT': '',
+ 'LVM2_LV_METADATA_SIZE': '',
+ 'LVM2_LV_ATTR': '-wi-ao---',
+ 'LVM2_MIRROR_LOG': '',
+ 'LVM2_LV_KERNEL_MINOR': '1',
+ 'LVM2_LV_SIZE': '3968.00',
+ 'LVM2_LV_MAJOR': '-1',
+ 'LVM2_ORIGIN_SIZE': '0',
+ 'LVM2_LV_TIME': '2014-03-14 04:28:01 +0530',
+ 'LVM2_METADATA_PERCENT': '',
+ 'LVM2_POOL_LV': '',
+ 'LVM2_COPY_PERCENT': '',
+ 'LVM2_CONVERT_LV': '',
+ 'LVM2_LV_KERNEL_READ_AHEAD': '0.12',
+ 'LVM2_LV_NAME': 'lv_swap',
+ 'LVM2_LV_HOST': 'shubh-nd.redhat.com',
+ 'LVM2_LV_UUID':
+ 'klTthp-BXN8-9loo-UUo9-Y2lB-6azb-X9fFdH',
+ 'LVM2_LV_MINOR': '-1',
+ 'LVM2_DATA_PERCENT': '',
+ 'LVM2_LV_KERNEL_MAJOR': '253',
+ 'LVM2_LV_TAGS': '',
+ 'LVM2_MODULES': '',
+ 'LVM2_VG_NAME': 'vg_shubhnd',
+ 'LVM2_METADATA_LV': '',
+ 'LVM2_LV_PATH': '/dev/vg_shubhnd/lv_swap',
+ 'LVM2_DATA_LV': '',
+ 'LVM2_LV_READ_AHEAD': 'auto',
+ 'LVM2_SNAP_PERCENT': '',
+ 'LVM2_MOVE_PV': '',
+ 'LVM2_ORIGIN': '',
+ 'LVM2_SEG_COUNT': '1'}}
+ self.assertEquals(ret_val, value_to_verify)
+
+ @mock.patch('glusternagios.storage.utils')
+ def testGetVgs(self, mock_utils):
+ tmp_str = ["LVM2_VG_FMT=lvm2^"
+ "LVM2_VG_UUID=sTDsBh-DOc7-JR3y-RPHb-yz4R-aWP7-yZWQ0E^"
+ "LVM2_VG_NAME=vg_shubhnd^"
+ "LVM2_VG_ATTR=wz--n-^"
+ "LVM2_VG_SIZE=50696.00^"
+ "LVM2_VG_FREE=0^"
+ "LVM2_VG_SYSID=^"
+ "LVM2_VG_EXTENT_SIZE=4.00^"
+ "LVM2_VG_EXTENT_COUNT=12674^"
+ "LVM2_VG_FREE_COUNT=0^"
+ "LVM2_MAX_LV=0^"
+ "LVM2_MAX_PV=0^"
+ "LVM2_PV_COUNT=1^"
+ "LVM2_LV_COUNT=2^"
+ "LVM2_SNAP_COUNT=0^"
+ "LVM2_VG_SEQNO=3^"
+ "LVM2_VG_TAGS=^"
+ "LVM2_VG_MDA_COUNT=1^"
+ "LVM2_VG_MDA_USED_COUNT=1^"
+ "LVM2_VG_MDA_FREE=0.50^"
+ "LVM2_VG_MDA_SIZE=1.00^"
+ "LVM2_VG_MDA_COPIES=unmanaged^"
+ "LVM2_LV_PATH=/dev/vg_shubhnd/lv_root",
+ "LVM2_VG_FMT=lvm2^"
+ "LVM2_VG_UUID=sTDsBh-DOc7-JR3y-RPHb-yz4R-aWP7-yZWQ0E^"
+ "LVM2_VG_NAME=vg_shubhnd^"
+ "LVM2_VG_ATTR=wz--n-^"
+ "LVM2_VG_SIZE=50696.00^"
+ "LVM2_VG_FREE=0^"
+ "LVM2_VG_SYSID=^"
+ "LVM2_VG_EXTENT_SIZE=4.00^"
+ "LVM2_VG_EXTENT_COUNT=12674^"
+ "LVM2_VG_FREE_COUNT=0^"
+ "LVM2_MAX_LV=0^"
+ "LVM2_MAX_PV=0^"
+ "LVM2_PV_COUNT=1^"
+ "LVM2_LV_COUNT=2^"
+ "LVM2_SNAP_COUNT=0^"
+ "LVM2_VG_SEQNO=3^"
+ "LVM2_VG_TAGS=^"
+ "LVM2_VG_MDA_COUNT=1^"
+ "LVM2_VG_MDA_USED_COUNT=1^"
+ "LVM2_VG_MDA_FREE=0.50^"
+ "LVM2_VG_MDA_SIZE=1.00^"
+ "LVM2_VG_MDA_COPIES=unmanaged^"
+ "LVM2_LV_PATH=/dev/vg_shubhnd/lv_swap"]
+ mock_utils.execCmd.return_value = (0, tmp_str, "")
+ ret_val = glusternagios.storage.getVgs()
+ value_to_verify = {'vg_shubhnd':
+ {'LVM2_VG_EXTENT_SIZE': '4.00',
+ 'LVM2_VG_MDA_COUNT': '1',
+ 'LVM2_VG_SYSID': '',
+ 'LVM2_VG_ATTR': 'wz--n-',
+ 'LVM2_VG_UUID':
+ 'sTDsBh-DOc7-JR3y-RPHb-yz4R-aWP7-yZWQ0E',
+ 'LVM2_VG_MDA_COPIES': 'unmanaged',
+ 'LVM2_VG_MDA_FREE': '0.50',
+ 'LVM2_VG_TAGS': '',
+ 'LVM2_VG_FMT': 'lvm2',
+ 'LVM2_PV_COUNT': '1',
+ 'LVM2_VG_EXTENT_COUNT': '12674',
+ 'LVM2_VG_MDA_SIZE': '1.00',
+ 'LVM2_SNAP_COUNT': '0',
+ 'LVM2_LV_COUNT': '2',
+ 'LVM2_VG_NAME': 'vg_shubhnd',
+ 'LVM2_VG_MDA_USED_COUNT': '1',
+ 'LVM2_VG_FREE': '0',
+ 'LVM2_VG_SEQNO': '3',
+ 'LVM2_LV_PATH':
+ ['/dev/vg_shubhnd/lv_root',
+ '/dev/vg_shubhnd/lv_swap'],
+ 'LVM2_VG_FREE_COUNT': '0',
+ 'LVM2_MAX_PV': '0',
+ 'LVM2_MAX_LV': '0',
+ 'LVM2_VG_SIZE': '50696.00'}}
+ self.assertEquals(ret_val, value_to_verify)
+
+ @mock.patch('glusternagios.storage.utils')
+ def testGetPvs(self, mock_utils):
+ tmp_str = ["LVM2_PV_FMT=lvm2^"
+ "LVM2_PV_UUID=NF1uv0-eXJM-YJrn-Rc7b-Z2nw-E1Ly-3S24zn^"
+ "LVM2_DEV_SIZE=50699.00^"
+ "LVM2_PV_NAME=/dev/vda2^"
+ "LVM2_PV_MDA_FREE=0.50^"
+ "LVM2_PV_MDA_SIZE=1.00^"
+ "LVM2_PE_START=1.00^"
+ "LVM2_PV_SIZE=50696.00^"
+ "LVM2_PV_FREE=0^"
+ "LVM2_PV_USED=50696.00^"
+ "LVM2_PV_ATTR=a--^"
+ "LVM2_PV_PE_COUNT=12674^"
+ "LVM2_PV_PE_ALLOC_COUNT=12674^"
+ "LVM2_PV_TAGS=^"
+ "LVM2_PV_MDA_COUNT=1^"
+ "LVM2_PV_MDA_USED_COUNT=1^"
+ "LVM2_VG_NAME=vg_shubhnd"]
+ mock_utils.execCmd.return_value = (0, tmp_str, "")
+ ret_val = glusternagios.storage.getPvs()
+ value_to_verify = {'/dev/vda2':
+ {'LVM2_PV_MDA_USED_COUNT': '1',
+ 'LVM2_PV_UUID':
+ 'NF1uv0-eXJM-YJrn-Rc7b-Z2nw-E1Ly-3S24zn',
+ 'LVM2_PE_START': '1.00',
+ 'LVM2_DEV_SIZE': '50699.00',
+ 'LVM2_PV_NAME': '/dev/vda2',
+ 'LVM2_PV_FMT': 'lvm2',
+ 'LVM2_PV_MDA_COUNT': '1',
+ 'LVM2_PV_MDA_FREE': '0.50',
+ 'LVM2_PV_TAGS': '',
+ 'LVM2_PV_FREE': '0',
+ 'LVM2_PV_SIZE': '50696.00',
+ 'LVM2_PV_PE_ALLOC_COUNT': '12674',
+ 'LVM2_PV_MDA_SIZE': '1.00',
+ 'LVM2_VG_NAME': 'vg_shubhnd',
+ 'LVM2_PV_USED': '50696.00',
+ 'LVM2_PV_ATTR': 'a--',
+ 'LVM2_PV_PE_COUNT': '12674'}}
+ self.assertEquals(ret_val, value_to_verify)
+
+ @mock.patch('glusternagios.storage._getMountPoint')
+ @mock.patch('glusternagios.storage._getProcMounts')
+ @mock.patch('glusternagios.storage.glustercli.utils')
+ @mock.patch('glusternagios.storage._getLvDetails')
+ def testGetBricksForDisk(self,
+ mock_get_lv_details,
+ mock_utils,
+ mock_proc_mounts,
+ mock_get_mount_point):
+ mock_get_lv_details.return_value = {'lv_root':
+ {'LVM2_LV_NAME': 'lv_root',
+ 'LVM2_PV_NAME': '/dev/vda2',
+ 'LVM2_VG_NAME': 'vg_shubhnd'},
+ 'lv_swap':
+ {'LVM2_LV_NAME': 'lv_swap',
+ 'LVM2_PV_NAME': '/dev/vda2',
+ 'LVM2_VG_NAME': 'vg_shubhnd'}}
+ tmp_out = ['<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
+ '<cliOutput>',
+ ' <opRet>0</opRet>',
+ ' <opErrno>0</opErrno>',
+ ' <opErrstr/>',
+ ' <volInfo>',
+ ' <volumes>',
+ ' <volume>',
+ ' <name>vol1</name>',
+ ' <id>9510c150-f471-450c-9c6e-1c489792bfb2</id>',
+ ' <status>1</status>',
+ ' <statusStr>Started</statusStr>',
+ ' <brickCount>1</brickCount>',
+ ' <distCount>1</distCount>',
+ ' <stripeCount>1</stripeCount>',
+ ' <replicaCount>1</replicaCount>',
+ ' <type>0</type>',
+ ' <typeStr>Distribute</typeStr>',
+ ' <transport>0</transport>',
+ ' <bricks>',
+ ' <brick>server-1:/tmp/vol1-a</brick>',
+ ' </bricks>',
+ ' <optCount>0</optCount>',
+ ' <options/>',
+ ' </volume>',
+ ' <count>1</count>',
+ ' </volumes>',
+ ' </volInfo>',
+ '</cliOutput>']
+ mock_utils.execCmd.return_value = (0, tmp_out, "")
+ mock_proc_mounts.return_value = {'devpts': '/dev/pts',
+ '/dev/mapper/vg_shubhnd-lv_root': '/',
+ 'sysfs': '/sys',
+ '/proc/bus/usb': '/proc/bus/usb',
+ 'proc': '/proc'}
+ mock_get_mount_point.return_value = "/"
+ bricks = glusternagios.storage.getBricksForDisk("/dev/vda2")
+ self.assertEquals(bricks, ['server-1:/tmp/vol1-a'])
+
+ @mock.patch('glusternagios.storage._getLvDetails')
+ @mock.patch('glusternagios.storage.glustercli.utils')
+ @mock.patch('glusternagios.storage._getMountPoint')
+ def testGetDisksForBrick(self,
+ mock_get_mount_point,
+ mock_utils,
+ mock_get_lv_details):
+ mock_get_mount_point.return_value = "/"
+ tmp_out = ['<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
+ '<cliOutput>',
+ ' <opRet>0</opRet>',
+ ' <opErrno>0</opErrno>',
+ ' <opErrstr>(null)</opErrstr>',
+ ' <volStatus>',
+ ' <volumes>',
+ ' <volume>',
+ ' <volName>vol1</volName>',
+ ' <nodeCount>1</nodeCount>',
+ ' <node>',
+ ' <hostname>server-1</hostname>',
+ ' <path>/tmp/vol1-a</path>',
+ ' <status>1</status>',
+ ' <port>49152</port>',
+ ' <pid>8716</pid>',
+ ' <sizeTotal>48228589568</sizeTotal>',
+ ' <sizeFree>45994987520</sizeFree>',
+ ' <device>/dev/mapper/vg_shubhnd-lv_root</device>',
+ ' <blockSize>4096</blockSize>',
+ ' <mntOptions>rw</mntOptions>',
+ ' <fsName>ext4</fsName>',
+ ' </node>',
+ ' </volume>',
+ ' </volumes>',
+ ' </volStatus>',
+ '</cliOutput>']
+ mock_utils.execCmd.return_value = (0, tmp_out, "")
+ mock_get_lv_details.return_value = {'lv_root':
+ {'LVM2_LV_NAME': 'lv_root',
+ 'LVM2_PV_NAME': '/dev/vda2',
+ 'LVM2_VG_NAME': 'vg_shubhnd'},
+ 'lv_swap':
+ {'LVM2_LV_NAME': 'lv_swap',
+ 'LVM2_PV_NAME': '/dev/vda2',
+ 'LVM2_VG_NAME': 'vg_shubhnd'}}
+ disk = glusternagios.storage.getDisksForBrick("server-1:"
+ "/tmp/vol1-a")
+ self.assertEquals(disk, "/dev/vda2")
+
+ disk = glusternagios.storage.getDisksForBrick(
+ "server-1:/tmp/vol1-a",
+ "/dev/mapper/vg_shubhnd-lv_root")
+ self.assertEquals(disk, "/dev/vda2")