diff options
-rw-r--r-- | glustolibs-gluster-gd2/glustolibs/gluster/mount_ops.py | 302 | ||||
-rw-r--r-- | glustolibs-gluster-gd2/glustolibs/gluster/peer_ops.py | 319 | ||||
-rw-r--r-- | glustolibs-gluster-gd2/glustolibs/gluster/snap_ops.py | 307 |
3 files changed, 928 insertions, 0 deletions
diff --git a/glustolibs-gluster-gd2/glustolibs/gluster/mount_ops.py b/glustolibs-gluster-gd2/glustolibs/gluster/mount_ops.py new file mode 100644 index 0000000..da0a993 --- /dev/null +++ b/glustolibs-gluster-gd2/glustolibs/gluster/mount_ops.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python +# Copyright (C) 2018 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 Mount operations. +""" + + +from glusto.core import Glusto as g +from glustolibs.gluster.exceptions import ConfigError +import copy + +class GlusterMount(): + """Gluster Mount class + Args: + mount (dict): Mount dict with mount_protocol, mountpoint, + server, client, volname, options + Example: + mount = + {'protocol': 'glusterfs', + 'mountpoint': '/mnt/g1', + 'server': 'abc.lab.eng.xyz.com', + 'client': 'def.lab.eng.xyz.com', + 'volname': 'testvol', + 'options': '' + } + Returns: + Instance of GlusterMount class + """ + def __init__(self, mount): + # Check for missing parameters + for param in ['protocol', 'mountpoint', 'server', + 'client', 'volname', 'options']: + if param not in mount: + raise ConfigError("Missing key %s" % param) + + # Get Protocol + self.mounttype = mount.get('protocol', 'glusterfs') + + # Get mountpoint + if bool(mount.get('mountpoint', False)): + self.mountpoint = mount['mountpoint'] + else: + self.mountpoint = "/mnt/%s" % self.mounttype + + # Get server + self.server_system = mount.get('server', None) + + # Get client + self.client_system = mount.get('client', None) + + # Get Volume name + self.volname = mount['volname'] + + # Get options + self.options = mount.get('options', None) + + def mount(self): + """Mounts the volume + Args: + uses instance args passed at init + Returns: + bool: True on success and False on failure. + """ + ret, out, err = mount_volume(self.volname, mtype=self.mounttype, + mpoint=self.mountpoint, + mserver=self.server_system, + mclient=self.client_system, + options=self.options) + if ret: + g.log.error("Failed to mount the volume") + return False + return True + + def is_mounted(self): + """Tests for mount on client + Args: + uses instance args passed at init + Returns: + bool: True on success and False on failure. + """ + ret = is_volume_mounted(self.volname, + mpoint=self.mountpoint, + mserver=self.server_system, + mclient=self.client_system, + mtype=self.mounttype) + + if not ret: + g.log.error("Volume is not mounted") + return False + return True + + def unmount(self): + """Unmounts the volume + Args: + uses instance args passed at init + Returns: + bool: True on success and False on failure. + """ + (ret, out, err) = umount_volume(mclient=self.client_system, + mpoint=self.mountpoint, + mtype=self.mounttype) + if ret: + g.log.error("Failed to unmount the volume") + return False + return True + + +def is_volume_mounted(volname, mpoint, mserver, mclient, mtype): + """Check if mount exist. + Args: + volname (str): Name of the volume + mpoint (str): Mountpoint dir + mserver (str): Server to which it is mounted to + mclient (str): Client from which it is mounted. + mtype (str): Mount type (glusterfs) + Returns: + bool: True if mounted and False otherwise. + """ + # python will error on missing arg, so just checking for empty args here + for param in [volname, mpoint, mserver, mclient, mtype]: + if not param: + g.log.error("Missing arguments for mount.") + return False + + ret, _, _ = g.run(mclient, "mount | grep %s | grep %s | grep \"%s\"" + % (volname, mpoint, mserver)) + if ret: + g.log.debug("Volume %s is mounted at %s:%s" % (volname, mclient, + mpoint)) + return True + g.log.error("Volume %s is not mounted at %s:%s" % (volname, + mclient, + mpoint)) + return False + + +def mount_volume(volname, mtype, mpoint, mserver, mclient, options=''): + """Mount the gluster volume with specified options. + Args: + volname (str): Name of the volume to mount. + mtype (str): Protocol to be used to mount. + mpoint (str): Mountpoint dir. + mserver (str): Server to mount. + mclient (str): Client from which it has to be mounted. + Kwargs: + option (str): Options for the mount command. + Returns: + tuple: Tuple containing three elements (ret, out, err). + (0, '', '') if already mounted. + (ret, out, err) of mount commnd execution otherwise. + """ + if is_mounted(volname, mpoint, mserver, mclient, mtype): + g.log.debug("Volume %s is already mounted at %s" % + (volname, mpoint)) + return (0, '', '') + + if not options: + options = "-o %s" % options + + # Create mount dir + g.run(mclient, "test -d %s || mkdir -p %s" % (mpoint, mpoint)) + + # Mount + mcmd = ("mount -t %s %s %s:/%s %s" % + (mtype, options, mserver, volname, mpoint)) + + # Create mount + return g.run(mclient, mcmd) + + +def umount_volume(mclient, mpoint, mtype=''): + """Unmounts the mountpoint. + Args: + mclient (str): Client from which it has to be mounted. + mpoint (str): Mountpoint dir. + Kwargs: + mtype (str): Mounttype. Defaults to ''. + Returns: + tuple: Tuple containing three elements (ret, out, err) as returned by + umount command execution. + """ + cmd = ("umount %s || umount -f %s || umount -l %s" % + (mpoint, mpoint, mpoint)) + + return g.run(mclient, cmd) + + +def create_mount_objs(mounts): + """Creates GlusterMount class objects for the given list of mounts + Args: + mounts (list): list of mounts with each element being dict having the + specifics of each mount + Example: + mounts: [ + {'protocol': 'glusterfs', + 'mountpoint': '/mnt/g1', + 'server': 'abc.lab.eng.xyz.com', + 'client': {'host': 'def.lab.eng.xyz.com'}, + 'volname': 'testvol', + 'options': '', + 'num_of_mounts': 2} + ] + Returns: + list : List of GlusterMount class objects. + Example: + mount_objs = create_mount_objs(mounts) + """ + mount_obj_list = [] + for mount in mounts: + temp_mount = copy.deepcopy(mount) + if (mount['protocol'] == "glusterfs"): + if 'mountpoint' in mount and mount['mountpoint']: + temp_mount['mountpoint'] = mount['mountpoint'] + else: + temp_mount['mountpoint'] = ("/mnt/%s_%s" % + (mount['volname'], + mount['protocol'])) + + num_of_mounts = 1 + if 'num_of_mounts' in mount: + if mount['num_of_mounts']: + num_of_mounts = mount['num_of_mounts'] + if num_of_mounts > 1: + mount_dir = temp_mount['mountpoint'] + for count in range(1, num_of_mounts + 1): + if mount_dir != "*": + temp_mount['mountpoint'] = '_'.join( + [mount_dir, str(count)]) + + mount_obj_list.append(GlusterMount(temp_mount)) + else: + mount_obj_list.append(GlusterMount(temp_mount)) + + return mount_obj_list + + +def operate_mounts(mount_objs, operation): + """Mounts/Unmounts using the details as specified + in the each mount obj + Args: + mount_objs (list): list of mounts objects with each element being + the GlusterMount class object + operation (str): Mount/unmount + Returns: + bool : True if creating the mount for all mount_objs is successful. + False otherwise. + Example: + ret = operate_mounts(create_mount_objs(mounts), operation='mount') + """ + _rc = True + for mount_obj in mount_objs: + if operation == 'mount': + ret = mount_obj.mount() + elif operation == 'unmount': + ret = mount_obj.unmount() + else: + g.log.error("Operation not found") + _rc = False + return _rc + + +def create_mounts(mount_objs): + """Creates Mounts using the details as specified in the each mount obj + Args: + mount_objs (list): list of mounts objects with each element being + the GlusterMount class object + Returns: + bool : True if creating the mount for all mount_objs is successful. + False otherwise. + Example: + ret = create_mounts(create_mount_objs(mounts)) + """ + return operate_mounts(mount_objs, operation='mount') + + +def unmount_mounts(mount_objs): + """Unmounts using the details as specified in the each mount obj + Args: + mount_objs (list): list of mounts objects with each element being + the GlusterMount class object + Returns: + bool : True if unmounting the mount for all mount_objs is successful. + False otherwise. + Example: + ret = unmount_mounts(create_mount_objs(mounts)) + """ + return operate_mounts(mount_objs, operation='unmount') diff --git a/glustolibs-gluster-gd2/glustolibs/gluster/peer_ops.py b/glustolibs-gluster-gd2/glustolibs/gluster/peer_ops.py new file mode 100644 index 0000000..f24251b --- /dev/null +++ b/glustolibs-gluster-gd2/glustolibs/gluster/peer_ops.py @@ -0,0 +1,319 @@ +# Copyright (C) 2018 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: Library for gluster peer operations. +""" + +import json +import httplib +from glustolibs.gluster.rest import RestClient +from glusto.core import Glusto as g + +def peer_probe(mnode, server): + """Probe the specified server. + + Args: + mnode (str): Node on which command has to be executed. + server (str): Server to be peer probed. + + 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 error message + and error code of the the command execution. + """ + + data = {"addresses": [server]} + return RestClient(mnode).handle_request('POST', "/v1/peers", httplib.CREATED, data) + + +def pool_list(mnode): + """Runs 'gluster pool list' command on the specified node. + + Args: + mnode (str): Node on which command has to be executed. + + 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. + """ + return RestClient(mnode).handle_request('GET', "/v1/peers", httplib.OK, None) + + +def peer_detach(mnode, server): + """ Detach the specified server. + + Args: + mnode (str): Node on which command has to be executed. + server (str): Server to be peer detached. + + 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. + """ + + server_id = get_peer_id(mnode, server) + ret, out, err = RestClient(mnode).handle_request('DELETE', "/v1/peers/%s" + % server_id, httplib.NO_CONTENT, None) + if ret != httplib.NO_CONTENT: + returncode = 1 + g.log.error("Failed to peer detach the node '%s'.", server) + else: + returncode = 0 + + return (returncode, out, err) + + +def peer_status(mnode, peer=None): + """ Fetches the peer status + + Args: + mnode (str): Node on which command has to be executed. + + 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. + """ + + path = "/v1/peers" + if peer: + peerid = get_peer_id(mnode, peer) + path = "%s/%s" % (path, peerid) + return RestClient(mnode).handle_request('GET', path, httplib.OK, None) + + +def peer_edit(mnode, peerid, zone): + """ Edits the peer zone +_ + Args: + mnode (str): Node on which command has to be executed. + peerid (str): The peerid of the peer. + Zone (str): The zone details that has to be edited. + + 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. + """ + + data = {"metadata": {"zone": zone}} + return RestClient(mnode).handle_request("POST", "/v1/peers/%s" % peerid, + httplib.CREATED, data) + + +def get_peer_id(mnode, server): + """ + Returns the peer_id of the given server + + Args: + server (str) : A server to fetch peer-ids + + Returns: + server_id (str) : Peer-id of the given server/peer + """ + from glustolibs.gluster.lib_utils import get_ip_from_hostname + + _ip = node = ids = [] + _ip = get_ip_from_hostname([server]) + server = ''.join(_ip) + _, out, _ = pool_list(mnode) + output = json.loads(out) + for elem in output: + item = elem['client-addresses'][1].split(":") + node.append(item[0]) + item = elem['id'] + ids.append(item) + if server in node: + return ids[-1] + +def is_peer_connected(mnode, servers): + """Checks whether specified peer is in cluster and 'Connected' state. + + Args: + mnode (str): Node from which peer probe has to be executed. + servers (str): A server| list of servers to be validated. + + Returns + bool : True on success (peer in cluster and connected), False on + failure. + """ + from glustolibs.gluster.lib_utils import to_list + + servers = to_list(servers) + + for server in servers: + _, out, _ = peer_status(mnode, server) + out = json.loads(out) + if not out['online']: + g.log.error("The peer %s is not connected", server) + return False + return True + + +def nodes_from_pool_list(mnode): + """Return list of nodes from the 'gluster pool list'. + + Args: + mnode (str): Node on which command has to be executed. + + Returns: + NoneType: None if command execution fails. + list: List of nodes in pool on Success, Empty list on failure. + """ + _, pool_list_data, _ = pool_list(mnode) + server_list = json.loads(pool_list_data) + if server_list is None: + g.log.error("Unable to get Nodes from the pool list command.") + return None + + nodes = [] + for server in server_list: + nodes.append(server['name']) + return nodes + + +def peer_probe_servers(mnode, servers, validate=True): + """Probe specified servers and validate whether probed servers + are in cluster and connected state if validate is set to True. + + Args: + mnode (str): Node on which command has to be executed. + servers (str|list): A server|List of servers to be peer probed. + + Kwargs: + validate (bool): True to validate if probed peer is in cluster and + connected state. False otherwise. Defaults to True. + + Returns: + bool: True on success and False on failure. + """ + from glustolibs.gluster.lib_utils import to_list + + servers = to_list(servers) + + if mnode in servers: + servers.remove(mnode) + + # Get list of nodes from 'gluster pool list' + nodes_in_pool_list = nodes_from_pool_list(mnode) + if not nodes_in_pool_list: + g.log.error("Unable to get nodes from gluster pool list. " + "Failing peer probe.") + return False + + for server in servers: + if server not in nodes_in_pool_list: + ret, _, _ = peer_probe(mnode, server) + if ret != 0: + g.log.error("Failed to peer probe the node '%s'.", server) + return False + g.log.info("Successfully peer probed the node '%s'.", server) + + # Validating whether peer is in connected state after peer probe + if validate: + _rc = False + i = 0 + while i < 200: + if is_peer_connected(mnode, servers): + _rc = True + break + + if not _rc: + g.log.error("Peers are in not connected state") + g.log.info("All peers are in connected state") + return _rc + + +def peer_detach_servers(mnode, servers, validate=True): + """Detach peers and validate status of peer if validate is set to True. + + Args: + mnode (str): Node on which command has to be executed. + servers (str|list): A server|List of servers to be detached. + + Kwargs: + validate (bool): True if status of the peer needs to be validated, + False otherwise. Defaults to True. + + Returns: + bool: True on success and False on failure. + """ + + from glustolibs.gluster.lib_utils import to_list + + servers = to_list(servers) + + if mnode in servers: + servers.remove(mnode) + + for server in servers: + ret, _, _ = peer_detach(mnode, server) + if ret: + g.log.error("Failed to peer detach the node '%s'.", server) + return False + + # Validating whether peer detach is successful + if validate: + i = 0 + while i < 200: + count = 0 + nodes_in_pool = nodes_from_pool_list(mnode) + _rc = True + for server in servers: + if server in nodes_in_pool: + g.log.error("Peer '%s' still in pool", server) + _rc = False + count += 1 + if not count: + break + + if not _rc: + g.log.error("Validation after peer detach failed.") + g.log.info("Validation after peer detach is successful") + return _rc diff --git a/glustolibs-gluster-gd2/glustolibs/gluster/snap_ops.py b/glustolibs-gluster-gd2/glustolibs/gluster/snap_ops.py new file mode 100644 index 0000000..8e94e1d --- /dev/null +++ b/glustolibs-gluster-gd2/glustolibs/gluster/snap_ops.py @@ -0,0 +1,307 @@ +# Copyright (C) 2018-2019 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: Library for gluster snapshot operations. +""" + +import json +import httplib +from glusto.core import Glusto as g +from glustolibs.gluster.rest import RestClient +from glustolibs.gluster.volume_ops import volume_start, volume_stop + + +def snap_create(mnode, volname, snapname, timestamp=False, description=None): + """Creates snapshot for the given volume. + + Args: + mnode (str): Node on which cmd has to be executed. + volname (str): volume name + snapname (str): snapshot name + + Kwargs: + timestamp (bool): If this option is set to True, then + timestamps will get appended to the snapname. If this option + is set to False, then timestamps will not be appended to snapname. + description (str): description for snapshot creation + + 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: + snap_create("abc.com", testvol, testsnap) + + """ + data = {"snapname": snapname, "volname": volname, + "description": description, "timestamp": timestamp} + return RestClient(mnode).handle_request("POST", "/v1/snapshots", httplib.CREATED, data) + + +def snap_activate(mnode, snapname): + """Activates the given snapshot + + Args: + mnode (str): Node on which cmd has to be executed. + snapname (str): snapshot name to be activated + + 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: + snap_activate("abc.com", testsnap) + + """ + return RestClient(mnode).handle_request('POST', "/v1/snapshots/%s/activate" + % snapname, httplib.OK, None) + + +def snap_deactivate(mnode, snapname): + """Deactivates the given snapshot + + Args: + mnode (str): Node on which cmd has to be executed. + snapname (str): snapshot name to be deactivated + + 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: + snap_deactivate("abc.com", testsnap) + + """ + return RestClient(mnode).handle_request('POST', + "/v1/snapshots/%s/deactivate" + % snapname, httplib.OK, None) + + +def snap_clone(mnode, snapname, clonename): + """Clones the given snapshot + + Args: + mnode (str): Node on which cmd has to be executed. + snapname (str): snapshot name to be cloned + clonename (str): clone name + + 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: + snap_clone("abc.com", testsnap, clone1) + + """ + data = {"clonename": clonename} + return RestClient(mnode).handle_request('POST', "/v1/snapshots/%s/clone" + % snapname, httplib.CREATED, data) + + +def snap_restore(mnode, snapname): + """Snap restore for the given snapshot + + Args: + mnode (str): Node on which cmd has to be executed. + snapname (str): snapshot name to be cloned + + 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: + snap_restore(mnode, testsnap) + + """ + return RestClient(mnode).handle_request('POST', "/v1/snapshots/%s/restore" + % snapname, httplib.CREATED, None) + + +def snap_restore_complete(mnode, volname, snapname): + """stops the volume, restore the snapshot and starts the volume + + Args: + mnode (str): Node on which cmd has to be executed. + volname (str): volume name + snapname (str): snapshot name + + Returns: + bool: True on success, False on failure + + Example: + snap_restore_complete(mnode, testvol, testsnap) + + """ + + # Stopping volume before snap restore + ret, _, _ = volume_stop(mnode, volname) + if not ret: + g.log.error("Failed to stop %s volume before restoring snapshot %s + in node %s", volname, snapname, mnode) + return False + + ret, _, _ = snap_restore(mnode, snapname) + if ret: + g.log.error("Snapshot %s restore failed on node %s", snapname, mnode) + return False + + # Starting volume after snap restore + ret, _, _ = volume_start(mnode, volname) + if not ret: + g.log.error("Failed to start volume %s after restoring snapshot %s + in node %s" , volname, snapname, mnode) + return False + return True + + +def snap_info(mnode, snapname): + """Gets the snap info by snapname + + Args: + mnode (str): Node on which command has to be executed. + snapname (str): snapshot name + + Returns: + NoneType: None if command execution fails, parse errors. + dict: on success. + """ + return RestClient(mnode).handle_request('GET', "/v1/snapshots/%s" + % snapname, httplib.OK, None) + + +def snap_list(mnode): + """Lists the snapshots + + Args: + mnode (str): Node on which cmd has to be executed. + + 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. + """ + return RestClient(mnode).handle_request('GET', "/v1/snapshots", httplib.OK, None) + + +def get_snap_list(mnode): + """ Lists the snapname + + Args: + mnode (str): Node on which cmd has to be executed. + + Returns: + list: List containing the snapname if exists else returns None + + """ + _, out, _ = snap_list(mnode) + if out: + output = json.loads(out) + snap_info = output[0] + snaps_list = [] + for elem in snap_info['snaps']: + snaps = elem['snapinfo']['name'] + snaps_list.append(snaps) + return snaps_list + return None + + +def snap_status(mnode, snapname): + """Get the snap status by snapname + + Args: + mnode (str): Node on which command has to be executed. + snapname (str): snapshot name + + 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. + + """ + return RestClient(mnode).handle_request('GET', "/v1/snapshots/%s/status" + % snapname, httplib.OK, None) + + +def snap_delete(mnode, snapname): + """Deletes the given snapshot + + Args: + mnode (str): Node on which cmd has to be executed. + snapname (str): snapshot name to be deleted + + 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. + """ + return RestClient(mnode).handle_request('DELETE', "/v1/snapshots/%s" + % snapname, httplib.DELETE, None) + # TODO: Few snapshot functions are yet to be automated after it is + # implemented in gd2 + |