diff options
Diffstat (limited to 'glusternagios')
-rw-r--r-- | glusternagios/Makefile.am | 1 | ||||
-rwxr-xr-x | glusternagios/storage.py | 253 | ||||
-rw-r--r-- | glusternagios/utils.py | 11 |
3 files changed, 254 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 |