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.

Additionally a custom vif script is provided, vif-ganeti
that is stored in /usr/lib/ganeti/vif-ganeti. This
script is executed instead of the one defined in
xend-config.sxp. Include this script in build process.
TODO: debian/links should include
a symlink of that file within /etc/xen/scripts/.

Cleanup NIC dir when removing config files. Upon Xen
configuration file removal, remove NIC dir as well.

Signed-off-by: Dimitris Aragiorgis <[email protected]>
---
 Makefile.am              |    7 +++++
 lib/hypervisor/hv_xen.py |   74 ++++++++++++++++++++++++++++++++++++++++++++--
 tools/vif-ganeti.in      |   47 +++++++++++++++++++++++++++++
 3 files changed, 126 insertions(+), 2 deletions(-)
 create mode 100755 tools/vif-ganeti.in

diff --git a/Makefile.am b/Makefile.am
index 037cf53..4e46d8f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -192,6 +192,7 @@ CLEANFILES = \
        $(man_MANS) \
        $(manhtml) \
        tools/kvm-ifup \
+       tools/vif-ganeti \
        tools/users-setup \
        tools/vcluster-setup \
        stamp-directories \
@@ -904,6 +905,7 @@ nodist_pkglib_python_scripts = \
 myexeclib_SCRIPTS = \
        daemons/daemon-util \
        tools/kvm-ifup \
+       tools/vif-ganeti \
        $(pkglib_python_scripts) \
        $(HS_MYEXECLIB_PROGS)
 
@@ -939,6 +941,7 @@ EXTRA_DIST = \
        devel/upload \
        devel/webserver \
        tools/kvm-ifup.in \
+       tools/vif-ganeti.in \
        tools/users-setup.in \
        tools/vcluster-setup.in \
        $(docinput) \
@@ -1337,6 +1340,10 @@ tools/kvm-ifup: tools/kvm-ifup.in $(REPLACE_VARS_SED)
        sed -f $(REPLACE_VARS_SED) < $< > $@
        chmod +x $@
 
+tools/vif-ganeti: tools/vif-ganeti.in $(REPLACE_VARS_SED)
+       sed -f $(REPLACE_VARS_SED) < $< > $@
+       chmod +x $@
+
 tools/users-setup: tools/users-setup.in $(REPLACE_VARS_SED)
        sed -f $(REPLACE_VARS_SED) < $< > $@
        chmod +x $@
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index 653f6b2..9c0c86e 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
@@ -41,6 +42,8 @@ XEND_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, 
"xend-config.sxp")
 XL_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, "xen/xl.conf")
 VIF_BRIDGE_SCRIPT = utils.PathJoin(pathutils.XEN_CONFIG_DIR,
                                    "scripts/vif-bridge")
+VIF_GANETI_SCRIPT = utils.PathJoin(pathutils.XEN_CONFIG_DIR,
+                                   "scripts/vif-ganeti")
 _DOM0_NAME = "Domain-0"
 _DISK_LETTERS = string.ascii_lowercase
 
@@ -310,6 +313,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,12 +378,68 @@ 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.
 
     """
     raise NotImplementedError
 
+
   def _WriteConfigFile(self, instance_name, data):
     """Write the Xen config file for the instance.
 
@@ -413,6 +474,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}.
@@ -840,14 +906,16 @@ 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]
+      nic_str += ", script=%s" % VIF_GANETI_SCRIPT
       vif_data.append("'%s'" % nic_str)
+      cls._WriteNICInfoFile(instance.name, idx, nic)
 
     disk_data = \
       _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
@@ -999,14 +1067,16 @@ 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]
+      nic_str += ", script=%s" % VIF_GANETI_SCRIPT
       vif_data.append("'%s'" % nic_str)
+      cls._WriteNICInfoFile(instance.name, idx, nic)
 
     config.write("vif = [%s]\n" % ",".join(vif_data))
 
diff --git a/tools/vif-ganeti.in b/tools/vif-ganeti.in
new file mode 100755
index 0000000..a8eebea
--- /dev/null
+++ b/tools/vif-ganeti.in
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+if [ -x "@SYSCONFDIR@/xen/scripts/vif-custom" ]; then
+       exec @SYSCONFDIR@/xen/scripts/vif-custom $*
+fi
+
+dir=$(dirname "$0")
+. "$dir"/vif-common.sh
+
+# taken from older vif-common.sh
+dev=$vif
+dev_=${dev#vif}
+domid=${dev_%.*}
+devid=${dev_#*.}
+domname=$(xm domname $domid)
+
+GANETI_NIC_DIR=/var/run/ganeti/xen-hypervisor/nic
+INTERFACE=$dev
+INSTANCE=$domname
+
+source $GANETI_NIC_DIR/$domname/$devid
+
+function setup_routed_mode {
+
+  ;;
+
+}
+
+
+function setup_bridged_mode {
+
+  ;;
+
+}
+
+ip link set $INTERFACE up
+
+if [ "$MODE" == "routed" ]; then
+  setup_routed_mode
+elif [ "$MODE" == "bridged" ]; then
+  BRIDGE=$(xenstore_read_default "$XENBUS_PATH/bridge" "$LINK")
+  brctl addif $BRIDGE $INTERFACE
+  setup_bridged_mode
+fi
+
+success
+
-- 
1.7.10.4

Reply via email to