diff -r 6a8faf6d98b2 tools/console/client/main.c --- a/tools/console/client/main.c Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/console/client/main.c Tue Sep 30 13:17:19 2008 +0200 @@ -221,7 +221,7 @@ int main(int argc, char **argv) { 0 }, }; - char *path; + char *path, *s; int spty, xsfd; struct xs_handle *xs; char *end; @@ -257,13 +257,18 @@ int main(int argc, char **argv) signal(SIGTERM, sighandler); - path = xs_get_domain_path(xs, domid); - if (path == NULL) - err(errno, "xs_get_domain_path()"); - path = realloc(path, strlen(path) + strlen("/console/tty") + 1); - if (path == NULL) + path = xs_get_backend_dev(xs, domid, "console", 0); + if (path == NULL) { + err(errno, "Could not get backend path to tty"); + } + + s = realloc(path, strlen(path) + 5); + if (s == NULL) { + free(path); err(ENOMEM, "realloc"); - strcat(path, "/console/tty"); + } + path = s; + strcat(path, "/tty"); /* FIXME consoled currently does not assume domain-0 doesn't have a console which is good when we break domain-0 up. To keep us diff -r 6a8faf6d98b2 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/console/daemon/io.c Tue Sep 30 12:15:51 2008 +0200 @@ -87,8 +87,10 @@ struct domain { bool is_dead; struct buffer buffer; struct domain *next; - char *conspath; - char *serialpath; + char *consfront; + char *consback; + char *serialfront; + char *serialback; int use_consolepath; int ring_ref; evtchn_port_or_error_t local_port; @@ -415,7 +417,7 @@ static int domain_create_tty(struct doma } if (dom->use_consolepath) { - success = asprintf(&path, "%s/limit", dom->conspath) != + success = asprintf(&path, "%s/limit", dom->consback) != -1; if (!success) goto out; @@ -427,7 +429,7 @@ static int domain_create_tty(struct doma free(path); } - success = asprintf(&path, "%s/limit", dom->serialpath) != -1; + success = asprintf(&path, "%s/limit", dom->serialback) != -1; if (!success) goto out; data = xs_read(xs, XBT_NULL, path, &len); @@ -437,7 +439,7 @@ static int domain_create_tty(struct doma } free(path); - success = asprintf(&path, "%s/tty", dom->serialpath) != -1; + success = asprintf(&path, "%s/tty", dom->serialback) != -1; if (!success) goto out; success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); @@ -446,7 +448,7 @@ static int domain_create_tty(struct doma goto out; if (dom->use_consolepath) { - success = (asprintf(&path, "%s/tty", dom->conspath) != -1); + success = (asprintf(&path, "%s/tty", dom->consback) != -1); if (!success) goto out; success = xs_write(xs, XBT_NULL, path, slave, strlen(slave)); @@ -504,12 +506,12 @@ static int domain_create_ring(struct dom int err, remote_port, ring_ref, rc; char *type, path[PATH_MAX]; - err = xs_gather(xs, dom->serialpath, + err = xs_gather(xs, dom->serialfront, "ring-ref", "%u", &ring_ref, "port", "%i", &remote_port, NULL); if (err) { - err = xs_gather(xs, dom->conspath, + err = xs_gather(xs, dom->consfront, "ring-ref", "%u", &ring_ref, "port", "%i", &remote_port, NULL); @@ -519,7 +521,7 @@ static int domain_create_ring(struct dom } else dom->use_consolepath = 0; - sprintf(path, "%s/type", dom->use_consolepath ? dom->conspath: dom->serialpath); + sprintf(path, "%s/type", dom->use_consolepath ? dom->consfront: dom->serialfront); type = xs_read(xs, XBT_NULL, path, NULL); if (type && strcmp(type, "xenconsoled") != 0) { free(type); @@ -594,17 +596,17 @@ static bool watch_domain(struct domain * snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid); if (watch) { - success = xs_watch(xs, dom->serialpath, domid_str); + success = xs_watch(xs, dom->serialfront, domid_str); if (success) { - success = xs_watch(xs, dom->conspath, domid_str); + success = xs_watch(xs, dom->consfront, domid_str); if (success) domain_create_ring(dom); else - xs_unwatch(xs, dom->serialpath, domid_str); + xs_unwatch(xs, dom->serialfront, domid_str); } } else { - success = xs_unwatch(xs, dom->serialpath, domid_str); - success = xs_unwatch(xs, dom->conspath, domid_str); + success = xs_unwatch(xs, dom->serialfront, domid_str); + success = xs_unwatch(xs, dom->consfront, domid_str); } return success; @@ -614,7 +616,6 @@ static struct domain *create_domain(int static struct domain *create_domain(int domid) { struct domain *dom; - char *s; struct timeval tv; if (gettimeofday(&tv, NULL) < 0) { @@ -632,21 +633,20 @@ static struct domain *create_domain(int dom->domid = domid; - dom->serialpath = xs_get_domain_path(xs, dom->domid); - s = realloc(dom->serialpath, strlen(dom->serialpath) + - strlen("/serial/0") + 1); - if (s == NULL) + if (asprintf(&dom->serialback, "backend/serial/%d/0", domid) == -1) { + dolog(LOG_ERR, "Out of memory %s:%s():L%d", + __FILE__, __FUNCTION__, __LINE__); goto out; - dom->serialpath = s; - strcat(dom->serialpath, "/serial/0"); - - dom->conspath = xs_get_domain_path(xs, dom->domid); - s = realloc(dom->conspath, strlen(dom->conspath) + - strlen("/console") + 1); - if (s == NULL) + } + + if (asprintf(&dom->consback, "backend/console/%d/0", domid) == -1) { + dolog(LOG_ERR, "Out of memory %s:%s():L%d", + __FILE__, __FUNCTION__, __LINE__); goto out; - dom->conspath = s; - strcat(dom->conspath, "/console"); + } + + dom->serialfront = xs_get_frontend_dev(xs, domid, "serial", 0); + dom->consfront = xs_get_frontend_dev(xs, domid, "console", 0); dom->master_fd = -1; dom->slave_fd = -1; @@ -678,8 +678,10 @@ static struct domain *create_domain(int return dom; out: - free(dom->serialpath); - free(dom->conspath); + free(dom->serialback); + free(dom->consback); + free(dom->serialfront); + free(dom->consfront); free(dom); return NULL; } @@ -716,11 +718,17 @@ static void cleanup_domain(struct domain free(d->buffer.data); d->buffer.data = NULL; - free(d->serialpath); - d->serialpath = NULL; - - free(d->conspath); - d->conspath = NULL; + free(d->serialback); + d->serialback = NULL; + + free(d->consback); + d->consback = NULL; + + free(d->serialfront); + d->serialfront = NULL; + + free(d->consfront); + d->consfront = NULL; remove_domain(d); } diff -r 6a8faf6d98b2 tools/console/daemon/utils.c --- a/tools/console/daemon/utils.c Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/console/daemon/utils.c Tue Sep 30 12:01:37 2008 +0200 @@ -109,7 +109,7 @@ bool xen_setup(void) bool xen_setup(void) { - xs = xs_daemon_open(); + xs = xs_domain_open(); if (xs == NULL) { dolog(LOG_ERR, "Failed to contact xenstore (%m). Is it running?"); @@ -136,7 +136,7 @@ bool xen_setup(void) out: if (xs) - xs_daemon_close(xs); + xs_domain_close(xs); if (xc != -1) xc_interface_close(xc); return false; diff -r 6a8faf6d98b2 tools/python/xen/xend/XendBootloader.py --- a/tools/python/xen/xend/XendBootloader.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/XendBootloader.py Mon Sep 29 16:21:31 2008 +0200 @@ -72,7 +72,9 @@ def bootloader(blexec, disk, dom, quiet fcntl.fcntl(m1, fcntl.F_SETFL, os.O_NDELAY); os.close(s1) slavename = ptsname.ptsname(m1) - dom.storeDom("console/tty", slavename) + + dev = dom.getDeviceController('console') + dev.writeBackend(0, 'tty', slavename) # Release the domain lock here, because we definitely don't want # a stuck bootloader to deny service to other xend clients. diff -r 6a8faf6d98b2 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Sep 29 16:21:31 2008 +0200 @@ -113,6 +113,25 @@ def create_from_dict(config_dict): raise return vm +def _tryVmPathRecover(uuid): + id = 0 + vm_path = None + while True: + path = '/vm/%s' % (uuid,) + if id: + path = '%s-%d' % (path, id,) + try: + uuid = xstransact.Read('%s/uuid' % path) + if uuid: + vm_path = path + else: + return vm_path + except: + # return the last good vm_path, or none + # if we never found one + return vm_path + id += 1 + def recreate(info, priv): """Create the VM object for an existing domain. The domain must not be dying, as the paths in the store should already have been removed, @@ -157,26 +176,17 @@ def recreate(info, priv): # entry disappears (eg. xenstore-rm /) # try: - vmpath = xstransact.Read(dompath, "vm") + # Do not trust /local/domain/%d/vm as the domU might touch + # No need to recheck to vm uuid then. + vmpath = xstransact.Read("/vm_path", str(domid)) if not vmpath: if not priv: - log.warn('/local/domain/%d/vm is missing. recreate is ' + log.warn('/vm_path/%d is missing. recreate is ' 'confused, trying our best to recover' % domid) - needs_reinitialising = True - raise XendError('reinit') - - uuid2_str = xstransact.Read(vmpath, "uuid") - if not uuid2_str: - log.warn('%s/uuid/ is missing. recreate is confused, ' - 'trying our best to recover' % vmpath) - needs_reinitialising = True - raise XendError('reinit') - - uuid2 = uuid.fromString(uuid2_str) - if uuid1 != uuid2: - log.warn('UUID in /vm does not match the UUID in /dom/%d.' - 'Trying out best to recover' % domid) - needs_reinitialising = True + vmpath = _tryVmPathRecover(uuid1) + if not vmpath: + needs_reinitialising = True + raise XendError('reinit') except XendError: pass # our best shot at 'goto' in python :) @@ -365,7 +375,7 @@ class XendDomainInfo: if i != 0: self.vmpath = self.vmpath + '-' + str(i) try: - if self._readVm("uuid"): + if self.readVm("uuid"): self.vmpath = None i = i + 1 except: @@ -450,8 +460,8 @@ class XendDomainInfo: try: self._constructDomain() self._storeVmDetails() + self._createChannels() self._createDevices() - self._createChannels() self._storeDomDetails() self._endRestore() except: @@ -809,7 +819,7 @@ class XendDomainInfo: self.info['vcpu_avail'] = (1 << xeninfo['online_vcpus']) - 1 # read image value - image_sxp = self._readVm('image') + image_sxp = self.readVm('image') if image_sxp: self.info.update_with_image_sxp(sxp.from_string(image_sxp)) @@ -830,27 +840,15 @@ class XendDomainInfo: if self.domid == None or self.domid == 0: return - # Update VT100 port if it exists - 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: - cfg = self.info.console_add('vt100', self.console_port) - self._createDevice('console', cfg) - else: - console_uuid = serial_consoles[0].get('uuid') - self.info.console_update(console_uuid, 'location', - self.console_port) - - # Update VNC port if it exists and write to xenstore if transaction is None: + # XXX todo maybe ? + # vnc_port = self.readDom('device/console/0/vnc-port') vnc_port = self.readDom('console/vnc-port') else: + # vnc_port = self.readDomTxn(transaction, 'device/console/0/vnc-port') 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': @@ -870,23 +868,23 @@ class XendDomainInfo: # Function to update xenstore /vm/* # - def _readVm(self, *args): + def readVm(self, *args): return xstransact.Read(self.vmpath, *args) def _writeVm(self, *args): return xstransact.Write(self.vmpath, *args) def _removeVm(self, *args): + self._removeVmPath() return xstransact.Remove(self.vmpath, *args) - def _gatherVm(self, *args): + def gatherVm(self, *args): return xstransact.Gather(self.vmpath, *args) def storeVm(self, *args): return xstransact.Store(self.vmpath, *args) - - def _readVmTxn(self, transaction, *args): + def readVmTxn(self, transaction, *args): paths = map(lambda x: self.vmpath + "/" + x, args) return transaction.read(*paths) @@ -923,8 +921,8 @@ class XendDomainInfo: return xstransact.Remove(self.dompath, *args) def storeDom(self, *args): + """Stores an information that we share with the domU""" return xstransact.Store(self.dompath, *args) - def readDomTxn(self, transaction, *args): paths = map(lambda x: self.dompath + "/" + x, args) @@ -956,12 +954,20 @@ class XendDomainInfo: t.set_permissions({'dom' : self.domid}) t.write('vm', self.vmpath) + def get_console_type(self): + # Figure out if we need to tell xenconsoled to ignore this guest's + # console - device model will handle console if it is running + constype = "ioemu" + if 'device_model' not in self.info['platform']: + constype = "xenconsoled" + + return constype + def _storeDomDetails(self): to_store = { 'domid': str(self.domid), 'vm': self.vmpath, 'name': self.info['name_label'], - 'console/limit': str(xoptions.get_console_limit() * 1024), 'memory/target': str(self.info['memory_dynamic_max'] / 1024), } @@ -972,17 +978,11 @@ class XendDomainInfo: else: to_store[n] = str(v) - # Figure out if we need to tell xenconsoled to ignore this guest's - # console - device model will handle console if it is running - constype = "ioemu" - if 'device_model' not in self.info['platform']: - constype = "xenconsoled" - - f('console/port', self.console_port) - f('console/ring-ref', self.console_mfn) - f('console/type', constype) f('store/port', self.store_port) f('store/ring-ref', self.store_mfn) + + f('device/console/0/port', self.console_port) + f('device/console/0/ring-ref', self.console_mfn) if arch.type == "x86": f('control/platform-feature-multiprocessor-suspend', True) @@ -1071,7 +1071,7 @@ class XendDomainInfo: changed = True # Check whether image definition has been updated - image_sxp = self._readVm('image') + image_sxp = self.readVm('image') if image_sxp and image_sxp != sxp.to_string(self.info.image_sxpr()): self.info.update_with_image_sxp(sxp.from_string(image_sxp)) changed = True @@ -1207,7 +1207,7 @@ class XendDomainInfo: self.info['vcpus_params']['weight'] = cpu_weight def getRestartCount(self): - return self._readVm('xend/restart_count') + return self.readVm('xend/restart_count') def refreshShutdown(self, xeninfo = None): """ Checks the domain for whether a shutdown is required. @@ -1366,7 +1366,7 @@ class XendDomainInfo: """ from xen.xend import XendDomain - if self._readVm(RESTART_IN_PROGRESS): + if self.readVm(RESTART_IN_PROGRESS): log.error('Xend failed during restart of domain %s. ' 'Refusing to restart to avoid loops.', str(self.domid)) @@ -1377,7 +1377,7 @@ class XendDomainInfo: self._writeVm(RESTART_IN_PROGRESS, 'True') now = time.time() - rst = self._readVm('xend/previous_restart_time') + rst = self.readVm('xend/previous_restart_time') if rst: rst = float(rst) timeout = now - rst @@ -1397,6 +1397,7 @@ class XendDomainInfo: else: self._unwatchVm() self.destroyDomain() + self._removeVm() # new_dom's VM will be the same as this domain's VM, except where # the rename flag has instructed us to call preserveForRestart. @@ -1410,7 +1411,7 @@ class XendDomainInfo: self.info) new_dom.waitForDevices() new_dom.unpause() - rst_cnt = self._readVm('xend/restart_count') + rst_cnt = self.readVm('xend/restart_count') rst_cnt = int(rst_cnt) + 1 self._writeVm('xend/restart_count', str(rst_cnt)) new_dom._removeVm(RESTART_IN_PROGRESS) @@ -1502,6 +1503,16 @@ class XendDomainInfo: return self.getDeviceController(deviceClass).reconfigureDevice( devid, devconfig) + def _createConsole(self): + """Setups the first console for this domain""" + log.debug('Creating initial console ring-ref %s' % self.console_mfn) + devid = self._createDevice('console', { + 'ring-ref': self.console_mfn, + 'port': self.console_port, + 'type': self.get_console_type() + } + ) + def _createDevices(self): """Create the devices for a vm. @@ -1764,6 +1775,7 @@ class XendDomainInfo: self._introduceDomain() + self._createConsole() self._createDevices() self.image.cleanupBootloading() @@ -1898,11 +1910,11 @@ class XendDomainInfo: paths = self._prepare_phantom_paths() - self._cleanupVm() if self.dompath is not None: self.destroyDomain() self._cleanup_phantom_devs(paths) + self._cleanupVm() if "transient" in self.info["other_config"] \ and bool(self.info["other_config"]["transient"]): @@ -2096,7 +2108,7 @@ class XendDomainInfo: """Read the specified parameters from the store. """ try: - return self._gatherVm(*params) + 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 @@ -2183,6 +2195,15 @@ class XendDomainInfo: log.info("Dev still active but hit max loop timeout") break + def _storeVmPath(self): + log.info("storeVmPath(%s) => %s", self.domid, self.vmpath) + if self.domid is not None: + xstransact.Write('/vm_path', str(self.domid), self.vmpath) + + def _removeVmPath(self): + if self.domid is not None: + xstransact.Remove('/vm_path/%s' % str(self.domid)) + def _storeVmDetails(self): to_store = {} @@ -2200,14 +2221,14 @@ class XendDomainInfo: if image_sxpr: to_store['image'] = sxp.to_string(image_sxpr) - if not self._readVm('xend/restart_count'): + if not self.readVm('xend/restart_count'): to_store['xend/restart_count'] = str(0) log.debug("Storing VM details: %s", scrub_password(to_store)) self._writeVm(to_store) self._setVmPermissions() - + self._storeVmPath() def _setVmPermissions(self): """Allow the guest domain to read its UUID. We don't allow it to @@ -2227,7 +2248,7 @@ class XendDomainInfo: log.warn("".join(traceback.format_stack())) return self._stateGet() else: - raise AttributeError() + raise AttributeError(name) def __setattr__(self, name, value): if name == "state": @@ -2338,12 +2359,6 @@ class XendDomainInfo: ignore_devices = ignore_store, legacy_only = legacy_only) - #if not ignore_store and self.dompath: - # vnc_port = self.readDom('console/vnc-port') - # if vnc_port is not None: - # result.append(['device', - # ['console', ['vnc-port', str(vnc_port)]]]) - return result # Xen API @@ -2608,7 +2623,7 @@ class XendDomainInfo: if not config.has_key('device'): devid = config.get('id') if devid != None: - config['device'] = 'eth%d' % devid + config['device'] = 'eth%s' % devid else: config['device'] = '' diff -r 6a8faf6d98b2 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/image.py Mon Sep 29 16:21:31 2008 +0200 @@ -289,7 +289,7 @@ class ImageHandler: log.info("spawning device models: %s %s", self.device_model, args) # keep track of pid and spawned options to kill it later self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env) - self.vm.storeDom("image/device-model-pid", self.pid) + self.vm.storeVm("image/device-model-pid", self.pid) log.info("device model pid: %d", self.pid) def saveDeviceModel(self): @@ -320,7 +320,7 @@ class ImageHandler: def recreate(self): if self.device_model is None: return - self.pid = self.vm.gatherDom(('image/device-model-pid', int)) + self.pid = self.vm.gatherVm(('image/device-model-pid', int)) def destroyDeviceModel(self): if self.device_model is None: diff -r 6a8faf6d98b2 tools/python/xen/xend/server/ConsoleController.py --- a/tools/python/xen/xend/server/ConsoleController.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/server/ConsoleController.py Mon Sep 29 16:21:31 2008 +0200 @@ -2,13 +2,16 @@ from xen.xend.XendLogging import log from xen.xend.XendLogging import log from xen.xend.XendError import VmError + +from xen.xend import XendOptions +xoptions = XendOptions.instance() class ConsoleController(DevController): """A dummy controller for us to represent serial and vnc console devices with persistent UUIDs. """ - valid_cfg = ['location', 'uuid', 'protocol'] + valid_cfg = ['location', 'uuid', 'protocol', 'limit'] def __init__(self, vm): DevController.__init__(self, vm) @@ -16,8 +19,17 @@ class ConsoleController(DevController): def getDeviceDetails(self, config): back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) - return (self.allocateDeviceID(), back, {}) + devid = self.allocateDeviceID() + front = { } + + if devid == 0 and self.vm.console_mfn: + front.update({ + 'type': '%s' % self.vm.get_console_type() + }) + + back['limit'] = str(xoptions.get_console_limit() * 1024) + return (devid, back, front) def getDeviceConfiguration(self, devid, transaction = None): result = DevController.getDeviceConfiguration(self, devid, transaction) diff -r 6a8faf6d98b2 tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/server/DevController.py Mon Sep 29 16:21:31 2008 +0200 @@ -122,8 +122,11 @@ class DevController: log.debug( 'DevController: still waiting to write device entries.') + devpath = self.devicePath(devid) + t.remove(frontpath) t.remove(backpath) + t.remove(devpath) t.mkdir(backpath) t.set_permissions(backpath, @@ -137,6 +140,14 @@ class DevController: t.write2(frontpath, front) t.write2(backpath, back) + + t.mkdir(devpath) + t.write2(devpath, { + 'backend' : backpath, + 'backend-id' : "%i" % backdom, + 'frontend' : frontpath, + 'frontend-id' : "%i" % self.vm.getDomid() + }) if t.commit(): return devid @@ -233,11 +244,12 @@ class DevController: if force: frontpath = self.frontendPath(dev) - backpath = xstransact.Read(frontpath, "backend") + backpath = self.readVm(devid, "backend") if backpath: xstransact.Remove(backpath) xstransact.Remove(frontpath) + # xstransact.Remove(self.devicePath()) ?? Below is the same ? self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev)) def configurations(self, transaction = None): @@ -281,9 +293,10 @@ class DevController: @return: dict """ if transaction is None: - backdomid = xstransact.Read(self.frontendPath(devid), "backend-id") - else: - backdomid = transaction.read(self.frontendPath(devid) + "/backend-id") + backdomid = xstransact.Read(self.devicePath(devid), "backend-id") + else: + backdomid = transaction.read(self.devicePath(devid) + "/backend-id") + if backdomid is None: raise VmError("Device %s not connected" % devid) @@ -411,18 +424,22 @@ class DevController: t.write("nextDeviceID", str(result + 1)) return result + def readVm(self, devid, *args): + devpath = self.devicePath(devid) + if devpath: + return xstransact.Read(devpath, *args) + else: + raise VmError("Device config %s not found" % devid) def readBackend(self, devid, *args): - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") + backpath = self.readVm(devid, "backend") if backpath: return xstransact.Read(backpath, *args) else: raise VmError("Device %s not connected" % devid) def readBackendTxn(self, transaction, devid, *args): - frontpath = self.frontendPath(devid) - backpath = transaction.read(frontpath + "/backend") + backpath = self.readVm(devid, "backend") if backpath: paths = map(lambda x: backpath + "/" + x, args) return transaction.read(*paths) @@ -440,7 +457,7 @@ class DevController: """@return The IDs of each of the devices currently configured for this instance's deviceClass. """ - fe = self.backendRoot() + fe = self.deviceRoot() if transaction: return map(lambda x: int(x.split('/')[-1]), transaction.list(fe)) @@ -449,8 +466,7 @@ class DevController: def writeBackend(self, devid, *args): - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") + backpath = self.readVm(devid, "backend") if backpath: xstransact.Write(backpath, *args) @@ -515,9 +531,8 @@ class DevController: def waitForBackend(self, devid): - frontpath = self.frontendPath(devid) - # lookup a phantom + # lookup a phantom phantomPath = xstransact.Read(frontpath, 'phantom_vbd') if phantomPath is not None: log.debug("Waiting for %s's phantom %s.", devid, phantomPath) @@ -530,7 +545,7 @@ class DevController: if result['status'] != 'Connected': return (result['status'], err) - backpath = xstransact.Read(frontpath, "backend") + backpath = self.readVm(devid, "backend") if backpath: @@ -579,17 +594,20 @@ class DevController: def frontendRoot(self): return "%s/device/%s" % (self.vm.getDomainPath(), self.deviceClass) - def backendRoot(self): - """Construct backend root path assuming backend is domain 0.""" - from xen.xend.XendDomain import DOM0_ID - from xen.xend.xenstore.xsutil import GetDomainPath - return "%s/backend/%s/%s" % (GetDomainPath(DOM0_ID), - self.deviceClass, self.vm.getDomid()) - def frontendMiscPath(self): return "%s/device-misc/%s" % (self.vm.getDomainPath(), self.deviceClass) + def deviceRoot(self): + """Return the /vm/device. Because backendRoot assumes the + backend domain is 0""" + return "%s/device/%s" % (self.vm.vmpath, self.deviceClass) + + def devicePath(self, devid): + """Return the /device entry of the given VM. We use it to store + backend/frontend locations""" + return "%s/device/%s/%s" % (self.vm.vmpath, + self.deviceClass, devid) def hotplugStatusCallback(statusPath, ev, result): log.debug("hotplugStatusCallback %s.", statusPath) diff -r 6a8faf6d98b2 tools/python/xen/xend/server/netif.py --- a/tools/python/xen/xend/server/netif.py Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/python/xen/xend/server/netif.py Mon Sep 29 16:21:31 2008 +0200 @@ -141,10 +141,6 @@ class NetifController(DevController): if sec_lab: back['security_label'] = sec_lab - config_path = "device/%s/%d/" % (self.deviceClass, devid) - for x in back: - self.vm._writeVm(config_path + x, back[x]) - back['handle'] = "%i" % devid back['script'] = os.path.join(xoptions.network_script_dir, script) if rate: @@ -188,40 +184,14 @@ class NetifController(DevController): 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'): if transaction is None: - y = self.vm._readVm(config_path + x) + y = self.readBackend(devid, 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 - - if script: - result['script'] = script - if ip: - result['ip'] = ip - if bridge: - result['bridge'] = bridge - if mac: - result['mac'] = mac - if typ: - result['type'] = typ - if vifname: - result['vifname'] = vifname - if rate: - result['rate'] = rate - if uuid: - result['uuid'] = uuid - if model: - result['model'] = model - if accel: - result['accel'] = accel - if security_label: - result['security_label'] = security_label + y = self.readBackendTxn(transaction, devid, x) + if y: + result[x] = y return result diff -r 6a8faf6d98b2 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/xenstore/xs.c Tue Sep 30 13:19:54 2008 +0200 @@ -17,6 +17,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include @@ -232,6 +233,11 @@ void xs_daemon_close(struct xs_handle *h free(h); } +void xs_domain_close(struct xs_handle *h) +{ + xs_daemon_close(h); +} + static bool read_all(int fd, void *data, unsigned int len) { while (len) { @@ -739,6 +745,60 @@ char *xs_get_domain_path(struct xs_handl return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL); } +/* read the vm path from /vm_path/ */ +char *xs_get_vm_path(struct xs_handle *h, unsigned int domid) +{ + char vm_path[MAX_STRLEN(domid) + 9]; + void *ret; + unsigned int len; + + sprintf(vm_path, "/vm_path/%u", domid); + + ret = xs_single(h, XBT_NULL, XS_READ, vm_path, &len); + if (len) + return ret; + return NULL; +} + +char *xs_get_backend_dev(struct xs_handle *h, unsigned int domid, + const char *devclass, unsigned int devid) +{ + char *vm_path; + char *vm_dev_path; + char *dev_path = NULL; + unsigned int len; + + vm_path = xs_get_vm_path(h, domid); + if (vm_path == NULL) + return NULL; + + if (asprintf(&vm_dev_path, "%s/device/%s/%d/backend", vm_path, + devclass, devid) == -1) { + errno = ENOMEM; + goto out; + } + + dev_path = xs_single(h, XBT_NULL, XS_READ, vm_dev_path, &len); + if (!dev_path) { + errno = ENOENT; + goto out; + } + +out: + free(vm_path); + free(vm_dev_path); + return dev_path; +} + +char *xs_get_frontend_dev(struct xs_handle *h, unsigned int domid, + const char *devclass, unsigned int devid) +{ + char *path; + asprintf(&path, "/local/domain/%d/device/%s/%d", + domid, devclass, devid); + return path; +} + bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid) { char *domain = single_with_domid(h, XS_IS_DOMAIN_INTRODUCED, domid); diff -r 6a8faf6d98b2 tools/xenstore/xs.h --- a/tools/xenstore/xs.h Wed Sep 17 15:46:15 2008 +0100 +++ b/tools/xenstore/xs.h Mon Sep 29 16:21:31 2008 +0200 @@ -42,6 +42,7 @@ struct xs_handle *xs_daemon_open_readonl /* Close the connection to the xs daemon. */ void xs_daemon_close(struct xs_handle *); +void xs_domain_close(struct xs_handle *); /* Get contents of a directory. * Returns a malloced array: call free() on it after use. @@ -146,6 +147,17 @@ bool xs_release_domain(struct xs_handle */ char *xs_get_domain_path(struct xs_handle *h, unsigned int domid); +/* Query the vm path for a domain. Call free() after use. + */ +char *xs_get_vm_path(struct xs_handle *h, unsigned int domid); + +/* Get a device backend path from domain, devclass, devid */ +char *xs_get_backend_dev(struct xs_handle *h, unsigned int domid, const char *devclass, unsigned int devid); + +/* Get a device frontend path from domain, devclass, devid */ +char *xs_get_frontend_dev(struct xs_handle *h, unsigned int domid, const char *devclass, unsigned int devid); + + /* Return whether the domain specified has been introduced to xenstored. */ bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid);