Change in vdsm[master]: virt: graphdev: support headless VM
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: virt: graphdev: support headless VM
......................................................................
virt: graphdev: support headless VM
This patch add support for headless VMs, aka VMs without
a graphic device.
Noteworthy side effects of this patch:
* It is now possible to create a VM without any display
(aka headless VM), and they are supported.
* The input 'display' parameter of the Vm.create API is
no longer mandatory
* In the API schema, the display* parameters are now
marked as optional, even though Engine is expected to still
send them in the near/medium term.
* setTicket and the internally used _reviveTicket can now
fail if they are invoked against a VM without graphic devices.
Change-Id: Iafeb0bebfb43c089614127d94c054175c111ce54
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M tests/functional/virtTests.py
M tests/vmTests.py
M vdsm/API.py
M vdsm/virt/vm.py
M vdsm_api/vdsmapi-schema.json
5 files changed, 117 insertions(+), 72 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/46/27846/1
diff --git a/tests/functional/virtTests.py b/tests/functional/virtTests.py
index a074e62..9a25850 100644
--- a/tests/functional/virtTests.py
+++ b/tests/functional/virtTests.py
@@ -225,6 +225,14 @@
self._waitForStartup(vm, VM_MINIMAL_UPTIME)
@requireKVM
+ def testHeadlessVm(self):
+ customization = {'vmId': '77777777-ffff-3333-bbbb-222222222222',
+ 'vmName': 'testHeadlessVm'}
+
+ with RunningVm(self.vdsm, customization) as vm:
+ self._waitForStartup(vm, VM_MINIMAL_UPTIME)
+
+ @requireKVM
@permutations([['localfs'], ['iscsi'], ['nfs']])
def testVmWithStorage(self, backendType):
disk = storage.StorageTest()
diff --git a/tests/vmTests.py b/tests/vmTests.py
index 69d5643..4022dfb 100644
--- a/tests/vmTests.py
+++ b/tests/vmTests.py
@@ -1077,6 +1077,11 @@
devs = fake.buildConfDevices()
self.assertTrue(devs['graphics'])
+ def testGraphicDeviceHeadless(self):
+ with FakeVM(self.conf) as fake:
+ devs = fake.buildConfDevices()
+ self.assertFalse(devs['graphics'])
+
def testGraphicsDeviceMixed(self):
"""
if proper Graphics Devices are supplied, display* params must be
diff --git a/vdsm/API.py b/vdsm/API.py
index 14e7bae..4747be1 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -200,7 +200,7 @@
self.log.error("Error restoring VM parameters",
exc_info=True)
- requiredParams = ['vmId', 'memSize', 'display']
+ requiredParams = ['vmId', 'memSize']
for param in requiredParams:
if param not in vmParams:
self.log.error('Missing required parameter %s' % (param))
@@ -252,11 +252,6 @@
'No space on /tmp?'}}
return errCode['createErr']
- if not vm.GraphicsDevice.isSupportedDisplayType(vmParams):
- 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')
return self._cif.createVm(vmParams)
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index a547a5e..5d08cea 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -1344,10 +1344,6 @@
'main', 'display', 'inputs', 'cursor', 'playback',
'record', 'smartcard', 'usbredir')
- @staticmethod
- def isSupportedDisplayType(vmParams):
- return vmParams.get('display') in ('vnc', 'qxl', 'qxlnc')
-
def __init__(self, conf, log, **kwargs):
super(GraphicsDevice, self).__init__(conf, log, **kwargs)
self.port = self.LIBVIRT_PORT_AUTOSELECT
@@ -1840,8 +1836,8 @@
if len(devices[device]) > 1:
raise ValueError("only a single %s device is "
"supported" % device)
- if len(devices[GRAPHICS_DEVICES]) != 1:
- raise ValueError("one graphics device is required")
+ if len(devices[GRAPHICS_DEVICES]) > 1:
+ raise ValueError("only one graphics device is supported")
def getConfController(self):
"""
@@ -1866,12 +1862,16 @@
devType = DEFAULT_VIDEOS[self.arch]
elif self.hasSpice:
devType = 'qxl'
+ else:
+ devType = None
- monitors = int(self.conf.get('spiceMonitors', '1'))
- vram = '65536' if (monitors <= 2) else '32768'
- for idx in range(monitors):
- vcards.append({'type': VIDEO_DEVICES, 'specParams': {'vram': vram},
- 'device': devType})
+ if devType:
+ monitors = int(self.conf.get('spiceMonitors', '1'))
+ vram = '65536' if (monitors <= 2) else '32768'
+ for idx in range(monitors):
+ vcards.append({'type': VIDEO_DEVICES,
+ 'specParams': {'vram': vram},
+ 'device': devType})
return vcards
@@ -1885,13 +1885,18 @@
for oldName, newName in GraphicsDevice.LEGACY_MAP.iteritems()
if oldName in conf)
- return [{
- 'type': GRAPHICS_DEVICES,
- 'device': (
- 'spice'
- if self.conf['display'] in ('qxl', 'qxlnc')
- else 'vnc'),
- 'specParams': makeSpecParams(self.conf)}]
+ graphDevs = []
+
+ if 'display' in self.conf:
+ graphDevs.append({
+ 'type': GRAPHICS_DEVICES,
+ 'device': (
+ 'spice'
+ if self.conf['display'] in ('qxl', 'qxlnc')
+ else 'vnc'),
+ 'specParams': makeSpecParams(self.conf)})
+
+ return graphDevs
def getConfSound(self):
"""
@@ -2520,10 +2525,6 @@
return self._getExitedVmStats()
stats = {
- 'displayPort': self.conf['displayPort'],
- 'displaySecurePort': self.conf['displaySecurePort'],
- 'displayType': self.conf['display'],
- 'displayIp': self.conf['displayIp'],
'pid': self.conf['pid'],
'vmType': self.conf['vmType'],
'kvmEnable': self._kvmEnable,
@@ -2534,6 +2535,8 @@
stats['cdrom'] = self.conf['cdrom']
if 'boot' in self.conf:
stats['boot'] = self.conf['boot']
+
+ stats.update(self._getGraphicsStats())
decStats = {}
try:
@@ -2602,6 +2605,16 @@
'exitReason': self.conf['exitReason']}
if 'timeOffset' in self.conf:
stats['timeOffset'] = self.conf['timeOffset']
+ return stats
+
+ def _getGraphicsStats(self):
+ stats = {}
+ if 'display' in self.conf:
+ stats['displayType'] = self.conf['display']
+ stats['displayPort'] = self.conf['displayPort']
+ stats['displaySecurePort'] = self.conf['displaySecurePort']
+ stats['displayIp'] = self.conf['displayIp']
+ # else headless VM
return stats
def isMigrating(self):
@@ -4266,8 +4279,13 @@
return {'status': doneCode, 'vmList': self.status()}
def setTicket(self, otp, seconds, connAct, params):
- graphics = _domParseStr(self._dom.XMLDesc(0)).childNodes[0]. \
- getElementsByTagName('graphics')[0]
+ try:
+ graphics = _domParseStr(self._dom.XMLDesc(0)).childNodes[0]. \
+ getElementsByTagName('graphics')[0]
+ except IndexError:
+ return {
+ 'status': {'code': errCode['ticketErr']['status']['code'],
+ 'message': 'no graphics devices configured'}}
graphics.setAttribute('passwd', otp)
if int(seconds) > 0:
validto = time.strftime('%Y-%m-%dT%H:%M:%S',
@@ -4288,9 +4306,13 @@
def _reviveTicket(self, newlife):
"""Revive an existing ticket, if it has expired or about to expire"""
- graphics = _domParseStr(
- self._dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)). \
- childNodes[0].getElementsByTagName('graphics')[0]
+ try:
+ graphics = _domParseStr(
+ self._dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)). \
+ childNodes[0].getElementsByTagName('graphics')[0]
+ except IndexError:
+ self.log.error('no graphics devices configured')
+ return
validto = max(time.strptime(graphics.getAttribute('passwdValidTo'),
'%Y-%m-%dT%H:%M:%S'),
time.gmtime(time.time() + newlife))
@@ -4855,19 +4877,20 @@
device of each type (sdl, vnc, spice) is supported
"""
graphicsXml = _domParseStr(self._lastXMLDesc).childNodes[0]. \
- getElementsByTagName('devices')[0].getElementsByTagName('graphics')[0]
+ getElementsByTagName('devices')[0].getElementsByTagName('graphics')
- graphicsType = graphicsXml.getAttribute('type')
- for dev in self.conf['devices']:
- if dev.get('device') == graphicsType:
- port = graphicsXml.getAttribute('port')
- if port:
- dev['port'] = port
- tlsPort = graphicsXml.getAttribute('tlsPort')
- if tlsPort:
- dev['tlsPort'] = tlsPort
- self._updateLegacyConf(dev)
- break
+ for gxml in graphicsXml:
+ graphicsType = gxml.getAttribute('type')
+
+ for dev in self.conf['devices']:
+ if dev.get('device') == graphicsType:
+ port = gxml.getAttribute('port')
+ if port:
+ dev['port'] = port
+ tlsPort = gxml.getAttribute('tlsPort')
+ if tlsPort:
+ dev['tlsPort'] = tlsPort
+ self._updateLegacyConf(dev)
def _getUnderlyingNetworkInterfaceInfo(self):
"""
@@ -5051,11 +5074,12 @@
return True
def _initLegacyConf(self):
- self.conf['displayPort'] = GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
- self.conf['displaySecurePort'] = \
- GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
- self.conf['displayIp'] = _getNetworkIp(
- self.conf.get('displayNetwork'))
+ if 'display' in self.conf:
+ self.conf['displayPort'] = GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
+ self.conf['displaySecurePort'] = \
+ GraphicsDevice.LIBVIRT_PORT_AUTOSELECT
+ self.conf['displayIp'] = _getNetworkIp(
+ self.conf.get('displayNetwork'))
def _updateLegacyConf(self, dev):
self.conf['display'] = 'qxl' if dev['device'] == 'spice' else 'vnc'
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index a9332ee..64d4179 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -3175,13 +3175,17 @@
#
# @devices: #optional An array of VM devices present
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
# @emulatedMachine: #optional The machine specification being emulated
#
@@ -3235,8 +3239,8 @@
{'type': 'VmDefinition',
'data': {'acpiEnable': 'bool', 'clientIp': 'str', 'cpuShares': 'str',
'*cpuType': 'str', '*custom': 'StringMap', '*devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'displayIp': 'str',
- 'displayPort': 'int', 'displaySecurePort': 'int',
+ '*display': 'VmDisplayType', '*displayIp': 'str',
+ '*displayPort': 'int', '*displaySecurePort': 'int',
'*emulatedMachine': 'str', '*keyboardLayout': 'str',
'kvmEnable': 'bool', '*maxVCpus': 'uint', 'memSize': 'uint',
'memGuaranteedSize': 'uint', 'nicModel': 'str', 'nice': 'int',
@@ -3264,7 +3268,8 @@
#
# @devices: #optional An array of VM devices requested
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
# @kvmEnable: Indicates if KVM hardware acceleration is enabled
#
@@ -3300,7 +3305,7 @@
{'type': 'VmParameters',
'data': {'acpiEnable': 'bool', '*bootMenuEnable': 'bool',
'*cpuShares': 'str', '*custom': 'StringMap', '*devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
+ '*display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
'nice': 'int', 'smp': 'uint', '*smpCoresPerSocket': 'uint',
'*smpThreadsPerCore': 'uint', 'timeOffset': 'uint',
'transparentHugePages': 'bool', 'vmId': 'UUID', 'vmName': 'str',
@@ -3347,7 +3352,8 @@
#
# @devices: An array of VM devices requested
#
-# @display: The type of display
+# @display: #optional The type of display
+# (made optional in version 4.15.0)
#
# @kvmEnable: Indicates if KVM hardware acceleration is enabled
#
@@ -3372,7 +3378,8 @@
#
# @memGuaranteedSize: The amount of memory guaranteed to the VM in MB
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
# @spiceSecureChannels: Secure space channels comma separated
#
@@ -3394,11 +3401,13 @@
# @guestFQDN: Fully qualified domain name of the guest OS. (Reported
# by the guest agent)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
# @keyboardLayout: The keyboard layout string (eg. 'en-us')
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
# @guestIPs: A space separated string of assigned IPv4 addresses
#
@@ -3416,15 +3425,15 @@
##
{'type': 'VMFullInfo',
'data': {'acpiEnable': 'bool', 'custom': 'StringMap', 'devices': ['VmDevice'],
- 'display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
+ '*display': 'VmDisplayType', 'kvmEnable': 'bool', 'memSize': 'uint',
'nice': 'int', 'smp': 'uint', 'smpCoresPerSocket': 'uint',
'timeOffset': 'uint', 'transparentHugePages': 'bool', 'vmId': 'UUID',
'vmName': 'str', 'vmType': 'VmType', 'memGuaranteedSize': 'uint',
- 'displaySecurePort': 'uint', 'spiceSecureChannels': 'str',
+ '*displaySecurePort': 'uint', 'spiceSecureChannels': 'str',
'username': 'str', 'emulatedMachine': 'str', 'pid': 'uint',
'spiceSslCipherSuite': 'str', 'cpuType': 'str', 'pauseCode': 'str',
- 'guestFQDN': 'str', 'displayIp': 'str', 'keyboardLayout': 'str',
- 'displayPort': 'uint', 'guestIPs': 'str', 'smartcardEnable': 'bool',
+ 'guestFQDN': 'str', '*displayIp': 'str', 'keyboardLayout': 'str',
+ '*displayPort': 'uint', 'guestIPs': 'str', 'smartcardEnable': 'bool',
'nicModel': 'VmInterfaceDeviceModel', 'pitReinjection': 'bool',
'status': 'str', 'clientIp': 'str'}}
@@ -6016,13 +6025,17 @@
#
# Statistics for a running virtual machine.
#
-# @displayPort: The port in use for unencrypted display data
+# @displayPort: #optional The port in use for unencrypted display data
+# (made optional in version 4.15.0)
#
-# @displaySecurePort: The port in use for encrypted display data
+# @displaySecurePort: #optional The port in use for encrypted display data
+# (made optional in version 4.15.0)
#
-# @displayType: The type of display in use
+# @displayType: #optional The type of display in use
+# (made optional in version 4.15.0)
#
-# @displayIp: The IP address to use for accessing the VM display
+# @displayIp: #optional The IP address to use for accessing the VM display
+# (made optional in version 4.15.0)
#
# @pid: The process ID of the underlying qemu process
#
@@ -6089,8 +6102,8 @@
# Since: 4.10.0
##
{'type': 'RunningVmStats',
- 'data': {'displayPort': 'uint', 'displaySecurePort': 'uint',
- 'displayType': 'VmDisplayType', 'displayIp': 'str', 'pid': 'uint',
+ 'data': {'*displayPort': 'uint', '*displaySecurePort': 'uint',
+ '*displayType': 'VmDisplayType', '*displayIp': 'str', 'pid': 'uint',
'vmType': 'VmType', 'kvmEnable': 'bool',
'network': 'NetworkInterfaceStatsMap',
'disks': 'VmDiskStatsMap', 'monitorResponse': 'int',
--
To view, visit http://gerrit.ovirt.org/27846
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iafeb0bebfb43c089614127d94c054175c111ce54
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: vm: run before_vm_create hook only in the VM boot
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: run before_vm_create hook only in the VM boot
......................................................................
vm: run before_vm_create hook only in the VM boot
The 'before_vm_create' hook is running in two flows:
* as expected, in the VM creation flow.
* as may not be expected, in the VM dehybernation flow.
The latter is surprising and, most important,
contractdicting because in the dehibernation flow
* the domain XML returned by the before_vm_create
is never used
* just after the before_vm_create hook, we run
the before_vm_dehibernate hook with the stored
domain XML.
At risk to breaking some probably already incorrect
hook, this patch makes the before_vm_create hook
run only in the VM creation path.
Change-Id: I2ad05e39029acc7b898c7b2af2141bba1d7d3c8e
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 3 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/30/34530/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 6e46119..751947e 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -2667,10 +2667,6 @@
# we need to complete the initialization, including
# domDependentInit, after the migration is completed.
- if not self.recovering and initDomain:
- domxml = hooks.before_vm_start(self._buildDomainXML(), self.conf)
- self.log.debug(domxml)
-
if self.recovering:
self._dom = NotifyingVirDomain(
self._connection.lookupByUUIDString(self.id),
@@ -2698,6 +2694,9 @@
self._connection.lookupByUUIDString(self.id),
self._timeoutExperienced)
else:
+ domxml = hooks.before_vm_start(self._buildDomainXML(), self.conf)
+ self.log.debug(domxml)
+
flags = libvirt.VIR_DOMAIN_NONE
if 'launchPaused' in self.conf:
flags |= libvirt.VIR_DOMAIN_START_PAUSED
--
To view, visit http://gerrit.ovirt.org/34530
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I2ad05e39029acc7b898c7b2af2141bba1d7d3c8e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: pyroute2: reuse created devices
by phoracek@redhat.com
Petr Horáček has uploaded a new change for review.
Change subject: pyroute2: reuse created devices
......................................................................
pyroute2: reuse created devices
When we try to create new device over existing one, pyroute2 raises
exception, while other configurators doesn't.
Now, if we try to create device which already exists, pyroute2 just
return existing device with no complains.
Change-Id: Ief8c2ad9e9a1a7369e4e81495daa3e31e613b5e5
Signed-off-by: Petr Horáček <phoracek(a)redhat.com>
---
M vdsm/network/configurators/pyroute_two.py
1 file changed, 4 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/97/34197/1
diff --git a/vdsm/network/configurators/pyroute_two.py b/vdsm/network/configurators/pyroute_two.py
index 59050e3..4986c12 100644
--- a/vdsm/network/configurators/pyroute_two.py
+++ b/vdsm/network/configurators/pyroute_two.py
@@ -108,7 +108,7 @@
self.ifup(iface)
def addBridge(self, bridge):
- self.ip.create(kind='bridge', ifname=bridge.name).commit()
+ self.ip.create(kind='bridge', ifname=bridge.name, reuse=True).commit()
def addBridgePort(self, bridge):
with self.ip.interfaces[bridge.name] as i:
@@ -124,8 +124,8 @@
def addVlan(self, vlan):
link = self.ip.interfaces[vlan.device.name].index
- self.ip.create(kind='vlan', ifname=vlan.name,
- link=link, vlan_id=vlan.tag).commit()
+ self.ip.create(kind='vlan', ifname=vlan.name, link=link,
+ vlan_id=vlan.tag, reuse=True).commit()
def removeVlan(self, vlan):
with self.ip.interfaces[vlan.name] as i:
@@ -133,7 +133,7 @@
def addBond(self, bond):
if bond.name not in netinfo.bondings():
- self.ip.create(kind='bond', ifname=bond.name).commit()
+ self.ip.create(kind='bond', ifname=bond.name, reuse=True).commit()
def removeBond(self, bond):
with self.ip.interfaces[bond.name] as i:
--
To view, visit http://gerrit.ovirt.org/34197
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ief8c2ad9e9a1a7369e4e81495daa3e31e613b5e5
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Petr Horáček <phoracek(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: pyroute2: release() is deprecated
by phoracek@redhat.com
Petr Horáček has uploaded a new change for review.
Change subject: pyroute2: release() is deprecated
......................................................................
pyroute2: release() is deprecated
release() method is deprecated, use close() instead.
Change-Id: Idbfe663b6180654dba76d69ccc11ecbf14abff8e
Signed-off-by: Petr Horáček <phoracek(a)redhat.com>
---
M vdsm/network/configurators/pyroute_two.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/99/34199/1
diff --git a/vdsm/network/configurators/pyroute_two.py b/vdsm/network/configurators/pyroute_two.py
index 08df1c4..1e41266 100644
--- a/vdsm/network/configurators/pyroute_two.py
+++ b/vdsm/network/configurators/pyroute_two.py
@@ -164,4 +164,4 @@
libvirt.removeNetwork(network)
def releaseSocket(self):
- self.ip.release()
+ self.ip.close()
--
To view, visit http://gerrit.ovirt.org/34199
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idbfe663b6180654dba76d69ccc11ecbf14abff8e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Petr Horáček <phoracek(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: networkTests: setupNetworksAddBondWithManyVlans bond not found
by phoracek@redhat.com
Petr Horáček has uploaded a new change for review.
Change subject: networkTests: setupNetworksAddBondWithManyVlans bond not found
......................................................................
networkTests: setupNetworksAddBondWithManyVlans bond not found
testSetupNetworksAddBondWithManyVlans always fails on Jenkins
with 'bond0.0' not found in ...' error
(http://jenkins.ovirt.org/job/vdsm_master_network_functional_
tests_gerrit/1837/testReport/junit/networkTests/NetworkTest/
testSetupNetworksAddBondWithManyVlans_kwargs_False_/)
Change-Id: Iccd0ba18ac223a63c6633ee64772cfe6998288b1
Signed-off-by: Petr Horáček <phoracek(a)redhat.com>
---
M tests/functional/networkTests.py
1 file changed, 2 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/55/31855/1
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index ed45b2a..581400b 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -294,6 +294,8 @@
@ValidateRunningAsRoot
def testSetupNetworksAddBondWithManyVlans(self, bridged):
def assertDevStatsReported():
+ # import time
+ # time.sleep(1)
status, msg, hostStats = self.vdsm_net.getVdsStats()
self.assertEqual(status, SUCCESS, msg)
self.assertIn('network', hostStats)
--
To view, visit http://gerrit.ovirt.org/31855
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iccd0ba18ac223a63c6633ee64772cfe6998288b1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Petr Horáček <phoracek(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: client: add option to make quiet
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: client: add option to make quiet
......................................................................
client: add option to make quiet
When used for (quite brutal) benchmarking, the output
from vdsClient can add noise and can cause a (little)
slowdown.
Add an option to make it quiet.
Change-Id: Icbb9654b47fd993aee34b2292a1d94d1e4019b6a
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M client/vdsClient.py
1 file changed, 25 insertions(+), 12 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/40/35340/1
diff --git a/client/vdsClient.py b/client/vdsClient.py
index 583a0a2..d675228 100644
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -183,11 +183,12 @@
self.useSSL = False
self.truststore = None
self.pretty = True
+ self.quiet = False
def do_connect(self, hostPort):
self.s = vdscli.connect(hostPort, self.useSSL, self.truststore)
- def ExecAndExit(self, response, parameterName='none'):
+ def printResponse(self, response, parameterName='none'):
if response['status']['code'] != 0:
print response['status']['message']
else:
@@ -202,6 +203,10 @@
printDict(response['info'], self.pretty)
else:
printDict(response['status'], self.pretty)
+
+ def ExecAndExit(self, response, parameterName='none'):
+ if not self.quiet:
+ self.printResponse(response, parameterName)
sys.exit(response['status']['code'])
def do_create(self, args):
@@ -309,7 +314,8 @@
if view == 'long':
if 'sysprepInf' in conf:
conf['sysprepInf'] = '<<exists>>'
- printConf(conf)
+ if not self.quiet:
+ printConf(conf)
elif view == 'table':
vmId = conf['vmId']
@@ -318,20 +324,23 @@
status = conf['status']
if allStats[vmId].get('monitorResponse') == '-1':
status += '*'
- print("%-36s %6s %-20s %-20s %-20s" %
- (vmId, conf.get('pid', 'none'),
- conf.get('vmName', '<< NO NAME >>'),
- status, allStats[vmId].get('guestIPs', '')))
+ if not self.quiet:
+ print("%-36s %6s %-20s %-20s %-20s" %
+ (vmId, conf.get('pid', 'none'),
+ conf.get('vmName', '<< NO NAME >>'),
+ status, allStats[vmId].get('guestIPs', '')))
elif view == 'ids':
- print conf['vmId']
+ if not self.quiet:
+ print conf['vmId']
sys.exit(response['status']['code'])
def do_destroy(self, args):
vmId = args[0]
response = self.s.destroy(vmId)
- print response['status']['message']
+ if not self.quiet:
+ print response['status']['message']
sys.exit(response['status']['code'])
def do_pause(self, args):
@@ -356,7 +365,8 @@
response = self.s.shutdown(vmId, delay, message, reboot)
else:
response = self.s.shutdown(vmId, delay, message)
- print response['status']['message']
+ if not self.quiet:
+ print response['status']['message']
sys.exit(response['status']['code'])
def do_setVmTicket(self, args):
@@ -2765,9 +2775,10 @@
commands.update(ge.getGlusterCmdDict(serv))
try:
- opts, args = getopt.getopt(sys.argv[1:], "hmso", ["help", "methods",
- "SSL", "truststore=",
- "oneliner"])
+ opts, args = getopt.getopt(sys.argv[1:],
+ "hmsoq",
+ ["help", "methods", "SSL", "truststore=",
+ "oneliner", "quiet"])
for o, v in opts:
if o == "-h" or o == "--help":
@@ -2782,6 +2793,8 @@
serv.truststore = v
if o == '-o' or o == '--oneliner':
serv.pretty = False
+ if o == '-q' or o == '--quiet':
+ serv.quiet = True
if len(args) < 2:
raise Exception("Need at least two arguments")
server, command = args[0:2]
--
To view, visit http://gerrit.ovirt.org/35340
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Icbb9654b47fd993aee34b2292a1d94d1e4019b6a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: client: vm params from JSON
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: client: vm params from JSON
......................................................................
client: vm params from JSON
the 'create' parameter accepts a configuration
file as source to define the parameters of the VM
being created.
This patch add support to
1. use JSON for this configuration file, so there is
little to no need to reformat data from Engine,
for example took from VDSM logs
2. use stdin as input, avoiding the need to write
(temporary) files.
Change-Id: Ic6a73bc0e5fe87eb1a48c708e7ea316c6d9df7e5
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M client/vdsClient.py
1 file changed, 95 insertions(+), 68 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/92/35292/1
diff --git a/client/vdsClient.py b/client/vdsClient.py
index aabf7a1..583a0a2 100644
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -19,6 +19,7 @@
import sys
import ast
+import json
import getopt
import traceback
import xmlrpclib
@@ -204,74 +205,13 @@
sys.exit(response['status']['code'])
def do_create(self, args):
- params = {}
- drives = []
- devices = []
- cpuPinning = {}
- numaTune = {}
- guestNumaNodes = []
- confLines = []
- confFile = open(args[0])
- for line in confFile.readlines():
- line = re.sub("\s+", '', line)
- line = re.sub("\#.*", '', line)
- if line:
- confLines.append(line)
- if len(args) > 1:
- confLines.extend(args[1:])
- for line in confLines:
- if '=' in line:
- param, value = line.split("=", 1)
- if param == 'devices':
- devices.append(self._parseDriveSpec(value))
- elif param == 'drive':
- drives.append(self._parseDriveSpec(value))
- elif param == 'cpuPinning':
- cpuPinning, rStr = self._parseNestedSpec(value)
- elif param == 'numaTune':
- numaTune, rStr = self._parseNestedSpec(value)
- elif param == 'guestNumaNodes':
- guestNumaNodes.append(self._parseDriveSpec(value))
- elif param.startswith('custom_'):
- if 'custom' not in params:
- params['custom'] = {}
- params['custom'][param[7:]] = value
- else:
- if param in ('cdrom', 'floppy'):
- value = self._parseDriveSpec(value)
- params[param] = value
- else:
- params[line.strip()] = ''
- if cpuPinning:
- params['cpuPinning'] = cpuPinning
- if numaTune:
- params['numaTune'] = numaTune
- if guestNumaNodes:
- params['guestNumaNodes'] = guestNumaNodes
- if drives:
- params['drives'] = drives
- if devices:
- params['devices'] = devices
- # Backward compatibility for vdsClient users
- if 'vt' in params:
- params['kvmEnable'] = params['vt']
-
- if 'imageFile' in params:
- params['hda'] = params['imageFile']
-
- drives = ['hdd', 'hdc', 'hdb']
- if 'moreImages' in params:
- for image in params['moreImages'].split(','):
- params[drives.pop()] = image
-
- if 'sysprepInf' in params:
- infFile = open(params['sysprepInf'], 'rb')
- try:
- params['sysprepInf'] = xmlrpclib.Binary(infFile.read())
- finally:
- infFile.close()
-
- return self.ExecAndExit(self.s.create(params))
+ if args[0] == '-' or args[0].endswith('.json'):
+ params = self._readVmParamsFromJson(args)
+ else:
+ params = self._readVmParamsFromConf(args)
+ if params is not None:
+ return self.ExecAndExit(self.s.create(params))
+ return sys.exit(1)
def vmUpdateDevice(self, args):
params = self._eqSplit(args[1:])
@@ -1884,6 +1824,93 @@
return status['status']['code'], status['status']['message']
+ def _readVmParamsFromJson(self, args):
+ if args[0] == "-":
+ data = sys.stdin.read()
+ else:
+ try:
+ with open(args[0]) as f:
+ data = f.read()
+ except IOError as e:
+ print "failed to read VM config: %s" % str(e)
+ return None
+ try:
+ return json.loads(data)
+ except ValueError as e:
+ print "failed to decode VM config: %s" % str(e)
+ return None
+
+ def _readVmParamsFromConf(self, args):
+ params = {}
+ drives = []
+ devices = []
+ cpuPinning = {}
+ numaTune = {}
+ guestNumaNodes = []
+ confLines = []
+ confFile = open(args[0])
+ for line in confFile.readlines():
+ line = re.sub("\s+", '', line)
+ line = re.sub("\#.*", '', line)
+ if line:
+ confLines.append(line)
+ if len(args) > 1:
+ confLines.extend(args[1:])
+ for line in confLines:
+ if '=' in line:
+ param, value = line.split("=", 1)
+ if param == 'devices':
+ devices.append(self._parseDriveSpec(value))
+ elif param == 'drive':
+ drives.append(self._parseDriveSpec(value))
+ elif param == 'cpuPinning':
+ cpuPinning, rStr = self._parseNestedSpec(value)
+ elif param == 'numaTune':
+ numaTune, rStr = self._parseNestedSpec(value)
+ elif param == 'guestNumaNodes':
+ guestNumaNodes.append(self._parseDriveSpec(value))
+ elif param.startswith('custom_'):
+ if 'custom' not in params:
+ params['custom'] = {}
+ params['custom'][param[7:]] = value
+ else:
+ if param in ('cdrom', 'floppy'):
+ value = self._parseDriveSpec(value)
+ params[param] = value
+ else:
+ params[line.strip()] = ''
+ if cpuPinning:
+ params['cpuPinning'] = cpuPinning
+ if numaTune:
+ params['numaTune'] = numaTune
+ if guestNumaNodes:
+ params['guestNumaNodes'] = guestNumaNodes
+ if drives:
+ params['drives'] = drives
+ if devices:
+ params['devices'] = devices
+ # Backward compatibility for vdsClient users
+ if 'vt' in params:
+ params['kvmEnable'] = params['vt']
+
+ if 'imageFile' in params:
+ params['hda'] = params['imageFile']
+
+ drives = ['hdd', 'hdc', 'hdb']
+ if 'moreImages' in params:
+ for image in params['moreImages'].split(','):
+ params[drives.pop()] = image
+
+ if 'sysprepInf' in params:
+ infFile = open(params['sysprepInf'], 'rb')
+ try:
+ params['sysprepInf'] = xmlrpclib.Binary(infFile.read())
+ finally:
+ infFile.close()
+
+ return params
+
+
if __name__ == '__main__':
if _glusterEnabled:
serv = ge.GlusterService()
--
To view, visit http://gerrit.ovirt.org/35292
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic6a73bc0e5fe87eb1a48c708e7ea316c6d9df7e5
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: utils: Add stopwatch for timing operations
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: utils: Add stopwatch for timing operations
......................................................................
utils: Add stopwatch for timing operations
stopwatch is a context manager that make it easy to time block of code:
with stopwatch("foo.bar"):
foo.bar("baz")
Will log debug message:
foo.bar: 0.123 seconds
The log can be disabled by disabling the vds.stopwatch logger.
Change-Id: Ie0a60538936dbb4596243abe9d731779fd9efb47
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/utils.py
1 file changed, 11 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/85/29685/1
diff --git a/lib/vdsm/utils.py b/lib/vdsm/utils.py
index 2ba5762..1ae5cc7 100644
--- a/lib/vdsm/utils.py
+++ b/lib/vdsm/utils.py
@@ -26,6 +26,7 @@
Contains a reverse dictionary pointing from error string to its error code.
"""
+from contextlib import contextmanager
from collections import namedtuple, deque
from fnmatch import fnmatch
from StringIO import StringIO
@@ -669,6 +670,16 @@
return decorator
+@contextmanager
+def stopwatch(message, log=logging.getLogger('vds.stopwatch')):
+ start = time.time()
+ try:
+ yield
+ finally:
+ elapsed = time.time() - start
+ log.debug("%s: %.3f seconds", message, elapsed)
+
+
def tobool(s):
try:
if s is None:
--
To view, visit http://gerrit.ovirt.org/29685
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie0a60538936dbb4596243abe9d731779fd9efb47
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: virt: dev: implement from_xml for ControllerDevice
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: virt: dev: implement from_xml for ControllerDevice
......................................................................
virt: dev: implement from_xml for ControllerDevice
Change-Id: I4cf7df0495a58c81207e680732fe0e72b8b5b04c
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 27 insertions(+), 20 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/54/33754/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index a6e68ae..05f0a2f 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -709,6 +709,17 @@
return ctrl
+ @classmethod
+ def from_xml(cls, conf, log, dev_xml):
+ alias = dev_xml.getElementsByTagName('alias')[0].getAttribute('name')
+ return cls(
+ conf, log,
+ alias=alias,
+ device=dev_xml.getAttribute('type'),
+ model=dev_xml.getAttribute('model'),
+ index=dev_xml.getAttribute('index'),
+ address=vmxml.device_address(dev_xml))
+
class SoundDevice(vmdevices.Base):
__slots__ = ('address', 'alias')
@@ -4726,41 +4737,37 @@
# Ignore controller devices without address
if not x.getElementsByTagName('address'):
continue
- alias = x.getElementsByTagName('alias')[0].getAttribute('name')
- device = x.getAttribute('type')
- # Get model and index. Relevant for USB controllers.
- model = x.getAttribute('model')
- index = x.getAttribute('index')
- # Get controller address
- address = vmxml.device_address(x)
+ dev = ControllerDevice.from_xml(x)
# In case the controller has index and/or model, they
# are compared. Currently relevant for USB controllers.
for ctrl in self._devices[CONTROLLER_DEVICES]:
- if ((ctrl.device == device) and
- (not hasattr(ctrl, 'index') or ctrl.index == index) and
- (not hasattr(ctrl, 'model') or ctrl.model == model)):
- ctrl.alias = alias
- ctrl.address = address
+ if ((ctrl.device == dev.device) and
+ (not hasattr(ctrl, 'index')
+ or ctrl.index == dev.index) and
+ (not hasattr(ctrl, 'model')
+ or ctrl.model == dev.model)):
+ ctrl.alias = dev.alias
+ ctrl.address = dev.address
# Update vm's conf with address for known controller devices
# In case the controller has index and/or model, they
# are compared. Currently relevant for USB controllers.
knownDev = False
for dev in self.conf['devices']:
if ((dev['type'] == CONTROLLER_DEVICES) and
- (dev['device'] == device) and
- ('index' not in dev or dev['index'] == index) and
- ('model' not in dev or dev['model'] == model)):
- dev['address'] = address
- dev['alias'] = alias
+ (dev['device'] == dev.device) and
+ ('index' not in dev or dev['index'] == dev.index) and
+ ('model' not in dev or dev['model'] == dev.model)):
+ dev['address'] = dev.address
+ dev['alias'] = dev.alias
knownDev = True
# Add unknown controller device to vm's conf
if not knownDev:
self.conf['devices'].append({'type': CONTROLLER_DEVICES,
- 'device': device,
- 'address': address,
- 'alias': alias})
+ 'device': dev.device,
+ 'address': dev.address,
+ 'alias': dev.alias})
def _getUnderlyingBalloonDeviceInfo(self):
"""
--
To view, visit http://gerrit.ovirt.org/33754
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I4cf7df0495a58c81207e680732fe0e72b8b5b04c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months
Change in vdsm[master]: virt: dev: implement from_xml for SmartcardDevice
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: virt: dev: implement from_xml for SmartcardDevice
......................................................................
virt: dev: implement from_xml for SmartcardDevice
Change-Id: I395c49d1cd9af04527840a7d5aaf853d35aa122d
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 5 insertions(+), 6 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/53/33753/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index e340ed0..a6e68ae 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4820,19 +4820,18 @@
if not x.getElementsByTagName('address'):
continue
- address = vmxml.device_address(x)
- alias = x.getElementsByTagName('alias')[0].getAttribute('name')
+ dev = SmartCardDevice.from_xml(x)
for dev in self._devices[SMARTCARD_DEVICES]:
if not hasattr(dev, 'address'):
- dev.address = address
- dev.alias = alias
+ dev.address = dev.address
+ dev.alias = dev.alias
for dev in self.conf['devices']:
if dev['device'] == SMARTCARD_DEVICES and \
not dev.get('address'):
- dev['address'] = address
- dev['alias'] = alias
+ dev['address'] = dev.address
+ dev['alias'] = dev.alias
def _getUnderlyingWatchdogDeviceInfo(self):
"""
--
To view, visit http://gerrit.ovirt.org/33753
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I395c49d1cd9af04527840a7d5aaf853d35aa122d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
8 years, 10 months