aboutsummaryrefslogtreecommitdiffstats
path: root/os_net_config
diff options
context:
space:
mode:
authorDan Prince <dprince@redhat.com>2014-06-11 13:52:12 -0400
committerDan Prince <dprince@redhat.com>2014-06-11 13:52:12 -0400
commit9110ad5fd4fa829a070d79da1f926758b15d5f10 (patch)
tree6ee2ed2e10d36a5e790ea26a0f999372322923fe /os_net_config
parent86230e11d10a9a605f1eaaf9ab3619875224eb3d (diff)
Add OvsBridge configuration support
Adds new object for OvsBridge. Also update the ifcfg network config class to support adding bridges. As part of the change both the bridge and interface classes extend a _BaseOpts base class.
Diffstat (limited to 'os_net_config')
-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)