aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os_net_config/__init__.py4
-rw-r--r--os_net_config/impl_ifcfg.py66
-rw-r--r--os_net_config/objects.py29
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py97
4 files changed, 162 insertions, 34 deletions
diff --git a/os_net_config/__init__.py b/os_net_config/__init__.py
index 27dc95e..066ebb5 100644
--- a/os_net_config/__init__.py
+++ b/os_net_config/__init__.py
@@ -29,8 +29,8 @@ class NetConfig(object):
def addInterface(self, interface):
raise NotImplemented("addInterface is not implemented.")
- def addRoutes(self, interface_name, routes=[]):
- raise NotImplemented("addRoutes is not implemented.")
+ def addBridge(self, bridge):
+ raise NotImplemented("addBridge is not implemented.")
def apply(self):
raise NotImplemented("apply is not implemented.")
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index c4ea5dd..b4da7bc 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -23,6 +23,11 @@ def ifcfg_config_path(name):
return "/etc/sysconfig/network-scripts/ifcfg-%s" % name
+#NOTE(dprince): added here for testability
+def bridge_config_path(name):
+ return ifcfg_config_path(name)
+
+
def route_config_path(name):
return "/etc/sysconfig/network-scripts/route-%s" % name
@@ -33,21 +38,32 @@ class IfcfgNetConfig(os_net_config.NetConfig):
def __init__(self):
self.interfaces = {}
self.routes = {}
+ self.bridges = {}
- def addInterface(self, interface):
+ def _addCommon(self, interface):
data = "DEVICE=%s\n" % interface.name
data += "ONBOOT=yes\n"
data += "HOTPLUG=no\n"
- if interface.type == 'ovs':
+ if interface.type == 'ovs_port':
data += "DEVICETYPE=ovs\n"
- if interface.bridge:
+ if interface.bridge_name:
data += "TYPE=OVSPort\n"
- data += "OVS_BRIDGE=%s\n" % interface.bridge
+ data += "OVS_BRIDGE=%s\n" % interface.bridge_name
+ if interface.type == 'ovs_bridge':
+ data += "DEVICETYPE=ovs\n"
+ data += "TYPE=OVSBridge\n"
+ if interface.use_dhcp:
+ data += "OVSBOOTPROTO=dhcp\n"
+ if interface.members:
+ members = [member.name for member in interface.members]
+ data += ("OVSDHCPINTERFACES=%s\n" % " ".join(members))
+ else:
+ if interface.use_dhcp:
+ data += "BOOTPROTO=dhcp\n"
+ elif not interface.addresses:
data += "BOOTPROTO=none\n"
if interface.mtu != 1500:
data += "MTU=%i\n" % interface.mtu
- if interface.use_dhcp:
- data += "BOOTPROTO=dhcp\n"
if interface.use_dhcpv6 or interface.v6_addresses():
data += "IPV6INIT=yes\n"
if interface.mtu != 1500:
@@ -69,11 +85,25 @@ class IfcfgNetConfig(os_net_config.NetConfig):
data += "IPV6_AUTOCONF=no\n"
data += "IPV6ADDR=%s\n" % first_v6.ip
+ return data
+
+ def addInterface(self, interface):
+ data = self._addCommon(interface)
+
self.interfaces[interface.name] = data
if interface.routes:
- self.addRoutes(interface.name, interface.routes)
+ self._addRoutes(interface.name, interface.routes)
- def addRoutes(self, interface_name, routes=[]):
+ def addBridge(self, bridge):
+ data = self._addCommon(bridge)
+
+ self.bridges[bridge.name] = data
+ if bridge.routes:
+ self._addRoutes(bridge.name, bridge.routes)
+ if bridge.routes:
+ self._addRoutes(bridge.name, bridge.routes)
+
+ def _addRoutes(self, interface_name, routes=[]):
data = ""
first_line = ""
for route in routes:
@@ -88,7 +118,9 @@ class IfcfgNetConfig(os_net_config.NetConfig):
def apply(self):
restart_interfaces = []
+ restart_bridges = []
update_files = {}
+
for interface_name, iface_data in self.interfaces.iteritems():
route_data = self.routes.get(interface_name)
if (utils.diff(ifcfg_config_path(interface_name), iface_data) or
@@ -97,11 +129,27 @@ class IfcfgNetConfig(os_net_config.NetConfig):
update_files[ifcfg_config_path(interface_name)] = iface_data
update_files[route_config_path(interface_name)] = route_data
+ for bridge_name, bridge_data in self.bridges.iteritems():
+ route_data = self.routes.get(bridge_name)
+ if (utils.diff(ifcfg_config_path(bridge_name), bridge_data) or
+ utils.diff(route_config_path(bridge_name), route_data)):
+ restart_bridges.append(bridge_name)
+ update_files[bridge_config_path(bridge_name)] = bridge_data
+ update_files[route_config_path(bridge_name)] = route_data
+
for interface in restart_interfaces:
- processutils.execute('/sbin/ifdown', interface)
+ processutils.execute('/sbin/ifdown', interface,
+ check_exit_code=False)
+
+ for bridge in restart_bridges:
+ processutils.execute('/sbin/ifdown', bridge,
+ check_exit_code=False)
for location, data in update_files.iteritems():
utils.write_config(location, data)
+ for bridge in restart_bridges:
+ processutils.execute('/sbin/ifup', bridge)
+
for interface in restart_interfaces:
processutils.execute('/sbin/ifup', interface)
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 4b6e09e..c4f5600 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -40,8 +40,8 @@ class Address(object):
self.routes = routes
-class Interface(object):
- """Base class for network interfaces."""
+class _BaseOpts(object):
+ """Base abstraction for logical port options."""
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500):
@@ -51,7 +51,7 @@ class Interface(object):
self.use_dhcpv6 = use_dhcpv6
self.addresses = addresses
self.routes = routes
- self.bridge = None
+ self.bridge_name = None
self.type = None
def v4_addresses(self):
@@ -69,3 +69,26 @@ class Interface(object):
v6_addresses.append(addr)
return v6_addresses
+
+
+class Interface(_BaseOpts):
+ """Base class for network interfaces."""
+
+ def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
+ routes=[], mtu=1500):
+ super(Interface, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
+ routes, mtu)
+
+
+class OvsBridge(_BaseOpts):
+ """Base class for OVS bridges."""
+
+ def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
+ routes=[], members=[], mtu=1500):
+ super(OvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
+ routes, mtu)
+ self.type = 'ovs_bridge'
+ self.members = members
+ for member in self.members:
+ member.bridge_name = name
+ member.type = 'ovs_port'
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index a383a56..e0df5b4 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -26,6 +26,8 @@ ONBOOT=yes
HOTPLUG=no
"""
+_NO_IP = _BASE_IFCFG + "BOOTPROTO=none\n"
+
_V4_IFCFG = _BASE_IFCFG + """BOOTPROTO=static
IPADDR=192.168.1.2
NETMASK=255.255.255.0
@@ -36,7 +38,7 @@ IPV6_AUTOCONF=no
IPV6ADDR=2001:abc:a::
"""
-_OVS_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\n"
+_OVS_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\nBOOTPROTO=none\n"
_OVS_BRIDGE_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\n"
@@ -46,27 +48,30 @@ _ROUTES = """default via 192.168.1.1 dev em1
172.19.0.0/24 via 192.168.1.1 dev em1
"""
+_OVS_INTERFACE = _BASE_IFCFG + """DEVICETYPE=ovs
+TYPE=OVSPort
+OVS_BRIDGE=br-ctlplane
+BOOTPROTO=none
+"""
+
+_OVS_BRIDGE_DHCP = """DEVICE=br-ctlplane
+ONBOOT=yes
+HOTPLUG=no
+DEVICETYPE=ovs
+TYPE=OVSBridge
+OVSBOOTPROTO=dhcp
+OVSDHCPINTERFACES=em1
+"""
+
class TestIfcfgNetConfig(base.TestCase):
def setUp(self):
super(TestIfcfgNetConfig, self).setUp()
- self.temp_ifcfg_file = tempfile.NamedTemporaryFile()
- self.temp_route_file = tempfile.NamedTemporaryFile()
-
- def test_ifcfg_path(name):
- return self.temp_ifcfg_file.name
- self.stubs.Set(impl_ifcfg, 'ifcfg_config_path', test_ifcfg_path)
-
- def test_routes_path(name):
- return self.temp_route_file.name
- self.stubs.Set(impl_ifcfg, 'route_config_path', test_routes_path)
self.provider = impl_ifcfg.IfcfgNetConfig()
def tearDown(self):
- self.temp_ifcfg_file.close()
- self.temp_route_file.close()
super(TestIfcfgNetConfig, self).tearDown()
def get_interface_config(self):
@@ -78,11 +83,11 @@ class TestIfcfgNetConfig(base.TestCase):
def test_add_base_interface(self):
interface = objects.Interface('em1')
self.provider.addInterface(interface)
- self.assertEqual(_BASE_IFCFG, self.get_interface_config())
+ self.assertEqual(_NO_IP, self.get_interface_config())
def test_add_ovs_interface(self):
interface = objects.Interface('em1')
- interface.type = 'ovs'
+ interface.type = 'ovs_port'
self.provider.addInterface(interface)
self.assertEqual(_OVS_IFCFG, self.get_interface_config())
@@ -107,7 +112,50 @@ class TestIfcfgNetConfig(base.TestCase):
self.assertEqual(_V4_IFCFG, self.get_interface_config())
self.assertEqual(_ROUTES, self.get_route_config())
- def test_apply(self):
+ def test_network_ovs_bridge_with_dhcp(self):
+ interface = objects.Interface('em1')
+ bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True,
+ members=[interface])
+ self.provider.addInterface(interface)
+ self.provider.addBridge(bridge)
+ self.assertEqual(_OVS_INTERFACE, self.get_interface_config())
+ self.assertEqual(_OVS_BRIDGE_DHCP,
+ self.provider.bridges['br-ctlplane'])
+
+
+class TestIfcfgNetConfigApply(base.TestCase):
+
+ def setUp(self):
+ super(TestIfcfgNetConfigApply, self).setUp()
+ self.temp_ifcfg_file = tempfile.NamedTemporaryFile()
+ self.temp_route_file = tempfile.NamedTemporaryFile()
+ self.temp_bridge_file = tempfile.NamedTemporaryFile()
+
+ def test_ifcfg_path(name):
+ return self.temp_ifcfg_file.name
+ self.stubs.Set(impl_ifcfg, 'ifcfg_config_path', test_ifcfg_path)
+
+ def test_routes_path(name):
+ return self.temp_route_file.name
+ self.stubs.Set(impl_ifcfg, 'route_config_path', test_routes_path)
+
+ def test_bridge_path(name):
+ return self.temp_bridge_file.name
+ self.stubs.Set(impl_ifcfg, 'bridge_config_path', test_bridge_path)
+
+ def test_execute(*args, **kwargs):
+ pass
+ self.stubs.Set(processutils, 'execute', test_execute)
+
+ self.provider = impl_ifcfg.IfcfgNetConfig()
+
+ def tearDown(self):
+ self.temp_ifcfg_file.close()
+ self.temp_route_file.close()
+ self.temp_bridge_file.close()
+ super(TestIfcfgNetConfigApply, self).tearDown()
+
+ def test_network_apply(self):
route1 = objects.Route('192.168.1.1', default=True)
route2 = objects.Route('192.168.1.1', '172.19.0.0/24')
v4_addr = objects.Address('192.168.1.2/24')
@@ -115,13 +163,22 @@ class TestIfcfgNetConfig(base.TestCase):
routes=[route1, route2])
self.provider.addInterface(interface)
- def test_execute(*args, **kwargs):
- pass
- self.stubs.Set(processutils, 'execute', test_execute)
-
self.provider.apply()
ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
self.assertEqual(_V4_IFCFG, ifcfg_data)
route_data = utils.get_file_data(self.temp_route_file.name)
self.assertEqual(_ROUTES, route_data)
+
+ def test_dhcp_ovs_bridge_network_apply(self):
+ interface = objects.Interface('em1')
+ bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True,
+ members=[interface])
+ self.provider.addInterface(interface)
+ self.provider.addBridge(bridge)
+ self.provider.apply()
+
+ ifcfg_data = utils.get_file_data(self.temp_ifcfg_file.name)
+ self.assertEqual(_OVS_INTERFACE, ifcfg_data)
+ bridge_data = utils.get_file_data(self.temp_bridge_file.name)
+ self.assertEqual(_OVS_BRIDGE_DHCP, bridge_data)