_CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
_DIRS = [_ROOT_DIR, _PIDS_DIR, _CTRL_DIR, _CONF_DIR]
- PARAMETERS = [
- constants.HV_KERNEL_PATH,
- constants.HV_INITRD_PATH,
- constants.HV_ROOT_PATH,
- constants.HV_KERNEL_ARGS,
- constants.HV_ACPI,
- constants.HV_SERIAL_CONSOLE,
- constants.HV_VNC_BIND_ADDRESS,
- constants.HV_VNC_TLS,
- constants.HV_VNC_X509,
- constants.HV_VNC_X509_VERIFY,
- constants.HV_CDROM_IMAGE_PATH,
- constants.HV_BOOT_ORDER,
- constants.HV_NIC_TYPE,
- constants.HV_DISK_TYPE,
- constants.HV_USB_MOUSE,
- ]
+ PARAMETERS = {
+ constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
+ constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
+ constants.HV_ROOT_PATH: hv_base.NO_CHECK,
+ constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
+ constants.HV_ACPI: hv_base.NO_CHECK,
+ constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
+ constants.HV_VNC_BIND_ADDRESS:
+ (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
+ "the VNC bind address must be either a valid IP address or an absolute"
+ " pathname", None, None),
+ constants.HV_VNC_TLS: hv_base.NO_CHECK,
+ constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
+ constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
+ constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
+ constants.HV_BOOT_ORDER:
+ hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
+ constants.HV_NIC_TYPE:
+ hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
+ constants.HV_DISK_TYPE:
+ hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
+ constants.HV_USB_MOUSE:
+ hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
+ }
_MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
re.M | re.I)
+ _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
+
+ ANCILLARY_FILES = [
+ _KVM_NETWORK_SCRIPT,
+ ]
+
def __init__(self):
hv_base.BaseHypervisor.__init__(self)
# Let's make sure the directories we need exist, even if the RUN_DIR lives
# in a tmpfs filesystem or has been otherwise wiped out.
- dirs = [(dir, constants.RUN_DIRS_MODE) for dir in self._DIRS]
+ dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
utils.EnsureDirs(dirs)
def _InstancePidAlive(self, instance_name):
"""
return '%s/%s.runtime' % (cls._CONF_DIR, instance_name)
+ @classmethod
+ def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
+ """Removes an instance's rutime sockets/files.
+
+ """
+ utils.RemoveFile(pidfile)
+ utils.RemoveFile(cls._InstanceMonitor(instance_name))
+ utils.RemoveFile(cls._InstanceSerial(instance_name))
+ utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
+
def _WriteNetScript(self, instance, seq, nic):
"""Write a script to connect a net interface to the proper bridge.
script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
script.write("export INSTANCE=%s\n" % instance.name)
script.write("export MAC=%s\n" % nic.mac)
- script.write("export IP=%s\n" % nic.ip)
- script.write("export BRIDGE=%s\n" % nic.bridge)
+ if nic.ip:
+ script.write("export IP=%s\n" % nic.ip)
+ script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
+ if nic.nicparams[constants.NIC_LINK]:
+ script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
+ if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
+ script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
script.write("export INTERFACE=$1\n")
# TODO: make this configurable at ./configure time
- script.write("if [ -x /etc/ganeti/kvm-vif-bridge ]; then\n")
+ script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
script.write(" # Execute the user-specific vif file\n")
- script.write(" /etc/ganeti/kvm-vif-bridge\n")
+ script.write(" %s\n" % self._KVM_NETWORK_SCRIPT)
script.write("else\n")
- script.write(" # Connect the interface to the bridge\n")
script.write(" /sbin/ifconfig $INTERFACE 0.0.0.0 up\n")
- script.write(" /usr/sbin/brctl addif $BRIDGE $INTERFACE\n")
+ if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
+ script.write(" # Connect the interface to the bridge\n")
+ script.write(" /usr/sbin/brctl addif $BRIDGE $INTERFACE\n")
+ elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
+ script.write(" # Route traffic targeted at the IP to the interface\n")
+ script.write(" /sbin/ip route add $IP/32 dev $INTERFACE\n")
+ interface_proxy_arp = "/proc/sys/net/ipv4/conf/$INTERFACE/proxy_arp"
+ script.write(" /bin/echo 1 > %s\n" % interface_proxy_arp)
script.write("fi\n\n")
# As much as we'd like to put this in our _ROOT_DIR, that will happen to be
# mounted noexec sometimes, so we'll have to find another place.
(tmpfd, tmpfile_name) = tempfile.mkstemp()
tmpfile = os.fdopen(tmpfd, 'w')
- tmpfile.write(script.getvalue())
- tmpfile.close()
+ try:
+ tmpfile.write(script.getvalue())
+ finally:
+ tmpfile.close()
os.chmod(tmpfile_name, 0755)
return tmpfile_name
cmdline_file = "/proc/%s/cmdline" % pid
try:
- fh = open(cmdline_file, 'r')
- try:
- cmdline = fh.read()
- finally:
- fh.close()
+ cmdline = utils.ReadFile(cmdline_file)
except EnvironmentError, err:
raise errors.HypervisorError("Failed to list instance %s: %s" %
(instance_name, err))
self._RetryInstancePowerdown(instance, pid)
if not utils.IsProcessAlive(pid):
- utils.RemoveFile(pidfile)
- utils.RemoveFile(self._InstanceMonitor(instance.name))
- utils.RemoveFile(self._InstanceSerial(instance.name))
- utils.RemoveFile(self._InstanceKVMRuntime(instance.name))
+ self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
return True
else:
return False
time.sleep(2)
utils.KillProcess(pid)
- utils.RemoveFile(pidfile)
- utils.RemoveFile(self._InstanceMonitor(instance_name))
- utils.RemoveFile(self._InstanceSerial(instance_name))
- utils.RemoveFile(self._InstanceKVMRuntime(instance_name))
+ self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
def GetNodeInfo(self):
"""Return information about the node.
kernel_path = hvparams[constants.HV_KERNEL_PATH]
if kernel_path:
- if not os.path.isabs(hvparams[constants.HV_KERNEL_PATH]):
- raise errors.HypervisorError("The kernel path must be an absolute path"
- ", if defined")
-
if not hvparams[constants.HV_ROOT_PATH]:
- raise errors.HypervisorError("Need a root partition for the instance"
- ", if a kernel is defined")
+ raise errors.HypervisorError("Need a root partition for the instance,"
+ " if a kernel is defined")
- 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")
-
- vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
- if vnc_bind_address:
- if not utils.IsValidIP(vnc_bind_address):
- if not os.path.isabs(vnc_bind_address):
- raise errors.HypervisorError("The VNC bind address must be either"
- " a valid IP address or an absolute"
- " pathname. '%s' given" %
- vnc_bind_address)
-
- if hvparams[constants.HV_VNC_X509_VERIFY] and \
- not hvparams[constants.HV_VNC_X509]:
- raise errors.HypervisorError("%s must be defined, if %s is" %
- (constants.HV_VNC_X509,
- constants.HV_VNC_X509_VERIFY))
-
- if hvparams[constants.HV_VNC_X509]:
- if not os.path.isabs(hvparams[constants.HV_VNC_X509]):
- raise errors.HypervisorError("The vnc x509 path must an absolute path"
- ", if defined")
-
- 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 CDROM image must be"
- " an absolute path, if defined")
+ if (hvparams[constants.HV_VNC_X509_VERIFY] and
+ not hvparams[constants.HV_VNC_X509]):
+ raise errors.HypervisorError("%s must be defined, if %s is" %
+ (constants.HV_VNC_X509,
+ constants.HV_VNC_X509_VERIFY))
boot_order = hvparams[constants.HV_BOOT_ORDER]
- if boot_order not in constants.HT_KVM_VALID_BO_TYPES:
- raise errors.HypervisorError(\
- "The boot order must be one of %s" %
- utils.CommaJoin(constants.HT_KVM_VALID_BO_TYPES))
- if boot_order == constants.HT_BO_CDROM and not iso_path:
+ if (boot_order == constants.HT_BO_CDROM and
+ not hvparams[constants.HV_CDROM_IMAGE_PATH]):
raise errors.HypervisorError("Cannot boot from cdrom without an"
" ISO path")
-
- nic_type = hvparams[constants.HV_NIC_TYPE]
- if nic_type not in constants.HT_KVM_VALID_NIC_TYPES:
- raise errors.HypervisorError(\
- "Invalid NIC type %s specified for the KVM"
- " hypervisor. Please choose one of: %s" %
- (nic_type, utils.CommaJoin(constants.HT_KVM_VALID_NIC_TYPES)))
- elif (boot_order == constants.HT_BO_NETWORK and
- nic_type == constants.HT_NIC_PARAVIRTUAL):
+ if (boot_order == constants.HT_BO_NETWORK and
+ hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
" change the NIC type.")
- disk_type = hvparams[constants.HV_DISK_TYPE]
- if disk_type not in constants.HT_KVM_VALID_DISK_TYPES:
- raise errors.HypervisorError(\
- "Invalid disk type %s specified for the KVM"
- " hypervisor. Please choose one of: %s" %
- (disk_type, utils.CommaJoin(constants.HT_KVM_VALID_DISK_TYPES)))
-
- mouse_type = hvparams[constants.HV_USB_MOUSE]
- if mouse_type and mouse_type not in constants.HT_KVM_VALID_MOUSE_TYPES:
- raise errors.HypervisorError(\
- "Invalid usb mouse type %s specified for the KVM hypervisor. Please"
- " choose one of %s" %
- utils.CommaJoin(constants.HT_KVM_VALID_MOUSE_TYPES))
-
- def ValidateParameters(self, hvparams):
- """Check the given parameters for validity.
-
- For the KVM hypervisor, this checks the existence of the
- kernel.
+ @classmethod
+ def PowercycleNode(cls):
+ """KVM powercycle, just a wrapper over Linux powercycle.
"""
- super(KVMHypervisor, self).ValidateParameters(hvparams)
-
- kernel_path = hvparams[constants.HV_KERNEL_PATH]
- if kernel_path and 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)
-
- vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
- if vnc_bind_address and not utils.IsValidIP(vnc_bind_address) and \
- not os.path.isdir(vnc_bind_address):
- raise errors.HypervisorError("Instance vnc bind address must be either"
- " an ip address or an existing directory")
-
- vnc_x509 = hvparams[constants.HV_VNC_X509]
- if vnc_x509 and not os.path.isdir(vnc_x509):
- raise errors.HypervisorError("Instance vnc x509 path '%s' not found"
- " or not a directory" % vnc_x509)
-
- iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
- if iso_path and not os.path.isfile(iso_path):
- raise errors.HypervisorError("Instance cdrom image '%s' not found or"
- " not a file" % iso_path)
+ cls.LinuxPowercycle()