# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID 32b574b24b18f709d3ae53661fd1dbe1ed6ce31f
# Parent 3631592ad7d3acf193eb0b0ae39f81169881b14b
Watch for changes in the /vm section of the store, so that we update our
internal state if the store is configured by an external tool.
We react properly to changes in name and on_{reboot,poweroff,crash}. Reacting
correctly to vcpus, vcpu_avail, memory, and maxmem will come soon (those code
aspects are already under review). cpu_weight and bootloader to be considered.
Removed unused and semantically invalid method XendDomainInfo.setDomid.
Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx>
diff -r 3631592ad7d3 -r 32b574b24b18 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Wed Nov 16 14:27:59 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Wed Nov 16 14:32:56 2005
@@ -45,6 +45,8 @@
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
+from xen.xend.xenstore.xswatch import xswatch
+
"""Shutdown code for poweroff."""
DOMAIN_POWEROFF = 0
@@ -82,7 +84,6 @@
SHUTDOWN_TIMEOUT = 30
-DOMROOT = '/local/domain/'
VMROOT = '/vm/'
ZOMBIE_PREFIX = 'Zombie-'
@@ -100,26 +101,52 @@
#log.setLevel(logging.TRACE)
-## Configuration entries that we expect to round-trip -- be read from the
+##
+# All parameters of VMs that may be configured on-the-fly, or at start-up.
+#
+VM_CONFIG_PARAMS = [
+ ('name', str),
+ ('on_poweroff', str),
+ ('on_reboot', str),
+ ('on_crash', str),
+ ]
+
+
+##
+# Configuration entries that we expect to round-trip -- be read from the
# config file or xc, written to save-files (i.e. through sxpr), and reused as
# config on restart or restore, all without munging. Some configuration
# entries are munged for backwards compatibility reasons, or because they
# don't come out of xc in the same form as they are specified in the config
# file, so those are handled separately.
ROUNDTRIPPING_CONFIG_ENTRIES = [
- ('name', str),
- ('uuid', str),
- ('ssidref', int),
- ('vcpus', int),
- ('vcpu_avail', int),
- ('cpu_weight', float),
- ('memory', int),
- ('maxmem', int),
- ('bootloader', str),
- ('on_poweroff', str),
- ('on_reboot', str),
- ('on_crash', str)
+ ('uuid', str),
+ ('ssidref', int),
+ ('vcpus', int),
+ ('vcpu_avail', int),
+ ('cpu_weight', float),
+ ('memory', int),
+ ('maxmem', int),
+ ('bootloader', str),
]
+
+ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS
+
+
+##
+# All entries written to the store. This is VM_CONFIGURATION_PARAMS, plus
+# those entries written to the store that cannot be reconfigured on-the-fly.
+#
+VM_STORE_ENTRIES = [
+ ('uuid', str),
+ ('ssidref', int),
+ ('vcpus', int),
+ ('vcpu_avail', int),
+ ('memory', int),
+ ('maxmem', int),
+ ]
+
+VM_STORE_ENTRIES += VM_CONFIG_PARAMS
#
@@ -156,6 +183,7 @@
vm.initDomain()
vm.storeVmDetails()
vm.storeDomDetails()
+ vm.registerWatch()
vm.refreshShutdown()
return vm
except:
@@ -211,6 +239,7 @@
vm.storeVmDetails()
vm.storeDomDetails()
+ vm.registerWatch()
vm.refreshShutdown(xeninfo)
return vm
@@ -371,12 +400,50 @@
self.console_port = None
self.console_mfn = None
+ self.vmWatch = None
+
self.state = STATE_DOM_OK
self.state_updated = threading.Condition()
self.refresh_shutdown_lock = threading.Condition()
## private:
+
+ def readVMDetails(self, params):
+ """Read from the store all of those entries that we consider
+ """
+ try:
+ return self.gatherVm(*params)
+ except ValueError:
+ # One of the int/float entries in params has a corresponding store
+ # entry that is invalid. We recover, because older versions of
+ # Xend may have put the entry there (memory/target, for example),
+ # but this is in general a bad situation to have reached.
+ log.exception(
+ "Store corrupted at %s! Domain %d's configuration may be "
+ "affected.", self.vmpath, self.domid)
+ return []
+
+
+ def storeChanged(self):
+ log.debug("XendDomainInfo.storeChanged");
+
+ changed = False
+
+ def f(x, y):
+ if y is not None and self.info[x[0]] != y:
+ self.info[x[0]] = y
+ changed = True
+
+ map(f, VM_CONFIG_PARAMS, self.readVMDetails(VM_CONFIG_PARAMS))
+
+ if changed:
+ # Update the domain section of the store, as this contains some
+ # parameters derived from the VM configuration.
+ self.storeDomDetails()
+
+ return 1
+
def augmentInfo(self):
"""Augment self.info, as given to us through {@link #recreate}, with
@@ -387,30 +454,8 @@
if not self.infoIsSet(name) and val is not None:
self.info[name] = val
- params = (("name", str),
- ("on_poweroff", str),
- ("on_reboot", str),
- ("on_crash", str),
- ("image", str),
- ("memory", int),
- ("maxmem", int),
- ("vcpus", int),
- ("vcpu_avail", int),
- ("start_time", float))
-
- try:
- from_store = self.gatherVm(*params)
- except ValueError, exn:
- # One of the int/float entries in params has a corresponding store
- # entry that is invalid. We recover, because older versions of
- # Xend may have put the entry there (memory/target, for example),
- # but this is in general a bad situation to have reached.
- log.exception(
- "Store corrupted at %s! Domain %d's configuration may be "
- "affected.", self.vmpath, self.domid)
- return
-
- map(lambda x, y: useIfNeeded(x[0], y), params, from_store)
+ map(lambda x, y: useIfNeeded(x[0], y), VM_STORE_ENTRIES,
+ self.readVMDetails(VM_STORE_ENTRIES))
device = []
for c in controllerClasses:
@@ -536,23 +581,23 @@
self.introduceDomain()
self.storeDomDetails()
+ self.registerWatch()
self.refreshShutdown()
log.debug("XendDomainInfo.completeRestore done")
def storeVmDetails(self):
- to_store = {
- 'uuid': self.info['uuid']
- }
+ to_store = {}
+
+ for k in VM_STORE_ENTRIES:
+ if self.infoIsSet(k[0]):
+ to_store[k[0]] = str(self.info[k[0]])
if self.infoIsSet('image'):
to_store['image'] = sxp.to_string(self.info['image'])
- for k in ['name', 'ssidref', 'memory', 'maxmem', 'on_poweroff',
- 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail']:
- if self.infoIsSet(k):
- to_store[k] = str(self.info[k])
+ to_store['start_time'] = str(self.info['start_time'])
log.debug("Storing VM details: %s", to_store)
@@ -599,13 +644,16 @@
return result
- def setDomid(self, domid):
- """Set the domain id.
-
- @param dom: domain id
- """
- self.domid = domid
- self.storeDom("domid", self.domid)
+ ## public:
+
+ def registerWatch(self):
+ """Register a watch on this VM's entries in the store, so that
+ when they are changed externally, we keep up to date. This should
+ only be called by {@link #create}, {@link #recreate}, or {@link
+ #restore}, once the domain's details have been written, but before the
+ new instance is returned."""
+ self.vmWatch = xswatch(self.vmpath, self.storeChanged)
+
def getDomid(self):
return self.domid
@@ -1116,6 +1164,13 @@
"""Cleanup VM resources. Idempotent. Nothrow guarantee."""
try:
+ try:
+ if self.vmWatch:
+ self.vmWatch.unwatch()
+ self.vmWatch = None
+ except:
+ log.exception("Unwatching VM path failed.")
+
self.removeVm()
except:
log.exception("Removing VM path failed.")
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|