diff options
author | Arthy Loganathan <aloganat@redhat.com> | 2016-06-26 23:14:35 +0530 |
---|---|---|
committer | Raghavendra Talur <rtalur@redhat.com> | 2016-06-26 11:19:56 -0700 |
commit | 8b53bfab1e86b7c110e5f2bab464678c4c99758a (patch) | |
tree | ee80314b73b7a0c6da1d0bcf6a0eb6a0fdff4aa1 /tests | |
parent | 931c656d6207645d2a7572cacf674f2b77f411f7 (diff) |
distaf: Modified volume_ops library
Modified gluster volume ops library modules
Change-Id: I2ef5ca44f3a4a9844aee48f3688e8617dbbb4fcd
BUG: 1350245
Signed-off-by: Arthy Loganathan <aloganat@redhat.com>
Reviewed-on: http://review.gluster.org/14801
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: ShwethaHPanduranga
Smoke: Gluster Build System <jenkins@build.gluster.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py | 719 |
1 files changed, 550 insertions, 169 deletions
diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py index 64c77ea047f..58939377939 100644 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py +++ b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py @@ -127,53 +127,115 @@ def create_volume(volname, mnode=None, dist=1, rep=1, stripe=1, trans='tcp', return ret -def start_volume(volname, mnode='', force=False): - """ - Starts the gluster volume - Returns True if success and False if failure +def start_volume(volname, mnode=None, force=False): + """Starts the gluster volume + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + force (bool): If this option is set to True, then start volume + will get executed with force option. If it is set to False, + then start volume will get executed without force option + + 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. + + Example: + start_volume("testvol") """ - if mnode == '': + if mnode is None: mnode = tc.servers[0] frce = '' if force: frce = 'force' - ret = tc.run(mnode, "gluster volume start %s %s" % (volname, frce)) - if ret[0] != 0: - return False - return True + cmd = "gluster volume start %s %s --mode=script" % (volname, frce) + return tc.run(mnode, cmd) -def stop_volume(volname, mnode='', force=False): - """ - Stops the gluster volume - Returns True if success and False if failure +def stop_volume(volname, mnode=None, force=False): + """Stops the gluster volume + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + force (bool): If this option is set to True, then stop volume + will get executed with force option. If it is set to False, + then stop volume will get executed without force option + + 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. + + Example: + stop_volume("testvol") """ - if mnode == '': + if mnode is None: mnode = tc.servers[0] frce = '' if force: frce = 'force' - ret = tc.run(mnode, "gluster volume stop %s %s --mode=script" \ - % (volname, frce)) - if ret[0] != 0: - return False - return True + cmd = "gluster volume stop %s %s --mode=script" % (volname, frce) + return tc.run(mnode, cmd) -def delete_volume(volname, mnode=''): - """ - Deletes the gluster volume - Returns True if success and False if failure +def delete_volume(volname, mnode=None): + """Deletes the gluster volume if given volume exists in + gluster and deletes the directories in the bricks + associated with the given volume + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + bool: True, if volume is deleted + False, otherwise """ - if mnode == '': + + if mnode is None: mnode = tc.servers[0] + volinfo = get_volume_info(volname, mnode) if volinfo is None or volname not in volinfo: tc.logger.info("Volume %s does not exist in %s" % (volname, mnode)) return True - bricks = volinfo[volname]['bricks'] - ret = tc.run(mnode, "gluster volume delete %s --mode=script" % volname) - if ret[0] != 0: + + if volinfo[volname]['typeStr'] == 'Tier': + tmp_hot_brick = volinfo[volname]["bricks"]["hotBricks"]["brick"] + hot_bricks = [x["name"] for x in tmp_hot_brick if "name" in x] + tmp_cold_brick = volinfo[volname]["bricks"]["coldBricks"]["brick"] + cold_bricks = [x["name"] for x in tmp_cold_brick if "name" in x] + bricks = hot_bricks + cold_bricks + else: + bricks = [x["name"] for x in volinfo[volname]["bricks"]["brick"] + if "name" in x] + ret, _, _ = tc.run(mnode, "gluster volume delete %s --mode=script" + % volname) + if ret != 0: return False try: del tc.global_flag[volname] @@ -186,82 +248,81 @@ def delete_volume(volname, mnode=''): return True -def reset_volume(volname, mnode='', force=False): - """ - Reset the gluster volume - Returns True if success and False if failure +def reset_volume(volname, mnode=None, force=False): + """Resets the gluster volume + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + force (bool): If this option is set to True, then reset volume + will get executed with force option. If it is set to False, + then reset volume will get executed without force option + + 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. + + Example: + reset_volume("testvol") """ - if mnode == '': + if mnode is None: mnode = tc.servers[0] frce = '' if force: frce = 'force' - ret = tc.run(mnode, "gluster volume reset %s %s --mode=script" \ - % (volname, frce)) - if ret[0] != 0: - return False - return True + cmd = "gluster volume reset %s %s --mode=script" % (volname, frce) + return tc.run(mnode, cmd) -def cleanup_volume(volname, mnode=''): - """ - stops and deletes the volume - returns True on success and False otherwise +def cleanup_volume(volname, mnode=None): + """deletes snapshots in the volume, stops and deletes the gluster + volume if given volume exists in gluster and deletes the + directories in the bricks associated with the given volume + + Args: + volname (str): volume name - TODO: Add snapshot cleanup part here + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + bool: True, if volume is deleted successfully + False, otherwise + + Example: + cleanup_volume("testvol") """ - if mnode == '': + from distaflibs.gluster.snap_ops import snap_delete_by_volumename + + if mnode is None: mnode = tc.servers[0] - ret = stop_volume(volname, mnode, True) | \ - delete_volume(volname, mnode) - if not ret: - tc.logger.error("Unable to cleanup the volume %s" % volname) - return False - return True + ret, _, _ = snap_delete_by_volumename(volname, mnode=mnode) + if ret != 0: + tc.logger.error("Failed to delete the snapshots in " + "volume %s" % volname) + return False -def setup_meta_vol(servers=''): - """ - Creates, starts and mounts the gluster meta-volume on the servers - specified. - """ - if servers == '': - servers = tc.servers - meta_volname = 'gluster_shared_storage' - mount_point = '/var/run/gluster/shared_storage' - metav_dist = int(tc.config_data['META_VOL_DIST_COUNT']) - metav_rep = int(tc.config_data['META_VOL_REP_COUNT']) - _num_bricks = metav_dist * metav_rep - repc = '' - if metav_rep > 1: - repc = "replica %d" % metav_rep - bricks = '' - brick_root = "/bricks" - _n = 0 - for i in range(0, _num_bricks): - bricks = "%s %s:%s/%s_brick%d" % (bricks, servers[_n], \ - brick_root, meta_volname, i) - if _n < len(servers) - 1: - _n = _n + 1 - else: - _n = 0 - gluster_cmd = "gluster volume create %s %s %s force" \ - % (meta_volname, repc, bricks) - ret = tc.run(servers[0], gluster_cmd) - if ret[0] != 0: - tc.logger.error("Unable to create meta volume") + ret, _, _ = stop_volume(volname, mnode, True) + if ret != 0: + tc.logger.error("Failed to stop volume %s" % volname) return False - ret = start_volume(meta_volname, servers[0]) + + ret = delete_volume(volname, mnode) if not ret: - tc.logger.error("Unable to start the meta volume") + tc.logger.error("Unable to cleanup the volume %s" % volname) return False - time.sleep(5) - for server in servers: - ret = mount_volume(meta_volname, 'glusterfs', mount_point, server, \ - server) - if ret[0] != 0: - tc.logger.error("Unable to mount meta volume on %s" % server) - return False return True @@ -344,11 +405,51 @@ def setup_vol(volname, mnode=None, dist=1, rep=1, dispd=1, red=1, return True +def volume_status(volname='all', service='', options='', mnode=None): + """Executes gluster volume status cli command + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + volname (str): volume name. Defaults to 'all' + service (str): name of the service to get status. + serivce can be, [nfs|shd|<BRICK>|quotad]], If not given, + the function returns all the services + options (str): options can be, + [detail|clients|mem|inode|fd|callpool|tasks]. If not given, + the function returns the output of gluster volume status + + 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. + + Example: + volume_status() + """ + if mnode is None: + mnode = tc.servers[0] + + cmd = "gluster vol status %s %s %s" % (volname, service, options) + + return tc.run(mnode, cmd) + + def _parse_volume_status_xml(root_xml): """ Helper module for get_volume_status. It takes root xml object as input, parses and returns the 'volume' tag xml object. """ + for element in root_xml: if element.findall("volume"): return element.findall("volume") @@ -359,8 +460,8 @@ def _parse_volume_status_xml(root_xml): def parse_xml(tag_obj): """ - This module takes any xml element object and parses all the child nodes - and returns the parsed data in dictionary format + This helper module takes any xml element object and parses all the child + nodes and returns the parsed data in dictionary format """ node_dict = {} for tag in tag_obj: @@ -373,36 +474,59 @@ def parse_xml(tag_obj): return node_dict -def get_volume_status(volname='all', service='', options='', mnode=''): +def get_volume_status(volname='all', service='', options='', mnode=None): """ This module gets the status of all or specified volume(s)/brick - @parameter: - * mnode - <str> (optional) name of the node to execute the volume - status command. If not given, the function takes the - first node from config file - * volname - <str> (optional) name of the volume to get status. It not - given, the function returns the status of all volumes - * service - <str> (optional) name of the service to get status. - serivce can be, [nfs|shd|<BRICK>|quotad]], If not given, - the function returns all the services - * options - <str> (optional) options can be, - [detail|clients|mem|inode|fd|callpool|tasks]. If not given, - the function returns the output of gluster volume status - @Returns: volume status in dict of dictionary format, on success - None, on failure + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + volname (str): volume name. Defaults to 'all' + service (str): name of the service to get status. + serivce can be, [nfs|shd|<BRICK>|quotad]], If not given, + the function returns all the services + options (str): options can be, + [detail|clients|mem|inode|fd|callpool|tasks]. If not given, + the function returns the output of gluster volume status + Returns: + dict: volume status in dict of dictionary format, on success + NoneType: on failure + + Example: + get_volume_status(volname="testvol") + >>>{'testvol': {'10.70.47.89': {'/bricks/brick1/a11': {'status': '1', + 'pid': '28963', 'bricktype': 'cold', 'port': '49163', 'peerid': + '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': 'N/A', + 'tcp': '49163'}}, '/bricks/brick2/a31': {'status': '1', 'pid': + '28982', 'bricktype': 'cold', 'port': '49164', 'peerid': + '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': 'N/A', + 'tcp': '49164'}}, 'NFS Server': {'status': '1', 'pid': '30525', + 'port': '2049', 'peerid': '7fc9015e-8134-4753-b837-54cbc6030c98', + 'ports': {'rdma': 'N/A', 'tcp': '2049'}}, '/bricks/brick1/a12': + {'status': '1', 'pid': '30505', 'bricktype': 'hot', 'port': '49165', + 'peerid': '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': + 'N/A', 'tcp': '49165'}}}, '10.70.47.118': {'/bricks/brick1/a21': + {'status': '1', 'pid': '5427', 'bricktype': 'cold', 'port': '49162', + 'peerid': '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': {'rdma': + 'N/A', 'tcp': '49162'}}, '/bricks/brick2/a41': {'status': '1', 'pid': + '5446', 'bricktype': 'cold', 'port': '49163', 'peerid': + '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': {'rdma': 'N/A', + 'tcp': '49163'}}, 'NFS Server': {'status': '1', 'pid': '6397', 'port': + '2049', 'peerid': '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': + {'rdma': 'N/A', 'tcp': '2049'}}}}} """ - if mnode == '': + if mnode is None: mnode = tc.servers[0] cmd = "gluster vol status %s %s %s --xml" % (volname, service, options) - ret = tc.run(mnode, cmd) - if ret[0] != 0: + ret, out, _ = tc.run(mnode, cmd) + if ret != 0: tc.logger.error("Failed to execute gluster volume status command") return None - root = etree.XML(ret[1]) + root = etree.XML(out) volume_list = _parse_volume_status_xml(root) if volume_list is None: tc.logger.error("No volumes exists in the gluster") @@ -412,6 +536,8 @@ def get_volume_status(volname='all', service='', options='', mnode=''): for volume in volume_list: tmp_dict1 = {} tmp_dict2 = {} + hot_bricks = [] + cold_bricks = [] vol_name = [vol.text for vol in volume if vol.tag == "volName"] # parsing volume status xml output @@ -428,16 +554,45 @@ def get_volume_status(volname='all', service='', options='', mnode=''): else: tmp_dict2[node_name] = [tmp_dict3] else: - nodes = volume.findall("node") + elem_tag = [] + for elem in volume.getchildren(): + elem_tag.append(elem.tag) + if ('hotBricks' in elem_tag) or ('coldBricks' in elem_tag): + for elem in volume.getchildren(): + if (elem.tag == 'hotBricks'): + nodes = elem.findall("node") + hot_bricks = [node.find('path').text + for node in nodes + if ( + node.find('path').text.startswith('/'))] + if (elem.tag == 'coldBricks'): + for n in elem.findall("node"): + nodes.append(n) + cold_bricks = [node.find('path').text + for node in nodes + if ( + (node.find('path'). + text.startswith('/')))] + else: + nodes = volume.findall("node") + for each_node in nodes: if each_node.find('path').text.startswith('/'): node_name = each_node.find('hostname').text + elif each_node.find('path').text == 'localhost': + node_name = mnode else: node_name = each_node.find('path').text node_dict = parse_xml(each_node) tmp_dict3 = {} if "hostname" in node_dict.keys(): if node_dict['path'].startswith('/'): + if node_dict['path'] in hot_bricks: + node_dict["bricktype"] = 'hot' + elif node_dict['path'] in cold_bricks: + node_dict["bricktype"] = 'cold' + else: + node_dict["bricktype"] = 'None' tmp = node_dict["path"] tmp_dict3[node_dict["path"]] = node_dict else: @@ -445,7 +600,6 @@ def get_volume_status(volname='all', service='', options='', mnode=''): tmp = node_dict["hostname"] del tmp_dict3[tmp]["path"] del tmp_dict3[tmp]["hostname"] - if node_name in tmp_dict1.keys(): tmp_dict1[node_name].append(tmp_dict3) else: @@ -458,41 +612,48 @@ def get_volume_status(volname='all', service='', options='', mnode=''): tmp_dict2[node_name] = tmp_dict4 vol_status[vol_name[0]] = tmp_dict2 - tc.logger.debug("Volume status output: %s" \ + tc.logger.debug("Volume status output: %s" % pformat(vol_status, indent=10)) return vol_status -def get_volume_option(volname, option='all', server=''): - """ - This module gets the option values for the given volume. - @parameter: - * volname - <str> name of the volume to get status. - * option - <str> (optional) name of the volume option to get status. +def get_volume_option(volname, option='all', mnode=None): + """gets the option values for the given volume. + + Args: + volname (str): volume name + + Kwargs: + option (str): volume option to get status. If not given, the function returns all the options for the given volume - * server - <str> (optional) name of the server to execute the volume - status command. If not given, the function takes the - first node from config file - @Returns: value for the given volume option in dict format, on success - None, on failure + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + dict: value for the given volume option in dict format, on success + NoneType: on failure + + Example: + get_volume_option("testvol") """ - if server == '': - server = tc.servers[0] + if mnode is None: + mnode = tc.servers[0] cmd = "gluster volume get %s %s" % (volname, option) - ret = tc.run(server, cmd) - if ret[0] != 0: - tc.logger.error("Failed to execute gluster volume get command") + ret, out, _ = tc.run(mnode, cmd) + if ret != 0: + tc.logger.error("Failed to execute gluster volume get command" + "for volume %s" % volname) return None volume_option = {} - raw_output = ret[1].split("\n") + raw_output = out.split("\n") for line in raw_output[2:-1]: match = re.search(r'^(\S+)(.*)', line.strip()) if match is None: - tc.logger.error("gluster get volume output is not in \ - expected format") + tc.logger.error("gluster get volume output is not in " + "expected format") return None volume_option[match.group(1)] = match.group(2).strip() @@ -500,26 +661,116 @@ def get_volume_option(volname, option='all', server=''): return volume_option -def get_volume_info(volname='all', server=''): +def set_volume_options(volname, options, mnode=None): + """sets the option values for the given volume. + + Args: + volname (str): volume name + options (dict): volume options in key + value format + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + bool: True, if the volume option is set + False, on failure + + Example: + options = {"user.cifs":"enable","user.smb":"enable"} + set_volume_option("testvol", options=options) """ - Fetches the volume information as displayed in the volume info. + if mnode is None: + mnode = tc.servers[0] + _rc = True + for option in options: + cmd = ("gluster volume set %s %s %s" + % (volname, option, options[option])) + ret, _, _ = tc.run(mnode, cmd) + if ret != 0: + tc.logger.error("Unable to set value %s for option %s" + % (options[option], option)) + _rc = False + return _rc + + +def volume_info(volname='all', mnode=None): + """Executes gluster volume info cli command + + Kwargs: + volname (str): volume name. Defaults to 'all' + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + 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. + + Example: + volume_status() + """ + if mnode is None: + mnode = tc.servers[0] + + cmd = "gluster volume info %s" % volname + return tc.run(mnode, cmd) + + +def get_volume_info(volname='all', mnode=None): + """Fetches the volume information as displayed in the volume info. Uses xml output of volume info and parses the into to a dict - Returns a dict of dicts. - -- Volume name is the first key - -- distCount/replicaCount/Type etc are second keys - -- The value of the each second level dict depends on the key - -- For distCount/replicaCount etc the value is key - -- For bricks, the value is a list of bricks (hostname:/brick_path) + Kwargs: + volname (str): volume name. Defaults to 'all' + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + NoneType: If there are errors + dict: volume info in dict of dicts + + Example: + get_volume_info(volname="testvol") + >>>{'testvol': {'status': '1', 'xlators': None, 'disperseCount': '0', + 'bricks': {'coldBricks': {'colddisperseCount': '0', + 'coldarbiterCount': '0', 'coldBrickType': 'Distribute', + 'coldbrickCount': '4', 'numberOfBricks': '4', 'brick': + [{'isArbiter': '0', 'name': '10.70.47.89:/bricks/brick1/a11', + 'hostUuid': '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': + '0', 'name': '10.70.47.118:/bricks/brick1/a21', 'hostUuid': + '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': '0', 'name': + '10.70.47.89:/bricks/brick2/a31', 'hostUuid': + '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': '0', + 'name': '10.70.47.118:/bricks/brick2/a41', 'hostUuid': + '7fc9015e-8134-4753-b837-54cbc6030c98'}], 'coldreplicaCount': '1'}, + 'hotBricks': {'hotBrickType': 'Distribute', 'numberOfBricks': '1', + 'brick': [{'name': '10.70.47.89:/bricks/brick1/a12', 'hostUuid': + '7fc9015e-8134-4753-b837-54cbc6030c98'}], 'hotbrickCount': '1', + 'hotreplicaCount': '1'}}, 'type': '5', 'distCount': '1', + 'replicaCount': '1', 'brickCount': '5', 'options': + {'cluster.tier-mode': 'cache', 'performance.readdir-ahead': 'on', + 'features.ctr-enabled': 'on'}, 'redundancyCount': '0', 'transport': + '0', 'typeStr': 'Tier', 'stripeCount': '1', 'arbiterCount': '0', + 'id': 'ffa8a8d1-546f-4ebf-8e82-fcc96c7e4e05', 'statusStr': 'Started', + 'optCount': '3'}} """ - if server == '': - server = tc.servers[0] - ret = tc.run(server, "gluster volume info %s --xml" % volname, \ - verbose=False) - if ret[0] != 0: + if mnode is None: + mnode = tc.servers[0] + + cmd = "gluster volume info %s --xml" % volname + ret, out, _ = tc.run(mnode, cmd, verbose=False) + if ret != 0: tc.logger.error("volume info returned error") return None - root = etree.XML(ret[1]) + root = etree.XML(out) volinfo = {} for volume in root.findall("volInfo/volumes/volume"): for elem in volume.getchildren(): @@ -527,10 +778,30 @@ def get_volume_info(volname='all', server=''): volname = elem.text volinfo[volname] = {} elif elem.tag == "bricks": - volinfo[volname]["bricks"] = [] - for el in elem.getiterator(): - if el.tag == "name": - volinfo[volname]["bricks"].append(el.text) + volinfo[volname]["bricks"] = {} + tag_list = [x.tag for x in elem.getchildren() if x] + if 'brick' in tag_list: + volinfo[volname]["bricks"]["brick"] = [] + for el in elem.getchildren(): + if el.tag == 'brick': + brick_info_dict = {} + for elmt in el.getchildren(): + brick_info_dict[elmt.tag] = elmt.text + (volinfo[volname]["bricks"]["brick"]. + append(brick_info_dict)) + + if el.tag == "hotBricks" or el.tag == "coldBricks": + volinfo[volname]["bricks"][el.tag] = {} + volinfo[volname]["bricks"][el.tag]["brick"] = [] + for elmt in el.getchildren(): + if elmt.tag == 'brick': + brick_info_dict = {} + for el_brk in elmt.getchildren(): + brick_info_dict[el_brk.tag] = el_brk.text + (volinfo[volname]["bricks"][el.tag]["brick"]. + append(brick_info_dict)) + else: + volinfo[volname]["bricks"][el.tag][elmt.tag] = elmt.text elif elem.tag == "options": volinfo[volname]["options"] = {} for option in elem.findall("option"): @@ -541,28 +812,138 @@ def get_volume_info(volname='all', server=''): volinfo[volname]["options"][opt] = el.text else: volinfo[volname][elem.tag] = elem.text + + tc.logger.debug("Volume info output: %s" + % pformat(volinfo, indent=10)) + return volinfo -def set_volume_option(volname, options, server=''): +def sync_volume(hostname, volname="all", mnode=None): + """syncs the volume + + Args: + hostname (str): host name + + Kwargs: + volname (str): volume name. Defaults to 'all'. + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + 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. + + Example: + sync_volume("abc.xyz.com",volname="testvol") """ - This module sets the option values for the given volume. - @parameter: - * volname - <str> name of the volume to get status. - * option - list of <dict> volume options in key value format. - * server - <str> (optional) name of the server to execute the volume - status command. If not given, the function takes the - first node from config file - @Returns: True, on success - False, on failure + if mnode is None: + mnode = tc.servers[0] + + cmd = "gluster volume sync %s %s --mode=script" % (hostname, volname) + return tc.run(mnode, cmd) + + +def get_subvols(volname, mnode=None): + """Gets the subvolumes in the given volume + + Args: + volname (str): volume name + + Kwargs: + mnode (str): Node on which cmd has to be executed. + If None, defaults to servers[0]. + + Returns: + dict: with empty list values for all keys, if volume doesn't exist + dict: Dictionary of subvols, value of each key is list of lists + containing subvols + Example: + get_subvols("testvol") """ - if server == '': - server = tc.servers[0] - _rc = True - for option in options: - cmd = "gluster volume set %s %s %s" % (volname, option, \ - options[option]) - ret = tc.run(server, cmd) - if ret[0] != 0: - _rc = False - return _rc + + subvols = { + 'hot_tier_subvols': [], + 'cold_tier_subvols': [], + 'volume_subvols': [] + } + if mnode is None: + mnode = tc.servers[0] + volinfo = get_volume_info(volname, mnode) + if volinfo is not None: + voltype = volinfo[volname]['typeStr'] + if voltype == 'Tier': + hot_tier_type = (volinfo[volname]["bricks"] + ['hotBricks']['hotBrickType']) + tmp = volinfo[volname]["bricks"]['hotBricks']["brick"] + hot_tier_bricks = [x["name"] for x in tmp if "name" in x] + if (hot_tier_type == 'Distribute'): + for brick in hot_tier_bricks: + subvols['hot_tier_subvols'].append([brick]) + + elif (hot_tier_type == 'Replicate' or + hot_tier_type == 'Distributed-Replicate'): + rep_count = int((volinfo[volname]["bricks"]['hotBricks'] + ['numberOfBricks']).split("=", 1)[0]. + split("x")[1].strip()) + subvol_list = ([hot_tier_bricks[i:i + rep_count] + for i in range(0, len(hot_tier_bricks), + rep_count)]) + subvols['hot_tier_subvols'] = subvol_list + cold_tier_type = (volinfo[volname]["bricks"]['coldBricks'] + ['coldBrickType']) + tmp = volinfo[volname]["bricks"]['coldBricks']["brick"] + cold_tier_bricks = [x["name"] for x in tmp if "name" in x] + if (cold_tier_type == 'Distribute' or + cold_tier_type == 'Disperse'): + for brick in cold_tier_bricks: + subvols['cold_tier_subvols'].append([brick]) + + elif (cold_tier_type == 'Replicate' or + cold_tier_type == 'Distributed-Replicate'): + rep_count = int((volinfo[volname]["bricks"]['coldBricks'] + ['numberOfBricks']).split("=", 1)[0]. + split("x")[1].strip()) + subvol_list = ([cold_tier_bricks[i:i + rep_count] + for i in range(0, len(cold_tier_bricks), + rep_count)]) + subvols['cold_tier_subvols'] = subvol_list + + elif (cold_tier_type == 'Distributed-Disperse'): + disp_count = sum([int(nums) for nums in + ((volinfo[volname]["bricks"]['coldBricks'] + ['numberOfBricks']).split("x", 1)[1]. + strip().split("=")[0].strip().strip("()"). + split()) if nums.isdigit()]) + subvol_list = [cold_tier_bricks[i:i + disp_count] + for i in range(0, len(cold_tier_bricks), + disp_count)] + subvols['cold_tier_subvols'] = subvol_list + return subvols + + tmp = volinfo[volname]["bricks"]["brick"] + bricks = [x["name"] for x in tmp if "name" in x] + if voltype == 'Replicate' or voltype == 'Distributed-Replicate': + rep_count = int(volinfo[volname]['replicaCount']) + subvol_list = [bricks[i:i + rep_count]for i in range(0, + len(bricks), + rep_count)] + subvols['volume_subvols'] = subvol_list + elif voltype == 'Distribute' or voltype == 'Disperse': + for brick in bricks: + subvols['volume_subvols'].append([brick]) + + elif voltype == 'Distributed-Disperse': + disp_count = int(volinfo[volname]['disperseCount']) + subvol_list = [bricks[i:i + disp_count]for i in range(0, + len(bricks), + disp_count)] + subvols['volume_subvols'] = subvol_list + return subvols |