On Fri, May 17, 2013 at 4:31 PM, Dimitris Aragiorgis <[email protected]>wrote:
> 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, > Shoudn't we actually check that this exist? > } > > 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)) > > Thanks, Guido
