← Back to team overview

cloud-init-dev team mailing list archive

[Merge] lp:~harmw/cloud-init/freebsd-static-networking into lp:cloud-init

 

Harm Weites has proposed merging lp:~harmw/cloud-init/freebsd-static-networking into lp:cloud-init.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~harmw/cloud-init/freebsd-static-networking/+merge/208973

This branch introduces support for static networking in freebsd. I had to change some minor stuff along the way that made this easier, and was needed anyway. These individual changes can be viewed in the revisionlog.
-- 
https://code.launchpad.net/~harmw/cloud-init/freebsd-static-networking/+merge/208973
Your team cloud init development team is requested to review the proposed merge of lp:~harmw/cloud-init/freebsd-static-networking into lp:cloud-init.
=== modified file 'cloudinit/distros/freebsd.py'
--- cloudinit/distros/freebsd.py	2014-02-28 21:40:08 +0000
+++ cloudinit/distros/freebsd.py	2014-03-02 19:45:08 +0000
@@ -26,6 +26,9 @@
 from cloudinit import ssh_util
 from cloudinit import util
 
+from cloudinit.distros import net_util
+from cloudinit.distros.parsers.resolv_conf import ResolvConf
+
 LOG = logging.getLogger(__name__)
 
 
@@ -33,6 +36,7 @@
     rc_conf_fn = "/etc/rc.conf"
     login_conf_fn = '/etc/login.conf'
     login_conf_fn_bak = '/etc/login.conf.orig'
+    resolv_conf_fn = '/etc/resolv.conf'
 
     def __init__(self, name, cfg, paths):
         distros.Distro.__init__(self, name, cfg, paths)
@@ -44,30 +48,34 @@
 
     # Updates a key in /etc/rc.conf.
     def updatercconf(self, key, value):
-        LOG.debug("updatercconf: %s => %s", key, value)
+        LOG.debug("Checking %s for: %s = %s", self.rc_conf_fn, key, value)
         conf = self.loadrcconf()
         config_changed = False
         for item in conf:
             if item == key and conf[item] != value:
                 conf[item] = value
-                LOG.debug("[rc.conf]: Value %s for key %s needs to be changed",
-                          value, key)
+                LOG.debug("Changing key in %s: %s = %s", self.rc_conf_fn, key,
+                            value)
                 config_changed = True
 
         if config_changed:
-            LOG.debug("Writing new %s file", self.rc_conf_fn)
+            LOG.info("Writing %s", self.rc_conf_fn)
             buf = StringIO()
             for keyval in conf.items():
-                buf.write("%s=%s\n" % keyval)
+                buf.write('%s="%s"\n' % keyval)
             util.write_file(self.rc_conf_fn, buf.getvalue())
 
-    # Load the contents of /etc/rc.conf and store all keys in a dict.
+    # Load the contents of /etc/rc.conf and store all keys in a dict. Make sure
+    # quotes are ignored:
+    #  hostname="bla"
     def loadrcconf(self):
         conf = {}
         lines = util.load_file(self.rc_conf_fn).splitlines()
         for line in lines:
             tok = line.split('=')
-            conf[tok[0]] = tok[1].rstrip()
+            key = tok[0]
+            val = re.sub(r'^"|"$', '', tok[1].rstrip())
+            conf[key] = val
         return conf
 
     def readrcconf(self, key):
@@ -218,7 +226,66 @@
             ssh_util.setup_user_keys(keys, name, options=None)
 
     def _write_network(self, settings):
