Change in vdsm[master]: [WIP] vdsm: add support for PCI passthrough
by mpoledni@redhat.com
Martin Polednik has uploaded a new change for review.
Change subject: [WIP] vdsm: add support for PCI passthrough
......................................................................
[WIP] vdsm: add support for PCI passthrough
required functionality:
* report PCI devices available on host [x]
* handle createVm xml generation [x]
* hotplugHostdev [ ] (required for after-migration)
* hotpunlugHostdev [ ] (required for migration)
Change-Id: I363d2622d72ca2db75f60032fe0892c348bab121
Signed-off-by: Martin Polednik <mpoledni(a)redhat.com>
---
M lib/vdsm/define.py
M vdsm/caps.py
M vdsm/vm.py
3 files changed, 83 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/62/22462/1
diff --git a/lib/vdsm/define.py b/lib/vdsm/define.py
index eb78633..9605f93 100644
--- a/lib/vdsm/define.py
+++ b/lib/vdsm/define.py
@@ -132,6 +132,12 @@
'transientErr': {'status': {
'code': 59,
'message': 'Action not permitted on a VM with transient disks'}},
+ 'hotplugHostdev': {'status': {
+ 'code': 60,
+ 'message': 'Failed to hotplug hostdev'}},
+ 'hotunplugHostdev': {'status': {
+ 'code': 61,
+ 'message': 'Failed to hotunplug hostdev'}},
'recovery': {'status': {
'code': 99,
'message': 'Recovering from crash or Initializing'}},
diff --git a/vdsm/caps.py b/vdsm/caps.py
index 3839134..d6af375 100644
--- a/vdsm/caps.py
+++ b/vdsm/caps.py
@@ -308,6 +308,38 @@
return dict(release=release, version=version, name=osname)
+def hostdevList():
+ devices = []
+ for device in libvirtconnection.get().listAllDevices():
+ devXML = minidom.parseString(device.XMLDesc())
+ dev = {}
+
+ # we have to grab attributes that will most likely not only
+ # uniquely identify device, but also serve as human readable
+ # representation of the device
+ try:
+ dev['name'] = devXML.getElementsByTagName('name')[0].\
+ childNodes[0].data
+ capability = devXML.getElementsByTagName('capability')[0]
+ try:
+ dev['product'] = capability.getElementsByTagName('product')[0]\
+ .childNodes[0].data
+ dev['vendor'] = capability.getElementsByTagName('vendor')[0].\
+ childNodes[0].data
+ except IndexError:
+ # althought the retrieval of product/vendor was not successful,
+ # we can still report back the name
+ pass
+ except IndexError:
+ # should device not have a name, there is nothing engine could send
+ # back that we could use to uniquely identify and initiate a device
+ continue
+
+ devices.append(dev)
+
+ return devices
+
+
def get():
targetArch = platform.machine()
@@ -360,6 +392,7 @@
config.getint('vars', 'extra_mem_reserve'))
caps['guestOverhead'] = config.get('vars', 'guest_ram_overhead')
caps['rngSources'] = _getRngSources()
+ caps['hostDevices'] = hostdevList()
return caps
diff --git a/vdsm/vm.py b/vdsm/vm.py
index a5d923b..a477bc9 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -78,6 +78,7 @@
WATCHDOG_DEVICES = 'watchdog'
CONSOLE_DEVICES = 'console'
SMARTCARD_DEVICES = 'smartcard'
+HOSTDEV_DEVICES = 'hostdev'
def isVdsmImage(drive):
@@ -1656,6 +1657,27 @@
return m
+class HostDevice(VmDevice):
+ def getXML(self):
+ """
+ Create domxml for a hostdev device.
+
+ <devices>
+ <hostdev mode='subsystem' type='usb'>
+ <source startupPolicy='optional'>
+ <vendor id='0x1234'/>
+ <product id='0xbeef'/>
+ </source>
+ <boot order='2'/>
+ </hostdev>
+ </devices>
+ """
+ # libvirt gives us direct api call to construct the XML
+ return xml.dom.minidom.parseString(libvirtconnection.get().
+ nodeDeviceLookupByName(self.name).
+ XMLDesc())
+
+
class WatchdogDevice(VmDevice):
def __init__(self, *args, **kwargs):
super(WatchdogDevice, self).__init__(*args, **kwargs)
@@ -1769,7 +1791,8 @@
(CONSOLE_DEVICES, ConsoleDevice),
(REDIR_DEVICES, RedirDevice),
(RNG_DEVICES, RngDevice),
- (SMARTCARD_DEVICES, SmartCardDevice))
+ (SMARTCARD_DEVICES, SmartCardDevice),
+ (HOSTDEV_DEVICES, HostDevice))
def _makeDeviceDict(self):
return dict((dev, []) for dev, _ in self.DeviceMapping)
@@ -3127,6 +3150,26 @@
break
+ def hotplugHostdev(self, params):
+ hostdev = HostDevice(self.conf, self.log, **params)
+ self._devices[HOSTDEV_DEVICES].append(hostdev)
+ hostdevXML = hostdev.getXML().toprettyxml(encoding='utf-8')
+ hostdev._deviceXML = hostdevXML
+ self.log.debug("Hotplug hostdev xml: %s", hostdevXML)
+
+ try:
+ self._dom.attachDevice(hostdevXML)
+ except libvirt.libvirtError as e:
+ self.log.error("Hotplug failed", exc_info=True)
+ if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
+ return errCode['noVM']
+ return {'status': {'code':
+ errCode['hotplugHostdev']['status']['code'],
+ 'message': e.message}}
+
+ def hotunplugHostdev(self, name):
+ pass
+
def hotplugNic(self, params):
if self.isMigrating():
return errCode['migInProgress']
--
To view, visit http://gerrit.ovirt.org/22462
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I363d2622d72ca2db75f60032fe0892c348bab121
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Martin Polednik <mpoledni(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: netinfo: improve which ipv4 addr is reported if there are mu...
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: netinfo: improve which ipv4 addr is reported if there are multiple primary
......................................................................
netinfo: improve which ipv4 addr is reported if there are multiple primary
The current code assumed that additional configured addresses for a
device would have the 'secondary' flag. However, this is no longer
true in recent kernels, as multiple primary addresses can be set for
a device.
The improvement is that now we will check if any of the addresses is
in the subnet of the gateway and report one of them. If there is no
default gw in the main table for the device we return the last
set primary ip and if there is a default gw but going through another
hop, we return the first set ip.
Change-Id: I8666cfef5bd8ea63edf8979e501d4785db5f4893
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M lib/vdsm/netinfo.py
1 file changed, 35 insertions(+), 7 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/75/33375/1
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index 6491505..816810d 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -292,25 +292,49 @@
struct.pack("!I", int('1' * prefix + '0' * (32 - prefix), 2)))
+def prefix2int(prefix):
+ if not 0 <= prefix <= 32:
+ raise ValueError('%s is not a valid prefix value. It must be between '
+ '0 and 32')
+ return (2 ** prefix - 1) << (32 - prefix)
+
+
+def addr2int(address):
+ return struct.unpack('!I', socket.inet_aton(address))[0]
+
+
def getDefaultGateway():
output = routeShowGateways('main')
return Route.fromText(output[0]) if output else None
-def getIpInfo(dev, ipaddrs=None):
+def getIpInfo(dev, ipaddrs=None, ipv4_gateway=None):
if ipaddrs is None:
ipaddrs = _getIpAddrs()
ipv4addr = ipv4netmask = ''
ipv4addrs = []
ipv6addrs = []
+ gateway_int = addr2int(ipv4_gateway) if ipv4_gateway else None
+
for addr in ipaddrs[dev]:
if addr['family'] == 'inet':
ipv4addrs.append(addr['address'])
if 'secondary' not in addr['flags']:
- ipv4addr, prefix = addr['address'].split('/')
- ipv4netmask = prefix2netmask(addr['prefixlen'])
+ address, _ = addr['address'].split('/')
+ mask = prefix2int(addr['prefixlen'])
+ if (gateway_int is None or
+ addr2int(address) & mask == gateway_int & mask):
+ ipv4addr = address
+ ipv4netmask = prefix2netmask(addr['prefixlen'])
else:
ipv6addrs.append(addr['address'])
+ if ipv4addrs and ipv4addr == '':
+ # If we didn't find an address in the gateway subnet (which is
+ # legal if there is another route that takes us to the gateway) we
+ # choose to report the first address
+ ipv4addr, prefix = ipv4addrs[0].split('/')
+ ipv4netmask = prefix2netmask(int(prefix))
+
return ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs
@@ -501,14 +525,16 @@
# comment when the version is no longer supported.
data['interface'] = iface
- ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(iface, ipaddrs)
+ gateway = _get_gateway(routes, iface)
+ ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(
+ iface, ipaddrs, gateway)
data.update({'iface': iface, 'bridged': bridged,
'addr': ipv4addr, 'netmask': ipv4netmask,
'bootproto4': ('dhcp' if ipv4addr and iface in dhcp4
else 'none'),
'ipv4addrs': ipv4addrs,
'ipv6addrs': ipv6addrs,
- 'gateway': _get_gateway(routes, iface),
+ 'gateway': gateway,
'ipv6gateway': _get_gateway(routes, iface, family=6),
'mtu': str(getMtu(iface))})
except (IOError, OSError) as e:
@@ -549,12 +575,14 @@
def _devinfo(link, routes, ipaddrs, dhcp4):
- ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(link.name, ipaddrs)
+ gateway = _get_gateway(routes, link.name)
+ ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(
+ link.name, ipaddrs, gateway)
info = {'addr': ipv4addr,
'cfg': getIfaceCfg(link.name),
'ipv4addrs': ipv4addrs,
'ipv6addrs': ipv6addrs,
- 'gateway': _get_gateway(routes, link.name),
+ 'gateway': gateway,
'ipv6gateway': _get_gateway(routes, link.name, family=6),
'bootproto4': ('dhcp' if ipv4addr and link.name in dhcp4
else 'none'),
--
To view, visit http://gerrit.ovirt.org/33375
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8666cfef5bd8ea63edf8979e501d4785db5f4893
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: tests: add tests for disk hotplug/hotunplug
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: tests: add tests for disk hotplug/hotunplug
......................................................................
tests: add tests for disk hotplug/hotunplug
Add tests for negative flows.
Negative flows are tested less often because
of the need to cause or inject faults.
Moreover, we want this test to help verify the upcoming
switch to response.error().
Change-Id: Idd8b467d49c183c81f6a11494d38984246f5b527
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M tests/vmTests.py
1 file changed, 74 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/53/39053/1
diff --git a/tests/vmTests.py b/tests/vmTests.py
index ab26135..9ca6655 100644
--- a/tests/vmTests.py
+++ b/tests/vmTests.py
@@ -53,6 +53,7 @@
from vmTestsData import CONF_TO_DOMXML_PPC64
from vmTestsData import CONF_TO_DOMXML_NO_VDSM
import vmfakelib as fake
+from vmStorageTests import drive_config
from testValidation import slowtest
@@ -1417,6 +1418,7 @@
self.assertEqual(NAME, testvm.getStats()['vmName'])
+@expandPermutations
class ChangeBlockDevTests(TestCaseBase):
def test_change_cd_failure(self):
@@ -1431,12 +1433,82 @@
virtError=libvirt.VIR_ERR_GET_FAILED)
res = fakevm.changeCD({})
+ self.assertEqual(res, response.error('changeDisk'))
- expected_status = define.errCode['changeDisk']['status']
- self.assertEqual(res['status'], expected_status)
+ # TODO: need a way to pass message through fake.Domain failIfRequested
+ @permutations([[libvirt.VIR_ERR_OPERATION_DENIED, 'hotplugDisk', ''],
+ [libvirt.VIR_ERR_NO_DOMAIN, 'noVM', '']])
+ def test_hotplug_disk_failure(self, virtError, vdsmError, customMessage):
+ # caveat emptor: in this test we DON't
+ # overwrite the message, thus will be the default one; but for
+ # errors != 'noVM', it can change.
+ PATH = '/this/path/does/not/exists'
+
+ def _fail(*args):
+ # no specific meaning, actually any error != None is good
+ raise_libvirt_error(libvirt.VIR_ERR_ACCESS_DENIED,
+ 'Failed to hotplug disk')
+
+ dom = fake.Domain()
+ dom.updateDeviceFlags = _fail
+ dom.attachDevice = _fail
+
+ cif = fake.ClientIF()
+
+ with MonkeyPatchScope([(cif, 'prepareVolumePath',
+ lambda _: PATH),
+ (cif, 'teardownVolumePath',
+ lambda _: None),
+ (hooks, 'before_disk_hotplug',
+ _fake_disk_hook),
+ (utils, 'isBlockDevice',
+ lambda path: True)]):
+ with fake.VM(devices=[drive_config()],
+ cif=cif) as fakevm:
+ fakevm._dom = dom
+
+ res = fakevm.hotplugDisk({
+ 'drive': drive_config(
+ path=PATH,
+ serial='65-a561-23e5b495b9bc')})
+
+ self.assertEqual(res,
+ response.error('hotplugDisk', customMessage))
+
+ def test_hotunplug_inexistent_disk(self):
+ PATH = '/this/path/does/not/exists'
+
+ def _fail(*args):
+ raise_libvirt_error(libvirt.VIR_ERR_ACCESS_DENIED, '')
+
+ dom = fake.Domain()
+ dom.updateDeviceFlags = _fail
+
+ cif = fake.ClientIF()
+ with MonkeyPatchScope([(cif, 'prepareVolumePath',
+ lambda _: PATH),
+ (cif, 'teardownVolumePath',
+ lambda _: None),
+ (hooks, 'before_disk_hotunplug',
+ _fake_disk_hook),
+ (utils, 'isBlockDevice',
+ lambda path: True)]):
+ with fake.VM(cif=cif) as fakevm:
+ # no specific meaning, actually any error != None is good
+ fakevm._dom = dom
+
+ res = fakevm.hotunplugDisk({})
+
+ self.assertEqual(res,
+ response.error('hotunplugDisk',
+ 'Disk not found'))
def raise_libvirt_error(code, message):
err = libvirt.libvirtError(defmsg=message)
err.err = [code]
raise err
+
+
+def _fake_disk_hook(driveXml, conf, params):
+ return driveXml
--
To view, visit https://gerrit.ovirt.org/39053
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idd8b467d49c183c81f6a11494d38984246f5b527
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: make acpiShutdown more robust
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: make acpiShutdown more robust
......................................................................
vm: make acpiShutdown more robust
In the Vm shutdown flow, the actual 'destruction'
of the domain -in libvirt jargon- may already happen
asynchonously, e.g. if QEMU dies suddenly.
Moreover, we want to make it asynchronously even on
our own code for performance reasons.
This means that the Vm._dom attribute may become None
asyncrhonously, even inside the Vm powerdown flow
itself.
This patch address the case for the acpiShutdown,
fixing this issue:
Thread-259072::ERROR::2014-10-15 12:06:52,842::utils::1193::utils.Callback::(__call__) acpiCallback failed
Traceback (most recent call last):
File "/usr/lib64/python2.6/site-packages/vdsm/utils.py", line 1191, in __call__
result = self.func(*self.args, **self.kwargs)
File "/usr/share/vdsm/virt/vmpowerdown.py", line 91, in acpiCallback
self.vm.acpiShutdown()
File "/usr/share/vdsm/virt/vm.py", line 4942, in acpiShutdown
self._dom.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN)
AttributeError: 'NoneType' object has no attribute 'shutdownFlags'
Change-Id: I244f00d62ee24fb42ba3d654961a8fc22f4a6c25
Related-To: https://bugzilla.redhat.com/show_bug.cgi?id=1154389
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 7 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/79/34879/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 9740ab3..2384aca 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4402,7 +4402,13 @@
def acpiShutdown(self):
self._shutdownReason = vmexitreason.ADMIN_SHUTDOWN
- self._dom.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN)
+ try:
+ self._dom.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN)
+ except AttributeError:
+ if not self._released:
+ raise
+ # else the VM was already shut off asynchronously,
+ # so ignore error and quickly exit
def setBalloonTarget(self, target):
--
To view, visit http://gerrit.ovirt.org/34879
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I244f00d62ee24fb42ba3d654961a8fc22f4a6c25
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]: Add feature to create dispersed volume
by tjeyasin@redhat.com
Timothy Asir has uploaded a new change for review.
Change subject: Add feature to create dispersed volume
......................................................................
Add feature to create dispersed volume
Added disperse count and redundancy count params into
create volume function which provides options to create
a dispersed volume.
Change-Id: I50f6dbae8d179c09480634c64d7d439ae82d72a2
Signed-off-by: Timothy Asir <tjeyasin(a)redhat.com>
---
M client/vdsClientGluster.py
M vdsm/gluster/api.py
M vdsm/gluster/apiwrapper.py
M vdsm/gluster/cli.py
M vdsm/rpc/vdsmapi-gluster-schema.json
5 files changed, 28 insertions(+), 12 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/74/37474/1
diff --git a/client/vdsClientGluster.py b/client/vdsClientGluster.py
index a5065f3..1139222 100644
--- a/client/vdsClientGluster.py
+++ b/client/vdsClientGluster.py
@@ -32,6 +32,8 @@
params = self._eqSplit(args)
brickList = params.get('bricks', '').split(',')
volumeName = params.get('volumeName', '')
+ disperseCount = params.get('disperse', '')
+ redundancyCount = params.get('redundancy', '')
replicaCount = params.get('replica', '')
stripeCount = params.get('stripe', '')
transport = params.get('transport', '')
@@ -39,6 +41,7 @@
force = (params.get('force', 'no').upper() == 'YES')
status = self.s.glusterVolumeCreate(volumeName, brickList,
+ disperseCount, redundancyCount,
replicaCount, stripeCount,
transportList, force)
pp.pprint(status)
@@ -522,6 +525,7 @@
{'glusterVolumeCreate': (
serv.do_glusterVolumeCreate,
('volumeName=<volume_name> bricks=<brick[,brick, ...]> '
+ '[disperse=<count>] [redundancy=<count>] '
'[replica=<count>] [stripe=<count>] [transport={tcp|rdma}] '
'[force={yes|no}]\n\t'
'<volume_name> is name of new volume',
diff --git a/vdsm/gluster/api.py b/vdsm/gluster/api.py
index 04e0f33..33f1724 100644
--- a/vdsm/gluster/api.py
+++ b/vdsm/gluster/api.py
@@ -79,10 +79,12 @@
remoteServer)}
@exportAsVerb
- def volumeCreate(self, volumeName, brickList, replicaCount=0,
+ def volumeCreate(self, volumeName, brickList, disperseCount=0,
+ redundancyCount=0, replicaCount=0,
stripeCount=0, transportList=[],
force=False, options=None):
return self.svdsmProxy.glusterVolumeCreate(volumeName, brickList,
+ disperseCount, redundancyCount,
replicaCount, stripeCount,
transportList, force)
diff --git a/vdsm/gluster/apiwrapper.py b/vdsm/gluster/apiwrapper.py
index d42f8ba..4f0689b 100644
--- a/vdsm/gluster/apiwrapper.py
+++ b/vdsm/gluster/apiwrapper.py
@@ -111,9 +111,10 @@
def list(self, volumeName=None, remoteServer=None):
return self._gluster.volumesList(volumeName, remoteServer)
- def create(self, volumeName, brickList, replicaCount=0, stripeCount=0,
- transportList=[], force=False):
- return self._gluster.volumeCreate(volumeName, brickList, replicaCount,
+ def create(self, volumeName, brickList, disperseCount=0, redundancyCount=0,
+ replicaCount=0, stripeCount=0, transportList=[], force=False):
+ return self._gluster.volumeCreate(volumeName, brickList, disperseCount,
+ redundancyCount, replicaCount,
stripeCount, transportList, force)
def start(self, volumeName, force=False):
diff --git a/vdsm/gluster/cli.py b/vdsm/gluster/cli.py
index d9ecd66..d161801 100644
--- a/vdsm/gluster/cli.py
+++ b/vdsm/gluster/cli.py
@@ -475,9 +475,13 @@
@makePublic
-def volumeCreate(volumeName, brickList, replicaCount=0, stripeCount=0,
- transportList=[], force=False):
+def volumeCreate(volumeName, brickList, disperseCount=0, redundancyCount=0,
+ replicaCount=0, stripeCount=0, transportList=[], force=False):
command = _getGlusterVolCmd() + ["create", volumeName]
+ if disperseCount:
+ command += ["disperse", "%s" % disperseCount]
+ if redundancyCount:
+ command += ["redundancy", "%s" % redundancyCount]
if stripeCount:
command += ["stripe", "%s" % stripeCount]
if replicaCount:
diff --git a/vdsm/rpc/vdsmapi-gluster-schema.json b/vdsm/rpc/vdsmapi-gluster-schema.json
index 5924fd9..bba7126 100644
--- a/vdsm/rpc/vdsmapi-gluster-schema.json
+++ b/vdsm/rpc/vdsmapi-gluster-schema.json
@@ -660,17 +660,21 @@
#
# Create a Gluster volume
#
-# @volumeName: Gluster volume name
+# @volumeName: Gluster volume name
#
-# @bricklist: List of bricks
+# @bricklist: List of bricks
#
-# @replicaCount: #optional Replica count for volume
+# @disperseCount: #optional Disperse count for volume
#
-# @stripeCount: #optional Stripe count for volume
+# @redundancyCount: #optional Redundancy count for volume
#
-# @transportList: #optional Transport type
+# @replicaCount: #optional Replica count for volume
#
-# @force: #optional Force create Volume (new in version 4.14.0)
+# @stripeCount: #optional Stripe count for volume
+#
+# @transportList: #optional Transport type
+#
+# @force: #optional Force create Volume (new in version 4.14.0)
#
# Returns:
# uuid of the volume
@@ -679,6 +683,7 @@
##
{'command': {'class': 'GlusterVolume', 'name': 'create'},
'data': {'volumeName': 'str', 'bricklist': ['str'],
+ '*disperseCount': 'int', '*redundancyCount': 'int',
'*replicaCount': 'int', '*stripeCount': 'int',
'*transportList': ['transType'], '*force': 'bool'},
'returns': 'UUID'}
--
To view, visit http://gerrit.ovirt.org/37474
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I50f6dbae8d179c09480634c64d7d439ae82d72a2
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Timothy Asir <tjeyasin(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: WIP: make _getInterfaceStats a function
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: WIP: make _getInterfaceStats a function
......................................................................
WIP: make _getInterfaceStats a function
Change-Id: I0b5796f3463585794d2696ce73f8357cb0fd1f78
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/sampling.py
1 file changed, 56 insertions(+), 72 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/30/40430/1
diff --git a/vdsm/virt/sampling.py b/vdsm/virt/sampling.py
index f61514b..45afdfd 100644
--- a/vdsm/virt/sampling.py
+++ b/vdsm/virt/sampling.py
@@ -622,10 +622,10 @@
if len(self._samples) < 2:
return stats
- stats.update(self._getInterfacesStats())
-
- hs0, hs1 = self._samples[0], self._samples[-1]
+ hs0, hs1, _ = self._samples.stats()
interval = hs1.timestamp - hs0.timestamp
+
+ stats.update(self._get_interfaces_stats(hs0, hs1, interval))
jiffies = (hs1.pidcpu.user - hs0.pidcpu.user) % (2 ** 32)
stats['cpuUserVdsmd'] = jiffies / interval
@@ -652,75 +652,6 @@
stats['cpuStatistics'] = _get_cpu_core_stats(hs0, hs1)
stats['v2vJobs'] = v2v.get_jobs_status()
- return stats
-
- def _getInterfacesStats(self):
- """
- Compile and return a dict containing the stats.
-
- :returns: a dict that with the following keys:
-
- * cpuUser
- * cpuSys
- * cpuIdle
- * rxRate
- * txRate
- """
- stats = {}
- if len(self._samples) < 2:
- return stats
- hs0, hs1 = self._samples[0], self._samples[-1]
- interval = hs1.timestamp - hs0.timestamp
-
- rx = tx = rxDropped = txDropped = 0
- stats['network'] = {}
- total_rate = 0
- for ifid in hs1.interfaces:
- # it skips hot-plugged devices if we haven't enough information
- # to count stats from it
- if ifid not in hs0.interfaces:
- continue
- ifrate = hs1.interfaces[ifid].speed or 1000
- Mbps2Bps = (10 ** 6) / 8
- thisRx = (hs1.interfaces[ifid].rx - hs0.interfaces[ifid].rx) % \
- (2 ** 32)
- thisTx = (hs1.interfaces[ifid].tx - hs0.interfaces[ifid].tx) % \
- (2 ** 32)
- rxRate = 100.0 * thisRx / interval / ifrate / Mbps2Bps
- txRate = 100.0 * thisTx / interval / ifrate / Mbps2Bps
- if txRate > 100 or rxRate > 100:
- txRate = min(txRate, 100.0)
- rxRate = min(rxRate, 100.0)
- self._log.debug('Rate above 100%%.')
- iface = hs1.interfaces[ifid]
- stats['network'][ifid] = {'name': ifid, 'speed': str(ifrate),
- 'rxDropped': str(iface.rxDropped),
- 'txDropped': str(iface.txDropped),
- 'rxErrors': str(iface.rxErrors),
- 'txErrors': str(iface.txErrors),
- 'state': iface.operstate,
- 'rxRate': '%.1f' % rxRate,
- 'txRate': '%.1f' % txRate,
- 'rx': str(iface.rx),
- 'tx': str(iface.tx),
- 'sampleTime': hs1.timestamp,
- }
- rx += thisRx
- tx += thisTx
- rxDropped += hs1.interfaces[ifid].rxDropped
- txDropped += hs1.interfaces[ifid].txDropped
- total_rate += ifrate
-
- total_bytes_per_sec = (total_rate or 1000) * (10 ** 6) / 8
- stats['rxRate'] = 100.0 * rx / interval / total_bytes_per_sec
- stats['txRate'] = 100.0 * tx / interval / total_bytes_per_sec
- if stats['txRate'] > 100 or stats['rxRate'] > 100:
- stats['txRate'] = min(stats['txRate'], 100.0)
- stats['rxRate'] = min(stats['rxRate'], 100.0)
- logging.debug(stats)
- stats['rxDropped'] = rxDropped
- stats['txDropped'] = txDropped
-
return stats
@@ -754,6 +685,59 @@
return cpuCoreStats
+def _get_interfaces_stats(self, hs0, hs1, interval):
+ rx = tx = rxDropped = txDropped = 0
+ stats['network'] = {}
+ total_rate = 0
+ for ifid in hs1.interfaces:
+ # it skips hot-plugged devices if we haven't enough information
+ # to count stats from it
+ if ifid not in hs0.interfaces:
+ continue
+ ifrate = hs1.interfaces[ifid].speed or 1000
+ Mbps2Bps = (10 ** 6) / 8
+ thisRx = (hs1.interfaces[ifid].rx - hs0.interfaces[ifid].rx) % \
+ (2 ** 32)
+ thisTx = (hs1.interfaces[ifid].tx - hs0.interfaces[ifid].tx) % \
+ (2 ** 32)
+ rxRate = 100.0 * thisRx / interval / ifrate / Mbps2Bps
+ txRate = 100.0 * thisTx / interval / ifrate / Mbps2Bps
+ if txRate > 100 or rxRate > 100:
+ txRate = min(txRate, 100.0)
+ rxRate = min(rxRate, 100.0)
+ logging.debug('Rate above 100%%.')
+ iface = hs1.interfaces[ifid]
+ stats['network'][ifid] = {'name': ifid, 'speed': str(ifrate),
+ 'rxDropped': str(iface.rxDropped),
+ 'txDropped': str(iface.txDropped),
+ 'rxErrors': str(iface.rxErrors),
+ 'txErrors': str(iface.txErrors),
+ 'state': iface.operstate,
+ 'rxRate': '%.1f' % rxRate,
+ 'txRate': '%.1f' % txRate,
+ 'rx': str(iface.rx),
+ 'tx': str(iface.tx),
+ 'sampleTime': hs1.timestamp,
+ }
+ rx += thisRx
+ tx += thisTx
+ rxDropped += hs1.interfaces[ifid].rxDropped
+ txDropped += hs1.interfaces[ifid].txDropped
+ total_rate += ifrate
+
+ total_bytes_per_sec = (total_rate or 1000) * (10 ** 6) / 8
+ stats['rxRate'] = 100.0 * rx / interval / total_bytes_per_sec
+ stats['txRate'] = 100.0 * tx / interval / total_bytes_per_sec
+ if stats['txRate'] > 100 or stats['rxRate'] > 100:
+ stats['txRate'] = min(stats['txRate'], 100.0)
+ stats['rxRate'] = min(stats['rxRate'], 100.0)
+ logging.debug(stats)
+ stats['rxDropped'] = rxDropped
+ stats['txDropped'] = txDropped
+
+ return stats
+
+
def _getLinkSpeed(dev):
if dev.isNIC():
speed = netinfo.nicSpeed(dev.name)
--
To view, visit https://gerrit.ovirt.org/40430
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0b5796f3463585794d2696ce73f8357cb0fd1f78
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]: WIP: sampling: make _getCpuCoresStats a function
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: WIP: sampling: make _getCpuCoresStats a function
......................................................................
WIP: sampling: make _getCpuCoresStats a function
Change-Id: If602a84096db7aa7d1a6672b84d62287e08b0ac2
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/sampling.py
1 file changed, 31 insertions(+), 31 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/29/40429/1
diff --git a/vdsm/virt/sampling.py b/vdsm/virt/sampling.py
index cbe53ef..f61514b 100644
--- a/vdsm/virt/sampling.py
+++ b/vdsm/virt/sampling.py
@@ -649,40 +649,10 @@
stats['bootTime'] = self._boot_time()
stats['numaNodeMemFree'] = hs1.numaNodeMem.nodesMemSample
- stats['cpuStatistics'] = self._getCpuCoresStats()
+ stats['cpuStatistics'] = _get_cpu_core_stats(hs0, hs1)
stats['v2vJobs'] = v2v.get_jobs_status()
return stats
-
- def _getCpuCoresStats(self):
- """
- :returns: a dict that with the following formats:
-
- {'<cpuId>': {'numaNodeIndex': int, 'cpuSys': 'str',
- 'cpuIdle': 'str', 'cpuUser': 'str'}, ...}
- """
- cpuCoreStats = {}
- for nodeIndex, numaNode in caps.getNumaTopology().iteritems():
- cpuCores = numaNode['cpus']
- for cpuCore in cpuCores:
- coreStat = {}
- coreStat['nodeIndex'] = int(nodeIndex)
- hs0, hs1 = self._samples[0], self._samples[-1]
- interval = hs1.timestamp - hs0.timestamp
- jiffies = (hs1.cpuCores.getCoreSample(cpuCore)['user'] -
- hs0.cpuCores.getCoreSample(cpuCore)['user']) % \
- (2 ** 32)
- coreStat['cpuUser'] = ("%.2f" % (jiffies / interval))
- jiffies = (hs1.cpuCores.getCoreSample(cpuCore)['sys'] -
- hs0.cpuCores.getCoreSample(cpuCore)['sys']) % \
- (2 ** 32)
- coreStat['cpuSys'] = ("%.2f" % (jiffies / interval))
- coreStat['cpuIdle'] = ("%.2f" %
- max(0.0, 100.0 -
- float(coreStat['cpuUser']) -
- float(coreStat['cpuSys'])))
- cpuCoreStats[str(cpuCore)] = coreStat
- return cpuCoreStats
def _getInterfacesStats(self):
"""
@@ -754,6 +724,36 @@
return stats
+def _get_cpu_core_stats(hs0, hs1):
+ """
+ :returns: a dict that with the following formats:
+
+ {'<cpuId>': {'numaNodeIndex': int, 'cpuSys': 'str',
+ 'cpuIdle': 'str', 'cpuUser': 'str'}, ...}
+ """
+ cpuCoreStats = {}
+ for nodeIndex, numaNode in caps.getNumaTopology().iteritems():
+ cpuCores = numaNode['cpus']
+ for cpuCore in cpuCores:
+ coreStat = {}
+ coreStat['nodeIndex'] = int(nodeIndex)
+ interval = hs1.timestamp - hs0.timestamp
+ jiffies = (hs1.cpuCores.getCoreSample(cpuCore)['user'] -
+ hs0.cpuCores.getCoreSample(cpuCore)['user']) % \
+ (2 ** 32)
+ coreStat['cpuUser'] = ("%.2f" % (jiffies / interval))
+ jiffies = (hs1.cpuCores.getCoreSample(cpuCore)['sys'] -
+ hs0.cpuCores.getCoreSample(cpuCore)['sys']) % \
+ (2 ** 32)
+ coreStat['cpuSys'] = ("%.2f" % (jiffies / interval))
+ coreStat['cpuIdle'] = ("%.2f" %
+ max(0.0, 100.0 -
+ float(coreStat['cpuUser']) -
+ float(coreStat['cpuSys'])))
+ cpuCoreStats[str(cpuCore)] = coreStat
+ return cpuCoreStats
+
+
def _getLinkSpeed(dev):
if dev.isNIC():
speed = netinfo.nicSpeed(dev.name)
--
To view, visit https://gerrit.ovirt.org/40429
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If602a84096db7aa7d1a6672b84d62287e08b0ac2
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]: json-rpc: export setLogLevel API
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: json-rpc: export setLogLevel API
......................................................................
json-rpc: export setLogLevel API
This API was already available over XMl-RPC.
There is no reason to leave JSON-RPC behind.
Change-Id: I7481a59fb5f0598a671118394e368eab79a381b5
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/rpc/Bridge.py
1 file changed, 1 insertion(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/38424/1
diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py
index 1d44b90..62773df 100644
--- a/vdsm/rpc/Bridge.py
+++ b/vdsm/rpc/Bridge.py
@@ -415,6 +415,7 @@
'Host_getVMList': {'call': Host_getVMList_Call, 'ret': 'vmList'},
'Host_getVMFullList': {'call': Host_getVMFullList_Call, 'ret': 'vmList'},
'Host_getAllVmStats': {'ret': 'statsList'},
+ 'Host_setLogLevel': {},
'Host_setupNetworks': {'ret': 'status'},
'Image_cloneStructure': {'ret': 'uuid'},
'Image_delete': {'ret': 'uuid'},
--
To view, visit https://gerrit.ovirt.org/38424
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7481a59fb5f0598a671118394e368eab79a381b5
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]: netinfo: Replace misused asserts with InvalidConfiguration
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: netinfo: Replace misused asserts with InvalidConfiguration
......................................................................
netinfo: Replace misused asserts with InvalidConfiguration
The code was assuming that asserts are always available, and if running
with in optimized mode, the code would skip the assert and use invalid
configuration, possibly corrupting application state or failing with
unrelated errors, hiding the root cause of the error.
The asserts are replaced now with new InvalidConfiguration exception and
the error messages are improved.
Change-Id: I99ee49aa7e2364f57112e2452e3eab3940b6b00a
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/netinfo.py
1 file changed, 17 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/61/34361/1
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index d818249..e848abc 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -84,6 +84,10 @@
DUMMY_BRIDGE # Appease flake8 since dummy bridge should be exported from here
+class InvalidConfiguration(Exception):
+ """ Raise when getting an invalid conifguration """
+
+
def _visible_devs(predicate):
"""Returns a list of visible (vdsm manageable) links for which the
predicate is True"""
@@ -834,8 +838,9 @@
bondings = [b for (b, attrs) in self.bondings.iteritems() if
nic in attrs['slaves']]
if bondings:
- assert len(bondings) == 1, \
- "Unexpected configuration: More than one bonding per nic"
+ if len(bondings) != 1:
+ raise InvalidConfiguration(
+ "Unexpected configuration: More than one bonding per nic")
return bondings[0]
return None
@@ -853,13 +858,20 @@
for port in ports:
if port in self.vlans:
- assert vlan is None
+ if vlan is not None:
+ raise InvalidConfiguration(
+ "Unexpected vlan: %s exepected: None" % (vlan,))
nic = getVlanDevice(port)
vlan = getVlanID(port)
- assert self.vlans[port]['iface'] == nic
+ if self.vlans[port]['iface'] != nic:
+ raise InvalidConfiguration(
+ "Unexpected iface: %s expected: %s" %
+ (self.vlans[port]['iface'], nic))
port = nic
if port in self.bondings:
- assert bonding is None
+ if bonding is not None:
+ raise InvalidConfiguration(
+ "Unexpected bonding: %s expected: None" % bonding)
bonding = port
lnics += self.bondings[bonding]['slaves']
elif port in self.nics:
--
To view, visit http://gerrit.ovirt.org/34361
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I99ee49aa7e2364f57112e2452e3eab3940b6b00a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
8 years, 9 months
Change in vdsm[master]: ipwrapper: Use zombiereaper to wait for process
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: ipwrapper: Use zombiereaper to wait for process
......................................................................
ipwrapper: Use zombiereaper to wait for process
Commit aea8aab95f eliminated ip process zombies by waiting for ip
process. This is may introduce unlimited wait if the process is not
responsive. We can avoid this issue by using zombiereaper.
Note that zombiereaper requires explicit initialization (registering
signal handler for SIGCHLD), so this make ipwrapper less useful as
generic utility.
Change-Id: I26263c5b4811d7f46f7c65d1d1b00bd96af02eb8
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/ipwrapper.py
1 file changed, 2 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/16/32216/1
diff --git a/lib/vdsm/ipwrapper.py b/lib/vdsm/ipwrapper.py
index af31159..781e95b 100644
--- a/lib/vdsm/ipwrapper.py
+++ b/lib/vdsm/ipwrapper.py
@@ -27,6 +27,7 @@
import signal
import socket
import struct
+import zombiereaper
from netaddr.core import AddrFormatError
from netaddr import IPAddress
@@ -638,7 +639,7 @@
def stop(self):
self.proc.kill()
- self.proc.wait()
+ zombiereaper.autoReapPID(self.proc.pid)
@classmethod
def _parseLine(cls, line):
--
To view, visit http://gerrit.ovirt.org/32216
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I26263c5b4811d7f46f7c65d1d1b00bd96af02eb8
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
8 years, 9 months