diff options
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  | 
