aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/os-net-config/samples/mapping.yaml4
-rw-r--r--os_net_config/cli.py15
-rw-r--r--os_net_config/impl_eni.py3
-rw-r--r--os_net_config/impl_ifcfg.py2
-rw-r--r--os_net_config/objects.py55
-rw-r--r--os_net_config/tests/base.py3
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py19
7 files changed, 81 insertions, 20 deletions
diff --git a/etc/os-net-config/samples/mapping.yaml b/etc/os-net-config/samples/mapping.yaml
index 5faec22..a832dc9 100644
--- a/etc/os-net-config/samples/mapping.yaml
+++ b/etc/os-net-config/samples/mapping.yaml
@@ -1,6 +1,10 @@
# This can be used with the -m option to override the
# default mapping of the nicN aliases in configs
# The mapping can specify either a device name or a mac address
+# If --persist-mapping is specified, we write the device aliases
+# config instead of the system names, e.g we actually configure
+# nic1 intead of em3. This is probably best used with --cleanup
+# to remove the stale configs e.g for em3
interface_mapping:
nic1: em3
nic2: em1
diff --git a/os_net_config/cli.py b/os_net_config/cli.py
index d22573d..939eeaa 100644
--- a/os_net_config/cli.py
+++ b/os_net_config/cli.py
@@ -74,6 +74,14 @@ def parse_opts(argv):
help="Cleanup unconfigured interfaces.",
required=False)
+ parser.add_argument(
+ '--persist-mapping',
+ dest="persist_mapping",
+ action='store_true',
+ help="Make aliases defined in the mapping file permanent "
+ "(WARNING, permanently renames nics).",
+ required=False)
+
opts = parser.parse_args(argv[1:])
return opts
@@ -139,13 +147,18 @@ def main(argv=sys.argv):
# mappings by specifying a specific nicN->name or nicN->MAC mapping
if os.path.exists(opts.mapping_file):
with open(opts.mapping_file) as cf:
- iface_mapping = yaml.load(cf.read()).get("interface_mapping")
+ iface_map = yaml.load(cf.read())
+ iface_mapping = iface_map.get("interface_mapping")
logger.debug('interface_mapping JSON: %s' % str(iface_mapping))
+ persist_mapping = opts.persist_mapping
+ logger.debug('persist_mapping: %s' % persist_mapping)
else:
iface_mapping = None
+ persist_mapping = False
for iface_json in iface_array:
iface_json.update({'nic_mapping': iface_mapping})
+ iface_json.update({'persist_mapping': persist_mapping})
obj = objects.object_from_json(iface_json)
provider.add_object(obj)
files_changed = provider.apply(noop=opts.noop, cleanup=opts.cleanup)
diff --git a/os_net_config/impl_eni.py b/os_net_config/impl_eni.py
index 5f4f727..ce4ffe9 100644
--- a/os_net_config/impl_eni.py
+++ b/os_net_config/impl_eni.py
@@ -129,6 +129,9 @@ class ENINetConfig(os_net_config.NetConfig):
if interface.mtu != 1500:
data += " mtu %i\n" % interface.mtu
+ if interface.hwaddr:
+ raise NotImplemented("hwaddr is not implemented.")
+
if ovs_extra:
data += " ovs_extra %s\n" % " -- ".join(ovs_extra)
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index c871296..a728f53 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -142,6 +142,8 @@ class IfcfgNetConfig(os_net_config.NetConfig):
first_v6 = v6_addresses[0]
data += "IPV6_AUTOCONF=no\n"
data += "IPV6ADDR=%s\n" % first_v6.ip
+ if base_opt.hwaddr:
+ data += "HWADDR=%s\n" % base_opt.hwaddr
if ovs_extra:
data += "OVS_EXTRA=\"%s\"\n" % " -- ".join(ovs_extra)
return data
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 929bcab..79d83e7 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -129,12 +129,20 @@ class _BaseOpts(object):
"""Base abstraction for logical port options."""
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
- routes=[], mtu=1500, primary=False, nic_mapping=None):
+ routes=[], mtu=1500, primary=False, nic_mapping=None,
+ persist_mapping=False):
numbered_nic_names = _numbered_nics(nic_mapping)
+ self.hwaddr = None
if name in numbered_nic_names:
- self.name = numbered_nic_names[name]
+ if persist_mapping:
+ self.name = name
+ hwname = numbered_nic_names[name]
+ self.hwaddr = utils.interface_mac(hwname)
+ else:
+ self.name = numbered_nic_names[name]
else:
self.name = name
+
self.mtu = mtu
self.use_dhcp = use_dhcp
self.use_dhcpv6 = use_dhcpv6
@@ -192,22 +200,25 @@ class _BaseOpts(object):
raise InvalidConfigException(msg)
nic_mapping = json.get('nic_mapping')
+ persist_mapping = json.get('persist_mapping')
if include_primary:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu, primary,
- nic_mapping)
+ nic_mapping, persist_mapping)
else:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu,
- nic_mapping)
+ nic_mapping, persist_mapping)
class Interface(_BaseOpts):
"""Base class for network interfaces."""
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
- routes=[], mtu=1500, primary=False, nic_mapping=None):
+ routes=[], mtu=1500, primary=False, nic_mapping=None,
+ persist_mapping=False):
super(Interface, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
- routes, mtu, primary, nic_mapping)
+ routes, mtu, primary, nic_mapping,
+ persist_mapping)
@staticmethod
def from_json(json):
@@ -225,10 +236,11 @@ class Vlan(_BaseOpts):
def __init__(self, device, vlan_id, use_dhcp=False, use_dhcpv6=False,
addresses=[], routes=[], mtu=1500, primary=False,
- nic_mapping=None):
+ nic_mapping=None, persist_mapping=False):
name = 'vlan%i' % vlan_id
super(Vlan, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
- routes, mtu, primary, nic_mapping)
+ routes, mtu, primary, nic_mapping,
+ persist_mapping)
self.vlan_id = int(vlan_id)
numbered_nic_names = _numbered_nics(nic_mapping)
@@ -251,9 +263,10 @@ class OvsBridge(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, members=[], ovs_options=None,
- ovs_extra=[], nic_mapping=None):
+ ovs_extra=[], nic_mapping=None, persist_mapping=False):
super(OvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
- routes, mtu, False, nic_mapping)
+ routes, mtu, False, nic_mapping,
+ persist_mapping)
self.members = members
self.ovs_options = ovs_options
self.ovs_extra = ovs_extra
@@ -272,8 +285,9 @@ class OvsBridge(_BaseOpts):
@staticmethod
def from_json(json):
name = _get_required_field(json, 'name', 'OvsBridge')
- (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping
- ) = _BaseOpts.base_opts_from_json(json, include_primary=False)
+ (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
+ persist_mapping) = _BaseOpts.base_opts_from_json(
+ json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra', [])
members = []
@@ -291,7 +305,8 @@ class OvsBridge(_BaseOpts):
return OvsBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
members=members, ovs_options=ovs_options,
- ovs_extra=ovs_extra, nic_mapping=nic_mapping)
+ ovs_extra=ovs_extra, nic_mapping=nic_mapping,
+ persist_mapping=persist_mapping)
class OvsBond(_BaseOpts):
@@ -299,9 +314,11 @@ class OvsBond(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, primary=False, members=[],
- ovs_options=None, ovs_extra=[], nic_mapping=None):
+ ovs_options=None, ovs_extra=[], nic_mapping=None,
+ persist_mapping=False):
super(OvsBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
- routes, mtu, primary, nic_mapping)
+ routes, mtu, primary, nic_mapping,
+ persist_mapping)
self.members = members
self.ovs_options = ovs_options
self.ovs_extra = ovs_extra
@@ -318,8 +335,9 @@ class OvsBond(_BaseOpts):
@staticmethod
def from_json(json):
name = _get_required_field(json, 'name', 'OvsBond')
- (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping
- ) = _BaseOpts.base_opts_from_json(json, include_primary=False)
+ (use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
+ persist_mapping) = _BaseOpts.base_opts_from_json(
+ json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra', [])
members = []
@@ -337,4 +355,5 @@ class OvsBond(_BaseOpts):
return OvsBond(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
members=members, ovs_options=ovs_options,
- ovs_extra=ovs_extra, nic_mapping=nic_mapping)
+ ovs_extra=ovs_extra, nic_mapping=nic_mapping,
+ persist_mapping=persist_mapping)
diff --git a/os_net_config/tests/base.py b/os_net_config/tests/base.py
index 30f9d97..d5adc66 100644
--- a/os_net_config/tests/base.py
+++ b/os_net_config/tests/base.py
@@ -36,9 +36,10 @@ class TestCase(testtools.TestCase):
super(TestCase, self).setUp()
self.stubs = stubout.StubOutForTesting()
+ self.stubbed_numbered_nics = {}
def dummy_numbered_nics(nic_mapping=None):
- return {}
+ return self.stubbed_numbered_nics
if self.stub_numbered_nics:
self.stubs.Set(objects, '_numbered_nics', dummy_numbered_nics)
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index c1026d9..46371db 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -36,6 +36,8 @@ IPADDR=192.168.1.2
NETMASK=255.255.255.0
"""
+_V4_IFCFG_MAPPED = _V4_IFCFG.replace('em1', 'nic1') + "HWADDR=a1:b2:c3:d4:e5\n"
+
_V6_IFCFG = _BASE_IFCFG + """IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6ADDR=2001:abc:a::
@@ -141,6 +143,23 @@ class TestIfcfgNetConfig(base.TestCase):
self.assertEqual(_V4_IFCFG, self.get_interface_config())
self.assertEqual('', self.get_route_config())
+ def test_add_interface_map_persisted(self):
+ def test_interface_mac(name):
+ macs = {'em1': 'a1:b2:c3:d4:e5'}
+ return macs[name]
+ self.stubs.Set(utils, 'interface_mac', test_interface_mac)
+
+ nic_mapping = {'nic1': 'em1'}
+ self.stubbed_numbered_nics = nic_mapping
+ v4_addr = objects.Address('192.168.1.2/24')
+ interface = objects.Interface('nic1', addresses=[v4_addr],
+ nic_mapping=nic_mapping,
+ persist_mapping=True)
+ self.assertEqual('a1:b2:c3:d4:e5', interface.hwaddr)
+ self.provider.add_interface(interface)
+ self.assertEqual(_V4_IFCFG_MAPPED, self.get_interface_config('nic1'))
+ self.assertEqual('', self.get_route_config('nic1'))
+
def test_add_interface_with_v6(self):
v6_addr = objects.Address('2001:abc:a::/64')
interface = objects.Interface('em1', addresses=[v6_addr])