View | Details | Raw Unified | Return to bug 240372
Collapse All | Expand All

(-)Makefile (+1 lines)
Lines 2-7 Link Here
2
2
3
PORTNAME=	cloud-init
3
PORTNAME=	cloud-init
4
PORTVERSION=	19.2
4
PORTVERSION=	19.2
5
PORTREVISION=	1
5
CATEGORIES=	net python
6
CATEGORIES=	net python
6
MASTER_SITES=	http://launchpad.net/${PORTNAME}/trunk/${PORTVERSION}/+download/
7
MASTER_SITES=	http://launchpad.net/${PORTNAME}/trunk/${PORTVERSION}/+download/
7
PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
8
PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
(-)files/patch-cloudinit_config_cc__set__passwords.py (+87 lines)
Line 0 Link Here
1
--- cloudinit/config/cc_set_passwords.py.orig	2019-07-17 16:30:07 UTC
2
+++ cloudinit/config/cc_set_passwords.py
3
@@ -153,71 +153,31 @@ def handle(_name, cfg, cloud, log, args):
4
         else:
5
             log.warn("No default or defined user to change password for.")
6
 
7
-    errors = []
8
+    random_msg = (
9
+        "Set the following 'random' password:\n"
10
+        "  '%s' to %s")
11
+
12
     if plist:
13
-        plist_in = []
14
-        hashed_plist_in = []
15
-        hashed_users = []
16
-        randlist = []
17
         users = []
18
         prog = re.compile(r'\$(1|2a|2y|5|6)(\$.+){2}')
19
         for line in plist:
20
             u, p = line.split(':', 1)
21
+            log.debug("Setting password for: %s" % u)
22
             if prog.match(p) is not None and ":" not in p:
23
-                hashed_plist_in.append("%s:%s" % (u, p))
24
-                hashed_users.append(u)
25
-            else:
26
-                if p == "R" or p == "RANDOM":
27
+                cloud.distro.set_passwd(u, p, hashed=True)
28
+            elif p == "R" or p == "RANDOM":
29
                     p = rand_user_password()
30
-                    randlist.append("%s:%s" % (u, p))
31
-                plist_in.append("%s:%s" % (u, p))
32
-                users.append(u)
33
+                    sys.stderr.write(random_msg % (p, u))
34
+                    cloud.distro.set_passwd(u, p)
35
+            else:
36
+                cloud.distro.set_passwd(u, p)
37
 
38
-        ch_in = '\n'.join(plist_in) + '\n'
39
-        if users:
40
-            try:
41
-                log.debug("Changing password for %s:", users)
42
-                util.subp(['chpasswd'], ch_in)
43
-            except Exception as e:
44
-                errors.append(e)
45
-                util.logexc(
46
-                    log, "Failed to set passwords with chpasswd for %s", users)
47
+            if expire:
48
+                cloud.distro.force_passwd_change(u)
49
 
50
-        hashed_ch_in = '\n'.join(hashed_plist_in) + '\n'
51
-        if hashed_users:
52
-            try:
53
-                log.debug("Setting hashed password for %s:", hashed_users)
54
-                util.subp(['chpasswd', '-e'], hashed_ch_in)
55
-            except Exception as e:
56
-                errors.append(e)
57
-                util.logexc(
58
-                    log, "Failed to set hashed passwords with chpasswd for %s",
59
-                    hashed_users)
60
-
61
-        if len(randlist):
62
-            blurb = ("Set the following 'random' passwords\n",
63
-                     '\n'.join(randlist))
64
-            sys.stderr.write("%s\n%s\n" % blurb)
65
-
66
-        if expire:
67
-            expired_users = []
68
-            for u in users:
69
-                try:
70
-                    util.subp(['passwd', '--expire', u])
71
-                    expired_users.append(u)
72
-                except Exception as e:
73
-                    errors.append(e)
74
-                    util.logexc(log, "Failed to set 'expire' for %s", u)
75
-            if expired_users:
76
-                log.debug("Expired passwords for: %s users", expired_users)
77
-
78
     handle_ssh_pwauth(
79
         cfg.get('ssh_pwauth'), service_cmd=cloud.distro.init_cmd,
80
         service_name=cloud.distro.get_option('ssh_svcname', 'ssh'))
