Finalize removal of ipxe_enabled option
Remove the dynamically registered ipxe_enabled option and say goodbye. Further extracts common bits to the PXEBaseMixin, tuning tests here and there. Story: 2007003 Task: 37779 Change-Id: I7c1b2a984d45bd63b4e95b62ce02960924c2ce17
This commit is contained in:
parent
6ba983b615
commit
34d34b3a9d
@ -1567,7 +1567,6 @@ function configure_ironic_conductor {
|
|||||||
local pxebin
|
local pxebin
|
||||||
pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
|
pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
|
||||||
uefipxebin=`basename $(get_uefi_ipxe_boot_file)`
|
uefipxebin=`basename $(get_uefi_ipxe_boot_file)`
|
||||||
iniset $IRONIC_CONF_FILE pxe ipxe_enabled True
|
|
||||||
iniset $IRONIC_CONF_FILE pxe pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
iniset $IRONIC_CONF_FILE pxe pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
||||||
iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
|
iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
|
||||||
iniset $IRONIC_CONF_FILE pxe uefi_pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
iniset $IRONIC_CONF_FILE pxe uefi_pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
||||||
|
@ -29,11 +29,4 @@ def parse_args(argv, default_config_files=None):
|
|||||||
version=version.version_info.release_string(),
|
version=version.version_info.release_string(),
|
||||||
default_config_files=default_config_files)
|
default_config_files=default_config_files)
|
||||||
rpc.init(cfg.CONF)
|
rpc.init(cfg.CONF)
|
||||||
# TODO(kaifeng) Remove ipxe_enabled option handling after ipxe support
|
|
||||||
# is completely removed from the pxe interface.
|
|
||||||
ipxe_enabled = cfg.BoolOpt('ipxe_enabled', default=False,
|
|
||||||
deprecated_for_removal=True)
|
|
||||||
cfg.CONF.register_opt(ipxe_enabled, group='pxe')
|
|
||||||
cfg.CONF.set_override('ipxe_enabled', False, group='pxe')
|
|
||||||
|
|
||||||
profiler_opts.set_defaults(cfg.CONF)
|
profiler_opts.set_defaults(cfg.CONF)
|
||||||
|
@ -20,7 +20,6 @@ from ironic_lib import utils as ironic_utils
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
from oslo_utils import importutils
|
|
||||||
from oslo_utils import netutils
|
from oslo_utils import netutils
|
||||||
|
|
||||||
from ironic.common import dhcp_factory
|
from ironic.common import dhcp_factory
|
||||||
@ -546,16 +545,7 @@ def is_ipxe_enabled(task):
|
|||||||
:returns: boolean true if ``[pxe]ipxe_enabled`` is configured
|
:returns: boolean true if ``[pxe]ipxe_enabled`` is configured
|
||||||
or if the task driver instance is the iPXE driver.
|
or if the task driver instance is the iPXE driver.
|
||||||
"""
|
"""
|
||||||
# NOTE(TheJulia): importutils used here as we seem to get in circular
|
return 'ipxe_boot' in task.driver.boot.capabilities
|
||||||
# import weirdness otherwise, specifically when the classes that use
|
|
||||||
# the pxe interface as their parent.
|
|
||||||
# TODO(TheJulia): We should remove this as soon as it is no longer
|
|
||||||
# required to help us bridge the split of the interfaces and helper
|
|
||||||
# methods.
|
|
||||||
iPXEBoot = importutils.import_class(
|
|
||||||
'ironic.drivers.modules.ipxe.iPXEBoot')
|
|
||||||
return CONF.pxe.ipxe_enabled or isinstance(task.driver.boot,
|
|
||||||
iPXEBoot)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_driver_info(node, mode='deploy'):
|
def parse_driver_info(node, mode='deploy'):
|
||||||
|
@ -15,24 +15,9 @@
|
|||||||
iPXE Boot Interface
|
iPXE Boot Interface
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ironic_lib import metrics_utils
|
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.common.glance_service import service_utils
|
|
||||||
from ironic.common.i18n import _
|
|
||||||
from ironic.common import pxe_utils
|
from ironic.common import pxe_utils
|
||||||
from ironic.conf import CONF
|
|
||||||
from ironic.drivers import base
|
from ironic.drivers import base
|
||||||
from ironic.drivers.modules import deploy_utils
|
|
||||||
from ironic.drivers.modules import pxe
|
|
||||||
from ironic.drivers.modules import pxe_base
|
from ironic.drivers.modules import pxe_base
|
||||||
from ironic.drivers import utils as driver_utils
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
|
||||||
|
|
||||||
COMMON_PROPERTIES = pxe_base.COMMON_PROPERTIES
|
|
||||||
|
|
||||||
|
|
||||||
class iPXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
class iPXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
||||||
@ -43,82 +28,3 @@ class iPXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pxe_utils.create_ipxe_boot_script()
|
pxe_utils.create_ipxe_boot_script()
|
||||||
|
|
||||||
def _validate_common(self, task):
|
|
||||||
node = task.node
|
|
||||||
|
|
||||||
if not driver_utils.get_node_mac_addresses(task):
|
|
||||||
raise exception.MissingParameterValue(
|
|
||||||
_("Node %s does not have any port associated with it.")
|
|
||||||
% node.uuid)
|
|
||||||
|
|
||||||
if not CONF.deploy.http_url or not CONF.deploy.http_root:
|
|
||||||
raise exception.MissingParameterValue(_(
|
|
||||||
"iPXE boot is enabled but no HTTP URL or HTTP "
|
|
||||||
"root was specified."))
|
|
||||||
|
|
||||||
# Check the trusted_boot capabilities value.
|
|
||||||
deploy_utils.validate_capabilities(node)
|
|
||||||
if deploy_utils.is_trusted_boot_requested(node):
|
|
||||||
# Check if 'boot_option' and boot mode is compatible with
|
|
||||||
# trusted boot.
|
|
||||||
# NOTE(TheJulia): So in theory (huge theory here, not put to
|
|
||||||
# practice or tested), that one can define the kernel as tboot
|
|
||||||
# and define the actual kernel and ramdisk as appended data.
|
|
||||||
# Similar to how one can iPXE load the XEN hypervisor.
|
|
||||||
# tboot mailing list seem to indicate pxe/ipxe support, or
|
|
||||||
# more specifically avoiding breaking the scenarios of use,
|
|
||||||
# but there is also no definitive documentation on the subject.
|
|
||||||
LOG.warning('Trusted boot has been requested for %(node)s in '
|
|
||||||
'concert with iPXE. This is not a supported '
|
|
||||||
'configuration for an ironic deployment.',
|
|
||||||
{'node': node.uuid})
|
|
||||||
pxe.validate_boot_parameters_for_trusted_boot(node)
|
|
||||||
|
|
||||||
pxe_utils.parse_driver_info(node)
|
|
||||||
|
|
||||||
@METRICS.timer('iPXEBoot.validate')
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the PXE-specific info for booting deploy/instance images.
|
|
||||||
|
|
||||||
This method validates the PXE-specific info for booting the
|
|
||||||
ramdisk and instance on the node. If invalid, raises an
|
|
||||||
exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:returns: None
|
|
||||||
:raises: InvalidParameterValue, if some parameters are invalid.
|
|
||||||
:raises: MissingParameterValue, if some required parameters are
|
|
||||||
missing.
|
|
||||||
"""
|
|
||||||
self._validate_common(task)
|
|
||||||
|
|
||||||
# NOTE(TheJulia): If we're not writing an image, we can skip
|
|
||||||
# the remainder of this method.
|
|
||||||
if (not task.driver.storage.should_write_image(task)):
|
|
||||||
return
|
|
||||||
|
|
||||||
node = task.node
|
|
||||||
d_info = deploy_utils.get_image_instance_info(node)
|
|
||||||
if (node.driver_internal_info.get('is_whole_disk_image')
|
|
||||||
or deploy_utils.get_boot_option(node) == 'local'):
|
|
||||||
props = []
|
|
||||||
elif service_utils.is_glance_image(d_info['image_source']):
|
|
||||||
props = ['kernel_id', 'ramdisk_id']
|
|
||||||
else:
|
|
||||||
props = ['kernel', 'ramdisk']
|
|
||||||
deploy_utils.validate_image_properties(task.context, d_info, props)
|
|
||||||
|
|
||||||
@METRICS.timer('iPXEBoot.validate_inspection')
|
|
||||||
def validate_inspection(self, task):
|
|
||||||
"""Validate that the node has required properties for inspection.
|
|
||||||
|
|
||||||
:param task: A TaskManager instance with the node being checked
|
|
||||||
:raises: UnsupportedDriverExtension
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self._validate_common(task)
|
|
||||||
except exception.MissingParameterValue:
|
|
||||||
# Fall back to non-managed in-band inspection
|
|
||||||
raise exception.UnsupportedDriverExtension(
|
|
||||||
driver=task.node.driver, extension='inspection')
|
|
||||||
|
@ -19,9 +19,7 @@ from ironic_lib import metrics_utils
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
from ironic.common.glance_service import service_utils
|
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
from ironic.common import pxe_utils
|
|
||||||
from ironic.common import states
|
from ironic.common import states
|
||||||
from ironic.conductor import task_manager
|
from ironic.conductor import task_manager
|
||||||
from ironic.conductor import utils as manager_utils
|
from ironic.conductor import utils as manager_utils
|
||||||
@ -29,89 +27,14 @@ from ironic.drivers import base
|
|||||||
from ironic.drivers.modules import agent
|
from ironic.drivers.modules import agent
|
||||||
from ironic.drivers.modules import deploy_utils
|
from ironic.drivers.modules import deploy_utils
|
||||||
from ironic.drivers.modules import pxe_base
|
from ironic.drivers.modules import pxe_base
|
||||||
from ironic.drivers import utils as driver_utils
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
COMMON_PROPERTIES = pxe_base.COMMON_PROPERTIES
|
|
||||||
|
|
||||||
# NOTE(TheJulia): This was previously a public method to the code being
|
|
||||||
# moved. This mapping should be removed in the T* cycle.
|
|
||||||
validate_boot_parameters_for_trusted_boot = pxe_utils.validate_boot_parameters_for_trusted_boot # noqa
|
|
||||||
TFTPImageCache = pxe_utils.TFTPImageCache
|
|
||||||
# NOTE(TheJulia): End section of mappings for migrated common pxe code.
|
|
||||||
|
|
||||||
|
|
||||||
class PXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
class PXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
||||||
|
|
||||||
# TODO(TheJulia): iscsi_volume_boot should be removed from
|
capabilities = ['ramdisk_boot', 'pxe_boot']
|
||||||
# the list below once ipxe support is removed from the PXE
|
|
||||||
# interface.
|
|
||||||
capabilities = ['iscsi_volume_boot', 'ramdisk_boot', 'pxe_boot']
|
|
||||||
|
|
||||||
def _validate_common(self, task):
|
|
||||||
node = task.node
|
|
||||||
|
|
||||||
if not driver_utils.get_node_mac_addresses(task):
|
|
||||||
raise exception.MissingParameterValue(
|
|
||||||
_("Node %s does not have any port associated with it.")
|
|
||||||
% node.uuid)
|
|
||||||
|
|
||||||
# Check the trusted_boot capabilities value.
|
|
||||||
deploy_utils.validate_capabilities(node)
|
|
||||||
if deploy_utils.is_trusted_boot_requested(node):
|
|
||||||
# Check if 'boot_option' and boot mode is compatible with
|
|
||||||
# trusted boot.
|
|
||||||
validate_boot_parameters_for_trusted_boot(node)
|
|
||||||
|
|
||||||
pxe_utils.parse_driver_info(node)
|
|
||||||
|
|
||||||
@METRICS.timer('PXEBoot.validate')
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the PXE-specific info for booting deploy/instance images.
|
|
||||||
|
|
||||||
This method validates the PXE-specific info for booting the
|
|
||||||
ramdisk and instance on the node. If invalid, raises an
|
|
||||||
exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:returns: None
|
|
||||||
:raises: InvalidParameterValue, if some parameters are invalid.
|
|
||||||
:raises: MissingParameterValue, if some required parameters are
|
|
||||||
missing.
|
|
||||||
"""
|
|
||||||
self._validate_common(task)
|
|
||||||
|
|
||||||
# NOTE(TheJulia): If we're not writing an image, we can skip
|
|
||||||
# the remainder of this method.
|
|
||||||
if (not task.driver.storage.should_write_image(task)):
|
|
||||||
return
|
|
||||||
|
|
||||||
node = task.node
|
|
||||||
d_info = deploy_utils.get_image_instance_info(node)
|
|
||||||
if (node.driver_internal_info.get('is_whole_disk_image')
|
|
||||||
or deploy_utils.get_boot_option(node) == 'local'):
|
|
||||||
props = []
|
|
||||||
elif service_utils.is_glance_image(d_info['image_source']):
|
|
||||||
props = ['kernel_id', 'ramdisk_id']
|
|
||||||
else:
|
|
||||||
props = ['kernel', 'ramdisk']
|
|
||||||
deploy_utils.validate_image_properties(task.context, d_info, props)
|
|
||||||
|
|
||||||
@METRICS.timer('PXEBoot.validate_inspection')
|
|
||||||
def validate_inspection(self, task):
|
|
||||||
"""Validate that the node has required properties for inspection.
|
|
||||||
|
|
||||||
:param task: A TaskManager instance with the node being checked
|
|
||||||
:raises: UnsupportedDriverExtension
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self._validate_common(task)
|
|
||||||
except exception.MissingParameterValue:
|
|
||||||
# Fall back to non-managed in-band inspection
|
|
||||||
raise exception.UnsupportedDriverExtension(
|
|
||||||
driver=task.node.driver, extension='inspection')
|
|
||||||
|
|
||||||
|
|
||||||
class PXERamdiskDeploy(agent.AgentDeploy):
|
class PXERamdiskDeploy(agent.AgentDeploy):
|
||||||
|
@ -22,6 +22,7 @@ from oslo_utils import strutils
|
|||||||
from ironic.common import boot_devices
|
from ironic.common import boot_devices
|
||||||
from ironic.common import dhcp_factory
|
from ironic.common import dhcp_factory
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
|
from ironic.common.glance_service import service_utils
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
from ironic.common import pxe_utils
|
from ironic.common import pxe_utils
|
||||||
from ironic.common import states
|
from ironic.common import states
|
||||||
@ -29,6 +30,7 @@ from ironic.conductor import task_manager
|
|||||||
from ironic.conductor import utils as manager_utils
|
from ironic.conductor import utils as manager_utils
|
||||||
from ironic.drivers.modules import boot_mode_utils
|
from ironic.drivers.modules import boot_mode_utils
|
||||||
from ironic.drivers.modules import deploy_utils
|
from ironic.drivers.modules import deploy_utils
|
||||||
|
from ironic.drivers import utils as driver_utils
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@ -306,6 +308,73 @@ class PXEBaseMixin(object):
|
|||||||
manager_utils.node_set_boot_device(task, boot_device,
|
manager_utils.node_set_boot_device(task, boot_device,
|
||||||
persistent=persistent)
|
persistent=persistent)
|
||||||
|
|
||||||
|
def _validate_common(self, task):
|
||||||
|
node = task.node
|
||||||
|
|
||||||
|
if not driver_utils.get_node_mac_addresses(task):
|
||||||
|
raise exception.MissingParameterValue(
|
||||||
|
_("Node %s does not have any port associated with it.")
|
||||||
|
% node.uuid)
|
||||||
|
|
||||||
|
if self.ipxe_enabled:
|
||||||
|
if not CONF.deploy.http_url or not CONF.deploy.http_root:
|
||||||
|
raise exception.MissingParameterValue(_(
|
||||||
|
"iPXE boot is enabled but no HTTP URL or HTTP "
|
||||||
|
"root was specified."))
|
||||||
|
|
||||||
|
# Check the trusted_boot capabilities value.
|
||||||
|
deploy_utils.validate_capabilities(node)
|
||||||
|
if deploy_utils.is_trusted_boot_requested(node):
|
||||||
|
# Check if 'boot_option' and boot mode is compatible with
|
||||||
|
# trusted boot.
|
||||||
|
if self.ipxe_enabled:
|
||||||
|
# NOTE(TheJulia): So in theory (huge theory here, not put to
|
||||||
|
# practice or tested), that one can define the kernel as tboot
|
||||||
|
# and define the actual kernel and ramdisk as appended data.
|
||||||
|
# Similar to how one can iPXE load the XEN hypervisor.
|
||||||
|
# tboot mailing list seem to indicate pxe/ipxe support, or
|
||||||
|
# more specifically avoiding breaking the scenarios of use,
|
||||||
|
# but there is also no definitive documentation on the subject.
|
||||||
|
LOG.warning('Trusted boot has been requested for %(node)s in '
|
||||||
|
'concert with iPXE. This is not a supported '
|
||||||
|
'configuration for an ironic deployment.',
|
||||||
|
{'node': node.uuid})
|
||||||
|
pxe_utils.validate_boot_parameters_for_trusted_boot(node)
|
||||||
|
|
||||||
|
pxe_utils.parse_driver_info(node)
|
||||||
|
|
||||||
|
@METRICS.timer('PXEBaseMixin.validate')
|
||||||
|
def validate(self, task):
|
||||||
|
"""Validate the PXE-specific info for booting deploy/instance images.
|
||||||
|
|
||||||
|
This method validates the PXE-specific info for booting the
|
||||||
|
ramdisk and instance on the node. If invalid, raises an
|
||||||
|
exception; otherwise returns None.
|
||||||
|
|
||||||
|
:param task: a task from TaskManager.
|
||||||
|
:returns: None
|
||||||
|
:raises: InvalidParameterValue, if some parameters are invalid.
|
||||||
|
:raises: MissingParameterValue, if some required parameters are
|
||||||
|
missing.
|
||||||
|
"""
|
||||||
|
self._validate_common(task)
|
||||||
|
|
||||||
|
# NOTE(TheJulia): If we're not writing an image, we can skip
|
||||||
|
# the remainder of this method.
|
||||||
|
if (not task.driver.storage.should_write_image(task)):
|
||||||
|
return
|
||||||
|
|
||||||
|
node = task.node
|
||||||
|
d_info = deploy_utils.get_image_instance_info(node)
|
||||||
|
if (node.driver_internal_info.get('is_whole_disk_image')
|
||||||
|
or deploy_utils.get_boot_option(node) == 'local'):
|
||||||
|
props = []
|
||||||
|
elif service_utils.is_glance_image(d_info['image_source']):
|
||||||
|
props = ['kernel_id', 'ramdisk_id']
|
||||||
|
else:
|
||||||
|
props = ['kernel', 'ramdisk']
|
||||||
|
deploy_utils.validate_image_properties(task.context, d_info, props)
|
||||||
|
|
||||||
@METRICS.timer('PXEBaseMixin.validate_rescue')
|
@METRICS.timer('PXEBaseMixin.validate_rescue')
|
||||||
def validate_rescue(self, task):
|
def validate_rescue(self, task):
|
||||||
"""Validate that the node has required properties for rescue.
|
"""Validate that the node has required properties for rescue.
|
||||||
@ -316,6 +385,20 @@ class PXEBaseMixin(object):
|
|||||||
"""
|
"""
|
||||||
pxe_utils.parse_driver_info(task.node, mode='rescue')
|
pxe_utils.parse_driver_info(task.node, mode='rescue')
|
||||||
|
|
||||||
|
@METRICS.timer('PXEBaseMixin.validate_inspection')
|
||||||
|
def validate_inspection(self, task):
|
||||||
|
"""Validate that the node has required properties for inspection.
|
||||||
|
|
||||||
|
:param task: A TaskManager instance with the node being checked
|
||||||
|
:raises: UnsupportedDriverExtension
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._validate_common(task)
|
||||||
|
except exception.MissingParameterValue:
|
||||||
|
# Fall back to non-managed in-band inspection
|
||||||
|
raise exception.UnsupportedDriverExtension(
|
||||||
|
driver=task.node.driver, extension='inspection')
|
||||||
|
|
||||||
def _persistent_ramdisk_boot(self, node):
|
def _persistent_ramdisk_boot(self, node):
|
||||||
"""If the ramdisk should be configured as a persistent boot device."""
|
"""If the ramdisk should be configured as a persistent boot device."""
|
||||||
value = node.driver_info.get('force_persistent_boot_device', 'Default')
|
value = node.driver_info.get('force_persistent_boot_device', 'Default')
|
||||||
|
@ -308,7 +308,6 @@ class TestPXEUtils(db_base.DbTestCase):
|
|||||||
@mock.patch('ironic.common.utils.create_link_without_raise', autospec=True)
|
@mock.patch('ironic.common.utils.create_link_without_raise', autospec=True)
|
||||||
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
||||||
def test__write_mac_ipxe_configs(self, unlink_mock, create_link_mock):
|
def test__write_mac_ipxe_configs(self, unlink_mock, create_link_mock):
|
||||||
self.config(ipxe_enabled=True, group='pxe')
|
|
||||||
port_1 = object_utils.create_test_port(
|
port_1 = object_utils.create_test_port(
|
||||||
self.context, node_id=self.node.id,
|
self.context, node_id=self.node.id,
|
||||||
address='11:22:33:44:55:66', uuid=uuidutils.generate_uuid())
|
address='11:22:33:44:55:66', uuid=uuidutils.generate_uuid())
|
||||||
@ -526,7 +525,6 @@ class TestPXEUtils(db_base.DbTestCase):
|
|||||||
def test_create_pxe_config_uefi_ipxe(self, ensure_tree_mock, render_mock,
|
def test_create_pxe_config_uefi_ipxe(self, ensure_tree_mock, render_mock,
|
||||||
write_mock, link_mac_pxe_mock,
|
write_mock, link_mac_pxe_mock,
|
||||||
chmod_mock):
|
chmod_mock):
|
||||||
self.config(ipxe_enabled=True, group='pxe')
|
|
||||||
ipxe_template = "ironic/drivers/modules/ipxe_config.template"
|
ipxe_template = "ironic/drivers/modules/ipxe_config.template"
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
task.node.properties['capabilities'] = 'boot_mode:uefi'
|
task.node.properties['capabilities'] = 'boot_mode:uefi'
|
||||||
@ -740,107 +738,6 @@ class TestPXEUtils(db_base.DbTestCase):
|
|||||||
self._test_get_kernel_ramdisk_info(expected_dir, mode='rescue',
|
self._test_get_kernel_ramdisk_info(expected_dir, mode='rescue',
|
||||||
ipxe_enabled=True)
|
ipxe_enabled=True)
|
||||||
|
|
||||||
def _dhcp_options_for_instance_ipxe(self, task, boot_file, ip_version=4):
|
|
||||||
self.config(ipxe_enabled=True, group='pxe')
|
|
||||||
self.config(ipxe_boot_script='/test/boot.ipxe', group='pxe')
|
|
||||||
self.config(tftp_root='/tftp-path/', group='pxe')
|
|
||||||
if ip_version == 4:
|
|
||||||
self.config(tftp_server='192.0.2.1', group='pxe')
|
|
||||||
self.config(http_url='http://192.0.3.2:1234', group='deploy')
|
|
||||||
self.config(ipxe_boot_script='/test/boot.ipxe', group='pxe')
|
|
||||||
elif ip_version == 6:
|
|
||||||
self.config(tftp_server='ff80::1', group='pxe')
|
|
||||||
self.config(http_url='http://[ff80::1]:1234', group='deploy')
|
|
||||||
|
|
||||||
self.config(dhcp_provider='isc', group='dhcp')
|
|
||||||
if ip_version == 6:
|
|
||||||
# NOTE(TheJulia): DHCPv6 RFCs seem to indicate that the prior
|
|
||||||
# options are not imported, although they may be supported
|
|
||||||
# by vendors. The apparent proper option is to return a
|
|
||||||
# URL in the field https://tools.ietf.org/html/rfc5970#section-3
|
|
||||||
expected_boot_script_url = 'http://[ff80::1]:1234/boot.ipxe'
|
|
||||||
expected_info = [{'opt_name': '!175,59',
|
|
||||||
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '59',
|
|
||||||
'opt_value': expected_boot_script_url,
|
|
||||||
'ip_version': ip_version}]
|
|
||||||
|
|
||||||
elif ip_version == 4:
|
|
||||||
expected_boot_script_url = 'http://192.0.3.2:1234/boot.ipxe'
|
|
||||||
expected_info = [{'opt_name': '!175,67',
|
|
||||||
'opt_value': boot_file,
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '66',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '150',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '67',
|
|
||||||
'opt_value': expected_boot_script_url,
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': 'server-ip-address',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version}]
|
|
||||||
|
|
||||||
self.assertItemsEqual(expected_info,
|
|
||||||
pxe_utils.dhcp_options_for_instance(
|
|
||||||
task, ipxe_enabled=True))
|
|
||||||
|
|
||||||
self.config(dhcp_provider='neutron', group='dhcp')
|
|
||||||
if ip_version == 6:
|
|
||||||
# Boot URL variable set from prior test of isc parameters.
|
|
||||||
expected_info = [{'opt_name': 'tag:!ipxe6,59',
|
|
||||||
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': 'tag:ipxe6,59',
|
|
||||||
'opt_value': expected_boot_script_url,
|
|
||||||
'ip_version': ip_version}]
|
|
||||||
|
|
||||||
elif ip_version == 4:
|
|
||||||
expected_info = [{'opt_name': 'tag:!ipxe,67',
|
|
||||||
'opt_value': boot_file,
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '66',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': '150',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': 'tag:ipxe,67',
|
|
||||||
'opt_value': expected_boot_script_url,
|
|
||||||
'ip_version': ip_version},
|
|
||||||
{'opt_name': 'server-ip-address',
|
|
||||||
'opt_value': '192.0.2.1',
|
|
||||||
'ip_version': ip_version}]
|
|
||||||
|
|
||||||
self.assertItemsEqual(expected_info,
|
|
||||||
pxe_utils.dhcp_options_for_instance(
|
|
||||||
task, ipxe_enabled=True))
|
|
||||||
|
|
||||||
def test_dhcp_options_for_instance_ipxe_bios(self):
|
|
||||||
self.config(ip_version=4, group='pxe')
|
|
||||||
boot_file = 'fake-bootfile-bios'
|
|
||||||
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
|
||||||
|
|
||||||
def test_dhcp_options_for_instance_ipxe_uefi(self):
|
|
||||||
self.config(ip_version=4, group='pxe')
|
|
||||||
boot_file = 'fake-bootfile-uefi'
|
|
||||||
self.config(uefi_pxe_bootfile_name=boot_file, group='pxe')
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.node.properties['capabilities'] = 'boot_mode:uefi'
|
|
||||||
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
|
||||||
|
|
||||||
def test_dhcp_options_for_ipxe_ipv6(self):
|
|
||||||
self.config(ip_version=6, group='pxe')
|
|
||||||
boot_file = 'fake-bootfile'
|
|
||||||
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
self._dhcp_options_for_instance_ipxe(task, boot_file, ip_version=6)
|
|
||||||
|
|
||||||
@mock.patch('ironic.common.utils.rmtree_without_raise', autospec=True)
|
@mock.patch('ironic.common.utils.rmtree_without_raise', autospec=True)
|
||||||
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
||||||
@mock.patch('ironic.common.dhcp_factory.DHCPFactory.provider',
|
@mock.patch('ironic.common.dhcp_factory.DHCPFactory.provider',
|
||||||
@ -924,29 +821,6 @@ class TestPXEUtils(db_base.DbTestCase):
|
|||||||
rmtree_mock.assert_called_once_with(
|
rmtree_mock.assert_called_once_with(
|
||||||
os.path.join(CONF.pxe.tftp_root, self.node.uuid))
|
os.path.join(CONF.pxe.tftp_root, self.node.uuid))
|
||||||
|
|
||||||
@mock.patch('ironic.common.utils.rmtree_without_raise', autospec=True)
|
|
||||||
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
|
||||||
def test_clean_up_ipxe_config_uefi(self, unlink_mock, rmtree_mock):
|
|
||||||
self.config(ipxe_enabled=True, group='pxe')
|
|
||||||
address = "aa:aa:aa:aa:aa:aa"
|
|
||||||
properties = {'capabilities': 'boot_mode:uefi'}
|
|
||||||
object_utils.create_test_port(self.context, node_id=self.node.id,
|
|
||||||
address=address)
|
|
||||||
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.node.properties = properties
|
|
||||||
pxe_utils.clean_up_pxe_config(task, ipxe_enabled=True)
|
|
||||||
|
|
||||||
ensure_calls = [
|
|
||||||
mock.call("/httpboot/pxelinux.cfg/%s"
|
|
||||||
% address.replace(':', '-')),
|
|
||||||
mock.call("/httpboot/%s.conf" % address)
|
|
||||||
]
|
|
||||||
|
|
||||||
unlink_mock.assert_has_calls(ensure_calls)
|
|
||||||
rmtree_mock.assert_called_once_with(
|
|
||||||
os.path.join(CONF.deploy.http_root, self.node.uuid))
|
|
||||||
|
|
||||||
def test_get_tftp_path_prefix_with_trailing_slash(self):
|
def test_get_tftp_path_prefix_with_trailing_slash(self):
|
||||||
self.config(tftp_root='/tftpboot-path/', group='pxe')
|
self.config(tftp_root='/tftpboot-path/', group='pxe')
|
||||||
path_prefix = pxe_utils.get_tftp_path_prefix()
|
path_prefix = pxe_utils.get_tftp_path_prefix()
|
||||||
@ -1154,6 +1028,118 @@ class PXEInterfacesTestCase(db_base.DbTestCase):
|
|||||||
image_info = pxe_utils.get_instance_image_info(task)
|
image_info = pxe_utils.get_instance_image_info(task)
|
||||||
self.assertEqual({}, image_info)
|
self.assertEqual({}, image_info)
|
||||||
|
|
||||||
|
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
||||||
|
def test__cache_tftp_images_master_path(self, mock_fetch_image):
|
||||||
|
temp_dir = tempfile.mkdtemp()
|
||||||
|
self.config(tftp_root=temp_dir, group='pxe')
|
||||||
|
self.config(tftp_master_path=os.path.join(temp_dir,
|
||||||
|
'tftp_master_path'),
|
||||||
|
group='pxe')
|
||||||
|
image_path = os.path.join(temp_dir, self.node.uuid,
|
||||||
|
'deploy_kernel')
|
||||||
|
image_info = {'deploy_kernel': ('deploy_kernel', image_path)}
|
||||||
|
fileutils.ensure_tree(CONF.pxe.tftp_master_path)
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
pxe_utils.cache_ramdisk_kernel(task, image_info)
|
||||||
|
|
||||||
|
mock_fetch_image.assert_called_once_with(self.context,
|
||||||
|
mock.ANY,
|
||||||
|
[('deploy_kernel',
|
||||||
|
image_path)],
|
||||||
|
True)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils, 'TFTPImageCache', lambda: None)
|
||||||
|
@mock.patch.object(fileutils, 'ensure_tree', autospec=True)
|
||||||
|
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
||||||
|
def test_cache_ramdisk_kernel(self, mock_fetch_image, mock_ensure_tree):
|
||||||
|
fake_pxe_info = {'foo': 'bar'}
|
||||||
|
expected_path = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
pxe_utils.cache_ramdisk_kernel(task, fake_pxe_info)
|
||||||
|
mock_ensure_tree.assert_called_with(expected_path)
|
||||||
|
mock_fetch_image.assert_called_once_with(
|
||||||
|
self.context, mock.ANY, list(fake_pxe_info.values()), True)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils, 'TFTPImageCache', lambda: None)
|
||||||
|
@mock.patch.object(fileutils, 'ensure_tree', autospec=True)
|
||||||
|
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
||||||
|
def test_cache_ramdisk_kernel_ipxe(self, mock_fetch_image,
|
||||||
|
mock_ensure_tree):
|
||||||
|
fake_pxe_info = {'foo': 'bar'}
|
||||||
|
expected_path = os.path.join(CONF.deploy.http_root,
|
||||||
|
self.node.uuid)
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
pxe_utils.cache_ramdisk_kernel(task, fake_pxe_info,
|
||||||
|
ipxe_enabled=True)
|
||||||
|
mock_ensure_tree.assert_called_with(expected_path)
|
||||||
|
mock_fetch_image.assert_called_once_with(self.context, mock.ANY,
|
||||||
|
list(fake_pxe_info.values()),
|
||||||
|
True)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
||||||
|
def test_validate_boot_parameters_for_trusted_boot_one(self, mock_log):
|
||||||
|
properties = {'capabilities': 'boot_mode:uefi'}
|
||||||
|
instance_info = {"boot_option": "netboot"}
|
||||||
|
self.node.properties = properties
|
||||||
|
self.node.instance_info['capabilities'] = instance_info
|
||||||
|
self.node.driver_internal_info['is_whole_disk_image'] = False
|
||||||
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
|
pxe_utils.validate_boot_parameters_for_trusted_boot,
|
||||||
|
self.node)
|
||||||
|
self.assertTrue(mock_log.called)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
||||||
|
def test_validate_boot_parameters_for_trusted_boot_two(self, mock_log):
|
||||||
|
properties = {'capabilities': 'boot_mode:bios'}
|
||||||
|
instance_info = {"boot_option": "local"}
|
||||||
|
self.node.properties = properties
|
||||||
|
self.node.instance_info['capabilities'] = instance_info
|
||||||
|
self.node.driver_internal_info['is_whole_disk_image'] = False
|
||||||
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
|
pxe_utils.validate_boot_parameters_for_trusted_boot,
|
||||||
|
self.node)
|
||||||
|
self.assertTrue(mock_log.called)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
||||||
|
def test_validate_boot_parameters_for_trusted_boot_three(self, mock_log):
|
||||||
|
properties = {'capabilities': 'boot_mode:bios'}
|
||||||
|
instance_info = {"boot_option": "netboot"}
|
||||||
|
self.node.properties = properties
|
||||||
|
self.node.instance_info['capabilities'] = instance_info
|
||||||
|
self.node.driver_internal_info['is_whole_disk_image'] = True
|
||||||
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
|
pxe_utils.validate_boot_parameters_for_trusted_boot,
|
||||||
|
self.node)
|
||||||
|
self.assertTrue(mock_log.called)
|
||||||
|
|
||||||
|
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
||||||
|
def test_validate_boot_parameters_for_trusted_boot_pass(self, mock_log):
|
||||||
|
properties = {'capabilities': 'boot_mode:bios'}
|
||||||
|
instance_info = {"boot_option": "netboot"}
|
||||||
|
self.node.properties = properties
|
||||||
|
self.node.instance_info['capabilities'] = instance_info
|
||||||
|
self.node.driver_internal_info['is_whole_disk_image'] = False
|
||||||
|
pxe_utils.validate_boot_parameters_for_trusted_boot(self.node)
|
||||||
|
self.assertFalse(mock_log.called)
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch.object(pxe.PXEBoot, '__init__', lambda self: None)
|
||||||
|
class PXEBuildConfigOptionsTestCase(db_base.DbTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(PXEBuildConfigOptionsTestCase, self).setUp()
|
||||||
|
n = {
|
||||||
|
'driver': 'fake-hardware',
|
||||||
|
'boot_interface': 'pxe',
|
||||||
|
'instance_info': INST_INFO_DICT,
|
||||||
|
'driver_info': DRV_INFO_DICT,
|
||||||
|
'driver_internal_info': DRV_INTERNAL_INFO_DICT,
|
||||||
|
}
|
||||||
|
self.config_temp_dir('http_root', group='deploy')
|
||||||
|
self.node = object_utils.create_test_node(self.context, **n)
|
||||||
|
|
||||||
@mock.patch('ironic.common.utils.render_template', autospec=True)
|
@mock.patch('ironic.common.utils.render_template', autospec=True)
|
||||||
def _test_build_pxe_config_options_pxe(self, render_mock,
|
def _test_build_pxe_config_options_pxe(self, render_mock,
|
||||||
whle_dsk_img=False,
|
whle_dsk_img=False,
|
||||||
@ -1294,6 +1280,122 @@ class PXEInterfacesTestCase(db_base.DbTestCase):
|
|||||||
'ipxe_timeout': 0}
|
'ipxe_timeout': 0}
|
||||||
self.assertEqual(expected_options, options)
|
self.assertEqual(expected_options, options)
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch.object(ipxe.iPXEBoot, '__init__', lambda self: None)
|
||||||
|
class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(iPXEBuildConfigOptionsTestCase, self).setUp()
|
||||||
|
n = {
|
||||||
|
'driver': 'fake-hardware',
|
||||||
|
'boot_interface': 'ipxe',
|
||||||
|
'instance_info': INST_INFO_DICT,
|
||||||
|
'driver_info': DRV_INFO_DICT,
|
||||||
|
'driver_internal_info': DRV_INTERNAL_INFO_DICT,
|
||||||
|
}
|
||||||
|
self.config(enabled_boot_interfaces=['ipxe'])
|
||||||
|
self.config_temp_dir('http_root', group='deploy')
|
||||||
|
self.node = object_utils.create_test_node(self.context, **n)
|
||||||
|
|
||||||
|
def _dhcp_options_for_instance_ipxe(self, task, boot_file, ip_version=4):
|
||||||
|
self.config(ipxe_boot_script='/test/boot.ipxe', group='pxe')
|
||||||
|
self.config(tftp_root='/tftp-path/', group='pxe')
|
||||||
|
if ip_version == 4:
|
||||||
|
self.config(tftp_server='192.0.2.1', group='pxe')
|
||||||
|
self.config(http_url='http://192.0.3.2:1234', group='deploy')
|
||||||
|
self.config(ipxe_boot_script='/test/boot.ipxe', group='pxe')
|
||||||
|
elif ip_version == 6:
|
||||||
|
self.config(tftp_server='ff80::1', group='pxe')
|
||||||
|
self.config(http_url='http://[ff80::1]:1234', group='deploy')
|
||||||
|
|
||||||
|
self.config(dhcp_provider='isc', group='dhcp')
|
||||||
|
if ip_version == 6:
|
||||||
|
# NOTE(TheJulia): DHCPv6 RFCs seem to indicate that the prior
|
||||||
|
# options are not imported, although they may be supported
|
||||||
|
# by vendors. The apparent proper option is to return a
|
||||||
|
# URL in the field https://tools.ietf.org/html/rfc5970#section-3
|
||||||
|
expected_boot_script_url = 'http://[ff80::1]:1234/boot.ipxe'
|
||||||
|
expected_info = [{'opt_name': '!175,59',
|
||||||
|
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '59',
|
||||||
|
'opt_value': expected_boot_script_url,
|
||||||
|
'ip_version': ip_version}]
|
||||||
|
|
||||||
|
elif ip_version == 4:
|
||||||
|
expected_boot_script_url = 'http://192.0.3.2:1234/boot.ipxe'
|
||||||
|
expected_info = [{'opt_name': '!175,67',
|
||||||
|
'opt_value': boot_file,
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '66',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '150',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '67',
|
||||||
|
'opt_value': expected_boot_script_url,
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': 'server-ip-address',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version}]
|
||||||
|
|
||||||
|
self.assertItemsEqual(expected_info,
|
||||||
|
pxe_utils.dhcp_options_for_instance(
|
||||||
|
task, ipxe_enabled=True))
|
||||||
|
|
||||||
|
self.config(dhcp_provider='neutron', group='dhcp')
|
||||||
|
if ip_version == 6:
|
||||||
|
# Boot URL variable set from prior test of isc parameters.
|
||||||
|
expected_info = [{'opt_name': 'tag:!ipxe6,59',
|
||||||
|
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': 'tag:ipxe6,59',
|
||||||
|
'opt_value': expected_boot_script_url,
|
||||||
|
'ip_version': ip_version}]
|
||||||
|
|
||||||
|
elif ip_version == 4:
|
||||||
|
expected_info = [{'opt_name': 'tag:!ipxe,67',
|
||||||
|
'opt_value': boot_file,
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '66',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': '150',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': 'tag:ipxe,67',
|
||||||
|
'opt_value': expected_boot_script_url,
|
||||||
|
'ip_version': ip_version},
|
||||||
|
{'opt_name': 'server-ip-address',
|
||||||
|
'opt_value': '192.0.2.1',
|
||||||
|
'ip_version': ip_version}]
|
||||||
|
|
||||||
|
self.assertItemsEqual(expected_info,
|
||||||
|
pxe_utils.dhcp_options_for_instance(
|
||||||
|
task, ipxe_enabled=True))
|
||||||
|
|
||||||
|
def test_dhcp_options_for_instance_ipxe_bios(self):
|
||||||
|
self.config(ip_version=4, group='pxe')
|
||||||
|
boot_file = 'fake-bootfile-bios'
|
||||||
|
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
||||||
|
|
||||||
|
def test_dhcp_options_for_instance_ipxe_uefi(self):
|
||||||
|
self.config(ip_version=4, group='pxe')
|
||||||
|
boot_file = 'fake-bootfile-uefi'
|
||||||
|
self.config(uefi_pxe_bootfile_name=boot_file, group='pxe')
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
task.node.properties['capabilities'] = 'boot_mode:uefi'
|
||||||
|
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
||||||
|
|
||||||
|
def test_dhcp_options_for_ipxe_ipv6(self):
|
||||||
|
self.config(ip_version=6, group='pxe')
|
||||||
|
boot_file = 'fake-bootfile'
|
||||||
|
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
self._dhcp_options_for_instance_ipxe(task, boot_file, ip_version=6)
|
||||||
|
|
||||||
@mock.patch('ironic.common.image_service.GlanceImageService',
|
@mock.patch('ironic.common.image_service.GlanceImageService',
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@mock.patch('ironic.common.utils.render_template', autospec=True)
|
@mock.patch('ironic.common.utils.render_template', autospec=True)
|
||||||
@ -1319,7 +1421,6 @@ class PXEInterfacesTestCase(db_base.DbTestCase):
|
|||||||
tftp_server = CONF.pxe.tftp_server
|
tftp_server = CONF.pxe.tftp_server
|
||||||
|
|
||||||
http_url = 'http://192.1.2.3:1234'
|
http_url = 'http://192.1.2.3:1234'
|
||||||
self.config(ipxe_enabled=True, group='pxe')
|
|
||||||
self.config(http_url=http_url, group='deploy')
|
self.config(http_url=http_url, group='deploy')
|
||||||
|
|
||||||
kernel_label = '%s_kernel' % mode
|
kernel_label = '%s_kernel' % mode
|
||||||
@ -1601,103 +1702,28 @@ class PXEInterfacesTestCase(db_base.DbTestCase):
|
|||||||
self._test_build_pxe_config_options_ipxe(mode='rescue',
|
self._test_build_pxe_config_options_ipxe(mode='rescue',
|
||||||
ipxe_timeout=120)
|
ipxe_timeout=120)
|
||||||
|
|
||||||
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
@mock.patch('ironic.common.utils.rmtree_without_raise', autospec=True)
|
||||||
def test__cache_tftp_images_master_path(self, mock_fetch_image):
|
@mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True)
|
||||||
temp_dir = tempfile.mkdtemp()
|
def test_clean_up_ipxe_config_uefi(self, unlink_mock, rmtree_mock):
|
||||||
self.config(tftp_root=temp_dir, group='pxe')
|
self.config(http_root='/httpboot', group='deploy')
|
||||||
self.config(tftp_master_path=os.path.join(temp_dir,
|
address = "aa:aa:aa:aa:aa:aa"
|
||||||
'tftp_master_path'),
|
|
||||||
group='pxe')
|
|
||||||
image_path = os.path.join(temp_dir, self.node.uuid,
|
|
||||||
'deploy_kernel')
|
|
||||||
image_info = {'deploy_kernel': ('deploy_kernel', image_path)}
|
|
||||||
fileutils.ensure_tree(CONF.pxe.tftp_master_path)
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
|
||||||
shared=True) as task:
|
|
||||||
pxe_utils.cache_ramdisk_kernel(task, image_info)
|
|
||||||
|
|
||||||
mock_fetch_image.assert_called_once_with(self.context,
|
|
||||||
mock.ANY,
|
|
||||||
[('deploy_kernel',
|
|
||||||
image_path)],
|
|
||||||
True)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils, 'TFTPImageCache', lambda: None)
|
|
||||||
@mock.patch.object(fileutils, 'ensure_tree', autospec=True)
|
|
||||||
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
|
||||||
def test_cache_ramdisk_kernel(self, mock_fetch_image, mock_ensure_tree):
|
|
||||||
self.config(ipxe_enabled=False, group='pxe')
|
|
||||||
fake_pxe_info = {'foo': 'bar'}
|
|
||||||
expected_path = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
|
||||||
shared=True) as task:
|
|
||||||
pxe_utils.cache_ramdisk_kernel(task, fake_pxe_info)
|
|
||||||
mock_ensure_tree.assert_called_with(expected_path)
|
|
||||||
mock_fetch_image.assert_called_once_with(
|
|
||||||
self.context, mock.ANY, list(fake_pxe_info.values()), True)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils, 'TFTPImageCache', lambda: None)
|
|
||||||
@mock.patch.object(fileutils, 'ensure_tree', autospec=True)
|
|
||||||
@mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
|
|
||||||
def test_cache_ramdisk_kernel_ipxe(self, mock_fetch_image,
|
|
||||||
mock_ensure_tree):
|
|
||||||
fake_pxe_info = {'foo': 'bar'}
|
|
||||||
expected_path = os.path.join(CONF.deploy.http_root,
|
|
||||||
self.node.uuid)
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
|
||||||
shared=True) as task:
|
|
||||||
pxe_utils.cache_ramdisk_kernel(task, fake_pxe_info,
|
|
||||||
ipxe_enabled=True)
|
|
||||||
mock_ensure_tree.assert_called_with(expected_path)
|
|
||||||
mock_fetch_image.assert_called_once_with(self.context, mock.ANY,
|
|
||||||
list(fake_pxe_info.values()),
|
|
||||||
True)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
|
||||||
def test_validate_boot_parameters_for_trusted_boot_one(self, mock_log):
|
|
||||||
properties = {'capabilities': 'boot_mode:uefi'}
|
properties = {'capabilities': 'boot_mode:uefi'}
|
||||||
instance_info = {"boot_option": "netboot"}
|
object_utils.create_test_port(self.context, node_id=self.node.id,
|
||||||
self.node.properties = properties
|
address=address)
|
||||||
self.node.instance_info['capabilities'] = instance_info
|
|
||||||
self.node.driver_internal_info['is_whole_disk_image'] = False
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
pxe.validate_boot_parameters_for_trusted_boot,
|
|
||||||
self.node)
|
|
||||||
self.assertTrue(mock_log.called)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
def test_validate_boot_parameters_for_trusted_boot_two(self, mock_log):
|
task.node.properties = properties
|
||||||
properties = {'capabilities': 'boot_mode:bios'}
|
pxe_utils.clean_up_pxe_config(task, ipxe_enabled=True)
|
||||||
instance_info = {"boot_option": "local"}
|
|
||||||
self.node.properties = properties
|
|
||||||
self.node.instance_info['capabilities'] = instance_info
|
|
||||||
self.node.driver_internal_info['is_whole_disk_image'] = False
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
pxe.validate_boot_parameters_for_trusted_boot,
|
|
||||||
self.node)
|
|
||||||
self.assertTrue(mock_log.called)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
ensure_calls = [
|
||||||
def test_validate_boot_parameters_for_trusted_boot_three(self, mock_log):
|
mock.call("/httpboot/pxelinux.cfg/%s"
|
||||||
properties = {'capabilities': 'boot_mode:bios'}
|
% address.replace(':', '-')),
|
||||||
instance_info = {"boot_option": "netboot"}
|
mock.call("/httpboot/%s.conf" % address)
|
||||||
self.node.properties = properties
|
]
|
||||||
self.node.instance_info['capabilities'] = instance_info
|
|
||||||
self.node.driver_internal_info['is_whole_disk_image'] = True
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
pxe.validate_boot_parameters_for_trusted_boot,
|
|
||||||
self.node)
|
|
||||||
self.assertTrue(mock_log.called)
|
|
||||||
|
|
||||||
@mock.patch.object(pxe_utils.LOG, 'error', autospec=True)
|
unlink_mock.assert_has_calls(ensure_calls)
|
||||||
def test_validate_boot_parameters_for_trusted_boot_pass(self, mock_log):
|
rmtree_mock.assert_called_once_with(
|
||||||
properties = {'capabilities': 'boot_mode:bios'}
|
os.path.join(CONF.deploy.http_root, self.node.uuid))
|
||||||
instance_info = {"boot_option": "netboot"}
|
|
||||||
self.node.properties = properties
|
|
||||||
self.node.instance_info['capabilities'] = instance_info
|
|
||||||
self.node.driver_internal_info['is_whole_disk_image'] = False
|
|
||||||
pxe.validate_boot_parameters_for_trusted_boot(self.node)
|
|
||||||
self.assertFalse(mock_log.called)
|
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(ironic_utils, 'unlink_without_raise', autospec=True)
|
@mock.patch.object(ironic_utils, 'unlink_without_raise', autospec=True)
|
||||||
|
@ -40,6 +40,7 @@ from ironic.drivers.modules.irmc import boot as irmc_boot
|
|||||||
from ironic.drivers.modules.irmc import common as irmc_common
|
from ironic.drivers.modules.irmc import common as irmc_common
|
||||||
from ironic.drivers.modules.irmc import management as irmc_management
|
from ironic.drivers.modules.irmc import management as irmc_management
|
||||||
from ironic.drivers.modules import pxe
|
from ironic.drivers.modules import pxe
|
||||||
|
from ironic.drivers.modules import pxe_base
|
||||||
from ironic.tests import base
|
from ironic.tests import base
|
||||||
from ironic.tests.unit.db import utils as db_utils
|
from ironic.tests.unit.db import utils as db_utils
|
||||||
from ironic.tests.unit.drivers.modules.irmc import test_common
|
from ironic.tests.unit.drivers.modules.irmc import test_common
|
||||||
@ -1889,7 +1890,7 @@ class IRMCPXEBootBasicTestCase(test_pxe.PXEBootTestCase):
|
|||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
properties = task.driver.get_properties()
|
properties = task.driver.get_properties()
|
||||||
for p in pxe.COMMON_PROPERTIES:
|
for p in pxe_base.COMMON_PROPERTIES:
|
||||||
self.assertIn(p, properties)
|
self.assertIn(p, properties)
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,17 +25,15 @@ class ExternalInterfaceTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ExternalInterfaceTestCase, self).setUp()
|
super(ExternalInterfaceTestCase, self).setUp()
|
||||||
self.config(ipxe_enabled=True,
|
self.config(enabled_storage_interfaces=['noop', 'external'],
|
||||||
group='pxe')
|
enabled_boot_interfaces=['fake', 'pxe'])
|
||||||
self.config(enabled_storage_interfaces=['noop', 'external'])
|
|
||||||
self.interface = external.ExternalStorage()
|
self.interface = external.ExternalStorage()
|
||||||
|
|
||||||
@mock.patch.object(external, 'LOG', autospec=True)
|
@mock.patch.object(external, 'LOG', autospec=True)
|
||||||
def test_validate_fails_with_ipxe_not_enabled(self, mock_log):
|
def test_validate_fails_with_ipxe_not_enabled(self, mock_log):
|
||||||
"""Ensure a validation failure is raised when iPXE not enabled."""
|
"""Ensure a validation failure is raised when iPXE not enabled."""
|
||||||
self.config(ipxe_enabled=False, group='pxe')
|
|
||||||
self.node = object_utils.create_test_node(
|
self.node = object_utils.create_test_node(
|
||||||
self.context, storage_interface='external')
|
self.context, storage_interface='external', boot_interface='pxe')
|
||||||
object_utils.create_test_volume_connector(
|
object_utils.create_test_volume_connector(
|
||||||
self.context, node_id=self.node.id, type='iqn',
|
self.context, node_id=self.node.id, type='iqn',
|
||||||
connector_id='foo.address')
|
connector_id='foo.address')
|
||||||
@ -48,8 +46,8 @@ class ExternalInterfaceTestCase(db_base.DbTestCase):
|
|||||||
task)
|
task)
|
||||||
self.assertTrue(mock_log.error.called)
|
self.assertTrue(mock_log.error.called)
|
||||||
|
|
||||||
# Prevent /httpboot validation on creating the node
|
# Prevents creating iPXE boot script
|
||||||
@mock.patch('ironic.drivers.modules.pxe.PXEBoot.__init__',
|
@mock.patch('ironic.drivers.modules.ipxe.iPXEBoot.__init__',
|
||||||
lambda self: None)
|
lambda self: None)
|
||||||
def test_should_write_image(self):
|
def test_should_write_image(self):
|
||||||
self.node = object_utils.create_test_node(
|
self.node = object_utils.create_test_node(
|
||||||
|
@ -86,7 +86,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
self.config(group='conductor', api_url='http://127.0.0.1:1234/')
|
self.config(group='conductor', api_url='http://127.0.0.1:1234/')
|
||||||
|
|
||||||
def test_get_properties(self):
|
def test_get_properties(self):
|
||||||
expected = ipxe.COMMON_PROPERTIES
|
expected = pxe_base.COMMON_PROPERTIES
|
||||||
expected.update(agent_base.VENDOR_PROPERTIES)
|
expected.update(agent_base.VENDOR_PROPERTIES)
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
@ -415,7 +415,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
self, render_mock, write_mock):
|
self, render_mock, write_mock):
|
||||||
self.node.provision_state = states.DEPLOYING
|
self.node.provision_state = states.DEPLOYING
|
||||||
self.node.save()
|
self.node.save()
|
||||||
self.config(group='pxe', ipxe_enabled=False)
|
|
||||||
render_mock.return_value = 'foo'
|
render_mock.return_value = 'foo'
|
||||||
self._test_prepare_ramdisk()
|
self._test_prepare_ramdisk()
|
||||||
write_mock.assert_called_once_with(
|
write_mock.assert_called_once_with(
|
||||||
@ -435,7 +434,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
self, render_mock, write_mock, file_has_content_mock):
|
self, render_mock, write_mock, file_has_content_mock):
|
||||||
self.node.provision_state = states.DEPLOYING
|
self.node.provision_state = states.DEPLOYING
|
||||||
self.node.save()
|
self.node.save()
|
||||||
self.config(group='pxe', ipxe_enabled=False)
|
|
||||||
render_mock.return_value = 'foo'
|
render_mock.return_value = 'foo'
|
||||||
self._test_prepare_ramdisk()
|
self._test_prepare_ramdisk()
|
||||||
self.assertFalse(file_has_content_mock.called)
|
self.assertFalse(file_has_content_mock.called)
|
||||||
@ -456,7 +454,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
self, render_mock, write_mock):
|
self, render_mock, write_mock):
|
||||||
self.node.provision_state = states.DEPLOYING
|
self.node.provision_state = states.DEPLOYING
|
||||||
self.node.save()
|
self.node.save()
|
||||||
self.config(group='pxe', ipxe_enabled=False)
|
|
||||||
self._test_prepare_ramdisk()
|
self._test_prepare_ramdisk()
|
||||||
self.assertFalse(write_mock.called)
|
self.assertFalse(write_mock.called)
|
||||||
|
|
||||||
@ -465,7 +462,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
def test_prepare_ramdisk_ipxe_swift(self, write_mock):
|
def test_prepare_ramdisk_ipxe_swift(self, write_mock):
|
||||||
self.node.provision_state = states.DEPLOYING
|
self.node.provision_state = states.DEPLOYING
|
||||||
self.node.save()
|
self.node.save()
|
||||||
self.config(group='pxe', ipxe_enabled=False)
|
|
||||||
self.config(group='pxe', ipxe_use_swift=True)
|
self.config(group='pxe', ipxe_use_swift=True)
|
||||||
self._test_prepare_ramdisk(ipxe_use_swift=True)
|
self._test_prepare_ramdisk(ipxe_use_swift=True)
|
||||||
write_mock.assert_called_once_with(
|
write_mock.assert_called_once_with(
|
||||||
@ -480,7 +476,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
self, write_mock):
|
self, write_mock):
|
||||||
self.node.provision_state = states.DEPLOYING
|
self.node.provision_state = states.DEPLOYING
|
||||||
self.node.save()
|
self.node.save()
|
||||||
self.config(group='pxe', ipxe_enabled=False)
|
|
||||||
self.config(group='pxe', ipxe_use_swift=True)
|
self.config(group='pxe', ipxe_use_swift=True)
|
||||||
self._test_prepare_ramdisk(ipxe_use_swift=True, whole_disk_image=True)
|
self._test_prepare_ramdisk(ipxe_use_swift=True, whole_disk_image=True)
|
||||||
write_mock.assert_called_once_with(
|
write_mock.assert_called_once_with(
|
||||||
@ -774,7 +769,6 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
|||||||
dhcp_factory_mock, switch_pxe_config_mock,
|
dhcp_factory_mock, switch_pxe_config_mock,
|
||||||
set_boot_device_mock, create_pxe_config_mock):
|
set_boot_device_mock, create_pxe_config_mock):
|
||||||
http_url = 'http://192.1.2.3:1234'
|
http_url = 'http://192.1.2.3:1234'
|
||||||
self.config(ipxe_enabled=False, group='pxe')
|
|
||||||
self.config(http_url=http_url, group='deploy')
|
self.config(http_url=http_url, group='deploy')
|
||||||
provider_mock = mock.MagicMock()
|
provider_mock = mock.MagicMock()
|
||||||
dhcp_factory_mock.return_value = provider_mock
|
dhcp_factory_mock.return_value = provider_mock
|
||||||
|
@ -88,7 +88,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
self.config(group='conductor', api_url='http://127.0.0.1:1234/')
|
self.config(group='conductor', api_url='http://127.0.0.1:1234/')
|
||||||
|
|
||||||
def test_get_properties(self):
|
def test_get_properties(self):
|
||||||
expected = pxe.COMMON_PROPERTIES
|
expected = pxe_base.COMMON_PROPERTIES
|
||||||
expected.update(agent_base.VENDOR_PROPERTIES)
|
expected.update(agent_base.VENDOR_PROPERTIES)
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
@ -266,7 +266,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
self.node.save()
|
self.node.save()
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
||||||
task, ipxe_enabled=CONF.pxe.ipxe_enabled)
|
task, ipxe_enabled=False)
|
||||||
task.driver.boot.prepare_ramdisk(task, {'foo': 'bar'})
|
task.driver.boot.prepare_ramdisk(task, {'foo': 'bar'})
|
||||||
mock_deploy_img_info.assert_called_once_with(task.node,
|
mock_deploy_img_info.assert_called_once_with(task.node,
|
||||||
mode=mode,
|
mode=mode,
|
||||||
@ -594,7 +594,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
self.node.save()
|
self.node.save()
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
||||||
task, ipxe_enabled=CONF.pxe.ipxe_enabled)
|
task, ipxe_enabled=False)
|
||||||
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
||||||
task.node.uuid)
|
task.node.uuid)
|
||||||
task.node.properties['capabilities'] = 'boot_mode:bios'
|
task.node.properties['capabilities'] = 'boot_mode:bios'
|
||||||
@ -688,7 +688,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
task.node.save()
|
task.node.save()
|
||||||
task.driver.boot.prepare_instance(task)
|
task.driver.boot.prepare_instance(task)
|
||||||
clean_up_pxe_config_mock.assert_called_once_with(
|
clean_up_pxe_config_mock.assert_called_once_with(
|
||||||
task, ipxe_enabled=CONF.pxe.ipxe_enabled)
|
task, ipxe_enabled=False)
|
||||||
set_boot_device_mock.assert_called_once_with(task,
|
set_boot_device_mock.assert_called_once_with(task,
|
||||||
boot_devices.DISK,
|
boot_devices.DISK,
|
||||||
persistent=True)
|
persistent=True)
|
||||||
@ -706,7 +706,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
task.node.save()
|
task.node.save()
|
||||||
task.driver.boot.prepare_instance(task)
|
task.driver.boot.prepare_instance(task)
|
||||||
clean_up_pxe_config_mock.assert_called_once_with(
|
clean_up_pxe_config_mock.assert_called_once_with(
|
||||||
task, ipxe_enabled=CONF.pxe.ipxe_enabled)
|
task, ipxe_enabled=False)
|
||||||
self.assertFalse(set_boot_device_mock.called)
|
self.assertFalse(set_boot_device_mock.called)
|
||||||
|
|
||||||
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
|
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
|
||||||
@ -733,7 +733,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
task.node.instance_info = instance_info
|
task.node.instance_info = instance_info
|
||||||
task.node.save()
|
task.node.save()
|
||||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
dhcp_opts = pxe_utils.dhcp_options_for_instance(
|
||||||
task, ipxe_enabled=CONF.pxe.ipxe_enabled)
|
task, ipxe_enabled=False)
|
||||||
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
||||||
task.node.uuid)
|
task.node.uuid)
|
||||||
task.driver.boot.prepare_instance(task)
|
task.driver.boot.prepare_instance(task)
|
||||||
@ -741,7 +741,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
get_image_info_mock.assert_called_once_with(task,
|
get_image_info_mock.assert_called_once_with(task,
|
||||||
ipxe_enabled=False)
|
ipxe_enabled=False)
|
||||||
cache_mock.assert_called_once_with(
|
cache_mock.assert_called_once_with(
|
||||||
task, image_info, CONF.pxe.ipxe_enabled)
|
task, image_info, False)
|
||||||
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
|
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
|
||||||
if config_file_exits:
|
if config_file_exits:
|
||||||
self.assertFalse(create_pxe_config_mock.called)
|
self.assertFalse(create_pxe_config_mock.called)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user