return _ParseInstanceList(lines, include_node)
+def _IsInstanceRunning(instance_info):
+ return instance_info == "r-----" \
+ or instance_info == "-b----"
+
+
+def _IsInstanceShutdown(instance_info):
+ return instance_info == "---s--"
+
+
def _ParseNodeInfo(info):
"""Return information about the node.
disk_data = []
- for sd_suffix, (cfdev, dev_path) in zip(_letters, block_devices):
+ for sd_suffix, (cfdev, dev_path, _) in zip(_letters, block_devices):
sd_name = blockdev_prefix + sd_suffix
if cfdev.mode == constants.DISK_RDWR:
mode = "r"
if cfdev.dev_type in [constants.DT_FILE, constants.DT_SHARED_FILE]:
- driver = _FILE_DRIVER_MAP[cfdev.physical_id[0]]
+ driver = _FILE_DRIVER_MAP[cfdev.logical_id[0]]
else:
driver = "phy"
return disk_data
+def _QuoteCpuidField(data):
+ """Add quotes around the CPUID field only if necessary.
+
+ Xen CPUID fields come in two shapes: LIBXL strings, which need quotes around
+ them, and lists of XEND strings, which don't.
+
+ @param data: Either type of parameter.
+ @return: The quoted version thereof.
+
+ """
+ return "'%s'" % data if data.startswith("host") else data
+
+
class XenHypervisor(hv_base.BaseHypervisor):
"""Xen generic hypervisor interface
self._cmd = _cmd
+ @staticmethod
+ def _GetCommandFromHvparams(hvparams):
+ """Returns the Xen command extracted from the given hvparams.
+
+ @type hvparams: dict of strings
+ @param hvparams: hypervisor parameters
+
+ """
+ if hvparams is None or constants.HV_XEN_CMD not in hvparams:
+ raise errors.HypervisorError("Cannot determine xen command.")
+ else:
+ return hvparams[constants.HV_XEN_CMD]
+
def _GetCommand(self, hvparams):
"""Returns Xen command to use.
"""
if self._cmd is None:
- if hvparams is None or constants.HV_XEN_CMD not in hvparams:
- raise errors.HypervisorError("Cannot determine xen command.")
- else:
- cmd = hvparams[constants.HV_XEN_CMD]
+ cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
else:
cmd = self._cmd
return utils.PathJoin(self._cfgdir, instance_name)
@classmethod
- def _WriteNICInfoFile(cls, instance_name, idx, nic):
+ def _WriteNICInfoFile(cls, instance, idx, nic):
"""Write the Xen config file for the instance.
This version of the function just writes the config file from static data.
"""
+ instance_name = instance.name
dirs = [(dname, constants.RUN_DIRS_MODE)
for dname in cls._DIRS + [cls._InstanceNICDir(instance_name)]]
utils.EnsureDirs(dirs)
cfg_file = cls._InstanceNICFile(instance_name, idx)
data = StringIO()
+ data.write("TAGS=%s\n" % "\ ".join(instance.GetTags()))
if nic.netinfo:
netinfo = objects.Network.FromDict(nic.netinfo)
- data.write("NETWORK_NAME=%s\n" % netinfo.name)
- if netinfo.network:
- data.write("NETWORK_SUBNET=%s\n" % netinfo.network)
- if netinfo.gateway:
- data.write("NETWORK_GATEWAY=%s\n" % netinfo.gateway)
- if netinfo.network6:
- data.write("NETWORK_SUBNET6=%s\n" % netinfo.network6)
- if netinfo.gateway6:
- data.write("NETWORK_GATEWAY6=%s\n" % netinfo.gateway6)
- if netinfo.mac_prefix:
- data.write("NETWORK_MAC_PREFIX=%s\n" % netinfo.mac_prefix)
- if netinfo.tags:
- data.write("NETWORK_TAGS=%s\n" % r"\ ".join(netinfo.tags))
+ for k, v in netinfo.HooksDict().iteritems():
+ data.write("%s=%s\n" % (k, v))
data.write("MAC=%s\n" % nic.mac)
- data.write("IP=%s\n" % nic.ip)
+ if nic.ip:
+ data.write("IP=%s\n" % nic.ip)
+ data.write("INTERFACE_INDEX=%s\n" % str(idx))
+ if nic.name:
+ data.write("INTERFACE_NAME=%s\n" % nic.name)
+ data.write("INTERFACE_UUID=%s\n" % nic.uuid)
data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
return self._StopInstance(name, force, instance.hvparams)
+ def _ShutdownInstance(self, name, hvparams):
+ """Shutdown an instance if the instance is running.
+
+ @type name: string
+ @param name: name of the instance to stop
+ @type hvparams: dict of string
+ @param hvparams: hypervisor parameters of the instance
+
+ The '-w' flag waits for shutdown to complete which avoids the need
+ to poll in the case where we want to destroy the domain
+ immediately after shutdown.
+
+ """
+ instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
+
+ if instance_info is None or _IsInstanceShutdown(instance_info[4]):
+ logging.info("Failed to shutdown instance %s, not running", name)
+ return None
+
+ return self._RunXen(["shutdown", "-w", name], hvparams)
+
+ def _DestroyInstance(self, name, hvparams):
+ """Destroy an instance if the instance if the instance exists.
+
+ @type name: string
+ @param name: name of the instance to destroy
+ @type hvparams: dict of string
+ @param hvparams: hypervisor parameters of the instance
+
+ """
+ instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
+
+ if instance_info is None:
+ logging.info("Failed to destroy instance %s, does not exist", name)
+ return None
+
+ return self._RunXen(["destroy", name], hvparams)
+
def _StopInstance(self, name, force, hvparams):
"""Stop an instance.
@type name: string
- @param name: name of the instance to be shutdown
+ @param name: name of the instance to destroy
+
@type force: boolean
- @param force: flag specifying whether shutdown should be forced
+ @param force: whether to do a "hard" stop (destroy)
+
@type hvparams: dict of string
@param hvparams: hypervisor parameters of the instance
"""
if force:
- action = "destroy"
+ result = self._DestroyInstance(name, hvparams)
else:
- action = "shutdown"
+ self._ShutdownInstance(name, hvparams)
+ result = self._DestroyInstance(name, hvparams)
- result = self._RunXen([action, name], hvparams)
- if result.failed:
+ if result is not None and result.failed and \
+ self.GetInstanceInfo(name, hvparams=hvparams) is not None:
raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
(name, result.fail_reason, result.output))
instance_list = self._GetInstanceList(True, hvparams)
return _GetNodeInfo(result.stdout, instance_list)
- def GetInstanceConsole(self, instance, primary_node, hvparams, beparams):
+ @classmethod
+ def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
"""Return a command for connecting to the console of an instance.
"""
- xen_cmd = self._GetCommand(hvparams)
+ xen_cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
return objects.InstanceConsole(instance=instance.name,
kind=constants.CONS_SSH,
host=primary_node.name,
constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
constants.HV_XEN_CMD:
hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
+ constants.HV_XEN_CPUID: hv_base.NO_CHECK,
+ constants.HV_SOUNDHW: hv_base.NO_CHECK,
}
def _GetConfig(self, instance, startup_memory, block_devices):
if hvp[constants.HV_VIF_SCRIPT]:
nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
vif_data.append("'%s'" % nic_str)
- self._WriteNICInfoFile(instance.name, idx, nic)
+ self._WriteNICInfoFile(instance, idx, nic)
disk_data = \
_GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
config.write("on_crash = 'restart'\n")
config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
+ cpuid = hvp[constants.HV_XEN_CPUID]
+ if cpuid:
+ config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
+
+ if hvp[constants.HV_SOUNDHW]:
+ config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
+
return config.getvalue()
constants.HV_VIRIDIAN: hv_base.NO_CHECK,
constants.HV_XEN_CMD:
hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
+ constants.HV_XEN_CPUID: hv_base.NO_CHECK,
+ constants.HV_SOUNDHW: hv_base.NO_CHECK,
}
def _GetConfig(self, instance, startup_memory, block_devices):
if hvp[constants.HV_VIF_SCRIPT]:
nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
vif_data.append("'%s'" % nic_str)
- self._WriteNICInfoFile(instance.name, idx, nic)
+ self._WriteNICInfoFile(instance, idx, nic)
config.write("vif = [%s]\n" % ",".join(vif_data))
config.write("on_reboot = 'destroy'\n")
config.write("on_crash = 'restart'\n")
+ cpuid = hvp[constants.HV_XEN_CPUID]
+ if cpuid:
+ config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
+
+ if hvp[constants.HV_SOUNDHW]:
+ config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
+
return config.getvalue()