diff options
-rw-r--r-- | etc/os-net-config/samples/ovs_patch_port.yaml | 2 | ||||
-rw-r--r-- | os_net_config/impl_ifcfg.py | 11 | ||||
-rw-r--r-- | os_net_config/objects.py | 18 | ||||
-rw-r--r-- | os_net_config/tests/test_objects.py | 28 | ||||
-rw-r--r-- | os_net_config/tests/test_utils.py | 24 | ||||
-rw-r--r-- | os_net_config/utils.py | 11 | ||||
-rw-r--r-- | tox.ini | 2 |
7 files changed, 87 insertions, 9 deletions
diff --git a/etc/os-net-config/samples/ovs_patch_port.yaml b/etc/os-net-config/samples/ovs_patch_port.yaml index 91858be..bae8880 100644 --- a/etc/os-net-config/samples/ovs_patch_port.yaml +++ b/etc/os-net-config/samples/ovs_patch_port.yaml @@ -10,7 +10,7 @@ network_config: # force the MAC address of the bridge to this interface primary: true mtu: 1500 - ovs_extra: "br-set-external-id br-ctlplane bridge-id br-ctlplane" + ovs_extra: ["br-set-external-id br-ctlplane bridge-id br-ctlplane"] - type: ovs_patch_port name: br_pub-patch diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index dfaf051..0a4f817 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -293,15 +293,18 @@ class IfcfgNetConfig(os_net_config.NetConfig): data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name elif isinstance(base_opt, objects.OvsDpdkBond): ovs_extra.extend(base_opt.ovs_extra) - if base_opt.primary_interface_name: - primary_name = base_opt.primary_interface_name - self.bond_primary_ifaces[base_opt.name] = primary_name + # Referring to bug:1643026, the below commenting of the interfaces, + # is to workaround the error, but is not the long term solution. + # The long term solution is to run DPDK options before + # os-net-config, which is being tracked at BUG:1654975 + # if base_opt.primary_interface_name: + # primary_name = base_opt.primary_interface_name + # self.bond_primary_ifaces[base_opt.name] = primary_name data += "DEVICETYPE=ovs\n" data += "TYPE=OVSDPDKBond\n" data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name if base_opt.members: members = [member.name for member in base_opt.members] - self.member_names[base_opt.name] = members data += ("BOND_IFACES=\"%s\"\n" % " ".join(members)) if base_opt.ovs_options: data += "OVS_OPTIONS=\"%s\"\n" % base_opt.ovs_options diff --git a/os_net_config/objects.py b/os_net_config/objects.py index 741f304..3136be0 100644 --- a/os_net_config/objects.py +++ b/os_net_config/objects.py @@ -439,7 +439,9 @@ class OvsBridge(_BaseOpts): dhclient_args, dns_servers) = _BaseOpts.base_opts_from_json( json, include_primary=False) ovs_options = json.get('ovs_options') - ovs_extra = json.get('ovs_extra') + ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] fail_mode = json.get('ovs_fail_mode', DEFAULT_OVS_BRIDGE_FAIL_MODE) members = [] @@ -504,7 +506,9 @@ class OvsUserBridge(_BaseOpts): dhclient_args, dns_servers) = _BaseOpts.base_opts_from_json( json, include_primary=False) ovs_options = json.get('ovs_options') - ovs_extra = json.get('ovs_extra') + ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] fail_mode = json.get('ovs_fail_mode', DEFAULT_OVS_BRIDGE_FAIL_MODE) members = [] @@ -860,6 +864,8 @@ class OvsBond(_BaseOpts): json, include_primary=False) ovs_options = json.get('ovs_options') ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] members = [] # members @@ -906,6 +912,8 @@ class OvsTunnel(_BaseOpts): ovs_options = json.get('ovs_options', []) ovs_options = ['options:%s' % opt for opt in ovs_options] ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] opts = _BaseOpts.base_opts_from_json(json) return OvsTunnel(name, *opts, tunnel_type=tunnel_type, ovs_options=ovs_options, ovs_extra=ovs_extra) @@ -940,6 +948,8 @@ class OvsPatchPort(_BaseOpts): ovs_options = json.get('ovs_options', []) ovs_options = ['options:%s' % opt for opt in ovs_options] ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] opts = _BaseOpts.base_opts_from_json(json) return OvsPatchPort(name, *opts, bridge_name=bridge_name, peer=peer, ovs_options=ovs_options, ovs_extra=ovs_extra) @@ -1023,6 +1033,8 @@ class OvsDpdkPort(_BaseOpts): ovs_options = json.get('ovs_options', []) ovs_options = ['options:%s' % opt for opt in ovs_options] 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) @@ -1067,6 +1079,8 @@ class OvsDpdkBond(_BaseOpts): json, include_primary=False) ovs_options = json.get('ovs_options') ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] members = [] # members diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py index 54d153c..f5daf31 100644 --- a/os_net_config/tests/test_objects.py +++ b/os_net_config/tests/test_objects.py @@ -295,6 +295,34 @@ class TestBridge(base.TestCase): self.assertTrue(interface2.ovs_port) self.assertEqual("br-foo", interface2.bridge_name) + def test_from_json_ovs_extra(self): + data = """{ +"type": "ovs_bridge", +"name": "br-foo", +"ovs_extra": ["bar"], +"ovs_fail_mode": "standalone" +} +""" + bridge = objects.object_from_json(json.loads(data)) + self.assertTrue(2 == len(bridge.ovs_extra)) + self.assertEqual("bar", bridge.ovs_extra[0]) + self.assertEqual("set bridge br-foo fail_mode=standalone", + bridge.ovs_extra[1]) + + def test_from_json_ovs_extra_string(self): + data = """{ +"type": "ovs_bridge", +"name": "br-foo", +"ovs_extra": "bar", +"ovs_fail_mode": "standalone" +} +""" + bridge = objects.object_from_json(json.loads(data)) + self.assertTrue(2 == len(bridge.ovs_extra)) + self.assertEqual("bar", bridge.ovs_extra[0]) + self.assertEqual("set bridge br-foo fail_mode=standalone", + bridge.ovs_extra[1]) + class TestLinuxBridge(base.TestCase): diff --git a/os_net_config/tests/test_utils.py b/os_net_config/tests/test_utils.py index b766384..1885cbb 100644 --- a/os_net_config/tests/test_utils.py +++ b/os_net_config/tests/test_utils.py @@ -217,3 +217,27 @@ class TestUtils(base.TestCase): def test_interface_mac_raises(self): self.assertRaises(IOError, utils.interface_mac, 'ens20f2p3') + + def test_is_active_nic_for_sriov_vf(self): + + tmpdir = tempfile.mkdtemp() + self.stubs.Set(utils, '_SYS_CLASS_NET', tmpdir) + + # SR-IOV PF = ens802f0 + # SR-IOV VF = enp129s2 + for nic in ['ens802f0', 'enp129s2']: + nic_path = os.path.join(tmpdir, nic) + os.makedirs(nic_path) + os.makedirs(os.path.join(nic_path, 'device')) + with open(os.path.join(nic_path, 'operstate'), 'w') as f: + f.write('up') + with open(os.path.join(nic_path, 'address'), 'w') as f: + f.write('1.2.3.4') + + nic_path = os.path.join(tmpdir, 'enp129s2', 'device', 'physfn') + os.makedirs(nic_path) + + self.assertEqual(utils._is_active_nic('ens802f0'), True) + self.assertEqual(utils._is_active_nic('enp129s2'), False) + + shutil.rmtree(tmpdir) diff --git a/os_net_config/utils.py b/os_net_config/utils.py index af359d5..98bfe99 100644 --- a/os_net_config/utils.py +++ b/os_net_config/utils.py @@ -107,7 +107,16 @@ def _is_active_nic(interface_name): with open(_SYS_CLASS_NET + '/%s/address' % interface_name, 'r') as f: address = f.read().rstrip() - if has_device_dir and operstate == 'up' and address: + # If SR-IOV Virtual Functions (VF) are enabled in an interface, there + # will be additional nics created for each VF. It has to be ignored in + # the nic numbering. All the VFs will have a reference to the PF with + # directory name as 'physfn', if this directory is present it should be + # ignored. + vf_path_check = _SYS_CLASS_NET + '/%s/device/physfn' % interface_name + is_sriov_vf = os.path.isdir(vf_path_check) + + if (has_device_dir and operstate == 'up' and address and + not is_sriov_vf): return True else: return False @@ -1,6 +1,6 @@ [tox] minversion = 1.6 -envlist = py27,py33,pypy,pep8 +envlist = py35,py27,pep8 skipsdist = True [testenv] |