summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glustolibs-gluster-gd2/glustolibs/gluster/mount_ops.py302
-rw-r--r--glustolibs-gluster-gd2/glustolibs/gluster/peer_ops.py319
-rw-r--r--glustolibs-gluster-gd2/glustolibs/gluster/snap_ops.py307
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
+