Commit f48148c3 authored by Iustin Pop's avatar Iustin Pop
Browse files

Implement the new hypervisor API in base/xen

This patch adds the new methods CheckParameterSyntax and the
ValidateParameters in the base and xen hypervisors. It also changes the
xen hypervisor to use the new hvparams field on instance.

Reviewed-by: imsnah
parent 937e4814
......@@ -23,13 +23,18 @@
"""
from ganeti import errors
class BaseHypervisor(object):
"""Abstract virtualisation technology interface
The goal is that all aspects of the virtualisation technology must
be abstracted away from the rest of code.
The goal is that all aspects of the virtualisation technology are
abstracted away from the rest of code.
"""
PARAMETERS = []
def __init__(self):
pass
......@@ -106,3 +111,38 @@ class BaseHypervisor(object):
"""
raise NotImplementedError
@classmethod
def CheckParameterSyntax(cls, hvparams):
"""Check the given parameters for validity.
This should check the passed set of parameters for
validity. Classes should extend, not replace, this function.
@type hvparams: dict
@param hvparams: dictionary with parameter names/value
@raise errors.HypervisorError: when a parameter is not valid
"""
for key in hvparams:
if key not in cls.PARAMETERS:
raise errors.HypervisorError("Hypervisor parameter '%s'"
" not supported" % key)
for key in cls.PARAMETERS:
if key not in hvparams:
raise errors.HypervisorError("Hypervisor parameter '%s'"
" missing" % key)
def ValidateParameters(self, hvparams):
"""Check the given parameters for validity.
This should check the passed set of parameters for
validity. Classes should extend, not replace, this function.
@type hvparams: dict
@param hvparams: dictionary with parameter names/value
@raise errors.HypervisorError: when a parameter is not valid
"""
pass
......@@ -287,6 +287,54 @@ class XenHypervisor(hv_base.BaseHypervisor):
class XenPvmHypervisor(XenHypervisor):
"""Xen PVM hypervisor interface"""
PARAMETERS = [
constants.HV_KERNEL_PATH,
constants.HV_INITRD_PATH,
]
@classmethod
def CheckParameterSyntax(cls, hvparams):
"""Check the given parameters for validity.
For the PVM hypervisor, this only check the existence of the
kernel.
@type hvparams: dict
@param hvparams: dictionary with parameter names/value
@raise errors.HypervisorError: when a parameter is not valid
"""
super(XenPvmHypervisor, cls).CheckParameterSyntax(hvparams)
if not hvparams[constants.HV_KERNEL_PATH]:
raise errors.HypervisorError("Need a kernel for the instance")
if not os.path.isabs(hvparams[constants.HV_KERNEL_PATH]):
raise errors.HypervisorError("The kernel path must an absolute path")
if hvparams[constants.HV_INITRD_PATH]:
if not os.path.isabs(hvparams[constants.HV_INITRD_PATH]):
raise errors.HypervisorError("The initrd path must an absolute path"
", if defined")
def ValidateParameters(self, hvparams):
"""Check the given parameters for validity.
For the PVM hypervisor, this only check the existence of the
kernel.
"""
super(XenPvmHypervisor, self).ValidateParameters(hvparams)
kernel_path = hvparams[constants.HV_KERNEL_PATH]
if not os.path.isfile(kernel_path):
raise errors.HypervisorError("Instance kernel '%s' not found or"
" not a file" % kernel_path)
initrd_path = hvparams[constants.HV_INITRD_PATH]
if initrd_path and not os.path.isfile(initrd_path):
raise errors.HypervisorError("Instance initrd '%s' not found or"
" not a file" % initrd_path)
@classmethod
def _WriteConfigFile(cls, instance, block_devices, extra_args):
"""Write the Xen config file for the instance.
......@@ -296,31 +344,11 @@ class XenPvmHypervisor(XenHypervisor):
config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
# kernel handling
if instance.kernel_path in (None, constants.VALUE_DEFAULT):
kpath = constants.XEN_KERNEL
else:
if not os.path.exists(instance.kernel_path):
raise errors.HypervisorError("The kernel %s for instance %s is"
" missing" % (instance.kernel_path,
instance.name))
kpath = instance.kernel_path
kpath = instance.hvparams[constants.HV_KERNEL_PATH]
config.write("kernel = '%s'\n" % kpath)
# initrd handling
if instance.initrd_path in (None, constants.VALUE_DEFAULT):
if os.path.exists(constants.XEN_INITRD):
initrd_path = constants.XEN_INITRD
else:
initrd_path = None
elif instance.initrd_path == constants.VALUE_NONE:
initrd_path = None
else:
if not os.path.exists(instance.initrd_path):
raise errors.HypervisorError("The initrd %s for instance %s is"
" missing" % (instance.initrd_path,
instance.name))
initrd_path = instance.initrd_path
initrd_path = instance.hvparams[constants.HV_INITRD_PATH]
if initrd_path:
config.write("ramdisk = '%s'\n" % initrd_path)
......@@ -364,6 +392,72 @@ class XenPvmHypervisor(XenHypervisor):
class XenHvmHypervisor(XenHypervisor):
"""Xen HVM hypervisor interface"""
PARAMETERS = [
constants.HV_ACPI,
constants.HV_BOOT_ORDER,
constants.HV_CDROM_IMAGE_PATH,
constants.HV_DISK_TYPE,
constants.HV_NIC_TYPE,
constants.HV_PAE,
constants.HV_VNC_BIND_ADDRESS,
]
@classmethod
def CheckParameterSyntax(cls, hvparams):
"""Check the given parameter syntax.
"""
super(XenHvmHypervisor, cls).CheckParameterSyntax(hvparams)
# boot order verification
boot_order = hvparams[constants.HV_BOOT_ORDER]
if len(boot_order.strip("acdn")) != 0:
raise errors.HypervisorError("Invalid boot order '%s' specified,"
" must be one or more of [acdn]" %
boot_order)
# device type checks
nic_type = hvparams[constants.HV_NIC_TYPE]
if nic_type not in constants.HT_HVM_VALID_NIC_TYPES:
raise errors.HypervisorError("Invalid NIC type %s specified for Xen HVM"
" hypervisor" % nic_type)
disk_type = hvparams[constants.HV_DISK_TYPE]
if disk_type not in constants.HT_HVM_VALID_DISK_TYPES:
raise errors.HypervisorError("Invalid disk type %s specified for Xen HVM"
" hypervisor" % disk_type)
# vnc_bind_address verification
vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
if vnc_bind_address is not None:
if not utils.IsValidIP(vnc_bind_address):
raise errors.OpPrereqError("given VNC bind address '%s' doesn't look"
" like a valid IP address" %
vnc_bind_address)
iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
if iso_path and not os.path.isabs(iso_path):
raise errors.HypervisorError("The path to the HVM CDROM image must"
" be an absolute path or None, not %s" %
iso_path)
def ValidateParameters(self, hvparams):
"""Check the given parameters for validity.
For the PVM hypervisor, this only check the existence of the
kernel.
@type hvparams: dict
@param hvparams: dictionary with parameter names/value
@raise errors.HypervisorError: when a parameter is not valid
"""
super(XenHvmHypervisor, self).ValidateParameters(hvparams)
# hvm_cdrom_image_path verification
iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
if iso_path and not os.path.isfile(iso_path):
raise errors.HypervisorError("The HVM CDROM image must either be a"
" regular file or a symlink pointing to"
" an existing regular file, not %s" %
iso_path)
@classmethod
def _WriteConfigFile(cls, instance, block_devices, extra_args):
"""Create a Xen 3.1 HVM config file.
......@@ -376,11 +470,11 @@ class XenHvmHypervisor(XenHypervisor):
config.write("memory = %d\n" % instance.memory)
config.write("vcpus = %d\n" % instance.vcpus)
config.write("name = '%s'\n" % instance.name)
if instance.hvm_pae:
if instance.hvparams[constants.HV_PAE]:
config.write("pae = 1\n")
else:
config.write("pae = 0\n")
if instance.hvm_acpi:
if instance.hvparams[constants.HV_ACPI]:
config.write("acpi = 1\n")
else:
config.write("acpi = 0\n")
......@@ -390,18 +484,19 @@ class XenHvmHypervisor(XenHypervisor):
config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
else:
config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
if instance.hvm_boot_order is None:
if instance.hvparams[constants.HV_BOOT_ORDER] is None:
config.write("boot = '%s'\n" % constants.HT_HVM_DEFAULT_BOOT_ORDER)
else:
config.write("boot = '%s'\n" % instance.hvm_boot_order)
config.write("boot = '%s'\n" % instance.hvparams["boot_order"])
config.write("sdl = 0\n")
config.write("usb = 1\n")
config.write("usbdevice = 'tablet'\n")
config.write("vnc = 1\n")
if instance.vnc_bind_address is None:
if instance.hvparams[constants.HV_VNC_BIND_ADDRESS] is None:
config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
else:
config.write("vnclisten = '%s'\n" % instance.vnc_bind_address)
config.write("vnclisten = '%s'\n" %
instance.hvparams["vnc_bind_address"])
if instance.network_port > constants.HT_HVM_VNC_BASE_PORT:
display = instance.network_port - constants.HT_HVM_VNC_BASE_PORT
......@@ -427,15 +522,16 @@ class XenHvmHypervisor(XenHypervisor):
config.write("localtime = 1\n")
vif_data = []
nic_type = instance.hvparams[constants.HV_NIC_TYPE]
if nic_type is None:
# ensure old instances don't change
nic_type_str = ", type=ioemu"
elif nic_type == constants.HT_HVM_DEV_PARAVIRTUAL:
nic_type_str = ", type=paravirtualized"
else:
nic_type_str = ", model=%s, type=ioemu" % nic_type
for nic in instance.nics:
if instance.hvm_nic_type is None: # ensure old instances don't change
nic_type = ", type=ioemu"
elif instance.hvm_nic_type == constants.HT_HVM_DEV_PARAVIRTUAL:
nic_type = ", type=paravirtualized"
else:
nic_type = ", model=%s, type=ioemu" % instance.hvm_nic_type
nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type)
nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type_str)
ip = getattr(nic, "ip", None)
if ip is not None:
nic_str += ", ip=%s" % ip
......@@ -444,14 +540,15 @@ class XenHvmHypervisor(XenHypervisor):
config.write("vif = [%s]\n" % ",".join(vif_data))
disk_data = cls._GetConfigFileDiskData(instance.disk_template,
block_devices)
if ((instance.hvm_disk_type is None) or
(instance.hvm_disk_type == constants.HT_HVM_DEV_IOEMU)):
disk_type = instance.hvparams[constants.HV_DISK_TYPE]
if disk_type in (None, constants.HT_HVM_DEV_IOEMU):
replacement = ",ioemu:hd"
else:
replacement = ",hd"
disk_data = [line.replace(",sd", replacement) for line in disk_data]
if instance.hvm_cdrom_image_path is not None:
iso = "'file:%s,hdc:cdrom,r'" % (instance.hvm_cdrom_image_path)
iso_path = instance.hvparams[constants.HV_CDROM_IMAGE_PATH]
if iso_path:
iso = "'file:%s,hdc:cdrom,r'" % iso_path
disk_data.append(iso)
config.write("disk = [%s]\n" % (",".join(disk_data)))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment