Ganeti currently supports two modes of operation for instance NICs: - bridged mode, where network interfaces are expected to be attached to bridges present on the hardware nodes. In this mode the bridges *must* exist before any instance-related action is taken (e.g. startup, migration).
- routed mode, where network interfaces are expected to be routed via some policy routing mechanism. For these interfaces, ganeti currently requires an IP address. These two cases cover most of the desired functionality, however there may be cases where the prerequisites (pre-existing bridges and ip addresses) can be fulfilled outside the scope of Ganeti. For example, one may rely on KVM's ifup script to dynamically provision bridges for 802.1q VLANs on trunk ports. To this end, we add a third mode, "manual", which simply passes the ip and link parameters directly to the network scripts, without interpreting them or imposing any kind of requirements. Site-local requirements can be enforced using pre-hooks, which can in turn deny starting an instance with an abnormal network configuration. Signed-off-by: Apollon Oikonomopoulos <[email protected]> --- lib/config.py | 2 ++ lib/constants.py | 4 +++- man/gnt-cluster.rst | 5 +++-- man/gnt-instance.rst | 7 +++++-- test/ganeti.config_unittest.py | 2 ++ test/ganeti.query_unittest.py | 7 ++++++- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/config.py b/lib/config.py index 0253a23..513009c 100644 --- a/lib/config.py +++ b/lib/config.py @@ -573,6 +573,8 @@ class ConfigWriter: link = "bridge:%s" % nic_link elif nic_mode == constants.NIC_MODE_ROUTED: link = "route:%s" % nic_link + elif nic_mode == constants.NIC_MODE_MANUAL: + link = "manual:%s" % nic_link else: raise errors.ProgrammerError("NIC mode '%s' not handled" % nic_mode) diff --git a/lib/constants.py b/lib/constants.py index a33186b..313b6b4 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -745,8 +745,10 @@ NIC_LINK = "link" NIC_MODE_BRIDGED = "bridged" NIC_MODE_ROUTED = "routed" +NIC_MODE_MANUAL = "manual" -NIC_VALID_MODES = frozenset([NIC_MODE_BRIDGED, NIC_MODE_ROUTED]) +NIC_VALID_MODES = frozenset([NIC_MODE_BRIDGED, NIC_MODE_ROUTED, + NIC_MODE_MANUAL]) NICS_PARAMETER_TYPES = { NIC_MODE: VTYPE_STRING, diff --git a/man/gnt-cluster.rst b/man/gnt-cluster.rst index d3fcecd..1488cf7 100644 --- a/man/gnt-cluster.rst +++ b/man/gnt-cluster.rst @@ -299,14 +299,15 @@ parameters for the cluster. The parameter format is a comma-separated list of key=value pairs with the following supported keys: mode - The default nic mode, 'routed' or 'bridged'. + The default nic mode, 'routed', 'bridged' or 'manual'. link In bridged mode the default NIC bridge. In routed mode it represents an hypervisor-vif-script dependent value to allow different instance groups. For example under the KVM default network script it is interpreted as a routing table number or - name. + name. In manual mode, the interpration of this parameter is left + entirely to the hypervisor network configuration script. The option ``--maintain-node-health`` allows to enable/disable automatic maintenance actions on nodes. Currently these include diff --git a/man/gnt-instance.rst b/man/gnt-instance.rst index b08b955..9a632be 100644 --- a/man/gnt-instance.rst +++ b/man/gnt-instance.rst @@ -102,13 +102,16 @@ ip the node expects the instance to use) mode - specifies the connection mode for this nic: routed or bridged. + specifies the connection mode for this nic: routed, bridged or + manual. link in bridged mode specifies the bridge to attach this NIC to, in routed mode it's intended to differentiate between different routing tables/instance groups (but the meaning is dependent on - the network script, see gnt-cluster(8) for more details) + the network script, see gnt-cluster(8) for more details). In manual + mode, the interpretation of this parameter is up to the hypervisor + network configuration script. Of these "mode" and "link" are nic parameters, and inherit their diff --git a/test/ganeti.config_unittest.py b/test/ganeti.config_unittest.py index a21bfa6..2659d5b 100755 --- a/test/ganeti.config_unittest.py +++ b/test/ganeti.config_unittest.py @@ -176,11 +176,13 @@ class TestConfigRunner(unittest.TestCase): link = constants.NIC_LINK m_bridged = constants.NIC_MODE_BRIDGED m_routed = constants.NIC_MODE_ROUTED + m_manual = constants.NIC_MODE_MANUAL CheckSyntax = objects.NIC.CheckParameterSyntax CheckSyntax(constants.NICC_DEFAULTS) CheckSyntax({mode: m_bridged, link: 'br1'}) CheckSyntax({mode: m_routed, link: 'default'}) + CheckSyntax({mode: m_manual, link: 'default'}) self.assertRaises(errors.ConfigurationError, CheckSyntax, {mode: '000invalid', link: 'any'}) self.assertRaises(errors.ConfigurationError, diff --git a/test/ganeti.query_unittest.py b/test/ganeti.query_unittest.py index 213470a..7b71b7e 100755 --- a/test/ganeti.query_unittest.py +++ b/test/ganeti.query_unittest.py @@ -689,6 +689,11 @@ class TestInstanceQuery(unittest.TestCase): constants.NIC_MODE: constants.NIC_MODE_BRIDGED, constants.NIC_LINK: "eth123", }), + objects.NIC(ip="192.0.2.5", mac=macs.pop(), + nicparams={ + constants.NIC_MODE: constants.NIC_MODE_MANUAL, + constants.NIC_LINK: "eth456", + }), ], osparams={}), objects.Instance(name="inst5", hvparams={}, nics=[], @@ -739,7 +744,7 @@ class TestInstanceQuery(unittest.TestCase): inst_bridges = { "inst3": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE], "inst4": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE, - None, "eth123"], + None, "eth123", None], } live_data = { -- 1.7.2.5
