summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBala Konda Reddy M <bmekala@redhat.com>2020-01-31 18:23:58 +0530
committerBala Konda Reddy M <bala12352@gmail.com>2020-03-16 06:34:15 +0000
commitd60d5c42692c547608c9a45f879d67e9c79e10ca (patch)
treeff142816228e13db4d64dafe1a74fc8f4015d8a1
parent730413b377895b04704048d1c03c3baccfb22fd2 (diff)
[Lib] Library for multi volume creation
Earlier, brick creation is carried out based on the difference of used and unused bricks. This is a bottleneck for implementing brick multiplexing testcases. Moreover we can't create more than 10 volumes. With this library, implementing a way to create bricks on top of the existing servers in a cyclic way to have equal number of bricks on each brick partition on each server Added paramter in setup_volume function, if multi_vol flag is set it will fetch bricks using cyclic manner using (form_bricks_for_multi_vol) otherwise it will fetch using old mechanism. Added bulk_volume_creation function, to create multiple volumes the user has specified. Change-Id: I2103ec6ce2be4e091e0a96b18220d5e3502284a0 Signed-off-by: Bala Konda Reddy M <bala12352@gmail.com>
-rw-r--r--glustolibs-gluster/glustolibs/gluster/brickmux_libs.py146
-rw-r--r--glustolibs-gluster/glustolibs/gluster/volume_libs.py79
2 files changed, 220 insertions, 5 deletions
diff --git a/glustolibs-gluster/glustolibs/gluster/brickmux_libs.py b/glustolibs-gluster/glustolibs/gluster/brickmux_libs.py
new file mode 100644
index 000000000..1206b4682
--- /dev/null
+++ b/glustolibs-gluster/glustolibs/gluster/brickmux_libs.py
@@ -0,0 +1,146 @@
+# Copyright (C) 2020 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 Brick multiplexing realted helper functions.
+"""
+
+from itertools import cycle
+try:
+ from itertools import zip_longest
+except ImportError:
+ from itertools import izip_longest as zip_longest
+
+from glusto.core import Glusto as g
+from glustolibs.gluster.volume_ops import get_volume_list
+from glustolibs.gluster.lib_utils import get_servers_bricks_dict
+
+
+def get_all_bricks_from_servers_multivol(servers, servers_info):
+ """
+ Form list of all the bricks to create/add-brick from the given
+ servers and servers_info
+
+ Args:
+ servers (list): List of servers in the storage pool.
+ servers_info (dict): Information about all servers.
+
+ Returns:
+ brickCount (int): Number of bricks available from the servers.
+ bricks_list (list): List of all bricks from the servers provided.
+
+ example :
+ servers_info = {
+ 'abc.lab.eng.xyz.com': {
+ 'host': 'abc.lab.eng.xyz.com',
+ 'brick_root': '/bricks',
+ 'devices': ['/dev/vdb', '/dev/vdc', '/dev/vdd', '/dev/vde']
+ },
+ 'def.lab.eng.xyz.com':{
+ 'host': 'def.lab.eng.xyz.com',
+ 'brick_root': '/bricks',
+ 'devices': ['/dev/vdb', '/dev/vdc', '/dev/vdd', '/dev/vde']
+ }
+ }
+ """
+ if not isinstance(servers, list):
+ servers = [servers]
+
+ brickCount, bricks_list = 0, []
+
+ servers_bricks = get_servers_bricks_dict(servers, servers_info)
+ server_ip = cycle(servers_bricks.keys())
+
+ for item in list(zip_longest(*list(servers_bricks.values()))):
+ for brick in item:
+ server = server_ip.next()
+ if brick:
+ bricks_list.append(server + ":" + brick)
+ brickCount += 1
+ return brickCount, bricks_list
+
+
+def get_current_brick_index(mnode):
+ """
+ Get the brick current index from the node of the cluster.
+
+ Args:
+ mnode (str): Node on which commands has to be executed.
+
+ Returns:
+ NoneType: If there are any errors
+ int: Count of the bricks in the cluster.
+ """
+ ret, brick_index, err = g.run(mnode, "gluster volume info | egrep "
+ "\"^Brick[0-9]+\" | grep -v \"ss_brick\"")
+ if ret:
+ g.log.error("Error in getting bricklist using gluster v info %s" % err)
+ return None
+
+ g.log.info("brick_index is ", brick_index)
+ return len(brick_index.splitlines())
+
+
+def form_bricks_for_multivol(mnode, volname, number_of_bricks, servers,
+ servers_info):
+ """
+ Forms brics list for volume create/add-brick given the number_of_bricks
+ servers, servers_info, for multiple volume cluster and for brick multiplex
+ enabled cluster.
+
+ Args:
+ mnode (str): Node on which commands has to be executed.
+ volname (str): Volume name for which we require brick-list
+ number_of_bricks (int): The number of bricks for which brick list
+ has to be created.
+ servers (str|list): A server|List of servers from which the bricks
+ needs to be selected for creating the brick list.
+ servers_info (dict): Dict of server info of each servers.
+
+ Returns:
+ list: List of bricks to use with volume create.
+ Nonetype: If unable to fetch the brick list
+
+ """
+ if not isinstance(servers, list):
+ servers = [servers]
+
+ brick_index, brick_list_for_volume = 0, []
+
+ # Importing get_all_bricks() from bricks_libs to avoid cyclic imports
+ from glustolibs.gluster.brick_libs import get_all_bricks
+
+ # Get all volume list present in the cluster from mnode
+ current_vol_list = get_volume_list(mnode)
+ for volume in current_vol_list:
+ brick_index = brick_index + len(get_all_bricks(mnode, volume))
+ g.log.info("current brick_index %s" % brick_index)
+
+ # Get all bricks_count and bricks_list
+ all_brick_count, bricks_list = get_all_bricks_from_servers_multivol(
+ servers, servers_info)
+ if not (all_brick_count > 1):
+ g.log.error("Unable to get the bricks present in the specified"
+ "servers")
+ return None
+
+ for num in range(number_of_bricks):
+ brick = brick_index % all_brick_count
+ brick_list_for_volume.append("%s/%s_brick%d" % (bricks_list[brick],
+ volname, brick_index))
+ brick_index += 1
+
+ return brick_list_for_volume
diff --git a/glustolibs-gluster/glustolibs/gluster/volume_libs.py b/glustolibs-gluster/glustolibs/gluster/volume_libs.py
index b530f80a1..a5e54101e 100644
--- a/glustolibs-gluster/glustolibs/gluster/volume_libs.py
+++ b/glustolibs-gluster/glustolibs/gluster/volume_libs.py
@@ -24,6 +24,7 @@ except ImportError:
import xml.etree.ElementTree as etree
from glusto.core import Glusto as g
from glustolibs.gluster.lib_utils import form_bricks_list
+from glustolibs.gluster.brickmux_libs import form_bricks_for_multivol
from glustolibs.gluster.volume_ops import (volume_create, volume_start,
set_volume_options, get_volume_info,
volume_stop, volume_delete,
@@ -65,7 +66,8 @@ def volume_exists(mnode, volname):
return False
-def setup_volume(mnode, all_servers_info, volume_config, force=False):
+def setup_volume(mnode, all_servers_info, volume_config, multi_vol=False,
+ force=False):
"""Setup Volume with the configuration defined in volume_config
Args:
@@ -106,6 +108,14 @@ def setup_volume(mnode, all_servers_info, volume_config, force=False):
'transport': 'tcp'}},
'options': {'performance.readdir-ahead': True}
}
+ Kwargs:
+ multi_vol (bool): True, If bricks need to created for multiple
+ volumes(more than 5)
+ False, Otherwise. By default, value is set to False.
+ force (bool): If this option is set to True, then volume creation
+ command is executed with force option.
+ False, without force option.
+ By default, value is set to False
Returns:
bool : True on successful setup. False Otherwise
@@ -261,10 +271,15 @@ def setup_volume(mnode, all_servers_info, volume_config, force=False):
return False
# get bricks_list
- bricks_list = form_bricks_list(mnode=mnode, volname=volname,
- number_of_bricks=number_of_bricks,
- servers=servers,
- servers_info=all_servers_info)
+ if multi_vol:
+ bricks_list = form_bricks_for_multivol(
+ mnode=mnode, volname=volname, number_of_bricks=number_of_bricks,
+ servers=servers, servers_info=all_servers_info)
+ else:
+ bricks_list = form_bricks_list(mnode=mnode, volname=volname,
+ number_of_bricks=number_of_bricks,
+ servers=servers,
+ servers_info=all_servers_info)
if not bricks_list:
g.log.error("Number_of_bricks is greater than the unused bricks on "
"servers")
@@ -407,6 +422,60 @@ def setup_volume(mnode, all_servers_info, volume_config, force=False):
return True
+def bulk_volume_creation(mnode, number_of_volumes, servers_info,
+ volume_config, vol_prefix="mult_vol_",
+ is_force=False):
+ """
+ Creates the number of volumes user has specified
+
+ Args:
+ mnode (str): Node on which commands has to be executed.
+ number_of_volumes (int): Specify the number of volumes
+ to be created.
+ servers_info (dict): Information about all servers.
+ volume_config (dict): Dict containing the volume information
+
+ Kwargs:
+ vol_prefix (str): Prefix to be added to the volume name.
+ is_force (bool): True, If volume create command need to be executed
+ with force, False Otherwise. Defaults to False
+ Returns:
+ bool: True on successful bulk volume creation, False Otherwise.
+
+ example:
+ volume_config = {
+ 'name': 'testvol',
+ 'servers': ['server-vm1', 'server-vm2', 'server-vm3',
+ 'server-vm4'],
+ 'voltype': {'type': 'distributed',
+ 'dist_count': 4,
+ 'transport': 'tcp'},
+ 'extra_servers': ['server-vm9', 'server-vm10',
+ 'server-vm11', 'server-vm12'],
+ 'quota': {'limit_usage': {'path': '/', 'percent': None,
+ 'size': '100GB'},
+ 'enable': False},
+ 'uss': {'enable': False},
+ 'options': {'performance.readdir-ahead': True}
+ }
+ """
+
+ if not (number_of_volumes > 1):
+ g.log.error("Provide number of volume greater than 1")
+ return False
+
+ volume_name = volume_config['name']
+ for volume in range(number_of_volumes):
+ volume_config['name'] = vol_prefix + volume_name + str(volume)
+ ret = setup_volume(mnode, servers_info, volume_config, multi_vol=True,
+ force=is_force)
+ if not ret:
+ g.log.error("Volume creation failed for the volume %s"
+ % volume_config['name'])
+ return False
+ return True
+
+
def cleanup_volume(mnode, volname):
"""deletes snapshots in the volume, stops and deletes the gluster
volume if given volume exists in gluster and deletes the