summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Fournier <bfournie@redhat.com>2017-06-01 21:07:40 -0400
committerBob Fournier <bfournie@redhat.com>2017-06-08 14:09:15 -0400
commit58a913e1554c5dd71a6fb7f7ba354d25379e2c97 (patch)
tree38670aab59f7ad25406502685e3aeb6012b1364c
parent9626b44cc931e899d22b1285b7acab87f0e67fe8 (diff)
Use os-net-config mapping file when interface in bond or bridge
Os-net-config was not using the user supplied mapping file to map interface names for interfaces in bonds or bridges. Fix is to set the mapping file info when creating interface objects in bonds/bridges. Closes-Bug: 1695122 Change-Id: I063256b93c44c2e7a05d9820b0c1f6bf5b73d7a0
-rw-r--r--os_net_config/objects.py140
-rw-r--r--os_net_config/tests/test_objects.py107
2 files changed, 162 insertions, 85 deletions
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index f7d5116..86e0895 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -81,6 +81,32 @@ def _get_required_field(json, name, object_name):
return field
+def _update_members(json, nic_mapping, persist_mapping):
+ """Update object's members fields and pass mapping info to each member.
+
+ :param json: dictionary containing object values
+ :param nic_mapping: mapping of abstractions to actual nic names
+ :param persist_mapping: bool indicating mapping file should be permanent
+ :returns members: updated members
+ """
+ members = []
+
+ members_json = json.get('members')
+ if members_json:
+ if isinstance(members_json, list):
+ for member in members_json:
+ # If this member already has a nic mapping, don't overwrite it
+ if not member.get('nic_mapping'):
+ member.update({'nic_mapping': nic_mapping})
+ member.update({'persist_mapping': persist_mapping})
+ members.append(object_from_json(member))
+ else:
+ msg = 'Members must be a list.'
+ raise InvalidConfigException(msg)
+
+ return members
+
+
def _mapped_nics(nic_mapping=None):
mapping = nic_mapping or {}
global _MAPPED_NICS
@@ -466,17 +492,8 @@ class OvsBridge(_BaseOpts):
if not isinstance(ovs_extra, list):
ovs_extra = [ovs_extra]
fail_mode = json.get('ovs_fail_mode', DEFAULT_OVS_BRIDGE_FAIL_MODE)
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return OvsBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -534,17 +551,8 @@ class OvsUserBridge(_BaseOpts):
if not isinstance(ovs_extra, list):
ovs_extra = [ovs_extra]
fail_mode = json.get('ovs_fail_mode', DEFAULT_OVS_BRIDGE_FAIL_MODE)
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return OvsUserBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -592,17 +600,8 @@ class LinuxBridge(_BaseOpts):
persist_mapping, defroute, dhclient_args,
dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return LinuxBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -655,17 +654,8 @@ class IvsBridge(_BaseOpts):
persist_mapping, defroute, dhclient_args,
dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return IvsBridge(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -715,16 +705,7 @@ class NfvswitchBridge(_BaseOpts):
dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
- # members
- members = []
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
options = json.get('options')
if not options:
@@ -778,17 +759,8 @@ class LinuxTeam(_BaseOpts):
dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
bonding_options = json.get('bonding_options')
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return LinuxTeam(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -837,17 +809,8 @@ class LinuxBond(_BaseOpts):
dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
bonding_options = json.get('bonding_options')
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return LinuxBond(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -902,17 +865,8 @@ class OvsBond(_BaseOpts):
ovs_extra = json.get('ovs_extra', [])
if not isinstance(ovs_extra, list):
ovs_extra = [ovs_extra]
- members = []
- # members
- members_json = json.get('members')
- if members_json:
- if isinstance(members_json, list):
- for member in members_json:
- members.append(object_from_json(member))
- else:
- msg = 'Members must be a list.'
- raise InvalidConfigException(msg)
+ members = _update_members(json, nic_mapping, persist_mapping)
return OvsBond(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
addresses=addresses, routes=routes, mtu=mtu,
@@ -1043,6 +997,10 @@ class OvsDpdkPort(_BaseOpts):
def from_json(json):
name = _get_required_field(json, 'name', 'OvsDpdkPort')
# driver name by default will be 'vfio-pci' if not specified
+ (use_dhcp, use_dhcpv6, addresses, routes, mtu, primary, nic_mapping,
+ persist_mapping, defroute, dhclient_args,
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(json)
+
driver = json.get('driver')
if not driver:
driver = 'vfio-pci'
@@ -1053,7 +1011,11 @@ class OvsDpdkPort(_BaseOpts):
if members_json:
if isinstance(members_json, list):
if len(members_json) == 1:
- iface = object_from_json(members_json[0])
+ member = members_json[0]
+ if not member.get('nic_mapping'):
+ member.update({'nic_mapping': nic_mapping})
+ member.update({'persist_mapping': persist_mapping})
+ iface = object_from_json(member)
if isinstance(iface, Interface):
# TODO(skramaja): Add checks for IP and route not to
# be set in the interface part of DPDK Port
@@ -1077,10 +1039,15 @@ class OvsDpdkPort(_BaseOpts):
ovs_extra = json.get('ovs_extra', [])
if not isinstance(ovs_extra, list):
ovs_extra = [ovs_extra]
- opts = _BaseOpts.base_opts_from_json(json)
- return OvsDpdkPort(name, *opts, members=members, driver=driver,
- ovs_options=ovs_options, ovs_extra=ovs_extra,
- rx_queue=rx_queue)
+ return OvsDpdkPort(name, use_dhcp=use_dhcp, use_dhcpv6=use_dhcpv6,
+ addresses=addresses, routes=routes, mtu=mtu,
+ primary=primary, nic_mapping=nic_mapping,
+ persist_mapping=persist_mapping, defroute=defroute,
+ dhclient_args=dhclient_args,
+ dns_servers=dns_servers,
+ nm_controlled=nm_controlled, members=members,
+ driver=driver, ovs_options=ovs_options,
+ ovs_extra=ovs_extra, rx_queue=rx_queue)
class OvsDpdkBond(_BaseOpts):
@@ -1132,6 +1099,9 @@ class OvsDpdkBond(_BaseOpts):
if members_json:
if isinstance(members_json, list):
for member in members_json:
+ if not member.get('nic_mapping'):
+ member.update({'nic_mapping': nic_mapping})
+ member.update({'persist_mapping': persist_mapping})
obj = object_from_json(member)
if isinstance(obj, OvsDpdkPort):
members.append(obj)
diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py
index 1199bb2..eb5adaf 100644
--- a/os_net_config/tests/test_objects.py
+++ b/os_net_config/tests/test_objects.py
@@ -621,6 +621,17 @@ class TestBond(base.TestCase):
interface2 = bridge.members[1]
self.assertEqual("em2", interface2.name)
+ def _stub_active_nics(self, nics):
+ def dummy_ordered_active_nics():
+ return nics
+ self.stubs.Set(utils, 'ordered_active_nics', dummy_ordered_active_nics)
+
+ def _stub_available_nics(self, nics):
+ def dummy_ordered_available_nics():
+ return nics
+ self.stubs.Set(utils, 'ordered_available_nics',
+ dummy_ordered_available_nics)
+
class TestLinuxTeam(base.TestCase):
@@ -1007,6 +1018,102 @@ class TestNicMapping(base.TestCase):
# This only emits a warning, so it should still work
self.assertEqual(expected, objects._mapped_nics())
+ # Test that mapping file is passed to interface members from parent object
+ def _test_mapped_nics_with_parent(self, type, name):
+ self._stub_available_nics(['foo', 'bar'])
+ mapping = {"nic1": "foo", "nic2": "bar"}
+
+ data = """{
+ "members": [{"type": "interface", "name": "nic1"},
+ {"type": "interface", "name": "nic2"}]
+ }
+ """
+ json_output = json.loads(data)
+ json_output.update({'type': type})
+ json_output.update({'name': name})
+ json_output.update({'nic_mapping': mapping})
+ obj = objects.object_from_json(json_output)
+
+ self.assertEqual("foo", obj.members[0].name)
+ self.assertEqual("bar", obj.members[1].name)
+
+ def test_mapped_nics_ovs_bond(self):
+ self._test_mapped_nics_with_parent("ovs_bond", "bond1")
+
+ def test_mapped_nics_linux_bond(self):
+ self._test_mapped_nics_with_parent("linux_bond", "bond1")
+
+ def test_mapped_nics_ovs_bridge(self):
+ self._test_mapped_nics_with_parent("ovs_bridge", "br-foo")
+
+ def test_mapped_nics_ovs_user_bridge(self):
+ self._test_mapped_nics_with_parent("ovs_user_bridge", "br-foo")
+
+ def test_mapped_nics_linux_bridge(self):
+ self._test_mapped_nics_with_parent("linux_bridge", "br-foo")
+
+ def test_mapped_nics_ivs_bridge(self):
+ self._test_mapped_nics_with_parent("ivs_bridge", "br-foo")
+
+ def test_mapped_nics_linux_team(self):
+ self._test_mapped_nics_with_parent("team", "team-foo")
+
+ def test_mapped_nics_bridge_and_bond(self):
+ self._stub_available_nics(['foo', 'bar'])
+ mapping = {"nic1": "foo", "nic2": "bar"}
+
+ data = """{
+"type": "ovs_bridge",
+"name": "br-foo",
+"members": [
+ {
+ "type": "ovs_bond",
+ "name": "bond0",
+ "members": [{"type": "interface", "name": "nic1"},
+ {"type": "interface", "name": "nic2"}]
+ }
+]
+}
+"""
+ json_output = json.loads(data)
+ json_output.update({'nic_mapping': mapping})
+ obj = objects.object_from_json(json_output)
+
+ interface1 = obj.members[0].members[0]
+ interface2 = obj.members[0].members[1]
+ self.assertEqual("foo", interface1.name)
+ self.assertEqual("bar", interface2.name)
+
+ def test_mapped_nics_ovs_dpdk_bond(self):
+ self._stub_available_nics(['foo', 'bar'])
+ mapping = {"nic2": "foo", "nic3": "bar"}
+
+ data = """{
+"type": "ovs_dpdk_bond",
+"name": "dpdkbond0",
+"members": [
+ {
+ "type": "ovs_dpdk_port",
+ "name": "dpdk0",
+ "members": [{"type": "interface", "name": "nic2"}]
+ },
+ {
+ "type": "ovs_dpdk_port",
+ "name": "dpdk1",
+ "members": [{"type": "interface", "name": "nic3"}]
+ }
+]
+}
+"""
+ json_output = json.loads(data)
+ json_output.update({'nic_mapping': mapping})
+ dpdk_port = objects.object_from_json(json_output)
+ interface1 = dpdk_port.members[0].members[0]
+ interface2 = dpdk_port.members[1].members[0]
+
+ self.assertEqual("foo", interface1.name)
+ self.assertEqual("bar", interface2.name)
+
class TestOvsDpdkBond(base.TestCase):