Create base pxe class

Create a base class to de-duplicate code across
the pxe and ipxe interfaces.

Only methods that do not have variation due to differences
in iPXE behavior.

Change-Id: I101f5ba7d44274d2b9d7d3a763198bc6fcc67e7a
Task: 26738
Story: 1628069
This commit is contained in:
Julia Kreger 2018-10-08 15:10:41 -07:00
parent 9ccfc31c62
commit 5cb45a1756
5 changed files with 110 additions and 146 deletions

View File

@ -32,56 +32,22 @@ from ironic.drivers import base
from ironic.drivers.modules import boot_mode_utils
from ironic.drivers.modules import deploy_utils
from ironic.drivers.modules import pxe
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__)
# TODO(TheJulia): Lets rip these out ASAP and move them to a pxe_common.
# One chunk moving at a time for sanity.
REQUIRED_PROPERTIES = {
'deploy_kernel': _("UUID (from Glance) of the deployment kernel. "
"Required."),
'deploy_ramdisk': _("UUID (from Glance) of the ramdisk that is "
"mounted at boot time. Required."),
}
OPTIONAL_PROPERTIES = {
'force_persistent_boot_device': _("True to enable persistent behavior "
"when the boot device is set during "
"deploy and cleaning operations. "
"Defaults to False. Optional."),
}
RESCUE_PROPERTIES = {
'rescue_kernel': _('UUID (from Glance) of the rescue kernel. This value '
'is required for rescue mode.'),
'rescue_ramdisk': _('UUID (from Glance) of the rescue ramdisk with agent '
'that is used at node rescue time. This value is '
'required for rescue mode.'),
}
COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
COMMON_PROPERTIES.update(RESCUE_PROPERTIES)
# TODO(TheJulia): Use these as the copy to move, no reason to touch pxe.py at
# the same time as doing the initial split out as deduplication goes on.
COMMON_PROPERTIES = pxe_base.COMMON_PROPERTIES
class iPXEBoot(base.BootInterface):
class iPXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
capabilities = ['iscsi_volume_boot', 'ramdisk_boot', 'ipxe_boot']
def __init__(self):
pxe_utils.create_ipxe_boot_script()
def get_properties(self):
"""Return the properties of the interface.
:returns: dictionary of <property name>:<property description> entries.
"""
# TODO(stendulker): COMMON_PROPERTIES should also include rescue
# related properties (RESCUE_PROPERTIES). We can add them in Rocky,
# when classic drivers get removed.
return COMMON_PROPERTIES
@METRICS.timer('iPXEBoot.validate')
def validate(self, task):
"""Validate the PXE-specific info for booting deploy/instance images.
@ -212,33 +178,6 @@ class iPXEBoot(base.BootInterface):
if pxe_info:
pxe_utils.cache_ramdisk_kernel(task, pxe_info)
@METRICS.timer('iPXEBoot.clean_up_ramdisk')
def clean_up_ramdisk(self, task):
"""Cleans up the boot of ironic ramdisk.
This method cleans up the PXE environment that was setup for booting
the deploy or rescue ramdisk. It unlinks the deploy/rescue
kernel/ramdisk in the node's directory in tftproot and removes it's PXE
config.
:param task: a task from TaskManager.
:param mode: Label indicating a deploy or rescue operation
was carried out on the node. Supported values are 'deploy' and
'rescue'. Defaults to 'deploy', indicating deploy operation was
carried out.
:returns: None
"""
node = task.node
mode = deploy_utils.rescue_or_deploy_mode(node)
try:
images_info = pxe_utils.get_image_info(node, mode=mode)
except exception.MissingParameterValue as e:
LOG.warning('Could not get %(mode)s image info '
'to clean up images for node %(node)s: %(err)s',
{'mode': mode, 'node': node.uuid, 'err': e})
else:
pxe_utils.clean_up_pxe_env(task, images_info)
@METRICS.timer('iPXEBoot.prepare_instance')
def prepare_instance(self, task):
"""Prepares the boot of instance.
@ -346,13 +285,3 @@ class iPXEBoot(base.BootInterface):
{'node': node.uuid, 'err': e})
else:
pxe_utils.clean_up_pxe_env(task, images_info)
@METRICS.timer('iPXEBoot.validate_rescue')
def validate_rescue(self, task):
"""Validate that the node has required properties for rescue.
:param task: a TaskManager instance with the node being checked
:raises: MissingParameterValue if node is missing one or more required
parameters
"""
pxe_utils.parse_driver_info(task.node, mode='rescue')