81
-
82
-    if len(errors):
83
-        log.debug("%s errors occured, re-raising the last one", len(errors))
84
-        raise errors[-1]
85
 
86
 
87
 def rand_user_password(pwlen=9):
(-)files/patch-cloudinit_config_tests_test__set__passwords.py (+25 lines)
Line 0 Link Here
1
--- cloudinit/config/tests/test_set_passwords.py.orig	2019-07-17 16:30:07 UTC
2
+++ cloudinit/config/tests/test_set_passwords.py
3
@@ -101,11 +101,18 @@ class TestSetPasswordsHandle(CiTestCase):
4
             'DEBUG: Handling input for chpasswd as list.',
5
             self.logs.getvalue())
6
         self.assertIn(
7
-            "DEBUG: Setting hashed password for ['root', 'ubuntu']",
8
+            "DEBUG: Setting password for: root",
9
             self.logs.getvalue())
10
-        self.assertEqual(
11
-            [mock.call(['chpasswd', '-e'],
12
-             '\n'.join(valid_hashed_pwds) + '\n')],
13
+        self.assertIn(
14
+            "DEBUG: Setting password for: ubuntu",
15
+            self.logs.getvalue())
16
+        self.assertEqual([
17
+            mock.call(['chpasswd', '-e'], valid_hashed_pwds[0],
18
+                      logstring='chpasswd for root'),
19
+            mock.call(['passwd', '--expire', 'root']),
20
+            mock.call(['chpasswd', '-e'], valid_hashed_pwds[1],
21
+                      logstring='chpasswd for ubuntu'),
22
+            mock.call(['passwd', '--expire', 'ubuntu'])],
23
             m_subp.call_args_list)
24
 
25
 # vi: ts=4 expandtab
(-)files/patch-cloudinit_distros_____init____.py (+30 lines)
Line 0 Link Here
1
--- cloudinit/distros/__init__.py.orig	2019-09-05 10:12:03 UTC
2
+++ cloudinit/distros/__init__.py
3
@@ -591,7 +591,7 @@ class Distro(object):
4
             util.logexc(LOG, 'Failed to disable password for user %s', name)
5
             raise e
6
 
7
-    def set_passwd(self, user, passwd, hashed=False):
8
+    def set_passwd(self, user, passwd, hashed=False, force_change=False):
9
         pass_string = '%s:%s' % (user, passwd)
10
         cmd = ['chpasswd']
11
 
12
@@ -606,8 +606,17 @@ class Distro(object):
13
         except Exception as e:
14
             util.logexc(LOG, "Failed to set password for %s", user)
15
             raise e
16
-
17
         return True
18
+
19
+    def force_passwd_change(self, user):
20
+        """
21
+        The users will have to enter a new password the first time they log in
22
+        """
23
+        try:
24
+            util.subp(['passwd', '--expire', user])
25
+        except Exception as e:
26
+            util.logexc(LOG, "Failed to set pw expiration for %s", user)
27
+            raise e
28
 
29
     def ensure_sudo_dir(self, path, sudo_base='/etc/sudoers'):
30
         # Ensure the dir is included and that
(-)files/patch-cloudinit_distros_freebsd.py (+25 lines)
Line 0 Link Here
1
--- cloudinit/distros/freebsd.py.orig	2019-09-05 10:12:03 UTC
2
+++ cloudinit/distros/freebsd.py
3
@@ -136,7 +136,7 @@ class Distro(distros.Distro):
4
         if passwd_val is not None:
5
             self.set_passwd(name, passwd_val, hashed=True)
6
 
7
-    def set_passwd(self, user, passwd, hashed=False):
8
+    def set_passwd(self, user, passwd, hashed=False, force_change=False):
9
         if hashed:
10
             hash_opt = "-H"
11
         else:
12
@@ -147,6 +147,13 @@ class Distro(distros.Distro):
13
                       data=passwd, logstring="chpasswd for %s" % user)
14
         except Exception as e:
15
             util.logexc(LOG, "Failed to set password for %s", user)
