Source code for ironic.drivers.modules.autodetect

# 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 oslo_log import log as logging

from ironic.common import driver_factory
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import metrics_utils
from ironic.conf import CONF
from ironic.drivers import base

LOG = logging.getLogger(__name__)

METRICS = metrics_utils.get_metrics_logger(__name__)


[docs] class AutodetectDeploy(base.DeployInterface): """Deploy interface that auto-detects the appropriate deployment method. """ def __init__(self): super(AutodetectDeploy, self).__init__() # Validate that all autodetect interfaces are enabled for interface_name in CONF.autodetect_deploy_interfaces: self._validate_autodetect_interface(interface_name) def _validate_autodetect_interface(self, interface_name): """Validate that the autodetect interface is enabled. :param interface_name: Name of the deploy interface to validate. :raises: InvalidParameterValue if the interface is not enabled. """ enabled_interfaces = CONF.enabled_deploy_interfaces if interface_name not in enabled_interfaces: raise exception.InvalidParameterValue( _("Deploy interface '%(interface)s' is configured in " "autodetect_deploy_interfaces but is not in " "enabled_deploy_interfaces. Please add '%(interface)s' " "to enabled_deploy_interfaces or remove it from " "autodetect_deploy_interfaces.") % {'interface': interface_name})
[docs] def get_properties(self): """Return the properties of the interface. :returns: dictionary of <property name>:<property description> entries. """ return {}
[docs] @METRICS.timer('AutodetectDeploy.validate') def validate(self, task): """Validate the driver-specific Node deployment info. This method creates the deploy interface that would be switched to and calls its validate() method. :param task: A TaskManager instance containing the node to act on. :raises: MissingParameterValue if required parameters are missing. """ switchable = self._create_switchable_interface(task) interface, interface_name, interface_supports = switchable return interface.validate(task)
[docs] @METRICS.timer('AutodetectDeploy.deploy') @base.deploy_step(priority=100) def deploy(self, task): """Perform a deployment to the task's node. This method should not be called directly as the autodetect interface is expected to switch to a concrete interface during switch_interface(). If this is called, it means the interface switch did not happen. :param task: A TaskManager instance containing the node to act on. :raises: InstanceDeployFailure if deployment fails. """ raise exception.InstanceDeployFailure( _("Autodetect deploy interface did not switch to a concrete " "interface during switch_interface(). This indicates a bug or " "misconfiguration."))
[docs] @METRICS.timer('AutodetectDeploy.tear_down') def tear_down(self, task): """Tear down a previous deployment on the task's node. :param task: A TaskManager instance containing the node to act on. :returns: deploy state DELETED. """ # Autodetect deploy interface does not perform any actual deployment. # This is handled by AgentBaseMixin.tear_down() for actual deployments pass
[docs] @METRICS.timer('AutodetectDeploy.prepare') def prepare(self, task): """Prepare the deployment environment for the task's node. """ # Autodetect deploy interface does not perform any actual deployment. # This is handled by AgentBaseMixin.prepare() for actual deployments raise exception.InstanceDeployFailure( _("Autodetect deploy interface did not switch to a concrete " "interface during switch_interface(). This indicates a bug or " "misconfiguration."))
[docs] @METRICS.timer('AutodetectDeploy.clean_up') def clean_up(self, task): """Clean up the deployment environment for the task's node. :param task: A TaskManager instance containing the node to act on. """ pass
[docs] @METRICS.timer('AutodetectDeploy.take_over') def take_over(self, task): """Take over management of this task's node from a dead conductor. :param task: A TaskManager instance containing the node to act on. """ pass
def _create_switchable_interface(self, task): """Detect and create the deploy interface to switch to. :param task: A TaskManager instance containing the node to act on. :raises: InvalidParameterValue if the interface is not enabled. :returns: A tuple of (interface instance, interface name, supports deploy). """ node = task.node hw_type = driver_factory.get_hardware_type(node.driver) interface = None interface_name = None interface_supports = False for interface_name in CONF.autodetect_deploy_interfaces: self._validate_autodetect_interface(interface_name) # Get the new deploy interface instance from the factory interface = driver_factory.get_interface( hw_type, 'deploy', interface_name) interface_supports = interface.supports_deploy(task) if interface_supports: break if not interface: raise exception.InvalidParameterValue( _("No valid deploy interfaces found in " "autodetect_deploy_interfaces configuration.")) return interface, interface_name, interface_supports
[docs] @METRICS.timer('AutodetectDeploy.switch_interface') def switch_interface(self, task): """Switch the interface to use for deployment. This calls supports_deploy() methods of deploy interfaces configured in the 'autodetect_deploy_interfaces' option, in order, to determine which interface is supported for the current node/image. The first interface that returns True from supports_deploy() is chosen. If no interfaces are detected as supported, the last interface in the list is chosen as the fallback. :raises: InvalidParameterValue if the interface is not enabled. :param task: A TaskManager instance containing the node to act on. """ switchable = self._create_switchable_interface(task) interface, interface_name, interface_supports = switchable if not interface_supports: LOG.warning("No deploy interfaces in autodetect_deploy_interfaces " "are supported for this node/image. " "Using last interface: %s", interface_name) LOG.info("autodetect switching to deploy interface: %s", interface_name) node = task.node # Save the original deploy interface to restore later node.set_driver_internal_info( 'original_deploy_interface', task.node.deploy_interface) # Update the node's deploy interface name node.deploy_interface = interface_name # Replace the deploy interface on the driver task.driver.deploy = interface node.save()