summaryrefslogtreecommitdiff
path: root/cloudinit/distros
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/distros')
-rw-r--r--cloudinit/distros/networking.py15
-rw-r--r--cloudinit/distros/tests/test_networking.py31
2 files changed, 46 insertions, 0 deletions
diff --git a/cloudinit/distros/networking.py b/cloudinit/distros/networking.py
index e407fa29..c291196a 100644
--- a/cloudinit/distros/networking.py
+++ b/cloudinit/distros/networking.py
@@ -2,6 +2,7 @@ import abc
import logging
import os
+from cloudinit import subp
from cloudinit import net, util
@@ -175,6 +176,10 @@ class Networking(metaclass=abc.ABCMeta):
if strict:
raise RuntimeError(msg)
+ @abc.abstractmethod
+ def try_set_link_up(self, devname: DeviceName) -> bool:
+ """Try setting the link to up explicitly and return if it is up."""
+
class BSDNetworking(Networking):
"""Implementation of networking functionality shared across BSDs."""
@@ -185,6 +190,9 @@ class BSDNetworking(Networking):
def settle(self, *, exists=None) -> None:
"""BSD has no equivalent to `udevadm settle`; noop."""
+ def try_set_link_up(self, devname: DeviceName) -> bool:
+ raise NotImplementedError()
+
class LinuxNetworking(Networking):
"""Implementation of networking functionality common to Linux distros."""
@@ -214,3 +222,10 @@ class LinuxNetworking(Networking):
if exists is not None:
exists = net.sys_dev_path(exists)
util.udevadm_settle(exists=exists)
+
+ def try_set_link_up(self, devname: DeviceName) -> bool:
+ """Try setting the link to up explicitly and return if it is up.
+ Not guaranteed to bring the interface up. The caller is expected to
+ add wait times before retrying."""
+ subp.subp(['ip', 'link', 'set', devname, 'up'])
+ return self.is_up(devname)
diff --git a/cloudinit/distros/tests/test_networking.py b/cloudinit/distros/tests/test_networking.py
index b9a63842..ec508f4d 100644
--- a/cloudinit/distros/tests/test_networking.py
+++ b/cloudinit/distros/tests/test_networking.py
@@ -30,6 +30,9 @@ def generic_networking_cls():
def settle(self, *args, **kwargs):
raise NotImplementedError
+ def try_set_link_up(self, *args, **kwargs):
+ raise NotImplementedError
+
error = AssertionError("Unexpectedly used /sys in generic networking code")
with mock.patch(
"cloudinit.net.get_sys_class_path", side_effect=error,
@@ -74,6 +77,34 @@ class TestLinuxNetworkingIsPhysical:
assert LinuxNetworking().is_physical(devname)
+class TestBSDNetworkingTrySetLinkUp:
+ def test_raises_notimplementederror(self):
+ with pytest.raises(NotImplementedError):
+ BSDNetworking().try_set_link_up("eth0")
+
+
+@mock.patch("cloudinit.net.is_up")
+@mock.patch("cloudinit.distros.networking.subp.subp")
+class TestLinuxNetworkingTrySetLinkUp:
+ def test_calls_subp_return_true(self, m_subp, m_is_up):
+ devname = "eth0"
+ m_is_up.return_value = True
+ is_success = LinuxNetworking().try_set_link_up(devname)
+
+ assert (mock.call(['ip', 'link', 'set', devname, 'up']) ==
+ m_subp.call_args_list[-1])
+ assert is_success
+
+ def test_calls_subp_return_false(self, m_subp, m_is_up):
+ devname = "eth0"
+ m_is_up.return_value = False
+ is_success = LinuxNetworking().try_set_link_up(devname)
+
+ assert (mock.call(['ip', 'link', 'set', devname, 'up']) ==
+ m_subp.call_args_list[-1])
+ assert not is_success
+
+
class TestBSDNetworkingSettle:
def test_settle_doesnt_error(self):
# This also implicitly tests that it doesn't use subp.subp