summaryrefslogtreecommitdiffstats
path: root/gluster
diff options
context:
space:
mode:
authorPrashanth Pai <ppai@redhat.com>2015-02-24 14:40:25 +0530
committerThiago da Silva <thiago@redhat.com>2015-06-17 12:58:49 -0700
commit658ebecb84951fd8e418f15a5c8e2c8b1901b9d4 (patch)
tree1d60080d82fa66218081481965c322aef361e854 /gluster
parent904ca8ff630cb81fbd35ba337de12643376e058e (diff)
Refactor volume initialization code
* Validate inputs during initialization of Volume object. * Move glfs_new() and glfs_init() into mount() method. * Provide user consumable unmount() method. * Provide "mounted" property to Volume object. Users can now check state whether a volume is virtual mounted or not. Change-Id: Idc53ee7f9386ed995315bd5fb492a7d36f44875f Signed-off-by: Prashanth Pai <ppai@redhat.com>
Diffstat (limited to 'gluster')
-rw-r--r--gluster/exceptions.py18
-rwxr-xr-xgluster/gfapi.py129
2 files changed, 138 insertions, 9 deletions
diff --git a/gluster/exceptions.py b/gluster/exceptions.py
new file mode 100644
index 0000000..2bb4732
--- /dev/null
+++ b/gluster/exceptions.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2012-2015 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+class LibgfapiException(Exception):
+ pass
diff --git a/gluster/gfapi.py b/gluster/gfapi.py
index 3554657..8a02831 100755
--- a/gluster/gfapi.py
+++ b/gluster/gfapi.py
@@ -14,6 +14,7 @@ import os
import stat
import errno
from gluster import api
+from gluster.exceptions import LibgfapiException
class File(object):
@@ -201,22 +202,132 @@ class Dir(object):
class Volume(object):
- def __init__(self, host, volid, proto="tcp", port=24007):
+ def __init__(self, host, volname,
+ proto="tcp", port=24007, log_file=None, log_level=7):
+ """
+ Create a Volume object instance.
+
+ :param host: Host with glusterd management daemon running.
+ :param volname: Name of GlusterFS volume to be mounted and used.
+ :param proto: Transport protocol to be used to connect to management
+ daemon. Permitted values are "tcp" and "rdma".
+ :param port: Port number where gluster management daemon is listening.
+ :param log_file: Path to log file. When this is set to None, a new
+ logfile will be created in default log directory
+ i.e /var/log/glusterfs
+ :param log_level: Integer specifying the degree of verbosity.
+ Higher the value, more verbose the logging.
+
+ TODO: Provide an interface where user can specify volfile directly
+ instead of providing host and other details. This is helpful in cases
+ where user wants to load some non default xlator on client side. For
+ example, aux-gfid-mount or mount volume as read-only.
+ """
# Add a reference so the module-level variable "api" doesn't
# get yanked out from under us (see comment above File def'n).
self._api = api
- self.fs = api.glfs_new(volid)
- api.glfs_set_volfile_server(self.fs, proto, host, port)
- def __del__(self):
- self._api.glfs_fini(self.fs)
- self._api = None
+ self._mounted = False
+ self.fs = None
+ self.log_file = log_file
+ self.log_level = log_level
- def set_logging(self, path, level):
- api.glfs_set_logging(self.fs, path, level)
+ if None in (volname, host):
+ # TODO: Validate host based on regex for IP/FQDN.
+ raise LibgfapiException("Host and Volume name should not be None.")
+ if proto not in ('tcp', 'rdma'):
+ raise LibgfapiException("Invalid protocol specified.")
+ if not isinstance(port, (int, long)):
+ raise LibgfapiException("Invalid port specified.")
+
+ self.host = host
+ self.volname = volname
+ self.protocol = proto
+ self.port = port
+
+ @property
+ def mounted(self):
+ return self._mounted
def mount(self):
- return api.glfs_init(self.fs)
+ """
+ Mount a GlusterFS volume for use.
+ """
+ if self.fs and self._mounted:
+ # Already mounted
+ return
+
+ self.fs = api.glfs_new(self.volname)
+ if not self.fs:
+ raise LibgfapiException("glfs_new(%s) failed." % (self.volname))
+
+ ret = api.glfs_set_volfile_server(self.fs, self.protocol,
+ self.host, self.port)
+ if ret < 0:
+ # FIXME: For some reason, get_errno() is not able to capture
+ # proper errno. Until then..
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1196161
+ raise LibgfapiException("glfs_set_volfile_server(%s, %s, %s, "
+ "%s) failed." % (self.fs, self.protocol,
+ self.host, self.port))
+
+ self.set_logging(self.log_file, self.log_level)
+
+ if self.fs and not self._mounted:
+ ret = api.glfs_init(self.fs)
+ if ret < 0:
+ raise LibgfapiException("glfs_init(%s) failed." % (self.fs))
+ else:
+ self._mounted = True
+
+ def unmount(self):
+ """
+ Unmount a mounted GlusterFS volume.
+
+ Provides users a way to free resources instead of just waiting for
+ python garbage collector to call __del__() at some point later.
+ """
+ if self.fs:
+ ret = self._api.glfs_fini(self.fs)
+ if ret < 0:
+ raise LibgfapiException("glfs_fini(%s) failed." % (self.fs))
+ else:
+ # Succeeded. Protect against multiple unmount() calls.
+ self._mounted = False
+ self.fs = None
+
+ def __del__(self):
+ try:
+ self.unmount()
+ except LibgfapiException:
+ pass
+
+ def set_logging(self, log_file, log_level):
+ """
+ Set logging parameters. Can be invoked either before or after
+ invoking mount().
+
+ When invoked before mount(), the preferred log file and log level
+ choices are recorded and then later enforced internally as part of
+ mount()
+
+ When invoked at any point after mount(), the change in log file
+ and log level is instantaneous.
+
+ :param log_file: Path of log file.
+ If set to "/dev/null", nothing will be logged.
+ If set to None, a new logfile will be created in
+ default log directory (/var/log/glusterfs)
+ :param log_level: Integer specifying the degree of verbosity.
+ Higher the value, more verbose the logging.
+ """
+ if self.fs:
+ ret = api.glfs_set_logging(self.fs, self.log_file, self.log_level)
+ if ret < 0:
+ raise LibgfapiException("glfs_set_logging(%s, %s) failed." %
+ (self.log_file, self.log_level))
+ self.log_file = log_file
+ self.log_level = log_level
def chmod(self, path, mode):
"""