aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os_net_config/objects.py34
-rw-r--r--os_net_config/tests/base.py7
-rw-r--r--os_net_config/tests/test_objects.py75
-rw-r--r--os_net_config/tests/test_utils.py47
-rw-r--r--os_net_config/utils.py49
5 files changed, 206 insertions, 6 deletions
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 14ecfc6..b73122c 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -14,9 +14,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+import logging
import netaddr
from openstack.common import strutils
+from os_net_config import utils
+
+
+logger = logging.getLogger(__name__)
+
+_NUMBERED_NICS = None
+
class InvalidConfigException(ValueError):
pass
@@ -43,6 +51,19 @@ def _get_required_field(json, name, object_name):
return field
+def _numbered_nics():
+ global _NUMBERED_NICS
+ if _NUMBERED_NICS:
+ return _NUMBERED_NICS
+ _NUMBERED_NICS = {}
+ count = 0
+ for nic in utils.ordered_active_nics():
+ count += 1
+ _NUMBERED_NICS["nic%i" % count] = nic
+ logger.info("nic%i mapped to: %s" % (count, nic))
+ return _NUMBERED_NICS
+
+
class Route(object):
"""Base class for network routes."""
@@ -80,7 +101,11 @@ class _BaseOpts(object):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, primary=False):
- self.name = name
+ numbered_nic_names = _numbered_nics()
+ if name in numbered_nic_names:
+ self.name = numbered_nic_names[name]
+ else:
+ self.name = name
self.mtu = mtu
self.use_dhcp = use_dhcp
self.use_dhcpv6 = use_dhcpv6
@@ -171,7 +196,12 @@ class Vlan(_BaseOpts):
super(Vlan, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary)
self.vlan_id = int(vlan_id)
- self.device = device
+
+ numbered_nic_names = _numbered_nics()
+ if device in numbered_nic_names:
+ self.device = numbered_nic_names[device]
+ else:
+ self.device = device
@staticmethod
def from_json(json):
diff --git a/os_net_config/tests/base.py b/os_net_config/tests/base.py
index c8ad7c4..1e87ba2 100644
--- a/os_net_config/tests/base.py
+++ b/os_net_config/tests/base.py
@@ -21,6 +21,8 @@ import fixtures
import stubout
import testtools
+from os_net_config import objects
+
_TRUE_VALUES = ('True', 'true', '1', 'yes')
@@ -33,6 +35,11 @@ class TestCase(testtools.TestCase):
super(TestCase, self).setUp()
self.stubs = stubout.StubOutForTesting()
+
+ def test_numbered_nics():
+ return {}
+ self.stubs.Set(objects, '_numbered_nics', test_numbered_nics)
+
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
try:
test_timeout = int(test_timeout)
diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py
index 830a809..2f43997 100644
--- a/os_net_config/tests/test_objects.py
+++ b/os_net_config/tests/test_objects.py
@@ -92,6 +92,16 @@ class TestInterface(base.TestCase):
self.assertEqual("em1", interface.name)
self.assertEqual(True, interface.use_dhcp)
+ def test_from_json_dhcp_nic1(self):
+ def test_numbered_nics():
+ return {"nic1": "em3"}
+ self.stubs.Set(objects, '_numbered_nics', test_numbered_nics)
+
+ data = '{"type": "interface", "name": "nic1", "use_dhcp": true}'
+ interface = objects.object_from_json(json.loads(data))
+ self.assertEqual("em3", interface.name)
+ self.assertEqual(True, interface.use_dhcp)
+
def test_from_json_with_addresses(self):
data = """{
"type": "interface",
@@ -130,6 +140,18 @@ class TestVlan(base.TestCase):
self.assertEqual(16, vlan.vlan_id)
self.assertEqual(True, vlan.use_dhcp)
+ def test_from_json_dhcp_nic1(self):
+ def test_numbered_nics():
+ return {"nic1": "em4"}
+ self.stubs.Set(objects, '_numbered_nics', test_numbered_nics)
+
+ data = '{"type": "vlan", "device": "nic1", "vlan_id": 16,' \
+ '"use_dhcp": true}'
+ vlan = objects.object_from_json(json.loads(data))
+ self.assertEqual("em4", vlan.device)
+ self.assertEqual(16, vlan.vlan_id)
+ self.assertEqual(True, vlan.use_dhcp)
+
class TestBridge(base.TestCase):
@@ -152,6 +174,29 @@ class TestBridge(base.TestCase):
self.assertEqual(True, interface1.ovs_port)
self.assertEqual("br-foo", interface1.bridge_name)
+ def test_from_json_dhcp_with_nic1(self):
+ def test_numbered_nics():
+ return {"nic1": "em5"}
+ self.stubs.Set(objects, '_numbered_nics', test_numbered_nics)
+
+ data = """{
+"type": "ovs_bridge",
+"name": "br-foo",
+"use_dhcp": true,
+"members": [{
+ "type": "interface",
+ "name": "nic1"
+}]
+}
+"""
+ bridge = objects.object_from_json(json.loads(data))
+ self.assertEqual("br-foo", bridge.name)
+ self.assertEqual(True, bridge.use_dhcp)
+ interface1 = bridge.members[0]
+ self.assertEqual("em5", interface1.name)
+ self.assertEqual(True, interface1.ovs_port)
+ self.assertEqual("br-foo", interface1.bridge_name)
+
def test_from_json_primary_interface(self):
data = """{
"type": "ovs_bridge",
@@ -210,3 +255,33 @@ class TestBond(base.TestCase):
self.assertEqual("em1", interface1.name)
interface2 = bridge.members[1]
self.assertEqual("em2", interface2.name)
+
+ def test_from_json_dhcp_with_nic1_nic2(self):
+
+ def test_numbered_nics():
+ return {"nic1": "em1", "nic2": "em2"}
+ self.stubs.Set(objects, '_numbered_nics', test_numbered_nics)
+
+ data = """{
+"type": "ovs_bond",
+"name": "bond1",
+"use_dhcp": true,
+"members": [
+ {
+ "type": "interface",
+ "name": "nic1"
+ },
+ {
+ "type": "interface",
+ "name": "nic2"
+ }
+]
+}
+"""
+ bridge = objects.object_from_json(json.loads(data))
+ self.assertEqual("bond1", bridge.name)
+ self.assertEqual(True, bridge.use_dhcp)
+ interface1 = bridge.members[0]
+ self.assertEqual("em1", interface1.name)
+ interface2 = bridge.members[1]
+ self.assertEqual("em2", interface2.name)
diff --git a/os_net_config/tests/test_utils.py b/os_net_config/tests/test_utils.py
new file mode 100644
index 0000000..e7326d3
--- /dev/null
+++ b/os_net_config/tests/test_utils.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2014 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os.path
+import shutil
+import tempfile
+
+from os_net_config.tests import base
+from os_net_config import utils
+
+
+class TestUtils(base.TestCase):
+
+ def test_ordered_active_nics(self):
+
+ tmpdir = tempfile.mkdtemp()
+ self.stubs.Set(utils, '_SYS_CLASS_NET', tmpdir)
+
+ def test_is_active_nic(interface_name):
+ return True
+ self.stubs.Set(utils, '_is_active_nic', test_is_active_nic)
+
+ for nic in ['a1', 'em1', 'em2', 'eth2', 'z1']:
+ with open(os.path.join(tmpdir, nic), 'w') as f:
+ f.write(nic)
+
+ nics = utils.ordered_active_nics()
+ self.assertEqual('em1', nics[0])
+ self.assertEqual('em2', nics[1])
+ self.assertEqual('eth2', nics[2])
+ self.assertEqual('a1', nics[3])
+ self.assertEqual('z1', nics[4])
+
+ shutil.rmtree(tmpdir)
diff --git a/os_net_config/utils.py b/os_net_config/utils.py
index cd7ee65..e51d197 100644
--- a/os_net_config/utils.py
+++ b/os_net_config/utils.py
@@ -14,35 +14,76 @@
# License for the specific language governing permissions and limitations
# under the License.
+import glob
import logging
logger = logging.getLogger(__name__)
+_SYS_CLASS_NET = '/sys/class/net'
def write_config(filename, data):
- with open(filename, "w") as f:
+ with open(filename, 'w') as f:
f.write(str(data))
def get_file_data(filename):
try:
- with open(filename, "r") as f:
+ with open(filename, 'r') as f:
return f.read()
except IOError:
logger.error("Error reading file: %s" % filename)
- return ""
+ return ''
def interface_mac(name):
try:
- with open('/sys/class/net/%s/address' % name, "r") as f:
+ with open('/sys/class/net/%s/address' % name, 'r') as f:
return f.read().rstrip()
except IOError:
logger.error("Unable to read file: %s" % name)
raise
+def _is_active_nic(interface_name):
+ try:
+ if interface_name == 'lo':
+ return False
+
+ addr_assign_type = None
+ with open(_SYS_CLASS_NET + '/%s/addr_assign_type' % interface_name,
+ 'r') as f:
+ addr_assign_type = int(f.read().rstrip())
+
+ carrier = None
+ with open(_SYS_CLASS_NET + '/%s/carrier' % interface_name, 'r') as f:
+ carrier = int(f.read().rstrip())
+
+ address = None
+ with open(_SYS_CLASS_NET + '/%s/address' % interface_name, 'r') as f:
+ address = f.read().rstrip()
+
+ if addr_assign_type == 0 and carrier == 1 and address:
+ return True
+ else:
+ return False
+ except IOError:
+ return False
+
+
+def ordered_active_nics():
+ embedded_nics = []
+ nics = []
+ for name in glob.iglob(_SYS_CLASS_NET + '/*'):
+ nic = name[(len(_SYS_CLASS_NET) + 1):]
+ if _is_active_nic(nic):
+ if nic.startswith('em') or nic.startswith('eth'):
+ embedded_nics.append(nic)
+ else:
+ nics.append(nic)
+ return sorted(embedded_nics) + sorted(nics)
+
+
def diff(filename, data):
file_data = get_file_data(filename)
logger.debug("Diff file data:\n%s" % file_data)