aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.coveragerc2
-rw-r--r--os_net_config/__init__.py2
-rw-r--r--os_net_config/cli.py11
-rw-r--r--os_net_config/impl_ifcfg.py8
-rw-r--r--os_net_config/objects.py39
-rw-r--r--os_net_config/tests/test_cli.py25
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py37
-rw-r--r--os_net_config/tests/test_objects.py11
8 files changed, 117 insertions, 18 deletions
diff --git a/.coveragerc b/.coveragerc
index 13fd272..96a0e8d 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -4,4 +4,4 @@ source = os_net_config
omit = os_net_config/tests/*,os_net_config/openstack/*
[report]
-ignore-errors = True \ No newline at end of file
+ignore_errors = True
diff --git a/os_net_config/__init__.py b/os_net_config/__init__.py
index 641ee3b..8c9b70d 100644
--- a/os_net_config/__init__.py
+++ b/os_net_config/__init__.py
@@ -31,7 +31,7 @@ class NotImplemented(Exception):
class NetConfig(object):
- """Configure network interfaces using the ifcfg format."""
+ """Common network config methods class."""
def __init__(self, noop=False, root_dir=''):
self.noop = noop
diff --git a/os_net_config/cli.py b/os_net_config/cli.py
index c2491a2..c0ac5c4 100644
--- a/os_net_config/cli.py
+++ b/os_net_config/cli.py
@@ -48,6 +48,13 @@ def parse_opts(argv):
parser.add_argument('-r', '--root-dir', metavar='ROOT_DIR',
help="""The root directory of the filesystem.""",
default='')
+ parser.add_argument('--detailed-exit-codes',
+ action='store_true',
+ help="""Enable detailed exit codes. """
+ """If enabled an exit code of '2' means """
+ """that files were modified."""
+ """Disabled by default.""",
+ default=False)
parser.add_argument(
'-d', '--debug',
dest="debug",
@@ -183,6 +190,10 @@ def main(argv=sys.argv):
print("File: %s\n" % location)
print(data)
print("----")
+
+ if opts.detailed_exit_codes and len(files_changed) > 0:
+ return 2
+
return 0
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index b964819..20bbe30 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -62,7 +62,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
children.add(member)
children.update(self.child_members(member))
except KeyError:
- children.add(name)
+ pass
return children
def _add_common(self, base_opt):
@@ -162,6 +162,12 @@ class IfcfgNetConfig(os_net_config.NetConfig):
data += "DEFROUTE=no\n"
if base_opt.dhclient_args:
data += "DHCLIENTARGS=%s\n" % base_opt.dhclient_args
+ if base_opt.dns_servers:
+ data += "DNS1=%s\n" % base_opt.dns_servers[0]
+ if len(base_opt.dns_servers) == 2:
+ data += "DNS2=%s\n" % base_opt.dns_servers[1]
+ elif len(base_opt.dns_servers) > 2:
+ logger.warning('ifcfg format supports a max of 2 dns servers.')
return data
def _add_routes(self, interface_name, routes=[]):
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 8899164..388ea7c 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -130,7 +130,8 @@ class _BaseOpts(object):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, primary=False, nic_mapping=None,
- persist_mapping=False, defroute=True, dhclient_args=None):
+ persist_mapping=False, defroute=True, dhclient_args=None,
+ dns_servers=[]):
numbered_nic_names = _numbered_nics(nic_mapping)
self.hwaddr = None
self.hwname = None
@@ -154,6 +155,7 @@ class _BaseOpts(object):
self.primary = primary
self.defroute = defroute
self.dhclient_args = dhclient_args
+ self.dns_servers = dns_servers
self.bridge_name = None # internal
self.ovs_port = False # internal
self.primary_interface_name = None # internal
@@ -183,6 +185,7 @@ class _BaseOpts(object):
True)))
mtu = json.get('mtu', 1500)
dhclient_args = json.get('dhclient_args')
+ dns_servers = json.get('dns_servers')
primary = strutils.bool_from_string(str(json.get('primary', False)))
addresses = []
routes = []
@@ -212,10 +215,12 @@ class _BaseOpts(object):
if include_primary:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu, primary,
- nic_mapping, persist_mapping, defroute, dhclient_args)
+ nic_mapping, persist_mapping, defroute, dhclient_args,
+ dns_servers)
else:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu,
- nic_mapping, persist_mapping, defroute, dhclient_args)
+ nic_mapping, persist_mapping, defroute, dhclient_args,
+ dns_servers)
class Interface(_BaseOpts):
@@ -223,11 +228,12 @@ class Interface(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, primary=False, nic_mapping=None,
- persist_mapping=False, defroute=True, dhclient_args=None):
+ persist_mapping=False, defroute=True, dhclient_args=None,
+ dns_servers=[]):
super(Interface, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args)
+ dhclient_args, dns_servers)
@staticmethod
def from_json(json):
@@ -246,11 +252,12 @@ class Vlan(_BaseOpts):
def __init__(self, device, vlan_id, use_dhcp=False, use_dhcpv6=False,
addresses=[], routes=[], mtu=1500, primary=False,
nic_mapping=None, persist_mapping=False, defroute=True,
- dhclient_args=None):
+ dhclient_args=None, dns_servers=[]):
name = 'vlan%i' % vlan_id
super(Vlan, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
- persist_mapping, defroute, dhclient_args)
+ persist_mapping, defroute, dhclient_args,
+ dns_servers)
self.vlan_id = int(vlan_id)
numbered_nic_names = _numbered_nics(nic_mapping)
@@ -274,11 +281,11 @@ class OvsBridge(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, members=[], ovs_options=None,
ovs_extra=[], nic_mapping=None, persist_mapping=False,
- defroute=True, dhclient_args=None):
+ defroute=True, dhclient_args=None, dns_servers=[]):
super(OvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, False, nic_mapping,
persist_mapping, defroute,
- dhclient_args)
+ dhclient_args, dns_servers)
self.members = members
self.ovs_options = ovs_options
self.ovs_extra = ovs_extra
@@ -299,7 +306,7 @@ class OvsBridge(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsBridge')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute,
- dhclient_args) = _BaseOpts.base_opts_from_json(
+ 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', [])
@@ -320,7 +327,7 @@ class OvsBridge(_BaseOpts):
members=members, ovs_options=ovs_options,
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
- dhclient_args=dhclient_args)
+ dhclient_args=dhclient_args, dns_servers=dns_servers)
class OvsBond(_BaseOpts):
@@ -329,10 +336,12 @@ class OvsBond(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=[],
routes=[], mtu=1500, primary=False, members=[],
ovs_options=None, ovs_extra=[], nic_mapping=None,
- persist_mapping=False, defroute=True, dhclient_args=None):
+ persist_mapping=False, defroute=True, dhclient_args=None,
+ dns_servers=[]):
super(OvsBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
- persist_mapping, defroute, dhclient_args)
+ persist_mapping, defroute, dhclient_args,
+ dns_servers)
self.members = members
self.ovs_options = ovs_options
self.ovs_extra = ovs_extra
@@ -355,7 +364,7 @@ class OvsBond(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsBond')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute,
- dhclient_args) = _BaseOpts.base_opts_from_json(
+ 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', [])
@@ -376,4 +385,4 @@ class OvsBond(_BaseOpts):
members=members, ovs_options=ovs_options,
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
- dhclient_args=dhclient_args)
+ dhclient_args=dhclient_args, dns_servers=dns_servers)
diff --git a/os_net_config/tests/test_cli.py b/os_net_config/tests/test_cli.py
index 310a527..98477fc 100644
--- a/os_net_config/tests/test_cli.py
+++ b/os_net_config/tests/test_cli.py
@@ -17,7 +17,9 @@
import os.path
import sys
+import os_net_config
from os_net_config import cli
+from os_net_config import impl_ifcfg
from os_net_config.tests import base
import six
@@ -121,3 +123,26 @@ class TestCli(base.TestCase):
'-c %s' % (provider, bond_yaml))
self.assertEqual('', stderr)
self.assertIn('File: /rootfs/', stdout_yaml)
+
+ def test_interface_noop_detailed_exit_codes(self):
+ interface_yaml = os.path.join(SAMPLE_BASE, 'interface.yaml')
+ stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop '
+ '-c %s --detailed-exit-codes'
+ % interface_yaml, exitcodes=(2,))
+
+ def test_interface_noop_detailed_exit_codes_no_changes(self):
+ interface_yaml = os.path.join(SAMPLE_BASE, 'interface.yaml')
+
+ class TestImpl(os_net_config.NetConfig):
+
+ def add_interface(self, interface):
+ pass
+
+ def apply(self, cleanup=False, activate=True):
+ # this fake implementation returns no changes
+ return {}
+
+ self.stubs.Set(impl_ifcfg, 'IfcfgNetConfig', TestImpl)
+ stdout_yaml, stderr = self.run_cli('ARG0 --provider=ifcfg --noop '
+ '-c %s --detailed-exit-codes'
+ % interface_yaml, exitcodes=(0,))
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index 73271e8..f8864c4 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -357,6 +357,34 @@ DHCLIENTARGS=--foobar
"""
self.assertEqual(em1_config, self.get_interface_config('em1'))
+ def test_interface_single_dns_server(self):
+ interface1 = objects.Interface('em1', dns_servers=['1.2.3.4'])
+ self.provider.add_interface(interface1)
+ em1_config = """# This file is autogenerated by os-net-config
+DEVICE=em1
+ONBOOT=yes
+HOTPLUG=no
+NM_CONTROLLED=no
+BOOTPROTO=none
+DNS1=1.2.3.4
+"""
+ self.assertEqual(em1_config, self.get_interface_config('em1'))
+
+ def test_interface_dns_servers(self):
+ interface1 = objects.Interface('em1', dns_servers=['1.2.3.4',
+ '5.6.7.8'])
+ self.provider.add_interface(interface1)
+ em1_config = """# This file is autogenerated by os-net-config
+DEVICE=em1
+ONBOOT=yes
+HOTPLUG=no
+NM_CONTROLLED=no
+BOOTPROTO=none
+DNS1=1.2.3.4
+DNS2=5.6.7.8
+"""
+ self.assertEqual(em1_config, self.get_interface_config('em1'))
+
class TestIfcfgNetConfigApply(base.TestCase):
@@ -515,6 +543,15 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.assertIn('em1', self.ifup_interface_names)
self.assertIn('em2', self.ifup_interface_names)
+ def test_restart_interface_counts(self):
+ interface = objects.Interface('em1')
+ self.provider.add_interface(interface)
+ interface2 = objects.Interface('em2')
+ self.provider.add_interface(interface2)
+ self.provider.apply()
+ self.assertEqual(1, self.ifup_interface_names.count("em1"))
+ self.assertEqual(1, self.ifup_interface_names.count("em2"))
+
def test_vlan_apply(self):
vlan = objects.Vlan('em1', 5)
self.provider.add_vlan(vlan)
diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py
index c824ba8..8488370 100644
--- a/os_net_config/tests/test_objects.py
+++ b/os_net_config/tests/test_objects.py
@@ -119,6 +119,17 @@ class TestInterface(base.TestCase):
interface1 = objects.object_from_json(json.loads(data))
self.assertEqual("--foobar", interface1.dhclient_args)
+ def test_from_json_dns_servers(self):
+ data = """{
+"type": "interface",
+"name": "em1",
+"use_dhcp": true,
+"dns_servers": ["1.2.3.4"]
+}
+"""
+ interface1 = objects.object_from_json(json.loads(data))
+ self.assertEqual(["1.2.3.4"], interface1.dns_servers)
+
def test_from_json_dhcp_nic1(self):
def dummy_numbered_nics(nic_mapping=None):
return {"nic1": "em3"}