Change in vdsm[master]: [WIP] Add a releaseHostId option to stop the DomainMonitorTh...
by Federico Simoncelli
Federico Simoncelli has uploaded a new change for review.
Change subject: [WIP] Add a releaseHostId option to stop the DomainMonitorThread
......................................................................
[WIP] Add a releaseHostId option to stop the DomainMonitorThread
Bug-Id: https://bugzilla.redhat.com/show_bug.cgi?id=851151
Change-Id: I83458fb4146de7e402606916615533da305bd867
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/storage/domainMonitor.py
M vdsm/storage/sp.py
2 files changed, 19 insertions(+), 9 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/81/7581/1
diff --git a/vdsm/storage/domainMonitor.py b/vdsm/storage/domainMonitor.py
index 95e2f7b..c1ec5a9 100644
--- a/vdsm/storage/domainMonitor.py
+++ b/vdsm/storage/domainMonitor.py
@@ -84,14 +84,14 @@
# The domain should be added only after it succesfully started
self._domains[sdUUID] = domainThread
- def stopMonitoring(self, sdUUID):
+ def stopMonitoring(self, sdUUID, releaseHostId=False):
# The domain monitor issues events that might become raceful if
# stopMonitoring doesn't stop until the thread exits.
# Eg: when a domain is detached the domain monitor is stopped and
# the host id is released. If the monitor didn't actually exit it
# might respawn a new acquire host id.
try:
- self._domains[sdUUID].stop()
+ self._domains[sdUUID].stop(releaseHostId=releaseHostId)
except KeyError:
return
@@ -100,13 +100,15 @@
def getStatus(self, sdUUID):
return self._domains[sdUUID].getStatus()
- def close(self):
+ def close(self, releaseHostId=False):
for sdUUID in self._domains.keys():
- self.stopMonitoring(sdUUID)
+ self.stopMonitoring(sdUUID, releaseHostId=releaseHostId)
class DomainMonitorThread(object):
log = logging.getLogger('Storage.DomainMonitorThread')
+
+ RELEASE_HOSTID_DEFAULT = False
def __init__(self, sdUUID, hostId, interval):
self.thread = Thread(target=self._monitorLoop)
@@ -121,16 +123,20 @@
self.nextStatus = DomainMonitorStatus()
self.isIsoDomain = None
self.lastRefresh = time()
+ self.releaseHostId = self.RELEASE_HOSTID_DEFAULT
self.refreshTime = \
config.getint("irs", "repo_stats_cache_refresh_timeout")
def start(self):
self.thread.start()
- def stop(self, wait=True):
+ def stop(self, wait=True, releaseHostId):
+ self.releaseHostId = releaseHostId
+
self.stopEvent.set()
if wait:
self.thread.join()
+
self.domain = None
def getStatus(self):
@@ -151,13 +157,17 @@
# If this is an ISO domain we didn't acquire the host id and releasing
# it is superfluous.
- if not self.isIsoDomain:
+ if not self.isIsoDomain and self.releaseHostId:
try:
self.domain.releaseHostId(self.hostId, unused=True)
except:
self.log.debug("Unable to release the host id %s for domain "
"%s", self.hostId, self.sdUUID, exc_info=True)
+ # Resetting the releaseHostId value to its default just to be sure in
+ # case in the future we want to recycle the DomainMonitor objects.
+ self.releaseHostId = self.RELEASE_HOSTID_DEFAULT
+
def _monitorDomain(self):
self.nextStatus.clear()
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index 40de20a..e8c59f3 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -647,8 +647,8 @@
@unsecured
- def stopMonitoringDomains(self):
- self.domainMonitor.close()
+ def stopMonitoringDomains(self, releaseHostId=False):
+ self.domainMonitor.close(releaseHostId=releaseHostId)
return True
@@ -675,7 +675,7 @@
if os.path.exists(self.poolPath):
fileUtils.cleanupdir(self.poolPath)
- self.stopMonitoringDomains()
+ self.stopMonitoringDomains(releaseHostId=True)
return True
--
To view, visit http://gerrit.ovirt.org/7581
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I83458fb4146de7e402606916615533da305bd867
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>
10 years
Change in vdsm[master]: vm: Avoid log spamming when drive format is undefined
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: vm: Avoid log spamming when drive format is undefined
......................................................................
vm: Avoid log spamming when drive format is undefined
Due to the dynamic way drive attribute are initialized, it is possible
that drive's format attribute is undefined. In this case _highwrite
fails repeatedly with noisy exception spamming vdsm log and syslog.
The purpose of _highwrite is to check if drive is too full and should be
extended before it is too late and the vm is paused. In this context, we
care only about block devices using 'cow' format. We could not care less
about drive without a format attribute, and there is no reason to spam
the log about this.
This patch use getattr to check if drive uses the cow format and make
the code more clear by extracting the check to new isExtendable method.
Change-Id: Ia50e8af94b9c9b54332066a3f30999ce73e7a56f
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M vdsm/vm.py
1 file changed, 5 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/51/22551/1
diff --git a/vdsm/vm.py b/vdsm/vm.py
index 1358b09..37b426a 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -1406,6 +1406,10 @@
def isDiskReplicationInProgress(self):
return hasattr(self, "diskReplicate")
+ def isExtendable(self):
+ # Note: format may not be defined during migration
+ return self.blockDev and getattr(self, 'format', None) == 'cow'
+
@property
def volExtensionChunk(self):
"""
@@ -2312,7 +2316,7 @@
extend = []
for drive in self._devices[DISK_DEVICES]:
- if not drive.blockDev or drive.format != 'cow':
+ if not drive.isExtendable():
continue
capacity, alloc, physical = self._dom.blockInfo(drive.path, 0)
--
To view, visit http://gerrit.ovirt.org/22551
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia50e8af94b9c9b54332066a3f30999ce73e7a56f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
10 years
Change in vdsm[master]: vmDevices: replace self.conf['devices'] by VmDeviceContainer
by mpoledni@redhat.com
Martin Polednik has uploaded a new change for review.
Change subject: vmDevices: replace self.conf['devices'] by VmDeviceContainer
......................................................................
vmDevices: replace self.conf['devices'] by VmDeviceContainer
This patch servers as an implementation of VmDeviceContainer, removing
access to self.conf['devices'] and keeping migration-friendly restore
file by pickling structure similar to self.conf['devices']
Change-Id: I3bdb5c331657c1c0d1ae902eabb5d3315d45bf8b
Signed-off-by: Martin Polednik <mpoledni(a)redhat.com>
---
M vdsm/vm.py
1 file changed, 42 insertions(+), 127 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/62/21162/1
diff --git a/vdsm/vm.py b/vdsm/vm.py
index d4ce708..f2e22cf 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -2919,14 +2919,7 @@
if not 'recover' in self.conf:
self.preparePaths(devices[DISK_DEVICES])
self._prepareTransientDisks(devices[DISK_DEVICES])
- # Update self.conf with updated devices
- # For old type vmParams, new 'devices' key will be
- # created with all devices info
- newDevices = []
- for dev in devices.values():
- newDevices.extend(dev)
- self.conf['devices'] = newDevices
# We need to save conf here before we actually run VM.
# It's not enough to save conf only on status changes as we did
# before, because if vdsm will restarted between VM run and conf
@@ -2939,6 +2932,7 @@
for dev in devices[devType]:
self._devices[devType].append(devClass(self.conf, self.log,
**dev))
+ self.conf['devices'] = self._devices.legacy
# We should set this event as a last part of drives initialization
self._pathsPreparedEvent.set()
@@ -3072,9 +3066,8 @@
# we sent command to libvirt and before save conf. In this case
# we will gather almost all needed info about this NIC from
# the libvirt during recovery process.
- self._devices[NIC_DEVICES].append(nic)
with self._confLock:
- self.conf['devices'].append(nicParams)
+ self._devices[NIC_DEVICES].append(nic)
self.saveState()
self._getUnderlyingNetworkInterfaceInfo()
hooks.after_nic_hotplug(nicXml, self.conf,
@@ -3109,9 +3102,8 @@
'not found' % alias)
def _lookupConfByAlias(self, alias):
- for devConf in self.conf['devices'][:]:
- if devConf['type'] == NIC_DEVICES and \
- devConf['alias'] == alias:
+ for devConf in self._devices[NIC_DEVICES]:
+ if devConf['alias'] == alias:
return devConf
raise LookupError('Configuration of device identified by alias %s not'
'found' % alias)
@@ -3256,15 +3248,6 @@
# Remove found NIC from vm's NICs list
if nic:
self._devices[NIC_DEVICES].remove(nic)
- # Find and remove NIC device from vm's conf
- nicDev = None
- for dev in self.conf['devices'][:]:
- if (dev['type'] == NIC_DEVICES and
- dev['macAddr'].lower() == nicParams['macAddr'].lower()):
- with self._confLock:
- self.conf['devices'].remove(dev)
- nicDev = dev
- break
self.saveState()
@@ -3274,10 +3257,7 @@
self.log.error("Hotunplug failed", exc_info=True)
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
return errCode['noVM']
- # Restore NIC device in vm's conf and _devices
- if nicDev:
- with self._confLock:
- self.conf['devices'].append(nicDev)
+ # Restore NIC device in vm's deviceContainer
if nic:
self._devices[NIC_DEVICES].append(nic)
self.saveState()
@@ -3365,11 +3345,10 @@
# we sent command to libvirt and before save conf. In this case
# we will gather almost all needed info about this drive from
# the libvirt during recovery process.
- self._devices[DISK_DEVICES].append(drive)
if vdsmImg:
self.sdIds.append(diskParams['domainID'])
with self._confLock:
- self.conf['devices'].append(diskParams)
+ self._devices[DISK_DEVICES].append(drive)
self.saveState()
self._getUnderlyingDriveInfo()
hooks.after_disk_hotplug(driveXml, self.conf,
@@ -3404,16 +3383,6 @@
if drive.isVdsmImage():
self.sdIds.remove(drive.domainID)
self._devices[DISK_DEVICES].remove(drive)
- # Find and remove disk device from vm's conf
- diskDev = None
- for dev in self.conf['devices'][:]:
- if (dev['type'] == DISK_DEVICES and
- dev['path'] == drive.path):
- with self._confLock:
- self.conf['devices'].remove(dev)
- diskDev = dev
- break
-
self.saveState()
hooks.before_disk_hotunplug(driveXml, self.conf,
@@ -3425,10 +3394,6 @@
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
return errCode['noVM']
self._devices[DISK_DEVICES].append(drive)
- # Restore disk device in vm's conf and _devices
- if diskDev:
- with self._confLock:
- self.conf['devices'].append(diskDev)
self.saveState()
return {
'status': {'code': errCode['hotunplugDisk']['status']['code'],
@@ -4407,12 +4372,11 @@
return {'status': doneCode}
def _getBalloonInfo(self):
- for dev in self.conf['devices']:
- if dev['type'] == BALLOON_DEVICES and \
- dev['specParams']['model'] != 'none':
+ for dev in self._devices[BALLOON_DEVICES]:
+ if dev.specParams['model'] != 'none':
max_mem = int(self.conf.get('memSize')) * 1024
min_mem = int(self.conf.get('memGuaranteedSize', '0')) * 1024
- target_mem = dev.get('target', max_mem)
+ target_mem = getattr(dev, 'target', max_mem)
cur_mem = self._dom.info()[2]
return {'balloon_max': str(max_mem),
'balloon_cur': str(cur_mem),
@@ -4443,10 +4407,9 @@
return reportError(key='noVM')
return reportError(msg=e.message)
else:
- for dev in self.conf['devices']:
- if dev['type'] == BALLOON_DEVICES and \
- dev['specParams']['model'] != 'none':
- dev['target'] = target
+ for dev in self._devices[BALLOON_DEVICES]:
+ if dev.specParams['model'] != 'none':
+ dev.target = target
# persist the target value to make it consistent after recovery
self.saveState()
return {'status': doneCode}
@@ -4475,9 +4438,12 @@
passed during VM creation request.
"""
def isKnownDevice(alias):
- for dev in self.conf['devices']:
- if dev.get('alias') == alias:
- return True
+ for devClass in self._devices:
+ for dev in devClass:
+ if (hasattr(dev, 'alias') and
+ getattr(dev, 'alias') == alias):
+
+ return True
return False
devsxml = _domParseStr(self._lastXMLDesc).childNodes[0]. \
@@ -4499,7 +4465,16 @@
'alias': alias,
'device': device,
'address': address}
- self.conf['devices'].append(newDev)
+
+ # lets find out which device we are dealing with
+ for devType, devClass in self.DeviceMapping:
+ if device == devType:
+ self._devices[devType].append(
+ devClass(self.conf, self.log, **newDev))
+ break
+
+ # TODO: here comes the problem: the can device not have the
+ # type at this point?
def _getUnderlyingControllerDeviceInfo(self):
"""
@@ -4521,6 +4496,7 @@
# Get controller address
address = self._getUnderlyingDeviceAddress(x)
+ knownDev = False
# In case the controller has index and/or model, they
# are compared. Currently relevant for USB controllers.
for ctrl in self._devices[CONTROLLER_DEVICES]:
@@ -4529,24 +4505,14 @@
(not hasattr(ctrl, 'model') or ctrl.model == model)):
ctrl.alias = alias
ctrl.address = 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
- (not 'index' in dev or dev['index'] == index) and
- (not 'model' in dev or dev['model'] == model)):
- dev['address'] = address
- dev['alias'] = 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})
+ self._devices[CONTROLLER_DEVICES].append(
+ ControllerDevice(self.conf, self.log,
+ type=CONTROLLER_DEVICES, device=device,
+ address=address, alias=alias))
def _getUnderlyingBalloonDeviceInfo(self):
"""
@@ -4569,13 +4535,6 @@
if not hasattr(dev, 'alias'):
dev.alias = alias
- for dev in self.conf['devices']:
- if dev['type'] == BALLOON_DEVICES:
- if address and not dev.get('address'):
- dev['address'] = address
- if not dev.get('alias'):
- dev['alias'] = alias
-
def _getUnderlyingConsoleDeviceInfo(self):
"""
Obtain the alias for the console device from libvirt
@@ -4586,14 +4545,10 @@
for x in consolexml:
# All we care about is the alias
alias = x.getElementsByTagName('alias')[0].getAttribute('name')
+
for dev in self._devices[CONSOLE_DEVICES]:
if not hasattr(dev, 'alias'):
dev.alias = alias
-
- for dev in self.conf['devices']:
- if dev['device'] == CONSOLE_DEVICES and \
- not dev.get('alias'):
- dev['alias'] = alias
def _getUnderlyingSmartcardDeviceInfo(self):
"""
@@ -4614,12 +4569,6 @@
dev.address = address
dev.alias = alias
- for dev in self.conf['devices']:
- if dev['device'] == SMARTCARD_DEVICES and \
- not dev.get('address'):
- dev['address'] = address
- dev['alias'] = alias
-
def _getUnderlyingWatchdogDeviceInfo(self):
"""
Obtain watchdog device info from libvirt.
@@ -4638,12 +4587,6 @@
if not hasattr(wd, 'address') or not hasattr(wd, 'alias'):
wd.address = address
wd.alias = alias
-
- for dev in self.conf['devices']:
- if ((dev['type'] == WATCHDOG_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
def _getUnderlyingVideoDeviceInfo(self):
"""
@@ -4665,13 +4608,6 @@
vc.alias = alias
vc.address = address
break
- # Update vm's conf with address
- for dev in self.conf['devices']:
- if ((dev['type'] == VIDEO_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
- break
def _getUnderlyingSoundDeviceInfo(self):
"""
@@ -4692,13 +4628,6 @@
if not hasattr(sc, 'address') or not hasattr(sc, 'alias'):
sc.alias = alias
sc.address = address
- break
- # Update vm's conf with address
- for dev in self.conf['devices']:
- if ((dev['type'] == SOUND_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
break
def _getUnderlyingDriveInfo(self):
@@ -4735,6 +4664,7 @@
# Get disk address
address = self._getUnderlyingDeviceAddress(x)
+ knownDev = False
for d in self._devices[DISK_DEVICES]:
if d.path == devPath:
d.name = name
@@ -4745,17 +4675,8 @@
d.readonly = readonly
if bootOrder:
d.bootOrder = bootOrder
- # Update vm's conf with address for known disk devices
- knownDev = False
- for dev in self.conf['devices']:
- if dev['type'] == DISK_DEVICES and dev['path'] == devPath:
- dev['name'] = name
- dev['address'] = address
- dev['alias'] = alias
- dev['readonly'] = str(readonly)
- if bootOrder:
- dev['bootOrder'] = bootOrder
knownDev = True
+
# Add unknown disk device to vm's conf
if not knownDev:
iface = 'ide' if address['type'] == 'drive' else 'pci'
@@ -4765,7 +4686,8 @@
'readonly': str(readonly)}
if bootOrder:
diskDev['bootOrder'] = bootOrder
- self.conf['devices'].append(diskDev)
+ self._devices[DISK_DEVICES].append(
+ Drive(self.conf, self.log, **diskDev))
def _getUnderlyingDisplayPort(self):
"""
@@ -4815,6 +4737,7 @@
network = source[0].getAttribute('network')
network = network[len(netinfo.LIBVIRT_NET_PREFIX):]
+ knownDev = False
# Get nic address
address = self._getUnderlyingDeviceAddress(x)
for nic in self._devices[NIC_DEVICES]:
@@ -4823,15 +4746,6 @@
nic.alias = alias
nic.address = address
nic.linkActive = linkActive
- # Update vm's conf with address for known nic devices
- knownDev = False
- for dev in self.conf['devices']:
- if (dev['type'] == NIC_DEVICES and
- dev['macAddr'].lower() == mac.lower()):
- dev['address'] = address
- dev['alias'] = alias
- dev['name'] = name
- dev['linkActive'] = linkActive
knownDev = True
# Add unknown nic device to vm's conf
if not knownDev:
@@ -4845,7 +4759,8 @@
'linkActive': linkActive}
if network:
nicDev['network'] = network
- self.conf['devices'].append(nicDev)
+ self._devices[DISK_DEVICES].append(
+ NetworkInterfaceDevice(self.conf, self.log, **nicDev))
def _setWriteWatermarks(self):
"""
--
To view, visit http://gerrit.ovirt.org/21162
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3bdb5c331657c1c0d1ae902eabb5d3315d45bf8b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Martin Polednik <mpoledni(a)redhat.com>
10 years
Change in vdsm[master]: multipath: Remove unused 'deduceType'
by ykaplan@redhat.com
Yeela Kaplan has uploaded a new change for review.
Change subject: multipath: Remove unused 'deduceType'
......................................................................
multipath: Remove unused 'deduceType'
Change-Id: I37a94c3d67641f1c78d8fbecd63cbf1480c6e1b0
Signed-off-by: Yeela Kaplan <ykaplan(a)redhat.com>
---
M vdsm/storage/multipath.py
1 file changed, 0 insertions(+), 7 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/63/13363/1
diff --git a/vdsm/storage/multipath.py b/vdsm/storage/multipath.py
index 94801ca..5fdaa27 100644
--- a/vdsm/storage/multipath.py
+++ b/vdsm/storage/multipath.py
@@ -184,13 +184,6 @@
raise se.MultipathRestartError()
-def deduceType(a, b):
- if a == b:
- return a
- else:
- return DEV_MIXED
-
-
def getDeviceBlockSizes(dev):
devName = os.path.basename(dev)
logical = int(file(os.path.join("/sys/block/", devName,
--
To view, visit http://gerrit.ovirt.org/13363
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I37a94c3d67641f1c78d8fbecd63cbf1480c6e1b0
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Yeela Kaplan <ykaplan(a)redhat.com>
10 years
Change in vdsm[master]: Adding monitorDomains.
by ewarszaw@redhat.com
Eduardo has uploaded a new change for review.
Change subject: Adding monitorDomains.
......................................................................
Adding monitorDomains.
Making repoStats pool independent.
Change-Id: I9f148764ac030730c93bfd9c8da25a7ea434dc33
Signed-off-by: Eduardo <ewarszaw(a)redhat.com>
---
M vdsm/storage/hsm.py
1 file changed, 19 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/74/14674/1
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index d3e1beb..3fb0c30 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -40,6 +40,7 @@
from vdsm.config import config
import sp
+import domainMonitor
import sd
import blockSD
import nfsSD
@@ -93,6 +94,7 @@
QEMU_READABLE_TIMEOUT = 30
+HSM_DOM_MON_LOCK = "HsmDomainMonitorLock"
def public(f=None, **kwargs):
if f is None:
@@ -395,6 +397,9 @@
name="storageRefresh")
storageRefreshThread.daemon = True
storageRefreshThread.start()
+
+ monitorInterval = config.getint('irs', 'sd_health_check_delay')
+ self.domainMonitor = domainMonitor.DomainMonitor(monitorInterval)
def _hsmSchedule(self, name, func, *args):
self.taskMng.scheduleJob("hsm", self.tasksDir, vars.task,
@@ -934,7 +939,10 @@
"spUUID=%s, msdUUID=%s, masterVersion=%s, hostID=%s, "
"scsiKey=%s" % (spUUID, msdUUID, masterVersion,
hostID, scsiKey)))
- return self._connectStoragePool(spUUID, hostID, scsiKey, msdUUID,
+ with rmanager.acquireResource(STORAGE, HSM_DOM_MON_LOCK,
+ rm.LockType.exclusive):
+ self.domainMonitor.close()
+ return self._connectStoragePool(spUUID, hostID, scsiKey, msdUUID,
masterVersion, options)
def _connectStoragePool(self, spUUID, hostID, scsiKey, msdUUID,
@@ -3578,3 +3586,13 @@
result[d] = repo_stats[d]['result']
return result
+
+ @public
+ def monitorDomains(self, sdUUIDs, hostID, options=None):
+ with rmanager.acquireResource(STORAGE, HSM_DOM_MON_LOCK,
+ rm.LockType.exclusive):
+ if self.pools:
+ raise se.StoragePoolConnected()
+ self.domainMonitor.close()
+ for sdUUID in sdUUIDs:
+ self.domainMonitor.startMonitoring(sdUUID, hostId)
--
To view, visit http://gerrit.ovirt.org/14674
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9f148764ac030730c93bfd9c8da25a7ea434dc33
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
10 years
Change in vdsm[master]: mount: Reassign mount specification in case of backup option
by ykaplan@redhat.com
Yeela Kaplan has uploaded a new change for review.
Change subject: mount: Reassign mount specification in case of backup option
......................................................................
mount: Reassign mount specification in case of backup option
When using glusterfs volumes the backup option
'backupvolfile-server' allows mount to an alternative volume
when mount source not available.
Change-Id: I3166c6863dffa297bc0adcdeb4c22f810d18de8e
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=922744
Signed-off-by: Yeela Kaplan <ykaplan(a)redhat.com>
---
M vdsm/storage/mount.py
M vdsm/storage/storageServer.py
2 files changed, 44 insertions(+), 20 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/34/16534/1
diff --git a/vdsm/storage/mount.py b/vdsm/storage/mount.py
index 90cacc7..8cade18 100644
--- a/vdsm/storage/mount.py
+++ b/vdsm/storage/mount.py
@@ -187,6 +187,15 @@
raise OSError(errno.ENOENT, 'device %s not mounted' % device)
+def _getRecord(spec, file):
+ for record in _iterMountRecords():
+ if (record.fs_spec == spec and record.fs_file == file):
+ return record
+
+ raise OSError(errno.ENOENT,
+ "Mount of `%s` at `%s` does not exist" % (spec, file))
+
+
class Mount(object):
def __init__(self, fs_spec, fs_file):
self.fs_spec = normpath(fs_spec)
@@ -261,14 +270,7 @@
return True
def getRecord(self):
- for record in _iterMountRecords():
- if (record.fs_spec == self.fs_spec and
- record.fs_file == self.fs_file):
- return record
-
- raise OSError(errno.ENOENT,
- "Mount of `%s` at `%s` does not exist" %
- (self.fs_spec, self.fs_file))
+ return _getRecord(self.fs_spec, self.fs_file)
def __repr__(self):
return ("<Mount fs_spec='%s' fs_file='%s'>" %
diff --git a/vdsm/storage/storageServer.py b/vdsm/storage/storageServer.py
index 023f607..515ebd9 100644
--- a/vdsm/storage/storageServer.py
+++ b/vdsm/storage/storageServer.py
@@ -197,14 +197,14 @@
self._remotePath.replace("_",
"__").replace("/", "_"))
- def connect(self):
+ def createConnection(self):
if self._mount.isMounted():
return
fileUtils.createdir(self._getLocalPath())
try:
- self._mount.mount(self.options, self._vfsType)
+ self._mount.mount(self.options, self.vfsType)
except MountError as e:
self.log.error("Mount failed: %s", e, exc_info=True)
try:
@@ -214,17 +214,21 @@
self._getLocalPath(), exc_info=True)
raise e
- else:
+ def validateConnection(self):
+ try:
+ fileSD.validateDirAccess(
+ self.getMountObj().getRecord().fs_file)
+ except se.StorageServerAccessPermissionError as e:
try:
- fileSD.validateDirAccess(
- self.getMountObj().getRecord().fs_file)
- except se.StorageServerAccessPermissionError as e:
- try:
- self.disconnect()
- except OSError:
- self.log.warn("Error while disconnecting after access"
- "problem", exc_info=True)
- raise e
+ self.disconnect()
+ except OSError:
+ self.log.warn("Error while disconnecting after access"
+ "problem", exc_info=True)
+ raise e
+
+ def connect(self):
+ self.createConnection()
+ self.validateConnection()
def isConnected(self):
return self._mount.isMounted()
@@ -255,6 +259,24 @@
def getLocalPathBase(cls):
return os.path.join(MountConnection.getLocalPathBase(), "glusterSD")
+ def updateBackup(self):
+ if self.options and not self.isConnected():
+ for opt in self.options.split(','):
+ if opt.strip().startswith("backupvolfile-server"):
+ backupSpec = opt.split('=', 1)[1].strip()
+ try:
+ mount._getRecord(backupSpec, self._mount.fs_file)
+ except OSError as e:
+ self.log.warning("Mount of backup failed: %s", e)
+ else:
+ self._mount.fs_spec = backupSpec
+ return
+
+ def connect(self):
+ self.createConnection()
+ self.updateBackup()
+ self.validateConnection()
+
class NFSConnection(object):
DEFAULT_OPTIONS = ["soft", "nosharecache"]
--
To view, visit http://gerrit.ovirt.org/16534
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3166c6863dffa297bc0adcdeb4c22f810d18de8e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Yeela Kaplan <ykaplan(a)redhat.com>
10 years
Change in vdsm[master]: More precise exception when multipath failed.
by ewarszaw@redhat.com
Eduardo has uploaded a new change for review.
Change subject: More precise exception when multipath failed.
......................................................................
More precise exception when multipath failed.
In spite that any OSError is translated to ENODEV in devicemapper,
the complete info is needed.
Related to BZ#965184.
Change-Id: I1b87e8e91b838db2c8a98c9afbbc998e8f4c792a
Signed-off-by: Eduardo <ewarszaw(a)redhat.com>
---
M vdsm/storage/devicemapper.py
1 file changed, 4 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/45/17145/1
diff --git a/vdsm/storage/devicemapper.py b/vdsm/storage/devicemapper.py
index 451c736..ff1fb7a 100644
--- a/vdsm/storage/devicemapper.py
+++ b/vdsm/storage/devicemapper.py
@@ -34,11 +34,10 @@
devlinkPath = DMPATH_FORMAT % deviceMultipathName
try:
devStat = os.stat(devlinkPath)
- except OSError:
- raise OSError(errno.ENODEV, "Could not find dm device named `%s`" %
- deviceMultipathName)
-
- return "dm-%d" % os.minor(devStat.st_rdev)
+ except OSError as e:
+ raise OSError(errno.ENODEV, "%s: %s" % (deviceMultipathName, e))
+ else:
+ return "dm-%d" % os.minor(devStat.st_rdev)
def findDev(major, minor):
--
To view, visit http://gerrit.ovirt.org/17145
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1b87e8e91b838db2c8a98c9afbbc998e8f4c792a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
10 years
Change in vdsm[master]: Avoid hsm image deletions.
by ewarszaw@redhat.com
Eduardo has uploaded a new change for review.
Change subject: Avoid hsm image deletions.
......................................................................
Avoid hsm image deletions.
This code was introduced to fix BZ#560389.
The bug was in Image.delete() which was already removed.
Related to BZ#965184.
Change-Id: Ie1ec2ea8793a4ad63453559bc5f663b65f9b9336
Signed-off-by: Eduardo <ewarszaw(a)redhat.com>
---
M vdsm/storage/blockSD.py
M vdsm/storage/fileSD.py
M vdsm/storage/sd.py
3 files changed, 0 insertions(+), 24 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/93/17193/1
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py
index 72b3ef0..6507cbf 100644
--- a/vdsm/storage/blockSD.py
+++ b/vdsm/storage/blockSD.py
@@ -416,7 +416,6 @@
# _extendlock is used to prevent race between
# VG extend and LV extend.
self._extendlock = threading.Lock()
- self.imageGarbageCollector()
self._registerResourceNamespaces()
self._lastUncachedSelftest = 0
diff --git a/vdsm/storage/fileSD.py b/vdsm/storage/fileSD.py
index 1651825..0042aab 100644
--- a/vdsm/storage/fileSD.py
+++ b/vdsm/storage/fileSD.py
@@ -165,7 +165,6 @@
if not self.oop.fileUtils.pathExists(self.metafile):
raise se.StorageDomainMetadataNotFound(sdUUID, self.metafile)
- self.imageGarbageCollector()
self._registerResourceNamespaces()
@property
@@ -515,20 +514,6 @@
mount.getMountFromTarget(self.mountpoint).umount()
raise se.FileStorageDomainStaleNFSHandle()
raise
-
- def imageGarbageCollector(self):
- """
- Image Garbage Collector
- remove the remnants of the removed images (they could be left sometimes
- (on NFS mostly) due to lazy file removal
- """
- removedPattern = os.path.join(self.domaindir, sd.DOMAIN_IMAGES,
- sd.REMOVED_IMAGE_PREFIX + '*')
- removedImages = self.oop.glob.glob(removedPattern)
- self.log.debug("Removing remnants of deleted images %s" %
- removedImages)
- for imageDir in removedImages:
- self.oop.fileUtils.cleanupdir(imageDir)
def templateRelink(self, imgUUID, volUUID):
"""
diff --git a/vdsm/storage/sd.py b/vdsm/storage/sd.py
index fd79059..c764d2d 100644
--- a/vdsm/storage/sd.py
+++ b/vdsm/storage/sd.py
@@ -786,11 +786,3 @@
def isData(self):
return self.getMetaParam(DMDK_CLASS) == DATA_DOMAIN
-
- def imageGarbageCollector(self):
- """
- Image Garbage Collector
- remove the remnants of the removed images (they could be left sometimes
- (on NFS mostly) due to lazy file removal
- """
- pass
--
To view, visit http://gerrit.ovirt.org/17193
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie1ec2ea8793a4ad63453559bc5f663b65f9b9336
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
10 years
Change in vdsm[master]: Refactor StoragePool.getPoolParams()
by ewarszaw@redhat.com
Eduardo has uploaded a new change for review.
Change subject: Refactor StoragePool.getPoolParams()
......................................................................
Refactor StoragePool.getPoolParams()
Change-Id: Ibbeaaaf67a39f3ca8b27252fc631a91f266d1adc
Signed-off-by: Eduardo <ewarszaw(a)redhat.com>
---
M vdsm/storage/sp.py
1 file changed, 4 insertions(+), 15 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/32/19232/1
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index 38eda39..d5a8b4e 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -734,21 +734,10 @@
@unsecured
def getPoolParams(self):
- file = open(self._poolFile, "r")
- for line in file:
- pair = line.strip().split("=")
- if len(pair) == 2:
- if pair[0] == "id":
- hostId = int(pair[1])
- elif pair[0] == "scsiKey":
- scsiKey = pair[1]
- elif pair[0] == "sdUUID":
- msdUUID = pair[1]
- elif pair[0] == "version":
- masterVersion = pair[1]
- file.close()
-
- return hostId, scsiKey, msdUUID, masterVersion
+ lines = open(self._poolFile, "r").readlines()
+ params = dict(line.strip().split('=') for line in lines if '=' in line)
+ return tuple(params[k] for k in ('hostId', 'scsiKey', 'msdUUID',
+ 'masterVersion'))
@unsecured
def createMaster(self, poolName, domain, masterVersion, leaseParams):
--
To view, visit http://gerrit.ovirt.org/19232
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibbeaaaf67a39f3ca8b27252fc631a91f266d1adc
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
10 years
Change in vdsm[master]: vdsm: Get underlying device info moved to Device classes
by Vinzenz Feenstra
Vinzenz Feenstra has uploaded a new change for review.
Change subject: vdsm: Get underlying device info moved to Device classes
......................................................................
vdsm: Get underlying device info moved to Device classes
Change-Id: I8f797baece3601b885777784f611b420523828f7
Signed-off-by: Vinzenz Feenstra <vfeenstr(a)redhat.com>
---
M vdsm/vm.py
1 file changed, 379 insertions(+), 396 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/32/19732/1
diff --git a/vdsm/vm.py b/vdsm/vm.py
index 4f2f35d..d23cd21 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -1196,6 +1196,98 @@
element.setAttrs(**elemAttrs)
return element
+ @classmethod
+ def _getDeviceAlias(cls, device):
+ return device.getElementsByTagName('alias')[0].getAttribute('name')
+
+ @classmethod
+ def _getDeviceAddress(cls, device):
+ """
+ Obtain device's address from libvirt
+ """
+ address = {}
+ dom = device.getElementsByTagName('address')[0]
+ # Parse address to create proper dictionary.
+ # Libvirt device's address definition is:
+ # PCI = {'type':'pci', 'domain':'0x0000', 'bus':'0x00',
+ # 'slot':'0x0c', 'function':'0x0'}
+ # IDE = {'type':'drive', 'controller':'0', 'bus':'0', 'unit':'0'}
+ for key in dom.attributes.keys():
+ address[key.strip()] = dom.getAttribute(key).strip()
+
+ return address
+
+ @classmethod
+ def _defaultUpdate(cls, element, type, desc, devices, conf, **kwargs):
+ getAddress = kwargs.get('address', True)
+ getAddressRequired = False
+ if 'getAddressRequired' in kwargs:
+ getAddressRequired = kwargs.get('aliasRequired')
+ getAddress = getAddressRequired
+
+ default = desc.getElementsByTagName(element)
+ for x in default:
+ if getAddressRequired:
+ if not x.getElementsByTagName('address'):
+ continue
+
+ address = None
+ if getAddress:
+ address = cls._getDeviceAddress(x)
+
+ alias = cls._getDeviceAliasName(x)
+
+ for x in devices[type]:
+ if address and not hasattr(x, 'address'):
+ x.address = address
+ if alias and not hasattr(x, 'alias'):
+ x.alias = alias
+
+ for dev in conf['devices']:
+ if dev['type'] == type:
+ if address and not dev.get('address'):
+ dev['address'] = address
+ if alias and not dev.get('alias'):
+ dev['alias'] = alias
+
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ pass
+
+
+class UnknownDevice(VmDevice):
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain unknown devices info from libvirt.
+
+ Unknown device is a device that has an address but wasn't
+ passed during VM creation request.
+ """
+ def isKnownDevice(alias):
+ for dev in conf['devices']:
+ if dev.get('alias') == alias:
+ return True
+ return False
+
+ for x in desc.childNodes:
+ # Ignore empty nodes and devices without address
+ if (x.nodeName == '#text' or
+ not x.getElementsByTagName('address')):
+ continue
+
+ alias = cls._getDeviceAliasName(x)
+ if not isKnownDevice(alias):
+ address = cls._getDeviceAddress(x)
+ # I general case we assume that device has attribute 'type',
+ # if it hasn't getAttribute returns ''.
+ device = x.getAttribute('type')
+ newDev = {'type': x.nodeName,
+ 'alias': alias,
+ 'device': device,
+ 'address': address}
+ conf['devices'].append(newDev)
+
class GeneralDevice(VmDevice):
@@ -1219,6 +1311,52 @@
return ctrl
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain controller devices info from libvirt.
+ """
+ controllers = desc.getElementsByTagName('controller')
+ for x in controllers:
+ # Ignore controller devices without address
+ if not x.getElementsByTagName('address'):
+ continue
+ alias = cls._getDeviceAliasName(x)
+ device = x.getAttribute('type')
+ # Get model and index. Relevant for USB controllers.
+ model = x.getAttribute('model')
+ index = x.getAttribute('index')
+
+ # Get controller address
+ address = cls._getDeviceAddress(x)
+
+ # In case the controller has index and/or model, they
+ # are compared. Currently relevant for USB controllers.
+ for ctrl in 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
+ # 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 conf['devices']:
+ if ((dev['type'] == CONTROLLER_DEVICES) and
+ (dev['device'] == device) and
+ (not 'index' in dev or dev['index'] == index) and
+ (not 'model' in dev or dev['model'] == model)):
+ dev['address'] = address
+ dev['alias'] = alias
+ knownDev = True
+ # Add unknown controller device to vm's conf
+ if not knownDev:
+ conf['devices'].append({'type': CONTROLLER_DEVICES,
+ 'device': device,
+ 'address': address,
+ 'alias': alias})
+
class VideoDevice(VmDevice):
@@ -1235,6 +1373,34 @@
video.appendChildWithArgs('model', type=self.device, **sourceAttrs)
return video
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain video devices info from libvirt.
+ """
+ videos = desc.getElementsByTagName('video')
+ for x in videos:
+ alias = cls._getDeviceAliasName(x)
+ # Get video card address
+ address = cls._getDeviceAddress(x)
+
+ # FIXME. We have an identification problem here.
+ # Video card device has not unique identifier, except the alias
+ # (but backend not aware to device's aliases). So, for now
+ # we can only assign the address according to devices order.
+ for vc in devices[VIDEO_DEVICES]:
+ if not hasattr(vc, 'address') or not hasattr(vc, 'alias'):
+ vc.alias = alias
+ vc.address = address
+ break
+ # Update vm's conf with address
+ for dev in conf['devices']:
+ if ((dev['type'] == VIDEO_DEVICES) and
+ (not dev.get('address') or not dev.get('alias'))):
+ dev['address'] = address
+ dev['alias'] = alias
+ break
+
class SoundDevice(VmDevice):
@@ -1245,6 +1411,34 @@
sound = self.createXmlElem('sound', None, ['address'])
sound.setAttrs(model=self.device)
return sound
+
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain sound devices info from libvirt.
+ """
+ soundDevices = desc.getElementsByTagName('sound')
+ for x in soundDevices:
+ alias = cls._getDeviceAliasName(x)
+ # Get sound card address
+ address = cls._getDeviceAddress(x)
+
+ # FIXME. We have an identification problem here.
+ # Sound device has not unique identifier, except the alias
+ # (but backend not aware to device's aliases). So, for now
+ # we can only assign the address according to devices order.
+ for sc in devices[SOUND_DEVICES]:
+ if not hasattr(sc, 'address') or not hasattr(sc, 'alias'):
+ sc.alias = alias
+ sc.address = address
+ break
+ # Update vm's conf with address
+ for dev in conf['devices']:
+ if ((dev['type'] == SOUND_DEVICES) and
+ (not dev.get('address') or not dev.get('alias'))):
+ dev['address'] = address
+ dev['alias'] = alias
+ break
class NetworkInterfaceDevice(VmDevice):
@@ -1337,6 +1531,73 @@
bandwidth.appendChildWithArgs('outbound', **outbound)
iface.appendChild(bandwidth)
return iface
+
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain network interface info from libvirt.
+ """
+ # TODO use xpath instead of parseString (here and elsewhere)
+ interfaces = desc.getElementsByTagName('interface')
+ for x in interfaces:
+ devType = x.getAttribute('type')
+ mac = x.getElementsByTagName('mac')[0].getAttribute('address')
+ alias = cls._getDeviceAliasName(x)
+ if devType == 'hostdev':
+ name = alias
+ model = 'passthrough'
+ else:
+ name = x.getElementsByTagName('target')[0].getAttribute('dev')
+ model = x.getElementsByTagName('model')[0].getAttribute('type')
+
+ network = None
+ try:
+ if x.getElementsByTagName('link')[0].getAttribute('state') == \
+ 'down':
+ linkActive = False
+ else:
+ linkActive = True
+ except IndexError:
+ linkActive = True
+ source = x.getElementsByTagName('source')
+ if source:
+ network = source[0].getAttribute('bridge')
+ if not network:
+ network = source[0].getAttribute('network')
+ network = network[len(netinfo.LIBVIRT_NET_PREFIX):]
+
+ # Get nic address
+ address = cls._getDeviceAddress(x)
+ for nic in devices[NIC_DEVICES]:
+ if nic.macAddr.lower() == mac.lower():
+ nic.name = name
+ nic.alias = alias
+ nic.address = address
+ nic.linkActive = linkActive
+ # Update vm's conf with address for known nic devices
+ knownDev = False
+ for dev in conf['devices']:
+ if (dev['type'] == NIC_DEVICES and
+ dev['macAddr'].lower() == mac.lower()):
+ dev['address'] = address
+ dev['alias'] = alias
+ dev['name'] = name
+ dev['linkActive'] = linkActive
+ knownDev = True
+ # Add unknown nic device to vm's conf
+ if not knownDev:
+ nicDev = {'type': NIC_DEVICES,
+ 'device': devType,
+ 'macAddr': mac,
+ 'nicModel': model,
+ 'address': address,
+ 'alias': alias,
+ 'name': name,
+ 'linkActive': linkActive}
+ if network:
+ nicDev['network'] = network
+ conf['devices'].append(nicDev)
+
class Drive(VmDevice):
@@ -1625,6 +1886,71 @@
return diskelem
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain block devices info from libvirt.
+ """
+ disks = desc.getElementsByTagName('disk')
+ # FIXME! We need to gather as much info as possible from the libvirt.
+ # In the future we can return this real data to management instead of
+ # vm's conf
+ for x in disks:
+ sources = x.getElementsByTagName('source')
+ if sources:
+ devPath = (sources[0].getAttribute('file') or
+ sources[0].getAttribute('dev'))
+ else:
+ devPath = ''
+
+ target = x.getElementsByTagName('target')
+ name = target[0].getAttribute('dev') if target else ''
+ alias = cls._getDeviceAliasName(x)
+ readonly = bool(x.getElementsByTagName('readonly'))
+ boot = x.getElementsByTagName('boot')
+ bootOrder = boot[0].getAttribute('order') if boot else ''
+
+ devType = x.getAttribute('device')
+ if devType == 'disk':
+ # raw/qcow2
+ drv = x.getElementsByTagName('driver')[0].getAttribute('type')
+ else:
+ drv = 'raw'
+ # Get disk address
+ address = cls._getDeviceAddress(x)
+
+ for d in devices[DISK_DEVICES]:
+ if d.path == devPath:
+ d.name = name
+ d.type = devType
+ d.drv = drv
+ d.alias = alias
+ d.address = address
+ d.readonly = readonly
+ if bootOrder:
+ d.bootOrder = bootOrder
+ # Update vm's conf with address for known disk devices
+ knownDev = False
+ for dev in conf['devices']:
+ if dev['type'] == DISK_DEVICES and dev['path'] == devPath:
+ dev['name'] = name
+ dev['address'] = address
+ dev['alias'] = alias
+ dev['readonly'] = str(readonly)
+ if bootOrder:
+ dev['bootOrder'] = bootOrder
+ knownDev = True
+ # Add unknown disk device to vm's conf
+ if not knownDev:
+ iface = 'ide' if address['type'] == 'drive' else 'pci'
+ diskDev = {'type': DISK_DEVICES, 'device': devType,
+ 'iface': iface, 'path': devPath, 'name': name,
+ 'address': address, 'alias': alias,
+ 'readonly': str(readonly)}
+ if bootOrder:
+ diskDev['bootOrder'] = bootOrder
+ conf['devices'].append(diskDev)
+
class BalloonDevice(VmDevice):
@@ -1640,6 +1966,15 @@
m = self.createXmlElem(self.device, None, ['address'])
m.setAttrs(model=self.specParams['model'])
return m
+
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain balloon device info from libvirt.
+ """
+ balloon = desc.getElementsByTagName('memballoon')
+ cls._defaultUpdate('watchdog', WATCHDOG_DEVICES, desc, devices, conf,
+ addressRequired=False)
class WatchdogDevice(VmDevice):
@@ -1657,6 +1992,14 @@
action=self.specParams['action'])
return m
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain watchdog device info from libvirt.
+ """
+ cls._defaultUpdate('watchdog', WATCHDOG_DEVICES, desc, devices, conf,
+ addressRequired=True)
+
class SmartCardDevice(VmDevice):
def getXML(self):
@@ -1673,6 +2016,13 @@
sourceAttrs['type'] = self.specParams['type']
card.setAttrs(**sourceAttrs)
return card
+
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain smartcard device info from libvirt.
+ """
+ cls._defaultUpdate('smartcard', SMARTCARD_DEVICES, desc, devices, conf)
class RedirDevice(VmDevice):
@@ -1700,6 +2050,13 @@
m.appendChildWithArgs('target', type='virtio', port='0')
return m
+ @classmethod
+ def updateFromDesc(cls, desc, devices, conf):
+ """
+ Obtain the alias for the console device from libvirt
+ """
+ cls._defaultUpdate('console', CONSOLE_DEVICES, desc, devices, conf,
+ address=False)
class Vm(object):
"""
@@ -1713,6 +2070,18 @@
# limit threads number until the libvirt lock will be fixed
_ongoingCreations = threading.BoundedSemaphore(4)
MigrationSourceThreadClass = MigrationSourceThread
+ DeviceMapping = ((DISK_DEVICES, Drive),
+ (NIC_DEVICES, NetworkInterfaceDevice),
+ (SOUND_DEVICES, SoundDevice),
+ (VIDEO_DEVICES, VideoDevice),
+ (CONTROLLER_DEVICES, ControllerDevice),
+ (GENERAL_DEVICES, GeneralDevice),
+ (BALLOON_DEVICES, BalloonDevice),
+ (WATCHDOG_DEVICES, WatchdogDevice),
+ (CONSOLE_DEVICES, ConsoleDevice),
+ (REDIR_DEVICES, RedirDevice),
+ (SMARTCARD_DEVICES, SmartCardDevice))
+
def _makeChannelPath(self, deviceName):
return constants.P_LIBVIRT_VMCHANNELS + self.id + '.' + deviceName
@@ -2747,7 +3116,7 @@
self._qemuguestSocketFile.decode('utf-8'),
_QEMU_GA_DEVICE_NAME)
domxml.appendInput()
- domxml.appendGraphics()
+ domxml.appendGraphics()
self._appendDevices(domxml)
@@ -2785,19 +3154,12 @@
Obtain underlying vm's devices info from libvirt.
"""
devicesXml = self._getDevicesXml()
- self._getUnderlyingNetworkInterfaceInfo(devicesXml=devicesXml)
- self._getUnderlyingDriveInfo(devicesXml=devicesXml)
+ for _, cls in self.DeviceMapping:
+ cls.updateFromDesc(devicesXml, self._devices, self.conf)
self._getUnderlyingDisplayPort(xml=self._lastXMLDesc.dom())
- self._getUnderlyingSoundDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingVideoDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingControllerDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingBalloonDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingWatchdogDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingSmartcardDeviceInfo(devicesXml=devicesXml)
- self._getUnderlyingConsoleDeviceInfo(devicesXml=devicesXml)
self._updateAgentChannels(devicesXml=devicesXml)
# Obtain info of all unknown devices. Must be last!
- self._getUnderlyingUnknownDeviceInfo(devicesXml=devicesXml)
+ UnknownDevice.updateFromDesc(devicesXml, self._devices, self.conf)
def _updateAgentChannels(self, devicesXml):
"""
@@ -2914,19 +3276,7 @@
else:
devices = self.getConfDevices()
- devMap = {DISK_DEVICES: Drive,
- NIC_DEVICES: NetworkInterfaceDevice,
- SOUND_DEVICES: SoundDevice,
- VIDEO_DEVICES: VideoDevice,
- CONTROLLER_DEVICES: ControllerDevice,
- GENERAL_DEVICES: GeneralDevice,
- BALLOON_DEVICES: BalloonDevice,
- WATCHDOG_DEVICES: WatchdogDevice,
- REDIR_DEVICES: RedirDevice,
- CONSOLE_DEVICES: ConsoleDevice,
- SMARTCARD_DEVICES: SmartCardDevice}
-
- for devType, devClass in devMap.items():
+ for devType, devClass in self.DeviceMapping:
for dev in devices[devType]:
self._devices[devType].append(devClass(self.conf, self.log,
**dev))
@@ -3066,10 +3416,9 @@
with self._confLock:
self.conf['devices'].append(nicParams)
self.saveState()
- self._getUnderlyingNetworkInterfaceInfo(
- devicesXml=self._getDevicesXml())
- hooks.after_nic_hotplug(nicXml, self.conf,
- params=customProps)
+ NetworkInterfaceDevice.updateFromDesc(self._getDevicesXml(),
+ self._devices, self.conf)
+ hooks.after_nic_hotplug(nicXml, self.conf, params=customProps)
if hasattr(nic, 'portMirroring'):
mirroredNetworks = []
@@ -3327,7 +3676,8 @@
with self._confLock:
self.conf['devices'].append(diskParams)
self.saveState()
- self._getUnderlyingDriveInfo(devicesXml=self._getDevicesXml())
+ Drive.updateFromDesc(self._getDevicesXml(), self._devices,
+ self.conf)
hooks.after_disk_hotplug(driveXml, self.conf,
params=customProps)
@@ -4397,308 +4747,6 @@
self.saveState()
return {'status': doneCode}
- def _getUnderlyingDeviceAliasName(self, devXml):
- return devXml.getElementsByTagName('alias')[0].getAttribute('name')
-
- def _getUnderlyingDeviceAddress(self, devXml):
- """
- Obtain device's address from libvirt
- """
- address = {}
- adrXml = devXml.getElementsByTagName('address')[0]
- # Parse address to create proper dictionary.
- # Libvirt device's address definition is:
- # PCI = {'type':'pci', 'domain':'0x0000', 'bus':'0x00',
- # 'slot':'0x0c', 'function':'0x0'}
- # IDE = {'type':'drive', 'controller':'0', 'bus':'0', 'unit':'0'}
- for key in adrXml.attributes.keys():
- address[key.strip()] = adrXml.getAttribute(key).strip()
-
- return address
-
- def _getUnderlyingUnknownDeviceInfo(self, devicesXml):
- """
- Obtain unknown devices info from libvirt.
-
- Unknown device is a device that has an address but wasn't
- passed during VM creation request.
- """
- def isKnownDevice(alias):
- for dev in self.conf['devices']:
- if dev.get('alias') == alias:
- return True
- return False
-
- for x in devicesXml.childNodes:
- # Ignore empty nodes and devices without address
- if (x.nodeName == '#text' or
- not x.getElementsByTagName('address')):
- continue
-
- alias = self._getUnderlyingDeviceAliasName(x)
- if not isKnownDevice(alias):
- address = self._getUnderlyingDeviceAddress(x)
- # I general case we assume that device has attribute 'type',
- # if it hasn't getAttribute returns ''.
- device = x.getAttribute('type')
- newDev = {'type': x.nodeName,
- 'alias': alias,
- 'device': device,
- 'address': address}
- self.conf['devices'].append(newDev)
-
- def _getUnderlyingControllerDeviceInfo(self, devicesXml):
- """
- Obtain controller devices info from libvirt.
- """
- ctrlsxml = devicesXml.getElementsByTagName('controller')
- for x in ctrlsxml:
- # Ignore controller devices without address
- if not x.getElementsByTagName('address'):
- continue
- alias = self._getUnderlyingDeviceAliasName(x)
- device = x.getAttribute('type')
- # Get model and index. Relevant for USB controllers.
- model = x.getAttribute('model')
- index = x.getAttribute('index')
-
- # Get controller address
- address = self._getUnderlyingDeviceAddress(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
- # 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
- (not 'index' in dev or dev['index'] == index) and
- (not 'model' in dev or dev['model'] == model)):
- dev['address'] = address
- dev['alias'] = 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})
-
- def _getUnderlyingBalloonDeviceInfo(self, devicesXml):
- """
- Obtain balloon device info from libvirt.
- """
- balloonxml = devicesXml.getElementsByTagName('memballoon')
- for x in balloonxml:
- # Ignore balloon devices without address.
- if not x.getElementsByTagName('address'):
- address = None
- else:
- address = self._getUnderlyingDeviceAddress(x)
- alias = self._getUnderlyingDeviceAliasName(x)
-
- for dev in self._devices[BALLOON_DEVICES]:
- if address and not hasattr(dev, 'address'):
- dev.address = address
- if not hasattr(dev, 'alias'):
- dev.alias = alias
-
- for dev in self.conf['devices']:
- if dev['type'] == BALLOON_DEVICES:
- if address and not dev.get('address'):
- dev['address'] = address
- if not dev.get('alias'):
- dev['alias'] = alias
-
- def _getUnderlyingConsoleDeviceInfo(self, devicesXml):
- """
- Obtain the alias for the console device from libvirt
- """
- consolexml = devicesXml.getElementsByTagName('console')
- for x in consolexml:
- # All we care about is the alias
- alias = self._getUnderlyingDeviceAliasName(x)
- for dev in self._devices[CONSOLE_DEVICES]:
- if not hasattr(dev, 'alias'):
- dev.alias = alias
-
- for dev in self.conf['devices']:
- if dev['device'] == CONSOLE_DEVICES and \
- not dev.get('alias'):
- dev['alias'] = alias
-
- def _getUnderlyingSmartcardDeviceInfo(self, devicesXml):
- """
- Obtain smartcard device info from libvirt.
- """
- smartcardxml = devicesXml.getElementsByTagName('smartcard')
- for x in smartcardxml:
- if not x.getElementsByTagName('address'):
- continue
-
- address = self._getUnderlyingDeviceAddress(x)
- alias = self._getUnderlyingDeviceAliasName(x)
-
- for dev in self._devices[SMARTCARD_DEVICES]:
- if not hasattr(dev, 'address'):
- dev.address = address
- dev.alias = alias
-
- for dev in self.conf['devices']:
- if dev['device'] == SMARTCARD_DEVICES and \
- not dev.get('address'):
- dev['address'] = address
- dev['alias'] = alias
-
- def _getUnderlyingWatchdogDeviceInfo(self, devicesXml):
- """
- Obtain watchdog device info from libvirt.
- """
- watchdogxml = devicesXml.getElementsByTagName('watchdog')
- for x in watchdogxml:
-
- # PCI watchdog has "address" different from ISA watchdog
- if x.getElementsByTagName('address'):
- address = self._getUnderlyingDeviceAddress(x)
- alias = self._getUnderlyingDeviceAliasName(x)
-
- for wd in self._devices[WATCHDOG_DEVICES]:
- if not hasattr(wd, 'address') or not hasattr(wd, 'alias'):
- wd.address = address
- wd.alias = alias
-
- for dev in self.conf['devices']:
- if ((dev['type'] == WATCHDOG_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
-
- def _getUnderlyingVideoDeviceInfo(self, devicesXml):
- """
- Obtain video devices info from libvirt.
- """
- videosxml = devicesXml.getElementsByTagName('video')
- for x in videosxml:
- alias = self._getUnderlyingDeviceAliasName(x)
- # Get video card address
- address = self._getUnderlyingDeviceAddress(x)
-
- # FIXME. We have an identification problem here.
- # Video card device has not unique identifier, except the alias
- # (but backend not aware to device's aliases). So, for now
- # we can only assign the address according to devices order.
- for vc in self._devices[VIDEO_DEVICES]:
- if not hasattr(vc, 'address') or not hasattr(vc, 'alias'):
- vc.alias = alias
- vc.address = address
- break
- # Update vm's conf with address
- for dev in self.conf['devices']:
- if ((dev['type'] == VIDEO_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
- break
-
- def _getUnderlyingSoundDeviceInfo(self, devicesXml):
- """
- Obtain sound devices info from libvirt.
- """
- soundsxml = devicesXml.getElementsByTagName('sound')
- for x in soundsxml:
- alias = self._getUnderlyingDeviceAliasName(x)
- # Get sound card address
- address = self._getUnderlyingDeviceAddress(x)
-
- # FIXME. We have an identification problem here.
- # Sound device has not unique identifier, except the alias
- # (but backend not aware to device's aliases). So, for now
- # we can only assign the address according to devices order.
- for sc in self._devices[SOUND_DEVICES]:
- if not hasattr(sc, 'address') or not hasattr(sc, 'alias'):
- sc.alias = alias
- sc.address = address
- break
- # Update vm's conf with address
- for dev in self.conf['devices']:
- if ((dev['type'] == SOUND_DEVICES) and
- (not dev.get('address') or not dev.get('alias'))):
- dev['address'] = address
- dev['alias'] = alias
- break
-
- def _getUnderlyingDriveInfo(self, devicesXml):
- """
- Obtain block devices info from libvirt.
- """
- disksxml = devicesXml.getElementsByTagName('disk')
- # FIXME! We need to gather as much info as possible from the libvirt.
- # In the future we can return this real data to management instead of
- # vm's conf
- for x in disksxml:
- sources = x.getElementsByTagName('source')
- if sources:
- devPath = (sources[0].getAttribute('file') or
- sources[0].getAttribute('dev'))
- else:
- devPath = ''
-
- target = x.getElementsByTagName('target')
- name = target[0].getAttribute('dev') if target else ''
- alias = self._getUnderlyingDeviceAliasName(x)
- readonly = bool(x.getElementsByTagName('readonly'))
- boot = x.getElementsByTagName('boot')
- bootOrder = boot[0].getAttribute('order') if boot else ''
-
- devType = x.getAttribute('device')
- if devType == 'disk':
- # raw/qcow2
- drv = x.getElementsByTagName('driver')[0].getAttribute('type')
- else:
- drv = 'raw'
- # Get disk address
- address = self._getUnderlyingDeviceAddress(x)
-
- for d in self._devices[DISK_DEVICES]:
- if d.path == devPath:
- d.name = name
- d.type = devType
- d.drv = drv
- d.alias = alias
- d.address = address
- d.readonly = readonly
- if bootOrder:
- d.bootOrder = bootOrder
- # Update vm's conf with address for known disk devices
- knownDev = False
- for dev in self.conf['devices']:
- if dev['type'] == DISK_DEVICES and dev['path'] == devPath:
- dev['name'] = name
- dev['address'] = address
- dev['alias'] = alias
- dev['readonly'] = str(readonly)
- if bootOrder:
- dev['bootOrder'] = bootOrder
- knownDev = True
- # Add unknown disk device to vm's conf
- if not knownDev:
- iface = 'ide' if address['type'] == 'drive' else 'pci'
- diskDev = {'type': DISK_DEVICES, 'device': devType,
- 'iface': iface, 'path': devPath, 'name': name,
- 'address': address, 'alias': alias,
- 'readonly': str(readonly)}
- if bootOrder:
- diskDev['bootOrder'] = bootOrder
- self.conf['devices'].append(diskDev)
-
def _getUnderlyingDisplayPort(self, xml):
"""
Obtain display port info from libvirt.
@@ -4710,71 +4758,6 @@
port = graphics.getAttribute('tlsPort')
if port:
self.conf['displaySecurePort'] = port
-
- def _getUnderlyingNetworkInterfaceInfo(self, devicesXml):
- """
- Obtain network interface info from libvirt.
- """
- # TODO use xpath instead of parseString (here and elsewhere)
- ifsxml = devicesXml.getElementsByTagName('interface')
- for x in ifsxml:
- devType = x.getAttribute('type')
- mac = x.getElementsByTagName('mac')[0].getAttribute('address')
- alias = self._getUnderlyingDeviceAliasName(x)
- if devType == 'hostdev':
- name = alias
- model = 'passthrough'
- else:
- name = x.getElementsByTagName('target')[0].getAttribute('dev')
- model = x.getElementsByTagName('model')[0].getAttribute('type')
-
- network = None
- try:
- if x.getElementsByTagName('link')[0].getAttribute('state') == \
- 'down':
- linkActive = False
- else:
- linkActive = True
- except IndexError:
- linkActive = True
- source = x.getElementsByTagName('source')
- if source:
- network = source[0].getAttribute('bridge')
- if not network:
- network = source[0].getAttribute('network')
- network = network[len(netinfo.LIBVIRT_NET_PREFIX):]
-
- # Get nic address
- address = self._getUnderlyingDeviceAddress(x)
- for nic in self._devices[NIC_DEVICES]:
- if nic.macAddr.lower() == mac.lower():
- nic.name = name
- nic.alias = alias
- nic.address = address
- nic.linkActive = linkActive
- # Update vm's conf with address for known nic devices
- knownDev = False
- for dev in self.conf['devices']:
- if (dev['type'] == NIC_DEVICES and
- dev['macAddr'].lower() == mac.lower()):
- dev['address'] = address
- dev['alias'] = alias
- dev['name'] = name
- dev['linkActive'] = linkActive
- knownDev = True
- # Add unknown nic device to vm's conf
- if not knownDev:
- nicDev = {'type': NIC_DEVICES,
- 'device': devType,
- 'macAddr': mac,
- 'nicModel': model,
- 'address': address,
- 'alias': alias,
- 'name': name,
- 'linkActive': linkActive}
- if network:
- nicDev['network'] = network
- self.conf['devices'].append(nicDev)
def _setWriteWatermarks(self):
"""
--
To view, visit http://gerrit.ovirt.org/19732
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8f797baece3601b885777784f611b420523828f7
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeenstr(a)redhat.com>
10 years