summaryrefslogtreecommitdiff
path: root/ironic/conductor/inspection.py
diff options
context:
space:
mode:
Diffstat (limited to 'ironic/conductor/inspection.py')
-rw-r--r--ironic/conductor/inspection.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/ironic/conductor/inspection.py b/ironic/conductor/inspection.py
new file mode 100644
index 000000000..53c76e99d
--- /dev/null
+++ b/ironic/conductor/inspection.py
@@ -0,0 +1,108 @@
+# 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.
+
+"""Inspection implementation for the conductor."""
+
+from oslo_log import log
+from oslo_utils import excutils
+
+from ironic.common import exception
+from ironic.common.i18n import _
+from ironic.common import states
+from ironic.conductor import task_manager
+from ironic.conductor import utils
+
+LOG = log.getLogger(__name__)
+
+
+@task_manager.require_exclusive_lock
+def inspect_hardware(task):
+ """Initiates inspection.
+
+ :param task: a TaskManager instance with an exclusive lock
+ on its node.
+ :raises: HardwareInspectionFailure if driver doesn't
+ return the state as states.MANAGEABLE, states.INSPECTWAIT.
+
+ """
+ node = task.node
+
+ def handle_failure(e, log_func=LOG.error):
+ utils.node_history_record(task.node, event=e,
+ event_type=states.INTROSPECTION,
+ error=True, user=task.context.user_id)
+ task.process_event('fail')
+ log_func("Failed to inspect node %(node)s: %(err)s",
+ {'node': node.uuid, 'err': e})
+
+ # Inspection cannot start in fast-track mode, wipe token and URL.
+ utils.wipe_token_and_url(task)
+
+ try:
+ new_state = task.driver.inspect.inspect_hardware(task)
+ except exception.IronicException as e:
+ with excutils.save_and_reraise_exception():
+ error = str(e)
+ handle_failure(error)
+ except Exception as e:
+ error = (_('Unexpected exception of type %(type)s: %(msg)s') %
+ {'type': type(e).__name__, 'msg': e})
+ handle_failure(error, log_func=LOG.exception)
+ raise exception.HardwareInspectionFailure(error=error)
+
+ if new_state == states.MANAGEABLE:
+ task.process_event('done')
+ LOG.info('Successfully inspected node %(node)s',
+ {'node': node.uuid})
+ elif new_state == states.INSPECTWAIT:
+ task.process_event('wait')
+ LOG.info('Successfully started introspection on node %(node)s',
+ {'node': node.uuid})
+ else:
+ error = (_("During inspection, driver returned unexpected "
+ "state %(state)s") % {'state': new_state})
+ handle_failure(error)
+ raise exception.HardwareInspectionFailure(error=error)
+
+
+@task_manager.require_exclusive_lock
+def abort_inspection(task):
+ """Abort inspection for the node."""
+ node = task.node
+
+ try:
+ task.driver.inspect.abort(task)
+ except exception.UnsupportedDriverExtension:
+ with excutils.save_and_reraise_exception():
+ LOG.error('Inspect interface "%(intf)s" does not support abort '
+ 'operation for node %(node)s',
+ {'intf': node.inspect_interface, 'node': node.uuid})
+ except Exception as e:
+ with excutils.save_and_reraise_exception():
+ LOG.exception('Error when aborting inspection of node %(node)s',
+ {'node': node.uuid})
+ error = _('Failed to abort inspection: %s') % e
+ utils.node_history_record(task.node, event=error,
+ event_type=states.INTROSPECTION,
+ error=True,
+ user=task.context.user_id)
+ node.save()
+
+ error = _('Inspection was aborted by request.')
+ utils.node_history_record(task.node, event=error,
+ event_type=states.INTROSPECTION,
+ error=True,
+ user=task.context.user_id)
+ utils.wipe_token_and_url(task)
+ task.process_event('abort')
+ LOG.info('Successfully aborted inspection of node %(node)s',
+ {'node': node.uuid})