View File

@ -33,32 +33,13 @@ from ironic.drivers import base
from ironic.drivers.modules import agent
from ironic.drivers.modules import boot_mode_utils
from ironic.drivers.modules import deploy_utils
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__)
REQUIRED_PROPERTIES = {
'deploy_kernel': _("UUID (from Glance) of the deployment kernel. "
"Required."),
'deploy_ramdisk': _("UUID (from Glance) of the ramdisk that is "
"mounted at boot time. Required."),
}
OPTIONAL_PROPERTIES = {
'force_persistent_boot_device': _("True to enable persistent behavior "
"when the boot device is set during "
"deploy and cleaning operations. "
"Defaults to False. Optional."),
}
RESCUE_PROPERTIES = {
'rescue_kernel': _('UUID (from Glance) of the rescue kernel. This value '
'is required for rescue mode.'),
'rescue_ramdisk': _('UUID (from Glance) of the rescue ramdisk with agent '
'that is used at node rescue time. This value is '
'required for rescue mode.'),
}
COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
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.
@ -67,8 +48,11 @@ TFTPImageCache = pxe_utils.TFTPImageCache
# NOTE(TheJulia): End section of mappings for migrated common pxe code.
class PXEBoot(base.BootInterface):
class PXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
# TODO(TheJulia): iscsi_volume_boot should be removed from
# the list below once ipxe support is removed from the PXE
# interface.
capabilities = ['iscsi_volume_boot', 'ramdisk_boot', 'ipxe_boot',
'pxe_boot']
@ -78,16 +62,6 @@ class PXEBoot(base.BootInterface):
if CONF.pxe.ipxe_enabled:
pxe_utils.create_ipxe_boot_script()
def get_properties(self):
"""Return the properties of the interface.
:returns: dictionary of <property name>:<property description> entries.
"""
# TODO(stendulker): COMMON_PROPERTIES should also include rescue
# related properties (RESCUE_PROPERTIES). We can add them in Rocky,
# when classic drivers get removed.
return COMMON_PROPERTIES
@METRICS.timer('PXEBoot.validate')
def validate(self, task):
"""Validate the PXE-specific info for booting deploy/instance images.
@ -211,33 +185,6 @@ class PXEBoot(base.BootInterface):
if pxe_info:
pxe_utils.cache_ramdisk_kernel(task, pxe_info)
@METRICS.timer('PXEBoot.clean_up_ramdisk')
def clean_up_ramdisk(self, task):
"""Cleans up the boot of ironic ramdisk.
This method cleans up the PXE environment that was setup for booting
the deploy or rescue ramdisk. It unlinks the deploy/rescue
kernel/ramdisk in the node's directory in tftproot and removes it's PXE
config.
:param task: a task from TaskManager.
:param mode: Label indicating a deploy or rescue operation
was carried out on the node. Supported values are 'deploy' and
'rescue'. Defaults to 'deploy', indicating deploy operation was
carried out.
:returns: None
"""
node = task.node
mode = deploy_utils.rescue_or_deploy_mode(node)
try:
images_info = pxe_utils.get_image_info(node, mode=mode)
except exception.MissingParameterValue as e:
LOG.warning('Could not get %(mode)s image info '
'to clean up images for node %(node)s: %(err)s',
{'mode': mode, 'node': node.uuid, 'err': e})
else:
pxe_utils.clean_up_pxe_env(task, images_info)
@METRICS.timer('PXEBoot.prepare_instance')
def prepare_instance(self, task):
"""Prepares the boot of instance.
@ -343,16 +290,6 @@ class PXEBoot(base.BootInterface):
else:
pxe_utils.clean_up_pxe_env(task, images_info)
@METRICS.timer('PXEBoot.validate_rescue')
def validate_rescue(self, task):
"""Validate that the node has required properties for rescue.
:param task: a TaskManager instance with the node being checked
:raises: MissingParameterValue if node is missing one or more required
parameters
"""
pxe_utils.parse_driver_info(task.node, mode='rescue')
class PXERamdiskDeploy(agent.AgentDeploy):

View File

