Merge "Configure admin NIC prior the first system boot"

This commit is contained in:
Jenkins 2016-09-14 12:52:52 +00:00 committed by Gerrit Code Review
commit 62a7800e26
13 changed files with 263 additions and 202 deletions

View File

@ -15,22 +15,6 @@ cloud-init-per instance disable_selinux_on_the_fly setenforce 0
cloud-init-per instance disable_selinux sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/sysconfig/selinux
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 service network stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
cloud-init-per instance configure_admin_interface /bin/sh -c "echo -e \"# FROM COBBLER SNIPPET\nDEVICE=$ADMIN_IF\nIPADDR={{ common.admin_ip }}\nNETMASK={{ common.admin_mask }}\nBOOTPROTO=none\nONBOOT=yes\nUSERCTL=no\n\" | tee /etc/sysconfig/network-scripts/ifcfg-$ADMIN_IF"
cloud-init-per instance set_gateway /bin/sh -c 'echo GATEWAY="{{ common.gw }}" | tee -a /etc/sysconfig/network'
cloud-init-per instance udev_persistent_net5 service network start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_remove rm -f /etc/resolv.conf

View File

@ -15,22 +15,6 @@ cloud-init-per instance disable_selinux_on_the_fly setenforce 0
cloud-init-per instance disable_selinux sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/sysconfig/selinux
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 service network stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
cloud-init-per instance configure_admin_interface /bin/sh -c "echo -e \"# FROM COBBLER SNIPPET\nDEVICE=$ADMIN_IF\nIPADDR={{ common.admin_ip }}\nNETMASK={{ common.admin_mask }}\nBOOTPROTO=none\nONBOOT=yes\nUSERCTL=no\n\" | tee /etc/sysconfig/network-scripts/ifcfg-$ADMIN_IF"
cloud-init-per instance set_gateway /bin/sh -c 'echo GATEWAY="{{ common.gw }}" | tee -a /etc/sysconfig/network'
cloud-init-per instance udev_persistent_net5 service network start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_remove rm -f /etc/resolv.conf

View File

@ -12,26 +12,6 @@ function add_str_to_file_if_not_exists {
cloud-init-per instance wipe_sources_list_templates /bin/sh -c 'echo | tee /etc/cloud/templates/sources.list.ubuntu.tmpl'
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 /etc/init.d/networking stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
# Check if we do not already have static config (or interface seems unconfigured)
if [ ! -d "/etc/network/interfaces.d" ]; then
mkdir -p /etc/network/interfaces.d
echo 'source /etc/network/interfaces.d/*' > /etc/network/interfaces
fi
if [ ! -e "/etc/network/interfaces.d/ifcfg-$ADMIN_IF" ]; then
echo -e "auto $ADMIN_IF\niface $ADMIN_IF inet static\n\taddress {{ common.admin_ip }}\n\tnetmask {{ common.admin_mask }}\n\tgateway {{ common.gw }}" > /etc/network/interfaces.d/ifcfg-"$ADMIN_IF"
fi
cloud-init-per instance udev_persistent_net5 /etc/init.d/networking start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_mkdir mkdir -p /etc/resolvconf/resolv.conf.d

View File

@ -15,22 +15,6 @@ cloud-init-per instance disable_selinux_on_the_fly setenforce 0
cloud-init-per instance disable_selinux sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/sysconfig/selinux
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 service network stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
cloud-init-per instance configure_admin_interface /bin/sh -c "echo -e \"# FROM COBBLER SNIPPET\nDEVICE=$ADMIN_IF\nIPADDR={{ common.admin_ip }}\nNETMASK={{ common.admin_mask }}\nBOOTPROTO=none\nONBOOT=yes\nUSERCTL=no\n\" | tee /etc/sysconfig/network-scripts/ifcfg-$ADMIN_IF"
cloud-init-per instance set_gateway /bin/sh -c 'echo GATEWAY="{{ common.gw }}" | tee -a /etc/sysconfig/network'
cloud-init-per instance udev_persistent_net5 service network start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_remove rm -f /etc/resolv.conf

View File

@ -12,26 +12,6 @@ function add_str_to_file_if_not_exists {
cloud-init-per instance wipe_sources_list_templates /bin/sh -c 'echo | tee /etc/cloud/templates/sources.list.ubuntu.tmpl'
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 /etc/init.d/networking stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
# Check if we do not already have static config (or interface seems unconfigured)
if [ ! -d "/etc/network/interfaces.d" ]; then
mkdir -p /etc/network/interfaces.d
echo 'source /etc/network/interfaces.d/*' > /etc/network/interfaces
fi
if [ ! -e "/etc/network/interfaces.d/ifcfg-$ADMIN_IF" ]; then
echo -e "auto $ADMIN_IF\niface $ADMIN_IF inet static\n\taddress {{ common.admin_ip }}\n\tnetmask {{ common.admin_mask }}\n\tgateway {{ common.gw }}" > /etc/network/interfaces.d/ifcfg-"$ADMIN_IF"
fi
cloud-init-per instance udev_persistent_net5 /etc/init.d/networking start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_mkdir mkdir -p /etc/resolvconf/resolv.conf.d

View File

@ -12,26 +12,6 @@ function add_str_to_file_if_not_exists {
cloud-init-per instance wipe_sources_list_templates /bin/sh -c 'echo | tee /etc/cloud/templates/sources.list.ubuntu.tmpl'
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 /etc/init.d/networking stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
# Check if we do not already have static config (or interface seems unconfigured)
if [ ! -d "/etc/network/interfaces.d" ]; then
mkdir -p /etc/network/interfaces.d
echo 'source /etc/network/interfaces.d/*' > /etc/network/interfaces
fi
if [ ! -e "/etc/network/interfaces.d/ifcfg-$ADMIN_IF" ]; then
echo -e "auto $ADMIN_IF\niface $ADMIN_IF inet static\n\taddress {{ common.admin_ip }}\n\tnetmask {{ common.admin_mask }}\n\tgateway {{ common.gw }}" > /etc/network/interfaces.d/ifcfg-"$ADMIN_IF"
fi
cloud-init-per instance udev_persistent_net5 /etc/init.d/networking start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_mkdir mkdir -p /etc/resolvconf/resolv.conf.d

View File

@ -12,26 +12,6 @@ function add_str_to_file_if_not_exists {
cloud-init-per instance wipe_sources_list_templates /bin/sh -c 'echo | tee /etc/cloud/templates/sources.list.ubuntu.tmpl'
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 /etc/init.d/networking stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
# Check if we do not already have static config (or interface seems unconfigured)
if [ ! -d "/etc/network/interfaces.d" ]; then
mkdir -p /etc/network/interfaces.d
echo 'source /etc/network/interfaces.d/*' > /etc/network/interfaces
fi
if [ ! -e "/etc/network/interfaces.d/ifcfg-$ADMIN_IF" ]; then
echo -e "auto $ADMIN_IF\niface $ADMIN_IF inet static\n\taddress {{ common.admin_ip }}\n\tnetmask {{ common.admin_mask }}\n\tgateway {{ common.gw }}" > /etc/network/interfaces.d/ifcfg-"$ADMIN_IF"
fi
cloud-init-per instance udev_persistent_net5 /etc/init.d/networking start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_mkdir mkdir -p /etc/resolvconf/resolv.conf.d
@ -96,4 +76,4 @@ cloud-init-per instance skel_bash cp -f /etc/skel/.bash* /root/
cloud-init-per instance hiera_puppet mkdir -p /etc/puppet /var/lib/hiera
cloud-init-per instance touch_puppet touch /var/lib/hiera/common.yaml /etc/puppet/hiera.yaml /var/log/puppet.log
cloud-init-per instance chmod_puppet chmod 600 /var/log/puppet.log
cloud-init-per instance chmod_puppet chmod 600 /var/log/puppet.log

View File

@ -12,26 +12,6 @@ function add_str_to_file_if_not_exists {
cloud-init-per instance wipe_sources_list_templates /bin/sh -c 'echo | tee /etc/cloud/templates/sources.list.ubuntu.tmpl'
# configure udev rules
# udev persistent net
cloud-init-per instance udev_persistent_net1 /etc/init.d/networking stop
ADMIN_MAC={{ common.admin_mac }}
ADMIN_IF=$(echo {{ common.udevrules }} | sed 's/[,=]/\n/g' | grep "$ADMIN_MAC" | cut -d_ -f2 | head -1)
# Check if we do not already have static config (or interface seems unconfigured)
if [ ! -d "/etc/network/interfaces.d" ]; then
mkdir -p /etc/network/interfaces.d
echo 'source /etc/network/interfaces.d/*' > /etc/network/interfaces
fi
if [ ! -e "/etc/network/interfaces.d/ifcfg-$ADMIN_IF" ]; then
echo -e "auto $ADMIN_IF\niface $ADMIN_IF inet static\n\taddress {{ common.admin_ip }}\n\tnetmask {{ common.admin_mask }}\n\tgateway {{ common.gw }}" > /etc/network/interfaces.d/ifcfg-"$ADMIN_IF"
fi
cloud-init-per instance udev_persistent_net5 /etc/init.d/networking start
# end of udev
#FIXME(agordeev): if operator updates dns settings on masternode after the node had been provisioned,
# cloud-init will start to generate resolv.conf with non-actual data
cloud-init-per instance resolv_conf_mkdir mkdir -p /etc/resolvconf/resolv.conf.d

View File

@ -182,3 +182,7 @@ class WrongOutputContainer(BaseError):
class BootstrapFileAlreadyExists(BaseError):
pass
class UnsupportedNetworkConfiguration(BaseError):
pass

View File

@ -32,6 +32,7 @@ from fuel_agent.utils import hardware as hw
from fuel_agent.utils import lvm as lu
from fuel_agent.utils import md as mu
from fuel_agent.utils import partition as pu
from fuel_agent.utils import provision
from fuel_agent.utils import utils
opts = [
@ -922,31 +923,19 @@ class Manager(object):
gu.grub2_install(install_devices, chroot=chroot)
if CONF.fix_udev_net_rules:
# FIXME(agordeev) There's no convenient way to perfrom NIC
# remapping in Ubuntu, so injecting files prior the first boot
# should work
with open(chroot + '/etc/udev/rules.d/70-persistent-net.rules',
'wt', encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning: '
u'BEGIN\n')
# pattern is aa:bb:cc:dd:ee:ff_eth0,aa:bb:cc:dd:ee:ff_eth1
for mapping in self.driver.configdrive_scheme. \
common.udevrules.split(','):
mac_addr, nic_name = mapping.split('_')
f.write(u'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
u'ATTR{address}=="%s", ATTR{type}=="1", '
u'KERNEL=="eth*", NAME="%s"\n' % (mac_addr,
nic_name))
f.write(
u'# Generated by fuel-agent during provisioning: END\n')
# FIXME(agordeev): Disable net-generator that will add new etries
# to 70-persistent-net.rules
with open(chroot + '/etc/udev/rules.d/'
'75-persistent-net-generator.rules', 'wt',
encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning:\n'
u'# DO NOT DELETE. It is needed to disable '
u'net-generator\n')
provision.udev_nic_naming_rules(
chroot, self.driver.configdrive_scheme.common.udevrules)
if CONF.prepare_configdrive:
# FIXME(agordeev): Normally, that should be handled out side of
# fuel-agent. Just a temporary fix to avoid dealing with cloud-init
# boothooks.
provision.configure_admin_nic(
chroot=chroot,
iface=self.driver.configdrive_scheme.common.admin_iface_name,
ip=self.driver.configdrive_scheme.common.admin_ip,
netmask=self.driver.configdrive_scheme.common.admin_mask,
gw=self.driver.configdrive_scheme.common.gw)
# FIXME(kozhukalov): Prevent nailgun-agent from doing anything.
# This ugly hack is to be used together with the command removing

View File

@ -61,6 +61,7 @@ class TestManager(unittest2.TestCase):
mock_lbd.return_value = test_nailgun.LIST_BLOCK_DEVICES_SAMPLE
self.mgr = manager.Manager(test_nailgun.PROVISION_SAMPLE_DATA)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -72,7 +73,8 @@ class TestManager(unittest2.TestCase):
def test_do_bootloader_grub1_kernel_initrd_guessed(self, mock_umount,
mock_mount, mock_utils,
mock_gu, mock_open,
mock_bu, mock_hw):
mock_bu, mock_hw,
mock_prov):
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('', '')
mock_gu.guess_grub_version.return_value = 1
@ -99,6 +101,7 @@ class TestManager(unittest2.TestCase):
mock_gu.guess_kernel.assert_called_once_with(
regexp='fake_kernel_regexp', chroot='/tmp/target')
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -110,7 +113,8 @@ class TestManager(unittest2.TestCase):
def test_do_bootloader_grub1_kernel_initrd_set(self, mock_umount,
mock_mount, mock_utils,
mock_gu, mock_open,
mock_bu, mock_hw):
mock_bu, mock_hw,
mock_prov):
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('', '')
mock_gu.guess_grub_version.return_value = 1
@ -132,6 +136,7 @@ class TestManager(unittest2.TestCase):
self.assertFalse(mock_gu.guess_kernel.called)
self.assertFalse(mock_bu.override_lvm_config.called)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.objects.bootloader.Grub', autospec=True)
@ -143,7 +148,7 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_rootfs_uuid(self, mock_umount, mock_mount,
mock_utils, mock_gu, mock_open,
mock_grub, mock_bu, mock_hw):
mock_grub, mock_bu, mock_hw, mock_prov):
def _fake_uuid(*args, **kwargs):
if len(args) >= 8 and args[7] == '/dev/mapper/os-root':
return ('FAKE_ROOTFS_UUID', None)
@ -179,6 +184,7 @@ class TestManager(unittest2.TestCase):
self.assertRaises(errors.WrongPartitionSchemeError,
self.mgr.do_bootloader)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -189,7 +195,7 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_grub_version_changes(
self, mock_umount, mock_mount, mock_utils, mock_gu, mock_open,
mock_bu, mock_hw):
mock_bu, mock_hw, mock_prov):
# actually covers only grub1 related logic
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('fake_UUID\n', None)
@ -199,6 +205,7 @@ class TestManager(unittest2.TestCase):
chroot='/tmp/target')
self.assertEqual('expected_version', self.mgr.driver.grub.version)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -208,7 +215,8 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'mount_target')
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_grub1(self, mock_umount, mock_mount, mock_utils,
mock_gu, mock_open, mock_bu, mock_hw):
mock_gu, mock_open, mock_bu, mock_hw,
mock_prov):
# actually covers only grub1 related logic
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('fake_UUID\n', None)
@ -231,6 +239,7 @@ class TestManager(unittest2.TestCase):
self.assertFalse(mock_gu.grub2_cfg.called)
self.assertFalse(mock_gu.grub2_install.called)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -240,7 +249,8 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'mount_target')
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_grub2(self, mock_umount, mock_mount, mock_utils,
mock_gu, mock_open, mock_bu, mock_hw):
mock_gu, mock_open, mock_bu, mock_hw,
mock_prov):
# actually covers only grub2 related logic
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('fake_UUID\n', None)
@ -258,6 +268,7 @@ class TestManager(unittest2.TestCase):
self.assertFalse(mock_gu.grub1_cfg.called)
self.assertFalse(mock_gu.grub1_install.called)
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.open',
@ -268,7 +279,7 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_with_multipath(
self, mock_umount, mock_mount, mock_utils, mock_gu, mock_open,
mock_bu, mock_hw):
mock_bu, mock_hw, mock_prov):
# actually covers only multipath related logic
# Lets assume that only /dev/sda device is not-multipath
mock_hw.is_multipath_device.side_effect = False, False, True
@ -294,6 +305,7 @@ class TestManager(unittest2.TestCase):
update_initramfs=True,
lvm_conf_path='/etc/lvm/lvm.conf')
@mock.patch('fuel_agent.manager.provision', autospec=True)
@mock.patch('fuel_agent.manager.hw', autospec=True)
@mock.patch('fuel_agent.manager.bu', autospec=True)
@mock.patch('fuel_agent.manager.gu', create=True)
@ -301,7 +313,7 @@ class TestManager(unittest2.TestCase):
@mock.patch.object(manager.Manager, 'mount_target')
@mock.patch.object(manager.Manager, 'umount_target')
def test_do_bootloader_writes(self, mock_umount, mock_mount, mock_utils,
mock_gu, mock_bu, mock_hw):
mock_gu, mock_bu, mock_hw, mock_prov):
# actually covers only write() calls
mock_hw.is_multipath_device.return_value = False
mock_utils.execute.return_value = ('fake_UUID\n', None)
@ -309,30 +321,10 @@ class TestManager(unittest2.TestCase):
file_handle_mock = mock_open.return_value.__enter__.return_value
self.mgr.do_bootloader()
expected_open_calls = [
mock.call('/tmp/target/etc/udev/rules.d/70-persistent-net.'
'rules', 'wt', encoding='utf-8'),
mock.call('/tmp/target/etc/udev/rules.d/75-persistent-net-'
'generator.rules', 'wt', encoding='utf-8'),
mock.call('/tmp/target/etc/nailgun-agent/nodiscover', 'w'),
mock.call('/tmp/target/etc/fstab', 'wt', encoding='utf-8')]
self.assertEqual(expected_open_calls, mock_open.call_args_list)
expected_write_calls = [
mock.call('# Generated by fuel-agent during provisioning: '
'BEGIN\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:79:da:80", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth0"\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:46:43:60", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth1"\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:b1:d7:15", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth2"\n'),
mock.call('# Generated by fuel-agent during provisioning: '
'END\n'),
mock.call('# Generated by fuel-agent during provisioning:\n# '
'DO NOT DELETE. It is needed to disable '
'net-generator\n'),
mock.call('UUID=fake_UUID /boot ext2 defaults 0 0\n'),
mock.call('UUID=fake_UUID /tmp ext2 defaults 0 0\n'),
mock.call(
@ -346,6 +338,14 @@ class TestManager(unittest2.TestCase):
mock_mount.assert_called_once_with('/tmp/target')
mock_utils.makedirs_if_not_exists.assert_called_once_with(
'/tmp/target/etc/nailgun-agent')
mock_prov.udev_nic_naming_rules.assert_called_once_with(
'/tmp/target', self.mgr.driver.configdrive_scheme.common.udevrules)
mock_prov.configure_admin_nic.assert_called_once_with(
chroot='/tmp/target',
iface=self.mgr.driver.configdrive_scheme.common.admin_iface_name,
ip=self.mgr.driver.configdrive_scheme.common.admin_ip,
netmask=self.mgr.driver.configdrive_scheme.common.admin_mask,
gw=self.mgr.driver.configdrive_scheme.common.gw)
@mock.patch('fuel_agent.drivers.nailgun.Nailgun.parse_image_meta',
return_value={})

View File

@ -0,0 +1,116 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
import unittest2
from fuel_agent import errors
from fuel_agent.utils import provision
class TestProvisionUtils(unittest2.TestCase):
def test_udev_nic_naming_rules(self):
udevrules = "08:00:27:79:da:80_eth0,08:00:27:46:43:60_eth1,"\
"08:00:27:b1:d7:15_eth2"
with mock.patch.object(provision, 'open', create=True) as mock_open:
file_handle_mock = mock_open.return_value.__enter__.return_value
provision.udev_nic_naming_rules('/tmp/target', udevrules)
expected_open_calls = [
mock.call('/tmp/target/etc/udev/rules.d/70-persistent-net.'
'rules', 'wt', encoding='utf-8'),
mock.call('/tmp/target/etc/udev/rules.d/75-persistent-net-'
'generator.rules', 'wt', encoding='utf-8')]
self.assertEqual(expected_open_calls, mock_open.call_args_list)
expected_write_calls = [
mock.call('# Generated by fuel-agent during provisioning: '
'BEGIN\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:79:da:80", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth0"\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:46:43:60", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth1"\n'),
mock.call('SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
'ATTR{address}=="08:00:27:b1:d7:15", ATTR{type}=="1"'
', KERNEL=="eth*", NAME="eth2"\n'),
mock.call('# Generated by fuel-agent during provisioning: '
'END\n'),
mock.call('# Generated by fuel-agent during provisioning:\n# '
'DO NOT DELETE. It is needed to disable '
'net-generator\n'),
]
self.assertEqual(expected_write_calls,
file_handle_mock.write.call_args_list)
@mock.patch.object(provision, 'os', autospec=True)
def test_configure_admin_nic_failed(self, mock_os):
mock_os.path.exists.return_value = False
self.assertRaises(errors.UnsupportedNetworkConfiguration,
provision.configure_admin_nic,
'chroot', 'iface', 'ip', 'netmask', 'gw')
self.assertEqual([mock.call('chroot/etc/network/interfaces'),
mock.call('chroot/etc/sysconfig/network-scripts')],
mock_os.path.exists.call_args_list)
@mock.patch.object(provision, 'utils', autospec=True)
def test_configure_admin_nic_ubuntu(self, mock_utils):
with mock.patch.object(provision, 'open', create=True) as mock_open:
file_handle_mock = mock_open.return_value.__enter__.return_value
provision.configure_admin_nic_ubuntu(
'/tmp/target', 'IFACE', 'IP', 'NETMASK', 'GW')
expected_open_calls = [
mock.call('/tmp/target/etc/network/interfaces',
'wt', encoding='utf-8'),
mock.call('/tmp/target/etc/network/interfaces.d/ifcfg-IFACE',
'wt', encoding='utf-8')]
self.assertEqual(expected_open_calls, mock_open.call_args_list)
expected_write_calls = [
mock.call(u'# Generated by fuel-agent during provisioning:\n'
u'source-directory /etc/network/interfaces.d\n'),
mock.call(u'# Generated by fuel-agent during provisioning:\n'
u'auto IFACE\n'
u'iface IFACE inet static\n'
u'\taddress IP\n'
u'\tnetmask NETMASK\n'
u'\tgateway GW\n'),
]
self.assertEqual(expected_write_calls,
file_handle_mock.write.call_args_list)
@mock.patch.object(provision, 'utils', autospec=True)
def test_configure_admin_nic_centos(self, mock_utils):
with mock.patch.object(provision, 'open', create=True) as mock_open:
file_handle_mock = mock_open.return_value.__enter__.return_value
provision.configure_admin_nic_centos(
'/tmp/target', 'IFACE', 'IP', 'NETMASK', 'GW')
expected_open_calls = [
mock.call('/tmp/target/etc/sysconfig/network-scripts/'
'ifcfg-IFACE',
'wt', encoding='utf-8'),
mock.call('/tmp/target/etc/sysconfig/network',
'at', encoding='utf-8')]
self.assertEqual(expected_open_calls, mock_open.call_args_list)
expected_write_calls = [
mock.call(u'# Generated by fuel-agent during provisioning:\n'
u'DEVICE=IFACE\n'
u'IPADDR=IP\n'
u'NETMASK=NETMASK\n'
u'BOOTPROTO=none\n'
u'ONBOOT=yes\n'
u'USERCTL=no\n'),
mock.call(u'GATEWAY="GW"\n'),
]
self.assertEqual(expected_write_calls,
file_handle_mock.write.call_args_list)

View File

@ -0,0 +1,100 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from io import open
import os
from oslo_log import log as logging
from fuel_agent import errors
from fuel_agent.utils import utils
LOG = logging.getLogger(__name__)
def udev_nic_naming_rules(chroot, udevrules):
"""Generates NIC naming rules for udev.
Expected string formatting: "(macaddrX)_(nicX)" comma separated.
Eg.: "08:00:27:79:da:80_eth0,08:00:27:46:43:60_eth1"
"""
# FIXME(agordeev) There's no convenient way to perfrom NIC
# remapping in Ubuntu, so injecting files prior the first boot
# should work
with open(chroot + '/etc/udev/rules.d/70-persistent-net.rules',
'wt', encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning: '
u'BEGIN\n')
# pattern is aa:bb:cc:dd:ee:ff_eth0,aa:bb:cc:dd:ee:ff_eth1
for mapping in udevrules.split(','):
mac_addr, nic_name = mapping.split('_')
f.write(u'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", '
u'ATTR{address}=="%s", ATTR{type}=="1", '
u'KERNEL=="eth*", NAME="%s"\n' % (mac_addr,
nic_name))
f.write(
u'# Generated by fuel-agent during provisioning: END\n')
# FIXME(agordeev): Disable net-generator that will add new entries
# to 70-persistent-net.rules
with open(chroot + '/etc/udev/rules.d/'
'75-persistent-net-generator.rules', 'wt',
encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning:\n'
u'# DO NOT DELETE. It is needed to disable '
u'net-generator\n')
def configure_admin_nic(chroot, iface, ip, netmask, gw):
debian_conf = '/etc/network/interfaces'
redhat_conf = '/etc/sysconfig/network-scripts'
if os.path.exists(chroot + debian_conf):
configure_admin_nic_ubuntu(chroot, iface, ip, netmask, gw)
elif os.path.exists(chroot + redhat_conf):
configure_admin_nic_centos(chroot, iface, ip, netmask, gw)
else:
raise errors.UnsupportedNetworkConfiguration(
"Can't find suitable configuration files for admin NIC")
def configure_admin_nic_ubuntu(chroot, iface, ip, netmask, gw):
ifaces_dir = '/etc/network/interfaces.d'
ifcfg_path = os.path.join(ifaces_dir, 'ifcfg-{0}'.format(iface))
utils.makedirs_if_not_exists(ifaces_dir)
with open(chroot + '/etc/network/interfaces', 'wt', encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning:\n'
u'source-directory /etc/network/interfaces.d\n')
with open(chroot + ifcfg_path, 'wt', encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning:\n'
u'auto {iface}\n'
u'iface {iface} inet static\n'
u'\taddress {ip}\n'
u'\tnetmask {netmask}\n'
u'\tgateway {gw}\n'.format(iface=iface,
ip=ip,
netmask=netmask,
gw=gw))
def configure_admin_nic_centos(chroot, iface, ip, netmask, gw):
ifcfg_path = '/etc/sysconfig/network-scripts/ifcfg-{0}'.format(iface)
with open(chroot + ifcfg_path, 'wt', encoding='utf-8') as f:
f.write(u'# Generated by fuel-agent during provisioning:\n'
u'DEVICE={iface}\n'
u'IPADDR={ip}\n'
u'NETMASK={netmask}\n'
u'BOOTPROTO=none\n'
u'ONBOOT=yes\n'
u'USERCTL=no\n'.format(iface=iface, ip=ip, netmask=netmask))
with open(chroot + '/etc/sysconfig/network', 'at', encoding='utf-8') as f:
f.write(u'GATEWAY="{gw}"\n'.format(gw=gw))