diff options
Diffstat (limited to 'glustolibs-gluster/glustolibs/gluster/heal_ops.py')
-rw-r--r-- | glustolibs-gluster/glustolibs/gluster/heal_ops.py | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/glustolibs-gluster/glustolibs/gluster/heal_ops.py b/glustolibs-gluster/glustolibs/gluster/heal_ops.py new file mode 100644 index 000000000..1bf8d2f87 --- /dev/null +++ b/glustolibs-gluster/glustolibs/gluster/heal_ops.py @@ -0,0 +1,432 @@ +#!/usr/bin/env python +# Copyright (C) 2015-2016 Red Hat, Inc. <http://www.redhat.com> +# +# 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 +# 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. + +""" + Description: Module for gluster heal operations. +""" + +import os +import time +from glusto.core import Glusto as g +from glustolibs.gluster.volume_ops import (get_volume_info, get_volume_status) +try: + import xml.etree.cElementTree as etree +except ImportError: + import xml.etree.ElementTree as etree + + +def trigger_heal(mnode, volname): + """Triggers heal on the volume. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if heal is triggered successfully. False otherwise. + """ + cmd = "gluster volume heal %s" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def trigger_heal_full(mnode, volname): + """Triggers heal 'full' on the volume. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if heal is triggered successfully. False otherwise. + """ + cmd = "gluster volume heal %s full" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def enable_heal(mnode, volname): + """Enable heal by executing 'gluster volume heal enable' + for the specified volume. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if heal is enabled on the volume. + False otherwise. + """ + cmd = "gluster volume heal %s enable" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def disable_heal(mnode, volname): + """Disable heal by executing 'gluster volume heal disable' + for the specified volume. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if heal is disabled on the volume. + False otherwise. + """ + cmd = "gluster volume heal %s disable" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def enable_self_heal_daemon(mnode, volname): + """Enables self-heal-daemon on a volume by setting volume option + 'self-heal-daemon' to value 'on' + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if setting self_heal_daemon option to 'on' is successful. + False otherwise. + """ + cmd = "gluster volume set %s self-heal-daemon on" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def disable_self_heal_daemon(mnode, volname): + """Disables self-heal-daemon on a volume by setting volume option + 'self-heal-daemon' to value 'off' + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + bool : True if setting self_heal_daemon option to 'off' is successful. + False otherwise. + """ + cmd = "gluster volume set %s self-heal-daemon off" % volname + ret, _, _ = g.run(mnode, cmd) + if ret != 0: + return False + + return True + + +def heal_info(mnode, volname): + """Get heal info for the volume by executing: + 'gluster volume heal <volname> info' + + Args: + mnode : Node on which commands are executed. + volname : Name of the volume + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = "gluster volume heal %s info" % volname + return g.run(mnode, cmd) + + +def heal_info_summary(mnode, volname): + """Get heal info summary i.e Bricks and it's corresponding number of + entries, status. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = ("gluster volume heal %s info | grep 'entries\|Brick\|Status'" % + volname) + return g.run(mnode, cmd) + + +def heal_info_healed(mnode, volname): + """Get healed entries information for the volume by executing: + 'gluster volume heal <volname> info healed' + + Args: + mnode : Node on which commands are executed. + volname : Name of the volume + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = "gluster volume heal %s info healed" % volname + return g.run(mnode, cmd) + + +def heal_info_heal_failed(mnode, volname): + """Get entries on which heal failed for the volume by executing: + 'gluster volume heal <volname> info heal-failed' + + Args: + mnode : Node on which commands are executed. + volname : Name of the volume + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = "gluster volume heal %s info heal-failed" % volname + return g.run(mnode, cmd) + + +def heal_info_split_brain(mnode, volname): + """Get entries that are in split-brain state for the volume by executing: + 'gluster volume heal <volname> info split-brain' + + Args: + mnode : Node on which commands are executed. + volname : Name of the volume + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = "gluster volume heal %s info split-brain" % volname + return g.run(mnode, cmd) + + +def get_heal_info(mnode, volname): + """From the xml output of heal info command get the heal info data. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + NoneType: None if parse errors. + list: list of dictionaries. Each element in the list is the + heal_info data per brick. + """ + cmd = "gluster volume heal %s info --xml" % volname + ret, out, _ = g.run(mnode, cmd) + if ret != 0: + g.log.error("Failed to get the heal info xml output for the volume %s." + "Hence failed to get the heal info summary." % volname) + return None + + try: + root = etree.XML(out) + except etree.ParseError: + g.log.error("Failed to parse the gluster heal info xml output.") + return None + + heal_info_data = [] + for brick in root.findall("healInfo/bricks/brick"): + brick_heal_info = {} + brick_files_to_heal = [] + file_to_heal_exist = False + for element in brick.getchildren(): + if element.tag == "file": + file_to_heal_exist = True + file_info = {} + file_info[element.attrib['gfid']] = element.text + brick_files_to_heal.append(file_info) + + else: + brick_heal_info[element.tag] = element.text + if file_to_heal_exist: + brick_heal_info['file'] = brick_files_to_heal + heal_info_data.append(brick_heal_info) + return heal_info_data + + +def get_heal_info_summary(mnode, volname): + """From the xml output of heal info command get heal info summary + i.e Bricks and it's corresponding number of entries, status. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + NoneType: None if parse errors. + dict: dict of dictionaries. brick names are the keys of the dict with + each key having brick's status, numberOfEntries info as dict. + Example: + heal_info_summary_data = { + 'ijk.lab.eng.xyz.com': { + 'status': 'Connected' + 'numberOfEntries': '11' + }, + 'def.lab.eng.xyz.com': { + 'status': 'Transport endpoint is not connected', + 'numberOfEntries': '-' + } + } + + """ + heal_info_data = get_heal_info(mnode, volname) + if heal_info_data is None: + g.log.error("Unable to get heal info summary for the volume %s" % + volname) + return None + + heal_info_summary_data = {} + for info_data in heal_info_data: + heal_info_summary_data[info_data['name']] = { + 'status': info_data['status'], + 'numberOfEntries': info_data['numberOfEntries'] + } + return heal_info_summary_data + + +def get_heal_info_split_brain(mnode, volname): + """From the xml output of heal info split-brain command get the + heal info split-brain data. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + NoneType: None if parse errors. + list: list of dictionaries. Each element in the list is the + heal_info_split_brain data per brick. + """ + cmd = "gluster volume heal %s info split-brain --xml" % volname + ret, out, _ = g.run(mnode, cmd) + if ret != 0: + g.log.error("Failed to get the heal info xml output for the volume %s." + "Hence failed to get the heal info summary." % volname) + return None + + try: + root = etree.XML(out) + except etree.ParseError: + g.log.error("Failed to parse the gluster heal info xml output.") + return None + + heal_info_split_brain_data = [] + for brick in root.findall("healInfo/bricks/brick"): + brick_heal_info_split_brain = {} + brick_files_in_split_brain = [] + is_file_in_split_brain = False + for element in brick.getchildren(): + if element.tag == "file": + is_file_in_split_brain = True + file_info = {} + file_info[element.attrib['gfid']] = element.text + brick_files_in_split_brain.append(file_info) + + else: + brick_heal_info_split_brain[element.tag] = element.text + if is_file_in_split_brain: + brick_heal_info_split_brain['file'] = brick_files_in_split_brain + heal_info_split_brain_data.append(brick_heal_info_split_brain) + return heal_info_split_brain_data + + +def get_heal_info_split_brain_summary(mnode, volname): + """Get heal info split_brain summary i.e Bricks and it's + corresponding number of split-brain entries, status. + + Args: + mnode : Node on which commands are executed + volname : Name of the volume + + Returns: + NoneType: None if parse errors. + dict: dict of dictionaries. brick names are the keys of the dict with + each key having brick's status, numberOfEntries info as dict. + Example: + heal_info_split_brain_summary_data = { + 'ijk.lab.eng.xyz.com': { + 'status': 'Connected' + 'numberOfEntries': '11' + }, + 'def.lab.eng.xyz.com': { + 'status': 'Connected', + 'numberOfEntries': '11' + } + } + + """ + heal_info_split_brain_data = get_heal_info_split_brain(mnode, volname) + if heal_info_split_brain_data is None: + g.log.error("Unable to get heal info summary for the volume %s" % + volname) + return None + + heal_info_split_brain_summary_data = {} + for info_data in heal_info_split_brain_data: + heal_info_split_brain_summary_data[info_data['name']] = { + 'status': info_data['status'], + 'numberOfEntries': info_data['numberOfEntries'] + } + return heal_info_split_brain_summary_data |