For every NIC write down a file that contains NIC's
info (MAC, mode, link, network details), that can
be sourced by any vif script.  The file location is:
/var/run/ganeti/xen-hypervisor/nic/<domname>/<nicidx>.

This file is created upon cfg file creation and before
starting the instance.

Upon Xen configuration file removal, remove corresponding
NIC dir as well.

Add new hv param vif_script that allows execution of
a user defined vif script and overrides the one
xend is configured with (in xend-config.sxp).

Signed-off-by: Dimitris Aragiorgis <[email protected]>
---
 lib/constants.py         |    4 +++
 lib/hypervisor/hv_xen.py |   74 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/lib/constants.py b/lib/constants.py
index 0266b2b..97b9fe8 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -943,6 +943,7 @@ HV_KVM_EXTRA = "kvm_extra"
 HV_KVM_MACHINE_VERSION = "machine_version"
 HV_KVM_PATH = "kvm_path"
 HV_VIF_TYPE = "vif_type"
+HV_VIF_SCRIPT = "vif_script"
 
 
 HVS_PARAMETER_TYPES = {
@@ -1013,6 +1014,7 @@ HVS_PARAMETER_TYPES = {
   HV_KVM_EXTRA: VTYPE_STRING,
   HV_KVM_MACHINE_VERSION: VTYPE_STRING,
   HV_VIF_TYPE: VTYPE_STRING,
+  HV_VIF_SCRIPT: VTYPE_STRING,
   }
 
 HVS_PARAMETERS = frozenset(HVS_PARAMETER_TYPES.keys())
@@ -2020,6 +2022,7 @@ HVC_DEFAULTS = {
     HV_CPU_MASK: CPU_PINNING_ALL,
     HV_CPU_CAP: 0,
     HV_CPU_WEIGHT: 256,
+    HV_VIF_SCRIPT: "",
     },
   HT_XEN_HVM: {
     HV_BOOT_ORDER: "cd",
@@ -2042,6 +2045,7 @@ HVC_DEFAULTS = {
     HV_CPU_CAP: 0,
     HV_CPU_WEIGHT: 256,
     HV_VIF_TYPE: HT_HVM_VIF_IOEMU,
+    HV_VIF_SCRIPT: "",
     },
   HT_KVM: {
     HV_KVM_PATH: KVM_PATH,
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index 653f6b2..b482892 100644
--- a/lib/hypervisor/hv_xen.py
+++ b/lib/hypervisor/hv_xen.py
@@ -25,6 +25,7 @@
 
 import logging
 import string # pylint: disable=W0402
+import shutil
 from cStringIO import StringIO
 
 from ganeti import constants
@@ -310,6 +311,8 @@ class XenHypervisor(hv_base.BaseHypervisor):
   CAN_MIGRATE = True
   REBOOT_RETRY_COUNT = 60
   REBOOT_RETRY_INTERVAL = 10
+  _ROOT_DIR = pathutils.RUN_DIR + "/xen-hypervisor"
+  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
 
   ANCILLARY_FILES = [
     XEND_CONFIG_FILE,
@@ -373,6 +376,60 @@ class XenHypervisor(hv_base.BaseHypervisor):
     return utils.PathJoin(self._cfgdir, instance_name)
 
   @classmethod
+  def _WriteNICInfoFile(cls, instance_name, idx, nic):
+    """Write the Xen config file for the instance.
+
+    This version of the function just writes the config file from static data.
+
+    """
+    utils.EnsureDirs([(cls._InstanceNICDir(instance_name),
+                     constants.RUN_DIRS_MODE)])
+    cfg_file = cls._InstanceNICFile(instance_name, idx)
+    data = StringIO()
+
+    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" % "\ ".join(netinfo.tags))
+
+    data.write("MAC=%s\n" % nic.mac)
+    data.write("IP=%s\n" % nic.ip)
+    data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
+    data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
+
+    try:
+      utils.WriteFile(cfg_file, data=data.getvalue())
+    except EnvironmentError, err:
+      raise errors.HypervisorError("Cannot write Xen instance configuration"
+                                   " file %s: %s" % (cfg_file, err))
+
+  @classmethod
+  def _InstanceNICDir(cls, instance_name):
+    """Returns the name of the directory holding the tap device files for a
+    given instance.
+
+    """
+    return utils.PathJoin(cls._NICS_DIR, instance_name)
+
+  @classmethod
+  def _InstanceNICFile(cls, instance_name, seq):
+    """Returns the name of the file containing the tap device for a given NIC
+
+    """
+    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
+
+  @classmethod
   def _GetConfig(cls, instance, startup_memory, block_devices):
     """Build Xen configuration for an instance.
 
@@ -413,6 +470,11 @@ class XenHypervisor(hv_base.BaseHypervisor):
 
     """
     utils.RemoveFile(self._ConfigFileName(instance_name))
+    try:
+      shutil.rmtree(self._InstanceNICDir(instance_name))
+    except OSError, err:
+      if err.errno != errno.ENOENT:
+        raise
 
   def _GetXmList(self, include_node):
     """Wrapper around module level L{_GetXmList}.
@@ -789,6 +851,7 @@ class XenPvmHypervisor(XenHypervisor):
     constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
     constants.HV_CPU_WEIGHT:
       (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
+    constants.HV_VIF_SCRIPT: hv_base.NO_CHECK,
     }
 
   def _GetConfig(self, instance, startup_memory, block_devices):
@@ -840,14 +903,17 @@ class XenPvmHypervisor(XenHypervisor):
     config.write("name = '%s'\n" % instance.name)
 
     vif_data = []
-    for nic in instance.nics:
+    for idx, nic in enumerate(instance.nics):
       nic_str = "mac=%s" % (nic.mac)
       ip = getattr(nic, "ip", None)
       if ip is not None:
         nic_str += ", ip=%s" % ip
       if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
         nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
+      if hvp[constants.HV_VIF_SCRIPT]:
+        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
       vif_data.append("'%s'" % nic_str)
+      cls._WriteNICInfoFile(instance.name, idx, nic)
 
     disk_data = \
       _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
@@ -911,6 +977,7 @@ class XenHvmHypervisor(XenHypervisor):
       (False, lambda x: 0 < x < 65535, "invalid weight", None, None),
     constants.HV_VIF_TYPE:
       hv_base.ParamInSet(False, constants.HT_HVM_VALID_VIF_TYPES),
+    constants.HV_VIF_SCRIPT: hv_base.NO_CHECK,
     }
 
   def _GetConfig(self, instance, startup_memory, block_devices):
@@ -999,14 +1066,17 @@ class XenHvmHypervisor(XenHypervisor):
       # parameter 'model' is only valid with type 'ioemu'
       nic_type_str = ", model=%s, type=%s" % \
         (nic_type, constants.HT_HVM_VIF_IOEMU)
-    for nic in instance.nics:
+    for idx, nic in enumerate(instance.nics):
       nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
       ip = getattr(nic, "ip", None)
       if ip is not None:
         nic_str += ", ip=%s" % ip
       if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
         nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
+      if hvp[constants.HV_VIF_SCRIPT]:
+        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
       vif_data.append("'%s'" % nic_str)
+      cls._WriteNICInfoFile(instance.name, idx, nic)
 
     config.write("vif = [%s]\n" % ",".join(vif_data))
 
-- 
1.7.10.4

Attachment: signature.asc
Description: Digital signature

Reply via email to