diff options
author | Prashanth Pai <ppai@redhat.com> | 2015-02-24 14:40:25 +0530 |
---|---|---|
committer | Thiago da Silva <thiago@redhat.com> | 2015-06-17 12:58:49 -0700 |
commit | 658ebecb84951fd8e418f15a5c8e2c8b1901b9d4 (patch) | |
tree | 1d60080d82fa66218081481965c322aef361e854 /gluster | |
parent | 904ca8ff630cb81fbd35ba337de12643376e058e (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.py | 18 | ||||
-rwxr-xr-x | gluster/gfapi.py | 129 |
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): """ |