← Back to team overview

cloud-init-dev team mailing list archive

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

 


Diff comments:

> === modified file 'cloudinit/config/cc_resizefs.py'
> --- cloudinit/config/cc_resizefs.py	2014-08-26 19:53:41 +0000
> +++ cloudinit/config/cc_resizefs.py	2014-08-28 17:55:48 +0000
> @@ -40,8 +40,13 @@
>      return ('xfs_growfs', devpth)
>  
>  
> +<<<<<<< TREE
>  def _resize_ufs(mount_point, devpth):
>      return ('growfs', devpth)
> +=======
> +def _resize_ufs(mount_point, devpth):  # pylint: disable=W0613
> +    return ('growfs', '-y', devpth)
> +>>>>>>> MERGE-SOURCE
>  
>  # Do not use a dictionary as these commands should be able to be used
>  # for multiple filesystem types if possible, e.g. one command for
> 
> === modified file 'cloudinit/distros/freebsd.py'
> --- cloudinit/distros/freebsd.py	2014-02-28 21:40:08 +0000
> +++ cloudinit/distros/freebsd.py	2014-08-28 17:55:48 +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,53 @@
>  
>      # 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)
> -                config_changed = True
> +        if key not in conf:
> +            LOG.debug("Adding key in %s: %s = %s", self.rc_conf_fn, key,
> +                      value)
> +            conf[key] = value
> +            config_changed = True
> +        else:
> +            for item in conf.keys():
> +                if item == key and conf[item] != value:
> +                    conf[item] = value
> +                    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):
> +        RE_MATCH = re.compile(r'^(\w+)\s*=\s*(.*)\s*')
>          conf = {}
>          lines = util.load_file(self.rc_conf_fn).splitlines()
>          for line in lines:
> -            tok = line.split('=')
> -            conf[tok[0]] = tok[1].rstrip()
> +            m = RE_MATCH.match(line)
> +            if not m:
> +                LOG.debug("Skipping line from /etc/rc.conf: %s", line)
> +                continue
> +            key = m.group(1).rstrip()
> +            val = m.group(2).rstrip()
> +            # Kill them quotes (not completely correct, aka won't handle
> +            # quoted values, but should be ok ...)
> +            if val[0] in ('"', "'"):
> +                val = val[1:]
> +            if val[-1] in ('"', "'"):
> +                val = val[0:-1]
> +            if len(val) == 0:
> +                LOG.debug("Skipping empty value from /etc/rc.conf: %s", line)
> +                continue
> +            conf[key] = val
>          return conf
>  
>      def readrcconf(self, key):
> @@ -218,7 +245,60 @@
>              ssh_util.setup_user_keys(keys, name, options=None)
>  
>      def _write_network(self, settings):
> -        return
> +        entries = net_util.translate_network(settings)
> +        nameservers = []
> +        searchdomains = []
> +        dev_names = entries.keys()
> +        for (dev, info) in entries.iteritems():
> +            # Skip the loopback interface.
> +            if dev.startswith('lo'):
> +                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
> 
> === added file 'config/cloud.cfg-freebsd'
> --- config/cloud.cfg-freebsd	1970-01-01 00:00:00 +0000
> +++ config/cloud.cfg-freebsd	2014-08-28 17:55:48 +0000
> @@ -0,0 +1,88 @@
> +# The top level settings are used as module
> +# and system configuration.
> +
> +syslog_fix_perms: root:wheel
> +
> +# This should not be required, but leave it in place until the real cause of
> +# not beeing able to find -any- datasources is resolved.
> +datasource_list: ['OpenStack']
> +
> +# A set of users which may be applied and/or used by various modules
> +# when a 'default' entry is found it will reference the 'default_user'
> +# from the distro configuration specified below
> +users:
> +   - default
> +
> +# If this is set, 'root' will not be able to ssh in and they 
> +# will get a message to login instead as the above $user (ubuntu)
> +disable_root: false
> +
> +# This will cause the set+update hostname module to not operate (if true)
> +preserve_hostname: false
> +
> +# Example datasource config
> +# datasource: 
> +#    Ec2: 
> +#      metadata_urls: [ 'blah.com' ]
> +#      timeout: 5 # (defaults to 50 seconds)
> +#      max_wait: 10 # (defaults to 120 seconds)
> +
> +# The modules that run in the 'init' stage
> +cloud_init_modules:
> +# - migrator

Should we just delete these instead of commenting them out?

