Change in vdsm[master]: Encapsulate vdsm-unregister into vdsm-tool function
by lilei@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>
10 years, 4 months
Change in vdsm[master]: add a jsonrpcSeverClient for jsonRPC Server functional test
by shaohef@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>
10 years, 4 months
Change in vdsm[master]: [WIP] objectfs integration
by peet@redhat.com
Peter V. Saveliev has uploaded a new change for review.
Change subject: [WIP] objectfs integration
......................................................................
[WIP] objectfs integration
Export VM objects as files in runtime.
Signed-off-by: Peter V. Saveliev <peet(a)redhat.com>
Change-Id: I6dd2ca2245f3f5496eca9f8c14bed79d4638c189
---
M vdsm/vm.py
1 file changed, 7 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/83/8383/1
diff --git a/vdsm/vm.py b/vdsm/vm.py
index d49eef1..cd6c6ca 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -33,6 +33,7 @@
from logUtils import SimpleLogAdapter
import libvirt
from vdsm import vdscli
+from pyvfs.objectfs import export
DEFAULT_BRIDGE = config.get("vars", "default_bridge")
@@ -250,6 +251,12 @@
'Restoring state', 'Saving State',
'Up', 'WaitForLaunch')
+
+@export(blacklist=[
+ "/log",
+ "/MigrationSourceThreadClass",
+ "/cif",
+ ])
class Vm(object):
"""
Used for abstracting communication between various parts of the
--
To view, visit http://gerrit.ovirt.org/8383
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6dd2ca2245f3f5496eca9f8c14bed79d4638c189
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Peter V. Saveliev <peet(a)redhat.com>
10 years, 4 months
Change in vdsm[master]: new API call getVersionInfo()
by peet@redhat.com
Peter V. Saveliev has uploaded a new change for review.
Change subject: new API call getVersionInfo()
......................................................................
new API call getVersionInfo()
getCapabilities() is too expensive to discover the target VDSM
version e.g. for migration
Signed-off-by: Peter V. Saveliev <peet(a)redhat.com>
Change-Id: I3f55ef437ca404ca04598d34c41756b1e68ced95
---
M vdsm/API.py
M vdsm/BindingXMLRPC.py
M vdsm_api/vdsmapi-schema.json
3 files changed, 50 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/31/8431/1
diff --git a/vdsm/API.py b/vdsm/API.py
index bbc3221..f95ac80 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -39,6 +39,7 @@
import storage.image
from vdsm.define import doneCode, errCode, Kbytes, Mbytes
import caps
+import dsaversion
from vdsm.config import config
import supervdsm
@@ -328,6 +329,12 @@
return errCode['noVM']
return v.migrateStatus()
+ def getVersionInfo(self):
+ """
+ """
+ info = dsaversion.version_info
+ return {'status': doneCode, 'info': info}
+
def getStats(self):
"""
Obtain statistics of the specified VM
diff --git a/vdsm/BindingXMLRPC.py b/vdsm/BindingXMLRPC.py
index fc57019..351e3a0 100644
--- a/vdsm/BindingXMLRPC.py
+++ b/vdsm/BindingXMLRPC.py
@@ -284,6 +284,10 @@
ret['info'].update(self.getServerInfo())
return ret
+ def getVersionInfo(self):
+ api = API.Global()
+ return api.getVersionInfo()
+
def getStats(self):
api = API.Global()
return api.getStats()
@@ -748,6 +752,7 @@
(self.vmGetMigrationStatus, 'migrateStatus'),
(self.vmMigrationCancel, 'migrateCancel'),
(self.getCapabilities, 'getVdsCapabilities'),
+ (self.getVersionInfo, 'getVersionInfo'),
(self.getStats, 'getVdsStats'),
(self.vmGetStats, 'getVmStats'),
(self.getAllVmStats, 'getAllVmStats'),
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index 10d2aaa..a1b5ba3 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -1515,6 +1515,44 @@
'returns': 'HostStats'}
##
+# @VdsmCapabilities:
+#
+# Host information and capabilities.
+#
+# @version_name: The name given to this version of VDSM
+#
+# @software_version: VDSM version (x.y.z)
+#
+# @software_revision: Extra VDSM version information
+#
+# @supportedRHEVMs: A list of supported ovirt-engine versions
+#
+# @supportedProtocols: A list of supported xmlrpc protocol versions
+#
+# @clusterLevels: A list of supported cluster versions
+#
+# Since: 4.10.1
+#
+##
+{'type': 'HostInfo',
+ 'data': {'version_name': 'str', 'software_version': 'str',
+ 'software_revision': 'str', 'supportedRHEVMs': ['str'],
+ 'supportedProtocols': ['str'], 'clusterLevels': ['str']}}
+
+##
+## @Host.getVersionInfo:
+#
+# Get VDSM version information
+#
+# Returns:
+# The versions dictionary
+#
+# Since: 4.10.1
+##
+{'command': {'class': 'Host', 'name': 'getVersionInfo'},
+ 'returns': 'HostInfo'}
+
+##
# @StorageDomainImageClass:
#
# An enumeration of Storage Domain classes.
--
To view, visit http://gerrit.ovirt.org/8431
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3f55ef437ca404ca04598d34c41756b1e68ced95
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Peter V. Saveliev <peet(a)redhat.com>
10 years, 4 months
Change in vdsm[master]: Change log message from warning to debug
by ykaplan@redhat.com
Yeela Kaplan has uploaded a new change for review.
Change subject: Change log message from warning to debug
......................................................................
Change log message from warning to debug
Related to BZ#876558
Change-Id: I87d78a36abe0751960ecd4e7798d79210a3a0704
Signed-off-by: Yeela Kaplan <ykaplan(a)redhat.com>
---
M vdsm/storage/blockVolume.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/21/10621/1
diff --git a/vdsm/storage/blockVolume.py b/vdsm/storage/blockVolume.py
index 186ca95..f399d58 100644
--- a/vdsm/storage/blockVolume.py
+++ b/vdsm/storage/blockVolume.py
@@ -641,7 +641,7 @@
def _getVolumeTag(sdUUID, volUUID, tagPrefix):
tags = lvm.getLV(sdUUID, volUUID).tags
if TAG_VOL_UNINIT in tags:
- log.warning("Reloading uninitialized volume %s/%s", sdUUID, volUUID)
+ log.debug("Reloading uninitialized volume %s/%s", sdUUID, volUUID)
lvm.invalidateVG(sdUUID)
tags = lvm.getLV(sdUUID, volUUID).tags
if TAG_VOL_UNINIT in tags:
--
To view, visit http://gerrit.ovirt.org/10621
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I87d78a36abe0751960ecd4e7798d79210a3a0704
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Yeela Kaplan <ykaplan(a)redhat.com>
10 years, 4 months
Change in vdsm[master]: Move uninstall preun section to vdsm-unregister
by lilei@linux.vnet.ibm.com
Lei Li has uploaded a new change for review.
Change subject: Move uninstall preun section to vdsm-unregister
......................................................................
Move uninstall preun section to vdsm-unregister
The specfile vdsm.spec.in has very long %post and %preun
sections, move the install/uninstall hooks into vdsm-tool.
This patch move unregister to a script which will be
encapsulated into a vdsm-tool function stop-vdsm-service.
Change-Id: I4e7b5dc969dfb51e6880b9bb209a363609f5e123
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
M vdsm.spec.in
M vdsm/Makefile.am
A vdsm/vdsm-unregister.in
3 files changed, 36 insertions(+), 42 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/26/4526/1
--
To view, visit http://gerrit.ovirt.org/4526
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I4e7b5dc969dfb51e6880b9bb209a363609f5e123
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Lei Li <lilei(a)linux.vnet.ibm.com>
10 years, 4 months
Change in vdsm[master]: utils.py: Add hostUUID retrieval support for KVM on PPC64
by Pradipta Kumar Banerjee
Pradipta Banerjee has uploaded a new change for review.
Change subject: utils.py: Add hostUUID retrieval support for KVM on PPC64
......................................................................
utils.py: Add hostUUID retrieval support for KVM on PPC64
Change-Id: I7a557b096550631e340fcc61bcb3fa4c3ae73837
Signed-off-by: Pradipta Kr. Banerjee <bpradip(a)in.ibm.com>
---
M vdsm/utils.py
1 file changed, 16 insertions(+), 10 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/37/8637/1
diff --git a/vdsm/utils.py b/vdsm/utils.py
index 0dbb342..80582d4 100644
--- a/vdsm/utils.py
+++ b/vdsm/utils.py
@@ -37,6 +37,7 @@
import functools
import stat
import glob
+import platform
import ethtool
@@ -701,19 +702,23 @@
with open(constants.P_VDSM_NODE_ID) as f:
__hostUUID = f.readline().replace("\n", "")
else:
- p = subprocess.Popen([constants.EXT_SUDO,
+ arch = platform.machine()
+ if arch == 'x86_64':
+ p = subprocess.Popen([constants.EXT_SUDO,
constants.EXT_DMIDECODE, "-s", "system-uuid"],
- close_fds=True, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = p.communicate()
- out = '\n'.join( line for line in out.splitlines()
+ close_fds=True, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ out = '\n'.join( line for line in out.splitlines()
if not line.startswith('#') )
- if p.returncode == 0 and 'Not' not in out:
- #Avoid error string - 'Not Settable' or 'Not Present'
- __hostUUID = out.strip()
- else:
- logging.warning('Could not find host UUID.')
+ if p.returncode == 0 and 'Not' not in out:
+ #Avoid error string - 'Not Settable' or 'Not Present'
+ __hostUUID = out.strip()
+ elif arch == 'ppc64':
+ if os.path.exists('/proc/device-tree/system-id'):
+ #eg. output IBM,03061C14A
+ __hostUUID = file('/proc/device-tree/system-id').readline().replace(",", "")
try:
mac = sorted(_getAllMacs())[0]
@@ -724,6 +729,7 @@
if __hostUUID != "None":
__hostUUID += "_" + mac
else:
+ logging.warning('Could not find host UUID')
__hostUUID = "_" + mac
except:
logging.error("Error retrieving host UUID", exc_info=True)
--
To view, visit http://gerrit.ovirt.org/8637
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7a557b096550631e340fcc61bcb3fa4c3ae73837
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Pradipta Banerjee <bpradip(a)in.ibm.com>
10 years, 4 months
Change in vdsm[master]: Adjust width for usage_command in vdsm-tool
by lilei@linux.vnet.ibm.com
Lei Li has uploaded a new change for review.
Change subject: Adjust width for usage_command in vdsm-tool
......................................................................
Adjust width for usage_command in vdsm-tool
The default value of width is 70 characters. It may not
be long enough for most of the usage_command comments.
So adjust it to add flexibility.
Change-Id: I800384e77452a76f651b73205b3335905274077c
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
---
M vdsm-tool/vdsm-tool
1 file changed, 2 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/48/4648/1
--
To view, visit http://gerrit.ovirt.org/4648
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I800384e77452a76f651b73205b3335905274077c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Lei Li <lilei(a)linux.vnet.ibm.com>
10 years, 4 months
Change in vdsm[master]: [WIP] Move vm logic to it's own module
by smizrahi@redhat.com
Saggi Mizrahi has uploaded a new change for review.
Change subject: [WIP] Move vm logic to it's own module
......................................................................
[WIP] Move vm logic to it's own module
Change-Id: Icc54c1d0ab7ad535d825dcd72fd2f4583b690f44
Signed-off-by: Saggi Mizrahi <smizrahi(a)redhat.com>
---
M vdsm/API.py
M vdsm/Makefile.am
M vdsm/clientIF.py
A vdsm/vmContainer.py
4 files changed, 134 insertions(+), 79 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/23/7423/1
diff --git a/vdsm/API.py b/vdsm/API.py
index e132fb9..818e00c 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -167,34 +167,36 @@
self.log.error("Error restoring VM parameters",
exc_info=True)
- requiredParams = ['vmId', 'memSize', 'display']
- for param in requiredParams:
+ for param in ['vmId', 'memSize', 'display']:
if param not in vmParams:
- self.log.error('Missing required parameter %s' % (param))
- return {'status': {'code': errCode['MissParam']
- ['status']['code'],
- 'message': 'Missing required' + \
- 'parameter %s' % (param)}}
+ return {'status': {
+ 'code': errCode['MissParam']['status']['code'],
+ 'message': 'Missing required parameter %s' % (param,)}
+ }
try:
storage.misc.validateUUID(vmParams['vmId'])
except:
- return {'status': {'code': errCode['MissParam']
- ['status']['code'],
- 'message': 'vmId must be a valid UUID'}}
+ return {'status': {
+ 'code': errCode['MissParam']['status']['code'],
+ 'message': 'vmId must be a valid UUID'}
+ }
if vmParams['memSize'] == 0:
- return {'status': {'code': errCode['MissParam']
- ['status']['code'],
- 'message': 'Must specify nonzero memSize'}}
+ return {'status': {
+ 'code': errCode['MissParam']['status']['code'],
+ 'message': 'Must specify nonzero memSize'}
+ }
if vmParams.get('boot') == 'c' and not 'hda' in vmParams \
and not vmParams.get('drives'):
- return {'status': {'code': errCode['MissParam']
- ['status']['code'],
- 'message': 'missing boot disk'}}
+ return {'status': {
+ 'code': errCode['MissParam']['status']['code'],
+ 'message': 'missing boot disk'}
+ }
if 'vmType' not in vmParams:
vmParams['vmType'] = 'kvm'
- elif vmParams['vmType'] == 'kvm':
+
+ if vmParams['vmType'] == 'kvm':
if 'kvmEnable' not in vmParams:
vmParams['kvmEnable'] = 'true'
@@ -205,25 +207,27 @@
vmParams['volatileFloppy'] = True
if caps.osversion()['name'] == caps.OSName.UNKNOWN:
- return {'status': {'code': errCode['createErr']
- ['status']['code'],
- 'message': 'Unknown host operating system'}}
+ return {'status': {
+ 'code': errCode['createErr']['status']['code'],
+ 'message': 'Unknown host operating system'}
+ }
if 'sysprepInf' in vmParams:
if not self._createSysprepFloppyFromInf(vmParams['sysprepInf'],
vmParams['floppy']):
- return {'status': {'code': errCode['createErr']
- ['status']['code'],
- 'message': 'Failed to create '
- 'sysprep floppy image. '
- 'No space on /tmp?'}}
- return errCode['createErr']
+ return {'status': {
+ 'code': errCode['createErr']['status']['code'],
+ 'message': 'Failed to create sysprep floppy image. '
+ 'No space on /tmp?'}
+ }
if vmParams.get('display') not in ('vnc', 'qxl', 'qxlnc', 'local'):
- return {'status': {'code': errCode['createErr']
- ['status']['code'],
- 'message': 'Unknown display type %s'
- % vmParams.get('display')}}
+ return {'status': {
+ 'code': errCode['createErr']['status']['code'],
+ 'message': 'Unknown display type %s' %
+ vmParams.get('display')}
+ }
+
if 'nicModel' not in vmParams:
vmParams['nicModel'] = config.get('vars', 'nic_model')
vmParams['displayIp'] = self._getNetworkIp(vmParams.get(
diff --git a/vdsm/Makefile.am b/vdsm/Makefile.am
index d4c52ed..574d762 100644
--- a/vdsm/Makefile.am
+++ b/vdsm/Makefile.am
@@ -53,6 +53,7 @@
tc.py \
vdsmDebugPlugin.py \
vmChannels.py \
+ vmContainer.py \
vm.py \
$(NULL)
diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py
index b9a4913..b2438fb 100644
--- a/vdsm/clientIF.py
+++ b/vdsm/clientIF.py
@@ -24,6 +24,7 @@
import pickle
from xml.dom import minidom
import uuid
+import errno
from storage.dispatcher import Dispatcher
from storage.hsm import HSM
@@ -40,9 +41,9 @@
import configNetwork
import caps
from vmChannels import Listener
-from libvirtvm import LibvirtVm
import blkid
import supervdsm
+import vmContainer
try:
import gluster.api as gapi
_glusterEnabled = True
@@ -66,7 +67,6 @@
:param log: a log object to be used for this object's logging.
:type log: :class:`logging.Logger`
"""
- self.vmContainerLock = threading.Lock()
self._networkSemaphore = threading.Semaphore()
self._shutdownSemaphore = threading.Semaphore()
self.log = log
@@ -82,7 +82,7 @@
else:
self.gluster = None
try:
- self.vmContainer = {}
+ self.vmContainer = vmContainer.VmContainer()
ifids = netinfo.nics() + netinfo.bondings()
ifrates = map(netinfo.speed, ifids)
self._hostStats = utils.HostStatsThread(
@@ -328,24 +328,19 @@
return res['status']['code']
def createVm(self, vmParams):
- self.vmContainerLock.acquire()
- self.log.info("vmContainerLock acquired by vm %s",
- vmParams['vmId'])
try:
- if 'recover' not in vmParams:
- if vmParams['vmId'] in self.vmContainer:
- self.log.warning('vm %s already exists' %
- vmParams['vmId'])
- return errCode['exist']
- vm = LibvirtVm(self, vmParams)
- self.vmContainer[vmParams['vmId']] = vm
- finally:
- container_len = len(self.vmContainer)
- self.vmContainerLock.release()
- vm.run()
- self.log.debug("Total desktops after creation of %s is %d" %
- (vmParams['vmId'], container_len))
- return {'status': doneCode, 'vmList': vm.status()}
+ vm = self.vmContainer.createVm(vmParams)
+ return {'status': doneCode, 'vmList': vm.status()}
+ except vmContainer.VmContainerError as e:
+ if e.errno == errno.EEXIST:
+ return errCode['exist']
+ return
+
+ def waitForShutdown(self, timeout=None):
+ self.shutdownEvent(timeout)
+ # Some versions of python have a bug where wait doesn't
+ # really return the correct value.
+ return self.shutdownEvent.isSet()
def _recoverExistingVms(self):
try:
@@ -364,10 +359,11 @@
'process with id: %s',
vmId, exc_info=True)
- while (self._enabled and
- 'WaitForLaunch' in [v.lastStatus for v in
- self.vmContainer.values()]):
- time.sleep(1)
+ vmList = self.vmContainer.getVMs()
+ while ('WaitForLaunch' in (v.lastStatus for v in vmList)):
+ if self.waitForShutdown(1):
+ break
+
self._cleanOldFiles()
self._recovery = False
@@ -375,20 +371,23 @@
# and then prepare all volumes.
# Actually, we need it just to get the resources for future
# volumes manipulations
- while self._enabled and self.vmContainer and \
- not self.irs.getConnectedStoragePoolsList()['poollist']:
- time.sleep(5)
+ if len(vmList) > 0:
+ while not self.irs.getConnectedStoragePoolsList()['poollist']:
+ if self.waitForShutdown(5):
+ break
- for vmId, vmObj in self.vmContainer.items():
- # Let's recover as much VMs as possible
+ # Let's recover as many VMs as possible
+ for vmObj in vmList:
+ # Do not prepare volumes when system goes down
+ if self.waitForShutdown(0):
+ break
+
try:
- # Do not prepare volumes when system goes down
- if self._enabled:
- vmObj.preparePaths(
- vmObj.getConfDevices()[vm.DISK_DEVICES])
+ devices = vmObj.getConfDevices()[vm.DISK_DEVICES]
+ vmObj.preparePaths(devices)
except:
- self.log.error("Vm %s recovery failed",
- vmId, exc_info=True)
+ self.log.error("Vm '%s' recovery failed", vmObj.id,
+ exc_info=True)
except:
self.log.error("Vm's recovery failed", exc_info=True)
@@ -452,27 +451,27 @@
return recoveryFile
except:
self.log.debug("Error recovering VM", exc_info=True)
- return None
def _cleanOldFiles(self):
for f in os.listdir(constants.P_VDSM_RUN):
try:
vmId, fileType = f.split(".", 1)
- if fileType in ["guest.socket", "monitor.socket", "pid",
+ if fileType not in ["guest.socket", "monitor.socket", "pid",
"stdio.dump", "recovery"]:
- if vmId in self.vmContainer:
- continue
- if f == 'vdsmd.pid':
- continue
- if f == 'respawn.pid':
- continue
- if f == 'svdsm.pid':
- continue
- if f == 'svdsm.sock':
- continue
- else:
continue
- self.log.debug("removing old file " + f)
+
+ if self.vmContainer.hasVM(vmId):
+ continue
+
+ #FIXME: Move VM crud to a subdir so we don't need a
+ # whitelist. I remember spending a considerable amount of
+ # time while writing Super VDSM trying to figure out why my
+ # pid file was disappearing!
+ if f in ('vdsmd.pid', 'respawn.pid',
+ 'svdsm.pid', 'svdsm.sock'):
+ continue
+
+ self.log.debug("Removing old file '%s'", f)
utils.rmFile(constants.P_VDSM_RUN + f)
except:
pass
diff --git a/vdsm/vmContainer.py b/vdsm/vmContainer.py
new file mode 100644
index 0000000..f15b8eb
--- /dev/null
+++ b/vdsm/vmContainer.py
@@ -0,0 +1,51 @@
+import logging
+import threading
+from libvirtvm import LibvirtVm
+import os
+import errno
+
+
+class VmContainerError(OSError):
+ def __init__(self, errno):
+ OSError.__init__(self, errno, os.strerror(errno))
+
+
+class VmContainer(object):
+ log = logging.getLogger("VmContainer")
+
+ def __init__(self):
+ self._syncroot = threading.Lock()
+ self._vms = {}
+
+ def createVm(self, vmParams):
+ self.log.info("vmContainerLock acquired by vm %s",
+ vmParams['vmId'])
+
+ with self._syncRoot:
+ if 'recover' not in vmParams:
+ if vmParams['vmId'] in self._vms:
+ self.log.warning('vm %s already exists' % vmParams['vmId'])
+
+ raise VmContainerError(errno.EEXIST)
+
+ vm = LibvirtVm(self, vmParams)
+ self._vms[vmParams['vmId']] = vm
+
+ container_len = len(self._vms)
+
+ vm.run()
+ self.log.debug("Total desktops after creation of %s is %d" %
+ (vmParams['vmId'], container_len))
+
+ return vm
+
+ def getVMs(self):
+ return self._vms.values()
+
+ def hasVM(self, vmId):
+ with self._syncRoot:
+ return vmId in self._vms
+
+ def get(self, vmId):
+ with self._syncRoot:
+ return self._vms.get(vmId)
--
To view, visit http://gerrit.ovirt.org/7423
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Icc54c1d0ab7ad535d825dcd72fd2f4583b690f44
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Saggi Mizrahi <smizrahi(a)redhat.com>
10 years, 4 months
Change in vdsm[master]: add verb for vdsm to tuneCpu params
by lvroyce@linux.vnet.ibm.com
Royce Lv has uploaded a new change for review.
Change subject: add verb for vdsm to tuneCpu params
......................................................................
add verb for vdsm to tuneCpu params
Engine and Mom need an interface to cap the max cpu and share.
So add this verb to vdsm.
tuneCpu:
Dynamically tune cpu absolute max proportion and relative share.
Input:
vmId: VM to be tuned
max_proportion=<value>: absolute max proportion for each vCPU can consume
-1:no limit,[0.001,1]:valid proportion
relative_share=<value>:relative share of CPU compared with other VMs
output:
success: return doneCode
failure: return errCode tunecpuErr.
Change-Id: I09e02e09ef06ad6de45be75c3f2f913a3025750f
Signed-off-by: Royce Lv<lvroyce(a)linux.vnet.ibm.com>
---
M vdsm/API.py
M vdsm/BindingXMLRPC.py
M vdsm/define.py
M vdsm/libvirtvm.py
M vdsm/storage/misc.py
M vdsm_cli/vdsClient.py
6 files changed, 97 insertions(+), 8 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/92/7492/1
diff --git a/vdsm/API.py b/vdsm/API.py
index 827f73b..f0c47d1 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -26,6 +26,7 @@
import time
import threading
import logging
+import math
from vdsm import utils
from clientIF import clientIF
@@ -37,6 +38,7 @@
import storage.volume
import storage.sd
import storage.image
+import storage.storage_exception as se
from vdsm.define import doneCode, errCode, Kbytes, Mbytes
import caps
from vdsm.config import config
@@ -555,6 +557,33 @@
message = USER_SHUTDOWN_MESSAGE
return v.shutdown(delay, message)
+ def tuneCpu(self, tuneParams):
+ try:
+ v = self._cif.vmContainer[self._UUID]
+ if 'relative_share' in tuneParams:
+ tuneParams['cpu_shares'] = storage.misc.validateN(
+ tuneParams['relative_share'], 'relative_share')
+ del(tuneParams['relative_share'])
+ if 'max_proportion' in tuneParams:
+ max = storage.misc.validateFloat(
+ tuneParams['max_proportion'], 'max_proportion')
+ tuneParams['vcpu_period'] = 1000000
+ if max > 1:
+ raise se.InvalidParameterException('max_proportion', max)
+ elif max >= 0.001:
+ tuneParams['vcpu_quota'] = int(
+ round(tuneParams['vcpu_period'] * max))
+ else:
+ tuneParams['vcpu_quota'] = int(math.floor(max))
+ del(tuneParams['max_proportion'])
+ del(tuneParams['vmId'])
+ except KeyError:
+ return errCode['noVM']
+ except se.InvalidParameterException:
+ return errCode['tunecpuErr']
+
+ return v.tuneCpu(tuneParams)
+
def _createSysprepFloppyFromInf(self, infFileBinary, floppyImage):
try:
rc, out, err = utils.execCmd([constants.EXT_MK_SYSPREP_FLOPPY,
diff --git a/vdsm/BindingXMLRPC.py b/vdsm/BindingXMLRPC.py
index 826c125..37b1f60 100644
--- a/vdsm/BindingXMLRPC.py
+++ b/vdsm/BindingXMLRPC.py
@@ -265,6 +265,10 @@
vm = API.VM(vmId)
return vm.snapshot(snapDrives)
+ def vmTuneCpu(self, params):
+ vm = API.VM(params['vmId'])
+ return vm.tuneCpu(params)
+
def vmMerge(self, vmId, mergeDrives):
vm = API.VM(vmId)
return vm.merge(mergeDrives)
@@ -765,7 +769,8 @@
(self.vmHotplugDisk, 'hotplugDisk'),
(self.vmHotunplugDisk, 'hotunplugDisk'),
(self.vmHotplugNic, 'hotplugNic'),
- (self.vmHotunplugNic, 'hotunplugNic'))
+ (self.vmHotunplugNic, 'hotunplugNic'),
+ (self.vmTuneCpu, 'tuneCpu'))
def getIrsMethods(self):
return ((self.domainActivate, 'activateStorageDomain'),
diff --git a/vdsm/define.py b/vdsm/define.py
index 049d36c..d41d467 100644
--- a/vdsm/define.py
+++ b/vdsm/define.py
@@ -117,6 +117,9 @@
'momErr': {'status':
{'code': 54,
'message': 'Failed to set mom policy'}},
+ 'tunecpuErr': {'status':
+ {'code': 55,
+ 'message': 'Failed to Tune CPU'}},
'recovery': {'status':
{'code': 99,
'message':
diff --git a/vdsm/libvirtvm.py b/vdsm/libvirtvm.py
index e95e94b..59c7ec6 100644
--- a/vdsm/libvirtvm.py
+++ b/vdsm/libvirtvm.py
@@ -1371,13 +1371,17 @@
if self._initTimePauseCode == 'ENOSPC':
self.cont()
self.conf['pid'] = self._getPid()
-
- nice = int(self.conf.get('nice', '0'))
- nice = max(min(nice, 19), 0)
- try:
- self._dom.setSchedulerParameters({'cpu_shares': (20 - nice) * 51})
- except:
- self.log.warning('failed to set Vm niceness', exc_info=True)
+ #do not trying to change cpu_shares for recovery and restore flows
+ if not 'recover' in self.conf and not 'restoreState' in self.conf:
+ nice = int(self.conf.get('nice', '0'))
+ nice = max(min(nice, 19), 0)
+ cpuShare = (20 - nice) * 51
+ try:
+ self._dom.setSchedulerParameters({'cpu_shares': cpuShare})
+ except:
+ self.log.warning('failed to set Vm niceness', exc_info=True)
+ self.conf['cpu_shares'] = cpuShare
+ self.saveState()
def _run(self):
self.log.info("VM wrapper has started")
@@ -1931,6 +1935,23 @@
(snapFlags & libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE
== libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE)}
+ def tuneCpu(self, tuneParams):
+ try:
+ self._dom.setSchedulerParameters(tuneParams)
+ self.conf['cpu_shares'] = tuneParams.get('cpu_shares')
+ self.conf['vcpu_quota'] = tuneParams.get('vcpu_quota')
+ self.conf['vcpu_period'] = tuneParams.get('vcpu_period')
+ self.saveState()
+ return {'status': doneCode}
+ except libvirt.libvirtError, e:
+ self.log.error("TuneCpu failed:%s",
+ e.message, exc_info=True)
+ return errCode['tunecpuErr']
+ except LookupError:
+ self.log.error('TuneCpu failed: unrecongnized params',
+ exc_info=True)
+ return errCode['tunecpuErr']
+
def _runMerge(self):
for mergeStatus in self.conf.get('liveMerge', []):
if mergeStatus['status'] != MERGESTATUS.NOT_STARTED:
diff --git a/vdsm/storage/misc.py b/vdsm/storage/misc.py
index 161726b..1f5ed1a 100644
--- a/vdsm/storage/misc.py
+++ b/vdsm/storage/misc.py
@@ -503,6 +503,13 @@
return n
+def validateFloat(floatNumber, name):
+ try:
+ return float(floatNumber)
+ except:
+ raise se.InvalidParameterException(floatNumber, name)
+
+
def rotateFiles(directory, prefixName, gen, cp=False, persist=False):
log.debug("dir: %s, prefixName: %s, versions: %s" %
(directory, prefixName, gen))
diff --git a/vdsm_cli/vdsClient.py b/vdsm_cli/vdsClient.py
index a164c20..ab0fa4c 100644
--- a/vdsm_cli/vdsClient.py
+++ b/vdsm_cli/vdsClient.py
@@ -204,6 +204,18 @@
return self.ExecAndExit(self.s.create(params))
+ def tuneCpu(self, args):
+ params = {}
+ confLines = []
+ params['vmId'] = args[0]
+ if len(args) > 1:
+ confLines.extend(args[1:])
+ for line in confLines:
+ if '=' in line:
+ param, value = line.split("=", 1)
+ params[param] = value
+ return self.ExecAndExit(self.s.tuneCpu(params))
+
def hotplugNic(self, args):
nic = self._parseDriveSpec(args[1])
nic['type'] = 'interface'
@@ -1802,6 +1814,18 @@
'Optional additional parameters in dictionary format,'
' name:value,name:value'
)),
+ 'tuneCpu': (serv.tuneCpu,
+ ('<vmId>'
+ '[max_proportion=value relative_share=value]',
+ 'Parameters list: r=required, o=optional',
+ 'r vmId: The vm to be tuned',
+ 'o max_proportion=<value>: '
+ 'max proportion for each vCPU can be consumed, '
+ '-1 is no limit,[0.001,1] is valid proportion',
+ 'o relative_share=<value>:relative share of CPU'
+ 'compared with other VMs',
+ 'Dynamically tune cpu absolute max proportion and relative share'
+ )),
'migrate': (serv.do_migrate,
('vmId=<id> method=<offline|online> src=<host:[port]> '
'dst=<host:[port]>',
--
To view, visit http://gerrit.ovirt.org/7492
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I09e02e09ef06ad6de45be75c3f2f913a3025750f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
10 years, 5 months