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
