def test_netconfig_passthrough_available_no_cloudinit( self, mock_which, mock_subp, mock_log): mock_which.return_value = None available = net.netconfig_passthrough_available(self.target) self.assertEqual(False, available, "netconfig passthrough was available") self.assertTrue(mock_log.warning.called) self.assertFalse(mock_subp.called)
def test_netconfig_passthrough_available(self, mock_which, mock_subp): cloud_init = '/usr/bin/cloud-init' mock_which.return_value = cloud_init mock_subp.return_value = ("NETWORK_CONFIG_V1\nNETWORK_CONFIG_V2\n", '') available = net.netconfig_passthrough_available(self.target) self.assertEqual(True, available, "netconfig passthrough was NOT available") mock_which.assert_called_with('cloud-init', target=self.target) mock_subp.assert_called_with([cloud_init, 'features'], capture=True, target=self.target)
def test_netconfig_passthrough_available_exc(self, mock_which, mock_subp, mock_log): cloud_init = '/usr/bin/cloud-init' mock_which.return_value = cloud_init mock_subp.side_effect = util.ProcessExecutionError available = net.netconfig_passthrough_available(self.target) self.assertEqual(False, available, "netconfig passthrough was available") mock_which.assert_called_with('cloud-init', target=self.target) mock_subp.assert_called_with([cloud_init, 'features'], capture=True, target=self.target) self.assertTrue(mock_log.warning.called)
def apply_net(target, network_state=None, network_config=None): if network_state is None and network_config is None: raise ValueError("Must provide network_config or network_state") if target is None: raise ValueError("target cannot be None.") passthrough = False if network_state: # NB: we cannot support passthrough until curtin can convert from # network_state to network-config yaml ns = net.network_state.from_state_file(network_state) raise ValueError('Not Supported; curtin lacks a network_state to ' 'network_config converter.') elif network_config: netcfg = config.load_config(network_config) # curtin will pass-through the netconfig into the target # for rendering at runtime unless the target OS does not # support NETWORK_CONFIG_V2 feature. LOG.info( 'Checking cloud-init in target [%s] for network ' 'configuration passthrough support.', target) try: passthrough = net.netconfig_passthrough_available(target) except util.ProcessExecutionError: LOG.warning('Failed to determine if passthrough is available') if passthrough: LOG.info('Passing network configuration through to target: %s', target) net.render_netconfig_passthrough(target, netconfig=netcfg) else: ns = net.parse_net_config_data(netcfg.get('network', {})) if ns is None: return if not passthrough: LOG.info('Rendering network configuration in target') net.render_network_state(target=target, network_state=ns) _maybe_remove_legacy_eth0(target) _disable_ipv6_privacy_extensions(target) _patch_ifupdown_ipv6_mtu_hook(target)
def centos_apply_network_config(netcfg, target=None): """ CentOS images execute built-in curthooks which only supports simple networking configuration. This hook enables advanced network configuration via config passthrough to the target. """ def cloud_init_repo(version): if not version: raise ValueError('Missing required version parameter') return CLOUD_INIT_YUM_REPO_TEMPLATE % version if netcfg: LOG.info('Removing embedded network configuration (if present)') ifcfgs = glob.glob( util.target_path(target, 'etc/sysconfig/network-scripts') + '/ifcfg-*') # remove ifcfg-* (except ifcfg-lo) for ifcfg in ifcfgs: if os.path.basename(ifcfg) != "ifcfg-lo": util.del_file(ifcfg) LOG.info( 'Checking cloud-init in target [%s] for network ' 'configuration passthrough support.', target) passthrough = net.netconfig_passthrough_available(target) LOG.debug('passthrough available via in-target: %s', passthrough) # if in-target cloud-init is not updated, upgrade via cloud-init repo if not passthrough: cloud_init_yum_repo = (util.target_path( target, 'etc/yum.repos.d/curtin-cloud-init.repo')) # Inject cloud-init daily yum repo util.write_file(cloud_init_yum_repo, content=cloud_init_repo(rpm_get_dist_id(target))) # we separate the installation of repository packages (epel, # cloud-init-el-release) as we need a new invocation of yum # to read the newly installed repo files. YUM_CMD = ['yum', '-y', '--noplugins', 'install'] retries = [1] * 30 with util.ChrootableTarget(target) as in_chroot: # ensure up-to-date ca-certificates to handle https mirror # connections in_chroot.subp(YUM_CMD + ['ca-certificates'], capture=True, log_captured=True, retries=retries) in_chroot.subp(YUM_CMD + ['epel-release'], capture=True, log_captured=True, retries=retries) in_chroot.subp(YUM_CMD + ['cloud-init-el-release'], log_captured=True, capture=True, retries=retries) in_chroot.subp(YUM_CMD + ['cloud-init'], capture=True, log_captured=True, retries=retries) # remove cloud-init el-stable bootstrap repo config as the # cloud-init-el-release package points to the correct repo util.del_file(cloud_init_yum_repo) # install bridge-utils if needed with util.ChrootableTarget(target) as in_chroot: try: in_chroot.subp(['rpm', '-q', 'bridge-utils'], capture=False, rcs=[0]) except util.ProcessExecutionError: LOG.debug('Image missing bridge-utils package, installing') in_chroot.subp(YUM_CMD + ['bridge-utils'], capture=True, log_captured=True, retries=retries) LOG.info('Passing network configuration through to target') net.render_netconfig_passthrough(target, netconfig={'network': netcfg})