-        return
+        entries = net_util.translate_network(settings)
+        LOG.debug("Translated network settings")
+        LOG.debug("\n========== UBUNTU FORMAT START ==========")
+        LOG.debug("%s\n========== UBUNTU FORMAT END ==========", settings)
+        LOG.debug("\n========== GENERIC FORMAT START ==========")
+        LOG.debug("%s\n========== GENERIC FORMAT END ==========", entries)
+
+        nameservers = []
+        searchdomains = []
+        dev_names = entries.keys()
+        for (dev, info) in entries.iteritems():
+            # Skip the loopback interface.
+            if dev == 'lo0':
+                continue
+
+            LOG.info('Configuring interface %s', dev)
+
+            if info.get('bootproto') == 'static':
+                LOG.debug('Configuring dev %s with %s / %s', dev, info.get('address'), info.get('netmask'))
+                # Configure an ipv4 address.
+                ifconfig = info.get('address') + ' netmask ' + info.get('netmask')
+
+                # Configure the gateway.
+                self.updatercconf('defaultrouter', info.get('gateway'))
+
+                if 'dns-nameservers' in info:
+                    nameservers.extend(info['dns-nameservers'])
+                if 'dns-search' in info:
+                    searchservers.extend(info['dns-search'])
+            else:
+                ifconfig = 'DHCP'
+     
+            self.updatercconf('ifconfig_' + dev, ifconfig)
+
+        # Try to read the /etc/resolv.conf or just start from scratch if that
+        # fails.
+        try:
+            resolvconf = ResolvConf(util.load_file(self.resolv_conf_fn))
+            resolvconf.parse()
+        except IOError:
+            util.logexc(LOG, "Failed to parse %s, use new empty file", self.resolv_conf_fn)
+            resolvconf = ResolvConf('')
+            resolvconf.parse()
+
+        # Add some nameservers
+        for server in nameservers:
+            try:
+                resolvconf.add_nameserver(server)
+            except ValueError:
+                util.logexc(LOG, "Failed to add nameserver %s", server)
+
+        # And add any searchdomains.
+        for domain in searchdomains:
+            try:
+                resolvconf.add_search_domain(domain)
+            except ValueError:
+                util.logexc(LOG, "Failed to add search domain %s", domain)
+        util.write_file(self.resolv_conf_fn, str(resolvconf), 0644)
+
+        return dev_names
 
     def apply_locale(self, locale, out_fn=None):
         # Adjust the locals value to the new value

=== modified file 'tests/unittests/test_distros/test_netconfig.py'
--- tests/unittests/test_distros/test_netconfig.py	2012-10-11 19:49:45 +0000
+++ tests/unittests/test_distros/test_netconfig.py	2014-03-02 19:45:08 +0000
@@ -173,3 +173,39 @@
 '''
         self.assertCfgEquals(expected_buf, str(write_buf))
         self.assertEquals(write_buf.mode, 0644)
+
+    def test_simple_write_freebsd(self):
+        fbsd_distro = self._get_distro('freebsd')
+        util_mock = self.mocker.replace(util.write_file,
+                                        spec=False, passthrough=False)
+        exists_mock = self.mocker.replace(os.path.isfile,
+                                          spec=False, passthrough=False)
+
+        exists_mock(mocker.ARGS)
+        self.mocker.count(0, None)
+        self.mocker.result(False)
+
+        write_bufs = {}
+
+        def replace_write(filename, content, mode=0644, omode="wb"):
+            buf = WriteBuffer()
+            buf.mode = mode
+            buf.omode = omode
+            buf.write(content)
+            write_bufs[filename] = buf
+
+        util_mock(mocker.ARGS)
+        self.mocker.call(replace_write)
+        self.mocker.replay()
+        fbsd_distro.apply_network(BASE_NET_CFG, False)
+
+        self.assertIn('/etc/rc.conf', write_bufs)
+        write_buf = write_bufs['/etc/rc.conf']
+        expected_buf = '''
+ifconfig_eth0="192.168.1.5 netmask 255.255.255.0"
+ifconfig_eth1="DHCP"
+defaultrouter="192.168.1.254"
+'''
+        self.assertCfgEquals(expected_buf, str(write_buf))
+        self.assertEquals(write_buf.mode, 0644)
+


Follow ups