from xen.xend.XendDevices import XendDevices
from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
+from xen.xend.xenstore.xstransact import xstransact
from xen.xend.server.BlktapController import blktap_disk_types
from xen.xend.server.netif import randomMAC
from xen.util.blkif import blkdev_name_to_number
# Marshall devices (running or from configuration)
if not ignore_devices:
- for cls in XendDevices.valid_devices():
- found = False
+ txn = xstransact()
+ try:
+ for cls in XendDevices.valid_devices():
+ found = False
- # figure if there is a dev controller is valid and running
- if domain and domain.getDomid() != None:
- try:
- controller = domain.getDeviceController(cls)
- configs = controller.configurations()
- for config in configs:
- if sxp.name(config) in ('vbd', 'tap'):
- # The bootable flag is never written to the
- # store as part of the device config.
- dev_uuid = sxp.child_value(config, 'uuid')
- dev_type, dev_cfg = self['devices'][dev_uuid]
- is_bootable = dev_cfg.get('bootable', 0)
- config.append(['bootable', int(is_bootable)])
-
- sxpr.append(['device', config])
-
- found = True
- except:
- log.exception("dumping sxp from device controllers")
- pass
+ # figure if there is a dev controller is valid and running
+ if domain and domain.getDomid() != None:
+ try:
+ controller = domain.getDeviceController(cls)
+ configs = controller.configurations(txn)
+ for config in configs:
+ if sxp.name(config) in ('vbd', 'tap'):
+ # The bootable flag is never written to the
+ # store as part of the device config.
+ dev_uuid = sxp.child_value(config, 'uuid')
+ dev_type, dev_cfg = self['devices'][dev_uuid]
+ is_bootable = dev_cfg.get('bootable', 0)
+ config.append(['bootable', int(is_bootable)])
+
+ sxpr.append(['device', config])
+
+ found = True
+ except:
+ log.exception("dumping sxp from device controllers")
+ pass
- # if we didn't find that device, check the existing config
- # for a device in the same class
- if not found:
- for dev_type, dev_info in self.all_devices_sxpr():
- if dev_type == cls:
- sxpr.append(['device', dev_info])
+ # if we didn't find that device, check the existing config
+ # for a device in the same class
+ if not found:
+ for dev_type, dev_info in self.all_devices_sxpr():
+ if dev_type == cls:
+ sxpr.append(['device', dev_info])
+
+ txn.commit()
+ except:
+ txn.abort()
+ raise
return sxpr
@rtype: None
"""
+ txn = xstransact()
+ try:
+ self._refreshTxn(txn, refresh_shutdown)
+ txn.commit()
+ except:
+ txn.abort()
+ raise
+
+ def _refreshTxn(self, transaction, refresh_shutdown):
running = self._running_domains()
# Add domains that are not already tracked but running in Xen,
# and update domain state for those that are running and tracked.
for dom in running:
domid = dom['domid']
if domid in self.domains:
- self.domains[domid].update(dom, refresh_shutdown)
+ self.domains[domid].update(dom, refresh_shutdown, transaction)
elif domid not in self.domains and dom['dying'] != 1:
try:
new_dom = XendDomainInfo.recreate(dom, False)
self._update_consoles()
- def _update_consoles(self):
+ def _update_consoles(self, transaction = None):
if self.domid == None or self.domid == 0:
return
# Update VT100 port if it exists
- self.console_port = self.readDom('console/port')
+ if transaction is None:
+ self.console_port = self.readDom('console/port')
+ else:
+ self.console_port = self.readDomTxn(transaction, 'console/port')
if self.console_port is not None:
serial_consoles = self.info.console_get_all('vt100')
if not serial_consoles:
# Update VNC port if it exists and write to xenstore
- vnc_port = self.readDom('console/vnc-port')
+ if transaction is None:
+ vnc_port = self.readDom('console/vnc-port')
+ else:
+ vnc_port = self.readDomTxn(transaction, 'console/vnc-port')
if vnc_port is not None:
for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
if dev_type == 'vfb':
def storeVm(self, *args):
return xstransact.Store(self.vmpath, *args)
+
+ def _readVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.read(*paths)
+
+ def _writeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.write(*paths)
+
+ def _removeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.remove(*paths)
+
+ def _gatherVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.gather(paths)
+
+ def storeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.store(*paths)
+
#
# Function to update xenstore /dom/*
#
def storeDom(self, *args):
return xstransact.Store(self.dompath, *args)
+
+ def readDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.read(*paths)
+
+ def gatherDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.gather(*paths)
+
+ def _writeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.write(*paths)
+
+ def _removeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.remove(*paths)
+
+ def storeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.store(*paths)
+
+
def _recreateDom(self):
complete(self.dompath, lambda t: self._recreateDomFunc(t))
(" as domain %s" % str(dom.domid)) or ""))
- def update(self, info = None, refresh = True):
+ def update(self, info = None, refresh = True, transaction = None):
"""Update with info from xc.domain_getinfo().
"""
log.trace("XendDomainInfo.update(%s) on domain %s", info,
# TODO: we should eventually get rid of old_dom_states
self.info.update_config(info)
- self._update_consoles()
+ self._update_consoles(transaction)
if refresh:
self.refreshShutdown(info)
return (self.allocateDeviceID(), back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
- devinfo = self.readBackend(devid, *self.valid_cfg)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
+ if transaction is None:
+ devinfo = self.readBackend(devid, *self.valid_cfg)
+ else:
+ devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
config = dict(zip(self.valid_cfg, devinfo))
config = dict([(key, val) for key, val in config.items()
if val != None])
self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
- def configurations(self):
- return map(self.configuration, self.deviceIDs())
+ def configurations(self, transaction = None):
+ return map(lambda x: self.configuration(x, transaction), self.deviceIDs(transaction))
- def configuration(self, devid):
+ def configuration(self, devid, transaction = None):
"""@return an s-expression giving the current configuration of the
specified device. This would be suitable for giving to {@link
#createDevice} in order to recreate that device."""
- configDict = self.getDeviceConfiguration(devid)
+ configDict = self.getDeviceConfiguration(devid, transaction)
sxpr = [self.deviceClass]
for key, val in configDict.items():
if isinstance(val, (types.ListType, types.TupleType)):
'id', devid]]
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device.
@note: Similar to L{configuration} except it returns a dict.
@return: dict
"""
- backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
+ if transaction is None:
+ backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
+ else:
+ backdomid = transaction.read(self.frontendPath(devid) + "/backend-id")
if backdomid is None:
raise VmError("Device %s not connected" % devid)
else:
raise VmError("Device %s not connected" % devid)
+ def readBackendTxn(self, transaction, devid, *args):
+ frontpath = self.frontendPath(devid)
+ backpath = transaction.read(frontpath + "/backend")
+ if backpath:
+ paths = map(lambda x: backpath + "/" + x, args)
+ return transaction.read(*paths)
+ else:
+ raise VmError("Device %s not connected" % devid)
+
def readFrontend(self, devid, *args):
return xstransact.Read(self.frontendPath(devid), *args)
+ def readFrontendTxn(self, transaction, devid, *args):
+ paths = map(lambda x: self.frontendPath(devid) + "/" + x, args)
+ return transaction.read(*paths)
+
def deviceIDs(self, transaction = None):
"""@return The IDs of each of the devices currently configured for
this instance's deviceClass.
"""
fe = self.backendRoot()
+
if transaction:
return map(lambda x: int(x.split('/')[-1]), transaction.list(fe))
else:
(self.deviceClass, devid, config))
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device.
@note: Similar to L{configuration} except it returns a dict.
@return: dict
"""
- config = DevController.getDeviceConfiguration(self, devid)
- devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
- 'uuid')
+ config = DevController.getDeviceConfiguration(self, devid, transaction)
+ if transaction is None:
+ devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
+ 'uuid')
+ else:
+ devinfo = self.readBackendTxn(transaction, devid,
+ 'dev', 'type', 'params', 'mode', 'uuid')
dev, typ, params, mode, uuid = devinfo
if dev:
- dev_type = self.readFrontend(devid, 'device-type')
+ if transaction is None:
+ dev_type = self.readFrontend(devid, 'device-type')
+ else:
+ dev_type = self.readFrontendTxn(transaction, devid, 'device-type')
if dev_type:
dev += ':' + dev_type
config['dev'] = dev
"network device")
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""@see DevController.configuration"""
- result = DevController.getDeviceConfiguration(self, devid)
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
config_path = "device/%s/%d/" % (self.deviceClass, devid)
devinfo = ()
for x in ( 'script', 'ip', 'bridge', 'mac',
'type', 'vifname', 'rate', 'uuid', 'model', 'accel',
'security_label'):
- y = self.vm._readVm(config_path + x)
+ if transaction is None:
+ y = self.vm._readVm(config_path + x)
+ else:
+ y = self.vm._readVmTxn(transaction, config_path + x)
devinfo += (y,)
(script, ip, bridge, mac, typ, vifname, rate, uuid,
model, accel, security_label) = devinfo
back['uuid'] = config.get('uuid','')
return (0, back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
num_devs = self.readBackend(devid, 'num_devs')
pci_devs = []
return (devid, back, front)
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device"""
- result = DevController.getDeviceConfiguration(self, devid)
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
(instance, uuid, type) = \
self.readBackend(devid, 'instance',
return (devid, back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
- devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
+ if transaction is None:
+ devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
+ else:
+ devinfo = self.readBackendTxn(transaction, devid, *CONFIG_ENTRIES)
return dict([(CONFIG_ENTRIES[i], devinfo[i])
for i in range(len(CONFIG_ENTRIES))
if devinfo[i] is not None])