📄 xenddomaininfo.py
字号:
#if not self._infoIsSet('uuid'): # self.info['uuid'] = uuid.toString(uuid.create()) # Find a unique /vm/<uuid>/<integer> path if not specified. # This avoids conflict between pre-/post-migrate domains when doing # localhost relocation. self.vmpath = vmpath i = 0 while self.vmpath == None: self.vmpath = XS_VMROOT + self.info['uuid'] if i != 0: self.vmpath = self.vmpath + '-' + str(i) try: if self._readVm("uuid"): self.vmpath = None i = i + 1 except: pass self.dompath = dompath self.image = None self.store_port = None self.store_mfn = None self.console_port = None self.console_mfn = None self.native_protocol = None self.vmWatch = None self.shutdownWatch = None self.shutdownStartTime = None self._resume = resume self.state_updated = threading.Condition() self.refresh_shutdown_lock = threading.Condition() self._stateSet(DOM_STATE_HALTED) self._deviceControllers = {} for state in DOM_STATES_OLD: self.info[state] = 0 if augment: self._augmentInfo(priv) self._checkName(self.info['name_label']) self.metrics = XendVMMetrics(uuid.createString(), self) # # Public functions available through XMLRPC # def start(self, is_managed = False): """Attempts to start the VM by do the appropriate initialisation if it not started. """ from xen.xend import XendDomain if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED): try: XendTask.log_progress(0, 30, self._constructDomain) XendTask.log_progress(31, 60, self._initDomain) XendTask.log_progress(61, 70, self._storeVmDetails) XendTask.log_progress(71, 80, self._storeDomDetails) XendTask.log_progress(81, 90, self._registerWatches) XendTask.log_progress(91, 100, self.refreshShutdown) xendomains = XendDomain.instance() xennode = XendNode.instance() # save running configuration if XendDomains believe domain is # persistent if is_managed: xendomains.managed_config_save(self) if xennode.xenschedinfo() == 'credit': xendomains.domain_sched_credit_set(self.getDomid(), self.getWeight(), self.getCap()) except: log.exception('VM start failed') self.destroy() raise else: raise XendError('VM already running') def resume(self): """Resumes a domain that has come back from suspension.""" state = self._stateGet() if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED): try: self._constructDomain() self._storeVmDetails() self._createDevices() self._createChannels() self._storeDomDetails() self._endRestore() except: log.exception('VM resume failed') self.destroy() raise else: raise XendError('VM is not suspended; it is %s' % XEN_API_VM_POWER_STATE[state]) def shutdown(self, reason): """Shutdown a domain by signalling this via xenstored.""" log.debug('XendDomainInfo.shutdown(%s)', reason) if self._stateGet() in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): raise XendError('Domain cannot be shutdown') if self.domid == 0: raise XendError('Domain 0 cannot be shutdown') if reason not in DOMAIN_SHUTDOWN_REASONS.values(): raise XendError('Invalid reason: %s' % reason) self._removeVm('xend/previous_restart_time') self.storeDom("control/shutdown", reason) # HVM domain shuts itself down only if it has PV drivers if self.info.is_hvm(): hvm_pvdrv = xc.hvm_get_param(self.domid, HVM_PARAM_CALLBACK_IRQ) if not hvm_pvdrv: code = REVERSE_DOMAIN_SHUTDOWN_REASONS[reason] xc.domain_destroy_hook(self.domid) log.info("HVM save:remote shutdown dom %d!", self.domid) xc.domain_shutdown(self.domid, code) def pause(self): """Pause domain @raise XendError: Failed pausing a domain """ try: xc.domain_pause(self.domid) self._stateSet(DOM_STATE_PAUSED) except Exception, ex: log.exception(ex) raise XendError("Domain unable to be paused: %s" % str(ex)) def unpause(self): """Unpause domain @raise XendError: Failed unpausing a domain """ try: xc.domain_unpause(self.domid) self._stateSet(DOM_STATE_RUNNING) except Exception, ex: log.exception(ex) raise XendError("Domain unable to be unpaused: %s" % str(ex)) def send_sysrq(self, key): """ Send a Sysrq equivalent key via xenstored.""" if self._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): raise XendError("Domain '%s' is not started" % self.info['name_label']) asserts.isCharConvertible(key) self.storeDom("control/sysrq", '%c' % key) def device_create(self, dev_config): """Create a new device. @param dev_config: device configuration @type dev_config: SXP object (parsed config) """ log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config)) dev_type = sxp.name(dev_config) dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config) dev_config_dict = self.info['devices'][dev_uuid][1] log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict)) if self.domid is not None: try: dev_config_dict['devid'] = devid = \ self._createDevice(dev_type, dev_config_dict) self._waitForDevice(dev_type, devid) except VmError, ex: del self.info['devices'][dev_uuid] if dev_type == 'tap': self.info['vbd_refs'].remove(dev_uuid) else: self.info['%s_refs' % dev_type].remove(dev_uuid) raise ex else: devid = None xen.xend.XendDomain.instance().managed_config_save(self) return self.getDeviceController(dev_type).sxpr(devid) def device_configure(self, dev_sxp, devid = None): """Configure an existing device. @param dev_config: device configuration @type dev_config: SXP object (parsed config) @param devid: device id @type devid: int @return: Returns True if successfully updated device @rtype: boolean """ # convert device sxp to a dict dev_class = sxp.name(dev_sxp) dev_config = {} for opt_val in dev_sxp[1:]: try: dev_config[opt_val[0]] = opt_val[1] except IndexError: pass # use DevController.reconfigureDevice to change device config dev_control = self.getDeviceController(dev_class) dev_uuid = dev_control.reconfigureDevice(devid, dev_config) # update XendConfig with new device info if dev_uuid: self.info.device_update(dev_uuid, dev_sxp) return True def waitForDevices(self): """Wait for this domain's configured devices to connect. @raise VmError: if any device fails to initialise. """ for devclass in XendDevices.valid_devices(): self.getDeviceController(devclass).waitForDevices() def destroyDevice(self, deviceClass, devid, force = False, rm_cfg = False): log.debug("XendDomainInfo.destroyDevice: deviceClass = %s, device = %s", deviceClass, devid) if rm_cfg: # Convert devid to device number. A device number is # needed to remove its configuration. dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid) # Save current sxprs. A device number and a backend # path are needed to remove its configuration but sxprs # do not have those after calling destroyDevice. sxprs = self.getDeviceSxprs(deviceClass) rc = None if self.domid is not None: rc = self.getDeviceController(deviceClass).destroyDevice(devid, force) if not force and rm_cfg: # The backend path, other than the device itself, # has to be passed because its accompanied frontend # path may be void until its removal is actually # issued. It is probable because destroyDevice is # issued first. for dev_num, dev_info in sxprs: dev_num = int(dev_num) if dev_num == dev: for x in dev_info: if x[0] == 'backend': backend = x[1] break break self._waitForDevice_destroy(deviceClass, devid, backend) if rm_cfg: if deviceClass == 'vif': if self.domid is not None: for dev_num, dev_info in sxprs: dev_num = int(dev_num) if dev_num == dev: for x in dev_info: if x[0] == 'mac': mac = x[1] break break dev_info = self._getDeviceInfo_vif(mac) else: _, dev_info = sxprs[dev] else: # 'vbd' or 'tap' dev_info = self._getDeviceInfo_vbd(dev) # To remove the UUID of the device from refs, # deviceClass must be always 'vbd'. deviceClass = 'vbd' if dev_info is None: raise XendError("Device %s is not defined" % devid) dev_uuid = sxp.child_value(dev_info, 'uuid') del self.info['devices'][dev_uuid] self.info['%s_refs' % deviceClass].remove(dev_uuid) xen.xend.XendDomain.instance().managed_config_save(self) return rc def getDeviceSxprs(self, deviceClass): if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): return self.getDeviceController(deviceClass).sxprs() else: sxprs = [] dev_num = 0 for dev_type, dev_info in self.info.all_devices_sxpr(): if dev_type == deviceClass: sxprs.append([dev_num, dev_info]) dev_num += 1 return sxprs def getBlockDeviceClass(self, devid): # To get a device number from the devid, # we temporarily use the device controller of VBD. dev = self.getDeviceController('vbd').convertToDeviceNumber(devid) dev_info = self._getDeviceInfo_vbd(dev) if dev_info: return dev_info[0] def _getDeviceInfo_vif(self, mac): for dev_type, dev_info in self.info.all_devices_sxpr(): if dev_type != 'vif': continue if mac == sxp.child_value(dev_info, 'mac'): return dev_info def _getDeviceInfo_vbd(self, devid): for dev_type, dev_info in self.info.all_devices_sxpr(): if dev_type != 'vbd' and dev_type != 'tap': continue dev = sxp.child_value(dev_info, 'dev') dev = dev.split(':')[0] dev = self.getDeviceController(dev_type).convertToDeviceNumber(dev) if devid == dev: return dev_info def setMemoryTarget(self, target): """Set the memory target of this domain. @param target: In MiB. """ log.debug("Setting memory target of domain %s (%s) to %d MiB.", self.info['name_label'], str(self.domid), target) MiB = 1024 * 1024 self._safe_set_memory('memory_dynamic_min', target * MiB) self._safe_set_memory('memory_dynamic_max', target * MiB) if self.domid >= 0: self.storeVm("memory", target) self.storeDom("memory/target", target << 10) xen.xend.XendDomain.instance().managed_config_save(self) def setMemoryMaximum(self, limit): """Set the maximum memory limit of this domain @param limit: In MiB. """ log.debug("Setting memory maximum of domain %s (%s) to %d MiB.",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -