# Copyright 2015 Rackspace, Inc. # # 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 ironic_python_agent import errors from ironic_python_agent.extensions import base from ironic_python_agent import hardware class CleanExtension(base.BaseAgentExtension): @base.sync_command('get_clean_steps') def get_clean_steps(self, node, ports): """Get the list of clean steps supported for the node and ports :param node: A dict representation of a node :param ports: A dict representation of ports attached to node :returns: A list of clean steps with keys step, priority, and reboot_requested """ # Results should be a dict, not a list steps = hardware.dispatch_to_all_managers('get_clean_steps', node, ports) return { 'clean_steps': steps, 'hardware_manager_version': _get_current_clean_version() } @base.async_command('execute_clean_step') def execute_clean_step(self, step, node, ports, clean_version=None, **kwargs): """Execute a clean step :param step: A clean step with 'step', 'priority' and 'interface' keys :param node: A dict representation of a node :param ports: A dict representation of ports attached to node :param clean_version: The clean version as returned by _get_current_clean_version() at the beginning of cleaning/zapping :returns: a CommandResult object with command_result set to whatever the step returns. """ # Ensure the agent is still the same version, or raise an exception _check_clean_version(clean_version) if 'step' not in step: raise ValueError('Malformed clean_step, no "step" key: %s'.format( step)) try: result = hardware.dispatch_to_managers(step['step'], node, ports) except Exception as e: raise errors.CleaningError( 'Error performing clean_step %(step)s: %(err)s' % {'step': step['step'], 'err': e}) # Return the step that was executed so we can dispatch # to the appropriate Ironic interface return { 'clean_result': result, 'clean_step': step } def _check_clean_version(clean_version=None): """Ensure the clean version hasn't changed.""" # If the version is None, assume this is the first run if clean_version is None: return agent_version = _get_current_clean_version() if clean_version != agent_version: raise errors.CleanVersionMismatch(agent_version=agent_version, node_version=clean_version) def _get_current_clean_version(): return {version.get('name'): version.get('version') for version in hardware.dispatch_to_all_managers( 'get_version').values()}