forked from pool/cloud-init
Robert Schweikert
1d35d9d69b
- Handle the exception when attempting to detect if the network device is up when it is not OBS-URL: https://build.opensuse.org/package/show/Cloud:Tools/cloud-init?expand=0&rev=48
211 lines
7.8 KiB
Diff
211 lines
7.8 KiB
Diff
--- cloudinit/net/__init__.py.orig
|
|
+++ cloudinit/net/__init__.py
|
|
@@ -33,10 +33,12 @@ def sys_dev_path(devname, path=""):
|
|
|
|
|
|
def read_sys_net(devname, path, translate=None, enoent=None, keyerror=None):
|
|
+ dev_path = sys_dev_path(devname, path)
|
|
try:
|
|
- contents = util.load_file(sys_dev_path(devname, path))
|
|
+ contents = util.load_file(dev_path)
|
|
except (OSError, IOError) as e:
|
|
- if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
|
|
+ e_errno = getattr(e, 'errno', None)
|
|
+ if e_errno in (errno.ENOENT, errno.ENOTDIR):
|
|
if enoent is not None:
|
|
return enoent
|
|
raise
|
|
@@ -109,24 +111,9 @@ def is_disabled_cfg(cfg):
|
|
return cfg.get('config') == "disabled"
|
|
|
|
|
|
-def sys_netdev_info(name, field):
|
|
- if not os.path.exists(os.path.join(SYS_CLASS_NET, name)):
|
|
- raise OSError("%s: interface does not exist in %s" %
|
|
- (name, SYS_CLASS_NET))
|
|
- fname = os.path.join(SYS_CLASS_NET, name, field)
|
|
- if not os.path.exists(fname):
|
|
- raise OSError("%s: could not find sysfs entry: %s" % (name, fname))
|
|
- data = util.load_file(fname)
|
|
- if data[-1] == '\n':
|
|
- data = data[:-1]
|
|
- return data
|
|
-
|
|
-
|
|
def generate_fallback_config():
|
|
"""Determine which attached net dev is most likely to have a connection and
|
|
generate network state to run dhcp on that interface"""
|
|
- # by default use eth0 as primary interface
|
|
- nconf = {'config': [], 'version': 1}
|
|
|
|
# get list of interfaces that could have connections
|
|
invalid_interfaces = set(['lo'])
|
|
@@ -143,28 +130,30 @@ def generate_fallback_config():
|
|
# skip any bridges
|
|
continue
|
|
try:
|
|
- carrier = int(sys_netdev_info(interface, 'carrier'))
|
|
+ carrier = read_sys_net(interface, 'carrier', enoent=False)
|
|
if carrier:
|
|
+ carrier = int(carrier)
|
|
connected.append(interface)
|
|
continue
|
|
- except OSError:
|
|
+ except (IOError, OSError, TypeError):
|
|
pass
|
|
# check if nic is dormant or down, as this may make a nick appear to
|
|
# not have a carrier even though it could acquire one when brought
|
|
# online by dhclient
|
|
try:
|
|
- dormant = int(sys_netdev_info(interface, 'dormant'))
|
|
+ dormant = read_sys_net(interface, 'dormant', enoent=False)
|
|
if dormant:
|
|
+ domant = int(dormant)
|
|
possibly_connected.append(interface)
|
|
continue
|
|
- except OSError:
|
|
+ except (IOError, OSError, TypeError):
|
|
pass
|
|
try:
|
|
- operstate = sys_netdev_info(interface, 'operstate')
|
|
+ operstate = read_sys_net(interface, 'operstate', enoent=False)
|
|
if operstate in ['dormant', 'down', 'lowerlayerdown', 'unknown']:
|
|
possibly_connected.append(interface)
|
|
continue
|
|
- except OSError:
|
|
+ except (IOError, OSError):
|
|
pass
|
|
|
|
# don't bother with interfaces that might not be connected if there are
|
|
@@ -173,23 +162,29 @@ def generate_fallback_config():
|
|
potential_interfaces = connected
|
|
else:
|
|
potential_interfaces = possibly_connected
|
|
- # if there are no interfaces, give up
|
|
- if not potential_interfaces:
|
|
- return
|
|
+
|
|
# if eth0 exists use it above anything else, otherwise get the interface
|
|
- # that looks 'first'
|
|
- if DEFAULT_PRIMARY_INTERFACE in potential_interfaces:
|
|
- name = DEFAULT_PRIMARY_INTERFACE
|
|
+ # that we can read 'first' (using the sorted defintion of first).
|
|
+ names = [DEFAULT_PRIMARY_INTERFACE]
|
|
+ names.extend(sorted(potential_interfaces))
|
|
+ target_name = None
|
|
+ target_mac = None
|
|
+ for name in names:
|
|
+ if name not in potential_interfaces:
|
|
+ continue
|
|
+ mac = read_sys_net(name, 'address', enoent=False)
|
|
+ if mac:
|
|
+ target_name = name
|
|
+ target_mac = mac
|
|
+ break
|
|
+ if target_mac and target_name:
|
|
+ nconf = {'config': [], 'version': 1}
|
|
+ nconf['config'].append(
|
|
+ {'type': 'physical', 'name': target_name,
|
|
+ 'mac_address': target_mac, 'subnets': [{'type': 'dhcp'}]})
|
|
+ return nconf
|
|
else:
|
|
- name = sorted(potential_interfaces)[0]
|
|
-
|
|
- mac = sys_netdev_info(name, 'address')
|
|
- target_name = name
|
|
-
|
|
- nconf['config'].append(
|
|
- {'type': 'physical', 'name': target_name,
|
|
- 'mac_address': mac, 'subnets': [{'type': 'dhcp'}]})
|
|
- return nconf
|
|
+ return None
|
|
|
|
|
|
def apply_network_config_names(netcfg, strict_present=True, strict_busy=True):
|
|
--- cloudinit/net/cmdline.py.orig
|
|
+++ cloudinit/net/cmdline.py
|
|
@@ -26,7 +26,7 @@ import sys
|
|
import six
|
|
|
|
from . import get_devicelist
|
|
-from . import sys_netdev_info
|
|
+from . import read_sys_net
|
|
|
|
from cloudinit import util
|
|
|
|
@@ -197,7 +197,10 @@ def read_kernel_cmdline_config(files=Non
|
|
return None
|
|
|
|
if mac_addrs is None:
|
|
- mac_addrs = dict((k, sys_netdev_info(k, 'address'))
|
|
- for k in get_devicelist())
|
|
+ mac_addrs = {}
|
|
+ for k in get_devicelist():
|
|
+ mac_addr = read_sys_net(k, 'address', enoent=False)
|
|
+ if mac_addr:
|
|
+ mac_addrs[k] = mac_addr
|
|
|
|
return config_from_klibc_net_cfg(files=files, mac_addrs=mac_addrs)
|
|
--- tests/unittests/test_net.py.orig
|
|
+++ tests/unittests/test_net.py
|
|
@@ -422,7 +422,7 @@ pre-down route del -net 10.0.0.0 netmask
|
|
}
|
|
|
|
|
|
-def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info,
|
|
+def _setup_test(tmp_dir, mock_get_devicelist, mock_read_sys_net,
|
|
mock_sys_dev_path):
|
|
mock_get_devicelist.return_value = ['eth1000']
|
|
dev_characteristics = {
|
|
@@ -435,10 +435,10 @@ def _setup_test(tmp_dir, mock_get_device
|
|
}
|
|
}
|
|
|
|
- def netdev_info(name, field):
|
|
+ def fake_read(devname, path, translate=None, enoent=None, keyerror=None):
|
|
return dev_characteristics[name][field]
|
|
|
|
- mock_sys_netdev_info.side_effect = netdev_info
|
|
+ mock_read_sys_net.side_effect = fake_read
|
|
|
|
def sys_dev_path(devname, path=""):
|
|
return tmp_dir + devname + "/" + path
|
|
@@ -454,15 +454,15 @@ def _setup_test(tmp_dir, mock_get_device
|
|
class TestSysConfigRendering(TestCase):
|
|
|
|
@mock.patch("cloudinit.net.sys_dev_path")
|
|
- @mock.patch("cloudinit.net.sys_netdev_info")
|
|
+ @mock.patch("cloudinit.net.read_sys_net")
|
|
@mock.patch("cloudinit.net.get_devicelist")
|
|
def test_default_generation(self, mock_get_devicelist,
|
|
- mock_sys_netdev_info,
|
|
+ mock_read_sys_net,
|
|
mock_sys_dev_path):
|
|
tmp_dir = tempfile.mkdtemp()
|
|
self.addCleanup(shutil.rmtree, tmp_dir)
|
|
_setup_test(tmp_dir, mock_get_devicelist,
|
|
- mock_sys_netdev_info, mock_sys_dev_path)
|
|
+ mock_read_sys_net, mock_sys_dev_path)
|
|
|
|
network_cfg = net.generate_fallback_config()
|
|
ns = network_state.parse_net_config_data(network_cfg,
|
|
@@ -511,15 +511,15 @@ USERCTL=no
|
|
class TestEniNetRendering(TestCase):
|
|
|
|
@mock.patch("cloudinit.net.sys_dev_path")
|
|
- @mock.patch("cloudinit.net.sys_netdev_info")
|
|
+ @mock.patch("cloudinit.net.read_sys_net")
|
|
@mock.patch("cloudinit.net.get_devicelist")
|
|
def test_default_generation(self, mock_get_devicelist,
|
|
- mock_sys_netdev_info,
|
|
+ mock_read_sys_net,
|
|
mock_sys_dev_path):
|
|
tmp_dir = tempfile.mkdtemp()
|
|
self.addCleanup(shutil.rmtree, tmp_dir)
|
|
_setup_test(tmp_dir, mock_get_devicelist,
|
|
- mock_sys_netdev_info, mock_sys_dev_path)
|
|
+ mock_read_sys_net, mock_sys_dev_path)
|
|
|
|
network_cfg = net.generate_fallback_config()
|
|
ns = network_state.parse_net_config_data(network_cfg,
|