summaryrefslogtreecommitdiff
path: root/cloudinit/net
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2017-03-15 14:33:45 -0400
committerScott Moser <smoser@brickies.net>2017-03-17 21:31:56 -0400
commit5beecdf88b630a397b3722ddb299e9a37ff02737 (patch)
tree620b47c50cd392789bcd8afd3dc355bcbbf751bc /cloudinit/net
parent58cc8f7521725d4f007ce90001a28326bc240231 (diff)
downloadvyos-cloud-init-5beecdf88b630a397b3722ddb299e9a37ff02737.tar.gz
vyos-cloud-init-5beecdf88b630a397b3722ddb299e9a37ff02737.zip
net: add renderers for automatically selecting the renderer.
Previously, the distro had hard coded which network renderer it would use. This adds support for just picking the right renderer based on what is available. Now, that can be set via a priority in system_info, but should generally work. That config looks like: system_info: network: renderers: ["eni", "sysconfig"] When no renderers are found, a specific RendererNotFoundError is raised. stages.py is modified to catch that and log it at error level. This path should not really be exercised, but could occur if for example an Ubuntu system did not have ifupdown, or a rhel system did not have sysconfig. In such a system previously we would have quietly rendered ENI configuration but that would have been ignored. This is one step better in that we at least log the error.
Diffstat (limited to 'cloudinit/net')
-rwxr-xr-xcloudinit/net/__init__.py5
-rw-r--r--cloudinit/net/eni.py14
-rw-r--r--cloudinit/net/renderer.py5
-rw-r--r--cloudinit/net/renderers.py51
-rw-r--r--cloudinit/net/sysconfig.py17
5 files changed, 92 insertions, 0 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index ea649cc2..1cf98ef5 100755
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -364,4 +364,9 @@ def get_interfaces_by_mac(devs=None):
ret[mac] = name
return ret
+
+class RendererNotFoundError(RuntimeError):
+ pass
+
+
# vi: ts=4 expandtab
diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
index efa034bf..9d39a2b0 100644
--- a/cloudinit/net/eni.py
+++ b/cloudinit/net/eni.py
@@ -500,4 +500,18 @@ def network_state_to_eni(network_state, header=None, render_hwaddress=False):
network_state, render_hwaddress=render_hwaddress)
return header + contents
+
+def available(target=None):
+ expected = ['ifquery', 'ifup', 'ifdown']
+ search = ['/sbin', '/usr/sbin']
+ for p in expected:
+ if not util.which(p, search=search, target=target):
+ return False
+ eni = util.target_path(target, 'etc/network/interfaces')
+ if not os.path.is_file(eni):
+ return False
+
+ return True
+
+
# vi: ts=4 expandtab
diff --git a/cloudinit/net/renderer.py b/cloudinit/net/renderer.py
index 3a192436..a5b2b573 100644
--- a/cloudinit/net/renderer.py
+++ b/cloudinit/net/renderer.py
@@ -7,6 +7,7 @@
import six
+from .network_state import parse_net_config_data
from .udev import generate_udev_rule
@@ -36,4 +37,8 @@ class Renderer(object):
iface['mac_address']))
return content.getvalue()
+ def render_network_config(self, network_config, target=None):
+ return self.render_network_state(
+ network_state=parse_net_config_data(network_config), target=target)
+
# vi: ts=4 expandtab
diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py
new file mode 100644
index 00000000..5ad84553
--- /dev/null
+++ b/cloudinit/net/renderers.py
@@ -0,0 +1,51 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from . import eni
+from . import RendererNotFoundError
+from . import sysconfig
+
+NAME_TO_RENDERER = {
+ "eni": eni,
+ "sysconfig": sysconfig,
+}
+
+DEFAULT_PRIORITY = ["eni", "sysconfig"]
+
+
+def search(priority=None, target=None, first=False):
+ if priority is None:
+ priority = DEFAULT_PRIORITY
+
+ available = NAME_TO_RENDERER
+
+ unknown = [i for i in priority if i not in available]
+ if unknown:
+ raise ValueError(
+ "Unknown renderers provided in priority list: %s" % unknown)
+
+ found = []
+ for name in priority:
+ render_mod = available[name]
+ if render_mod.available(target):
+ cur = (name, render_mod.Renderer)
+ if first:
+ return cur
+ found.append(cur)
+
+ return found
+
+
+def select(priority=None, target=None):
+ found = search(priority, target=target, first=True)
+ if not found:
+ if priority is None:
+ priority = DEFAULT_PRIORITY
+ tmsg = ""
+ if target and target != "/":
+ tmsg = " in target=%s" % target
+ raise RendererNotFoundError(
+ "No available network renderers found%s. Searched "
+ "through list: %s" % (tmsg, priority))
+ return found
+
+# vi: ts=4 expandtab
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 4eeaaa8a..117b515c 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -404,4 +404,21 @@ class Renderer(renderer.Renderer):
netrules_path = util.target_path(target, self.netrules_path)
util.write_file(netrules_path, netrules_content)
+
+def available(target=None):
+ expected = ['ifup', 'ifdown']
+ search = ['/sbin', '/usr/sbin']
+ for p in expected:
+ if not util.which(p, search=search, target=target):
+ return False
+
+ expected_paths = [
+ 'etc/sysconfig/network-scripts/network-functions',
+ 'etc/sysconfig/network-scripts/ifdown-eth']
+ for p in expected_paths:
+ if not os.path.isfile(util.target_path(target, p)):
+ return False
+ return True
+
+
# vi: ts=4 expandtab