Change in vdsm[master]: Implement a zombie reaper
by smizrahi@redhat.com
Saggi Mizrahi has uploaded a new change for review.
Change subject: Implement a zombie reaper
......................................................................
Implement a zombie reaper
This is meant to solve the issues where one starts a process but doesn't
care about the return value.
By using zombieReaper.autoReapPID(pid) you can register the reaper to
automatically reap your process when it dies.
Change-Id: I0fdf96e195135284b2733b21f611918ffbf69791
Signed-off-by: Saggi Mizrahi <smizrahi(a)redhat.com>
---
M tests/Makefile.am
A tests/zombieReaperTests.py
M vdsm.spec.in
M vdsm/Makefile.am
M vdsm/vdsm
A vdsm/zombieReaper.py
6 files changed, 81 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/37/8937/1
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0e3763b..ac9804a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -47,7 +47,9 @@
tcTests.py \
vdsClientTests.py \
remoteFileHandlerTests.py \
- resourceManagerTests.py
+ resourceManagerTests.py \
+ zombieReaperTests.py \
+ $(NULL)
dist_noinst_DATA = \
run_tests_local.sh
diff --git a/tests/zombieReaperTests.py b/tests/zombieReaperTests.py
new file mode 100644
index 0000000..6406ce3
--- /dev/null
+++ b/tests/zombieReaperTests.py
@@ -0,0 +1,42 @@
+#
+# Copyright 2012 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
+#
+from time import sleep
+import os
+
+from testrunner import VdsmTestCase as TestCaseBase
+import zombieReaper
+from vdsm.betterPopen import BetterPopen
+
+
+class zombieReaperTests(TestCaseBase):
+ def setUp(self):
+ zombieReaper.registerSignalHandler()
+
+ def tearDown(self):
+ zombieReaper.unregisterSignalHandler()
+
+ def test(self):
+ p = BetterPopen(["sleep", "1"])
+ zombieReaper.autoReapPID(p.pid)
+ # wait for the grim reaper to arrive
+ sleep(4)
+
+ # Throws error because pid is not found or is not child
+ self.assertRaises(OSError, os.waitpid, p.pid, os.WNOHANG)
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 37f37a3..649581f 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -625,6 +625,7 @@
%{_datadir}/%{vdsm_name}/vdsm-store-net-config
%{_datadir}/%{vdsm_name}/vm.py*
%{_datadir}/%{vdsm_name}/write-net-config
+%{_datadir}/%{vdsm_name}/zombieReaper.py*
%attr (755,vdsm,kvm) %{_datadir}/%{vdsm_name}/nwfilter.py*
%config(noreplace) %{_sysconfdir}/%{vdsm_name}/logger.conf
%config(noreplace) %{_sysconfdir}/%{vdsm_name}/mom.conf
diff --git a/vdsm/Makefile.am b/vdsm/Makefile.am
index 7c79036..76a81c6 100644
--- a/vdsm/Makefile.am
+++ b/vdsm/Makefile.am
@@ -52,6 +52,7 @@
vdsmDebugPlugin.py \
vmChannels.py \
vm.py \
+ zombieReaper.py \
$(NULL)
dist_vdsmpylib_PYTHON = \
diff --git a/vdsm/vdsm b/vdsm/vdsm
index f2db404..00b99a0 100755
--- a/vdsm/vdsm
+++ b/vdsm/vdsm
@@ -20,6 +20,7 @@
from logging import config as lconfig
from vdsm import constants
+import zombieReaper
import dsaversion
if sys.version_info[0] == 2:
# as long as we work with Python 2, we need to monkey-patch threading
@@ -49,6 +50,7 @@
signal.signal(signal.SIGTERM, sigtermHandler)
signal.signal(signal.SIGUSR1, sigusr1Handler)
+ zombieReaper.registerSignalHandler()
from clientIF import clientIF # must import after config is read
cif = clientIF.getInstance(log)
diff --git a/vdsm/zombieReaper.py b/vdsm/zombieReaper.py
new file mode 100644
index 0000000..74b311d
--- /dev/null
+++ b/vdsm/zombieReaper.py
@@ -0,0 +1,32 @@
+import os
+import signal
+
+_trackedPids = set()
+
+
+def autoReapPID(pid):
+ _trackedPids.add(pid)
+ # SIGCHLD happend before we added the pid to the set
+ _tryReap(pid)
+
+
+def _tryReap(pid):
+ try:
+ pid, rv = os.waitpid(pid, os.WNOHANG)
+ if pid != 0:
+ _trackedPids.discard(pid)
+ except OSError:
+ _trackedPids.discard(pid)
+
+
+def _zombieReaper(signum, frame):
+ for pid in _trackedPids.copy():
+ _tryReap(pid)
+
+
+def registerSignalHandler():
+ signal.signal(signal.SIGCHLD, _zombieReaper)
+
+
+def unregisterSignalHandler():
+ signal.signal(signal.SIGCHLD, signal.SIG_DFL)
--
To view, visit http://gerrit.ovirt.org/8937
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0fdf96e195135284b2733b21f611918ffbf69791
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Saggi Mizrahi <smizrahi(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: vdsmapi: fix a pep8 glitch
by Dan Kenigsberg
Dan Kenigsberg has uploaded a new change for review.
Change subject: vdsmapi: fix a pep8 glitch
......................................................................
vdsmapi: fix a pep8 glitch
I've forgot to include it into Adam's former patch.
Change-Id: I05c77b507fcde6ea4072179da9ea03184635dd53
Signed-off-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm_api/vdsmapi.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/95/9195/1
diff --git a/vdsm_api/vdsmapi.py b/vdsm_api/vdsmapi.py
index 7a169bd..a91b233 100644
--- a/vdsm_api/vdsmapi.py
+++ b/vdsm_api/vdsmapi.py
@@ -197,7 +197,7 @@
return '%s *' % c_list_type(name[0])
elif is_enum(name):
return name
- elif name == None or len(name) == 0:
+ elif name is None or len(name) == 0:
return 'void'
elif name == name.upper():
return '%sEvent *' % camel_case(name)
--
To view, visit http://gerrit.ovirt.org/9195
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I05c77b507fcde6ea4072179da9ea03184635dd53
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Dan Kenigsberg <danken(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: jsonrpc: Implement the JsonRPC server for the next-gen API
by agl@us.ibm.com
Adam Litke has uploaded a new change for review.
Change subject: jsonrpc: Implement the JsonRPC server for the next-gen API
......................................................................
jsonrpc: Implement the JsonRPC server for the next-gen API
This patch implements a new Binding plugin to serve the next generation vdsm API
over a JsonRPC wire protocol. The basic format of a message is:
<size><json-data>
<size> is an unsigned 64 bit integer in big endian format that indicates the
length of <json-data> in bytes. <json-data> is either a request or a response
in Javascript object notation (JSON).
A request object has the following fields:
id: An integer which will be repeated in the matching response
methodName: The name of the API method to be called
args (optional): A JSON object containing arguments to the method
A response object has the following fields:
id: An integer which will be the same as the matching request
result: The return value of the method (defined in the API schema)
error: A JSON object containing error information
code: An integer error code
message: Error context information
Method calls are dispatched to vdsm using a MethodBridge. The DynamicBridge
dispatches calls based on an API schema document and a set of schema exceptions.
In this way, the API can be expanded without the need to add more code to this
server infrastructure. When a request is made, the DynamicBridge attempts to
resolve 'methodName' to a schema defined method. If found, the necessary
arguments are collected from the request and the function call is dispatched to
the internal vdsm API.
Schema exceptions:
Currently, vdsm does not completely conform to its own API schema. It is not
possible to correct all of the discrepencies due to the need to maintain
backwards compatibility with current API users. To facilitate migration to this
API, the DynamicBridge implements a set of overrides to translate between the
schema-defined API and what is implemented in vdsm today. There are three types
of method overrides and one type of argument override:
Method overrides:
1. Custom call function: If a new API does not map directly to an existing vdsm
API (or multiple functions must be called to get the result), a custom 'call'
function can be defined for the API. This function will be called instead of
trying to find a vdsm API to call.
2. Return field name: Many vdsm functions' return values are nested in a
dictionary. This override specifies the key to use when accessing the result
so that it can be returned un-nested to the caller.
3. Custom result post-processing function: Some vdsm APIs return results in a
non-standard format and a special function must be used to reformat the data
to comply with the schema.
Type override:
Some data types have a different representation internally to vdsm than we have
defined in the schema. A type override can be used to convert between the two
formats. Currently, the only kind of translation we do is to rename fields
within a given type.
Change-Id: Idae0faa80ffc6a5af002a8a7151aa40dc9a6673d
Signed-off-by: Adam Litke <agl(a)us.ibm.com>
---
M Makefile.am
M configure.ac
M tests/Makefile.am
A tests/apiData.py
A tests/apiTests.py
M tests/run_tests_local.sh.in
M vdsm.spec.in
M vdsm/clientIF.py
M vdsm/config.py.in
A vdsm_api/BindingJsonRpc.py
A vdsm_api/Bridge.py
A vdsm_api/Makefile.am
12 files changed, 725 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/14/8614/1
diff --git a/Makefile.am b/Makefile.am
index 7548f42..b1a0418 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@
# Refer to the README and COPYING files for full details of the license
#
-SUBDIRS = vdsm vdsm_cli vds_bootstrap vdsm_reg vdsm_hooks tests vdsm-tool
+SUBDIRS = vdsm vdsm_cli vds_bootstrap vdsm_reg vdsm_hooks tests vdsm-tool vdsm_api
include $(top_srcdir)/build-aux/Makefile.subs
@@ -112,8 +112,7 @@
vds_bootstrap/miniyum.py \
$(NULL)
-PEP8_BLACKLIST = \
- restData.py
+PEP8_BLACKLIST = apiData.py,restData.py
check-local:
find . -path './.git' -prune -type f -o \
diff --git a/configure.ac b/configure.ac
index 450f714..679ad04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,7 @@
AC_SUBST([vdsmpylibdir], ['${pyexecdir}/vdsm'])
AC_SUBST([vdsmtooldir], ['${vdsmpylibdir}/tool'])
AC_SUBST([vdsmtestsdir], ['${datarootdir}/vdsm/tests'])
+AC_SUBST([vdsmapidir], ['${datarootdir}/vdsm_api'])
# VDSM registration default paths
AC_SUBST([vdsmregdir], ['${datarootdir}/vdsm-reg'])
@@ -191,6 +192,7 @@
tests/Makefile
tests/functional/Makefile
vds_bootstrap/Makefile
+ vdsm_api/Makefile
vdsm_cli/Makefile
vdsm_hooks/directlun/Makefile
vdsm_hooks/faqemu/Makefile
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2b61dde..d1fca34 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,7 @@
test_modules = \
alignmentScanTests.py \
+ apiTests.py \
betterPopenTests.py \
betterThreadingTests.py \
capsTests.py \
@@ -66,6 +67,7 @@
dist_vdsmtests_PYTHON = \
$(test_modules) \
+ apiData.py \
monkeypatch.py \
testrunner.py \
testValidation.py
diff --git a/tests/apiData.py b/tests/apiData.py
new file mode 100644
index 0000000..fdb2611
--- /dev/null
+++ b/tests/apiData.py
@@ -0,0 +1,10 @@
+class APIData(object):
+ def __init__(self, obj, meth, data):
+ self.obj = obj
+ self.meth = meth
+ self.data = data
+
+testPing_apidata = [
+ APIData('Global', 'ping', {
+ 'status': {'code': 0, 'message': 'OK'}})
+]
diff --git a/tests/apiTests.py b/tests/apiTests.py
new file mode 100644
index 0000000..9bfe347
--- /dev/null
+++ b/tests/apiTests.py
@@ -0,0 +1,228 @@
+#
+# Copyright 2012 Adam Litke, IBM Corporation
+#
+# 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
+import os
+import os.path
+import socket
+import json
+import struct
+import time
+
+from testrunner import VdsmTestCase as TestCaseBase
+from vdsm import constants
+import apiData
+
+ip = '0.0.0.0'
+port = 9824
+_fakeret = {}
+
+apiWhitelist = ('StorageDomain.Classes', 'StorageDomain.Types',
+ 'Volume.Formats', 'Volume.Types', 'Volume.Roles', 'Image.DiskTypes')
+
+
+def getFakeAPI():
+ """
+ Create a Mock API module for testing. Mock API will return data from
+ the _fakeret global variable instead of calling into vdsm. _fakeret is
+ expected to have the following format:
+
+ {
+ '<class1>': {
+ '<func1>': [ <ret1>, <ret2>, ... ],
+ '<func2>': [ ... ],
+ }, '<class2>': {
+ ...
+ }
+ }
+ """
+ class FakeObj(object):
+ def __new__(cls, *args, **kwargs):
+ return object.__new__(cls)
+
+ def default(self, *args, **kwargs):
+ try:
+ return _fakeret[self.type][self.lastFunc].pop(0)
+ except (KeyError, IndexError):
+ raise Exception("No API data avilable for %s.%s" % \
+ (self.type, self.lastFunc))
+
+ def __getattr__(self, name):
+ # While we are constructing the API module, use the normal getattr
+ if 'API' not in sys.modules:
+ return object.__getattr__(name)
+ self.lastFunc = name
+ return self.default
+
+ import sys
+ import imp
+ from new import classobj
+
+ _API = __import__('API', globals(), locals(), {}, -1)
+ _newAPI = imp.new_module('API')
+
+ for obj in ('Global', 'ConnectionRefs', 'StorageDomain', 'Image', 'Volume',
+ 'Task', 'StoragePool', 'VM'):
+ cls = classobj(obj, (FakeObj,), {'type': obj})
+ setattr(_newAPI, obj, cls)
+
+ # Apply the whitelist to our version of API
+ for name in apiWhitelist:
+ parts = name.split('.')
+ dstObj = _newAPI
+ srcObj = _API
+ # Walk the object hierarchy copying each component of the whitelisted
+ # attribute from the real API to our fake one
+ for obj in parts:
+ srcObj = getattr(srcObj, obj)
+ try:
+ dstObj = getattr(dstObj, obj)
+ except AttributeError:
+ setattr(dstObj, obj, srcObj)
+
+ # Install our fake API into the module table for use by the whole program
+ sys.modules['API'] = _newAPI
+
+
+def findSchema():
+ """
+ Find the API schema file whether we are running tests from the source dir
+ or from the tests install location
+ """
+ scriptdir = os.path.dirname(__file__)
+ localpath = os.path.join(scriptdir, '../vdsm_api/vdsmapi-schema.json')
+ installedpath = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
+ for f in localpath, installedpath:
+ if os.access(f, os.R_OK):
+ return f
+ raise Exception("Unable to find schema in %s or %s",
+ localpath, installedpath)
+
+def setUpModule():
+ """
+ Set up the environment for all tests:
+ 1. Override the API so we can program our own return values
+ 2. Start an embedded server to process our requests
+ """
+ log = logging.getLogger('apiTests')
+ handler = logging.StreamHandler()
+ fmt_str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
+ formatter = logging.Formatter(fmt_str)
+ handler.setFormatter(formatter)
+ handler.setLevel(logging.INFO)
+ log.addHandler(handler)
+
+ schema = findSchema()
+ getFakeAPI()
+ import BindingJsonRpc
+ import Bridge
+ bridge = Bridge.DynamicBridge(schema)
+ server = BindingJsonRpc.BindingJsonRpc(bridge, ip, port)
+ server.start()
+
+
+class APITest(TestCaseBase):
+ def expectAPI(self, obj, meth, retval):
+ global _fakeret
+ if obj not in _fakeret:
+ _fakeret[obj] = {}
+ if meth not in _fakeret[obj]:
+ _fakeret[obj][meth] = []
+ _fakeret[obj][meth].append(retval)
+
+ def programAPI(self, key):
+ key += '_apidata'
+ for item in getattr(apiData, key):
+ self.expectAPI(item.obj, item.meth, item.data)
+
+ def clearAPI(self):
+ global _fakeret
+ _fakeret = {}
+
+class JsonRawTest(APITest):
+ _Size = struct.Struct("!Q")
+
+ def buildMessage(self, data):
+ msg = json.dumps(data)
+ msg = msg.encode('utf-8')
+ msize = JsonRawTest._Size.pack(len(msg))
+ resp = msize + msg
+ return resp
+
+ def sendMessage(self, msg):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ sock.connect((ip, port))
+ sock.sendall(msg)
+ data = sock.recv(JsonRawTest._Size.size)
+ msgLen = JsonRawTest._Size.unpack(data)[0]
+ data = sock.recv(msgLen)
+ return json.loads(data)
+ finally:
+ sock.close()
+
+ def testPing(self):
+ self.clearAPI()
+ self.programAPI("testPing")
+ msg = self.buildMessage({'id': 1, 'methodName': 'Host.ping',
+ 'args': {}})
+ reply = self.sendMessage(msg)
+ self.assertEquals(0, reply['error']['code'])
+ self.assertEquals('Success', reply['error']['message'])
+
+ def testNoMethod(self):
+ msg = self.buildMessage({'id': 1, 'methodName': 'Host.fake'})
+ reply = self.sendMessage(msg)
+ self.assertEquals(4, reply['error']['code'])
+
+ def testBadMethod(self):
+ msg = self.buildMessage({'id': 1, 'methodName': 'malformed\''})
+ reply = self.sendMessage(msg)
+ self.assertEquals(4, reply['error']['code'])
+
+ def testMissingSize(self):
+ self.assertRaises(struct.error, self.sendMessage,
+ "malformed message")
+
+ def testNotJson(self):
+ msg = "malformed message"
+ msize = JsonRawTest._Size.pack(len(msg))
+ msg = msize + msg
+ self.assertRaises(struct.error, self.sendMessage, msg)
+
+ def testSynchronization(self):
+ def doPing(msg):
+ self.clearAPI()
+ self.programAPI("testPing")
+ return self.sendMessage(msg)['error']['code']
+
+ msg = self.buildMessage({'id': 1, 'methodName': 'Host.ping'})
+ # Send Truncated message
+ self.assertRaises(struct.error, doPing, msg[:-1])
+
+ # Test that the server recovers
+ self.assertEquals(0, doPing(msg))
+
+ # Send too much data
+ self.assertEquals(0, doPing(msg + "Hello"))
+
+ # Test that the server recovers
+ self.assertEquals(0, doPing(msg))
+
diff --git a/tests/run_tests_local.sh.in b/tests/run_tests_local.sh.in
index fc4ac37..8f668f9 100644
--- a/tests/run_tests_local.sh.in
+++ b/tests/run_tests_local.sh.in
@@ -1,2 +1,2 @@
#!/bin/sh
-PYTHONDONTWRITEBYTECODE=1 LC_ALL=C PYTHONPATH="@builddir@/vdsm:@top_srcdir@/vdsm:@top_srcdir@/vdsm_cli:$PYTHONPATH" @PYTHON@ @top_srcdir(a)/tests/testrunner.py --local-modules $@
+PYTHONDONTWRITEBYTECODE=1 LC_ALL=C PYTHONPATH="@builddir@/vdsm:@top_srcdir@/vdsm:@top_srcdir@/vdsm_cli:@top_srcdir@/vdsm_api:$PYTHONPATH" @PYTHON@ @top_srcdir(a)/tests/testrunner.py --local-modules $@
diff --git a/vdsm.spec.in b/vdsm.spec.in
index dce14a9..8e7fa6c 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -154,6 +154,15 @@
%description rest
A REST interface for interacting with vdsmd.
+%package jsonrpc
+Summary: VDSM API Server
+BuildArch: noarch
+
+Requires: %{name}-python = %{version}-%{release}
+
+%description jsonrpc
+A Json-based RPC interface that serves as the protocol for libvdsm.
+
%package bootstrap
Summary: VDSM bootstrapping package
BuildArch: noarch
@@ -912,6 +921,12 @@
%{_datadir}/%{vdsm_name}/rest/templates/api.xsd
%{_datadir}/%{vdsm_name}/rest/templates/rsdl.xml
+%files jsonrpc
+%{_datadir}/%{vdsm_name}/BindingJsonRpc.py*
+%{_datadir}/%{vdsm_name}/Bridge.py*
+%{_datadir}/%{vdsm_name}/vdsmapi.py*
+%{_datadir}/%{vdsm_name}/vdsmapi-schema.json
+
%files bootstrap
%defattr(-, root, root, -)
%doc COPYING
diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py
index e9ca7c9..cf8468c 100644
--- a/vdsm/clientIF.py
+++ b/vdsm/clientIF.py
@@ -158,6 +158,15 @@
self.bindings['rest'] = BindingREST(self, self.log, ip, rest_port,
templatePath)
+ def _loadBindingJsonRpc(self):
+ from BindingJsonRpc import BindingJsonRpc
+ from Bridge import DynamicBridge
+ schema = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
+ ip = self._getServerIP(config.get('addresses', 'management_ip'))
+ port = config.getint('addresses', 'json_port')
+ self.bindings['json'] = BindingJsonRpc(DynamicBridge(schema),
+ ip, port)
+
def _prepareBindings(self):
self.bindings = {}
if config.getboolean('vars', 'xmlrpc_enable'):
@@ -172,6 +181,12 @@
except ImportError:
self.log.warn('Unable to load the rest server module. '
'Please make sure it is installed.')
+ if config.getboolean('vars', 'jsonrpc_enable'):
+ try:
+ self._loadBindingJsonRpc()
+ except ImportError:
+ self.log.warn('Unable to load the json rpc server module. '
+ 'Please make sure it is installed.')
def _prepareMOM(self):
try:
diff --git a/vdsm/config.py.in b/vdsm/config.py.in
index df85e7e..51a7ad6 100644
--- a/vdsm/config.py.in
+++ b/vdsm/config.py.in
@@ -130,6 +130,8 @@
('rest_enable', 'true', 'Enable the REST server'),
+ ('jsonrpc_enable', 'true', 'Enable the JSON RPC server'),
+
('report_host_threads_as_cores', 'false',
'Count each cpu hyperthread as an individual core'),
]),
@@ -251,6 +253,10 @@
'Port on which the vdsmd REST server listens to network '
'clients.'),
+ ('json_port', '4044',
+ 'Port on which the vdsmd Json RPC server listens to network '
+ 'clients.'),
+
('management_ip', '', None),
('guests_gateway_ip', '', None),
diff --git a/vdsm_api/BindingJsonRpc.py b/vdsm_api/BindingJsonRpc.py
new file mode 100644
index 0000000..9ac8b5d
--- /dev/null
+++ b/vdsm_api/BindingJsonRpc.py
@@ -0,0 +1,99 @@
+# VDSM JsonRPC Server
+# Copyright (C) 2012 Adam Litke, IBM Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+import threading
+import SocketServer
+import json
+import logging
+
+import struct
+
+_Size = struct.Struct("!Q")
+
+__bridge__ = None
+
+class BindingJsonRpc:
+ def __init__(self, bridge, ip, port):
+ self.bridge = bridge
+ self.serverPort = port
+ self.serverIP = ip
+ self.log = logging.getLogger('BindingJsonRpc')
+ self._createServer()
+
+ def _createServer(self):
+ global __bridge__
+ __bridge__ = self.bridge
+ ip = self.serverIP or '0.0.0.0'
+ self.server = JsonRpcServer((ip, self.serverPort), JsonRpcTCPHandler)
+
+ def start(self):
+ def threaded_start():
+ self.server.serve_forever()
+ t = threading.Thread(target=threaded_start,
+ name='JsonRpc')
+ t.setDaemon(True)
+ t.start()
+
+ def prepareForShutdown(self):
+ self.server.shutdown()
+
+
+class JsonRpcServer(SocketServer.TCPServer):
+ def __init__(self, addrInfo, handler):
+ self.allow_reuse_address = True
+ SocketServer.TCPServer.__init__(self, addrInfo, handler)
+
+
+class JsonRpcTCPHandler(SocketServer.StreamRequestHandler):
+ """
+ The RequestHandler class for our server.
+
+ It is instantiated once per connection to the server, and must
+ override the handle() method to implement communication to the
+ client.
+ """
+
+ def handle(self):
+ bridge = __bridge__
+ log = logging.getLogger('JsonRpcTCPHandler')
+ while True:
+ # self.request is the TCP socket connected to the client
+ try:
+ data = self.request.recv(_Size.size)
+ if len(data) == 0:
+ log.debug("Connection closed")
+ return
+ msgLen = _Size.unpack(data)[0]
+ msg = json.loads(self.request.recv(msgLen))
+ except:
+ log.warn("Unexpected exception", exc_info=True)
+ return
+ log.debug('--> %s', msg)
+
+ try:
+ ret = bridge._dispatch(msg['methodName'], msg.get('args', {}))
+ except Exception:
+ log.error("Dispatch error", exc_info=True)
+ continue
+ ret['id'] = msg['id']
+ msg = json.dumps(ret)
+ msg = msg.encode('utf-8')
+ msize = _Size.pack(len(msg))
+ resp = msize + msg
+ log.debug('<-- %s', msg)
+
+ self.wfile.write(resp)
+ self.wfile.flush()
+
diff --git a/vdsm_api/Bridge.py b/vdsm_api/Bridge.py
new file mode 100644
index 0000000..7402e08
--- /dev/null
+++ b/vdsm_api/Bridge.py
@@ -0,0 +1,332 @@
+# VDSM API Connector
+# Copyright (C) 2012 Adam Litke, IBM Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from functools import partial
+import vdsmapi
+import logging
+import types
+import API
+
+class VdsmError(Exception):
+ def __init__(self, code, message):
+ self.code = code
+ self.message = message
+
+class MethodBridge(object):
+
+ def _dispatch(self, name, argobj):
+ method = name.replace('.', '_')
+ result = None
+ error = {'code': 0, 'message': 'Success'}
+ try:
+ fn = getattr(self, method)
+ except AttributeError:
+ error = {'code': 4,
+ 'message': "Operation '%s' not supported" % name}
+ return {'result': result, 'error': error}
+ try:
+ result = fn(argobj)
+ except VdsmError, e:
+ error = {'code': e.code, 'message': e.message}
+ except Exception, e:
+ error = {'code': 5, 'message': 'Internal error: %s' % e}
+ return {'result': result, 'error': error}
+
+ def getArgs(self, argobj, arglist):
+ ret = ()
+ for arg in arglist:
+ if arg in argobj:
+ ret += (argobj[arg],)
+ return ret
+
+ def getResult(self, response, member=None):
+ if member is None:
+ return None
+ try:
+ return response[member]
+ except KeyError:
+ raise VdsmError(5, "Response is missing '%s' member" % member)
+
+class DynamicBridge(MethodBridge):
+ def __init__(self, schema):
+ self.parseSchema(schema)
+
+
+ def parseSchema(self, schema):
+ self.commands = {}
+ self.classes = {}
+ self.types = {}
+ with open(schema) as f:
+ symbols = vdsmapi.parse_schema(f)
+ for s in symbols:
+ if 'command' in s:
+ key = "%s_%s" % (s['command']['class'],
+ s['command']['name'])
+ self.commands[key] = s
+ elif 'class' in s:
+ cls = s['class']
+ self.classes[cls] = s
+ elif 'type' in s:
+ t = s['type']
+ self.types[t] = s
+
+
+ def __getattr__(self, attr):
+ if attr in self.commands:
+ cls, name = attr.split('_')
+ return partial(self.dynamicMethod, cls, name)
+ else:
+ raise AttributeError
+
+
+ def getArgList(self, cmd):
+ return self.commands[cmd].get('data', {}).keys()
+
+
+ def getObjargList(self, cls):
+ return self.classes[cls]['data'].keys()
+
+ def getApiClass(self, cls):
+ name_map = { 'Host': 'Global' }
+ try:
+ cls = name_map[cls]
+ except KeyError:
+ pass
+ return getattr(API, cls)
+
+ def typeFixup(self, sym_name, sym_type, obj):
+ logging.info("typeFixup: '%s': '%s'" % (sym_name, sym_type))
+ isList = False
+ if type(sym_type) is list:
+ sym_type = sym_type[0]
+ isList = True
+ if sym_name[0] == '*':
+ sym_name = sym_name[1:]
+
+ try:
+ symbol = self.types[sym_type]
+ except KeyError:
+ return
+
+ if isList:
+ itemList = obj
+ else:
+ itemList = [obj]
+
+ for item in itemList:
+ if sym_type in typefixups:
+ logging.error("Fixing up type %s", sym_type)
+ typefixups[sym_type](item)
+ for (k, v) in symbol.get('data', {}).items():
+ if k[0] == '*':
+ k = k[1:]
+ if k in item:
+ self.typeFixup(k, v, item[k])
+
+
+ def fixupArgs(self, cmd, args):
+ argInfo = zip(self.commands[cmd].get('data', {}).items(), args)
+ for typeInfo, val in argInfo:
+ argName, argType = typeInfo
+ if argType not in self.types:
+ continue
+ self.typeFixup(argName, argType, val)
+
+ def fixupRet(self, cmd, result):
+ retType = self.commands[cmd].get('returns', None)
+ if retType is not None:
+ self.typeFixup('return', retType, result)
+ return result
+
+ def dynamicMethod(self, cls, name, argobj):
+ cmd = '%s_%s' % (cls, name)
+ ctorArgObj = argobj.get('__obj__', {})
+ ctorargs = self.getArgs(ctorArgObj, self.getObjargList(cls))
+ args = self.getArgs(argobj, self.getArgList(cmd))
+ apiobj = self.getApiClass(cls)
+ api = apiobj(*ctorargs)
+
+ self.fixupArgs(cmd, args)
+
+ # Call the override function (if given). Otherwise, just call directly
+ fn = command_info.get(cmd, {}).get('call')
+ if fn:
+ result = fn(api, argobj)
+ else:
+ fn = getattr(api, name)
+ result = fn(*args)
+
+ if result['status']['code']:
+ code = result['status']['code']
+ msg = result['status']['message']
+ return {'code': code, 'message': msg}
+
+ retfield = command_info.get(cmd, {}).get('ret')
+ if type(retfield) == types.FunctionType:
+ ret = retfield(result)
+ else:
+ ret = self.getResult(result, retfield)
+ return self.fixupRet(cmd, ret)
+
+
+def Host_getStorageRepoStats_Ret(ret):
+ """
+ The returned dictionary doesn't separate the stats from the status code
+ so we need to rebuild the result.
+ """
+ del ret['status']
+ return ret
+
+
+def Host_getVMList_Call(api, args):
+ """
+ This call is only interested in returning the VM UUIDs so pass False for
+ the first argument in order to suppress verbose results.
+ """
+ vmList = args.get('vmList', [])
+ return API.Global().getVMList(False, vmList)
+
+def Host_getVMList_Ret(ret):
+ """
+ Just return a list of VM UUIDs
+ """
+ return [v['vmId'] for v in ret['vmList']]
+
+
+def StoragePool_getInfo_Ret(ret):
+ """
+ The result contains two data structures which must be merged
+ """
+ return {'info': ret['info'], 'dominfo': ret['dominfo']}
+
+
+def VM_getInfo_Call(api, args):
+ """
+ The VM object has no getInfo method. We use the method from 'Global' and
+ pass arguments to get verbose information for only this one VM.
+ """
+ vmId = api._UUID
+ return API.Global().getVMList(True, [vmId])
+
+def VM_getInfo_Ret(ret):
+ """
+ The result will be a list with only one element.
+ """
+ return ret['vmList'][0]
+
+def VM_migrationCreate_Ret(ret):
+ """
+ The result contains two data structures which must be merged
+ """
+ return {'params': ret['params'], 'migrationPort': ret['migrationPort']}
+
+
+def Volume_getsize_Ret(ret):
+ """
+ Merge the two sizes into a single dictionary result.
+ """
+ return {'truesize': ret['truesize'], 'apparentsize': ret['apparentsize']}
+
+
+##
+# Possible ways to override a command:
+# - Supply a custom call function if the function name doesn't map directly to
+# a vdsm API.
+# - Specify the name of the field in the result that is the return value
+# - Specify a custom function to post-process the result into a return value
+##
+command_info = {
+ 'ConnectionRefs_acquire': {'ret': 'results'},
+ 'ConnectionRefs_release': {'ret': 'results'},
+ 'ConnectionRefs_statuses': {'ret': 'connectionslist'},
+ 'Host_fenceNode': {'ret': 'power'},
+ 'Host_getAllTasksInfo': {'ret': 'allTasksInfo'},
+ 'Host_getAllTasksStatuses': {'ret': 'allTasksStatus'},
+ 'Host_getCapabilities': {'ret': 'info'},
+ 'Host_getConnectedStoragePools': {'ret': 'poollist'},
+ 'Host_getDeviceInfo': {'ret': 'info'},
+ 'Host_getDeviceList': {'ret': 'devList'},
+ 'Host_getDevicesVisibility': {'ret': 'visibility'},
+ 'Host_getLVMVolumeGroups': {'ret': 'vglist'},
+ 'Host_getStats': {'ret': 'info'},
+ 'Host_getStorageDomains': {'ret': 'domlist'},
+ 'Host_getStorageRepoStats': {'ret': Host_getStorageRepoStats_Ret},
+ 'Host_getVMList': {'call': Host_getVMList_Call, 'ret': Host_getVMList_Ret},
+ 'Image_delete': {'ret': 'uuid'},
+ 'Image_deleteVolumes': {'ret': 'uuid'},
+ 'Image_getVolumes': {'ret': 'uuidlist'},
+ 'Image_mergeSnapshots': {'ret': 'uuid'},
+ 'Image_move': {'ret': 'uuid'},
+ 'ISCSIConnection_discoverSendTargets': {'ret': 'fullTargets'},
+ 'LVMVolumeGroup_create': {'ret': 'uuid'},
+ 'LVMVolumeGroup_getInfo': {'ret': 'info'},
+ 'StorageDomain_getFileList': {'ret': 'files'},
+ 'StorageDomain_getImages': {'ret': 'imageslist'},
+ 'StorageDomain_getInfo': {'ret': 'info'},
+ 'StorageDomain_getStats': {'ret': 'stats'},
+ 'StorageDomain_getVolumes': {'ret': 'uuidlist'},
+ 'StoragePool_connectStorageServer': {'ret': 'statuslist'},
+ 'StoragePool_disconnectStorageServer': {'ret': 'statuslist'},
+ 'StoragePool_fence': {'ret': 'spm_st'},
+ 'StoragePool_getBackedUpVmsInfo': {'ret': 'vmlist'},
+ 'StoragePool_getBackedUpVmsList': {'ret': 'vmlist'},
+ 'StoragePool_getDomainsContainingImage': {'ret': 'domainslist'},
+ 'StoragePool_getFloppyList': {'ret': 'isolist'},
+ 'StoragePool_getInfo': {'ret': StoragePool_getInfo_Ret},
+ 'StoragePool_getIsoList': {'ret': 'isolist'},
+ 'StoragePool_getSpmStatus': {'ret': 'spm_st'},
+ 'StoragePool_spmStart': {'ret': 'uuid'},
+ 'StoragePool_upgrade': {'ret': 'upgradeStatus'},
+ 'StoragePool_validateStorageServerConnection': {'ret': 'statuslist'},
+ 'Task_getInfo': {'ret': 'TaskInfo'},
+ 'Task_getStatus': {'ret': 'taskStatus'},
+ 'VM_changeCD': {'ret': 'vmList'},
+ 'VM_changeFloppy': {'ret': 'vmList'},
+ 'VM_create': {'ret': 'vmList'},
+ 'VM_getInfo': {'call': VM_getInfo_Call, 'ret': VM_getInfo_Ret},
+ 'VM_getStats': {'ret': 'statsList'},
+ 'VM_hotplugDisk': {'ret': 'vmList'},
+ 'VM_hotplugNic': {'ret': 'vmList'},
+ 'VM_hotUnplugDisk': {'ret': 'vmList'},
+ 'VM_hotUnplugNic': {'ret': 'vmList'},
+ 'VM_mergeStatus': {'ret': 'mergeStatus'},
+ 'VM_migrationCreate': {'ret': VM_migrationCreate_Ret},
+ 'Volume_copy': {'ret': 'uuid'},
+ 'Volume_create': {'ret': 'uuid'},
+ 'Volume_delete': {'ret': 'uuid'},
+ 'Volume_getInfo': {'ret': 'info'},
+ 'Volume_getPath': {'ret': 'path'},
+ 'Volume_getSize': {'ret': Volume_getsize_Ret},
+ 'Host_getAllTasks': {'ret': 'TasksDetails'},
+}
+
+
+def fieldClone(oldName, newName, obj):
+ logging.warning("fieldClone: %s -> %s", oldName, newName)
+ if oldName in obj:
+ obj[newName] = obj[oldName]
+ elif newName in obj:
+ obj[oldName] = obj[newName]
+
+typefixups = {
+ 'VmDevice': partial(fieldClone, 'type', 'deviceType'),
+ 'BlockDevicePathInfo': partial(fieldClone, 'type', 'deviceType'),
+ 'VolumeGroupInfo': partial(fieldClone, 'type', 'deviceType'),
+ 'VmDeviceAddress': partial(fieldClone, 'type', 'addressType'),
+ 'IscsiCredentials': partial(fieldClone, 'type', 'authType'),
+ 'ConnectionRefArgs': partial(fieldClone, 'type', 'connType'),
+ 'VolumeInfo': partial(fieldClone, 'type', 'allocType'),
+}
diff --git a/vdsm_api/Makefile.am b/vdsm_api/Makefile.am
new file mode 100644
index 0000000..655586f
--- /dev/null
+++ b/vdsm_api/Makefile.am
@@ -0,0 +1,13 @@
+EXTRA_DIST = \
+ vdsmapi-schema.json \
+ $(NULL)
+
+dist_vdsm_PYTHON = \
+ BindingJsonRpc.py \
+ Bridge.py \
+ vdsmapi.py \
+ $(NULL)
+
+dist_vdsm_DATA = \
+ vdsmapi-schema.json \
+ $(NULL)
--
To view, visit http://gerrit.ovirt.org/8614
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idae0faa80ffc6a5af002a8a7151aa40dc9a6673d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <agl(a)us.ibm.com>
11 years, 6 months
Change in vdsm[master]: vdsm.spec: Add vdsm-xmlrpc as Requirement
by Douglas Schilling Landgraf
Douglas Schilling Landgraf has uploaded a new change for review.
Change subject: vdsm.spec: Add vdsm-xmlrpc as Requirement
......................................................................
vdsm.spec: Add vdsm-xmlrpc as Requirement
For vdsm-json stuff and vdsm initialization, we should require vdsm-xmlrpc package.
Change-Id: I41e8507edb2e5b72d6492229d4323b6574b2afc0
Signed-off-by: Douglas Schilling Landgraf <dougsland(a)redhat.com>
---
M vdsm.spec.in
1 file changed, 1 insertion(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/36/9136/1
diff --git a/vdsm.spec.in b/vdsm.spec.in
index c117ee5..2f171b7 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -67,6 +67,7 @@
Requires: rpm-python
Requires: nfs-utils
Requires: python-pthreading
+Requires: %{name}-xmlrpc
%ifarch x86_64
Requires: dmidecode
--
To view, visit http://gerrit.ovirt.org/9136
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I41e8507edb2e5b72d6492229d4323b6574b2afc0
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Douglas Schilling Landgraf <dougsland(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: netinfo: added configuration to show dummy NIC's too
by hercinger.viktor@gmail.com
Hercinger Viktor has uploaded a new change for review.
Change subject: netinfo: added configuration to show dummy NIC's too
......................................................................
netinfo: added configuration to show dummy NIC's too
With the vars.fake_nics configuration a list of comma-separated
interfaces can be specified. If a dummy interface matches the
fnmatch pattern, it will be included in the NIC list.
Change-Id: Ica0ad974e6dd0d144a6bb0904fdcd6bbce99ff9f
Signed-off-by: Hercinger Viktor <hercinger.viktor(a)gmail.com>
---
M tests/netinfoTests.py
M vdsm/netinfo.py
2 files changed, 18 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/17/8917/1
diff --git a/tests/netinfoTests.py b/tests/netinfoTests.py
index f5a4b95..a678fbc 100644
--- a/tests/netinfoTests.py
+++ b/tests/netinfoTests.py
@@ -23,6 +23,7 @@
from testrunner import VdsmTestCase as TestCaseBase
from vdsm import netinfo
+from vdsm import config
from monkeypatch import MonkeyPatch
# speeds defined in ethtool
@@ -66,3 +67,6 @@
# just log a traceback. If it raises an exception the test will fail as
# it should.
netinfo.get()
+
+ def testMatchNicName(self):
+ self.assertTrue(netinfo.match_nic_name('test1', ['test0', 'test1']))
diff --git a/vdsm/netinfo.py b/vdsm/netinfo.py
index c3c5a6f..26ad247 100644
--- a/vdsm/netinfo.py
+++ b/vdsm/netinfo.py
@@ -19,6 +19,7 @@
#
import os
+import os.path
import errno
import glob
import ethtool
@@ -43,13 +44,22 @@
LIBVIRT_NET_PREFIX = 'vdsm-'
+def match_nic_name(nic, patterns):
+ return any(map(lambda p: fnmatch(nic, p), patterns))
+
def nics():
res = []
- for b in glob.glob('/sys/class/net/*/device'):
- nic = b.split('/')[-2]
- if not any(map(lambda p: fnmatch(nic, p),
- config.get('vars', 'hidden_nics').split(','))):
+ hidden_nics = config.get('vars', 'hidden_nics').split(',')
+ fake_nics = config.get('vars', 'fake_nics').split(',')
+
+ for b in glob.glob('/sys/class/net/*'):
+ nic = b.split('/')[-1]
+ if not os.path.exists(os.path.join(b, 'device')):
+ if match_nic_name(nic, fake_nics):
+ res.append(nic)
+ elif not match_nic_name(nic, hidden_nics):
res.append(nic)
+
return res
--
To view, visit http://gerrit.ovirt.org/8917
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ica0ad974e6dd0d144a6bb0904fdcd6bbce99ff9f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Hercinger Viktor <hercinger.viktor(a)gmail.com>
11 years, 6 months
Change in vdsm[master]: Report hsm tasks in getAllTasksStatuses and getAllTasksInfo
by smizrahi@redhat.com
Saggi Mizrahi has uploaded a new change for review.
Change subject: Report hsm tasks in getAllTasksStatuses and getAllTasksInfo
......................................................................
Report hsm tasks in getAllTasksStatuses and getAllTasksInfo
Change-Id: I40a42db6554e5145d05f913c742d00dc26969899
Signed-off-by: Saggi Mizrahi <smizrahi(a)redhat.com>
---
M vdsm/storage/hsm.py
1 file changed, 2 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/72/6672/1
--
To view, visit http://gerrit.ovirt.org/6672
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I40a42db6554e5145d05f913c742d00dc26969899
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Saggi Mizrahi <smizrahi(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: storage/threadPool: fix copyright notice
by Dan Kenigsberg
Dan Kenigsberg has uploaded a new change for review.
Change subject: storage/threadPool: fix copyright notice
......................................................................
storage/threadPool: fix copyright notice
Change-Id: Ib6a06dc60f53f12793a93bb71cd3d5bfec4cc0d1
Signed-off-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm/storage/threadPool.py
1 file changed, 5 insertions(+), 17 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/19/9119/1
diff --git a/vdsm/storage/threadPool.py b/vdsm/storage/threadPool.py
index 4cf4568..22633b7 100644
--- a/vdsm/storage/threadPool.py
+++ b/vdsm/storage/threadPool.py
@@ -1,21 +1,9 @@
#
-# Copyright 2011 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
+# Adapted by Red Hat from
+# http://code.activestate.com/recipes/203871-a-generic-programming-thread-p...
+# Author: Tim Lesher
+# License: PSF License
+# http://wiki.python.org/moin/PythonSoftwareFoundationLicenseV2Easy
#
import threading
--
To view, visit http://gerrit.ovirt.org/9119
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib6a06dc60f53f12793a93bb71cd3d5bfec4cc0d1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Dan Kenigsberg <danken(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: clienteIF: replace MOM self.log.error to warn
by Douglas Schilling Landgraf
Douglas Schilling Landgraf has uploaded a new change for review.
Change subject: clienteIF: replace MOM self.log.error to warn
......................................................................
clienteIF: replace MOM self.log.error to warn
If mom package is not installed, at this point vdsm should
throw warning message instead of error.
Change-Id: I860c5d0833ae0e7d9feb326d340a34dd68104d98
Signed-off-by: Douglas Schilling Landgraf <dougsland(a)redhat.com>
---
M vdsm/clientIF.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/32/9132/1
diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py
index 6c5a670..ed2a3c1 100644
--- a/vdsm/clientIF.py
+++ b/vdsm/clientIF.py
@@ -178,7 +178,7 @@
momconf = config.get("mom", "conf")
self.mom = MomThread(momconf)
except:
- self.log.error("MOM initialization failed and fall "
+ self.log.warn("MOM initialization failed and fall "
"back to KsmMonitor", exc_info=True)
self.ksmMonitor = ksm.KsmMonitorThread(self)
--
To view, visit http://gerrit.ovirt.org/9132
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I860c5d0833ae0e7d9feb326d340a34dd68104d98
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Douglas Schilling Landgraf <dougsland(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: libvirtvm: set volume the format in live snapshots
by ewarszaw@redhat.com
Hello Federico Simoncelli,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/9129
to review the following change.
Change subject: libvirtvm: set volume the format in live snapshots
......................................................................
libvirtvm: set volume the format in live snapshots
When we update the drive objects (and configurations) at the end of
a live snapshot we should also update the format to be "cow" in order
to start requesting the drive extensions on block devices.
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=874481
Change-Id: Ia5535cc8ad55441046e81aa329fac82a354592b9
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/libvirtvm.py
1 file changed, 1 insertion(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/29/9129/1
diff --git a/vdsm/libvirtvm.py b/vdsm/libvirtvm.py
index 86e39a3..ca31a43 100644
--- a/vdsm/libvirtvm.py
+++ b/vdsm/libvirtvm.py
@@ -1853,6 +1853,7 @@
newDrives[vmDevName] = tgetDrv.copy()
newDrives[vmDevName]["poolID"] = vmDrive.poolID
newDrives[vmDevName]["name"] = vmDevName
+ newDrives[vmDevName]["format"] = "cow"
try:
newDrives[vmDevName]["path"] = \
--
To view, visit http://gerrit.ovirt.org/9129
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia5535cc8ad55441046e81aa329fac82a354592b9
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
Gerrit-Reviewer: Federico Simoncelli <fsimonce(a)redhat.com>
11 years, 6 months
Change in vdsm[master]: Using only globalPool allow only 10 processes
by ybronhei@redhat.com
Yaniv Bronhaim has uploaded a new change for review.
Change subject: Using only globalPool allow only 10 processes
......................................................................
Using only globalPool allow only 10 processes
For each domain we want to have process pool with limit slots of
processes, this way we optimize glob over mounted links.
This fix uses different pool for each domain, instead of the global one.
Change-Id: I9a4024b8d8be8b9cbbb4836987dfb94e3a11d7d3
Signed-off-by: Yaniv Bronhaim <ybronhei(a)redhat.com>
Bug-Id: https://bugzilla.redhat.com/show_bug.cgi?id=853011
---
M vdsm/storage/fileSD.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/29/9029/1
diff --git a/vdsm/storage/fileSD.py b/vdsm/storage/fileSD.py
index a6a718f..f221eb0 100644
--- a/vdsm/storage/fileSD.py
+++ b/vdsm/storage/fileSD.py
@@ -479,7 +479,7 @@
def collectMetaFiles(possibleDomain):
try:
- metaFiles = oop.getGlobalProcPool().glob.glob(
+ metaFiles = oop.getProcessPool(possibleDomain).glob.glob(
os.path.join(possibleDomain,
constants.UUID_GLOB_PATTERN,
sd.DOMAIN_META_DATA))
--
To view, visit http://gerrit.ovirt.org/9029
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9a4024b8d8be8b9cbbb4836987dfb94e3a11d7d3
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Yaniv Bronhaim <ybronhei(a)redhat.com>
11 years, 6 months