16
+            raise e
17
+
18
+    def force_passwd_change(self, user):
19
+        try:
20
+            util.subp(['pw', 'usermod', user, '-p', '01-Jan-1970'])
21
+        except Exception as e:
22
+            util.logexc(LOG, "Failed to set pw expiration for %s", user)
23
             raise e
24
 
25
     def lock_passwd(self, name):
(-)files/patch-cloudinit_net_____init____.py (+30 lines)
Line 0 Link Here
1
--- cloudinit/net/__init__.py.orig	2019-07-17 16:30:07 UTC
2
+++ cloudinit/net/__init__.py
3
@@ -585,6 +585,27 @@ def get_ib_interface_hwaddr(ifname, ethernet_format):
4
 
5
 
6
 def get_interfaces_by_mac():
7
+    if util.is_FreeBSD():
8
+        return get_interfaces_by_mac_on_freebsd()
9
+    else:
10
+        return get_interfaces_by_mac_on_linux()
11
+
12
+
13
+def get_interfaces_by_mac_on_freebsd():
14
+    ret = {}
15
+    (out, _) = util.subp(['ifconfig', '-a'])
16
+    blocks = re.split(r'(^\S+|\n\S+):', out)
17
+    blocks.reverse()
18
+    blocks.pop()  # Ignore the first one
19
+    while blocks:
20
+        ifname = blocks.pop()
21
+        m = re.search(r'ether\s([\da-f:]{17})', blocks.pop())
22
+        if m and m.group(1):
23
+            ret[m.group(1)] = ifname
24
+    return ret
25
+
26
+
27
+def get_interfaces_by_mac_on_linux():
28
     """Build a dictionary of tuples {mac: name}.
29
 
30
     Bridges and any devices that have a 'stolen' mac are excluded."""
