SHA256
1
0
forked from pool/cloud-init
cloud-init/0001-switch-to-using-iproute2-tools.patch
Robert Schweikert fb31094f97 - Update to version 17.2 (boo#1069635, bsc#1072811)
+ Add cloud-init-skip-ovf-tests.patch
  + Add cloud-init-no-python-linux-dist.patch
  + Add 0001-switch-to-using-iproute2-tools.patch
  + Add 0001-Support-chrony-configuration-lp-1731619.patch
  + Add 0002-Disable-method-deprecation-warning-for-pylint.patch
  + Add 0003-Distro-dependent-chrony-config-file.patch
  + removed cloud-init-add-variant-cloudcfg.patch replaced by
    cloud-init-no-python-linux-dist.patch
  + removed zypp_add_repos.diff included upstream
  + removed zypp_add_repo_test.patch included upstream
  + removed cloud-init-hosts-template.patch included upstream
  + removed cloud-init-more-tasks.patch included upstream
  + removed cloud-init-final-no-apt.patch included upstream
  + removed cloud-init-ntp-conf-suse.patch included upstream
  + removed cloud-init-break-cycle-local-service.patch included upstream
  + removed cloud-init-reproduce-build.patch included upstream
  + For the complete changelog see https://launchpad.net/cloud-init/trunk/17.2

OBS-URL: https://build.opensuse.org/package/show/Cloud:Tools/cloud-init?expand=0&rev=105
2018-01-29 21:11:23 +00:00

683 lines
25 KiB
Diff

From 48c4dcd464d8c6daccf09b3dccc664ad347b34ce Mon Sep 17 00:00:00 2001
From: Robert Schweikert <rjschwei@suse.com>
Date: Mon, 18 Dec 2017 13:34:21 -0500
Subject: [PATCH] - switch to using iproute2 tools + ifconfig, netstat and
other tools are being deprecated, switch to using tools that are part of
iproute2 for implementations that support these tools
---
cloudinit/config/cc_disable_ec2_metadata.py | 14 +-
.../config/tests/test_disable_ec2_metadata.py | 72 +++++
cloudinit/netinfo.py | 302 +++++++++++++++------
cloudinit/tests/test_netinfo.py | 174 +++++++++++-
4 files changed, 474 insertions(+), 88 deletions(-)
create mode 100644 cloudinit/config/tests/test_disable_ec2_metadata.py
diff --git a/cloudinit/config/cc_disable_ec2_metadata.py b/cloudinit/config/cc_disable_ec2_metadata.py
index c56319b5..8a166ddf 100644
--- a/cloudinit/config/cc_disable_ec2_metadata.py
+++ b/cloudinit/config/cc_disable_ec2_metadata.py
@@ -32,13 +32,23 @@ from cloudinit.settings import PER_ALWAYS
frequency = PER_ALWAYS
-REJECT_CMD = ['route', 'add', '-host', '169.254.169.254', 'reject']
+REJECT_CMD_IF = ['route', 'add', '-host', '169.254.169.254', 'reject']
+REJECT_CMD_IP = ['ip', 'route', 'add', 'prohibit', '169.254.169.254']
def handle(name, cfg, _cloud, log, _args):
disabled = util.get_cfg_option_bool(cfg, "disable_ec2_metadata", False)
if disabled:
- util.subp(REJECT_CMD, capture=False)
+ reject_cmd = None
+ if util.which('ifconfig'):
+ reject_cmd = REJECT_CMD_IF
+ elif util.which('ip'):
+ reject_cmd = REJECT_CMD_IP
+ else:
+ log.error(('Neither "route" nor "ip" command found, unable to '
+ 'manipulate routing table'))
+ return
+ util.subp(reject_cmd, capture=False)
else:
log.debug(("Skipping module named %s,"
" disabling the ec2 route not enabled"), name)
diff --git a/cloudinit/config/tests/test_disable_ec2_metadata.py b/cloudinit/config/tests/test_disable_ec2_metadata.py
new file mode 100644
index 00000000..bade814e
--- /dev/null
+++ b/cloudinit/config/tests/test_disable_ec2_metadata.py
@@ -0,0 +1,72 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+"""Tests cc_disable_ec2_metadata handler"""
+
+import cloudinit.config.cc_disable_ec2_metadata as ec2_meta
+
+from cloudinit.tests.helpers import CiTestCase, mock
+
+import logging
+
+LOG = logging.getLogger(__name__)
+
+DISABLE_CFG = {'disable_ec2_metadata': 'true'}
+
+
+class TestEC2MetadataRoute(CiTestCase):
+
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.which')
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.subp')
+ def test_disable_ifconfig(self, m_subp, m_which):
+ """Set the route if ifconfig command is available"""
+ m_subp.side_effect = command_check_ifconfig
+ m_which.side_effect = side_effect_use_ifconfig
+ ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.which')
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.subp')
+ def test_disable_ip(self, m_subp, m_which):
+ """Set the route if ip command is available"""
+ m_subp.side_effect = command_check_ip
+ m_which.side_effect = side_effect_use_ip
+ ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.which')
+ @mock.patch('cloudinit.config.cc_disable_ec2_metadata.util.subp')
+ def test_disable_no_tool(self, m_subp, m_which):
+ """Set the route if ip command is available"""
+ m_subp.side_effect = command_dont_reach
+ m_which.side_effect = side_effect_has_no_tool
+ ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+
+
+def side_effect_use_ifconfig(tool):
+ if tool == 'ifconfig':
+ return True
+ else:
+ return False
+
+
+def side_effect_use_ip(tool):
+ if tool == 'ip':
+ return True
+ else:
+ return False
+
+
+def side_effect_has_no_tool(tool):
+ return False
+
+
+def command_check_ifconfig(cmd, capture):
+ assert(cmd == ['route', 'add', '-host', '169.254.169.254', 'reject'])
+
+
+def command_check_ip(cmd, capture):
+ assert(cmd == ['ip', 'route', 'add', 'prohibit', '169.254.169.254'])
+
+
+def command_dont_reach(cmd, capture):
+ assert('Test should not have reached this location' == 0)
+
+# vi: ts=4 expandtab
diff --git a/cloudinit/netinfo.py b/cloudinit/netinfo.py
index 993b26cf..baad3f92 100644
--- a/cloudinit/netinfo.py
+++ b/cloudinit/netinfo.py
@@ -19,6 +19,117 @@ LOG = logging.getLogger()
def netdev_info(empty=""):
+ if util.which('ifconfig'):
+ return _netdev_info_from_ifconfig(empty)
+ elif util.which('ip'):
+ return _netdev_info_from_ip(empty)
+ else:
+ LOG.error(('Neither "ifconfig" nor "ip" command found, unable to '
+ 'collect network device information'))
+ return {}
+
+
+def route_info():
+ if util.which('netstat'):
+ return _route_info_from_netstat()
+ elif util.which('ip'):
+ return _route_info_from_ip()
+ else:
+ LOG.error(('Neither "netstat" nor "ip" command found, unable to '
+ 'collect routing information'))
+ return {}
+
+
+def getgateway():
+ try:
+ routes = route_info()
+ except Exception:
+ pass
+ else:
+ for r in routes.get('ipv4', []):
+ if r['flags'].find("G") >= 0:
+ return "%s[%s]" % (r['gateway'], r['iface'])
+ return None
+
+
+def netdev_pformat():
+ lines = []
+ try:
+ netdev = netdev_info(empty=".")
+ except Exception:
+ lines.append(util.center("Net device info failed", '!', 80))
+ else:
+ fields = ['Device', 'Up', 'Address', 'Mask', 'Scope', 'Hw-Address']
+ tbl = SimpleTable(fields)
+ for (dev, d) in sorted(netdev.items()):
+ tbl.add_row([dev, d["up"], d["addr"], d["mask"], ".", d["hwaddr"]])
+ if d.get('addr6'):
+ tbl.add_row([dev, d["up"],
+ d["addr6"], ".", d.get("scope6"), d["hwaddr"]])
+ netdev_s = tbl.get_string()
+ max_len = len(max(netdev_s.splitlines(), key=len))
+ header = util.center("Net device info", "+", max_len)
+ lines.extend([header, netdev_s])
+ return "\n".join(lines)
+
+
+def route_pformat():
+ lines = []
+ try:
+ routes = route_info()
+ except Exception as e:
+ lines.append(util.center('Route info failed', '!', 80))
+ util.logexc(LOG, "Route info failed: %s" % e)
+ else:
+ if routes.get('ipv4'):
+ fields_v4 = ['Route', 'Destination', 'Gateway',
+ 'Genmask', 'Interface', 'Flags']
+ tbl_v4 = SimpleTable(fields_v4)
+ for (n, r) in enumerate(routes.get('ipv4')):
+ route_id = str(n)
+ tbl_v4.add_row([route_id, r['destination'],
+ r['gateway'], r['genmask'],
+ r['iface'], r['flags']])
+ route_s = tbl_v4.get_string()
+ max_len = len(max(route_s.splitlines(), key=len))
+ header = util.center("Route IPv4 info", "+", max_len)
+ lines.extend([header, route_s])
+ if routes.get('ipv6'):
+ fields_v6 = ['Route', 'Proto', 'Recv-Q', 'Send-Q',
+ 'Local Address', 'Foreign Address', 'State']
+ tbl_v6 = SimpleTable(fields_v6)
+ for (n, r) in enumerate(routes.get('ipv6')):
+ route_id = str(n)
+ tbl_v6.add_row([route_id, r['proto'],
+ r['recv-q'], r['send-q'],
+ r['local address'], r['foreign address'],
+ r['state']])
+ route_s = tbl_v6.get_string()
+ max_len = len(max(route_s.splitlines(), key=len))
+ header = util.center("Route IPv6 info", "+", max_len)
+ lines.extend([header, route_s])
+ return "\n".join(lines)
+
+
+def debug_info(prefix='ci-info: '):
+ lines = []
+ netdev_lines = netdev_pformat().splitlines()
+ if prefix:
+ for line in netdev_lines:
+ lines.append("%s%s" % (prefix, line))
+ else:
+ lines.extend(netdev_lines)
+ route_lines = route_pformat().splitlines()
+ if prefix:
+ for line in route_lines:
+ lines.append("%s%s" % (prefix, line))
+ else:
+ lines.extend(route_lines)
+ return "\n".join(lines)
+
+
+def _netdev_info_from_ifconfig(empty=""):
+ """Use legacy ifconfig output"""
fields = ("hwaddr", "addr", "bcast", "mask")
(ifcfg_out, _err) = util.subp(["ifconfig", "-a"], rcs=[0, 1])
devs = {}
@@ -84,7 +195,54 @@ def netdev_info(empty=""):
return devs
-def route_info():
+def _netdev_info_from_ip(empty=""):
+ """Use ip to get network information"""
+ fields = ("hwaddr", "addr", "bcast", "mask")
+ (ipdata_out, _err) = util.subp(["ip", "a"], rcs=[0, 1])
+ devs = {}
+ this_device = None
+ for line in str(ipdata_out).splitlines():
+ if len(line) == 0:
+ continue
+ if line[0].isdigit():
+ prts = line.strip().split(':')
+ this_device = prts[1].strip()
+ devs[this_device] = {}
+ for field in fields:
+ devs[this_device][field] = ''
+ devs[this_device]['up'] = False
+ status_info = re.match('(<)(.*)(>)', prts[-1].strip()).group(2)
+ status_info = status_info.lower().split(',')
+ if 'up' in status_info:
+ devs[this_device]['up'] = True
+ if 'broadcast' in status_info and 'multicast' in status_info:
+ devs[this_device]['bcast'] = 'multicast'
+ continue
+ conf_data = line.strip()
+ conf_data_prts = conf_data.split()
+ if conf_data.startswith('inet '):
+ devs[this_device]['addr'] = conf_data_prts[1]
+ if 'brd' in conf_data_prts:
+ loc = conf_data_prts.index('brd')
+ devs[this_device]['bcast'] = conf_data_prts[loc + 1]
+ if conf_data.startswith('inet6'):
+ devs[this_device]['addr6'] = conf_data_prts[1]
+ if 'scope' in conf_data_prts:
+ loc = conf_data_prts.index('scope')
+ devs[this_device]['scope6'] = conf_data_prts[loc + 1]
+ if conf_data.startswith('link/ether'):
+ devs[this_device]['hwaddr'] = conf_data_prts[1]
+
+ if empty != "":
+ for (_devname, dev) in devs.items():
+ for field in dev:
+ if dev[field] == "":
+ dev[field] = empty
+
+ return devs
+
+
+def _route_info_from_netstat():
(route_out, _err) = util.subp(["netstat", "-rn"], rcs=[0, 1])
routes = {}
@@ -150,91 +308,69 @@ def route_info():
return routes
-def getgateway():
- try:
- routes = route_info()
- except Exception:
- pass
- else:
- for r in routes.get('ipv4', []):
- if r['flags'].find("G") >= 0:
- return "%s[%s]" % (r['gateway'], r['iface'])
- return None
-
-
-def netdev_pformat():
- lines = []
- try:
- netdev = netdev_info(empty=".")
- except Exception:
- lines.append(util.center("Net device info failed", '!', 80))
- else:
- fields = ['Device', 'Up', 'Address', 'Mask', 'Scope', 'Hw-Address']
- tbl = SimpleTable(fields)
- for (dev, d) in sorted(netdev.items()):
- tbl.add_row([dev, d["up"], d["addr"], d["mask"], ".", d["hwaddr"]])
- if d.get('addr6'):
- tbl.add_row([dev, d["up"],
- d["addr6"], ".", d.get("scope6"), d["hwaddr"]])
- netdev_s = tbl.get_string()
- max_len = len(max(netdev_s.splitlines(), key=len))
- header = util.center("Net device info", "+", max_len)
- lines.extend([header, netdev_s])
- return "\n".join(lines)
+def _route_info_from_ip():
+ """Detremine route information from ip route command"""
+ routes = {}
+ routes['ipv4'] = []
+ routes['ipv6'] = []
+ # IPv4
+ (route_out, _err) = util.subp(['ip', '-4', 'route', 'list'], rcs=[0, 1])
-def route_pformat():
- lines = []
- try:
- routes = route_info()
- except Exception as e:
- lines.append(util.center('Route info failed', '!', 80))
- util.logexc(LOG, "Route info failed: %s" % e)
- else:
- if routes.get('ipv4'):
- fields_v4 = ['Route', 'Destination', 'Gateway',
- 'Genmask', 'Interface', 'Flags']
- tbl_v4 = SimpleTable(fields_v4)
- for (n, r) in enumerate(routes.get('ipv4')):
- route_id = str(n)
- tbl_v4.add_row([route_id, r['destination'],
- r['gateway'], r['genmask'],
- r['iface'], r['flags']])
- route_s = tbl_v4.get_string()
- max_len = len(max(route_s.splitlines(), key=len))
- header = util.center("Route IPv4 info", "+", max_len)
- lines.extend([header, route_s])
- if routes.get('ipv6'):
- fields_v6 = ['Route', 'Proto', 'Recv-Q', 'Send-Q',
- 'Local Address', 'Foreign Address', 'State']
- tbl_v6 = SimpleTable(fields_v6)
- for (n, r) in enumerate(routes.get('ipv6')):
- route_id = str(n)
- tbl_v6.add_row([route_id, r['proto'],
- r['recv-q'], r['send-q'],
- r['local address'], r['foreign address'],
- r['state']])
- route_s = tbl_v6.get_string()
- max_len = len(max(route_s.splitlines(), key=len))
- header = util.center("Route IPv6 info", "+", max_len)
- lines.extend([header, route_s])
- return "\n".join(lines)
+ entries = route_out.splitlines()
+ for line in entries:
+ route_info = line.strip().split()
+ dest = route_info[0]
+ if route_info[0] == 'default':
+ dest = '0.0.0.0'
+ flags = ''
+ gw = '0.0.0.0'
+ if 'via' in route_info:
+ loc = route_info.index('via')
+ # The NH (Next Hop) is basically equivalent to the gateway
+ gw = route_info[loc + 1]
+ flags = 'G'
+ loc = route_info.index('dev')
+ dev = route_info[loc + 1]
+ entry = {
+ 'destination': dest,
+ 'gateway': gw,
+ 'genmask': '',
+ 'flags': flags,
+ 'metric': '0',
+ 'ref': '0',
+ 'use': '0',
+ 'iface': dev
+ }
+ routes['ipv4'].append(entry)
+ # IPv6
+ (route_out, _err) = util.subp(['ip', '-6', 'route', 'list'], rcs=[0, 1])
-def debug_info(prefix='ci-info: '):
- lines = []
- netdev_lines = netdev_pformat().splitlines()
- if prefix:
- for line in netdev_lines:
- lines.append("%s%s" % (prefix, line))
- else:
- lines.extend(netdev_lines)
- route_lines = route_pformat().splitlines()
- if prefix:
- for line in route_lines:
- lines.append("%s%s" % (prefix, line))
- else:
- lines.extend(route_lines)
- return "\n".join(lines)
+ entries = route_out.splitlines()
+ for line in entries:
+ route_info = line.strip().split()
+ ip = route_info[0]
+ if ip == 'default':
+ ip = '::'
+ proto = 'tcp6'
+ if 'proto' in route_info:
+ loc = route_info.index('proto')
+ proto = route_info[loc + 1]
+ gw = ''
+ if 'via' in route_info:
+ loc = route_info.index('via')
+ # The NH (Next Hop) is basically equivalent to the gateway
+ gw = route_info[loc + 1]
+ entry = {
+ 'proto': proto,
+ 'recv-q': '0',
+ 'send-q': '0',
+ 'local address': ip,
+ 'foreign address': gw,
+ 'state': '',
+ }
+ routes['ipv6'].append(entry)
+ return routes
# vi: ts=4 expandtab
diff --git a/cloudinit/tests/test_netinfo.py b/cloudinit/tests/test_netinfo.py
index 7dea2e41..3dc557cc 100644
--- a/cloudinit/tests/test_netinfo.py
+++ b/cloudinit/tests/test_netinfo.py
@@ -2,7 +2,7 @@
"""Tests netinfo module functions and classes."""
-from cloudinit.netinfo import netdev_pformat, route_pformat
+from cloudinit.netinfo import getgateway, netdev_pformat, route_pformat
from cloudinit.tests.helpers import CiTestCase, mock
@@ -27,6 +27,48 @@ lo Link encap:Local Loopback
collisions:0 txqueuelen:1
"""
+SAMPLE_IP_A_OUT = (
+ '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN '
+ 'group default qlen 1000\n'
+ 'link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n'
+ 'inet 127.0.0.1/8 scope host lo\n'
+ ' valid_lft forever preferred_lft forever\n'
+ 'inet6 ::1/128 scope host\n'
+ ' valid_lft forever preferred_lft forever\n'
+ '2: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state '
+ 'UP group default qlen 1000\n'
+ 'link/ether 84:3a:4b:09:6f:ec brd ff:ff:ff:ff:ff:ff\n'
+ 'inet 192.168.1.101/24 brd 192.168.1.255 scope global wlp3s0\n'
+ ' valid_lft forever preferred_lft forever\n'
+ 'inet 192.168.1.3/24 brd 192.168.1.255 scope global secondary wlp3s0\n'
+ ' valid_lft forever preferred_lft forever\n'
+ 'inet6 fe80::863a:4bff:fe09:6fec/64 scope link\n'
+ ' valid_lft forever preferred_lft forever'
+)
+
+SAMPLE_ROUTE_INFO = {
+ 'ipv4': [
+ {
+ 'genmask': '0.0.0.0',
+ 'use': '0',
+ 'iface': 'eth1',
+ 'flags': 'UG',
+ 'metric': '0',
+ 'destination': '0.0.0.0',
+ 'ref': '0',
+ 'gateway': '192.168.1.1'},
+ {
+ 'genmask': '255.0.0.0',
+ 'use': '0',
+ 'iface': 'eth2',
+ 'flags': 'UG',
+ 'metric': '0',
+ 'destination': '10.0.0.0',
+ 'ref': '0',
+ 'gateway': '10.163.8.1'}
+ ]
+}
+
SAMPLE_ROUTE_OUT = '\n'.join([
'0.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0'
' enp0s25',
@@ -35,6 +77,20 @@ SAMPLE_ROUTE_OUT = '\n'.join([
'192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0'
' enp0s25'])
+SAMPLE_ROUTE_OUT_IP_V4 = '\n'.join([
+ 'default via 192.168.1.1 dev br0',
+ '10.0.0.0/8 via 10.163.8.1 dev tun0',
+ '10.163.8.1 dev tun0 proto kernel scope link src 10.163.8.118 ',
+ '137.65.0.0/16 via 10.163.8.1 dev tun0'])
+
+SAMPLE_ROUTE_OUT_IP_V6 = '\n'.join([
+ '2621:111:80c0:8080:12:160:68:53 dev eth0 proto kernel metric 256 expires '
+ '9178sec pref medium',
+ '2621:111:80c0:8080::/64 dev eth0 proto ra metric 100 pref medium',
+ 'fe80::1 dev eth0 proto static metric 100 pref medium',
+ 'fe80::/64 dev eth0 proto kernel metric 256 pref medium',
+ 'default via fe80::1 dev eth0 proto static metric 100 pref medium',
+ '2620:113:80c0:8000::/50 dev tun0 metric 1024 pref medium'])
NETDEV_FORMATTED_OUT = '\n'.join([
'+++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++'
@@ -56,6 +112,26 @@ NETDEV_FORMATTED_OUT = '\n'.join([
'+---------+------+------------------------------+---------------+-------+'
'-------------------+'])
+NETDEV_FORMATTED_OUT_IP = '\n'.join([
+ '++++++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++'
+ '++++++++++++',
+ '+--------+------+------------------------------+------+-------+----------'
+ '---------+',
+ '| Device | Up | Address | Mask | Scope | Hw-Ad'
+ 'dress |',
+ '+--------+------+------------------------------+------+-------+----------'
+ '---------+',
+ '| lo | True | 127.0.0.1/8 | . | . | .'
+ ' |',
+ '| lo | True | ::1/128 | . | host | .'
+ ' |',
+ '| wlp3s0 | True | 192.168.1.3/24 | . | . | 84:3a:4b:'
+ '09:6f:ec |',
+ '| wlp3s0 | True | fe80::863a:4bff:fe09:6fec/64 | . | link | 84:3a:4b:'
+ '09:6f:ec |',
+ '+--------+------+------------------------------+------+-------+----------'
+ '---------+'])
+
ROUTE_FORMATTED_OUT = '\n'.join([
'+++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++'
'+++',
@@ -86,21 +162,113 @@ ROUTE_FORMATTED_OUT = '\n'.join([
'+-------+-------------+-------------+---------------+---------------+'
'-----------------+-------+'])
+ROUTE_FORMATTED_OUT_IP = '\n'.join([
+ '+++++++++++++++++++++++++++Route IPv4 info+++++++++++++++++++++++++++',
+ '+-------+---------------+-------------+---------+-----------+-------+',
+ '| Route | Destination | Gateway | Genmask | Interface | Flags |',
+ '+-------+---------------+-------------+---------+-----------+-------+',
+ '| 0 | 0.0.0.0 | 192.168.1.1 | | br0 | G |',
+ '| 1 | 10.0.0.0/8 | 10.163.8.1 | | tun0 | G |',
+ '| 2 | 10.163.8.1 | 0.0.0.0 | | tun0 | |',
+ '| 3 | 137.65.0.0/16 | 10.163.8.1 | | tun0 | G |',
+ '+-------+---------------+-------------+---------+-----------+-------+',
+ '++++++++++++++++++++++++++++++++++++++++Route IPv6 info++++++++++++++'
+ '+++++++++++++++++++++++++++',
+ '+-------+--------+--------+--------+---------------------------------'
+ '+-----------------+-------+',
+ '| Route | Proto | Recv-Q | Send-Q | Local Address '
+ '| Foreign Address | State |',
+ '+-------+--------+--------+--------+---------------------------------'
+ '+-----------------+-------+',
+ '| 0 | kernel | 0 | 0 | 2621:111:80c0:8080:12:160:68:53 '
+ '| | |',
+ '| 1 | ra | 0 | 0 | 2621:111:80c0:8080::/64 '
+ '| | |',
+ '| 2 | static | 0 | 0 | fe80::1 '
+ '| | |',
+ '| 3 | kernel | 0 | 0 | fe80::/64 '
+ '| | |',
+ '| 4 | static | 0 | 0 | :: '
+ '| fe80::1 | |',
+ '| 5 | tcp6 | 0 | 0 | 2620:113:80c0:8000::/50 '
+ '| | |',
+ '+-------+--------+--------+--------+---------------------------------'
+ '+-----------------+-------+'])
+
class TestNetInfo(CiTestCase):
maxDiff = None
+ @mock.patch('cloudinit.netinfo.route_info')
+ def test_getdateway_route(self, m_route_info):
+ """getgateway finds the first gateway"""
+ m_route_info.return_value = SAMPLE_ROUTE_INFO
+ gateway = getgateway()
+ self.assertEqual('192.168.1.1[eth1]', gateway)
+
+ @mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
- def test_netdev_pformat(self, m_subp):
+ def test_netdev_pformat_ifconfig(self, m_subp, m_which):
"""netdev_pformat properly rendering network device information."""
m_subp.return_value = (SAMPLE_IFCONFIG_OUT, '')
+ m_which.side_effect = side_effect_use_ifconfig
content = netdev_pformat()
self.assertEqual(NETDEV_FORMATTED_OUT, content)
+ @mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
- def test_route_pformat(self, m_subp):
+ def test_netdev_pformat_ip(self, m_subp, m_which):
+ """netdev_pformat properly rendering network device information."""
+ m_subp.return_value = (SAMPLE_IP_A_OUT, '')
+ m_which.side_effect = side_effect_use_ip
+ content = netdev_pformat()
+ self.assertEqual(NETDEV_FORMATTED_OUT_IP, content)
+
+ @mock.patch('cloudinit.netinfo.util.which')
+ @mock.patch('cloudinit.netinfo.util.subp')
+ def test_route_pformat_netstat(self, m_subp, m_which):
"""netdev_pformat properly rendering network device information."""
m_subp.return_value = (SAMPLE_ROUTE_OUT, '')
+ m_which.side_effect = side_effect_use_netstat
content = route_pformat()
self.assertEqual(ROUTE_FORMATTED_OUT, content)
+
+ @mock.patch('cloudinit.netinfo.util.which')
+ @mock.patch('cloudinit.netinfo.util.subp')
+ def test_route_pformat_ip(self, m_subp, m_which):
+ """netdev_pformat properly rendering network device information."""
+ m_subp.side_effect = side_effect_return_route_info
+ m_which.side_effect = side_effect_use_ip
+ content = route_pformat()
+ self.assertEqual(ROUTE_FORMATTED_OUT_IP, content)
+
+
+def side_effect_use_ifconfig(tool):
+ if tool == 'ifconfig':
+ return True
+ else:
+ return False
+
+
+def side_effect_use_ip(tool):
+ if tool == 'ip':
+ return True
+ else:
+ return False
+
+
+def side_effect_use_netstat(tool):
+ if tool == 'netstat':
+ return True
+ else:
+ return False
+
+
+def side_effect_return_route_info(cmd, rcs=None):
+ if '-4' in list(cmd):
+ return (SAMPLE_ROUTE_OUT_IP_V4, 0)
+ else:
+ return (SAMPLE_ROUTE_OUT_IP_V6, 0)
+
+# vi: ts=4 expandtab
--
2.13.6