diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py index 97ef649..aaf7136 100644 --- a/cloudinit/config/cc_chef.py +++ b/cloudinit/config/cc_chef.py @@ -6,70 +6,7 @@ # # This file is part of cloud-init. See LICENSE file for license information. -""" -Chef ----- -**Summary:** module that configures, starts and installs chef. - -This module enables chef to be installed (from packages or -from gems, or from omnibus). Before this occurs chef configurations are -written to disk (validation.pem, client.pem, firstboot.json, client.rb), -and needed chef folders/directories are created (/etc/chef and /var/log/chef -and so-on). Then once installing proceeds correctly if configured chef will -be started (in daemon mode or in non-daemon mode) and then once that has -finished (if ran in non-daemon mode this will be when chef finishes -converging, if ran in daemon mode then no further actions are possible since -chef will have forked into its own process) then a post run function can -run that can do finishing activities (such as removing the validation pem -file). - -**Internal name:** ``cc_chef`` - -**Module frequency:** per always - -**Supported distros:** all - -**Config keys**:: - - chef: - directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef, - /var/cache/chef, /var/backups/chef, /run/chef) - validation_cert: (optional string to be written to file validation_key) - special value 'system' means set use existing file - validation_key: (optional the path for validation_cert. default - /etc/chef/validation.pem) - firstboot_path: (path to write run_list and initial_attributes keys that - should also be present in this configuration, defaults - to /etc/chef/firstboot.json) - exec: boolean to run or not run chef (defaults to false, unless - a gem installed is requested - where this will then default - to true) - - chef.rb template keys (if falsey, then will be skipped and not - written to /etc/chef/client.rb) - - chef: - client_key: - encrypted_data_bag_secret: - environment: - file_backup_path: - file_cache_path: - json_attribs: - log_level: - log_location: - node_name: - omnibus_url: - omnibus_url_retries: - omnibus_version: - pid_file: - server_url: - show_time: - ssl_verify_mode: - validation_cert: - validation_key: - validation_name: -""" +"""Chef: module that configures, starts and installs chef.""" import itertools import json @@ -94,7 +31,7 @@ CHEF_DIRS = tuple([ '/var/lib/chef', '/var/cache/chef', '/var/backups/chef', - '/run/chef', + '/var/run/chef', ]) REQUIRED_CHEF_DIRS = tuple([ '/etc/chef', diff --git a/cloudinit/config/cc_refresh_rmc_and_interface.py b/cloudinit/config/cc_refresh_rmc_and_interface.py deleted file mode 100644 index 146758a..0000000 --- a/cloudinit/config/cc_refresh_rmc_and_interface.py +++ /dev/null @@ -1,159 +0,0 @@ -# (c) Copyright IBM Corp. 2020 All Rights Reserved -# -# Author: Aman Kumar Sinha -# -# This file is part of cloud-init. See LICENSE file for license information. - -""" -Refresh IPv6 interface and RMC ------------------------------- -**Summary:** Ensure Network Manager is not managing IPv6 interface - -This module is IBM PowerVM Hypervisor specific - -Reliable Scalable Cluster Technology (RSCT) is a set of software components -that together provide a comprehensive clustering environment(RAS features) -for IBM PowerVM based virtual machines. RSCT includes the Resource -Monitoring and Control (RMC) subsystem. RMC is a generalized framework used -for managing, monitoring, and manipulating resources. RMC runs as a daemon -process on individual machines and needs creation of unique node id and -restarts during VM boot. -More details refer -https://www.ibm.com/support/knowledgecenter/en/SGVKBA_3.2/admin/bl503_ovrv.htm - -This module handles -- Refreshing RMC -- Disabling NetworkManager from handling IPv6 interface, as IPv6 interface - is used for communication between RMC daemon and PowerVM hypervisor. - -**Internal name:** ``cc_refresh_rmc_and_interface`` - -**Module frequency:** per always - -**Supported distros:** RHEL - -""" - -from cloudinit import log as logging -from cloudinit.settings import PER_ALWAYS -from cloudinit import util -from cloudinit import subp -from cloudinit import netinfo - -import errno - -frequency = PER_ALWAYS - -LOG = logging.getLogger(__name__) -# Ensure that /opt/rsct/bin has been added to standard PATH of the -# distro. The symlink to rmcctrl is /usr/sbin/rsct/bin/rmcctrl . -RMCCTRL = 'rmcctrl' - - -def handle(name, _cfg, _cloud, _log, _args): - if not subp.which(RMCCTRL): - LOG.debug("No '%s' in path, disabled", RMCCTRL) - return - - LOG.debug( - 'Making the IPv6 up explicitly. ' - 'Ensuring IPv6 interface is not being handled by NetworkManager ' - 'and it is restarted to re-establish the communication with ' - 'the hypervisor') - - ifaces = find_ipv6_ifaces() - - # Setting NM_CONTROLLED=no for IPv6 interface - # making it down and up - - if len(ifaces) == 0: - LOG.debug("Did not find any interfaces with ipv6 addresses.") - else: - for iface in ifaces: - refresh_ipv6(iface) - disable_ipv6(sysconfig_path(iface)) - restart_network_manager() - - -def find_ipv6_ifaces(): - info = netinfo.netdev_info() - ifaces = [] - for iface, data in info.items(): - if iface == "lo": - LOG.debug('Skipping localhost interface') - if len(data.get("ipv4", [])) != 0: - # skip this interface, as it has ipv4 addrs - continue - ifaces.append(iface) - return ifaces - - -def refresh_ipv6(interface): - # IPv6 interface is explicitly brought up, subsequent to which the - # RMC services are restarted to re-establish the communication with - # the hypervisor. - subp.subp(['ip', 'link', 'set', interface, 'down']) - subp.subp(['ip', 'link', 'set', interface, 'up']) - - -def sysconfig_path(iface): - return '/etc/sysconfig/network-scripts/ifcfg-' + iface - - -def restart_network_manager(): - subp.subp(['systemctl', 'restart', 'NetworkManager']) - - -def disable_ipv6(iface_file): - # Ensuring that the communication b/w the hypervisor and VM is not - # interrupted due to NetworkManager. For this purpose, as part of - # this function, the NM_CONTROLLED is explicitly set to No for IPV6 - # interface and NetworkManager is restarted. - try: - contents = util.load_file(iface_file) - except IOError as e: - if e.errno == errno.ENOENT: - LOG.debug("IPv6 interface file %s does not exist\n", - iface_file) - else: - raise e - - if 'IPV6INIT' not in contents: - LOG.debug("Interface file %s did not have IPV6INIT", iface_file) - return - - LOG.debug("Editing interface file %s ", iface_file) - - # Dropping any NM_CONTROLLED or IPV6 lines from IPv6 interface file. - lines = contents.splitlines() - lines = [line for line in lines if not search(line)] - lines.append("NM_CONTROLLED=no") - - with open(iface_file, "w") as fp: - fp.write("\n".join(lines) + "\n") - - -def search(contents): - # Search for any NM_CONTROLLED or IPV6 lines in IPv6 interface file. - return( - contents.startswith("IPV6ADDR") or - contents.startswith("IPADDR6") or - contents.startswith("IPV6INIT") or - contents.startswith("NM_CONTROLLED")) - - -def refresh_rmc(): - # To make a healthy connection between RMC daemon and hypervisor we - # refresh RMC. With refreshing RMC we are ensuring that making IPv6 - # down and up shouldn't impact communication between RMC daemon and - # hypervisor. - # -z : stop Resource Monitoring & Control subsystem and all resource - # managers, but the command does not return control to the user - # until the subsystem and all resource managers are stopped. - # -s : start Resource Monitoring & Control subsystem. - try: - subp.subp([RMCCTRL, '-z']) - subp.subp([RMCCTRL, '-s']) - except Exception: - util.logexc(LOG, 'Failed to refresh the RMC subsystem.') - raise diff --git a/cloudinit/config/cc_reset_rmc.py b/cloudinit/config/cc_reset_rmc.py deleted file mode 100644 index 1cd7277..0000000 --- a/cloudinit/config/cc_reset_rmc.py +++ /dev/null @@ -1,143 +0,0 @@ -# (c) Copyright IBM Corp. 2020 All Rights Reserved -# -# Author: Aman Kumar Sinha -# -# This file is part of cloud-init. See LICENSE file for license information. - - -""" -Reset RMC ------------- -**Summary:** reset rsct node id - -Reset RMC module is IBM PowerVM Hypervisor specific - -Reliable Scalable Cluster Technology (RSCT) is a set of software components, -that together provide a comprehensive clustering environment (RAS features) -for IBM PowerVM based virtual machines. RSCT includes the Resource monitoring -and control (RMC) subsystem. RMC is a generalized framework used for managing, -monitoring, and manipulating resources. RMC runs as a daemon process on -individual machines and needs creation of unique node id and restarts -during VM boot. -More details refer -https://www.ibm.com/support/knowledgecenter/en/SGVKBA_3.2/admin/bl503_ovrv.htm - -This module handles -- creation of the unique RSCT node id to every instance/virtual machine - and ensure once set, it isn't changed subsequently by cloud-init. - In order to do so, it restarts RSCT service. - -Prerequisite of using this module is to install RSCT packages. - -**Internal name:** ``cc_reset_rmc`` - -**Module frequency:** per instance - -**Supported distros:** rhel, sles and ubuntu - -""" -import os - -from cloudinit import log as logging -from cloudinit.settings import PER_INSTANCE -from cloudinit import util -from cloudinit import subp - -frequency = PER_INSTANCE - -# RMCCTRL is expected to be in system PATH (/opt/rsct/bin) -# The symlink for RMCCTRL and RECFGCT are -# /usr/sbin/rsct/bin/rmcctrl and -# /usr/sbin/rsct/install/bin/recfgct respectively. -RSCT_PATH = '/opt/rsct/install/bin' -RMCCTRL = 'rmcctrl' -RECFGCT = 'recfgct' - -LOG = logging.getLogger(__name__) - -NODE_ID_FILE = '/etc/ct_node_id' - - -def handle(name, _cfg, cloud, _log, _args): - # Ensuring node id has to be generated only once during first boot - if cloud.datasource.platform_type == 'none': - LOG.debug('Skipping creation of new ct_node_id node') - return - - if not os.path.isdir(RSCT_PATH): - LOG.debug("module disabled, RSCT_PATH not present") - return - - orig_path = os.environ.get('PATH') - try: - add_path(orig_path) - reset_rmc() - finally: - if orig_path: - os.environ['PATH'] = orig_path - else: - del os.environ['PATH'] - - -def reconfigure_rsct_subsystems(): - # Reconfigure the RSCT subsystems, which includes removing all RSCT data - # under the /var/ct directory, generating a new node ID, and making it - # appear as if the RSCT components were just installed - try: - out = subp.subp([RECFGCT])[0] - LOG.debug(out.strip()) - return out - except subp.ProcessExecutionError: - util.logexc(LOG, 'Failed to reconfigure the RSCT subsystems.') - raise - - -def get_node_id(): - try: - fp = util.load_file(NODE_ID_FILE) - node_id = fp.split('\n')[0] - return node_id - except Exception: - util.logexc(LOG, 'Failed to get node ID from file %s.' % NODE_ID_FILE) - raise - - -def add_path(orig_path): - # Adding the RSCT_PATH to env standard path - # So thet cloud init automatically find and - # run RECFGCT to create new node_id. - suff = ":" + orig_path if orig_path else "" - os.environ['PATH'] = RSCT_PATH + suff - return os.environ['PATH'] - - -def rmcctrl(): - # Stop the RMC subsystem and all resource managers so that we can make - # some changes to it - try: - return subp.subp([RMCCTRL, '-z']) - except Exception: - util.logexc(LOG, 'Failed to stop the RMC subsystem.') - raise - - -def reset_rmc(): - LOG.debug('Attempting to reset RMC.') - - node_id_before = get_node_id() - LOG.debug('Node ID at beginning of module: %s', node_id_before) - - # Stop the RMC subsystem and all resource managers so that we can make - # some changes to it - rmcctrl() - reconfigure_rsct_subsystems() - - node_id_after = get_node_id() - LOG.debug('Node ID at end of module: %s', node_id_after) - - # Check if new node ID is generated or not - # by comparing old and new node ID - if node_id_after == node_id_before: - msg = 'New node ID did not get generated.' - LOG.error(msg) - raise Exception(msg) diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py index d9e7fd5..b2f7d31 100644 --- a/cloudinit/net/network_state.py +++ b/cloudinit/net/network_state.py @@ -820,8 +820,7 @@ def _normalize_subnet(subnet): if subnet.get('type') in ('static', 'static6'): normal_subnet.update( - _normalize_net_keys(normal_subnet, address_keys=( - 'address', 'ip_address',))) + _normalize_net_keys(normal_subnet, address_keys=('address',))) normal_subnet['routes'] = [_normalize_route(r) for r in subnet.get('routes', [])] diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py index 1793977..0a5d481 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py @@ -99,10 +99,6 @@ class ConfigMap(object): def __len__(self): return len(self._conf) - def skip_key_value(self, key, val): - """Skip the pair key, value if it matches a certain rule.""" - return False - def to_string(self): buf = io.StringIO() buf.write(_make_header()) @@ -110,8 +106,6 @@ class ConfigMap(object): buf.write("\n") for key in sorted(self._conf.keys()): value = self._conf[key] - if self.skip_key_value(key, value): - continue if isinstance(value, bool): value = self._bool_map[value] if not isinstance(value, str): @@ -220,7 +214,6 @@ class NetInterface(ConfigMap): 'bond': 'Bond', 'bridge': 'Bridge', 'infiniband': 'InfiniBand', - 'vlan': 'Vlan', } def __init__(self, iface_name, base_sysconf_dir, templates, @@ -274,11 +267,6 @@ class NetInterface(ConfigMap): c.routes = self.routes.copy() return c - def skip_key_value(self, key, val): - if key == 'TYPE' and val == 'Vlan': - return True - return False - class Renderer(renderer.Renderer): """Renders network information in a /etc/sysconfig format.""" @@ -289,7 +277,7 @@ class Renderer(renderer.Renderer): # details about this) iface_defaults = { - 'rhel': {'ONBOOT': True, 'USERCTL': False, + 'rhel': {'ONBOOT': True, 'USERCTL': False, 'NM_CONTROLLED': False, 'BOOTPROTO': 'none'}, 'suse': {'BOOTPROTO': 'static', 'STARTMODE': 'auto'}, } @@ -391,13 +379,6 @@ class Renderer(renderer.Renderer): # Only IPv6 is DHCP, IPv4 may be static iface_cfg['BOOTPROTO'] = 'dhcp6' iface_cfg['DHCLIENT6_MODE'] = 'managed' - # only if rhel AND dhcpv6 stateful - elif (flavor == 'rhel' and - subnet_type == 'ipv6_dhcpv6-stateful'): - iface_cfg['BOOTPROTO'] = 'dhcp' - iface_cfg['DHCPV6C'] = True - iface_cfg['IPV6INIT'] = True - iface_cfg['IPV6_AUTOCONF'] = False else: iface_cfg['IPV6INIT'] = True # Configure network settings using DHCPv6 @@ -470,10 +451,6 @@ class Renderer(renderer.Renderer): iface_cfg[mtu_key] = subnet['mtu'] else: iface_cfg[mtu_key] = subnet['mtu'] - - if subnet_is_ipv6(subnet) and flavor == 'rhel': - iface_cfg['IPV6_FORCE_ACCEPT_RA'] = False - iface_cfg['IPV6_AUTOCONF'] = False elif subnet_type == 'manual': if flavor == 'suse': LOG.debug('Unknown subnet type setting "%s"', subnet_type) @@ -720,16 +697,7 @@ class Renderer(renderer.Renderer): iface_cfg['ETHERDEVICE'] = iface_name[:iface_name.rfind('.')] else: iface_cfg['VLAN'] = True - iface_cfg.kind = 'vlan' - - rdev = iface['vlan-raw-device'] - supported = _supported_vlan_names(rdev, iface['vlan_id']) - if iface_name not in supported: - LOG.info( - "Name '%s' for vlan '%s' is not officially supported" - "by RHEL. Supported: %s", - iface_name, rdev, ' '.join(supported)) - iface_cfg['PHYSDEV'] = rdev + iface_cfg['PHYSDEV'] = iface_name[:iface_name.rfind('.')] iface_subnets = iface.get("subnets", []) route_cfg = iface_cfg.routes @@ -920,16 +888,7 @@ class Renderer(renderer.Renderer): # Distros configuring /etc/sysconfig/network as a file e.g. Centos if sysconfig_path.endswith('network'): util.ensure_dir(os.path.dirname(sysconfig_path)) - netcfg = [] - for line in util.load_file(sysconfig_path, quiet=True).split('\n'): - if 'cloud-init' in line: - break - if not line.startswith(('NETWORKING=', - 'IPV6_AUTOCONF=', - 'NETWORKING_IPV6=')): - netcfg.append(line) - # Now generate the cloud-init portion of sysconfig/network - netcfg.extend([_make_header(), 'NETWORKING=yes']) + netcfg = [_make_header(), 'NETWORKING=yes'] if network_state.use_ipv6: netcfg.append('NETWORKING_IPV6=yes') netcfg.append('IPV6_AUTOCONF=no') @@ -937,15 +896,6 @@ class Renderer(renderer.Renderer): "\n".join(netcfg) + "\n", file_mode) -def _supported_vlan_names(rdev, vid): - """Return list of supported names for vlan devices per RHEL doc - 11.5. Naming Scheme for VLAN Interfaces.""" - return [ - v.format(rdev=rdev, vid=int(vid)) - for v in ("{rdev}{vid:04}", "{rdev}{vid}", - "{rdev}.{vid:04}", "{rdev}.{vid}")] - - def available(target=None): sysconfig = available_sysconfig(target=target) nm = available_nm(target=target) diff --git a/cloudinit/settings.py b/cloudinit/settings.py index 439eee0..ca4ffa8 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py @@ -45,18 +45,14 @@ CFG_BUILTIN = { 'None', ], 'def_log_file': '/var/log/cloud-init.log', - 'def_log_file_mode': 0o600, 'log_cfgs': [], - 'mount_default_fields': [None, None, 'auto', 'defaults,nofail', '0', '2'], - 'ssh_deletekeys': False, - 'ssh_genkeytypes': [], - 'syslog_fix_perms': [], + 'syslog_fix_perms': ['syslog:adm', 'root:adm', 'root:wheel', 'root:root'], 'system_info': { 'paths': { 'cloud_dir': '/var/lib/cloud', 'templates_dir': '/etc/cloud/templates/', }, - 'distro': 'rhel', + 'distro': 'ubuntu', 'network': {'renderers': None}, }, 'vendor_data': {'enabled': True, 'prefix': []}, diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 1c214db..f3c6452 100755 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -258,7 +258,7 @@ def get_hostname(hostname_command='hostname'): def set_hostname(hostname, hostname_command='hostname'): - util.subp(['hostnamectl', 'set-hostname', str(hostname)]) + subp.subp([hostname_command, hostname]) @azure_ds_telemetry_reporter diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py index 3e6365f..65e020c 100644 --- a/cloudinit/sources/helpers/openstack.py +++ b/cloudinit/sources/helpers/openstack.py @@ -602,17 +602,11 @@ def convert_net_json(network_json=None, known_macs=None): elif network['type'] in ['ipv6_slaac', 'ipv6_dhcpv6-stateless', 'ipv6_dhcpv6-stateful']: subnet.update({'type': network['type']}) - elif network['type'] in ['ipv4', 'static']: + elif network['type'] in ['ipv4', 'ipv6']: subnet.update({ 'type': 'static', 'address': network.get('ip_address'), }) - elif network['type'] in ['ipv6', 'static6']: - cfg.update({'accept-ra': False}) - subnet.update({ - 'type': 'static6', - 'address': network.get('ip_address'), - }) # Enable accept_ra for stateful and legacy ipv6_dhcp types if network['type'] in ['ipv6_dhcpv6-stateful', 'ipv6_dhcp']: diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py index d511399..c08042d 100644 --- a/cloudinit/ssh_util.py +++ b/cloudinit/ssh_util.py @@ -262,13 +262,13 @@ def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): except (IOError, OSError): # Give up and use a default key filename - auth_key_fns.append(default_authorizedkeys_file) + auth_key_fns[0] = default_authorizedkeys_file util.logexc(LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fns[0]) - # always store all the keys in the first file configured on sshd_config - return (auth_key_fns[0], parse_authorized_keys(auth_key_fns)) + # always store all the keys in the user's private file + return (default_authorizedkeys_file, parse_authorized_keys(auth_key_fns)) def setup_user_keys(keys, username, options=None): diff --git a/cloudinit/stages.py b/cloudinit/stages.py index d769375..765f4aa 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py @@ -147,9 +147,8 @@ class Init(object): def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, 'def_log_file') - log_file_mode = util.get_cfg_option_int(self.cfg, 'def_log_file_mode') if log_file: - util.ensure_file(log_file, mode=log_file_mode) + util.ensure_file(log_file) perms = self.cfg.get('syslog_fix_perms') if not perms: perms = {} diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl index 7171aaa..2beb9b0 100644 --- a/config/cloud.cfg.tmpl +++ b/config/cloud.cfg.tmpl @@ -135,8 +135,6 @@ cloud_final_modules: - chef - mcollective - salt-minion - - reset_rmc - - refresh_rmc_and_interface - rightscale_userdata - scripts-vendor - scripts-per-once diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt index b5b1fdd..f3ae5e6 100644 --- a/doc/examples/cloud-config.txt +++ b/doc/examples/cloud-config.txt @@ -414,14 +414,10 @@ timezone: US/Eastern # if syslog_fix_perms is a list, it will iterate through and use the # first pair that does not raise error. # -# 'def_log_file' will be created with mode 'def_log_file_mode', which -# is specified as a numeric value and defaults to 0600. -# # the default values are '/var/log/cloud-init.log' and 'syslog:adm' # the value of 'def_log_file' should match what is configured in logging # if either is empty, then no change of ownership will be done def_log_file: /var/log/my-logging-file.log -def_log_file_mode: 0600 syslog_fix_perms: syslog:root # you can set passwords for a user or multiple users diff --git a/rhel/README.rhel b/rhel/README.rhel deleted file mode 100644 index aa29630..0000000 --- a/rhel/README.rhel +++ /dev/null @@ -1,5 +0,0 @@ -The following cloud-init modules are currently unsupported on this OS: - - apt_update_upgrade ('apt_update', 'apt_upgrade', 'apt_mirror', 'apt_preserve_sources_list', 'apt_old_mirror', 'apt_sources', 'debconf_selections', 'packages' options) - - byobu ('byobu_by_default' option) - - chef - - grub_dpkg diff --git a/rhel/cloud-init-tmpfiles.conf b/rhel/cloud-init-tmpfiles.conf deleted file mode 100644 index 0c6d2a3..0000000 --- a/rhel/cloud-init-tmpfiles.conf +++ /dev/null @@ -1 +0,0 @@ -d /run/cloud-init 0700 root root - - diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg deleted file mode 100644 index 9ecba21..0000000 --- a/rhel/cloud.cfg +++ /dev/null @@ -1,69 +0,0 @@ -users: - - default - -disable_root: 1 -ssh_pwauth: 0 - -mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2'] -resize_rootfs_tmp: /dev -ssh_deletekeys: 1 -ssh_genkeytypes: ~ -syslog_fix_perms: ~ -disable_vmware_customization: false - -cloud_init_modules: - - disk_setup - - migrator - - bootcmd - - write-files - - growpart - - resizefs - - set_hostname - - update_hostname - - update_etc_hosts - - rsyslog - - users-groups - - ssh - -cloud_config_modules: - - mounts - - locale - - set-passwords - - rh_subscription - - yum-add-repo - - package-update-upgrade-install - - timezone - - puppet - - chef - - salt-minion - - mcollective - - disable-ec2-metadata - - runcmd - -cloud_final_modules: - - rightscale_userdata - - 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_info: - default_user: - name: cloud-user - lock_passwd: true - gecos: Cloud User - groups: [adm, systemd-journal] - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - shell: /bin/bash - distro: rhel - paths: - cloud_dir: /var/lib/cloud - templates_dir: /etc/cloud/templates - ssh_svcname: sshd - -# vim:syntax=yaml diff --git a/rhel/systemd/cloud-config.service b/rhel/systemd/cloud-config.service deleted file mode 100644 index f3dcd4b..0000000 --- a/rhel/systemd/cloud-config.service +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Apply the settings specified in cloud-config -After=network-online.target cloud-config.target -Wants=network-online.target cloud-config.target -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init modules --mode=config -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-config.target b/rhel/systemd/cloud-config.target deleted file mode 100644 index ae9b7d0..0000000 --- a/rhel/systemd/cloud-config.target +++ /dev/null @@ -1,11 +0,0 @@ -# cloud-init normally emits a "cloud-config" upstart event to inform third -# parties that cloud-config is available, which does us no good when we're -# using systemd. cloud-config.target serves as this synchronization point -# instead. Services that would "start on cloud-config" with upstart can -# instead use "After=cloud-config.target" and "Wants=cloud-config.target" -# as appropriate. - -[Unit] -Description=Cloud-config availability -Wants=cloud-init-local.service cloud-init.service -After=cloud-init-local.service cloud-init.service diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service deleted file mode 100644 index e281c0c..0000000 --- a/rhel/systemd/cloud-final.service +++ /dev/null @@ -1,24 +0,0 @@ -[Unit] -Description=Execute cloud user/final scripts -After=network-online.target cloud-config.service rc-local.service -Wants=network-online.target cloud-config.service -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init modules --mode=final -RemainAfterExit=yes -TimeoutSec=0 -KillMode=process -# Restart NetworkManager if it is present and running. -ExecStartPost=/bin/sh -c 'u=NetworkManager.service; \ - out=$(systemctl show --property=SubState $u) || exit; \ - [ "$out" = "SubState=running" ] || exit 0; \ - systemctl reload-or-try-restart $u' - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init-local.service b/rhel/systemd/cloud-init-local.service deleted file mode 100644 index 8f9f6c9..0000000 --- a/rhel/systemd/cloud-init-local.service +++ /dev/null @@ -1,31 +0,0 @@ -[Unit] -Description=Initial cloud-init job (pre-networking) -DefaultDependencies=no -Wants=network-pre.target -After=systemd-remount-fs.service -Requires=dbus.socket -After=dbus.socket -Before=NetworkManager.service network.service -Before=network-pre.target -Before=shutdown.target -Before=firewalld.target -Conflicts=shutdown.target -RequiresMountsFor=/var/lib/cloud -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStartPre=/bin/mkdir -p /run/cloud-init -ExecStartPre=/sbin/restorecon /run/cloud-init -ExecStartPre=/usr/bin/touch /run/cloud-init/enabled -ExecStart=/usr/bin/cloud-init init --local -ExecStart=/bin/touch /run/cloud-init/network-config-ready -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init.service b/rhel/systemd/cloud-init.service deleted file mode 100644 index 0b3d796..0000000 --- a/rhel/systemd/cloud-init.service +++ /dev/null @@ -1,26 +0,0 @@ -[Unit] -Description=Initial cloud-init job (metadata service crawler) -Wants=cloud-init-local.service -Wants=sshd-keygen.service -Wants=sshd.service -After=cloud-init-local.service -After=NetworkManager.service network.service -After=NetworkManager-wait-online.service -Before=network-online.target -Before=sshd-keygen.service -Before=sshd.service -Before=systemd-user-sessions.service -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init init -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init.target b/rhel/systemd/cloud-init.target deleted file mode 100644 index 083c3b6..0000000 --- a/rhel/systemd/cloud-init.target +++ /dev/null @@ -1,7 +0,0 @@ -# cloud-init target is enabled by cloud-init-generator -# To disable it you can either: -# a.) boot with kernel cmdline of 'cloud-init=disabled' -# b.) touch a file /etc/cloud/cloud-init.disabled -[Unit] -Description=Cloud-init target -After=multi-user.target diff --git a/setup.py b/setup.py index d5cd01a..cbacf48 100755 --- a/setup.py +++ b/setup.py @@ -125,6 +125,14 @@ INITSYS_FILES = { 'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)], 'sysvinit_openrc': [f for f in glob('sysvinit/gentoo/*') if is_f(f)], 'sysvinit_suse': [f for f in glob('sysvinit/suse/*') if is_f(f)], + 'systemd': [render_tmpl(f) + for f in (glob('systemd/*.tmpl') + + glob('systemd/*.service') + + glob('systemd/*.target')) + if (is_f(f) and not is_generator(f))], + 'systemd.generators': [ + render_tmpl(f, mode=0o755) + for f in glob('systemd/*') if is_f(f) and is_generator(f)], 'upstart': [f for f in glob('upstart/*') if is_f(f)], } INITSYS_ROOTS = { @@ -134,6 +142,9 @@ INITSYS_ROOTS = { 'sysvinit_deb': 'etc/init.d', 'sysvinit_openrc': 'etc/init.d', 'sysvinit_suse': 'etc/init.d', + 'systemd': pkg_config_read('systemd', 'systemdsystemunitdir'), + 'systemd.generators': pkg_config_read('systemd', + 'systemdsystemgeneratordir'), 'upstart': 'etc/init/', } INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()]) @@ -234,11 +245,14 @@ if not in_virtualenv(): INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k] data_files = [ - (ETC + '/bash_completion.d', ['bash_completion/cloud-init']), + (ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]), (ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')), (ETC + '/cloud/templates', glob('templates/*')), - (USR_LIB_EXEC + '/cloud-init', ['tools/uncloud-init', + (USR_LIB_EXEC + '/cloud-init', ['tools/ds-identify', + 'tools/uncloud-init', 'tools/write-ssh-key-fingerprints']), + (USR + '/share/bash-completion/completions', + ['bash_completion/cloud-init']), (USR + '/share/doc/cloud-init', [f for f in glob('doc/*') if is_f(f)]), (USR + '/share/doc/cloud-init/examples', [f for f in glob('doc/examples/*') if is_f(f)]), @@ -249,7 +263,8 @@ if not platform.system().endswith('BSD'): data_files.extend([ (ETC + '/NetworkManager/dispatcher.d/', ['tools/hook-network-manager']), - ('/usr/lib/udev/rules.d', [f for f in glob('udev/*.rules')]) + (ETC + '/dhcp/dhclient-exit-hooks.d/', ['tools/hook-dhclient']), + (LIB + '/udev/rules.d', [f for f in glob('udev/*.rules')]) ]) # Use a subclass for install that handles # adding on the right init system configuration files @@ -271,6 +286,8 @@ setuptools.setup( scripts=['tools/cloud-init-per'], license='Dual-licensed under GPLv3 or Apache 2.0', data_files=data_files, + install_requires=requirements, + cmdclass=cmdclass, entry_points={ 'console_scripts': [ 'cloud-init = cloudinit.cmd.main:main', diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py index a1df066..8d7b09c 100644 --- a/tests/unittests/test_distros/test_netconfig.py +++ b/tests/unittests/test_distros/test_netconfig.py @@ -514,9 +514,7 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): DEVICE=eth0 IPV6ADDR=2607:f0d0:1002:0011::2/64 IPV6INIT=yes - IPV6_AUTOCONF=no IPV6_DEFAULTGW=2607:f0d0:1002:0011::1 - IPV6_FORCE_ACCEPT_RA=no NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet @@ -541,87 +539,6 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase): V1_NET_CFG_IPV6, expected_cfgs=expected_cfgs.copy()) - def test_vlan_render_unsupported(self): - """Render officially unsupported vlan names.""" - cfg = { - 'version': 2, - 'ethernets': { - 'eth0': {'addresses': ["192.10.1.2/24"], - 'match': {'macaddress': "00:16:3e:60:7c:df"}}}, - 'vlans': { - 'infra0': {'addresses': ["10.0.1.2/16"], - 'id': 1001, 'link': 'eth0'}}, - } - expected_cfgs = { - self.ifcfg_path('eth0'): dedent("""\ - BOOTPROTO=none - DEVICE=eth0 - HWADDR=00:16:3e:60:7c:df - IPADDR=192.10.1.2 - NETMASK=255.255.255.0 - NM_CONTROLLED=no - ONBOOT=yes - TYPE=Ethernet - USERCTL=no - """), - self.ifcfg_path('infra0'): dedent("""\ - BOOTPROTO=none - DEVICE=infra0 - IPADDR=10.0.1.2 - NETMASK=255.255.0.0 - NM_CONTROLLED=no - ONBOOT=yes - PHYSDEV=eth0 - USERCTL=no - VLAN=yes - """), - self.control_path(): dedent("""\ - NETWORKING=yes - """), - } - self._apply_and_verify( - self.distro.apply_network_config, cfg, - expected_cfgs=expected_cfgs) - - def test_vlan_render(self): - cfg = { - 'version': 2, - 'ethernets': { - 'eth0': {'addresses': ["192.10.1.2/24"]}}, - 'vlans': { - 'eth0.1001': {'addresses': ["10.0.1.2/16"], - 'id': 1001, 'link': 'eth0'}}, - } - expected_cfgs = { - self.ifcfg_path('eth0'): dedent("""\ - BOOTPROTO=none - DEVICE=eth0 - IPADDR=192.10.1.2 - NETMASK=255.255.255.0 - NM_CONTROLLED=no - ONBOOT=yes - TYPE=Ethernet - USERCTL=no - """), - self.ifcfg_path('eth0.1001'): dedent("""\ - BOOTPROTO=none - DEVICE=eth0.1001 - IPADDR=10.0.1.2 - NETMASK=255.255.0.0 - NM_CONTROLLED=no - ONBOOT=yes - PHYSDEV=eth0 - USERCTL=no - VLAN=yes - """), - self.control_path(): dedent("""\ - NETWORKING=yes - """), - } - self._apply_and_verify( - self.distro.apply_network_config, cfg, - expected_cfgs=expected_cfgs) - class TestNetCfgDistroOpensuse(TestNetCfgDistroBase): diff --git a/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py b/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py deleted file mode 100644 index e13b779..0000000 --- a/tests/unittests/test_handler/test_handler_refresh_rmc_and_interface.py +++ /dev/null @@ -1,109 +0,0 @@ -from cloudinit.config import cc_refresh_rmc_and_interface as ccrmci - -from cloudinit import util - -from cloudinit.tests import helpers as t_help -from cloudinit.tests.helpers import mock - -from textwrap import dedent -import logging - -LOG = logging.getLogger(__name__) -MPATH = "cloudinit.config.cc_refresh_rmc_and_interface" -NET_INFO = { - 'lo': {'ipv4': [{'ip': '127.0.0.1', - 'bcast': '', 'mask': '255.0.0.0', - 'scope': 'host'}], - 'ipv6': [{'ip': '::1/128', - 'scope6': 'host'}], 'hwaddr': '', - 'up': 'True'}, - 'env2': {'ipv4': [{'ip': '8.0.0.19', - 'bcast': '8.0.0.255', 'mask': '255.255.255.0', - 'scope': 'global'}], - 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8220/64', - 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:20', - 'up': 'True'}, - 'env3': {'ipv4': [{'ip': '90.0.0.14', - 'bcast': '90.0.0.255', 'mask': '255.255.255.0', - 'scope': 'global'}], - 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8221/64', - 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:21', - 'up': 'True'}, - 'env4': {'ipv4': [{'ip': '9.114.23.7', - 'bcast': '9.114.23.255', 'mask': '255.255.255.0', - 'scope': 'global'}], - 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8222/64', - 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:22', - 'up': 'True'}, - 'env5': {'ipv4': [], - 'ipv6': [{'ip': 'fe80::9c26:c3ff:fea4:62c8/64', - 'scope6': 'link'}], 'hwaddr': '42:20:86:df:fa:4c', - 'up': 'True'}} - - -class TestRsctNodeFile(t_help.CiTestCase): - def test_disable_ipv6_interface(self): - """test parsing of iface files.""" - fname = self.tmp_path("iface-eth5") - util.write_file(fname, dedent("""\ - BOOTPROTO=static - DEVICE=eth5 - HWADDR=42:20:86:df:fa:4c - IPV6INIT=yes - IPADDR6=fe80::9c26:c3ff:fea4:62c8/64 - IPV6ADDR=fe80::9c26:c3ff:fea4:62c8/64 - NM_CONTROLLED=yes - ONBOOT=yes - STARTMODE=auto - TYPE=Ethernet - USERCTL=no - """)) - - ccrmci.disable_ipv6(fname) - self.assertEqual(dedent("""\ - BOOTPROTO=static - DEVICE=eth5 - HWADDR=42:20:86:df:fa:4c - ONBOOT=yes - STARTMODE=auto - TYPE=Ethernet - USERCTL=no - NM_CONTROLLED=no - """), util.load_file(fname)) - - @mock.patch(MPATH + '.refresh_rmc') - @mock.patch(MPATH + '.restart_network_manager') - @mock.patch(MPATH + '.disable_ipv6') - @mock.patch(MPATH + '.refresh_ipv6') - @mock.patch(MPATH + '.netinfo.netdev_info') - @mock.patch(MPATH + '.subp.which') - def test_handle(self, m_refresh_rmc, - m_netdev_info, m_refresh_ipv6, m_disable_ipv6, - m_restart_nm, m_which): - """Basic test of handle.""" - m_netdev_info.return_value = NET_INFO - m_which.return_value = '/opt/rsct/bin/rmcctrl' - ccrmci.handle( - "refresh_rmc_and_interface", None, None, None, None) - self.assertEqual(1, m_netdev_info.call_count) - m_refresh_ipv6.assert_called_with('env5') - m_disable_ipv6.assert_called_with( - '/etc/sysconfig/network-scripts/ifcfg-env5') - self.assertEqual(1, m_restart_nm.call_count) - self.assertEqual(1, m_refresh_rmc.call_count) - - @mock.patch(MPATH + '.netinfo.netdev_info') - def test_find_ipv6(self, m_netdev_info): - """find_ipv6_ifaces parses netdev_info returning those with ipv6""" - m_netdev_info.return_value = NET_INFO - found = ccrmci.find_ipv6_ifaces() - self.assertEqual(['env5'], found) - - @mock.patch(MPATH + '.subp.subp') - def test_refresh_ipv6(self, m_subp): - """refresh_ipv6 should ip down and up the interface.""" - iface = "myeth0" - ccrmci.refresh_ipv6(iface) - m_subp.assert_has_calls([ - mock.call(['ip', 'link', 'set', iface, 'down']), - mock.call(['ip', 'link', 'set', iface, 'up'])]) diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index 844d5ba..54cc846 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -535,6 +535,7 @@ GATEWAY=172.19.3.254 HWADDR=fa:16:3e:ed:9a:59 IPADDR=172.19.1.34 NETMASK=255.255.252.0 +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -632,6 +633,7 @@ IPADDR=172.19.1.34 IPADDR1=10.0.0.10 NETMASK=255.255.252.0 NETMASK1=255.255.255.0 +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -750,10 +752,9 @@ IPADDR=172.19.1.34 IPV6ADDR=2001:DB8::10/64 IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64" IPV6INIT=yes -IPV6_AUTOCONF=no IPV6_DEFAULTGW=2001:DB8::1 -IPV6_FORCE_ACCEPT_RA=no NETMASK=255.255.252.0 +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -881,6 +882,7 @@ NETWORK_CONFIGS = { BOOTPROTO=none DEVICE=eth1 HWADDR=cf:d6:af:48:e8:80 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -897,6 +899,7 @@ NETWORK_CONFIGS = { IPADDR=192.168.21.3 NETMASK=255.255.255.0 METRIC=10000 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -1024,9 +1027,8 @@ NETWORK_CONFIGS = { IPADDR=192.168.14.2 IPV6ADDR=2001:1::1/64 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -1251,33 +1253,6 @@ NETWORK_CONFIGS = { """), }, }, - 'static6': { - 'yaml': textwrap.dedent("""\ - version: 1 - config: - - type: 'physical' - name: 'iface0' - accept-ra: 'no' - subnets: - - type: 'static6' - address: 2001:1::1/64 - """).rstrip(' '), - 'expected_sysconfig_rhel': { - 'ifcfg-iface0': textwrap.dedent("""\ - BOOTPROTO=none - DEVICE=iface0 - IPV6ADDR=2001:1::1/64 - IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no - DEVICE=iface0 - NM_CONTROLLED=no - ONBOOT=yes - TYPE=Ethernet - USERCTL=no - """), - }, - }, 'dhcpv6_stateless': { 'expected_eni': textwrap.dedent("""\ auto lo @@ -1359,11 +1334,10 @@ NETWORK_CONFIGS = { }, 'expected_sysconfig_rhel': { 'ifcfg-iface0': textwrap.dedent("""\ - BOOTPROTO=dhcp + BOOTPROTO=none DEVICE=iface0 DHCPV6C=yes IPV6INIT=yes - IPV6_AUTOCONF=no IPV6_FORCE_ACCEPT_RA=yes DEVICE=iface0 NM_CONTROLLED=no @@ -1648,6 +1622,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DHCPV6C=yes IPV6INIT=yes MACADDR=aa:bb:cc:dd:ee:ff + NM_CONTROLLED=no ONBOOT=yes TYPE=Bond USERCTL=no"""), @@ -1655,8 +1630,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=dhcp DEVICE=bond0.200 DHCLIENT_SET_DEFAULT_ROUTE=no + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=bond0 + TYPE=Ethernet USERCTL=no VLAN=yes"""), 'ifcfg-br0': textwrap.dedent("""\ @@ -1667,11 +1644,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true IPADDR=192.168.14.2 IPV6ADDR=2001:1::1/64 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no IPV6_DEFAULTGW=2001:4800:78ff:1b::1 MACADDR=bb:bb:bb:bb:bb:aa NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PRIO=22 STP=no @@ -1681,6 +1657,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=none DEVICE=eth0 HWADDR=c0:d6:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -1697,8 +1674,10 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true MTU=1500 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=eth0 + TYPE=Ethernet USERCTL=no VLAN=yes"""), 'ifcfg-eth1': textwrap.dedent("""\ @@ -1706,6 +1685,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth1 HWADDR=aa:d6:9f:2c:e8:80 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes TYPE=Ethernet @@ -1715,6 +1695,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth2 HWADDR=c0:bb:9f:2c:e8:80 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes TYPE=Ethernet @@ -1724,6 +1705,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth3 HWADDR=66:bb:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -1732,6 +1714,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth4 HWADDR=98:bb:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -1740,6 +1723,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth5 DHCLIENT_SET_DEFAULT_ROUTE=no HWADDR=98:bb:9f:2c:e8:8a + NM_CONTROLLED=no ONBOOT=no TYPE=Ethernet USERCTL=no"""), @@ -2190,11 +2174,10 @@ iface bond0 inet6 static IPADDR1=192.168.1.2 IPV6ADDR=2001:1::1/92 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no MTU=9000 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes TYPE=Bond USERCTL=no @@ -2204,6 +2187,7 @@ iface bond0 inet6 static DEVICE=bond0s0 HWADDR=aa:bb:cc:dd:e8:00 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes TYPE=Ethernet @@ -2225,6 +2209,7 @@ iface bond0 inet6 static DEVICE=bond0s1 HWADDR=aa:bb:cc:dd:e8:01 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes TYPE=Ethernet @@ -2281,6 +2266,7 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=en0 HWADDR=aa:bb:cc:dd:e8:00 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no"""), @@ -2293,14 +2279,14 @@ iface bond0 inet6 static IPADDR1=192.168.1.2 IPV6ADDR=2001:1::bbbb/96 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no IPV6_DEFAULTGW=2001:1::1 MTU=2222 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=en0 + TYPE=Ethernet USERCTL=no VLAN=yes"""), }, @@ -2363,6 +2349,7 @@ iface bond0 inet6 static DEVICE=br0 IPADDR=192.168.2.2 NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PRIO=22 STP=no @@ -2376,8 +2363,6 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:00 IPV6ADDR=2001:1::100/96 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet @@ -2390,8 +2375,6 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:01 IPV6ADDR=2001:1::101/96 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet @@ -2486,6 +2469,7 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:00 IPADDR=192.168.1.2 NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=no TYPE=Ethernet USERCTL=no @@ -2495,6 +2479,7 @@ iface bond0 inet6 static DEVICE=eth1 HWADDR=52:54:00:12:34:aa MTU=1480 + NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -2503,6 +2488,7 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=eth2 HWADDR=52:54:00:12:34:ff + NM_CONTROLLED=no ONBOOT=no TYPE=Ethernet USERCTL=no @@ -2919,6 +2905,7 @@ class TestRhelSysConfigRendering(CiTestCase): BOOTPROTO=dhcp DEVICE=eth1000 HWADDR=07-1c-c6-75-a4-be +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -3039,6 +3026,7 @@ GATEWAY=10.0.2.2 HWADDR=52:54:00:12:34:00 IPADDR=10.0.2.15 NETMASK=255.255.255.0 +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -3108,6 +3096,7 @@ USERCTL=no # BOOTPROTO=dhcp DEVICE=eth0 +NM_CONTROLLED=no ONBOOT=yes TYPE=Ethernet USERCTL=no @@ -3192,61 +3181,6 @@ USERCTL=no self._compare_files_to_expected(entry[self.expected_name], found) self._assert_headers(found) - def test_stattic6_from_json(self): - net_json = { - "services": [{"type": "dns", "address": "172.19.0.12"}], - "networks": [{ - "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4", - "type": "ipv4", "netmask": "255.255.252.0", - "link": "tap1a81968a-79", - "routes": [{ - "netmask": "0.0.0.0", - "network": "0.0.0.0", - "gateway": "172.19.3.254", - }, { - "netmask": "0.0.0.0", # A second default gateway - "network": "0.0.0.0", - "gateway": "172.20.3.254", - }], - "ip_address": "172.19.1.34", "id": "network0" - }, { - "network_id": "mgmt", - "netmask": "ffff:ffff:ffff:ffff::", - "link": "interface1", - "mode": "link-local", - "routes": [], - "ip_address": "fe80::c096:67ff:fe5c:6e84", - "type": "static6", - "id": "network1", - "services": [], - "accept-ra": "false" - }], - "links": [ - { - "ethernet_mac_address": "fa:16:3e:ed:9a:59", - "mtu": None, "type": "bridge", "id": - "tap1a81968a-79", - "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f" - }, - ], - } - macs = {'fa:16:3e:ed:9a:59': 'eth0'} - render_dir = self.tmp_dir() - network_cfg = openstack.convert_net_json(net_json, known_macs=macs) - ns = network_state.parse_net_config_data(network_cfg, - skip_broken=False) - renderer = self._get_renderer() - with self.assertRaises(ValueError): - renderer.render_network_state(ns, target=render_dir) - self.assertEqual([], os.listdir(render_dir)) - - def test_static6_from_yaml(self): - entry = NETWORK_CONFIGS['static6'] - found = self._render_and_read(network_config=yaml.load( - entry['yaml'])) - self._compare_files_to_expected(entry[self.expected_name], found) - self._assert_headers(found) - def test_dhcpv6_reject_ra_config_v2(self): entry = NETWORK_CONFIGS['dhcpv6_reject_ra'] found = self._render_and_read(network_config=yaml.load( @@ -3364,8 +3298,6 @@ USERCTL=no IPADDR=192.168.42.100 IPV6ADDR=2001:db8::100/32 IPV6INIT=yes - IPV6_AUTOCONF=no - IPV6_FORCE_ACCEPT_RA=no IPV6_DEFAULTGW=2001:db8::1 NETMASK=255.255.255.0 NM_CONTROLLED=no @@ -3407,6 +3339,7 @@ USERCTL=no NM_CONTROLLED=no ONBOOT=yes PHYSDEV=eno1 + TYPE=Ethernet USERCTL=no VLAN=yes """) diff --git a/tests/unittests/test_sshutil.py b/tests/unittests/test_sshutil.py index 88a111e..fd1d1ba 100644 --- a/tests/unittests/test_sshutil.py +++ b/tests/unittests/test_sshutil.py @@ -593,7 +593,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): fpw.pw_name, sshd_config) content = ssh_util.update_authorized_keys(auth_key_entries, []) - self.assertEqual(authorized_keys, auth_key_fn) + self.assertEqual("%s/.ssh/authorized_keys" % fpw.pw_dir, auth_key_fn) self.assertTrue(VALID_CONTENT['rsa'] in content) self.assertTrue(VALID_CONTENT['dsa'] in content) @@ -610,7 +610,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): sshd_config = self.tmp_path('sshd_config') util.write_file( sshd_config, - "AuthorizedKeysFile %s %s" % (user_keys, authorized_keys) + "AuthorizedKeysFile %s %s" % (authorized_keys, user_keys) ) (auth_key_fn, auth_key_entries) = ssh_util.extract_authorized_keys( @@ -618,7 +618,7 @@ class TestMultipleSshAuthorizedKeysFile(test_helpers.CiTestCase): ) content = ssh_util.update_authorized_keys(auth_key_entries, []) - self.assertEqual(user_keys, auth_key_fn) + self.assertEqual("%s/.ssh/authorized_keys" % fpw.pw_dir, auth_key_fn) self.assertTrue(VALID_CONTENT['rsa'] in content) self.assertTrue(VALID_CONTENT['dsa'] in content) diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers index 802a35b..c67db43 100644 --- a/tools/.github-cla-signers +++ b/tools/.github-cla-signers @@ -1,5 +1,4 @@ AlexBaranowski -Aman306 beezly bipinbachhao BirknerAlex diff --git a/tools/ccfg-merge-debug b/tools/ccfg-merge-debug index 3d60f7f..59c573a 100755 --- a/tools/ccfg-merge-debug +++ b/tools/ccfg-merge-debug @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 from cloudinit import handlers from cloudinit.handlers import cloud_config as cc_part diff --git a/tools/cloudconfig-schema b/tools/cloudconfig-schema index abba445..32f0d61 100755 --- a/tools/cloudconfig-schema +++ b/tools/cloudconfig-schema @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 # This file is part of cloud-init. See LICENSE file for license information. """cloudconfig-schema diff --git a/tools/migrate-lp-user-to-github b/tools/migrate-lp-user-to-github index d0bc890..f1247cb 100755 --- a/tools/migrate-lp-user-to-github +++ b/tools/migrate-lp-user-to-github @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 """Link your Launchpad user to github, proposing branches to LP and Github""" from argparse import ArgumentParser diff --git a/tools/mock-meta.py b/tools/mock-meta.py index 298ba23..9dd067b 100755 --- a/tools/mock-meta.py +++ b/tools/mock-meta.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 # Provides a somewhat random, somewhat compat, somewhat useful mock version of # http://docs.amazonwebservices.com diff --git a/tools/pipremove b/tools/pipremove index 409a955..e1213ed 100755 --- a/tools/pipremove +++ b/tools/pipremove @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 import subprocess import sys diff --git a/tools/read-dependencies b/tools/read-dependencies index 16dcc47..6ad5f70 100755 --- a/tools/read-dependencies +++ b/tools/read-dependencies @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 """List pip dependencies or system package dependencies for cloud-init.""" # You might be tempted to rewrite this as a shell script, but you diff --git a/tools/read-version b/tools/read-version index 334f2c0..02c9064 100755 --- a/tools/read-version +++ b/tools/read-version @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 import os import json @@ -71,8 +71,32 @@ version_long = None is_release_branch_ci = ( os.environ.get("TRAVIS_PULL_REQUEST_BRANCH", "").startswith("upstream/") ) -version = src_version -version_long = None +if is_gitdir(_tdir) and which("git") and not is_release_branch_ci: + flags = [] + if use_tags: + flags = ['--tags'] + cmd = ['git', 'describe', '--abbrev=8', '--match=[0-9]*'] + flags + + try: + version = tiny_p(cmd).strip() + except RuntimeError: + version = None + + if version is None or not version.startswith(src_version): + sys.stderr.write("git describe version (%s) differs from " + "cloudinit.version (%s)\n" % (version, src_version)) + sys.stderr.write( + "Please get the latest upstream tags.\n" + "As an example, this can be done with the following:\n" + "$ git remote add upstream https://git.launchpad.net/cloud-init\n" + "$ git fetch upstream --tags\n" + ) + sys.exit(1) + + version_long = tiny_p(cmd + ["--long"]).strip() +else: + version = src_version + version_long = None # version is X.Y.Z[+xxx.gHASH] # version_long is None or X.Y.Z-xxx-gHASH diff --git a/tools/render-cloudcfg b/tools/render-cloudcfg index 459d543..ed45484 100755 --- a/tools/render-cloudcfg +++ b/tools/render-cloudcfg @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 import argparse import os diff --git a/tools/validate-yaml.py b/tools/validate-yaml.py index a29dfd4..d8bbcfc 100755 --- a/tools/validate-yaml.py +++ b/tools/validate-yaml.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python33 +#!/usr/bin/env python3 """Try to read a YAML file and report any errors. """