Unify the “--backend-parameters” option
[ganeti-local] / lib / hypervisor / hv_kvm.py
index 2394683..fd51ae5 100644 (file)
@@ -55,22 +55,22 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     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 os.path.isabs(x)),
-     "the VNC bind address must be either a valid IP address or an absolute"
-     " pathname", None, None),
+    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),
+    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+)',
@@ -78,11 +78,15 @@ class KVMHypervisor(hv_base.BaseHypervisor):
 
   _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):
@@ -146,24 +150,37 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     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 '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
     script.write("  # Execute the user-specific vif file\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
 
@@ -195,11 +212,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
 
     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))
@@ -626,7 +639,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
           time.sleep(2)
 
     utils.KillProcess(pid)
-    self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
+    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
 
   def GetNodeInfo(self):
     """Return information about the node.
@@ -717,3 +730,10 @@ class KVMHypervisor(hv_base.BaseHypervisor):
         hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
       raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
                                    " change the NIC type.")
+
+  @classmethod
+  def PowercycleNode(cls):
+    """KVM powercycle, just a wrapper over Linux powercycle.
+
+    """
+    cls.LinuxPowercycle()