From fca0ea653538034c75dfa12ecf9161ebb21fc7a8 Mon Sep 17 00:00:00 2001 From: Oleksiy Molchanov Date: Tue, 14 Jul 2015 18:48:30 +0300 Subject: [PATCH] Add errors=panic to rootfs * Add errors=panic to rootfs in order to panic and not to go to 'ro' when there are any errors on the disk * Set parameter kernel.panic in sysctl to 60 (By default, the kernel will not reboot after a panic, but this option will cause a kernel reboot after 60 seconds.) Doc-Impact Change-Id: Ib24f13d3cbbf792e7ee81a9b4054e084f4ec1b5e Closes-Bug: 1371689 --- cloud-init-templates/boothook_centos.jinja2 | 2 + cloud-init-templates/boothook_ubuntu.jinja2 | 2 + fuel_agent/manager.py | 8 +- fuel_agent/tests/test_manager.py | 100 ++++++++++++++++++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/cloud-init-templates/boothook_centos.jinja2 b/cloud-init-templates/boothook_centos.jinja2 index 538d6563..b8dbe8fe 100644 --- a/cloud-init-templates/boothook_centos.jinja2 +++ b/cloud-init-templates/boothook_centos.jinja2 @@ -50,10 +50,12 @@ cloud-init-per instance conntrack_ipv4 /bin/sh -c 'echo nf_conntrack_ipv4 | tee cloud-init-per instance conntrack_ipv6 /bin/sh -c 'echo nf_conntrack_ipv6 | tee -a /etc/rc.modules' cloud-init-per instance chmod_rc_modules chmod +x /etc/rc.modules cloud-init-per instance conntrack_max /bin/sh -c 'echo "net.nf_conntrack_max=1048576" | tee -a /etc/sysctl.conf' +cloud-init-per instance kernel_panic /bin/sh -c 'echo "kernel.panic=60" | tee -a /etc/sysctl.conf' cloud-init-per instance conntrack_ipv4_load modprobe nf_conntrack_ipv4 cloud-init-per instance conntrack_ipv6_load modprobe nf_conntrack_ipv6 cloud-init-per instance conntrack_max_set sysctl -w "net.nf_conntrack_max=1048576" +cloud-init-per instance kernel_panic_set sysctl -w "kernel.panic=60" cloud-init-per instance mkdir_coredump mkdir -p /var/log/coredump cloud-init-per instance set_coredump /bin/sh -c 'echo -e "kernel.core_pattern=/var/log/coredump/core.%e.%p.%h.%t" | tee -a /etc/sysctl.conf' diff --git a/cloud-init-templates/boothook_ubuntu.jinja2 b/cloud-init-templates/boothook_ubuntu.jinja2 index 5a0be724..60bf6364 100644 --- a/cloud-init-templates/boothook_ubuntu.jinja2 +++ b/cloud-init-templates/boothook_ubuntu.jinja2 @@ -56,10 +56,12 @@ fi cloud-init-per instance conntrack_ipv4 /bin/sh -c 'echo nf_conntrack_ipv4 | tee -a /etc/modules' cloud-init-per instance conntrack_ipv6 /bin/sh -c 'echo nf_conntrack_ipv6 | tee -a /etc/modules' cloud-init-per instance conntrack_max /bin/sh -c 'echo "net.nf_conntrack_max=1048576" | tee -a /etc/sysctl.conf' +cloud-init-per instance kernel_panic /bin/sh -c 'echo "kernel.panic=60" | tee -a /etc/sysctl.conf' cloud-init-per instance conntrack_ipv4_load modprobe nf_conntrack_ipv4 cloud-init-per instance conntrack_ipv6_load modprobe nf_conntrack_ipv6 cloud-init-per instance conntrack_max_set sysctl -w "net.nf_conntrack_max=1048576" +cloud-init-per instance kernel_panic_set sysctl -w "kernel.panic=60" cloud-init-per instance dhclient /bin/sh -c 'echo "supersede routers 0;" | tee /etc/dhcp/dhclient.conf' diff --git a/fuel_agent/manager.py b/fuel_agent/manager.py index 052a7e27..600354c6 100644 --- a/fuel_agent/manager.py +++ b/fuel_agent/manager.py @@ -454,8 +454,12 @@ class Manager(object): # at fstab line. Currently we set it into 0 which means # a corresponding file system will never be checked. We assume # puppet or other configuration tool will care of it. - f.write('UUID=%s %s %s defaults 0 0\n' % - (mount2uuid[fs.mount], fs.mount, fs.type)) + if fs.mount == '/': + f.write('UUID=%s %s %s defaults,errors=panic 0 0\n' % + (mount2uuid[fs.mount], fs.mount, fs.type)) + else: + f.write('UUID=%s %s %s defaults 0 0\n' % + (mount2uuid[fs.mount], fs.mount, fs.type)) self.umount_target(chroot) diff --git a/fuel_agent/tests/test_manager.py b/fuel_agent/tests/test_manager.py index 04fd0b99..f78ee122 100644 --- a/fuel_agent/tests/test_manager.py +++ b/fuel_agent/tests/test_manager.py @@ -45,6 +45,106 @@ class TestManager(test_base.BaseTestCase): mock_lbd.return_value = test_nailgun.LIST_BLOCK_DEVICES_SAMPLE self.mgr = manager.Manager(test_nailgun.PROVISION_SAMPLE_DATA) + @mock.patch('fuel_agent.manager.open', + create=True, new_callable=mock.mock_open) + @mock.patch('fuel_agent.manager.gu', create=True) + @mock.patch('fuel_agent.manager.utils', create=True) + @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): + # actually covers only grub1 related logic + mock_utils.execute.return_value = ('fake_UUID\n', None) + mock_gu.guess_initrd.return_value = 'guessed_initrd' + mock_gu.guess_kernel.return_value = 'guessed_kernel' + mock_gu.guess_grub_version.return_value = 1 + self.mgr.do_bootloader() + mock_gu.guess_grub_version.assert_called_once_with( + chroot='/tmp/target') + mock_gu.grub1_cfg.assert_called_once_with( + kernel_params=' console=ttyS0,9600 console=tty0 rootdelay=90 ' + 'nomodeset root=UUID=fake_UUID ', + initrd='guessed_initrd', + chroot='/tmp/target', + kernel='guessed_kernel') + mock_gu.grub1_install.assert_called_once_with( + ['/dev/sda', '/dev/sdb', '/dev/sdc'], + '/dev/sda3', chroot='/tmp/target') + self.assertFalse(mock_gu.grub2_cfg.called) + self.assertFalse(mock_gu.grub2_install.called) + + @mock.patch('fuel_agent.manager.open', + create=True, new_callable=mock.mock_open) + @mock.patch('fuel_agent.manager.gu', create=True) + @mock.patch('fuel_agent.manager.utils', create=True) + @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): + # actually covers only grub2 related logic + mock_utils.execute.return_value = ('fake_UUID\n', None) + mock_gu.guess_grub_version.return_value = 2 + self.mgr.do_bootloader() + mock_gu.guess_grub_version.assert_called_once_with( + chroot='/tmp/target') + mock_gu.grub2_cfg.assert_called_once_with( + kernel_params=' console=ttyS0,9600 console=tty0 rootdelay=90 ' + 'nomodeset root=UUID=fake_UUID ', + chroot='/tmp/target') + mock_gu.grub2_install.assert_called_once_with( + ['/dev/sda', '/dev/sdb', '/dev/sdc'], + chroot='/tmp/target') + self.assertFalse(mock_gu.grub1_cfg.called) + self.assertFalse(mock_gu.grub1_install.called) + + @mock.patch('fuel_agent.manager.gu', create=True) + @mock.patch('fuel_agent.manager.utils', create=True) + @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): + # actually covers only write() calls + mock_utils.execute.return_value = ('fake_UUID\n', None) + with mock.patch('fuel_agent.manager.open', create=True) as mock_open: + 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', 'w'), + mock.call('/tmp/target/etc/udev/rules.d/75-persistent-net-' + 'generator.rules', 'w'), + mock.call('/tmp/target/etc/nailgun-agent/nodiscover', 'w'), + mock.call('/tmp/target/etc/fstab', 'wb')] + 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('UUID=fake_UUID / ext4 defaults,errors=panic 0 0\n'), + mock.call('UUID=fake_UUID swap swap defaults 0 0\n'), + mock.call('UUID=fake_UUID /var/lib/glance xfs defaults 0 0\n')] + self.assertEqual(expected_write_calls, + file_handle_mock.write.call_args_list) + mock_umount.assert_called_once_with('/tmp/target') + mock_mount.assert_called_once_with('/tmp/target') + mock_utils.makedirs_if_not_exists.assert_called_once_with( + '/tmp/target/etc/nailgun-agent') + @mock.patch('six.moves.builtins.open') @mock.patch.object(os, 'symlink') @mock.patch.object(os, 'remove')