Change in vdsm[master]: monitor: Add udev monitor
by rmohr@redhat.com
Roman Mohr has uploaded a new change for review.
Change subject: monitor: Add udev monitor
......................................................................
monitor: Add udev monitor
Allow easy monitoring of device hotplug and device state changes which
are covered by udev.
Change-Id: I4b91753424d83896fa538eb6b57f8653b6332fbb
Signed-off-by: Roman Mohr <rmohr(a)redhat.com>
---
A lib/vdsm/udev/monitor.py
M tests/Makefile.am
A tests/udevMonitorTests.py
M vdsm.spec.in
4 files changed, 272 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/29/47729/1
diff --git a/lib/vdsm/udev/monitor.py b/lib/vdsm/udev/monitor.py
new file mode 100644
index 0000000..8698bf3
--- /dev/null
+++ b/lib/vdsm/udev/monitor.py
@@ -0,0 +1,133 @@
+# Copyright 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from functools import partial
+import logging
+import threading
+from time import sleep
+
+from pyudev import Context, Monitor, MonitorObserver
+
+
+class UdevMonitor(object):
+
+ """
+ ``udev`` event monitor. Usage:
+
+ The monitor is a thread-save thin wrapper arount pyudev.MonitorObserver.
+ This allows multiple callbacks for the same netlink socket. To avoid
+ listening for udev events the application is not interested in, the
+ monitoring thread only starts listening on the socket when the monitor is
+ started and at least one subscriber is added.
+
+ The simplest way to use the monitor is to subscribe a callback to a
+ specific subsystem event and let the callback do the work:
+
+ dev listen_for_disabled_cpu_events(device):
+ if device.action == 'offline':
+ print('CPU {0.name} is now offline'.format(device))
+
+ monitor = UdevMonitor()
+ monitor.start()
+ monitor.subscribe(listen_for_disabled_cpu_events, subsystem='cpu')
+
+ Another approach would be to just enqueue the udev event in a queue and do
+ the actual work in another thread or a thread pool. This is one approach to
+ do this:
+
+ queue = Queue.Queue()
+ def new_device_listener(device):
+ if device.action == 'add':
+ queue.put(device)
+
+ monitor = UdevMonitor()
+ monitor.subscribe(new_device_listener, subsystem='usb',
+ device_type='usb_device')
+ monitor.start()
+ """
+
+ def __init__(self):
+ self._subsystems = {}
+ self._context = Context()
+ self._monitor = Monitor.from_netlink(self._context)
+ self._observer = MonitorObserver(self._monitor, callback=partial(
+ UdevMonitor._event_loop, self), name='udev-monitor')
+ self._filter_lock = threading.Lock()
+ self._is_started = False
+ self._can_start = False
+
+ def _event_loop(self, device):
+ subsystem = self._subsystems[device.subsystem]
+ for callback in subsystem.get(device.device_type, []):
+ _execute_callback(callback, device)
+ if device.device_type:
+ for callback in subsystem.get(None, []):
+ _execute_callback(callback, device)
+
+ def subscribe(self, callback, subsystem, device_type=None):
+ """
+ Raise :exc:`~exceptions.ValueError` if the callback is None
+
+ :param callback: function to invoke
+ :param subsystem: byte or unicode string representing the subsystem to
+ listen on (e.g. ``'cpu'``, ``'usb'``)
+ :param device_type: byte or unicode string representing the device type
+ to listen for changes (e.g. ``'usb_device'``,
+ ``'block'``)
+ :return: None
+ """
+ if callback is None:
+ raise ValueError('callback missing')
+ with self._filter_lock:
+ self._monitor.filter_by(subsystem, device_type)
+ device_types = self._subsystems.get(subsystem, {})
+ callbacks = device_types.get(device_type, [])
+ callbacks.append(callback)
+ device_types[device_type] = callbacks
+ self._subsystems[subsystem] = device_types
+ self._start_if_necessary()
+
+ def start(self):
+ self._can_start = True
+ with self._filter_lock:
+ if self._subsystems:
+ self._start_if_necessary()
+
+ def _start_if_necessary(self):
+ if self._can_start and not self._is_started:
+ self._observer.start()
+ self._is_started = True
+
+ def stop(self):
+ """
+ Stops the monitoring thread. It is guaranteed that callbacks are no
+ longer invoked after calling this method. The method can be called
+ multiple times.
+
+ Note that this only stops the monitoring thread and not the monitor
+ itself. The monitor stops listening when it is dereferenced.
+ """
+ self._observer.stop()
+
+
+def _execute_callback(callback, device):
+ try:
+ callback(device)
+ except Exception as callbackException:
+ logging.error(
+ 'Callback execution threw an exception: %s', callbackException)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1168862..7483d0c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -110,6 +110,7 @@
testlibTests.py \
toolTests.py \
transportWrapperTests.py \
+ udevMonitorTests.py \
utilsTests.py \
vdscliTests.py \
vdsClientTests.py \
diff --git a/tests/udevMonitorTests.py b/tests/udevMonitorTests.py
new file mode 100644
index 0000000..2526459
--- /dev/null
+++ b/tests/udevMonitorTests.py
@@ -0,0 +1,137 @@
+# Copyright 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+from functools import partial
+
+import Queue
+
+from nettestlib import Bridge
+from testValidation import ValidateRunningAsRoot
+from testlib import VdsmTestCase
+from vdsm.udev.monitor import UdevMonitor
+
+
+class UdevMonitorTest(VdsmTestCase):
+
+ def setUp(self):
+ self._queue = Queue.Queue()
+ self._monitor = UdevMonitor()
+ self._monitor.start()
+
+ def tearDown(self):
+ self._monitor.stop()
+
+ @ValidateRunningAsRoot
+ def testAddDevice(self):
+ self._monitor.subscribe(
+ partial(UdevMonitorTest._device_listener, self),
+ subsystem='net',
+ device_type='bridge')
+ bridge = Bridge()
+ try:
+ bridge.addDevice()
+ device = None
+ try:
+ device = self._queue.get(timeout=1)
+ except Queue.Empty:
+ pass
+ self.assertIsNotNone(device,
+ msg='Should have detected an event')
+ self.assertEqual(device.action, 'add')
+ finally:
+ bridge.delDevice()
+
+ @ValidateRunningAsRoot
+ def testAddDeviceForSubsystem(self):
+ self._monitor.subscribe(
+ partial(UdevMonitorTest._device_listener, self),
+ subsystem='net',
+ device_type=None)
+ bridge = Bridge()
+ try:
+ bridge.addDevice()
+ device = None
+ try:
+ device = self._queue.get(timeout=1)
+ except Queue.Empty:
+ pass
+ self.assertIsNotNone(device,
+ msg='Should have detected an event')
+ self.assertEqual(device.action, 'add')
+ finally:
+ bridge.delDevice()
+
+ @ValidateRunningAsRoot
+ def testRemoveDevice(self):
+
+ bridge = Bridge()
+ try:
+ bridge.addDevice()
+ self._monitor.subscribe(
+ partial(UdevMonitorTest._device_listener, self),
+ subsystem='net',
+ device_type='bridge')
+ bridge.delDevice()
+ device = None
+ try:
+ device = self._queue.get(timeout=1)
+ except Queue.Empty:
+ pass
+ self.assertIsNotNone(device,
+ msg='Should have detected an event')
+ self.assertEqual(device.action, 'remove')
+ except:
+ bridge.delDevice()
+
+ @ValidateRunningAsRoot
+ def testEventSeries(self):
+
+ bridge1 = Bridge()
+ bridge2 = Bridge()
+ try:
+ self._monitor.subscribe(
+ partial(UdevMonitorTest._device_listener, self),
+ subsystem='net',
+ device_type='bridge')
+ bridge1.addDevice()
+ bridge1.delDevice()
+ bridge2.addDevice()
+ bridge2.delDevice()
+ events = []
+ try:
+ events.append(self._queue.get(timeout=1))
+ events.append(self._queue.get(timeout=1))
+ events.append(self._queue.get(timeout=1))
+ events.append(self._queue.get(timeout=1))
+ except Queue.Empty:
+ pass
+ self.assertEqual(len(events), 4)
+ except:
+ _delBridge(bridge1)
+ _delBridge(bridge2)
+
+ def _device_listener(self, device):
+ self._queue.put(device)
+
+
+def _delBridge(bridge):
+ try:
+ bridge.delDevice()
+ except:
+ pass
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 8f758ca..ae5e483 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -126,6 +126,7 @@
Requires: python-pthreading >= 0.1.3-3
Requires: python-six
Requires: python-requests
+Requires: python-udev >= 0.15
Requires: %{name}-infra = %{version}-%{release}
Requires: rpm-python
Requires: nfs-utils
--
To view, visit https://gerrit.ovirt.org/47729
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I4b91753424d83896fa538eb6b57f8653b6332fbb
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Roman Mohr <rmohr(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: vm: split guest agent init from domDependentInit
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: split guest agent init from domDependentInit
......................................................................
vm: split guest agent init from domDependentInit
Move into an helper to modularize Vm._domDependentInit()
with no change of behaviour.
Change-Id: I13e456d101659848c494f2c27912303c294ccf9f
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 19 insertions(+), 16 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/16/59816/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 470b627..4a545b2 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -1845,22 +1845,7 @@
self._dom_init_devices()
self._guestEventTime = self._startTime
- try:
- self.guestAgent.start()
- except Exception:
- self.log.exception("Failed to connect to guest agent channel")
-
- try:
- if self.conf.get('enableGuestEvents', False):
- if self.lastStatus == vmstatus.MIGRATION_DESTINATION:
- self.guestAgent.events.after_migration()
- elif self.lastStatus == vmstatus.RESTORING_STATE:
- self.guestAgent.events.after_hibernation()
- except Exception:
- self.log.exception("Unexpected error on guest event notification")
-
- # Drop enableGuestEvents from conf - Not required from here anymore
- self.conf.pop('enableGuestEvents', None)
+ self._dom_init_guest_agent()
self._guestCpuRunning = self._isDomainRunning()
self._logGuestCpuStatus('domain initialization')
@@ -1879,6 +1864,24 @@
self._dom_init_sla()
+ def _dom_init_guest_agent(self):
+ try:
+ self.guestAgent.start()
+ except Exception:
+ self.log.exception("Failed to connect to guest agent channel")
+
+ try:
+ if self.conf.get('enableGuestEvents', False):
+ if self.lastStatus == vmstatus.MIGRATION_DESTINATION:
+ self.guestAgent.events.after_migration()
+ elif self.lastStatus == vmstatus.RESTORING_STATE:
+ self.guestAgent.events.after_hibernation()
+ except Exception:
+ self.log.exception("Unexpected error on guest event notification")
+
+ # Drop enableGuestEvents from conf - Not required from here anymore
+ self.conf.pop('enableGuestEvents', None)
+
def _dom_init_devices(self):
# REQUIRED_FOR migrate from vdsm-4.16
#
--
To view, visit https://gerrit.ovirt.org/59816
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I13e456d101659848c494f2c27912303c294ccf9f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: vm: split device init from domDependentInit
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: split device init from domDependentInit
......................................................................
vm: split device init from domDependentInit
Move into an helper to modularize Vm._domDependentInit()
with no change of behaviour.
Change-Id: I33b347889c930b4ae2fa183e7202ed0dd7b9da26
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 25 insertions(+), 21 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/14/59814/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 3cd4aba..d3a45ab 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -1839,24 +1839,8 @@
raise MissingLibvirtDomainError(vmexitreason.LIBVIRT_START_FAILED)
self._updateDomainDescriptor()
-
- # REQUIRED_FOR migrate from vdsm-4.16
- #
- # We need to clean out unknown devices that are created for
- # RNG devices by VDSM 3.5 and are left in the configuration
- # after upgrade to 3.6.
- self._fixLegacyRngConf()
-
- self._getUnderlyingVmDevicesInfo()
- self._updateAgentChannels()
-
- # Currently there is no protection agains mirroring a network twice,
- if not self.recovering:
- for nic in self._devices[hwclass.NIC]:
- if hasattr(nic, 'portMirroring'):
- for network in nic.portMirroring:
- supervdsm.getProxy().setPortMirroring(network,
- nic.name)
+
+ self._dom_init_devices()
self._guestEventTime = self._startTime
sampling.stats_cache.add(self.id)
@@ -1877,9 +1861,6 @@
# Drop enableGuestEvents from conf - Not required from here anymore
self.conf.pop('enableGuestEvents', None)
- for con in self._devices[hwclass.CONSOLE]:
- con.prepare()
-
self._guestCpuRunning = self._isDomainRunning()
self._logGuestCpuStatus('domain initialization')
if self.lastStatus not in (vmstatus.MIGRATION_DESTINATION,
@@ -1897,6 +1878,29 @@
self._dom_init_sla()
+ def _dom_init_devices(self):
+ # REQUIRED_FOR migrate from vdsm-4.16
+ #
+ # We need to clean out unknown devices that are created for
+ # RNG devices by VDSM 3.5 and are left in the configuration
+ # after upgrade to 3.6.
+ self._fixLegacyRngConf()
+
+ self._getUnderlyingVmDevicesInfo()
+ self._updateAgentChannels()
+
+ # Currently there is no protection agains mirroring a network twice,
+ if not self.recovering:
+ for nic in self._devices[hwclass.NIC]:
+ if hasattr(nic, 'portMirroring'):
+ for network in nic.portMirroring:
+ supervdsm.getProxy().setPortMirroring(network,
+ nic.name)
+
+ # must be done after the setup and once the device is ready
+ for con in self._devices[hwclass.CONSOLE]:
+ con.prepare()
+
def _dom_init_sla(self):
nice = int(self.conf.get('nice', '0'))
nice = max(min(nice, 19), 0)
--
To view, visit https://gerrit.ovirt.org/59814
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I33b347889c930b4ae2fa183e7202ed0dd7b9da26
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: FileVolumeMetadata: split getMetadata
by alitke@redhat.com
Adam Litke has uploaded a new change for review.
Change subject: FileVolumeMetadata: split getMetadata
......................................................................
FileVolumeMetadata: split getMetadata
Change-Id: I1d3fb61831de5b50a3e562b80bf38ef15ede254f
Signed-off-by: Adam Litke <alitke(a)redhat.com>
---
M vdsm/storage/fileVolume.py
1 file changed, 16 insertions(+), 13 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/69/44569/1
diff --git a/vdsm/storage/fileVolume.py b/vdsm/storage/fileVolume.py
index 08e3f50..74aa911 100644
--- a/vdsm/storage/fileVolume.py
+++ b/vdsm/storage/fileVolume.py
@@ -123,18 +123,10 @@
"""
return (self.getVolumePath(),)
- def getMetadata(self, metaId=None):
- """
- Get Meta data array of key,values lines
- """
- if not metaId:
- metaId = self.getMetadataId()
-
- volPath, = metaId
- metaPath = self._getMetaVolumePath(volPath)
-
+ @classmethod
+ def read_metadata(cls, oop, meta_path):
try:
- f = self.oop.directReadLines(metaPath)
+ f = oop.directReadLines(meta_path)
out = {}
for l in f:
if l.startswith("EOF"):
@@ -145,11 +137,22 @@
out[key.strip()] = value.strip()
except Exception as e:
- self.log.error(e, exc_info=True)
- raise se.VolumeMetadataReadError("%s: %s" % (metaId, e))
+ cls.log.error(e, exc_info=True)
+ raise se.VolumeMetadataReadError("%s: %s" % (meta_path, e))
return out
+ def getMetadata(self, metaId=None):
+ """
+ Get Meta data array of key,values lines
+ """
+ if not metaId:
+ metaId = self.getMetadataId()
+
+ volPath, = metaId
+ metaPath = self._getMetaVolumePath(volPath)
+ return self.read_metadata(self.oop, metaPath)
+
def getParentId(self):
"""
Return parent volume UUID
--
To view, visit https://gerrit.ovirt.org/44569
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1d3fb61831de5b50a3e562b80bf38ef15ede254f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <alitke(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: VolumeMetadata: move prepare and teardown
by alitke@redhat.com
Adam Litke has uploaded a new change for review.
Change subject: VolumeMetadata: move prepare and teardown
......................................................................
VolumeMetadata: move prepare and teardown
Change-Id: Iba0954ace3b1da5ea9afc41aeb6ea69a729fe29c
Signed-off-by: Adam Litke <alitke(a)redhat.com>
---
M vdsm/storage/blockVolume.py
M vdsm/storage/fileVolume.py
M vdsm/storage/volume.py
3 files changed, 117 insertions(+), 109 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/50/44050/1
diff --git a/vdsm/storage/blockVolume.py b/vdsm/storage/blockVolume.py
index 0168d64..597e7ee 100644
--- a/vdsm/storage/blockVolume.py
+++ b/vdsm/storage/blockVolume.py
@@ -74,6 +74,8 @@
volume.VolumeMetadata.__init__(self, repoPath, sdUUID, imgUUID,
volUUID)
self.metaoff = None
+ self.lvmActivationNamespace = sd.getNamespace(self.sdUUID,
+ LVM_ACTIVATION_NAMESPACE)
def getMetadataId(self):
"""
@@ -332,6 +334,49 @@
lvs = lvm.lvsByTag(sdUUID, "%s%s" % (TAG_PREFIX_IMAGE, imgUUID))
return [lv.name for lv in lvs]
+ @logskip("ResourceManager")
+ def llPrepare(self, rw=False, setrw=False):
+ """
+ Perform low level volume use preparation
+
+ For the Block Volumes the actual LV activation is wrapped
+ into lvmActivation resource. It is being initialized by the
+ storage domain sitting on top of the encapsulating VG.
+ We just use it here.
+ """
+ if setrw:
+ self.setrw(rw=rw)
+ access = rm.LockType.exclusive if rw else rm.LockType.shared
+ activation = rmanager.acquireResource(self.lvmActivationNamespace,
+ self.volUUID, access)
+ activation.autoRelease = False
+
+ @classmethod
+ def teardown(cls, sdUUID, volUUID, justme=False):
+ """
+ Deactivate volume and release resources.
+ Volume deactivation occurs as part of resource releasing.
+ If justme is false, the entire COW chain should be torn down.
+ """
+ cls.log.info("Tearing down volume %s/%s justme %s"
+ % (sdUUID, volUUID, justme))
+ lvmActivationNamespace = sd.getNamespace(sdUUID,
+ LVM_ACTIVATION_NAMESPACE)
+ rmanager.releaseResource(lvmActivationNamespace, volUUID)
+ if not justme:
+ try:
+ pvolUUID = _getVolumeTag(sdUUID, volUUID, TAG_PREFIX_PARENT)
+ except Exception as e:
+ # If storage not accessible or lvm error occurred
+ # we will failure to get the parent volume.
+ # We can live with it and still succeed in volume's teardown.
+ pvolUUID = volume.BLANK_UUID
+ cls.log.warn("Failure to get parent of volume %s/%s (%s)"
+ % (sdUUID, volUUID, e))
+
+ if pvolUUID != volume.BLANK_UUID:
+ cls.teardown(sdUUID=sdUUID, volUUID=pvolUUID, justme=False)
+
class BlockVolume(volume.Volume):
""" Actually represents a single volume (i.e. part of virtual disk).
@@ -341,8 +386,6 @@
def __init__(self, repoPath, sdUUID, imgUUID, volUUID):
md = self.MetadataClass(repoPath, sdUUID, imgUUID, volUUID)
volume.Volume.__init__(self, md)
- self.lvmActivationNamespace = sd.getNamespace(self.sdUUID,
- LVM_ACTIVATION_NAMESPACE)
@property
def metaoff(self):
@@ -609,49 +652,6 @@
def shareVolumeRollback(cls, taskObj, volPath):
cls.log.info("Volume rollback for volPath=%s", volPath)
utils.rmFile(volPath)
-
- @logskip("ResourceManager")
- def llPrepare(self, rw=False, setrw=False):
- """
- Perform low level volume use preparation
-
- For the Block Volumes the actual LV activation is wrapped
- into lvmActivation resource. It is being initialized by the
- storage domain sitting on top of the encapsulating VG.
- We just use it here.
- """
- if setrw:
- self.setrw(rw=rw)
- access = rm.LockType.exclusive if rw else rm.LockType.shared
- activation = rmanager.acquireResource(self.lvmActivationNamespace,
- self.volUUID, access)
- activation.autoRelease = False
-
- @classmethod
- def teardown(cls, sdUUID, volUUID, justme=False):
- """
- Deactivate volume and release resources.
- Volume deactivation occurs as part of resource releasing.
- If justme is false, the entire COW chain should be torn down.
- """
- cls.log.info("Tearing down volume %s/%s justme %s"
- % (sdUUID, volUUID, justme))
- lvmActivationNamespace = sd.getNamespace(sdUUID,
- LVM_ACTIVATION_NAMESPACE)
- rmanager.releaseResource(lvmActivationNamespace, volUUID)
- if not justme:
- try:
- pvolUUID = _getVolumeTag(sdUUID, volUUID, TAG_PREFIX_PARENT)
- except Exception as e:
- # If storage not accessible or lvm error occurred
- # we will failure to get the parent volume.
- # We can live with it and still succeed in volume's teardown.
- pvolUUID = volume.BLANK_UUID
- cls.log.warn("Failure to get parent of volume %s/%s (%s)"
- % (sdUUID, volUUID, e))
-
- if pvolUUID != volume.BLANK_UUID:
- cls.teardown(sdUUID=sdUUID, volUUID=pvolUUID, justme=False)
def getVolumeTag(self, tagPrefix):
return self.md.getVolumeTag(tagPrefix)
diff --git a/vdsm/storage/fileVolume.py b/vdsm/storage/fileVolume.py
index 2dad91f..08e3f50 100644
--- a/vdsm/storage/fileVolume.py
+++ b/vdsm/storage/fileVolume.py
@@ -337,6 +337,26 @@
volList.append(volid)
return volList
+ def llPrepare(self, rw=False, setrw=False):
+ """
+ Make volume accessible as readonly (internal) or readwrite (leaf)
+ """
+ volPath = self.getVolumePath()
+
+ # Volumes leaves created in 2.2 did not have group writeable bit
+ # set. We have to set it here if we want qemu-kvm to write to old
+ # NFS volumes.
+ self.oop.fileUtils.copyUserModeToGroup(volPath)
+
+ if setrw:
+ self.setrw(rw=rw)
+ if rw:
+ if not self.oop.os.access(volPath, os.R_OK | os.W_OK):
+ raise se.VolumeAccessError(volPath)
+ else:
+ if not self.oop.os.access(volPath, os.R_OK):
+ raise se.VolumeAccessError(volPath)
+
class FileVolume(volume.Volume):
""" Actually represents a single volume (i.e. part of virtual disk).
@@ -488,26 +508,6 @@
procPool.utils.rmFile(volPath)
procPool.utils.rmFile(cls.__metaVolumePath(volPath))
procPool.utils.rmFile(cls.MetadataClass._leaseVolumePath(volPath))
-
- def llPrepare(self, rw=False, setrw=False):
- """
- Make volume accessible as readonly (internal) or readwrite (leaf)
- """
- volPath = self.getVolumePath()
-
- # Volumes leaves created in 2.2 did not have group writeable bit
- # set. We have to set it here if we want qemu-kvm to write to old
- # NFS volumes.
- self.oop.fileUtils.copyUserModeToGroup(volPath)
-
- if setrw:
- self.setrw(rw=rw)
- if rw:
- if not self.oop.os.access(volPath, os.R_OK | os.W_OK):
- raise se.VolumeAccessError(volPath)
- else:
- if not self.oop.os.access(volPath, os.R_OK):
- raise se.VolumeAccessError(volPath)
@classmethod
def __putMetadata(cls, metaId, meta):
diff --git a/vdsm/storage/volume.py b/vdsm/storage/volume.py
index a098eb7..22f7ead 100644
--- a/vdsm/storage/volume.py
+++ b/vdsm/storage/volume.py
@@ -525,6 +525,56 @@
return apparentSize
return req_size
+ def prepare(self, rw=True, justme=False,
+ chainrw=False, setrw=False, force=False):
+ """
+ Prepare volume for use by consumer.
+ If justme is false, the entire COW chain is prepared.
+ Note: setrw arg may be used only by SPM flows.
+ """
+ self.log.info("Volume: preparing volume %s/%s",
+ self.sdUUID, self.volUUID)
+
+ if not force:
+ # Cannot prepare ILLEGAL volume
+ if not self.isLegal():
+ raise se.prepareIllegalVolumeError(self.volUUID)
+
+ if rw and self.isShared():
+ if chainrw:
+ rw = False # Shared cannot be set RW
+ else:
+ raise se.SharedVolumeNonWritable(self)
+
+ if (not chainrw and rw and self.isInternal() and setrw and
+ not self.recheckIfLeaf()):
+ raise se.InternalVolumeNonWritable(self)
+
+ self.llPrepare(rw=rw, setrw=setrw)
+ self.updateInvalidatedSize()
+
+ try:
+ if justme:
+ return True
+ pvol = self.produceParent()
+ if pvol:
+ pvol.prepare(rw=chainrw, justme=False,
+ chainrw=chainrw, setrw=setrw)
+ except Exception:
+ self.log.error("Unexpected error", exc_info=True)
+ self.teardown(self.sdUUID, self.volUUID)
+ raise
+
+ return True
+
+ @classmethod
+ def teardown(cls, sdUUID, volUUID, justme=False):
+ """
+ Teardown volume.
+ If justme is false, the entire COW chain is teared down.
+ """
+ pass
+
class Volume(object):
log = logging.getLogger('Storage.Volume')
@@ -1091,53 +1141,11 @@
def prepare(self, rw=True, justme=False,
chainrw=False, setrw=False, force=False):
- """
- Prepare volume for use by consumer.
- If justme is false, the entire COW chain is prepared.
- Note: setrw arg may be used only by SPM flows.
- """
- self.log.info("Volume: preparing volume %s/%s",
- self.sdUUID, self.volUUID)
-
- if not force:
- # Cannot prepare ILLEGAL volume
- if not self.isLegal():
- raise se.prepareIllegalVolumeError(self.volUUID)
-
- if rw and self.isShared():
- if chainrw:
- rw = False # Shared cannot be set RW
- else:
- raise se.SharedVolumeNonWritable(self)
-
- if (not chainrw and rw and self.isInternal() and setrw and
- not self.recheckIfLeaf()):
- raise se.InternalVolumeNonWritable(self)
-
- self.llPrepare(rw=rw, setrw=setrw)
- self.updateInvalidatedSize()
-
- try:
- if justme:
- return True
- pvol = self.produceParent()
- if pvol:
- pvol.prepare(rw=chainrw, justme=False,
- chainrw=chainrw, setrw=setrw)
- except Exception:
- self.log.error("Unexpected error", exc_info=True)
- self.teardown(self.sdUUID, self.volUUID)
- raise
-
- return True
+ return self.md.prepare(rw, justme, chainrw, setrw, force)
@classmethod
def teardown(cls, sdUUID, volUUID, justme=False):
- """
- Teardown volume.
- If justme is false, the entire COW chain is teared down.
- """
- pass
+ cls.MetadataClass.teardown(sdUUID, volUUID, justme)
@classmethod
def newMetadata(cls, metaId, sdUUID, imgUUID, puuid, size, format, type,
--
To view, visit https://gerrit.ovirt.org/44050
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iba0954ace3b1da5ea9afc41aeb6ea69a729fe29c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <alitke(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: sdc: Allow StorageDomainCache to cache StorageDomainManifest...
by alitke@redhat.com
Adam Litke has uploaded a new change for review.
Change subject: sdc: Allow StorageDomainCache to cache StorageDomainManifest objects
......................................................................
sdc: Allow StorageDomainCache to cache StorageDomainManifest objects
When HSM is operating without SPM the system should always be using
StorageDomainManifest objects instead of StorageDomains. With this
patch we can instruct the cache to serve the correct type of object
without changing all consumers of sdCache.
Change-Id: I9a3dc7d9bf24f7d8b60ddff6f5364b65a9354e45
Signed-off-by: Adam Litke <alitke(a)redhat.com>
---
M vdsm/storage/sdc.py
1 file changed, 12 insertions(+), 3 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/41/44041/1
diff --git a/vdsm/storage/sdc.py b/vdsm/storage/sdc.py
index ecb9708..cbdaed9 100644
--- a/vdsm/storage/sdc.py
+++ b/vdsm/storage/sdc.py
@@ -64,12 +64,13 @@
STORAGE_STALE = 1
STORAGE_REFRESHING = 2
- def __init__(self, storage_repo):
+ def __init__(self, storage_repo, use_manifests=False):
self._syncroot = threading.Condition()
self.__domainCache = {}
self.__inProgress = set()
self.__staleStatus = self.STORAGE_STALE
self.storage_repo = storage_repo
+ self.use_manifests = use_manifests
self.knownSDs = {} # {sdUUID: mod.findDomain}
def invalidateStorage(self):
@@ -162,12 +163,18 @@
# this changes, please update the order.
for mod in (blockSD, glusterSD, localFsSD, nfsSD):
try:
- return mod.findDomain(sdUUID)
+ if self.use_manifests:
+ ret = mod.findDomainManifest(sdUUID)
+ else:
+ ret = mod.findDomain(sdUUID)
except se.StorageDomainDoesNotExist:
pass
except Exception:
self.log.error("Error while looking for domain `%s`", sdUUID,
exc_info=True)
+ else:
+ self.log.debug("Found domain %s", ret)
+ return ret
raise se.StorageDomainDoesNotExist(sdUUID)
@@ -181,10 +188,12 @@
return uuids
- def refresh(self):
+ def refresh(self, use_manifests=None):
with self._syncroot:
lvm.invalidateCache()
self.__domainCache.clear()
+ if use_manifests is not None:
+ self.use_manifests = use_manifests
def manuallyAddDomain(self, domain):
with self._syncroot:
--
To view, visit https://gerrit.ovirt.org/44041
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9a3dc7d9bf24f7d8b60ddff6f5364b65a9354e45
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <alitke(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: doc: Typo fixes and other doc improvements in periodic.py
by mzamazal@redhat.com
Milan Zamazal has uploaded a new change for review.
Change subject: doc: Typo fixes and other doc improvements in periodic.py
......................................................................
doc: Typo fixes and other doc improvements in periodic.py
This is a documentation only change to fix some typos, inconsistencies
and other errors in comments and docstrings.
Change-Id: I9550acf4c8c8ffde0ae3f7d5aad6e8b9d22fed95
Signed-off-by: Milan Zamazal <mzamazal(a)redhat.com>
---
M lib/vdsm/virt/periodic.py
1 file changed, 17 insertions(+), 17 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/34/59734/1
diff --git a/lib/vdsm/virt/periodic.py b/lib/vdsm/virt/periodic.py
index 8ed5d67..87227b9 100644
--- a/lib/vdsm/virt/periodic.py
+++ b/lib/vdsm/virt/periodic.py
@@ -20,7 +20,7 @@
from __future__ import absolute_import
"""
-code to perform periodic maintenance and bookkeeping of the VMs.
+Code to perform periodic maintenance and bookkeeping of the VMs.
"""
import logging
@@ -37,7 +37,7 @@
from vdsm.virt import vmstatus
-# just a made up number. Maybe should be equal to number of cores?
+# Just a made up number. Maybe should be equal to number of cores?
# TODO: make them tunable through private, unsupported configuration items
_WORKERS = config.getint('sampling', 'periodic_workers')
_TASK_PER_WORKER = config.getint('sampling', 'periodic_task_per_worker')
@@ -71,13 +71,13 @@
return Operation(disp, period, scheduler)
_operations = [
- # needs dispatching becuse updating the volume stats needs the
- # access the storage, thus can block.
+ # Needs dispatching because updating the volume stats needs
+ # access to the storage, thus can block.
per_vm_operation(
UpdateVolumes,
config.getint('irs', 'vol_size_sample_interval')),
- # needs dispatching becuse access FS and libvirt data
+ # Needs dispatching because it accesses FS and libvirt data.
per_vm_operation(
NumaInfoMonitor,
config.getint('vars', 'vm_sample_numa_interval')),
@@ -98,8 +98,8 @@
config.getint('vars', 'vm_sample_interval'),
scheduler),
- # we do this only until we get high water mark notifications
- # from qemu. Access storage and/or qemu monitor, so can block,
+ # We do this only until we get high water mark notifications
+ # from QEMU. It accesses storage and/or QEMU monitor, so can block,
# thus we need dispatching.
per_vm_operation(
DriveWatermarkMonitor,
@@ -129,7 +129,7 @@
"""
Operation runs a callable with a given period until
someone stops it.
- Operations builds on Schedule and on Executor,
+ Operation builds on Schedule and on Executor,
so that the underlying "func" is called periodically.
It would be called again even if a former call is blocked.
"""
@@ -184,14 +184,14 @@
def _step(self):
"""
- Schedule a next call of `func'
+ Schedule a next call of `func'.
"""
self._call = self._scheduler.schedule(self._period,
self._try_to_dispatch)
def _try_to_dispatch(self):
"""
- Dispatch anoter Execution, if Operation is still running.
+ Dispatch another Execution, if Operation is still running.
"""
with self._lock:
if self._running:
@@ -245,10 +245,10 @@
if not op.required:
continue
# When dealing with blocked domains, we also want to avoid
- # to pile up jobs that libvirt can't handle and eventually
- # clog it.
+ # to pile up jobs that libvirt can't handle and that will
+ # eventually clog it.
# We don't care too much about precise tracking, so it is
- # still OK if occasional misdetection occours, but we
+ # still OK if occasional misdetection occurs, but we
# definitely want to avoid known-bad situation and to
# needlessly overload libvirt.
if not op.runnable:
@@ -281,8 +281,8 @@
@property
def required(self):
- # disable everything until migration destination VM
- # isn't fully started, to avoid false positives log spam.
+ # Disable everything until the migration destination VM
+ # is fully started, to avoid false positives log spam.
return not self._vm.incomingMigrationPending()
@property
@@ -328,7 +328,7 @@
def _execute(self):
for drive in self._vm.getDiskDevices():
- # TODO: If this block (it is actually possible?)
+ # TODO: If this blocks (is it actually possible?)
# we must make sure we don't overwrite good data
# with stale old data.
self._vm.updateDriveVolume(drive)
@@ -357,7 +357,7 @@
def required(self):
# For performance reasons, we must avoid as much
# as possible to create per-vm executor tasks, even
- # though they will do nothing but a few check and exit
+ # though they will do nothing but a few checks and exit
# early, as they do if a VM doesn't have Block Jobs to
# monitor (most often true).
return (super(BlockjobMonitor, self).required and self._vm.hasVmJobs)
--
To view, visit https://gerrit.ovirt.org/59734
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9550acf4c8c8ffde0ae3f7d5aad6e8b9d22fed95
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Milan Zamazal <mzamazal(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: tox: Exclude all dotted files from pep8 check
by mzamazal@redhat.com
Milan Zamazal has uploaded a new change for review.
Change subject: tox: Exclude all dotted files from pep8 check
......................................................................
tox: Exclude all dotted files from pep8 check
pep8 breaks on files in .ropeproject, created by Python rope tools.
We probably don't need to check files in any dotted directories, so this
patch excludes them all to avoid the need to add every possible
auxiliary directory here.
Change-Id: I09029b6209195d11e6013f776011f6565ab950d1
Signed-off-by: Milan Zamazal <mzamazal(a)redhat.com>
---
M tox.sh
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/77/59677/1
diff --git a/tox.sh b/tox.sh
index 5d01520..172f4a5 100755
--- a/tox.sh
+++ b/tox.sh
@@ -35,7 +35,7 @@
for x in ${PEP8_BLACKLIST[@]}; do \
exclude="$${exclude},$${x}" ; \
done ; \
- pep8 --exclude="$${exclude}" --exclude='.tox/*' \
+ pep8 --exclude="$${exclude}" --exclude='.*' \
--filename '*.py' . \
"${WHITELIST[@]}"
fi
--
To view, visit https://gerrit.ovirt.org/59677
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I09029b6209195d11e6013f776011f6565ab950d1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Milan Zamazal <mzamazal(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: wip: tox: add version check and disable tox running option
by igoihman@redhat.com
Irit Goihman has uploaded a new change for review.
Change subject: wip: tox: add version check and disable tox running option
......................................................................
wip: tox: add version check and disable tox running option
if tox is installed with 'yum install' on RHEL, an older version is installed
and the build fails.
Now tox won't run if it's not in the right version and a DIABLE_STYLE_VALIDATION
flag has been added.
Change-Id: I665025dacdd5346a5e021ac98e864f7b6461917c
Signed-off-by: Irit Goihman <igoihman(a)redhat.com>
---
M Makefile.am
1 file changed, 12 insertions(+), 3 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/06/59306/1
diff --git a/Makefile.am b/Makefile.am
index 9ac2515..2fa6527 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -89,10 +89,19 @@
.PHONY: pep8
pep8:
- if [ -n "$(TOX)" ]; then \
- tox -- pep8; \
+ if [ "$(DISABLE_STYLE_VALIDATION)" == "1" ]; then \
+ echo "Style validation disabled, skipping check"; \
else \
- echo "Warning: tox is not installed, skipping check"; \
+ if [ -n "$(TOX)" ]; then \
+ if [ "$(tox --version)" == 2.1.1 ]; then \
+ tox -- pep8; \
+ echo "$(RUN_ARGS)"; \
+ else \
+ echo "Warning: tox version doesn't match"; \
+ fi \
+ else \
+ echo "Warning: tox is not installed, skipping check"; \
+ fi \
fi
.PHONY: python3
--
To view, visit https://gerrit.ovirt.org/59306
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I665025dacdd5346a5e021ac98e864f7b6461917c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Irit Goihman <igoihman(a)redhat.com>
7 years, 9 months
Change in vdsm[master]: vm: split out SLA settings from domDependentInit
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: split out SLA settings from domDependentInit
......................................................................
vm: split out SLA settings from domDependentInit
Move into helper to modularize the Vm._domDependentInit()
method, with no intended change on behaviour
Change-Id: I9907a428b00d5851ece0037acfcc1ad72442ae46
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 3 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/13/59813/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 6a3a7a8..3cd4aba 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -1895,6 +1895,9 @@
with self._confLock:
self.conf['pid'] = str(self._getPid())
+ self._dom_init_sla()
+
+ def _dom_init_sla(self):
nice = int(self.conf.get('nice', '0'))
nice = max(min(nice, 19), 0)
--
To view, visit https://gerrit.ovirt.org/59813
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9907a428b00d5851ece0037acfcc1ad72442ae46
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
7 years, 9 months