> + - seed_random
> + - bootcmd
> +# - write-files
> + - growpart
> + - resizefs
> + - set_hostname
> + - update_hostname
> +# - update_etc_hosts
> +# - ca-certs
> +# - rsyslog
> + - users-groups
> + - ssh
> +
> +# The modules that run in the 'config' stage
> +cloud_config_modules:
> +# - disk_setup
> +# - mounts
> + - ssh-import-id
> + - locale
> +# - set-passwords
> +# - package-update-upgrade-install
> +# - landscape
> +# - timezone
> +# - puppet
> +# - chef
> +# - salt-minion
> +# - mcollective
> + - disable-ec2-metadata
> + - runcmd
> +# - byobu
> +
> +# The modules that run in the 'final' stage
> +cloud_final_modules:
> + - rightscale_userdata
> + - scripts-vendor
> + - scripts-per-once
> + - scripts-per-boot
> + - scripts-per-instance
> + - scripts-user
> + - ssh-authkey-fingerprints
> + - keys-to-console
> + - phone-home
> + - final-message
> + - power-state-change
> +
> +# System and/or distro specific settings
> +# (not accessible to handlers/transforms)
> +system_info:
> +   distro: freebsd
> +   default_user:
> +     name: beastie
> +     lock_passwd: True
> +     gecos: FreeBSD
> +     groups: [wheel]
> +     sudo: ["ALL=(ALL) NOPASSWD:ALL"]
> +     shell: /bin/sh
> 
> === modified file 'setup.py'
> --- setup.py	2014-08-26 19:53:41 +0000
> +++ setup.py	2014-08-28 17:55:48 +0000
> @@ -63,18 +63,28 @@
>  
>  INITSYS_FILES = {
>      'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
> +    'sysvinit_freebsd': [f for f in glob('sysvinit/freebsd/*') if is_f(f)],
>      'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)],
>      'systemd': [f for f in glob('systemd/*') if is_f(f)],
>      'upstart': [f for f in glob('upstart/*') if is_f(f)],
>  }
>  INITSYS_ROOTS = {
>      'sysvinit': '/etc/rc.d/init.d',
> +    'sysvinit_freebsd': '/usr/local/etc/rc.d',
>      'sysvinit_deb': '/etc/init.d',
>      'systemd': systemd_unitdir(),
>      'upstart': '/etc/init/',
>  }
>  INITSYS_TYPES = sorted(list(INITSYS_ROOTS.keys()))
>  
> +# Install everything in the right location and take care of Linux (default) and
> +# FreeBSD systems.
> +USR = "/usr"
> +ETC = "/etc"
> +if os.uname()[0] == 'FreeBSD':
> +    USR = "/usr/local"
> +    ETC = "/usr/local/etc"
> +
>  
>  def get_version():
>      cmd = ['tools/read-version']
> @@ -136,18 +146,17 @@
>                 'tools/cloud-init-per',
>                 ],
>        license='GPLv3',
> -      data_files=[('/etc/cloud', glob('config/*.cfg')),
> -                  ('/etc/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
> -                  ('/etc/cloud/templates', glob('templates/*')),
> -                  ('/usr/share/cloud-init', []),
> -                  ('/usr/lib/cloud-init',
> +      data_files=[(ETC + '/cloud', glob('config/*.cfg')),
> +                  (ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
> +                  (ETC + '/cloud/templates', glob('templates/*')),
> +                  (USR + '/lib/cloud-init',
>                      ['tools/uncloud-init',
>                       'tools/write-ssh-key-fingerprints']),
> -                  ('/usr/share/doc/cloud-init',
> +                  (USR + '/share/doc/cloud-init',
>                     [f for f in glob('doc/*') if is_f(f)]),
> -                  ('/usr/share/doc/cloud-init/examples',
> +                  (USR + '/share/doc/cloud-init/examples',
>                     [f for f in glob('doc/examples/*') if is_f(f)]),
> -                  ('/usr/share/doc/cloud-init/examples/seed',
> +                  (USR + '/share/doc/cloud-init/examples/seed',
>                     [f for f in glob('doc/examples/seed/*') if is_f(f)]),
>                   ],
>        install_requires=read_requires(),
> 
> === modified file 'sysvinit/freebsd/cloudconfig'
> --- sysvinit/freebsd/cloudconfig	2014-01-18 00:45:23 +0000
> +++ sysvinit/freebsd/cloudconfig	2014-08-28 17:55:48 +0000
> @@ -6,28 +6,28 @@
>  
>  . /etc/rc.subr
>  
> +export CLOUD_CFG=/usr/local/etc/cloud/cloud.cfg
> +
>  name="cloudconfig"
> -command="/usr/bin/cloud-init"
> +command="/usr/local/bin/cloud-init"
>  start_cmd="cloudconfig_start"
>  stop_cmd=":"
>  rcvar="cloudinit_enable"
>  start_precmd="cloudinit_override"
>  start_cmd="cloudconfig_start"
>  
> -: ${cloudinit_config:="/etc/cloud/cloud.cfg"}
> -
>  cloudinit_override()
>  {
> -	# If there exist sysconfig/default variable override files use it...
> -	if [ -f /etc/default/cloud-init ]; then
> -		. /etc/default/cloud-init
> +	# If there exist sysconfig/defaults variable override files use it...
> +	if [ -f /etc/defaults/cloud-init ]; then
> +		. /etc/defaults/cloud-init
>  	fi
>  }
>  
>  cloudconfig_start()
>  {
>  	echo "${command} starting"
> -	${command} ${cloudinit_config} modules --mode config
> +	${command} modules --mode config
>  }
>  
>  load_rc_config $name
> 
> === modified file 'sysvinit/freebsd/cloudfinal'
> --- sysvinit/freebsd/cloudfinal	2014-01-18 00:45:23 +0000
> +++ sysvinit/freebsd/cloudfinal	2014-08-28 17:55:48 +0000
> @@ -6,28 +6,28 @@
>  
>  . /etc/rc.subr
>  
> +export CLOUD_CFG=/usr/local/etc/cloud/cloud.cfg
> +
>  name="cloudfinal"
> -command="/usr/bin/cloud_init"
> +command="/usr/local/bin/cloud-init"
>  start_cmd="cloudfinal_start"
>  stop_cmd=":"
>  rcvar="cloudinit_enable"
>  start_precmd="cloudinit_override"
>  start_cmd="cloudfinal_start"
>  
> -: ${cloudinit_config:="/etc/cloud/cloud.cfg"}
> -
>  cloudinit_override()
>  {
> -	# If there exist sysconfig/default variable override files use it...
> -	if [ -f /etc/default/cloud-init ]; then
> -		 . /etc/default/cloud-init
> +	# If there exist sysconfig/defaults variable override files use it...
> +	if [ -f /etc/defaults/cloud-init ]; then
> +		 . /etc/defaults/cloud-init
>  	fi
>  }
>  
>  cloudfinal_start()
>  {
>  	echo -n "${command} starting"
> -	${command} ${cloudinit_config} modules --mode final
> +	${command} modules --mode final
>  }
>  
>  load_rc_config $name
> 
> === modified file 'sysvinit/freebsd/cloudinit'
> --- sysvinit/freebsd/cloudinit	2014-01-18 00:45:23 +0000
> +++ sysvinit/freebsd/cloudinit	2014-08-28 17:55:48 +0000
> @@ -6,28 +6,28 @@
>  
>  . /etc/rc.subr
>  
> +export CLOUD_CFG=/usr/local/etc/cloud/cloud.cfg
> +
>  name="cloudinit"
> -command="/usr/bin/cloud_init"
> +command="/usr/local/bin/cloud-init"
>  start_cmd="cloudinit_start"
>  stop_cmd=":"
>  rcvar="cloudinit_enable"
>  start_precmd="cloudinit_override"
>  start_cmd="cloudinit_start"
>  
> -: ${cloudinit_config:="/etc/cloud/cloud.cfg"}
> -
>  cloudinit_override()
>  {
> -	# If there exist sysconfig/default variable override files use it...
> -	if [ -f /etc/default/cloud-init ]; then
> -		. /etc/default/cloud-init
> +	# If there exist sysconfig/defaults variable override files use it...
> +	if [ -f /etc/defaults/cloud-init ]; then
> +		. /etc/defaults/cloud-init
>  	fi
>  }
>  
>  cloudinit_start()
>  {
>  	echo -n "${command} starting"
> -	${command} ${cloudinit_config} init
> +	${command} init
>  }
>  
>  load_rc_config $name
> 
> === modified file 'sysvinit/freebsd/cloudinitlocal'
> --- sysvinit/freebsd/cloudinitlocal	2014-01-18 00:45:23 +0000
> +++ sysvinit/freebsd/cloudinitlocal	2014-08-28 17:55:48 +0000
> @@ -6,28 +6,28 @@
>  
>  . /etc/rc.subr
>  
> +export CLOUD_CFG=/usr/local/etc/cloud/cloud.cfg
> +
>  name="cloudinitlocal"
> -command="/usr/bin/cloud-init"
> +command="/usr/local/bin/cloud-init"
>  start_cmd="cloudlocal_start"
>  stop_cmd=":"
>  rcvar="cloudinit_enable"
>  start_precmd="cloudinit_override"
>  start_cmd="cloudlocal_start"
>  
> -: ${cloudinit_config:="/etc/cloud/cloud.cfg"}
> -
>  cloudinit_override()
>  {
> -	# If there exist sysconfig/default variable override files use it...
> -	if [ -f /etc/default/cloud-init ]; then
> -		. /etc/default/cloud-init
> +	# If there exist sysconfig/defaults variable override files use it...
> +	if [ -f /etc/defaults/cloud-init ]; then
> +		. /etc/defaults/cloud-init
>  	fi
>  }
>  
>  cloudlocal_start()
>  {
>  	echo -n "${command} starting"
> -	${command} ${cloudinit_config} init --local
> +	${command} init --local
>  }
>  
>  load_rc_config $name
> 
> === 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-08-28 17:55:48 +0000
> @@ -173,3 +173,60 @@
>  '''
>          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)
> +        load_mock = self.mocker.replace(util.load_file,
> +                                        spec=False, passthrough=False)
> +
> +        exists_mock(mocker.ARGS)
> +        self.mocker.count(0, None)
> +        self.mocker.result(False)
> +
> +        write_bufs = {}
> +        read_bufs = {
> +            '/etc/rc.conf': '',
> +        }
> +
> +        def replace_write(filename, content, mode=0644, omode="wb"):
> +            buf = WriteBuffer()
> +            buf.mode = mode
> +            buf.omode = omode
> +            buf.write(content)
> +            write_bufs[filename] = buf
> +
> +        def replace_read(fname, read_cb=None, quiet=False):
> +            if fname not in read_bufs:
> +                if fname in write_bufs:
> +                    return str(write_bufs[fname])
> +                raise IOError("%s not found" % fname)
> +            else:
> +                if fname in write_bufs:
> +                    return str(write_bufs[fname])
> +                return read_bufs[fname]
> +
> +        util_mock(mocker.ARGS)
> +        self.mocker.call(replace_write)
> +        self.mocker.count(0, None)
> +
> +        load_mock(mocker.ARGS)
> +        self.mocker.call(replace_read)
> +        self.mocker.count(0, None)
> +
> +        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)
> +
> 
> === added file 'tools/build-on-freebsd'
> --- tools/build-on-freebsd	1970-01-01 00:00:00 +0000
> +++ tools/build-on-freebsd	2014-08-28 17:55:48 +0000
> @@ -0,0 +1,57 @@
> +#!/bin/sh
> +# Since there is no official FreeBSD port yet, we need some way of building and
> +# installing cloud-init. This script takes care of building and installing. It
> +# will optionally make a first run at the end.
> +
> +fail() { echo "FAILED:" "$@" 1>&2; exit 1; }
> +
> +# Check dependencies:
> +depschecked=/tmp/c-i.dependencieschecked
> +pkgs="
> +   dmidecode
> +   py27-argparse
> +   py27-boto gpart sudo
> +   py27-configobj py27-yaml
> +   py27-Jinja2
> +   py27-oauth py27-serial
> +   py27-prettytable
> +   py27-requests py27-six
> +   python py27-cheetah
> +"
> +[ -f "$depschecked" ] || pkg install ${pkgs} || fail "install packages"
> +touch $depschecked
> +
> +# Required but unavailable port/pkg: py27-jsonpatch py27-jsonpointer
> +# Luckily, the install step will take care of this by installing it from pypi...
> +
> +# Build the code and install in /usr/local/:
> +python setup.py build
> +python setup.py install -O1 --skip-build --prefix /usr/local/ --init-system sysvinit_freebsd
> +
> +# Install the correct config file:
> +cp config/cloud.cfg-freebsd /usr/local/etc/cloud/cloud.cfg
> +
> +# Enable cloud-init in /etc/rc.conf:
> +sed -i.bak -e "/cloudinit_enable=.*/d" /etc/rc.conf
> +echo 'cloudinit_enable="YES"' >> /etc/rc.conf
> +
> +echo "Installation completed."
> +
> +if [ "$1" = "run" ]; then
> +	echo "Ok, now let's see if it works."
> +
> +	# Backup SSH keys
> +	mv /etc/ssh/ssh_host_* /tmp/
> +
> +	# Remove old metadata
> +	rm -rf /var/lib/cloud
> +
> +	# Just log everything, quick&dirty
> +	rm /usr/local/etc/cloud/cloud.cfg.d/05_logging.cfg 
> +
> +	# Start:
> +	/usr/local/etc/rc.d/cloudinit start
> +
> +	# Restore SSH keys
> +	mv /tmp/ssh_host_* /etc/ssh/
> +fi
> 


-- 
https://code.launchpad.net/~harmw/cloud-init/freebsd/+merge/231024
Your team cloud init development team is requested to review the proposed merge of lp:~harmw/cloud-init/freebsd into lp:cloud-init.


References