Deepak C Shetty has uploaded a new change for review.
Change subject: glusterSD: BZ 988299: Deduce gluster volume name from domain metadata
......................................................................
glusterSD: BZ 988299: Deduce gluster volume name from domain metadata
Gluster volume name thats present as part of mount point path is
mangled, hence gluster volume lookup fails if volume has '_' or '/' in it.
Use the pristine value of server:volname stored in domain metadata
to deduce the gluster volume name.
Change-Id: Ibfc8af4aa7ab028a7a6f0e691eae1c89f5148ee9
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=988299
Signed-off-by: Deepak C Shetty <deepakcs(a)linux.vnet.ibm.com>
---
M vdsm/storage/glusterVolume.py
1 file changed, 11 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/19/19219/1
diff --git a/vdsm/storage/glusterVolume.py b/vdsm/storage/glusterVolume.py
index 3368de3..1a1b40e 100644
--- a/vdsm/storage/glusterVolume.py
+++ b/vdsm/storage/glusterVolume.py
@@ -3,6 +3,7 @@
from sdc import sdCache
import supervdsm as svdsm
from gluster.exception import GlusterException
+from fileSD import REMOTE_PATH
class GlusterVolume(fileVolume.FileVolume):
@@ -15,10 +16,18 @@
"""
Send info to represent Gluster volume as a network block device
"""
- rpath = sdCache.produce(self.sdUUID).getRemotePath()
+
+ # Get the pristine remote path (hostname:volname) from MD,
+ # so that we don't end up using the mangled volume and/or hostnames.
+ rpath = sdCache.produce(self.sdUUID).getMetaParam(REMOTE_PATH)
rpath_list = rpath.rsplit(":", 1)
volfileServer = rpath_list[0]
- volname = rpath_list[1]
+ # Check for leading '/', since its perfectly valid to say
+ # hostname:/volname for gluster mounts.
+ if rpath_list[1][0] == '/':
+ volname = rpath_list[1][1:]
+ else:
+ volname = rpath_list[1]
# Volume transport to Libvirt transport mapping
VOLUME_TRANS_MAP = {'TCP': 'tcp', 'RDMA': 'rdma'}
--
To view, visit http://gerrit.ovirt.org/19219
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibfc8af4aa7ab028a7a6f0e691eae1c89f5148ee9
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Deepak C Shetty <deepakcs(a)linux.vnet.ibm.com>
Royce Lv has uploaded a new change for review.
Change subject: force reload udev rules to avoid LUN device permission error
......................................................................
force reload udev rules to avoid LUN device permission error
udev rules creat symlink for LUN device making it usable for qemu
but the rules are not instantly loaded by udev
result in LUN device symlink not created before vm run
force reload to make the rules take effect instantly
Change-Id: I718d62e67b0a228f2510233c5dd9d1d94c4a736c
Signed-off-by: Royce Lv<lvroyce(a)linux.vnet.ibm.com>
---
M vdsm/storage/hsm.py
M vdsm/supervdsmServer.py
2 files changed, 9 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/80/6780/1
--
To view, visit http://gerrit.ovirt.org/6780
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I718d62e67b0a228f2510233c5dd9d1d94c4a736c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Lei Li has uploaded a new change for review.
Change subject: Encapsulate vdsm-unregister into vdsm-tool function
......................................................................
Encapsulate vdsm-unregister into vdsm-tool function
Change-Id: I7348baeabbdcbb0c2da64170b6957430feaa1954
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
M vdsm-tool/Makefile.am
A vdsm-tool/register.py
M vdsm.spec.in
3 files changed, 43 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/27/4527/1
--
To view, visit http://gerrit.ovirt.org/4527
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7348baeabbdcbb0c2da64170b6957430feaa1954
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Lei Li <lilei(a)linux.vnet.ibm.com>
ShaoHe Feng has uploaded a new change for review.
Change subject: add a jsonrpcSeverClient for jsonRPC Server functional test
......................................................................
add a jsonrpcSeverClient for jsonRPC Server functional test
This jsonrpcSeverClient is easy to call the jsonRPC server.
And it is an example for user to call the jsonRPC server.
The jsonrpcSeverClient will parser the vdsmapi-schema.json.
It will generate the method of vdsm-api dynamically.
Then we can easy call the vdsm-api, refer to vdsm-api.html.
vdsm-api.html is in the vdsm doc path.
Some comments tell us how to call the vdsm-api at the end of
jsonrpcSeverClient.py
Change-Id: Ib081e26203638114d7d632489432a50eeea45dd4
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
M tests/functional/Makefile.am
A tests/functional/jsonrpcSeverClient.py
2 files changed, 144 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/83/11283/1
diff --git a/tests/functional/Makefile.am b/tests/functional/Makefile.am
index 030242b..e3374e8 100644
--- a/tests/functional/Makefile.am
+++ b/tests/functional/Makefile.am
@@ -21,6 +21,7 @@
vdsmfunctestsdir = ${vdsmtestsdir}/functional
dist_vdsmfunctests_PYTHON = \
+ jsonrpcSeverClient.py \
momTests.py \
sosPluginTests.py \
xmlrpcTests.py \
diff --git a/tests/functional/jsonrpcSeverClient.py b/tests/functional/jsonrpcSeverClient.py
new file mode 100644
index 0000000..77af03b
--- /dev/null
+++ b/tests/functional/jsonrpcSeverClient.py
@@ -0,0 +1,143 @@
+#
+# 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
+#
+
+import json
+import os
+import socket
+import ssl
+import struct
+import vdsmapi
+from functools import partial
+from contextlib import closing
+from vdsm.config import config
+from vdsm import constants
+
+
+class ConnectionError(Exception):
+ pass
+
+
+class ProtocolError(Exception):
+ pass
+
+
+class jsonRpcServerClient(object):
+
+ #TODO: spport ssl
+ def __init__(self, ip, port, certReq=False, tsPath=None):
+ self._ip = ip
+ self._port = port
+ self._tsPath = tsPath
+ self._Size = struct.Struct("!Q")
+ self._cert_reqs = ssl.CERT_REQUIRED if certReq else ssl.CERT_NONE
+ schema = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
+ self._dynamicAttribute(schema)
+
+ def buildMessage(self, data):
+ msg = json.dumps(data)
+ msg = msg.encode('utf-8')
+ msize = self._Size.pack(len(msg))
+ resp = msize + msg
+ return resp
+
+ def _createRequest(self, method, reqId=None, params=()):
+ return {'jsonrpc': '2.0', "id": reqId, "method": method,
+ "params": params}
+
+ def sendMessage(self, msg):
+ with closing(socket.socket(socket.AF_INET,
+ socket.SOCK_STREAM)) as tcp_sock:
+ if self._cert_reqs == ssl.CERT_REQUIRED:
+ if self._tsPath is None:
+ self._tsPath = config.get('vars', 'trust_store_path')
+ KEYFILE = self._tsPath + '/keys/vdsmkey.pem'
+ CERTFILE = self._tsPath + '/certs/vdsmcert.pem'
+ CACERT = self._tsPath + '/certs/cacert.pem'
+ sock = ssl.wrap_socket(tcp_sock,
+ keyfile=KEYFILE,
+ certfile=CERTFILE,
+ ca_certs=CACERT,
+ cert_reqs=self._cert_reqs)
+ else:
+ sock = tcp_sock
+ sock.settimeout(3) # TBD timeout
+ try:
+ sock.connect((self._ip, self._port))
+ except socket.error as e:
+ raise ConnectionError("Unable to connect to server: %s", e)
+ try:
+ sock.sendall(msg)
+ except (socket.error, socket.timeout), e:
+ raise ProtocolError("Unable to send request: %s", e)
+ try:
+ data = sock.recv(self._Size.size)
+ except socket.error as e:
+ raise ProtocolError("Unable to read response length: %s", e)
+ if not data:
+ raise ProtocolError("No data received")
+ msgLen = self._Size.unpack(data)[0]
+ try:
+ data = sock.recv(msgLen)
+ except socket.error as e:
+ raise ProtocolError("Unable to read response body: %s", e)
+ if len(data) != msgLen:
+ raise ProtocolError("Response body length mismatch")
+ return json.loads(data)
+
+ def call(self, method, reqId=None, params=()):
+ msg = self.buildMessage(self._createRequest(method, reqId, params))
+ reply = self.sendMessage(msg)
+ return reply
+
+ def _dynamicAttribute(self, schema):
+ self.dynamicAttr = {}
+ with open(schema) as f:
+ symbols = vdsmapi.parse_schema(f)
+ for s in symbols:
+ if 'command' in s:
+ className = s['command']['class']
+ functionName = s['command']['name']
+ if className not in self.dynamicAttr.keys():
+ self.dynamicAttr[className] = []
+ self.dynamicAttr[className].append(functionName)
+ for key, funs in self.dynamicAttr.items():
+ funDicts = {}
+ for fun in funs:
+ method = ".".join((key, fun))
+ funDicts[fun] = partial(self.call, method)
+ cls = type(key, (object,), funDicts)
+ setattr(self, key, cls())
+
+
+if __name__ == '__main__':
+ if not config.getboolean('vars', 'jsonrpc_enable'):
+ exit(1)
+
+ ip = "127.0.0.1"
+ port = config.getint('addresses', 'json_port')
+ rpcIns = jsonRpcServerClient(ip, port)
+
+ # test the RpcClient
+ # you can open vdsm-api.html by your browser, such as by firefox
+ # firefox /usr/share/doc/vdsm-*/vdsm-api.html
+ # vdsm-api.html is in the vdsm doc path.
+ # then can call the API show in vdsm-api.html as follow
+ print rpcIns.call("Host.getAllTasksInfo", 1)
+ print rpcIns.Host.getAllTasksInfo(1)
--
To view, visit http://gerrit.ovirt.org/11283
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib081e26203638114d7d632489432a50eeea45dd4
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
Federico Simoncelli has uploaded a new change for review.
Change subject: sp: improve masterMigrate safety
......................................................................
sp: improve masterMigrate safety
The goal of this patch is to clean, optimize and give robustness to
the masterMigrate method.
In this patch:
- acquire the cluster lock before start using the new master filesystem
- refactor out all the required metadata changes in switchMasterDomain
(rename copyPoolMD to switchMasterDomain, and include the domain role
changes)
- divde the method in two parts (operations required to switch to the
new master and previous master cleanup)
- address the two parts exception handling (hard failure for the first,
logging only for the second)
Change-Id: I155b36d41df43230f99ba610699bba05bee3f0c0
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/storage/sp.py
1 file changed, 61 insertions(+), 78 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/19/22419/1
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index 19d07b3..c370b52 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -836,27 +836,29 @@
else:
futureMaster.releaseClusterLock()
- @unsecured
- def copyPoolMD(self, prevMd, newMD):
- prevPoolMD = self._getPoolMD(prevMd)
+ def switchMasterDomain(self, currentMasterDomain, newMasterDomain,
+ newMasterVersion):
+ prevPoolMD = self._getPoolMD(currentMasterDomain)
domains = prevPoolMD[PMDK_DOMAINS]
pool_descr = prevPoolMD[PMDK_POOL_DESCRIPTION]
lver = prevPoolMD[PMDK_LVER]
spmId = prevPoolMD[PMDK_SPM_ID]
# This is actually domain metadata, But I can't change this because of
# backward compatibility
- leaseParams = prevMd.getLeaseParams()
+ leaseParams = currentMasterDomain.getLeaseParams()
# Now insert pool metadata into new mastersd metadata
- newPoolMD = self._getPoolMD(newMD)
+ newPoolMD = self._getPoolMD(newMasterDomain)
with newPoolMD.transaction():
newPoolMD.update({
PMDK_DOMAINS: domains,
PMDK_POOL_DESCRIPTION: pool_descr,
PMDK_LVER: lver,
- PMDK_SPM_ID: spmId})
- newMD.changeLeaseParams(leaseParams)
+ PMDK_SPM_ID: spmId,
+ PMDK_MASTER_VER: newMasterVersion,
+ })
+ newMasterDomain.changeLeaseParams(leaseParams)
@unsecured
def _copyLeaseParameters(self, srcDomain, dstDomain):
@@ -865,7 +867,6 @@
srcDomain.sdUUID, leaseParams)
dstDomain.changeLeaseParams(leaseParams)
- @unsecured
def masterMigrate(self, sdUUID, msdUUID, masterVersion):
self.log.info("sdUUID=%s spUUID=%s msdUUID=%s", sdUUID, self.spUUID,
msdUUID)
@@ -895,95 +896,77 @@
if newmsd.isBackup():
raise se.BackupCannotBeMasterDomain(msdUUID)
- # Copy master file system content to the new master
- src = os.path.join(curmsd.domaindir, sd.MASTER_FS_DIR)
- dst = os.path.join(newmsd.domaindir, sd.MASTER_FS_DIR)
+ # If the new master domain is using safelease (version < 3) then
+ # we can speed up the cluster lock acquirement by resetting the
+ # SPM lease.
+ # XXX: With SANLock there is no need to speed up the process (the
+ # acquirement will take a short time anyway since we already hold
+ # the host id) and more importantly resetting the lease is going
+ # to interfere with the regular SANLock behavior.
+ # @deprecated this is relevant only for domain version < 3
+ if not newmsd.hasVolumeLeases():
+ newmsd.initSPMlease()
- # Mount new master file system
- newmsd.mountMaster()
- # Make sure there is no cruft left over
- for dir in [newmsd.getVMsDir(), newmsd.getTasksDir()]:
- fileUtils.cleanupdir(dir)
+ # Forcing to acquire the host id (if it's not acquired already)
+ # and acquiring the cluster lock on new master.
+ newmsd.acquireHostId(self.id)
+ newmsd.acquireClusterLock(self.id)
try:
- fileUtils.tarCopy(src, dst, exclude=("./lost+found",))
- except fileUtils.TarCopyFailed:
- self.log.error("tarCopy failed", exc_info=True)
- # Failed to copy the master data
+ self.log.debug('migration to the new master %s begins',
+ newmsd.sdUUID)
+
+ # Mount new master file system
+ newmsd.mountMaster()
+
+ # Make sure there is no cruft left over
+ for dir in [newmsd.getVMsDir(), newmsd.getTasksDir()]:
+ fileUtils.cleanupdir(dir)
+
+ # Copy master file system content to the new master
+ src = os.path.join(curmsd.domaindir, sd.MASTER_FS_DIR)
+ dst = os.path.join(newmsd.domaindir, sd.MASTER_FS_DIR)
+ fileUtils.tarCopy(src, dst, exclude=('./lost+found',))
+
+ if not newmsd.getMDPath():
+ raise se.StorageDomainLayoutError("domain", msdUUID)
+
+ newmsd.changeRole(sd.MASTER_DOMAIN)
+ self.switchMasterDomain(curmsd, newmsd, masterVersion)
+ except Exception:
+ self.log.exception('migration to new master failed')
try:
newmsd.unmountMaster()
- except Exception:
- self.log.error("Unexpected error", exc_info=True)
- raise se.StorageDomainMasterCopyError(msdUUID)
-
- self.copyPoolMD(curmsd, newmsd)
-
- path = newmsd.getMDPath()
- if not path:
- newmsd.unmountMaster()
- raise se.StorageDomainLayoutError("domain", msdUUID)
-
- # Acquire cluster lock on new master
- try:
- # If the new master domain is using safelease (version < 3) then
- # we can speed up the cluster lock acquirement by resetting the
- # SPM lease.
- # XXX: With SANLock there is no need to speed up the process (the
- # acquirement will take a short time anyway since we already hold
- # the host id) and more importantly resetting the lease is going
- # to interfere with the regular SANLock behavior.
- # @deprecated this is relevant only for domain version < 3
- if not newmsd.hasVolumeLeases():
- newmsd.initSPMlease()
- # Forcing to acquire the host id (if it's not acquired already)
- newmsd.acquireHostId(self.id)
- newmsd.acquireClusterLock(self.id)
- except Exception:
- self.log.error("Unexpected error", exc_info=True)
+ except: # logging only
+ self.log.error('unable to unmount master filesystem '
+ 'for domain %s', newmsd.sdUUID)
newmsd.releaseClusterLock()
- newmsd.unmountMaster()
- raise
- self.log.debug("masterMigrate - lease acquired successfully")
-
- try:
- # Now mark new domain as 'master'
- # if things break down here move the master back pronto
- newPoolMD = self._getPoolMD(newmsd)
- with newPoolMD.transaction():
- newPoolMD[PMDK_MASTER_VER] = masterVersion
- newmsd.changeRole(sd.MASTER_DOMAIN)
- self._saveReconnectInformation(self.id, self.scsiKey,
- newmsd.sdUUID, masterVersion)
- except Exception:
- self.log.error("Unexpected error", exc_info=True)
- newmsd.releaseClusterLock()
- newmsd.unmountMaster()
raise
# From this point on we have a new master and should not fail
try:
- # Now recreate 'mastersd' link
- # we can use refresh() to do the job
self.refresh(msdUUID, masterVersion)
+ self._saveReconnectInformation(
+ self.id, self.scsiKey, newmsd.sdUUID, masterVersion)
# From this point on there is a new master domain in the pool
- # Now that we are beyond the critical point we can clean up things
- curmsd.changeRole(sd.REGULAR_DOMAIN)
+ # Now that we are beyond the critical point we can clean up
+ # things
+ self.setDomainRegularRole(curmsd)
# Clean up the old data from previous master fs
for directory in [curmsd.getVMsDir(), curmsd.getTasksDir()]:
fileUtils.cleanupdir(directory)
-
- # NOTE: here we unmount the *previous* master file system !!!
- curmsd.unmountMaster()
except Exception:
- self.log.error("Unexpected error", exc_info=True)
-
- try:
- # Release old lease
+ self.log.exception('ignoring old master cleanup failure')
+ finally:
+ # Unmoung old master filesystem and release old cluster lock
+ try:
+ curmsd.unmountMaster()
+ except: # logging only
+ self.log.error('unable to unmount master filesystem '
+ 'for domain %s', curmsd.sdUUID)
curmsd.releaseClusterLock()
- except Exception:
- self.log.error("Unexpected error", exc_info=True)
def attachSD(self, sdUUID):
"""
--
To view, visit http://gerrit.ovirt.org/22419
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I155b36d41df43230f99ba610699bba05bee3f0c0
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>