(-)files/patch-cloudinit_net_freebsd.py (+127 lines)
Line 0 Link Here
1
--- cloudinit/net/freebsd.py.orig	2019-09-05 10:12:03 UTC
2
+++ cloudinit/net/freebsd.py
3
@@ -0,0 +1,124 @@
4
+# This file is part of cloud-init. See LICENSE file for license information.
5
+
6
+import re
7
+
8
+from cloudinit import log as logging
9
+from cloudinit import net
10
+from cloudinit import util
11
+from cloudinit.distros import rhel_util
12
+from cloudinit.distros.parsers.resolv_conf import ResolvConf
13
+
14
+from . import renderer
15
+
16
+LOG = logging.getLogger(__name__)
17
+
18
+
19
+class Renderer(renderer.Renderer):
20
+    resolv_conf_fn = 'etc/resolv.conf'
21
+    rc_conf_fn = 'etc/rc.conf'
22
+
23
+    def __init__(self, config=None):
24
+        if not config:
25
+            config = {}
26
+        self.dhcp_interfaces = []
27
+        self._postcmds = config.get('postcmds', True)
28
+
29
+    def _render_route(self, route, indent=""):
30
+        pass
31
+
32
+    def _render_iface(self, iface, render_hwaddress=False):
33
+        pass
34
+
35
+    def _write_network(self, settings, target=None):
36
+        nameservers = []
37
+        searchdomains = []
38
+        ifname_by_mac = net.get_interfaces_by_mac()
39
+        for interface in settings.iter_interfaces():
40
+            device_name = interface.get("name")
41
+            device_mac = interface.get("mac_address")
42
+            if device_name:
43
+                if re.match(r'^lo\d+$', device_name):
44
+                    continue
45
+            if device_mac and device_name:
46
+                cur_name = ifname_by_mac[device_mac]
47
+                if not cur_name:
48
+                    LOG.info('Cannot find any device with MAC %s', device_mac)
49
+                    continue
50
+                if cur_name != device_name:
51
+                    rhel_util.update_sysconfig_file(
52
+                        util.target_path(target, self.rc_conf_fn), {
53
+                            'ifconfig_%s_name' % cur_name: device_name})
54
+            elif device_mac:
55
+                device_name = ifname_by_mac[device_mac]
56
+
57
+            subnet = interface.get("subnets", [])[0]
58
+            LOG.info('Configuring interface %s', device_name)
59
+
60
+            if subnet.get('type') == 'static':
61
+                LOG.debug('Configuring dev %s with %s / %s', device_name,
62
+                          subnet.get('address'), subnet.get('netmask'))
63
+                # Configure an ipv4 address.
64
+                ifconfig = (subnet.get('address') + ' netmask ' +
65
+                            subnet.get('netmask'))
66
+
67
+                # Configure the gateway.
68
+                rhel_util.update_sysconfig_file(
69
+                    util.target_path(target, self.rc_conf_fn), {
70
+                        'defaultrouter': subnet.get('gateway')})
71
+
72
+                if 'dns_nameservers' in subnet:
73
+                    nameservers.extend(subnet['dns_nameservers'])
74
+                if 'dns_search' in subnet:
75
+                    searchdomains.extend(subnet['dns_search'])
76
+            else:
77
+                self.dhcp_interfaces.append(device_name)
78
+                ifconfig = 'DHCP'
79
+
80
+            rhel_util.update_sysconfig_file(
81
+                util.target_path(target, self.rc_conf_fn), {
82
+                    'ifconfig_' + device_name: ifconfig})
83
+
84
+        # Try to read the /etc/resolv.conf or just start from scratch if that
85
+        # fails.
86
+        try:
87
+            resolvconf = ResolvConf(util.load_file(self.resolv_conf_fn))
88
+            resolvconf.parse()
89
+        except IOError:
90
+            util.logexc(LOG, "Failed to parse %s, use new empty file",
91
+                        self.resolv_conf_fn)
92
+            resolvconf = ResolvConf('')
93
+            resolvconf.parse()
94
+
95
+        # Add some nameservers
96
+        for server in nameservers:
97
+            try:
98
+                resolvconf.add_nameserver(server)
99
+            except ValueError:
100
+                util.logexc(LOG, "Failed to add nameserver %s", server)
101
+
102
+        # And add any searchdomains.
103
+        for domain in searchdomains:
104
+            try:
105
+                resolvconf.add_search_domain(domain)
106
+            except ValueError:
107
+                util.logexc(LOG, "Failed to add search domain %s", domain)
108
+        util.write_file(self.resolv_conf_fn, str(resolvconf), 0o644)
109
+        self.start_services()
110
+
111
+    def render_network_state(self, network_state, templates=None, target=None):
112
+        self._write_network(network_state, target=target)
113
+
114
+    def start_services(self):
115
+        if not self._postcmds:
116
+            LOG.debug("freebsd generate postcmd disabled")
117
+            return
118
+
119
+        util.subp(['service', 'netif', 'restart'], capture=True)
120
+        util.subp(['service', 'routing', 'restart'], capture=True)
121
+        for dhcp_interface in self.dhcp_interfaces:
122
+            util.subp(['service', 'dhclient', 'restart', dhcp_interface],
123
+                      capture=True)
124
+
125
+
126
+def available(target=None):
127
+    return util.is_FreeBSD()
(-)files/patch-cloudinit_net_renderers.py (+23 lines)
Line 0 Link Here
1
--- cloudinit/net/renderers.py.orig	2019-07-17 16:30:07 UTC
2
+++ cloudinit/net/renderers.py
3
@@ -1,17 +1,19 @@
4
 # This file is part of cloud-init. See LICENSE file for license information.
5
 
6
 from . import eni
7
+from . import freebsd
8
 from . import netplan
9
 from . import RendererNotFoundError
10
 from . import sysconfig
11
 
12
 NAME_TO_RENDERER = {
13
     "eni": eni,
14
+    "freebsd": freebsd,
15
     "netplan": netplan,
16
     "sysconfig": sysconfig,
17
 }
18
 
19
-DEFAULT_PRIORITY = ["eni", "sysconfig", "netplan"]
20
+DEFAULT_PRIORITY = ["eni", "sysconfig", "netplan", "freebsd"]
21
 
22
 
23
 def search(priority=None, target=None, first=False):