@ -0,0 +1,95 @@
# 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.
"""
Base PXE Interface Methods
"""
from ironic_lib import metrics_utils
from oslo_log import log as logging
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import pxe_utils as pxe_utils
from ironic.drivers.modules import deploy_utils
LOG = logging.getLogger(__name__)
METRICS = metrics_utils.get_metrics_logger(__name__)
REQUIRED_PROPERTIES = {
'deploy_kernel': _("UUID (from Glance) of the deployment kernel. "
"Required."),
'deploy_ramdisk': _("UUID (from Glance) of the ramdisk that is "
"mounted at boot time. Required."),
}
OPTIONAL_PROPERTIES = {
'force_persistent_boot_device': _("True to enable persistent behavior "
"when the boot device is set during "
"deploy and cleaning operations. "
"Defaults to False. Optional."),
}
RESCUE_PROPERTIES = {
'rescue_kernel': _('UUID (from Glance) of the rescue kernel. This value '
'is required for rescue mode.'),
'rescue_ramdisk': _('UUID (from Glance) of the rescue ramdisk with agent '
'that is used at node rescue time. This value is '
'required for rescue mode.'),
}
COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
COMMON_PROPERTIES.update(RESCUE_PROPERTIES)
class PXEBaseMixin(object):
def get_properties(self):
"""Return the properties of the interface.
:returns: dictionary of <property name>:<property description> entries.
"""
return COMMON_PROPERTIES
@METRICS.timer('PXEBaseMixin.clean_up_ramdisk')
def clean_up_ramdisk(self, task):
"""Cleans up the boot of ironic ramdisk.
This method cleans up the PXE environment that was setup for booting
the deploy or rescue ramdisk. It unlinks the deploy/rescue
kernel/ramdisk in the node's directory in tftproot and removes it's PXE
config.
:param task: a task from TaskManager.
:param mode: Label indicating a deploy or rescue operation
was carried out on the node. Supported values are 'deploy' and
'rescue'. Defaults to 'deploy', indicating deploy operation was
carried out.
:returns: None
"""
node = task.node
mode = deploy_utils.rescue_or_deploy_mode(node)
try:
images_info = pxe_utils.get_image_info(node, mode=mode)
except exception.MissingParameterValue as e:
LOG.warning('Could not get %(mode)s image info '
'to clean up images for node %(node)s: %(err)s',
{'mode': mode, 'node': node.uuid, 'err': e})
else:
pxe_utils.clean_up_pxe_env(task, images_info)
@METRICS.timer('PXEBaseMixin.validate_rescue')
def validate_rescue(self, task):
"""Validate that the node has required properties for rescue.
:param task: a TaskManager instance with the node being checked
:raises: MissingParameterValue if node is missing one or more required
parameters
"""
pxe_utils.parse_driver_info(task.node, mode='rescue')

View File

@ -6816,7 +6816,8 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
'ipmi_target_address', 'ipmi_local_address',
'deploy_kernel', 'deploy_ramdisk',
'force_persistent_boot_device', 'ipmi_protocol_version',
'ipmi_force_boot_device', 'deploy_forces_oob_reboot']
'ipmi_force_boot_device', 'deploy_forces_oob_reboot',
'rescue_kernel', 'rescue_ramdisk']
self._check_driver_properties("ipmi", expected)
def test_driver_properties_snmp(self):
@ -6824,6 +6825,7 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
enabled_power_interfaces=['snmp'])
expected = ['deploy_kernel', 'deploy_ramdisk',
'force_persistent_boot_device',
'rescue_kernel', 'rescue_ramdisk',
'snmp_driver', 'snmp_address', 'snmp_port', 'snmp_version',
'snmp_community',
'snmp_community_read', 'snmp_community_write',
@ -6873,7 +6875,8 @@ class ManagerTestHardwareTypeProperties(mgr_utils.ServiceSetUpMixin,
def test_hardware_type_properties_manual_management(self):
expected = ['deploy_kernel', 'deploy_ramdisk',
'force_persistent_boot_device', 'deploy_forces_oob_reboot']
'force_persistent_boot_device', 'deploy_forces_oob_reboot',
'rescue_kernel', 'rescue_ramdisk']
self._check_hardware_type_properties('manual-management', expected)

View File

@ -67,7 +67,7 @@ class ManualManagementHardwareTestCase(db_base.DbTestCase):
# These properties are from vendor (agent) and boot (pxe) interfaces
expected_prop_keys = [
'deploy_forces_oob_reboot', 'deploy_kernel', 'deploy_ramdisk',
'force_persistent_boot_device']
'force_persistent_boot_device', 'rescue_kernel', 'rescue_ramdisk']
hardware_type = driver_factory.get_hardware_type("manual-management")
properties = hardware_type.get_properties()
self.assertEqual(sorted(expected_prop_keys), sorted(properties))