cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #00509
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