(-)files/patch-doc_rtd_topics_network-config.rst (+11 lines)
Line 0 Link Here
1
--- doc/rtd/topics/network-config.rst.orig	2019-07-17 16:30:07 UTC
2
+++ doc/rtd/topics/network-config.rst
3
@@ -191,7 +191,7 @@ supplying an updated configuration in cloud-config. ::
4
 
5
   system_info:
6
     network:
7
-      renderers: ['netplan', 'eni', 'sysconfig']
8
+      renderers: ['netplan', 'eni', 'sysconfig', 'freebsd']
9
 
10
 
11
 Network Configuration Tools
(-)files/patch-tests_unittests_test__distros_test__netconfig.py (+222 lines)
Line 0 Link Here
1
--- tests/unittests/test_distros/test_netconfig.py.orig	2019-07-17 16:30:07 UTC
2
+++ tests/unittests/test_distros/test_netconfig.py
3
@@ -1,5 +1,6 @@
4
 # This file is part of cloud-init. See LICENSE file for license information.
5
 
6
+import copy
7
 import os
8
 from six import StringIO
9
 from textwrap import dedent
10
@@ -14,7 +15,7 @@ from cloudinit.distros.parsers.sys_conf import SysConf
11
 from cloudinit import helpers
12
 from cloudinit import settings
13
 from cloudinit.tests.helpers import (
14
-    FilesystemMockingTestCase, dir2dict, populate_dir)
15
+    FilesystemMockingTestCase, dir2dict)
16
 from cloudinit import util
17
 
18
 
19
@@ -213,128 +214,95 @@ class TestNetCfgDistroBase(FilesystemMockingTestCase):
20
             self.assertEqual(v, b2[k])
21
 
22
 
23
-class TestNetCfgDistroFreebsd(TestNetCfgDistroBase):
24
+class TestNetCfgDistroFreeBSD(TestNetCfgDistroBase):
25
 
26
-    frbsd_ifout = """\
27
-hn0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
28
-        options=51b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,TSO4,LRO>
29
-        ether 00:15:5d:4c:73:00
30
-        inet6 fe80::215:5dff:fe4c:7300%hn0 prefixlen 64 scopeid 0x2
31
-        inet 10.156.76.127 netmask 0xfffffc00 broadcast 10.156.79.255
32
-        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
33
-        media: Ethernet autoselect (10Gbase-T <full-duplex>)
34
-        status: active
35
-"""
36
+    def setUp(self):
37
+        super(TestNetCfgDistroFreeBSD, self).setUp()
38
+        self.distro = self._get_distro('freebsd', renderers=['freebsd'])
39
 
40
-    @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_list')
41
-    @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ifname_out')
42
-    def test_get_ip_nic_freebsd(self, ifname_out, iflist):
43
-        frbsd_distro = self._get_distro('freebsd')
44
-        iflist.return_value = "lo0 hn0"
45
-        ifname_out.return_value = self.frbsd_ifout
46
-        res = frbsd_distro.get_ipv4()
47
-        self.assertEqual(res, ['lo0', 'hn0'])
48
-        res = frbsd_distro.get_ipv6()
49
-        self.assertEqual(res, [])
50
+    def _apply_and_verify_freebsd(self, apply_fn, config, expected_cfgs=None,
51
+                                  bringup=False):
52
+        if not expected_cfgs:
53
+            raise ValueError('expected_cfg must not be None')
54
 
55
-    @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ether')
56
-    @mock.patch('cloudinit.distros.freebsd.Distro.get_ifconfig_ifname_out')
57
-    @mock.patch('cloudinit.distros.freebsd.Distro.get_interface_mac')
58
-    def test_generate_fallback_config_freebsd(self, mac, ifname_out, if_ether):
59
-        frbsd_distro = self._get_distro('freebsd')
60
+        tmpd = None
61
+        with mock.patch('cloudinit.net.freebsd.available') as m_avail:
62
+            m_avail.return_value = True
63
+            with self.reRooted(tmpd) as tmpd:
64
+                util.ensure_dir('/etc')
65
+                util.ensure_file('/etc/rc.conf')
66
+                util.ensure_file('/etc/resolv.conf')
67
+                apply_fn(config, bringup)
68
 
