if config.ConfigWriter.IsCluster():
raise errors.OpPrereqError("Cluster is already initialised")
+ if self.op.hypervisor_type == constants.HT_XEN_HVM31:
+ if not os.path.exists(constants.VNC_PASSWORD_FILE):
+ raise errors.OpPrereqError("Please prepare the cluster VNC"
+ "password file %s" %
+ constants.VNC_PASSWORD_FILE)
+
self.hostname = hostname = utils.HostInfo()
if hostname.ip.startswith("127."):
primary_ip=primary_ip,
secondary_ip=secondary_ip)
+ if self.sstore.GetHypervisorType() == constants.HT_XEN_HVM31:
+ if not os.path.exists(constants.VNC_PASSWORD_FILE):
+ raise errors.OpPrereqError("Cluster VNC password file %s missing" %
+ constants.VNC_PASSWORD_FILE)
+
def Exec(self, feedback_fn):
"""Adds the new node to the cluster.
(fname, to_node))
to_copy = ss.GetFileList()
+ if self.sstore.GetHypervisorType() == constants.HT_XEN_HVM31:
+ to_copy.append(constants.VNC_PASSWORD_FILE)
for fname in to_copy:
if not ssh.CopyFileToNode(node, fname):
logger.Error("could not copy file %s to node %s" % (fname, node))
if self.inst_ip is not None:
nic.ip = self.inst_ip
- network_port = None # placeholder assignment for later
+ ht_kind = self.sstore.GetHypervisorType()
+ if ht_kind in constants.HTS_REQ_PORT:
+ network_port = self.cfg.AllocatePort()
+ else:
+ network_port = None
disks = _GenerateDiskTemplate(self.cfg,
self.op.disk_template,
from ganeti import logger
from ganeti import ssconf
from ganeti import constants
+from ganeti import errors
from ganeti.errors import HypervisorError
cls = XenPvmHypervisor
elif ht_kind == constants.HT_FAKE:
cls = FakeHypervisor
+ elif ht_kind == constants.HT_XEN_HVM31:
+ cls = XenHvmHypervisor
else:
raise HypervisorError("Unknown hypervisor type '%s'" % ht_kind)
return cls()
"""
if not os.path.exists(self._ROOT_DIR):
return "The required directory '%s' does not exist." % self._ROOT_DIR
+
+
+class XenHvmHypervisor(XenHypervisor):
+ """Xen HVM hypervisor interface"""
+
+ @staticmethod
+ def _WriteConfigFile(instance, block_devices, extra_args):
+ """Create a Xen 3.1 HVM config file.
+
+ """
+ config = StringIO()
+ config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
+ config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
+ config.write("builder = 'hvm'\n")
+ config.write("memory = %d\n" % instance.memory)
+ config.write("vcpus = %d\n" % instance.vcpus)
+ config.write("name = '%s'\n" % instance.name)
+ config.write("pae = 1\n")
+ config.write("acpi = 1\n")
+ config.write("apic = 1\n")
+ arch = os.uname()[4]
+ if '64' in arch:
+ config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
+ else:
+ config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
+ config.write("boot = 'dc'\n")
+ config.write("sdl = 0\n")
+ config.write("vnc = 1\n")
+ config.write("vnclisten = '0.0.0.0'\n")
+
+ if instance.network_port > constants.HT_HVM_VNC_BASE_PORT:
+ display = instance.network_port - constants.HT_HVM_VNC_BASE_PORT
+ config.write("vncdisplay = %s\n" % display)
+ config.write("vncunused = 0\n")
+ else:
+ config.write("# vncdisplay = 1\n")
+ config.write("vncunused = 1\n")
+
+ try:
+ password_file = open(constants.VNC_PASSWORD_FILE, "r")
+ try:
+ password = password_file.readline()
+ finally:
+ password_file.close()
+ except IOError:
+ raise errors.OpExecError("failed to open VNC password file %s " %
+ constants.VNC_PASSWORD_FILE)
+
+ config.write("vncpasswd = '%s'\n" % password.rstrip())
+
+ config.write("serial = 'pty'\n")
+ config.write("localtime = 1\n")
+
+ vif_data = []
+ for nic in instance.nics:
+ nic_str = "mac=%s, bridge=%s, type=ioemu" % (nic.mac, nic.bridge)
+ ip = getattr(nic, "ip", None)
+ if ip is not None:
+ nic_str += ", ip=%s" % ip
+ vif_data.append("'%s'" % nic_str)
+
+ config.write("vif = [%s]\n" % ",".join(vif_data))
+
+ disk_data = ["'phy:%s,%s,w'" %
+ (rldev.dev_path, cfdev.iv_name.replace("sd", "ioemu:hd"))
+ for cfdev, rldev in block_devices]
+ iso = "'file:/srv/ganeti/iso/hvm-install.iso,hdc:cdrom,r'"
+ config.write("disk = [%s, %s]\n" % (",".join(disk_data), iso) )
+
+ config.write("on_poweroff = 'destroy'\n")
+ config.write("on_reboot = 'restart'\n")
+ config.write("on_crash = 'restart'\n")
+ if extra_args:
+ config.write("extra = '%s'\n" % extra_args)
+ # just in case it exists
+ utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
+ try:
+ f = open("/etc/xen/%s" % instance.name, "w")
+ try:
+ f.write(config.getvalue())
+ finally:
+ f.close()
+ except IOError, err:
+ raise errors.OpExecError("Cannot write Xen instance confile"
+ " file /etc/xen/%s: %s" % (instance.name, err))
+ return True
+
+ @staticmethod
+ def GetShellCommandForConsole(instance):
+ """Return a command for connecting to the console of an instance.
+
+ """
+ if instance.network_port is None:
+ raise errors.OpExecError("no console port defined for %s"
+ % instance.name)
+ else:
+ raise errors.OpExecError("no PTY console, connect to %s:%s via VNC"
+ % (instance.primary_node,
+ instance.network_port))
" addresses",
metavar="ADDRESS", default=None),
make_option("-t", "--hypervisor-type", dest="hypervisor_type",
- help="Specify the hypervisor type (xen-3.0, fake)",
- metavar="TYPE", choices=["xen-3.0", "fake"],
+ help="Specify the hypervisor type "
+ "(xen-3.0, fake, xen-hvm-3.1)",
+ metavar="TYPE", choices=["xen-3.0",
+ "fake",
+ "xen-hvm-3.1"],
default="xen-3.0",),
make_option("-m", "--mac-prefix", dest="mac_prefix",
help="Specify the mac prefix for the instance IP"