Change in vdsm[master]: gluster: Get size information of a gluster volume.
dnarayan at redhat.com
dnarayan at redhat.com
Wed Apr 2 05:17:27 UTC 2014
Darshan N has uploaded a new change for review.
Change subject: gluster: Get size information of a gluster volume.
......................................................................
gluster: Get size information of a gluster volume.
New vdsm gluster verb to get free, used and total size of
gluster volume. This verb uses gluster-libgfapi to get the
statistics related to volume.
verb: glusterVolumeStatsInfoGet
Output format:
{"sizeTotal": LONG as STR, "sizeFree": LONG as STR, "sizeUsed": LONG as STR}
Exception(s):
code: 4570
Name: GlusterVolumeStatsInfoGetFailedException
Message: Failed to get Gluster volume <VOL NAME> Stats
code: 4571
Name: GlusterVolumeIsNotOnlineException
Message: Failed to get Gluster volume stats
Change-Id: Ib628b10c3b9743bb9fef5cbf41195e69ff851efd
Signed-off-by: Darshan n <dnarayan at redhat.com>
---
M client/vdsClientGluster.py
M configure.ac
M vdsm.spec.in
M vdsm/Makefile.am
M vdsm/gluster/Makefile.am
M vdsm/gluster/__init__.py
M vdsm/gluster/api.py
M vdsm/gluster/exception.py
A vdsm/gluster/statvfs.py
M vdsm/gluster/vdsmapi-gluster-schema.json
A vdsm/gluster_glfs/Makefile.am
A vdsm/gluster_glfs/__init__.py
A vdsm/gluster_glfs/glfs_vol.h
A vdsm/gluster_glfs/setup.py
A vdsm/gluster_glfs/volCap.c
15 files changed, 313 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/43/26343/1
diff --git a/client/vdsClientGluster.py b/client/vdsClientGluster.py
index 9fa58b2..421c853 100644
--- a/client/vdsClientGluster.py
+++ b/client/vdsClientGluster.py
@@ -422,6 +422,14 @@
pp.pprint(status)
return status['status']['code'], status['status']['message']
+ def do_glusterVolumeStatsInfoGet(self, args):
+ params = self._eqSplit(args)
+ volumeName = params.get('volumeName', '')
+
+ status = self.s.glusterVolumeStatsInfoGet(volumeName)
+ pp.pprint(status)
+ return status['status']['code'], status['status']['message']
+
def getGlusterCmdDict(serv):
return \
@@ -718,4 +726,9 @@
('[taskIds=<task_id1,task_id2,..>]',
'list all or given gluster tasks'
)),
+ 'glusterVolumeStatsInfoGet': (
+ serv.do_glusterVolumeStatsInfoGet,
+ ('volumeName=<volume name>',
+ 'Returns total, free and used space(bytes) of gluster volume'
+ )),
}
diff --git a/configure.ac b/configure.ac
index 71f91bc..d260e4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -270,6 +270,7 @@
vdsm-tool/Makefile
vdsm/Makefile
vdsm/gluster/Makefile
+ vdsm/gluster_glfs/Makefile
vdsm/netconf/Makefile
vdsm/sos/Makefile
vdsm/storage/Makefile
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 6c92b15..77e563e 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -1,4 +1,3 @@
-# Packages names
%global vdsm_name vdsm
%global vdsm_bootstrap vdsm-bootstrap
%global vdsm_reg vdsm-reg
@@ -61,6 +60,7 @@
BuildRequires: python-nose
BuildRequires: python-netaddr
BuildRequires: rpm-build
+BuildRequires: glusterfs-devel
# BuildRequires needed by the tests during the build
BuildRequires: dosfstools
@@ -587,7 +587,6 @@
%if 0%{?with_gluster}
%package gluster
Summary: Gluster Plugin for VDSM
-BuildArch: noarch
Requires: %{name} = %{version}-%{release}
Requires: glusterfs-server
@@ -629,6 +628,7 @@
# Install the respawn utility
install -Dm 0755 init/sysvinit/respawn \
%{buildroot}%{_datadir}/%{vdsm_name}/respawn
+
# Install the lvm rules
install -Dm 0644 vdsm/storage/vdsm-lvm.rules \
@@ -1431,12 +1431,22 @@
%dir %{_datadir}/%{vdsm_name}/gluster
%doc COPYING
%{_datadir}/%{vdsm_name}/gluster/api.py*
+%{_datadir}/%{vdsm_name}/gluster/statvfs.py*
%{_datadir}/%{vdsm_name}/gluster/vdsmapi-gluster-schema.json
%{_datadir}/%{vdsm_name}/gluster/hooks.py*
%{_datadir}/%{vdsm_name}/gluster/services.py*
%{_datadir}/%{vdsm_name}/gluster/tasks.py*
%endif
+%if 0%{?with_gluster}
+%defattr(-, root, root, -)
+%dir %{_datadir}/%{vdsm_name}/gluster_glfs
+%doc COPYING
+%{_datadir}/%{vdsm_name}/gluster_glfs/__init__.py*
+%{_datadir}/%{vdsm_name}/gluster_glfs/capacity.so*
+%endif
+
+
%changelog
* Sun Oct 13 2013 Yaniv Bronhaim <ybronhei at redhat.com> - 4.13.0
- Removing vdsm-python-cpopen from the spec
diff --git a/vdsm/Makefile.am b/vdsm/Makefile.am
index 8ab0072..4e34936 100644
--- a/vdsm/Makefile.am
+++ b/vdsm/Makefile.am
@@ -18,7 +18,7 @@
# Refer to the README and COPYING files for full details of the license
#
-SUBDIRS = netconf sos storage gluster
+SUBDIRS = netconf sos storage gluster gluster_glfs
include $(top_srcdir)/build-aux/Makefile.subs
diff --git a/vdsm/gluster/Makefile.am b/vdsm/gluster/Makefile.am
index b397e95..f30d67f 100644
--- a/vdsm/gluster/Makefile.am
+++ b/vdsm/gluster/Makefile.am
@@ -32,6 +32,7 @@
cli.py \
exception.py \
hooks.py \
+ statvfs.py \
services.py \
tasks.py \
$(NULL)
diff --git a/vdsm/gluster/__init__.py b/vdsm/gluster/__init__.py
index 0aefb8d..f86a5dc 100644
--- a/vdsm/gluster/__init__.py
+++ b/vdsm/gluster/__init__.py
@@ -22,7 +22,7 @@
import tempfile
from functools import wraps
-MODULE_LIST = ('cli', 'hooks', 'services', 'tasks')
+MODULE_LIST = ('cli', 'hooks', 'services', 'tasks', 'statvfs')
def makePublic(func):
diff --git a/vdsm/gluster/api.py b/vdsm/gluster/api.py
index 761ee78..506cd10 100644
--- a/vdsm/gluster/api.py
+++ b/vdsm/gluster/api.py
@@ -306,6 +306,12 @@
status = self.svdsmProxy.glusterTasksList(taskIds)
return {'tasks': status}
+ @exportAsVerb
+ def volumeStatsInfoGet(self, volumeName, volumeServer='localhost',
+ options=None):
+ return self.svdsmProxy.glusterVolumeStatsInfoGet(volumeName,
+ volumeServer)
+
def getGlusterMethods(gluster):
l = []
diff --git a/vdsm/gluster/exception.py b/vdsm/gluster/exception.py
index 93a2225..1295ce4 100644
--- a/vdsm/gluster/exception.py
+++ b/vdsm/gluster/exception.py
@@ -486,3 +486,13 @@
prefix = "%s: " % (action)
self.message = prefix + "Service action is not supported"
self.err = [self.message]
+
+
+class GlusterVolumeStatsInfoGetFailedException(GlusterException):
+ code = 4570
+ message = "Failed to get Gluster volume Stats"
+
+
+class GlusterVolumeIsNotOnlineException(GlusterVolumeException):
+ code = 4571
+ message = "Failed to get Gluster volume stats"
diff --git a/vdsm/gluster/statvfs.py b/vdsm/gluster/statvfs.py
new file mode 100644
index 0000000..af8ea92
--- /dev/null
+++ b/vdsm/gluster/statvfs.py
@@ -0,0 +1,60 @@
+#
+# Copyright 2013 Red Hat, Inc.
+#
+# 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
+# (at your option) 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+import logging
+from gluster_glfs.capacity import statvfs
+import exception as ge
+from . import makePublic
+from . import cli
+
+log = logging.getLogger("Gluster")
+
+
+ at makePublic
+def volumeStatsInfoGet(volumeName, volumeServer="localhost"):
+ volume_data = cli.volumeInfo(volumeName=volumeName,
+ remoteServer=volumeServer)
+ if volumeName not in volume_data:
+ msg = "Volume \"%s\" does not exists" % volumeName
+ raise ge.GlusterVolumeNameErrorException(err=[msg])
+
+ if volume_data[volumeName]['volumeStatus'] == cli.VolumeStatus.OFFLINE:
+ msg = "Volume \"%s\" is not Online" % volumeName
+ raise ge.GlusterVolumeIsNotOnlineException(err=[msg])
+
+ try:
+ statvfsData = statvfs(volumeName, volumeServer)
+ except:
+ errMsg = "Failed to retrive statistics"
+ " of glusterfs volume %s" % volumeName
+ raise ge.GlusterVolumeSizeInfoGetFailedException(err=[errMsg])
+
+ # f_blocks = Total number of blocks
+ # f_bfree = Total number of blocks free
+ # f_bavail = Total number of blocks available for non root user
+ # total blocks available = f_blocks - (f_bfree - f_bavail)
+ total = ((statvfsData['f_blocks'] -
+ (statvfsData['f_bfree'] - statvfsData['f_bavail'])) *
+ statvfsData['f_bsize'])
+ free = statvfsData['f_bavail'] * statvfsData['f_bsize']
+ used = total - free
+
+ return {'sizeTotal': str(total),
+ 'sizeFree': str(free),
+ 'sizeUsed': str(used)}
diff --git a/vdsm/gluster/vdsmapi-gluster-schema.json b/vdsm/gluster/vdsmapi-gluster-schema.json
index 4e80679..7c30c9e 100644
--- a/vdsm/gluster/vdsmapi-gluster-schema.json
+++ b/vdsm/gluster/vdsmapi-gluster-schema.json
@@ -1205,3 +1205,37 @@
##
{'command': {'class': 'GlusterHost', 'name': 'list'},
'returns': ['HostList']}
+
+##
+# @GlusterVolumeStatsInfo:
+#
+# Gluster Volumes disk usage statistics
+#
+# @sizeTotal: Total space available in bytes
+#
+# @sizeFree: Free space available in bytes
+#
+# @sizeUsed: Used space in bytes
+#
+# Since: 4.14.0
+##
+{'type': 'GlusterVolumeStatsInfo',
+ 'data': {'sizeTotal': 'str', 'sizeFree': 'str', 'sizeUsed': 'str'}}
+
+##
+# @GlusterVolume.statsInfoGet:
+#
+# Get the list of Gluster volumes
+#
+# @volumeName: Gluster volume name
+#
+# @volumeServer: Gluster volume server default is localhost
+#
+# Returns:
+# Stats info of GlusterFS volume
+#
+# Since: 4.14.0
+##
+{'command': {'class': 'GlusterVolume', 'name': 'statsInfoGet'},
+ 'data': {'volumeName': 'str', 'volumeServer': 'str'},
+ 'returns': 'GlusterVolumeStatsInfo'}
diff --git a/vdsm/gluster_glfs/Makefile.am b/vdsm/gluster_glfs/Makefile.am
new file mode 100644
index 0000000..f10158a
--- /dev/null
+++ b/vdsm/gluster_glfs/Makefile.am
@@ -0,0 +1,19 @@
+statisticsdir = $(vdsmdir)/gluster_glfs
+dist_statistics_PYTHON = \
+ __init__.py \
+ capacity.so \
+ $(NULL)
+
+capacity.so: volCap.c setup.py
+ (cd $(srcdir);$(PYTHON) setup.py build \
+ --build-temp $(abs_builddir) --build-lib $(abs_builddir))
+
+all-local: capacity.so
+
+EXTRA_DIST = \
+ __init__.py \
+ volCap.c \
+ setup.py
+CLEANFILES = \
+ volcap.o \
+ capacity.so
diff --git a/vdsm/gluster_glfs/__init__.py b/vdsm/gluster_glfs/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vdsm/gluster_glfs/__init__.py
diff --git a/vdsm/gluster_glfs/glfs_vol.h b/vdsm/gluster_glfs/glfs_vol.h
new file mode 100644
index 0000000..80c8434
--- /dev/null
+++ b/vdsm/gluster_glfs/glfs_vol.h
@@ -0,0 +1,41 @@
+#include <syslog.h>
+
+#define GLFS_INIT_FAILURE -3
+#define GLFS_FINI_FAILURE -5
+#define DEFAULT_TRANSPORT "tcp"
+#define DEFAULT_SERVER "127.0.0.1"
+#define DEFAULT_SERVER_PORT 24007
+
+int get_volume (const char *volume_name, const char *server_name, glfs_t *fs)
+{
+ int ret = 0;
+ int rv = 0;
+
+ if (server_name)
+ {
+ ret = glfs_set_volfile_server(fs, DEFAULT_TRANSPORT, server_name, DEFAULT_SERVER_PORT);
+ }
+ else
+ {
+ ret = glfs_set_volfile_server(fs, DEFAULT_TRANSPORT, DEFAULT_SERVER, DEFAULT_SERVER_PORT);
+ }
+
+ ret = glfs_set_logging (fs, "/tmp/libg.txt", 2);
+
+ ret = glfs_init (fs);
+ if (ret != 0)
+ {
+ syslog (LOG_ERR, "glfs_init() failed with code %d",ret);
+ rv = GLFS_INIT_FAILURE;
+ ret = glfs_fini (fs);
+ if (ret != 0)
+ {
+ syslog (LOG_ERR, "glfs_fini() failed with code %d\n", ret);
+ }
+
+ return rv;
+ }
+ sleep(3);
+ return 0;
+}
+
diff --git a/vdsm/gluster_glfs/setup.py b/vdsm/gluster_glfs/setup.py
new file mode 100644
index 0000000..e934817
--- /dev/null
+++ b/vdsm/gluster_glfs/setup.py
@@ -0,0 +1,11 @@
+from distutils.core import setup, Extension
+
+module1 = Extension('capacity', sources=['volCap.c'],
+ libraries=['gfapi'])
+
+setup(name='capacity',
+ version='1.0',
+ description='gets volume capacity',
+ py_modules=['__init__'],
+ url='redhat.com',
+ ext_modules=[module1])
diff --git a/vdsm/gluster_glfs/volCap.c b/vdsm/gluster_glfs/volCap.c
new file mode 100644
index 0000000..bd3c646
--- /dev/null
+++ b/vdsm/gluster_glfs/volCap.c
@@ -0,0 +1,103 @@
+#include <Python.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include "/usr/include/glusterfs/api/glfs.h"
+#include "/usr/include/glusterfs/api/glfs-handles.h"
+#include "glfs_vol.h"
+
+#define USAGE_ERROR -1
+#define GLFS_NEW_FAILURE -2
+#define GLFS_STATVFS_FAILURE -4
+
+static PyObject *StatvfsError;
+
+int get_volume_statvfs (const char *volume_name, const char *server_name, struct statvfs *buf)
+{
+ glfs_t *fs = NULL;
+ int ret = 0;
+ struct statvfs statvfsinfo = {0, };
+ int rv = 0;
+
+ if (!(volume_name && buf))
+ {
+ return USAGE_ERROR;
+ }
+
+ fs = glfs_new (volume_name);
+ if (!fs)
+ {
+ syslog (LOG_ERR, "glfs_new: returned NULL");
+ return GLFS_NEW_FAILURE;
+ }
+ ret = get_volume(volume_name, server_name, fs);
+ if(ret!=0)
+ {
+ return ret;
+ }
+ ret = glfs_statvfs (fs, "/", &statvfsinfo);
+ if (ret == 0)
+ {
+ *buf = statvfsinfo;
+ }
+ else
+ {
+ syslog (LOG_ERR, "glfs_statvfs() failed with [%d:%s] for \"/\"\n", ret, strerror (errno));
+ rv = GLFS_STATVFS_FAILURE;
+ }
+ ret = glfs_fini (fs);
+ if (ret != 0)
+ {
+ syslog (LOG_ERR, "glfs_fini() failed with code %d\n", ret);
+ }
+ return rv;
+}
+
+static PyObject *glfspy_statvfs (PyObject *self, PyObject *args)
+{
+ char *volume_name = NULL;
+ char *server_name = NULL;
+ int port = 0;
+ char *transport = NULL;
+ struct statvfs buf = {0, };
+ int rv = 0;
+
+ StatvfsError = PyErr_NewException("statvfs.error", NULL, NULL);
+ setlogmask (LOG_UPTO (LOG_DEBUG));
+ openlog ("statvfs", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
+ syslog (LOG_INFO, "Invoking glfspy_statvfs to get the volume utlization");
+
+ if (!PyArg_ParseTuple (args, "s|ziz", &volume_name, &server_name, &port, &transport))
+ {
+ PyErr_SetString(StatvfsError, "Argument parsing failed");
+ return NULL;
+ }
+
+ rv = get_volume_statvfs (volume_name, server_name, &buf);
+ closelog ();
+ if(rv==0)
+ return Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i}","f_bsize",buf.f_bsize,"f_frsize",buf.f_frsize,"f_blocks",buf.f_blocks,"f_bfree",buf.f_bfree,"f_bavail",buf.f_bavail,"f_files",buf.f_files,"f_ffree",buf.f_ffree,"f_favail",buf.f_favail,"f_fsid",buf.f_fsid,"f_flag",buf.f_flag,"f_namemax",buf.f_namemax);
+ else{
+ if(rv == USAGE_ERROR)
+ PyErr_SetString(StatvfsError, "Usage error");
+ if(rv == GLFS_NEW_FAILURE)
+ PyErr_SetString(StatvfsError, "glfs_new() failed");
+ if(rv == GLFS_INIT_FAILURE)
+ PyErr_SetString(StatvfsError, "glfs_init() failed");
+ if(rv == GLFS_STATVFS_FAILURE)
+ PyErr_SetString(StatvfsError, "glfs_statvfs() failed");
+ return NULL;
+ }
+}
+
+
+static PyMethodDef glfspy_methods[] = {
+ { "statvfs", (PyCFunction)glfspy_statvfs, METH_VARARGS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+
+PyMODINIT_FUNC initcapacity ()
+{
+ Py_InitModule3 ("capacity", glfspy_methods, "gluster gfapi top level extension module.");
+}
--
To view, visit http://gerrit.ovirt.org/26343
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib628b10c3b9743bb9fef5cbf41195e69ff851efd
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Darshan N <dnarayan at redhat.com>
More information about the vdsm-patches
mailing list