69
-        if_ether.return_value = 'hn0'
70
-        ifname_out.return_value = self.frbsd_ifout
71
-        mac.return_value = '00:15:5d:4c:73:00'
72
-        res = frbsd_distro.generate_fallback_config()
73
-        self.assertIsNotNone(res)
74
+        results = dir2dict(tmpd)
75
+        for cfgpath, expected in expected_cfgs.items():
76
+            print("----------")
77
+            print(expected)
78
+            print("^^^^ expected | rendered VVVVVVV")
79
+            print(results[cfgpath])
80
+            print("----------")
81
+            self.assertEqual(
82
+                set(expected.split('\n')),
83
+                set(results[cfgpath].split('\n')))
84
+            self.assertEqual(0o644, get_mode(cfgpath, tmpd))
85
 
86
-    def test_simple_write_freebsd(self):
87
-        fbsd_distro = self._get_distro('freebsd')
88
+    @mock.patch('cloudinit.net.get_interfaces_by_mac')
89
+    def test_apply_network_config_freebsd_standard(self, ifaces_mac):
90
+        ifaces_mac.return_value = {
91
+            '00:15:5d:4c:73:00': 'eth0',
92
+        }
93
+        rc_conf_expected = """\
94
+defaultrouter=192.168.1.254
95
+ifconfig_eth0='192.168.1.5 netmask 255.255.255.0'
96
+ifconfig_eth1=DHCP
97
+"""
98
 
99
-        rc_conf = '/etc/rc.conf'
100
-        read_bufs = {
101
-            rc_conf: 'initial-rc-conf-not-validated',
102
-            '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
103
+        expected_cfgs = {
104
+            '/etc/rc.conf': rc_conf_expected,
105
+            '/etc/resolv.conf': ''
106
         }
107
+        self._apply_and_verify_freebsd(self.distro.apply_network_config,
108
+                                       V1_NET_CFG,
109
+                                       expected_cfgs=expected_cfgs.copy())
110
 
111
-        tmpd = self.tmp_dir()
112
-        populate_dir(tmpd, read_bufs)
113
-        with self.reRooted(tmpd):
114
-            with mock.patch("cloudinit.distros.freebsd.util.subp",
115
-                            return_value=('vtnet0', '')):
116
-                fbsd_distro.apply_network(BASE_NET_CFG, False)
117
-                results = dir2dict(tmpd)
118
+    @mock.patch('cloudinit.net.get_interfaces_by_mac')
119
+    def test_apply_network_config_freebsd_ifrename(self, ifaces_mac):
120
+        ifaces_mac.return_value = {
121
+            '00:15:5d:4c:73:00': 'vtnet0',
122
+        }
123
+        rc_conf_expected = """\
124
+ifconfig_vtnet0_name=eth0
125
+defaultrouter=192.168.1.254
126
+ifconfig_eth0='192.168.1.5 netmask 255.255.255.0'
127
+ifconfig_eth1=DHCP
128
+"""
129
 
130
-        self.assertIn(rc_conf, results)
131
-        self.assertCfgEquals(
132
-            dedent('''\
133
-                ifconfig_vtnet0="192.168.1.5 netmask 255.255.255.0"
134
-                ifconfig_vtnet1="DHCP"
135
-                defaultrouter="192.168.1.254"
136
-                '''), results[rc_conf])
137
-        self.assertEqual(0o644, get_mode(rc_conf, tmpd))
138
+        V1_NET_CFG_RENAME = copy.deepcopy(V1_NET_CFG)
139
+        V1_NET_CFG_RENAME['config'][0]['mac_address'] = '00:15:5d:4c:73:00'
140
 
141
-    def test_simple_write_freebsd_from_v2eni(self):
142
-        fbsd_distro = self._get_distro('freebsd')
143
-
144
-        rc_conf = '/etc/rc.conf'
145
-        read_bufs = {
146
-            rc_conf: 'initial-rc-conf-not-validated',
147
-            '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
148
+        expected_cfgs = {
149
+            '/etc/rc.conf': rc_conf_expected,
150
+            '/etc/resolv.conf': ''
151
         }
152
+        self._apply_and_verify_freebsd(self.distro.apply_network_config,
153
+                                       V1_NET_CFG_RENAME,
154
+                                       expected_cfgs=expected_cfgs.copy())
155
 
156
-        tmpd = self.tmp_dir()
157
-        populate_dir(tmpd, read_bufs)
158
-        with self.reRooted(tmpd):
159
-            with mock.patch("cloudinit.distros.freebsd.util.subp",
160
-                            return_value=('vtnet0', '')):
161
-                fbsd_distro.apply_network(BASE_NET_CFG_FROM_V2, False)
162
-                results = dir2dict(tmpd)
163
-
164
-        self.assertIn(rc_conf, results)
165
-        self.assertCfgEquals(
166
-            dedent('''\
167
-                ifconfig_vtnet0="192.168.1.5 netmask 255.255.255.0"
168
-                ifconfig_vtnet1="DHCP"
169
-                defaultrouter="192.168.1.254"
170
-                '''), results[rc_conf])
171
-        self.assertEqual(0o644, get_mode(rc_conf, tmpd))
172
-
173
-    def test_apply_network_config_fallback_freebsd(self):
174
-        fbsd_distro = self._get_distro('freebsd')
175
-
176
-        # a weak attempt to verify that we don't have an implementation
177
-        # of _write_network_config or apply_network_config in fbsd now,
178
-        # which would make this test not actually test the fallback.
179
-        self.assertRaises(
180
-            NotImplementedError, fbsd_distro._write_network_config,
181
-            BASE_NET_CFG)
182
-
183
-        # now run
184
-        mynetcfg = {
185
-            'config': [{"type": "physical", "name": "eth0",
186
-                        "mac_address": "c0:d6:9f:2c:e8:80",
187
-                        "subnets": [{"type": "dhcp"}]}],
188
-            'version': 1}
189
-
190
-        rc_conf = '/etc/rc.conf'
191
-        read_bufs = {
192
-            rc_conf: 'initial-rc-conf-not-validated',
193
-            '/etc/resolv.conf': 'initial-resolv-conf-not-validated',
194
+    @mock.patch('cloudinit.net.get_interfaces_by_mac')
195
+    def test_apply_network_config_freebsd_nameserver(self, ifaces_mac):
196
+        ifaces_mac.return_value = {
197
+            '00:15:5d:4c:73:00': 'eth0',
198
         }
199
 
200
-        tmpd = self.tmp_dir()
201
-        populate_dir(tmpd, read_bufs)
202
-        with self.reRooted(tmpd):
203
-            with mock.patch("cloudinit.distros.freebsd.util.subp",
204
-                            return_value=('vtnet0', '')):
205
-                fbsd_distro.apply_network_config(mynetcfg, bring_up=False)
206
-                results = dir2dict(tmpd)
207
-
208
-        self.assertIn(rc_conf, results)
209
-        self.assertCfgEquals('ifconfig_vtnet0="DHCP"', results[rc_conf])
210
-        self.assertEqual(0o644, get_mode(rc_conf, tmpd))
211
+        V1_NET_CFG_DNS = copy.deepcopy(V1_NET_CFG)
212
+        ns = ['1.2.3.4']
213
+        V1_NET_CFG_DNS['config'][0]['subnets'][0]['dns_nameservers'] = ns
214
+        expected_cfgs = {
215
+            '/etc/resolv.conf': 'nameserver 1.2.3.4\n'
216
+        }
217
+        self._apply_and_verify_freebsd(self.distro.apply_network_config,
218
+                                       V1_NET_CFG_DNS,
219
+                                       expected_cfgs=expected_cfgs.copy())
220
 
221
 
222
 class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
(-)files/patch-tools_build-on-freebsd (+10 lines)
Line 0 Link Here
1
--- tools/build-on-freebsd.orig	2019-07-17 16:30:07 UTC
2
+++ tools/build-on-freebsd
3
@@ -18,7 +18,6 @@ py_prefix=$(${PYTHON} -c 'import sys; print("py%d%d" %
4
 depschecked=/tmp/c-i.dependencieschecked
5
 pkgs="
6
     bash
7
-    chpasswd
8
     dmidecode
9
     e2fsprogs
10
     $py_prefix-Jinja2

Return to bug 240372