Add bootloader do_action
Partially implements blueprint: pluggable-do-actions Change-Id: I92c8864dc3021b04d0d0f898198007176a1e92fe
This commit is contained in:
parent
981a3e9023
commit
478e4c149d
182
bareon/actions/bootloader.py
Normal file
182
bareon/actions/bootloader.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
# 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_config import cfg
|
||||||
|
|
||||||
|
from bareon.actions import base
|
||||||
|
from bareon.drivers.deploy import mixins
|
||||||
|
from bareon import errors
|
||||||
|
from bareon.openstack.common import log as logging
|
||||||
|
from bareon.utils import grub as gu
|
||||||
|
from bareon.utils import utils
|
||||||
|
|
||||||
|
opts = [
|
||||||
|
cfg.IntOpt(
|
||||||
|
'grub_timeout',
|
||||||
|
default=5,
|
||||||
|
help='Timeout in secs for GRUB'
|
||||||
|
),
|
||||||
|
cfg.BoolOpt(
|
||||||
|
'fix_udev_net_rules',
|
||||||
|
default=True,
|
||||||
|
help='Add udev rules for NIC remapping'
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.register_opts(opts)
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(agordeev): rename to GrubBootLoaderAction ?
|
||||||
|
class BootLoaderAction(base.BaseAction, mixins.MountableMixin):
|
||||||
|
"""BootLoaderAction
|
||||||
|
|
||||||
|
installs and configures bootloader
|
||||||
|
"""
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
# TODO(agordeev): implement validate for bootloader
|
||||||
|
pass
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
self.do_bootloader()
|
||||||
|
|
||||||
|
def do_bootloader(self):
|
||||||
|
LOG.debug('--- Installing bootloader (do_bootloader) ---')
|
||||||
|
chroot = '/tmp/target'
|
||||||
|
partition_scheme = self.driver.partition_scheme
|
||||||
|
with self.mount_target(chroot):
|
||||||
|
mount2uuid = {}
|
||||||
|
for fs in partition_scheme.fss:
|
||||||
|
mount2uuid[fs.mount] = utils.execute(
|
||||||
|
'blkid', '-o', 'value', '-s', 'UUID', fs.device,
|
||||||
|
check_exit_code=[0])[0].strip()
|
||||||
|
|
||||||
|
if '/' not in mount2uuid:
|
||||||
|
raise errors.WrongPartitionSchemeError(
|
||||||
|
'Error: device with / mountpoint has not been found')
|
||||||
|
|
||||||
|
grub = self.driver.grub
|
||||||
|
|
||||||
|
guessed_version = gu.guess_grub_version(chroot=chroot)
|
||||||
|
if guessed_version != grub.version:
|
||||||
|
grub.version = guessed_version
|
||||||
|
LOG.warning('Grub version differs from which the operating '
|
||||||
|
'system should have by default. Found version in '
|
||||||
|
'image: %s', guessed_version)
|
||||||
|
boot_device = partition_scheme.boot_device(grub.version)
|
||||||
|
install_devices = [d.name for d in partition_scheme.parteds
|
||||||
|
if d.install_bootloader]
|
||||||
|
|
||||||
|
grub.append_kernel_params('root=UUID=%s ' % mount2uuid['/'])
|
||||||
|
|
||||||
|
kernel = grub.kernel_name or \
|
||||||
|
gu.guess_kernel(chroot=chroot, regexp=grub.kernel_regexp)
|
||||||
|
|
||||||
|
initrd = grub.initrd_name or \
|
||||||
|
gu.guess_initrd(chroot=chroot, regexp=grub.initrd_regexp)
|
||||||
|
|
||||||
|
if grub.version == 1:
|
||||||
|
gu.grub1_cfg(kernel=kernel, initrd=initrd,
|
||||||
|
kernel_params=grub.kernel_params, chroot=chroot,
|
||||||
|
grub_timeout=CONF.grub_timeout)
|
||||||
|
gu.grub1_install(install_devices, boot_device, chroot=chroot)
|
||||||
|
else:
|
||||||
|
# TODO(kozhukalov): implement which kernel to use by default
|
||||||
|
# Currently only grub1_cfg accepts kernel and initrd
|
||||||
|
# parameters.
|
||||||
|
gu.grub2_cfg(kernel_params=grub.kernel_params, chroot=chroot,
|
||||||
|
grub_timeout=CONF.grub_timeout)
|
||||||
|
gu.grub2_install(install_devices, chroot=chroot)
|
||||||
|
|
||||||
|
# TODO(agordeev): move to separate actions?
|
||||||
|
|
||||||
|
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 bareon 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", '
|
||||||
|
u'DRIVERS=="?*", ATTR{address}=="%s", '
|
||||||
|
u'ATTR{type}=="1", KERNEL=="eth*", '
|
||||||
|
u'NAME="%s"\n' % (mac_addr, nic_name))
|
||||||
|
f.write(
|
||||||
|
u'# Generated by bareon during provisioning: END\n')
|
||||||
|
# FIXME(agordeev): Disable net-generator that adds 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 bareon during provisioning:\n'
|
||||||
|
u'# DO NOT DELETE. It is needed to disable '
|
||||||
|
u'net-generator\n')
|
||||||
|
|
||||||
|
# FIXME(kozhukalov): Prevent nailgun-agent from doing anything.
|
||||||
|
# This ugly hack is to be used together with the command removing
|
||||||
|
# this lock file not earlier than /etc/rc.local
|
||||||
|
# The reason for this hack to appear is to prevent nailgun-agent
|
||||||
|
# from changing mcollective config at the same time when cloud-init
|
||||||
|
# does the same. Otherwise, we can end up with corrupted
|
||||||
|
# mcollective config.
|
||||||
|
# For details see https://bugs.launchpad.net/fuel/+bug/1449186
|
||||||
|
LOG.debug('Preventing nailgun-agent from doing '
|
||||||
|
'anything until it is unlocked')
|
||||||
|
utils.makedirs_if_not_exists(os.path.join(chroot,
|
||||||
|
'etc/nailgun-agent'))
|
||||||
|
with open(os.path.join(chroot, 'etc/nailgun-agent/nodiscover'),
|
||||||
|
'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# FIXME(kozhukalov): When we have just os-root fs image and don't
|
||||||
|
# have os-var-log fs image while / and /var/log are supposed to be
|
||||||
|
# separate file systems and os-var-log is mounted into
|
||||||
|
# non-empty directory on the / file system, those files in /var/log
|
||||||
|
# directory become unavailable.
|
||||||
|
# The thing is that among those file there is /var/log/upstart
|
||||||
|
# where upstart daemon writes its logs. We have specific upstart
|
||||||
|
# job which is to flush open files once all file systems are
|
||||||
|
# mounted.
|
||||||
|
# This job needs upstart directory to be available on os-var-log
|
||||||
|
# file system.
|
||||||
|
# This is just a temporary fix and correct fix will be available
|
||||||
|
# soon via updates.
|
||||||
|
utils.execute('mkdir', '-p', chroot + '/var/log/upstart')
|
||||||
|
|
||||||
|
with open(chroot + '/etc/fstab', 'wt', encoding='utf-8') as f:
|
||||||
|
for fs in self.driver.partition_scheme.fss:
|
||||||
|
# TODO(kozhukalov): Think of improving the logic so as to
|
||||||
|
# insert a meaningful fsck order value which is last zero
|
||||||
|
# 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.
|
||||||
|
if fs.mount == '/':
|
||||||
|
f.write(u'UUID=%s %s %s defaults,errors=panic 0 0\n' %
|
||||||
|
(mount2uuid[fs.mount], fs.mount, fs.type))
|
||||||
|
else:
|
||||||
|
f.write(u'UUID=%s %s %s defaults 0 0\n' %
|
||||||
|
(mount2uuid[fs.mount], fs.mount, fs.type))
|
@ -28,7 +28,8 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class MountableMixin(object):
|
class MountableMixin(object):
|
||||||
|
|
||||||
def _mount_target(self, mount_dir, os_id, pseudo=True, treat_mtab=True):
|
def _mount_target(self, mount_dir, os_id=None, pseudo=True,
|
||||||
|
treat_mtab=True):
|
||||||
LOG.debug('Mounting target file systems: %s', mount_dir)
|
LOG.debug('Mounting target file systems: %s', mount_dir)
|
||||||
# Here we are going to mount all file systems in partition schema.
|
# Here we are going to mount all file systems in partition schema.
|
||||||
for fs in self.driver.partition_scheme.fs_sorted_by_depth(os_id):
|
for fs in self.driver.partition_scheme.fs_sorted_by_depth(os_id):
|
||||||
@ -53,10 +54,11 @@ class MountableMixin(object):
|
|||||||
with open(mtab_path, 'wb') as f:
|
with open(mtab_path, 'wb') as f:
|
||||||
f.write(mtab)
|
f.write(mtab)
|
||||||
|
|
||||||
def _umount_target(self, mount_dir, os_id, pseudo=True):
|
def _umount_target(self, mount_dir, os_id=None, pseudo=True):
|
||||||
LOG.debug('Umounting target file systems: %s', mount_dir)
|
LOG.debug('Umounting target file systems: %s', mount_dir)
|
||||||
if pseudo:
|
if pseudo:
|
||||||
for path in ('/proc', '/dev', '/sys'):
|
# umount fusectl (typically mounted at /sys/fs/fuse/connections)
|
||||||
|
for path in ('/proc', '/dev', '/sys/fs/fuse/connections', '/sys'):
|
||||||
fu.umount_fs(os.path.join(mount_dir, path.strip(os.sep)),
|
fu.umount_fs(os.path.join(mount_dir, path.strip(os.sep)),
|
||||||
try_lazy_umount=True)
|
try_lazy_umount=True)
|
||||||
for fs in self.driver.partition_scheme.fs_sorted_by_depth(os_id,
|
for fs in self.driver.partition_scheme.fs_sorted_by_depth(os_id,
|
||||||
@ -66,13 +68,14 @@ class MountableMixin(object):
|
|||||||
fu.umount_fs(os.path.join(mount_dir, fs.mount.strip(os.sep)))
|
fu.umount_fs(os.path.join(mount_dir, fs.mount.strip(os.sep)))
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def mount_target(self, mount_dir, os_id, pseudo=True, treat_mtab=True):
|
def mount_target(self, mount_dir, os_id=None, pseudo=True,
|
||||||
self._mount_target(mount_dir, os_id, pseudo=pseudo,
|
treat_mtab=True):
|
||||||
|
self._mount_target(mount_dir, os_id=os_id, pseudo=pseudo,
|
||||||
treat_mtab=treat_mtab)
|
treat_mtab=treat_mtab)
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
self._umount_target(mount_dir, os_id, pseudo)
|
self._umount_target(mount_dir, os_id=os_id, pseudo=pseudo)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _mount_bootloader(self, mount_dir):
|
def _mount_bootloader(self, mount_dir):
|
||||||
|
@ -21,6 +21,7 @@ from oslo_config import cfg
|
|||||||
import six
|
import six
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from bareon.actions import bootloader
|
||||||
from bareon.actions import configdrive
|
from bareon.actions import configdrive
|
||||||
from bareon.actions import copyimage
|
from bareon.actions import copyimage
|
||||||
from bareon.actions import partitioning
|
from bareon.actions import partitioning
|
||||||
@ -29,7 +30,6 @@ from bareon import errors
|
|||||||
from bareon.openstack.common import log as logging
|
from bareon.openstack.common import log as logging
|
||||||
from bareon.utils import build as bu
|
from bareon.utils import build as bu
|
||||||
from bareon.utils import fs as fu
|
from bareon.utils import fs as fu
|
||||||
from bareon.utils import grub as gu
|
|
||||||
from bareon.utils import utils
|
from bareon.utils import utils
|
||||||
|
|
||||||
opts = [
|
opts = [
|
||||||
@ -132,6 +132,9 @@ class Manager(BaseDeployDriver):
|
|||||||
def do_copyimage(self):
|
def do_copyimage(self):
|
||||||
copyimage.CopyImageAction(self.driver).execute()
|
copyimage.CopyImageAction(self.driver).execute()
|
||||||
|
|
||||||
|
def do_bootloader(self):
|
||||||
|
bootloader.BootLoaderAction(self.driver).execute()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _update_metadata_with_repos(metadata, repos):
|
def _update_metadata_with_repos(metadata, repos):
|
||||||
"""Update action metadata with information about repositories
|
"""Update action metadata with information about repositories
|
||||||
@ -394,123 +397,6 @@ class Manager(BaseDeployDriver):
|
|||||||
with open(meta_file, 'wt') as f:
|
with open(meta_file, 'wt') as f:
|
||||||
yaml.safe_dump(drop_data, stream=f, encoding='utf-8')
|
yaml.safe_dump(drop_data, stream=f, encoding='utf-8')
|
||||||
|
|
||||||
def do_bootloader(self):
|
|
||||||
LOG.debug('--- Installing bootloader (do_bootloader) ---')
|
|
||||||
chroot = '/tmp/target'
|
|
||||||
self.mount_target(chroot)
|
|
||||||
|
|
||||||
mount2uuid = {}
|
|
||||||
for fs in self.driver.partition_scheme.fss:
|
|
||||||
mount2uuid[fs.mount] = utils.execute(
|
|
||||||
'blkid', '-o', 'value', '-s', 'UUID', fs.device,
|
|
||||||
check_exit_code=[0])[0].strip()
|
|
||||||
|
|
||||||
if '/' not in mount2uuid:
|
|
||||||
raise errors.WrongPartitionSchemeError(
|
|
||||||
'Error: device with / mountpoint has not been found')
|
|
||||||
|
|
||||||
grub = self.driver.grub
|
|
||||||
|
|
||||||
guessed_version = gu.guess_grub_version(chroot=chroot)
|
|
||||||
if guessed_version != grub.version:
|
|
||||||
grub.version = guessed_version
|
|
||||||
LOG.warning('Grub version differs from which the operating system '
|
|
||||||
'should have by default. Found version in image: '
|
|
||||||
'{0}'.format(guessed_version))
|
|
||||||
boot_device = self.driver.partition_scheme.boot_device(grub.version)
|
|
||||||
install_devices = [d.name for d in self.driver.partition_scheme.parteds
|
|
||||||
if d.install_bootloader]
|
|
||||||
|
|
||||||
grub.append_kernel_params('root=UUID=%s ' % mount2uuid['/'])
|
|
||||||
|
|
||||||
kernel = grub.kernel_name or gu.guess_kernel(chroot=chroot,
|
|
||||||
regexp=grub.kernel_regexp)
|
|
||||||
|
|
||||||
initrd = grub.initrd_name or gu.guess_initrd(chroot=chroot,
|
|
||||||
regexp=grub.initrd_regexp)
|
|
||||||
|
|
||||||
if grub.version == 1:
|
|
||||||
gu.grub1_cfg(kernel=kernel, initrd=initrd,
|
|
||||||
kernel_params=grub.kernel_params, chroot=chroot,
|
|
||||||
grub_timeout=CONF.grub_timeout)
|
|
||||||
gu.grub1_install(install_devices, boot_device, chroot=chroot)
|
|
||||||
else:
|
|
||||||
# TODO(kozhukalov): implement which kernel to use by default
|
|
||||||
# Currently only grub1_cfg accepts kernel and initrd parameters.
|
|
||||||
gu.grub2_cfg(kernel_params=grub.kernel_params, chroot=chroot,
|
|
||||||
grub_timeout=CONF.grub_timeout)
|
|
||||||
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 bareon 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 bareon 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 bareon during provisioning:\n'
|
|
||||||
u'# DO NOT DELETE. It is needed to disable '
|
|
||||||
u'net-generator\n')
|
|
||||||
|
|
||||||
# FIXME(kozhukalov): Prevent nailgun-agent from doing anything.
|
|
||||||
# This ugly hack is to be used together with the command removing
|
|
||||||
# this lock file not earlier than /etc/rc.local
|
|
||||||
# The reason for this hack to appear is to prevent nailgun-agent from
|
|
||||||
# changing mcollective config at the same time when cloud-init
|
|
||||||
# does the same. Otherwise, we can end up with corrupted mcollective
|
|
||||||
# config. For details see https://bugs.launchpad.net/fuel/+bug/1449186
|
|
||||||
LOG.debug('Preventing nailgun-agent from doing '
|
|
||||||
'anything until it is unlocked')
|
|
||||||
utils.makedirs_if_not_exists(os.path.join(chroot, 'etc/nailgun-agent'))
|
|
||||||
with open(os.path.join(chroot, 'etc/nailgun-agent/nodiscover'), 'w'):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# FIXME(kozhukalov): When we have just os-root fs image and don't have
|
|
||||||
# os-var-log fs image while / and /var/log are supposed to be
|
|
||||||
# separate file systems and os-var-log is mounted into
|
|
||||||
# non-empty directory on the / file system, those files in /var/log
|
|
||||||
# directory become unavailable.
|
|
||||||
# The thing is that among those file there is /var/log/upstart
|
|
||||||
# where upstart daemon writes its logs. We have specific upstart job
|
|
||||||
# which is to flush open files once all file systems are mounted.
|
|
||||||
# This job needs upstart directory to be available on os-var-log
|
|
||||||
# file system.
|
|
||||||
# This is just a temporary fix and correct fix will be available soon
|
|
||||||
# via updates.
|
|
||||||
utils.execute('mkdir', '-p', chroot + '/var/log/upstart')
|
|
||||||
|
|
||||||
with open(chroot + '/etc/fstab', 'wt', encoding='utf-8') as f:
|
|
||||||
for fs in self.driver.partition_scheme.fss:
|
|
||||||
# TODO(kozhukalov): Think of improving the logic so as to
|
|
||||||
# insert a meaningful fsck order value which is last zero
|
|
||||||
# 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.
|
|
||||||
if fs.mount == '/':
|
|
||||||
f.write(u'UUID=%s %s %s defaults,errors=panic 0 0\n' %
|
|
||||||
(mount2uuid[fs.mount], fs.mount, fs.type))
|
|
||||||
else:
|
|
||||||
f.write(u'UUID=%s %s %s defaults 0 0\n' %
|
|
||||||
(mount2uuid[fs.mount], fs.mount, fs.type))
|
|
||||||
|
|
||||||
self.umount_target(chroot)
|
|
||||||
|
|
||||||
def do_reboot(self):
|
def do_reboot(self):
|
||||||
LOG.debug('--- Rebooting node (do_reboot) ---')
|
LOG.debug('--- Rebooting node (do_reboot) ---')
|
||||||
utils.execute('reboot')
|
utils.execute('reboot')
|
||||||
|
253
bareon/tests/test_do_bootloader.py
Normal file
253
bareon/tests/test_do_bootloader.py
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
# 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 six
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
from bareon.actions import bootloader
|
||||||
|
from bareon.drivers.data import nailgun
|
||||||
|
from bareon import errors
|
||||||
|
from bareon import objects
|
||||||
|
|
||||||
|
if six.PY2:
|
||||||
|
import mock
|
||||||
|
elif six.PY3:
|
||||||
|
import unittest.mock as mock
|
||||||
|
|
||||||
|
|
||||||
|
class TestBootLoaderAction(unittest2.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBootLoaderAction, self).setUp()
|
||||||
|
self.drv = mock.MagicMock(spec=nailgun.Nailgun)
|
||||||
|
self.action = bootloader.BootLoaderAction(self.drv)
|
||||||
|
self.action._mount_target = mock.Mock()
|
||||||
|
self.action._umount_target = mock.Mock()
|
||||||
|
self.drv.grub = objects.Grub(
|
||||||
|
kernel_params=' console=ttyS0,9600 console=tty0 '
|
||||||
|
'rootdelay=90 nomodeset')
|
||||||
|
root_fs = objects.FS('/dev/sda', mount='/')
|
||||||
|
self.drv.partition_scheme.fss = [root_fs]
|
||||||
|
self.drv.partition_scheme.boot_device.return_value = '/dev/sda3'
|
||||||
|
parteds = [objects.Parted('/dev/sd%s' % x, 'gpt',
|
||||||
|
install_bootloader=True)
|
||||||
|
for x in ['a', 'b', 'c']]
|
||||||
|
self.drv.partition_scheme.parteds = parteds
|
||||||
|
|
||||||
|
@mock.patch.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_grub1_kernel_initrd_guessed(self, mock_utils,
|
||||||
|
mock_gu, mock_open):
|
||||||
|
mock_utils.execute.return_value = ('fake_root_uuid', '')
|
||||||
|
mock_gu.guess_grub_version.return_value = 1
|
||||||
|
# grub has kernel_name and initrd_name both set to None
|
||||||
|
self.drv.grub.kernel_name = None
|
||||||
|
self.drv.grub.initrd_name = None
|
||||||
|
self.drv.grub.kernel_params = 'fake_kernel_params'
|
||||||
|
self.drv.grub.kernel_regexp = 'fake_kernel_regexp'
|
||||||
|
self.drv.grub.initrd_regexp = 'fake_initrd_regexp'
|
||||||
|
mock_gu.guess_kernel.return_value = 'guessed_kernel'
|
||||||
|
mock_gu.guess_initrd.return_value = 'guessed_initrd'
|
||||||
|
self.action.execute()
|
||||||
|
self.assertFalse(mock_gu.grub2_cfg.called)
|
||||||
|
self.assertFalse(mock_gu.grub2_install.called)
|
||||||
|
mock_gu.grub1_cfg.assert_called_once_with(
|
||||||
|
kernel_params='fake_kernel_params root=UUID=fake_root_uuid ',
|
||||||
|
initrd='guessed_initrd', kernel='guessed_kernel',
|
||||||
|
chroot='/tmp/target', grub_timeout=5)
|
||||||
|
mock_gu.grub1_install.assert_called_once_with(
|
||||||
|
['/dev/sda', '/dev/sdb', '/dev/sdc'],
|
||||||
|
'/dev/sda3', chroot='/tmp/target')
|
||||||
|
mock_gu.guess_initrd.assert_called_once_with(
|
||||||
|
regexp='fake_initrd_regexp', chroot='/tmp/target')
|
||||||
|
mock_gu.guess_kernel.assert_called_once_with(
|
||||||
|
regexp='fake_kernel_regexp', chroot='/tmp/target')
|
||||||
|
|
||||||
|
@mock.patch.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_grub1_kernel_initrd_set(self, mock_utils,
|
||||||
|
mock_gu, mock_open):
|
||||||
|
mock_utils.execute.return_value = ('', '')
|
||||||
|
mock_gu.guess_grub_version.return_value = 1
|
||||||
|
self.drv.grub.kernel_params = 'fake_kernel_params'
|
||||||
|
# grub has kernel_name and initrd_name set
|
||||||
|
self.drv.grub.kernel_name = 'kernel_name'
|
||||||
|
self.drv.grub.initrd_name = 'initrd_name'
|
||||||
|
self.action.execute()
|
||||||
|
self.assertFalse(mock_gu.grub2_cfg.called)
|
||||||
|
self.assertFalse(mock_gu.grub2_install.called)
|
||||||
|
mock_gu.grub1_cfg.assert_called_once_with(
|
||||||
|
kernel_params='fake_kernel_params root=UUID= ',
|
||||||
|
initrd='initrd_name', kernel='kernel_name', chroot='/tmp/target',
|
||||||
|
grub_timeout=5)
|
||||||
|
mock_gu.grub1_install.assert_called_once_with(
|
||||||
|
['/dev/sda', '/dev/sdb', '/dev/sdc'],
|
||||||
|
'/dev/sda3', chroot='/tmp/target')
|
||||||
|
self.assertFalse(mock_gu.guess_initrd.called)
|
||||||
|
self.assertFalse(mock_gu.guess_kernel.called)
|
||||||
|
|
||||||
|
@mock.patch.object(objects, 'Grub', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_rootfs_uuid(self, mock_utils, mock_gu, mock_open,
|
||||||
|
mock_grub):
|
||||||
|
def _fake_uuid(*args, **kwargs):
|
||||||
|
if len(args) >= 6 and args[5] == '/dev/sda':
|
||||||
|
return ('FAKE_ROOTFS_UUID', None)
|
||||||
|
else:
|
||||||
|
return ('FAKE_UUID', None)
|
||||||
|
mock_utils.execute.side_effect = _fake_uuid
|
||||||
|
mock_grub.version = 2
|
||||||
|
mock_gu.guess_grub_version.return_value = 2
|
||||||
|
mock_grub.kernel_name = 'fake_kernel_name'
|
||||||
|
mock_grub.initrd_name = 'fake_initrd_name'
|
||||||
|
mock_grub.kernel_params = 'fake_kernel_params'
|
||||||
|
self.drv.grub = mock_grub
|
||||||
|
self.action.execute()
|
||||||
|
mock_grub.append_kernel_params.assert_called_once_with(
|
||||||
|
'root=UUID=FAKE_ROOTFS_UUID ')
|
||||||
|
self.assertEqual(2, mock_grub.version)
|
||||||
|
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_rootfs_not_found(self, mock_utils):
|
||||||
|
mock_utils.execute.return_value = ('fake', 'fake')
|
||||||
|
self.drv.partition_scheme.fss = [
|
||||||
|
objects.FS(device='fake', mount='/boot', fs_type='ext2'),
|
||||||
|
objects.FS(device='fake', mount='swap', fs_type='swap')]
|
||||||
|
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||||
|
self.action.execute)
|
||||||
|
|
||||||
|
@mock.patch.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_grub_version_changes(
|
||||||
|
self, mock_utils, mock_gu, mock_open):
|
||||||
|
# actually covers only grub1 related logic
|
||||||
|
mock_utils.execute.return_value = ('fake_UUID\n', None)
|
||||||
|
mock_gu.guess_grub_version.return_value = 'expected_version'
|
||||||
|
self.action.execute()
|
||||||
|
mock_gu.guess_grub_version.assert_called_once_with(
|
||||||
|
chroot='/tmp/target')
|
||||||
|
self.assertEqual('expected_version', self.drv.grub.version)
|
||||||
|
|
||||||
|
@mock.patch.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_grub1(self, 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.action.execute()
|
||||||
|
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',
|
||||||
|
grub_timeout=5)
|
||||||
|
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.object(bootloader, 'open', create=True,
|
||||||
|
new_callable=mock.mock_open)
|
||||||
|
@mock.patch.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_grub2(self, 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.action.execute()
|
||||||
|
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', grub_timeout=5)
|
||||||
|
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.object(bootloader, 'gu', autospec=True)
|
||||||
|
@mock.patch.object(bootloader, 'utils', autospec=True)
|
||||||
|
def test_do_bootloader_writes(self, mock_utils, mock_gu):
|
||||||
|
# actually covers only write() calls
|
||||||
|
mock_utils.execute.return_value = ('fake_UUID\n', None)
|
||||||
|
self.drv.configdrive_scheme.common.udevrules = "08:00:27:79:da:80_"\
|
||||||
|
"eth0,08:00:27:46:43:60_eth1,08:00:27:b1:d7:15_eth2"
|
||||||
|
self.drv.partition_scheme.fss = [
|
||||||
|
objects.FS('device', mount='/boot', fs_type='ext2'),
|
||||||
|
objects.FS('device', mount='/tmp', fs_type='ext2'),
|
||||||
|
objects.FS('device', mount='/', fs_type='ext4'),
|
||||||
|
objects.FS('device', mount='swap', fs_type='swap'),
|
||||||
|
objects.FS('device', mount='/var/lib/glance')]
|
||||||
|
with mock.patch.object(bootloader, 'open', create=True) as mock_open:
|
||||||
|
file_handle_mock = mock_open.return_value.__enter__.return_value
|
||||||
|
self.action.execute()
|
||||||
|
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 bareon 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 bareon during provisioning: '
|
||||||
|
'END\n'),
|
||||||
|
mock.call('# Generated by bareon 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)
|
||||||
|
self.action._mount_target.assert_called_once_with(
|
||||||
|
'/tmp/target', os_id=None, pseudo=True, treat_mtab=True)
|
||||||
|
mock_utils.makedirs_if_not_exists.assert_called_once_with(
|
||||||
|
'/tmp/target/etc/nailgun-agent')
|
||||||
|
self.action._umount_target.assert_called_once_with(
|
||||||
|
'/tmp/target', os_id=None, pseudo=True)
|
@ -21,11 +21,7 @@ import unittest2
|
|||||||
|
|
||||||
import bareon
|
import bareon
|
||||||
from bareon.drivers.data import nailgun as nailgun_data
|
from bareon.drivers.data import nailgun as nailgun_data
|
||||||
from bareon.drivers.deploy import nailgun as nailgun_deploy
|
|
||||||
from bareon import errors
|
|
||||||
from bareon import objects
|
from bareon import objects
|
||||||
from bareon.tests import test_nailgun
|
|
||||||
from bareon.utils import hardware as hu
|
|
||||||
from bareon.utils import utils
|
from bareon.utils import utils
|
||||||
|
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
@ -36,334 +32,6 @@ elif six.PY3:
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
@unittest2.skip("Fix after cray rebase")
|
|
||||||
class TestManager(unittest2.TestCase):
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.data.nailgun.Nailgun.parse_image_meta',
|
|
||||||
return_value={})
|
|
||||||
@mock.patch.object(hu, 'list_block_devices')
|
|
||||||
def setUp(self, mock_lbd, mock_image_meta):
|
|
||||||
super(TestManager, self).setUp()
|
|
||||||
mock_lbd.return_value = test_nailgun.LIST_BLOCK_DEVICES_SAMPLE
|
|
||||||
self.mgr = nailgun_deploy.Manager(test_nailgun.PROVISION_SAMPLE_DATA)
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'umount_target')
|
|
||||||
def test_do_bootloader_grub1_kernel_initrd_guessed(self, mock_umount,
|
|
||||||
mock_mount, mock_utils,
|
|
||||||
mock_gu, mock_open):
|
|
||||||
mock_utils.execute.return_value = ('', '')
|
|
||||||
mock_gu.guess_grub_version.return_value = 1
|
|
||||||
# grub has kernel_name and initrd_name both set to None
|
|
||||||
self.mgr.driver.grub.kernel_name = None
|
|
||||||
self.mgr.driver.grub.initrd_name = None
|
|
||||||
self.mgr.driver.grub.kernel_params = 'fake_kernel_params'
|
|
||||||
self.mgr.driver.grub.kernel_regexp = 'fake_kernel_regexp'
|
|
||||||
self.mgr.driver.grub.initrd_regexp = 'fake_initrd_regexp'
|
|
||||||
mock_gu.guess_kernel.return_value = 'guessed_kernel'
|
|
||||||
mock_gu.guess_initrd.return_value = 'guessed_initrd'
|
|
||||||
self.mgr.do_bootloader()
|
|
||||||
self.assertFalse(mock_gu.grub2_cfg.called)
|
|
||||||
self.assertFalse(mock_gu.grub2_install.called)
|
|
||||||
mock_gu.grub1_cfg.assert_called_once_with(
|
|
||||||
kernel_params='fake_kernel_params root=UUID= ',
|
|
||||||
initrd='guessed_initrd', kernel='guessed_kernel',
|
|
||||||
chroot='/tmp/target', grub_timeout=5)
|
|
||||||
mock_gu.grub1_install.assert_called_once_with(
|
|
||||||
['/dev/sda', '/dev/sdb', '/dev/sdc'],
|
|
||||||
'/dev/sda3', chroot='/tmp/target')
|
|
||||||
mock_gu.guess_initrd.assert_called_once_with(
|
|
||||||
regexp='fake_initrd_regexp', chroot='/tmp/target')
|
|
||||||
mock_gu.guess_kernel.assert_called_once_with(
|
|
||||||
regexp='fake_kernel_regexp', chroot='/tmp/target')
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'umount_target')
|
|
||||||
def test_do_bootloader_grub1_kernel_initrd_set(self, mock_umount,
|
|
||||||
mock_mount, mock_utils,
|
|
||||||
mock_gu, mock_open):
|
|
||||||
mock_utils.execute.return_value = ('', '')
|
|
||||||
mock_gu.guess_grub_version.return_value = 1
|
|
||||||
self.mgr.driver.grub.kernel_params = 'fake_kernel_params'
|
|
||||||
# grub has kernel_name and initrd_name set
|
|
||||||
self.mgr.driver.grub.kernel_name = 'kernel_name'
|
|
||||||
self.mgr.driver.grub.initrd_name = 'initrd_name'
|
|
||||||
self.mgr.do_bootloader()
|
|
||||||
self.assertFalse(mock_gu.grub2_cfg.called)
|
|
||||||
self.assertFalse(mock_gu.grub2_install.called)
|
|
||||||
mock_gu.grub1_cfg.assert_called_once_with(
|
|
||||||
kernel_params='fake_kernel_params root=UUID= ',
|
|
||||||
initrd='initrd_name', kernel='kernel_name', chroot='/tmp/target',
|
|
||||||
grub_timeout=5)
|
|
||||||
mock_gu.grub1_install.assert_called_once_with(
|
|
||||||
['/dev/sda', '/dev/sdb', '/dev/sdc'],
|
|
||||||
'/dev/sda3', chroot='/tmp/target')
|
|
||||||
self.assertFalse(mock_gu.guess_initrd.called)
|
|
||||||
self.assertFalse(mock_gu.guess_kernel.called)
|
|
||||||
|
|
||||||
@mock.patch('bareon.objects.bootloader.Grub', autospec=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'umount_target')
|
|
||||||
def test_do_bootloader_rootfs_uuid(self, mock_umount, mock_mount,
|
|
||||||
mock_utils, mock_gu, mock_open,
|
|
||||||
mock_grub):
|
|
||||||
def _fake_uuid(*args, **kwargs):
|
|
||||||
if len(args) >= 6 and args[5] == '/dev/mapper/os-root':
|
|
||||||
return ('FAKE_ROOTFS_UUID', None)
|
|
||||||
else:
|
|
||||||
return ('FAKE_UUID', None)
|
|
||||||
mock_utils.execute.side_effect = _fake_uuid
|
|
||||||
mock_grub.version = 2
|
|
||||||
mock_gu.guess_grub_version.return_value = 2
|
|
||||||
mock_grub.kernel_name = 'fake_kernel_name'
|
|
||||||
mock_grub.initrd_name = 'fake_initrd_name'
|
|
||||||
mock_grub.kernel_params = 'fake_kernel_params'
|
|
||||||
self.mgr.driver._grub = mock_grub
|
|
||||||
self.mgr.do_bootloader()
|
|
||||||
mock_grub.append_kernel_params.assert_called_once_with(
|
|
||||||
'root=UUID=FAKE_ROOTFS_UUID ')
|
|
||||||
self.assertEqual(2, mock_grub.version)
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
def test_do_bootloader_rootfs_not_found(self, mock_umount, mock_utils):
|
|
||||||
mock_utils.execute.return_value = ('fake', 'fake')
|
|
||||||
self.mgr.driver._partition_scheme = objects.PartitionScheme()
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/boot', fs_type='ext2')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='swap', fs_type='swap')
|
|
||||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
|
||||||
self.mgr.do_bootloader)
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'umount_target')
|
|
||||||
def test_do_bootloader_grub_version_changes(
|
|
||||||
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_grub_version.return_value = 'expected_version'
|
|
||||||
self.mgr.do_bootloader()
|
|
||||||
mock_gu.guess_grub_version.assert_called_once_with(
|
|
||||||
chroot='/tmp/target')
|
|
||||||
self.assertEqual('expected_version', self.mgr.driver.grub.version)
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, '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',
|
|
||||||
grub_timeout=5)
|
|
||||||
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('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, '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', grub_timeout=5)
|
|
||||||
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('bareon.drivers.deploy.nailgun.gu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, 'mount_target')
|
|
||||||
@mock.patch.object(bareon.drivers.deploy.nailgun, '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('bareon.drivers.deploy.nailgun.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', '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 bareon 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 bareon during provisioning: '
|
|
||||||
'END\n'),
|
|
||||||
mock.call('# Generated by bareon 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('bareon.drivers.deploy.nailgun.fu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.os', create=True)
|
|
||||||
def test_mount_target_mtab_is_link(self, mock_os, mock_open, mock_utils,
|
|
||||||
mock_fu):
|
|
||||||
mock_os.path.islink.return_value = True
|
|
||||||
mock_utils.execute.return_value = (None, None)
|
|
||||||
self.mgr.driver._partition_scheme = objects.PartitionScheme()
|
|
||||||
self.mgr.mount_target('fake_chroot')
|
|
||||||
mock_open.assert_called_once_with('fake_chroot/etc/mtab', 'wt',
|
|
||||||
encoding='utf-8')
|
|
||||||
mock_os.path.islink.assert_called_once_with('fake_chroot/etc/mtab')
|
|
||||||
mock_os.remove.assert_called_once_with('fake_chroot/etc/mtab')
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.fu', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.utils', create=True)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.open',
|
|
||||||
create=True, new_callable=mock.mock_open)
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.os', create=True)
|
|
||||||
def test_mount_target(self, mock_os, mock_open, mock_utils, mock_fu):
|
|
||||||
mock_os.path.islink.return_value = False
|
|
||||||
self.mgr.driver._partition_scheme = objects.PartitionScheme()
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/var/lib', fs_type='xfs')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/', fs_type='ext4')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/boot', fs_type='ext2')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='swap', fs_type='swap')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/var', fs_type='ext4')
|
|
||||||
fake_mtab = """
|
|
||||||
proc /proc proc rw,noexec,nosuid,nodev 0 0
|
|
||||||
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
|
|
||||||
none /sys/fs/fuse/connections fusectl rw 0 0
|
|
||||||
none /sys/kernel/debug debugfs rw 0 0
|
|
||||||
none /sys/kernel/security securityfs rw 0 0
|
|
||||||
udev /dev devtmpfs rw,mode=0755 0 0
|
|
||||||
devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=0620 0 0
|
|
||||||
tmpfs /run tmpfs rw,noexec,nosuid,size=10%,mode=0755 0 0
|
|
||||||
none /run/lock tmpfs rw,noexec,nosuid,nodev,size=5242880 0 0
|
|
||||||
none /run/shm tmpfs rw,nosuid,nodev 0 0"""
|
|
||||||
mock_utils.execute.return_value = (fake_mtab, None)
|
|
||||||
self.mgr.mount_target('fake_chroot')
|
|
||||||
self.assertEqual([mock.call('fake_chroot/'),
|
|
||||||
mock.call('fake_chroot/boot'),
|
|
||||||
mock.call('fake_chroot/var'),
|
|
||||||
mock.call('fake_chroot/var/lib'),
|
|
||||||
mock.call('fake_chroot/sys'),
|
|
||||||
mock.call('fake_chroot/dev'),
|
|
||||||
mock.call('fake_chroot/proc')],
|
|
||||||
mock_utils.makedirs_if_not_exists.call_args_list)
|
|
||||||
self.assertEqual([mock.call('ext4', 'fake', 'fake_chroot/'),
|
|
||||||
mock.call('ext2', 'fake', 'fake_chroot/boot'),
|
|
||||||
mock.call('ext4', 'fake', 'fake_chroot/var'),
|
|
||||||
mock.call('xfs', 'fake', 'fake_chroot/var/lib')],
|
|
||||||
mock_fu.mount_fs.call_args_list)
|
|
||||||
self.assertEqual([mock.call('fake_chroot', '/sys'),
|
|
||||||
mock.call('fake_chroot', '/dev'),
|
|
||||||
mock.call('fake_chroot', '/proc')],
|
|
||||||
mock_fu.mount_bind.call_args_list)
|
|
||||||
file_handle = mock_open.return_value.__enter__.return_value
|
|
||||||
file_handle.write.assert_called_once_with(fake_mtab)
|
|
||||||
mock_open.assert_called_once_with('fake_chroot/etc/mtab', 'wt',
|
|
||||||
encoding='utf-8')
|
|
||||||
mock_os.path.islink.assert_called_once_with('fake_chroot/etc/mtab')
|
|
||||||
self.assertFalse(mock_os.remove.called)
|
|
||||||
|
|
||||||
@mock.patch('bareon.drivers.deploy.nailgun.fu', create=True)
|
|
||||||
def test_umount_target(self, mock_fu):
|
|
||||||
self.mgr.driver._partition_scheme = objects.PartitionScheme()
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/var/lib', fs_type='xfs')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/', fs_type='ext4')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/boot', fs_type='ext2')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='swap', fs_type='swap')
|
|
||||||
self.mgr.driver.partition_scheme.add_fs(
|
|
||||||
device='fake', mount='/var', fs_type='ext4')
|
|
||||||
self.mgr.umount_target('fake_chroot')
|
|
||||||
self.assertEqual([mock.call('fake_chroot/proc'),
|
|
||||||
mock.call('fake_chroot/dev'),
|
|
||||||
mock.call('fake_chroot/sys/fs/fuse/connections'),
|
|
||||||
mock.call('fake_chroot/sys'),
|
|
||||||
mock.call('fake_chroot/var/lib'),
|
|
||||||
mock.call('fake_chroot/boot'),
|
|
||||||
mock.call('fake_chroot/var'),
|
|
||||||
mock.call('fake_chroot/')],
|
|
||||||
mock_fu.umount_fs.call_args_list)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest2.skip("Fix after cray rebase")
|
@unittest2.skip("Fix after cray rebase")
|
||||||
class TestImageBuild(unittest2.TestCase):
|
class TestImageBuild(unittest2.TestCase):
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ bareon.actions =
|
|||||||
do_partitioning = bareon.actions.partitioning:PartitioningAction
|
do_partitioning = bareon.actions.partitioning:PartitioningAction
|
||||||
do_configdrive = bareon.actions.configdrive:ConfigDriveAction
|
do_configdrive = bareon.actions.configdrive:ConfigDriveAction
|
||||||
do_copyimage = bareon.actions.copyimage:CopyImageAction
|
do_copyimage = bareon.actions.copyimage:CopyImageAction
|
||||||
|
do_bootloader = bareon.actions.bootloader:BootLoaderAction
|
||||||
|
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
bareon.manager = bareon.manager:list_opts
|
bareon.manager = bareon.manager:list_opts
|
||||||
|
Loading…
x
Reference in New Issue
Block a user