diff options
author | Dan Prince <dprince@redhat.com> | 2014-06-10 14:01:06 -0400 |
---|---|---|
committer | Dan Prince <dprince@redhat.com> | 2014-06-10 14:01:06 -0400 |
commit | 86230e11d10a9a605f1eaaf9ab3619875224eb3d (patch) | |
tree | cac4dce869f1049b86b576dfb4e034f41e40e784 /os_net_config | |
parent | 3e1474324568a277bd3d8e493d26021ec3f3767c (diff) |
Implement apply for ifcfg implementation
Adds an apply function to the ifcfg implementation
which:
1) Shuts down existing interfaces w/ ifdown
2) writes new interfaces config files (routes too)
3) Starts up new interfaces w/ ifup
Diffstat (limited to 'os_net_config')
-rw-r--r-- | os_net_config/__init__.py | 5 | ||||
-rw-r--r-- | os_net_config/impl_ifcfg.py | 56 | ||||
-rw-r--r-- | os_net_config/objects.py | 1 | ||||
-rw-r--r-- | os_net_config/tests/test_impl_ifcfg.py | 81 | ||||
-rw-r--r-- | os_net_config/utils.py | 30 |
5 files changed, 133 insertions, 40 deletions
diff --git a/os_net_config/__init__.py b/os_net_config/__init__.py index bdbc69f..27dc95e 100644 --- a/os_net_config/__init__.py +++ b/os_net_config/__init__.py @@ -23,7 +23,7 @@ class NotImplemented(Exception): pass -class NetworkConfig(object): +class NetConfig(object): """Configure network interfaces using the ifcfg format.""" def addInterface(self, interface): @@ -31,3 +31,6 @@ class NetworkConfig(object): def addRoutes(self, interface_name, routes=[]): raise NotImplemented("addRoutes 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 c4fbde4..c4ea5dd 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -12,6 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. +import os_net_config +from os_net_config import utils + + +from os_net_config.openstack.common import processutils + def ifcfg_config_path(name): return "/etc/sysconfig/network-scripts/ifcfg-%s" % name @@ -21,21 +27,7 @@ def route_config_path(name): return "/etc/sysconfig/network-scripts/route-%s" % name -def writeConfig(filename, data): - with open(filename, "w") as f: - f.write(str(data)) - - -def get_config(filename): - with open(filename, "r") as f: - return f.read() - - -def diff(filename, data): - return get_config(filename) == data - - -class IfcfgNetwork(object): +class IfcfgNetConfig(os_net_config.NetConfig): """Configure network interfaces using the ifcfg format.""" def __init__(self): @@ -78,16 +70,38 @@ class IfcfgNetwork(object): data += "IPV6ADDR=%s\n" % first_v6.ip self.interfaces[interface.name] = data + if interface.routes: + self.addRoutes(interface.name, interface.routes) def addRoutes(self, interface_name, routes=[]): data = "" first_line = "" for route in routes: if route.default: - first_line = "default %s dev %s\n" % (route.next_hop, - interface_name) + first_line = "default via %s dev %s\n" % (route.next_hop, + interface_name) else: - data += "%s via %s dev %s" % (route.ip_netmask, - route.next_hop, - interface_name) - self.routes[interface_name] == first_line + data + data += "%s via %s dev %s\n" % (route.ip_netmask, + route.next_hop, + interface_name) + self.routes[interface_name] = first_line + data + + def apply(self): + restart_interfaces = [] + 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 + utils.diff(route_config_path(interface_name), route_data)): + restart_interfaces.append(interface_name) + update_files[ifcfg_config_path(interface_name)] = iface_data + update_files[route_config_path(interface_name)] = route_data + + for interface in restart_interfaces: + processutils.execute('/sbin/ifdown', interface) + + for location, data in update_files.iteritems(): + utils.write_config(location, data) + + 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 455e55f..4b6e09e 100644 --- a/os_net_config/objects.py +++ b/os_net_config/objects.py @@ -50,6 +50,7 @@ class Interface(object): self.use_dhcp = use_dhcp self.use_dhcpv6 = use_dhcpv6 self.addresses = addresses + self.routes = routes self.bridge = None self.type = None diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py index 7a2deec..a383a56 100644 --- a/os_net_config/tests/test_impl_ifcfg.py +++ b/os_net_config/tests/test_impl_ifcfg.py @@ -16,16 +16,18 @@ import tempfile from os_net_config import impl_ifcfg from os_net_config import objects +from os_net_config.openstack.common import processutils from os_net_config.tests import base +from os_net_config import utils -_BASE_IFCFG = """DEVICE=foo +_BASE_IFCFG = """DEVICE=em1 ONBOOT=yes HOTPLUG=no """ _V4_IFCFG = _BASE_IFCFG + """BOOTPROTO=static -IPADDR=192.168.1.1 +IPADDR=192.168.1.2 NETMASK=255.255.255.0 """ @@ -40,43 +42,86 @@ _OVS_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\n" _OVS_BRIDGE_IFCFG = _BASE_IFCFG + "DEVICETYPE=ovs\n" -class TestIfcfgNetwork(base.TestCase): +_ROUTES = """default via 192.168.1.1 dev em1 +172.19.0.0/24 via 192.168.1.1 dev em1 +""" + + +class TestIfcfgNetConfig(base.TestCase): def setUp(self): - super(TestIfcfgNetwork, self).setUp() - self.temp_config_file = tempfile.NamedTemporaryFile() + 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_config_path(name): - return self.temp_config_file.name - self.stubs.Set(impl_ifcfg, 'ifcfg_config_path', test_config_path) - self.provider = impl_ifcfg.IfcfgNetwork() + 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_config_file.close() - super(TestIfcfgNetwork, self).tearDown() + self.temp_ifcfg_file.close() + self.temp_route_file.close() + super(TestIfcfgNetConfig, self).tearDown() def get_interface_config(self): - return self.provider.interfaces['foo'] + return self.provider.interfaces['em1'] + + def get_route_config(self): + return self.provider.routes['em1'] def test_add_base_interface(self): - interface = objects.Interface('foo') + interface = objects.Interface('em1') self.provider.addInterface(interface) self.assertEqual(_BASE_IFCFG, self.get_interface_config()) def test_add_ovs_interface(self): - interface = objects.Interface('foo') + interface = objects.Interface('em1') interface.type = 'ovs' self.provider.addInterface(interface) self.assertEqual(_OVS_IFCFG, self.get_interface_config()) def test_add_interface_with_v4(self): - v4_addr = objects.Address('192.168.1.1/24') - interface = objects.Interface('foo', addresses=[v4_addr]) + v4_addr = objects.Address('192.168.1.2/24') + interface = objects.Interface('em1', addresses=[v4_addr]) self.provider.addInterface(interface) self.assertEqual(_V4_IFCFG, self.get_interface_config()) def test_add_interface_with_v6(self): v6_addr = objects.Address('2001:abc:a::/64') - interface = objects.Interface('foo', addresses=[v6_addr]) + interface = objects.Interface('em1', addresses=[v6_addr]) self.provider.addInterface(interface) - self.assertEqual(_V6_IFCFG, self.get_interface_config()) + + def test_network_with_routes(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') + interface = objects.Interface('em1', addresses=[v4_addr], + routes=[route1, route2]) + self.provider.addInterface(interface) + self.assertEqual(_V4_IFCFG, self.get_interface_config()) + self.assertEqual(_ROUTES, self.get_route_config()) + + def test_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') + interface = objects.Interface('em1', addresses=[v4_addr], + 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) diff --git a/os_net_config/utils.py b/os_net_config/utils.py new file mode 100644 index 0000000..41bc55e --- /dev/null +++ b/os_net_config/utils.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +# 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. + + +def write_config(filename, data): + with open(filename, "w") as f: + f.write(str(data)) + + +def get_file_data(filename): + try: + with open(filename, "r") as f: + return f.read() + except IOError: + return "" + + +def diff(filename, data): + return not get_file_data(filename) == data |