diff options
-rw-r--r-- | Jenkinsfile | 194 | ||||
-rw-r--r-- | cloudinit/config/cc_vyos.py | 333 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceOVF.py | 3 | ||||
-rw-r--r-- | config/cloud.cfg.tmpl | 202 | ||||
-rw-r--r-- | systemd/cloud-config.service.tmpl | 1 |
5 files changed, 542 insertions, 191 deletions
diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..1b9d23e4 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,194 @@ +// Copyright (C) 2019 VyOS maintainers and contributors +// +// This program is free software; you can redistribute it and/or modify +// in order to easy exprort images built to "external" world +// it under the terms of the GNU General Public License version 2 or later as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +@NonCPS + +def getGitBranchName() { + def branch = scm.branches[0].name + return branch.split('/')[-1] +} + +def getGitRepoURL() { + return scm.userRemoteConfigs[0].url +} + +def getGitRepoName() { + return getGitRepoURL().split('/').last() +} + +// Returns true if this is a custom build launched on any project fork. +// Returns false if this is build from git@github.com:vyos/<reponame>. +// <reponame> can be e.g. vyos-1x.git or vyatta-op.git +def isCustomBuild() { + // GitHub organisation base URL + def gitURI = 'git@github.com:vyos/' + getGitRepoName() + def httpURI = 'https://github.com/vyos/' + getGitRepoName() + + return ! ((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) +} + +def setDescription() { + def item = Jenkins.instance.getItemByFullName(env.JOB_NAME) + + // build up the main description text + def description = "" + description += "<h2>VyOS individual package build: " + getGitRepoName().replace('.git', '') + "</h2>" + + if (isCustomBuild()) { + description += "<p style='border: 3px dashed red; width: 50%;'>" + description += "<b>Build not started from official Git repository!</b><br>" + description += "<br>" + description += "Repository: <font face = 'courier'>" + getGitRepoURL() + "</font><br>" + description += "Branch: <font face = 'courier'>" + getGitBranchName() + "</font><br>" + description += "</p>" + } else { + description += "Sources taken from Git branch: <font face = 'courier'>" + getGitBranchName() + "</font><br>" + } + + item.setDescription(description) + item.save() +} + +/* Only keep the 10 most recent builds. */ +def projectProperties = [ + [$class: 'BuildDiscarderProperty',strategy: [$class: 'LogRotator', numToKeepStr: '10']], +] + +properties(projectProperties) +setDescription() + +node('Docker') { + stage('Define Agent') { + script { + // create container name on demand + def branchName = getGitBranchName() + if (branchName == "master") { + branchName = "current" + } + env.DOCKER_IMAGE = "vyos/vyos-build:" + branchName + } + } +} + +pipeline { + agent { + docker { + args "--sysctl net.ipv6.conf.lo.disable_ipv6=0 -e GOSU_UID=1006 -e GOSU_GID=1006" + image "${env.DOCKER_IMAGE}" + alwaysPull true + } + } + options { + disableConcurrentBuilds() + skipDefaultCheckout() + timeout(time: 30, unit: 'MINUTES') + timestamps() + } + stages { + stage('Fetch') { + steps { + script { + dir('build') { + git branch: getGitBranchName(), + url: getGitRepoURL() + } + } + } + } + stage('Install missed dependencies') { + steps { + script { + dir('build') { + sh 'sudo apt update' + sh 'sudo apt install -y python3-jsonschema python3-contextlib2 cloud-utils' + } + } + } + } + stage('Build') { + steps { + script { + dir('build') { + def commitId = sh(returnStdout: true, script: 'git rev-parse --short=11 HEAD').trim() + currentBuild.description = sprintf('Git SHA1: %s', commitId[-11..-1]) + + sh './packages/bddeb' + } + } + } + } + } + post { + cleanup { + deleteDir() + } + success { + script { + // archive *.deb artifact on custom builds, deploy to repo otherwise + if ( isCustomBuild()) { + archiveArtifacts artifacts: 'cloud-init_*_all.deb', fingerprint: true + } else { + // publish build result, using SSH-dev.packages.vyos.net Jenkins Credentials + sshagent(['SSH-dev.packages.vyos.net']) { + // build up some fancy groovy variables so we do not need to write/copy + // every option over and over again! + def RELEASE = getGitBranchName() + if (getGitBranchName() == "master") { + RELEASE = 'current' + } + + def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + RELEASE + '/' + if (getGitBranchName() == "crux") + VYOS_REPO_PATH += 'vyos/' + + def SSH_OPTS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR' + def SSH_REMOTE = 'khagen@10.217.48.113' + + echo "Uploading package(s) and updating package(s) in the repository ..." + + files = findFiles(glob: 'cloud-init_*_all.deb') + files.each { PACKAGE -> + def ARCH = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Architecture").trim() + def SUBSTRING = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Package").trim() + def SSH_DIR = '~/VyOS/' + RELEASE + '/' + ARCH + def ARCH_OPT = '' + if (ARCH != 'all') + ARCH_OPT = '-A ' + ARCH + + // No need to explicitly check the return code. The pipeline + // will fail if sh returns a non 0 exit code + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "bash --login -c 'mkdir -p ${SSH_DIR}'" + """ + sh """ + scp ${SSH_OPTS} ${PACKAGE} ${SSH_REMOTE}:${SSH_DIR}/ + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} remove ${RELEASE} ${SUBSTRING}'" + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} deleteunreferenced'" + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} includedeb ${RELEASE} ${SSH_DIR}/${PACKAGE}'" + """ + } + } + } + } + } + } +} + diff --git a/cloudinit/config/cc_vyos.py b/cloudinit/config/cc_vyos.py new file mode 100644 index 00000000..e51ed7f2 --- /dev/null +++ b/cloudinit/config/cc_vyos.py @@ -0,0 +1,333 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2009-2010 Canonical Ltd. +# Copyright (C) 2012 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2019 Sentrium S.L. +# +# Author: Scott Moser <scott.moser@canonical.com> +# Author: Juerg Haefliger <juerg.haefliger@hp.com> +# Author: Kim Hagen <kim@sentrium.io> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import re +import sys +import ast + +import ipaddress +from cloudinit import stages +from cloudinit import util + +from cloudinit.distros import ug_util +from cloudinit.settings import PER_INSTANCE +from cloudinit import handlers +from cloudinit import log as logging + +from vyos.configtree import ConfigTree + +# configure logging +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +frequency = PER_INSTANCE + +class VyosError(Exception): + """Raised when the distro runs into an exception when setting vyos config. + This may happen when the ssh pub key format is wrong. + """ + pass + +# configure user account with password +def set_pass_login(config, user, password, encrypted_pass): + if encrypted_pass: + config.set(['system', 'login', 'user', user, 'authentication', 'encrypted-password'], value=password, replace=True) + else: + config.set(['system', 'login', 'user', user, 'authentication', 'plaintext-password'], value=password, replace=True) + + config.set_tag(['system', 'login', 'user']) + +# configure user account with ssh key +def set_ssh_login(config, user, key_string, key_x): + key_type = None + key_data = None + key_name = None + + if key_string == '': + logger.error("No keys found.") + return + + key_parts = key_string.split(None) + + for key in key_parts: + if 'ssh-dss' in key or 'ssh-rsa' in key: + key_type = key + + if key.startswith('AAAAB3NzaC1yc2E') or key.startswith('AAAAB3NzaC1kc3M'): + key_data = key + + if not key_type: + logger.error("Key type not defined, wrong ssh key format.") + return + + if not key_data: + logger.error("Key base64 not defined, wrong ssh key format.") + return + + if len(key_parts) > 2: + if key_parts[2] != key_type or key_parts[2] != key_data: + key_name = key_parts[2] + else: + key_name = "cloud-init-%s" % key_x + else: + key_name = "cloud-init-%s" % key_x + + config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name , 'key'], value=key_data, replace=True) + config.set(['system', 'login', 'user', user, 'authentication', 'public-keys', key_name , 'type'], value=key_type, replace=True) + config.set_tag(['system', 'login', 'user']) + config.set_tag(['system', 'login', 'user', user, 'authentication', 'public-keys']) + + +# configure system parameters from OVF template +def set_config_ovf(config, hostname, metadata): + ip_0 = metadata['ip0'] + mask_0 = metadata['netmask0'] + gateway = metadata['gateway'] + DNS = list(metadata['DNS'].replace(' ', '').split(',')) + NTP = list(metadata['NTP'].replace(' ', '').split(',')) + APIKEY = metadata['APIKEY'] + APIPORT = metadata['APIPORT'] + APIDEBUG = metadata['APIDEBUG'] + + if ip_0 and ip_0 != 'null' and mask_0 and mask_0 != 'null' and gateway and gateway != 'null': + cidr = str(ipaddress.IPv4Network('0.0.0.0/' + mask_0).prefixlen) + ipcidr = ip_0 + '/' + cidr + + config.set(['interfaces', 'ethernet', 'eth0', 'address'], value=ipcidr, replace=True) + config.set_tag(['interfaces', 'ethernet']) + config.set(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop'], value=gateway, replace=True) + config.set_tag(['protocols', 'static', 'route']) + config.set_tag(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop']) + else: + config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True) + config.set_tag(['interfaces', 'ethernet']) + + DNS = [server for server in DNS if server and server != 'null'] + if DNS: + for server in DNS: + config.set(['system', 'name-server'], value=server, replace=False) + + NTP = [server for server in NTP if server and server != 'null'] + if NTP: + for server in NTP: + config.set(['system', 'ntp', 'server'], value=server, replace=False) + config.set_tag(['system', 'ntp', 'server']) + + if APIKEY and APIKEY != 'null': + config.set(['service', 'https', 'api', 'keys', 'id', 'cloud-init', 'key'], value=APIKEY, replace=True) + config.set_tag(['service', 'https', 'api', 'keys', 'id']) + + if APIDEBUG != 'False' and APIKEY and APIKEY != 'null': + config.set(['service', 'https', 'api', 'debug'], replace=True) + + if APIPORT and APIPORT != 'null' and APIKEY and APIKEY != 'null': + config.set(['service', 'https', 'listen-address', '0.0.0.0', 'listen-port'], value=APIPORT, replace=True) + config.set_tag(['service', 'https', 'listen-address']) + + config.set(['service', 'ssh'], replace=True) + config.set(['service', 'ssh', 'port'], value='22', replace=True) + + if hostname and hostname != 'null': + config.set(['system', 'host-name'], value=hostname, replace=True) + else: + config.set(['system', 'host-name'], value='vyos', replace=True) + + +# configure interface +def set_config_interfaces(config, iface_name, iface_config): + # configure DHCP client + if 'dhcp4' in iface_config: + if iface_config['dhcp4'] == True: + config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp', replace=True) + config.set_tag(['interfaces', 'ethernet']) + if 'dhcp6' in iface_config: + if iface_config['dhcp6'] == True: + config.set(['interfaces', 'ethernet', iface_name, 'address'], value='dhcp6', replace=True) + config.set_tag(['interfaces', 'ethernet']) + + # configure static addresses + if 'addresses' in iface_config: + for item in iface_config['addresses']: + config.set(['interfaces', 'ethernet', iface_name, 'address'], value=item, replace=True) + config.set_tag(['interfaces', 'ethernet']) + + # configure gateways + if 'gateway4' in iface_config: + config.set(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop'], value=item, replace=True) + config.set_tag(['protocols', 'static', 'route']) + config.set_tag(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop']) + if 'gateway6' in iface_config: + config.set(['protocols', 'static', 'route6', '::/0', 'next-hop'], value=item, replace=True) + config.set_tag(['protocols', 'static', 'route6']) + config.set_tag(['protocols', 'static', 'route6', '::/0', 'next-hop']) + + # configre MTU + if 'mtu' in iface_config: + config.set(['interfaces', 'ethernet', iface_name, 'mtu'], value=iface_config['mtu'], replace=True) + config.set_tag(['interfaces', 'ethernet']) + + # configure routes + if 'routes' in iface_config: + for item in iface_config['routes']: + try: + if ipaddress.ip_network(item['to']).version == 4: + config.set(['protocols', 'static', 'route', item['to'], 'next-hop'], value=item['via'], replace=True) + config.set_tag(['protocols', 'static', 'route']) + config.set_tag(['protocols', 'static', 'route', item['to'], 'next-hop']) + if ipaddress.ip_network(item['to']).version == 6: + config.set(['protocols', 'static', 'route6', item['to'], 'next-hop'], value=item['via'], replace=True) + config.set_tag(['protocols', 'static', 'route6']) + config.set_tag(['protocols', 'static', 'route6', item['to'], 'next-hop']) + except Exception as err: + logger.error("Impossible to detect IP protocol version: {}".format(err)) + + # configure nameservers + if 'nameservers' in iface_config: + if 'search' in iface_config['nameservers']: + for item in iface_config['nameservers']['search']: + config.set(['system', 'domain-search'], value=item, replace=False) + if 'addresses' in iface_config['nameservers']: + for item in iface_config['nameservers']['addresses']: + config.set(['system', 'name-server'], value=item, replace=False) + + +# configure DHCP client for interface +def set_config_dhcp(config): + config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True) + config.set_tag(['interfaces', 'ethernet']) + + +# configure SSH server service +def set_config_ssh(config): + config.set(['service', 'ssh'], replace=True) + config.set(['service', 'ssh', 'port'], value='22', replace=True) + config.set(['service', 'ssh', 'client-keepalive-interval'], value='180', replace=True) + + +# configure hostname +def set_config_hostname(config, hostname): + config.set(['system', 'host-name'], value=hostname, replace=True) + + +# configure SSH, eth0 interface and hostname +def set_config_cloud(config, hostname): + config.set(['service', 'ssh'], replace=True) + config.set(['service', 'ssh', 'port'], value='22', replace=True) + config.set(['service', 'ssh', 'client-keepalive-interval'], value='180', replace=True) + config.set(['interfaces', 'ethernet', 'eth0', 'address'], value='dhcp', replace=True) + config.set_tag(['interfaces', 'ethernet']) + config.set(['system', 'host-name'], value=hostname, replace=True) + + +# main config handler +def handle(name, cfg, cloud, log, _args): + init = stages.Init() + dc = init.fetch() + cfg_file_name = '/opt/vyatta/etc/config/config.boot' + bak_file_name = '/opt/vyatta/etc/config.boot.default' + metadata = cloud.datasource.metadata + (netcfg, _) = init._find_networking_config() + (users, _) = ug_util.normalize_users_groups(cfg, cloud.distro) + (hostname, _) = util.get_hostname_fqdn(cfg, cloud) + key_x = 1 + key_y = 0 + + # look at data that can be used for configuration + #print(dir(dc)) + + if not os.path.exists(cfg_file_name): + file_name = bak_file_name + else: + file_name = cfg_file_name + + with open(file_name, 'r') as f: + config_file = f.read() + config = ConfigTree(config_file) + + if 'Azure' in dc.dsname: + encrypted_pass = True + for key, val in users.items(): + user = key + + if 'passwd' in val: + password = val.get('passwd') + set_pass_login(config, user, password, encrypted_pass) + + vyos_keys = metadata['public-keys'] + + for ssh_key in vyos_keys: + set_ssh_login(config, user, ssh_key, key_x) + key_x = key_x + 1 + else: + encrypted_pass = False + for user in users: + password = util.get_cfg_option_str(cfg, 'passwd', None) + + if not password: + password = util.get_cfg_option_str(cfg, 'password', None) + + if password and password != '': + hash = re.match("(^\$.\$)", password) + hash_count = password.count('$') + if hash and hash_count >= 3: + base64 = password.split('$')[3] + base_64_len = len(base64) + if ((hash.group(1) == '$1$' and base_64_len == 22) or + (hash.group(1) == '$5$' and base_64_len == 43) or + (hash.group(1) == '$6$' and base_64_len == 86)): + encrypted_pass = True + set_pass_login(config, user, password, encrypted_pass) + + vyos_keys = cloud.get_public_ssh_keys() or [] + if 'ssh_authorized_keys' in cfg: + cfgkeys = cfg['ssh_authorized_keys'] + vyos_keys.extend(cfgkeys) + + for ssh_key in vyos_keys: + set_ssh_login(config, user, ssh_key, key_x) + key_x = key_x + 1 + + if 'OVF' in dc.dsname: + set_config_ovf(config, hostname, metadata) + key_y = 1 + elif netcfg: + if 'ethernets' in netcfg: + key_y = 1 + for interface_name, interface_config in netcfg['ethernets'].items(): + set_config_interfaces(config, interface_name, interface_config) + + set_config_ssh(config) + set_config_hostname(config, hostname) + else: + set_config_dhcp(config) + set_config_ssh(config) + set_config_hostname(config, hostname) + + if key_y == 0: + set_config_dhcp(config) + + try: + with open(cfg_file_name, 'w') as f: + f.write(config.to_string()) + except Exception as e: + logger.error("Failed to write configs into file %s error %s", file_name, e) diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py index 9f6e6b6c..7f55b5f8 100644 --- a/cloudinit/sources/DataSourceOVF.py +++ b/cloudinit/sources/DataSourceOVF.py @@ -414,7 +414,8 @@ def read_ovf_environment(contents): cfg = {} ud = None cfg_props = ['password'] - md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id'] + md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id', + 'ip0', 'netmask0', 'gateway', 'DNS', 'NTP', 'APIKEY' ,'APIPORT', 'APIDEBUG'] for (prop, val) in props.items(): if prop == 'hostname': prop = "local-hostname" diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl index 99f96ea1..8f98cb96 100644 --- a/config/cloud.cfg.tmpl +++ b/config/cloud.cfg.tmpl @@ -2,228 +2,50 @@ # The top level settings are used as module # and system configuration. -{% if variant in ["freebsd"] %} -syslog_fix_perms: root:wheel -{% elif variant in ["suse"] %} -syslog_fix_perms: root:root -{% endif %} # 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 default $user -{% if variant in ["freebsd"] %} -disable_root: false -{% else %} -disable_root: true -{% endif %} - -{% if variant in ["amazon", "centos", "fedora", "rhel"] %} -mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] -{% if variant == "amazon" %} -resize_rootfs: noblock -{% endif %} -resize_rootfs_tmp: /dev -ssh_pwauth: 0 - -{% endif %} # This will cause the set+update hostname module to not operate (if true) -preserve_hostname: false +preserve_hostname: true -{% if variant in ["freebsd"] %} -# This should not be required, but leave it in place until the real cause of -# not finding -any- datasources is resolved. -datasource_list: ['NoCloud', 'ConfigDrive', 'Azure', 'OpenStack', 'Ec2'] -{% endif %} # Example datasource config # datasource: # Ec2: # metadata_urls: [ 'blah.com' ] # timeout: 5 # (defaults to 50 seconds) # max_wait: 10 # (defaults to 120 seconds) +datasource: + Azure: + agent_command: [/usr/bin/python3, -u, /usr/sbin/waagent, -start] - -{% if variant == "amazon" %} -# Amazon Linux relies on ec2-net-utils for network configuration -network: - config: disabled -{% endif %} +# disable customization for VMware +disable_vmware_customization: true # The modules that run in the 'init' stage cloud_init_modules: - - migrator - - seed_random - - bootcmd - - write-files - - growpart - - resizefs -{% if variant not in ["freebsd"] %} - - disk_setup - - mounts -{% endif %} - - set_hostname - - update_hostname -{% if variant not in ["freebsd"] %} - - update_etc_hosts - - ca-certs - - rsyslog -{% endif %} - - users-groups - - ssh # The modules that run in the 'config' stage cloud_config_modules: -{% if variant in ["ubuntu", "unknown", "debian"] %} -# Emit the cloud config ready event -# this can be used by upstart jobs for 'start on cloud-config'. - - emit_upstart - - snap -{% endif %} - - ssh-import-id - - locale - - set-passwords -{% if variant in ["rhel", "fedora"] %} - - spacewalk - - yum-add-repo -{% endif %} -{% if variant in ["ubuntu", "unknown", "debian"] %} - - grub-dpkg - - apt-pipelining - - apt-configure -{% endif %} -{% if variant in ["ubuntu"] %} - - ubuntu-advantage -{% endif %} -{% if variant in ["suse"] %} - - zypper-add-repo -{% endif %} -{% if variant not in ["freebsd"] %} - - ntp -{% endif %} - - timezone - - disable-ec2-metadata - - runcmd -{% if variant in ["ubuntu", "unknown", "debian"] %} - - byobu -{% endif %} + - vyos # The modules that run in the 'final' stage cloud_final_modules: - - package-update-upgrade-install -{% if variant in ["ubuntu", "unknown", "debian"] %} - - fan - - landscape - - lxd -{% endif %} -{% if variant in ["ubuntu", "unknown"] %} - - ubuntu-drivers -{% endif %} -{% if variant not in ["freebsd"] %} - - puppet - - chef - - mcollective -{% endif %} - - salt-minion - - 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 + - runcmd + # System and/or distro specific settings # (not accessible to handlers/transforms) system_info: # This will affect which distro class gets used -{% if variant in ["amazon", "arch", "centos", "debian", "fedora", "freebsd", "rhel", "suse", "ubuntu"] %} - distro: {{ variant }} -{% else %} - # Unknown/fallback distro. - distro: ubuntu -{% endif %} -{% if variant in ["ubuntu", "unknown", "debian"] %} + distro: debian # Default user name + that default users groups (if added/used) default_user: - name: ubuntu - lock_passwd: True - gecos: Ubuntu - groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video] - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - shell: /bin/bash - # Automatically discover the best ntp_client - ntp_client: auto + name: vyos # Other config here will be given to the distro class and/or path classes paths: - cloud_dir: /var/lib/cloud/ + cloud_dir: /opt/vyatta/etc/config/cloud/ templates_dir: /etc/cloud/templates/ upstart_dir: /etc/init/ - package_mirrors: - - arches: [i386, amd64] - failsafe: - primary: http://archive.ubuntu.com/ubuntu - security: http://security.ubuntu.com/ubuntu - search: - primary: - - http://%(ec2_region)s.ec2.archive.ubuntu.com/ubuntu/ - - http://%(availability_zone)s.clouds.archive.ubuntu.com/ubuntu/ - - http://%(region)s.clouds.archive.ubuntu.com/ubuntu/ - security: [] - - arches: [arm64, armel, armhf] - failsafe: - primary: http://ports.ubuntu.com/ubuntu-ports - security: http://ports.ubuntu.com/ubuntu-ports - search: - primary: - - http://%(ec2_region)s.ec2.ports.ubuntu.com/ubuntu-ports/ - - http://%(availability_zone)s.clouds.ports.ubuntu.com/ubuntu-ports/ - - http://%(region)s.clouds.ports.ubuntu.com/ubuntu-ports/ - security: [] - - arches: [default] - failsafe: - primary: http://ports.ubuntu.com/ubuntu-ports - security: http://ports.ubuntu.com/ubuntu-ports - ssh_svcname: ssh -{% elif variant in ["amazon", "arch", "centos", "fedora", "rhel", "suse"] %} - # Default user name + that default users groups (if added/used) - default_user: -{% if variant == "amazon" %} - name: ec2-user - lock_passwd: True - gecos: EC2 Default User -{% else %} - name: {{ variant }} - lock_passwd: True - gecos: {{ variant }} Cloud User -{% endif %} -{% if variant == "suse" %} - groups: [cdrom, users] -{% elif variant == "arch" %} - groups: [wheel, users] -{% else %} - groups: [wheel, adm, systemd-journal] -{% endif %} - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - shell: /bin/bash - # Other config here will be given to the distro class and/or path classes - paths: - cloud_dir: /var/lib/cloud/ - templates_dir: /etc/cloud/templates/ - ssh_svcname: sshd -{% elif variant in ["freebsd"] %} - # Default user name + that default users groups (if added/used) - default_user: - name: freebsd - lock_passwd: True - gecos: FreeBSD - groups: [wheel] - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - shell: /bin/tcsh -{% endif %} diff --git a/systemd/cloud-config.service.tmpl b/systemd/cloud-config.service.tmpl index 9d928ca2..508d777e 100644 --- a/systemd/cloud-config.service.tmpl +++ b/systemd/cloud-config.service.tmpl @@ -1,6 +1,7 @@ ## template:jinja [Unit] Description=Apply the settings specified in cloud-config +Before=vyos-router.service After=network-online.target cloud-config.target After=snapd.seeded.service Wants=network-online.target cloud-config.target |