summaryrefslogtreecommitdiff
path: root/ironic/conductor/inspection.py
blob: 53c76e99dda5ef50bf46188da84be2f42390ad23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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})