# Copyright 2014 Cisco Systems, Inc.
# All Rights Reserved.
#
#    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.

import json

import mock

from ironic.common import exception
from ironic.common import raid
from ironic.common import states
from ironic.drivers import base as driver_base
from ironic.drivers.modules import fake
from ironic.tests import base


class FakeVendorInterface(driver_base.VendorInterface):
    def get_properties(self):
        pass

    @driver_base.passthru(['POST'])
    def noexception(self):
        return "Fake"

    @driver_base.driver_passthru(['POST'])
    def driver_noexception(self):
        return "Fake"

    @driver_base.passthru(['POST'])
    def ironicexception(self):
        raise exception.IronicException("Fake!")

    @driver_base.passthru(['POST'])
    def normalexception(self):
        raise Exception("Fake!")

    @driver_base.passthru(['POST'], require_exclusive_lock=False)
    def shared_task(self):
        return "shared fake"

    def validate(self, task, **kwargs):
        pass

    def driver_validate(self, **kwargs):
        pass


class PassthruDecoratorTestCase(base.TestCase):

    def setUp(self):
        super(PassthruDecoratorTestCase, self).setUp()
        self.fvi = FakeVendorInterface()

    def test_passthru_noexception(self):
        result = self.fvi.noexception()
        self.assertEqual("Fake", result)

    @mock.patch.object(driver_base, 'LOG', autospec=True)
    def test_passthru_ironicexception(self, mock_log):
        self.assertRaises(exception.IronicException,
                          self.fvi.ironicexception, mock.ANY)
        mock_log.exception.assert_called_with(
            mock.ANY, 'ironicexception')

    @mock.patch.object(driver_base, 'LOG', autospec=True)
    def test_passthru_nonironicexception(self, mock_log):
        self.assertRaises(exception.VendorPassthruException,
                          self.fvi.normalexception, mock.ANY)
        mock_log.exception.assert_called_with(
            mock.ANY, 'normalexception')

    def test_passthru_shared_task_metadata(self):
        self.assertIn('require_exclusive_lock',
                      self.fvi.shared_task._vendor_metadata[1])
        self.assertFalse(
            self.fvi.shared_task._vendor_metadata[1]['require_exclusive_lock'])

    def test_passthru_exclusive_task_metadata(self):
        self.assertIn('require_exclusive_lock',
                      self.fvi.noexception._vendor_metadata[1])
        self.assertTrue(
            self.fvi.noexception._vendor_metadata[1]['require_exclusive_lock'])

    def test_passthru_check_func_references(self):
        inst1 = FakeVendorInterface()
        inst2 = FakeVendorInterface()

        self.assertNotEqual(inst1.vendor_routes['noexception']['func'],
                            inst2.vendor_routes['noexception']['func'])
        self.assertNotEqual(inst1.driver_routes['driver_noexception']['func'],
                            inst2.driver_routes['driver_noexception']['func'])


class CleanStepDecoratorTestCase(base.TestCase):

    def setUp(self):
        super(CleanStepDecoratorTestCase, self).setUp()
        method_mock = mock.MagicMock()
        del method_mock._is_clean_step
        del method_mock._clean_step_priority
        del method_mock._clean_step_abortable
        del method_mock._clean_step_argsinfo
        self.method = method_mock

    def test__validate_argsinfo(self):
        # None, empty dict
        driver_base._validate_argsinfo(None)
        driver_base._validate_argsinfo({})

        # Only description specified
        driver_base._validate_argsinfo({'arg1': {'description': 'desc1'}})

        # Multiple args
        driver_base._validate_argsinfo({'arg1': {'description': 'desc1',
                                                 'required': True},
                                        'arg2': {'description': 'desc2'}})

    def test__validate_argsinfo_not_dict(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'argsinfo.+dictionary',
                               driver_base._validate_argsinfo, 'not-a-dict')

    def test__validate_argsinfo_arg_not_dict(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'Argument.+dictionary',
                               driver_base._validate_argsinfo,
                               {'arg1': 'not-a-dict'})

    def test__validate_argsinfo_arg_empty_dict(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'description',
                               driver_base._validate_argsinfo,
                               {'arg1': {}})

    def test__validate_argsinfo_arg_missing_description(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'description',
                               driver_base._validate_argsinfo,
                               {'arg1': {'required': True}})

    def test__validate_argsinfo_arg_description_invalid(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'string',
                               driver_base._validate_argsinfo,
                               {'arg1': {'description': True}})

    def test__validate_argsinfo_arg_required_invalid(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'Boolean',
                               driver_base._validate_argsinfo,
                               {'arg1': {'description': 'desc1',
                                         'required': 'maybe'}})

    def test__validate_argsinfo_arg_unknown_key(self):
        self.assertRaisesRegex(exception.InvalidParameterValue,
                               'invalid',
                               driver_base._validate_argsinfo,
                               {'arg1': {'description': 'desc1',
                                         'unknown': 'bad'}})

    def test_clean_step_priority_only(self):
        d = driver_base.clean_step(priority=10)
        d(self.method)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(10, self.method._clean_step_priority)
        self.assertFalse(self.method._clean_step_abortable)
        self.assertIsNone(self.method._clean_step_argsinfo)

    def test_clean_step_all_args(self):
        argsinfo = {'arg1': {'description': 'desc1',
                             'required': True}}
        d = driver_base.clean_step(priority=0, abortable=True,
                                   argsinfo=argsinfo)
        d(self.method)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(0, self.method._clean_step_priority)
        self.assertTrue(self.method._clean_step_abortable)
        self.assertEqual(argsinfo, self.method._clean_step_argsinfo)

    def test_clean_step_bad_priority(self):
        d = driver_base.clean_step(priority='hi')
        self.assertRaisesRegex(exception.InvalidParameterValue, 'priority',
                               d, self.method)
        self.assertTrue(self.method._is_clean_step)
        self.assertFalse(hasattr(self.method, '_clean_step_priority'))
        self.assertFalse(hasattr(self.method, '_clean_step_abortable'))
        self.assertFalse(hasattr(self.method, '_clean_step_argsinfo'))

    def test_clean_step_bad_abortable(self):
        d = driver_base.clean_step(priority=0, abortable='blue')
        self.assertRaisesRegex(exception.InvalidParameterValue, 'abortable',
                               d, self.method)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(0, self.method._clean_step_priority)
        self.assertFalse(hasattr(self.method, '_clean_step_abortable'))
        self.assertFalse(hasattr(self.method, '_clean_step_argsinfo'))

    @mock.patch.object(driver_base, '_validate_argsinfo', spec_set=True,
                       autospec=True)
    def test_clean_step_bad_argsinfo(self, mock_valid):
        mock_valid.side_effect = exception.InvalidParameterValue('bad')
        d = driver_base.clean_step(priority=0, argsinfo=100)
        self.assertRaises(exception.InvalidParameterValue, d, self.method)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(0, self.method._clean_step_priority)
        self.assertFalse(self.method._clean_step_abortable)
        self.assertFalse(hasattr(self.method, '_clean_step_argsinfo'))


class CleanStepTestCase(base.TestCase):
    def test_get_and_execute_clean_steps(self):
        # Create a fake Driver class, create some clean steps, make sure
        # they are listed correctly, and attempt to execute one of them

        method_mock = mock.MagicMock(spec_set=[])
        method_args_mock = mock.MagicMock(spec_set=[])
        task_mock = mock.MagicMock(spec_set=[])

        class BaseTestClass(driver_base.BaseInterface):
            def get_properties(self):
                return {}

            def validate(self, task):
                pass

        class TestClass(BaseTestClass):
            interface_type = 'test'

            @driver_base.clean_step(priority=0)
            def manual_method(self, task):
                pass

            @driver_base.clean_step(priority=10, abortable=True)
            def automated_method(self, task):
                method_mock(task)

            def not_clean_method(self, task):
                pass

        class TestClass2(BaseTestClass):
            interface_type = 'test2'

            @driver_base.clean_step(priority=0)
            def manual_method2(self, task):
                pass

            @driver_base.clean_step(priority=20, abortable=True)
            def automated_method2(self, task):
                method_mock(task)

            def not_clean_method2(self, task):
                pass

        class TestClass3(BaseTestClass):
            interface_type = 'test3'

            @driver_base.clean_step(priority=0, abortable=True, argsinfo={
                                    'arg1': {'description': 'desc1',
                                             'required': True}})
            def manual_method3(self, task, **kwargs):
                method_args_mock(task, **kwargs)

            @driver_base.clean_step(priority=15, argsinfo={
                                    'arg10': {'description': 'desc10'}})
            def automated_method3(self, task, **kwargs):
                pass

            def not_clean_method3(self, task):
                pass

        obj = TestClass()
        obj2 = TestClass2()
        obj3 = TestClass3()

        self.assertEqual(2, len(obj.get_clean_steps(task_mock)))
        # Ensure the steps look correct
        self.assertEqual(10, obj.get_clean_steps(task_mock)[0]['priority'])
        self.assertTrue(obj.get_clean_steps(task_mock)[0]['abortable'])
        self.assertEqual('test', obj.get_clean_steps(
            task_mock)[0]['interface'])
        self.assertEqual('automated_method', obj.get_clean_steps(
            task_mock)[0]['step'])
        self.assertEqual(0, obj.get_clean_steps(task_mock)[1]['priority'])
        self.assertFalse(obj.get_clean_steps(task_mock)[1]['abortable'])
        self.assertEqual('test', obj.get_clean_steps(
            task_mock)[1]['interface'])
        self.assertEqual('manual_method', obj.get_clean_steps(
            task_mock)[1]['step'])

        # Ensure the second obj get different clean steps
        self.assertEqual(2, len(obj2.get_clean_steps(task_mock)))
        # Ensure the steps look correct
        self.assertEqual(20, obj2.get_clean_steps(task_mock)[0]['priority'])
        self.assertTrue(obj2.get_clean_steps(task_mock)[0]['abortable'])
        self.assertEqual('test2', obj2.get_clean_steps(
            task_mock)[0]['interface'])
        self.assertEqual('automated_method2', obj2.get_clean_steps(
            task_mock)[0]['step'])
        self.assertEqual(0, obj2.get_clean_steps(task_mock)[1]['priority'])
        self.assertFalse(obj2.get_clean_steps(task_mock)[1]['abortable'])
        self.assertEqual('test2', obj2.get_clean_steps(
            task_mock)[1]['interface'])
        self.assertEqual('manual_method2', obj2.get_clean_steps(
            task_mock)[1]['step'])
        self.assertIsNone(obj2.get_clean_steps(task_mock)[0]['argsinfo'])

        # Ensure the third obj has different clean steps
        self.assertEqual(2, len(obj3.get_clean_steps(task_mock)))
        self.assertEqual(15, obj3.get_clean_steps(task_mock)[0]['priority'])
        self.assertFalse(obj3.get_clean_steps(task_mock)[0]['abortable'])
        self.assertEqual('test3', obj3.get_clean_steps(
            task_mock)[0]['interface'])
        self.assertEqual('automated_method3', obj3.get_clean_steps(
            task_mock)[0]['step'])
        self.assertEqual({'arg10': {'description': 'desc10'}},
                         obj3.get_clean_steps(task_mock)[0]['argsinfo'])
        self.assertEqual(0, obj3.get_clean_steps(task_mock)[1]['priority'])
        self.assertTrue(obj3.get_clean_steps(task_mock)[1]['abortable'])
        self.assertEqual(obj3.interface_type, obj3.get_clean_steps(
            task_mock)[1]['interface'])
        self.assertEqual('manual_method3', obj3.get_clean_steps(
            task_mock)[1]['step'])
        self.assertEqual({'arg1': {'description': 'desc1', 'required': True}},
                         obj3.get_clean_steps(task_mock)[1]['argsinfo'])

        # Ensure we can execute the function.
        obj.execute_clean_step(task_mock, obj.get_clean_steps(task_mock)[0])
        method_mock.assert_called_once_with(task_mock)

        args = {'arg1': 'val1'}
        clean_step = {'interface': 'test3', 'step': 'manual_method3',
                      'args': args}
        obj3.execute_clean_step(task_mock, clean_step)
        method_args_mock.assert_called_once_with(task_mock, **args)


class DeployStepDecoratorTestCase(base.TestCase):

    def setUp(self):
        super(DeployStepDecoratorTestCase, self).setUp()
        method_mock = mock.MagicMock()
        del method_mock._is_deploy_step
        del method_mock._deploy_step_priority
        del method_mock._deploy_step_argsinfo
        self.method = method_mock

    def test_deploy_step_priority_only(self):
        d = driver_base.deploy_step(priority=10)
        d(self.method)
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(10, self.method._deploy_step_priority)
        self.assertIsNone(self.method._deploy_step_argsinfo)

    def test_deploy_step_all_args(self):
        argsinfo = {'arg1': {'description': 'desc1',
                             'required': True}}
        d = driver_base.deploy_step(priority=0, argsinfo=argsinfo)
        d(self.method)
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(0, self.method._deploy_step_priority)
        self.assertEqual(argsinfo, self.method._deploy_step_argsinfo)

    def test_deploy_step_bad_priority(self):
        d = driver_base.deploy_step(priority='hi')
        self.assertRaisesRegex(exception.InvalidParameterValue, 'priority',
                               d, self.method)
        self.assertTrue(self.method._is_deploy_step)
        self.assertFalse(hasattr(self.method, '_deploy_step_priority'))
        self.assertFalse(hasattr(self.method, '_deploy_step_argsinfo'))

    @mock.patch.object(driver_base, '_validate_argsinfo', spec_set=True,
                       autospec=True)
    def test_deploy_step_bad_argsinfo(self, mock_valid):
        mock_valid.side_effect = exception.InvalidParameterValue('bad')
        d = driver_base.deploy_step(priority=0, argsinfo=100)
        self.assertRaises(exception.InvalidParameterValue, d, self.method)
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(0, self.method._deploy_step_priority)
        self.assertFalse(hasattr(self.method, '_deploy_step_argsinfo'))


class DeployAndCleanStepDecoratorTestCase(base.TestCase):

    def setUp(self):
        super(DeployAndCleanStepDecoratorTestCase, self).setUp()
        method_mock = mock.MagicMock()
        del method_mock._is_deploy_step
        del method_mock._deploy_step_priority
        del method_mock._deploy_step_argsinfo
        del method_mock._is_clean_step
        del method_mock._clean_step_priority
        del method_mock._clean_step_abortable
        del method_mock._clean_step_argsinfo
        self.method = method_mock

    def test_deploy_and_clean_step_priority_only(self):
        dd = driver_base.deploy_step(priority=10)
        dc = driver_base.clean_step(priority=11)
        dd(dc(self.method))
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(10, self.method._deploy_step_priority)
        self.assertIsNone(self.method._deploy_step_argsinfo)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(11, self.method._clean_step_priority)
        self.assertFalse(self.method._clean_step_abortable)
        self.assertIsNone(self.method._clean_step_argsinfo)

    def test_deploy_and_clean_step_all_args(self):
        dargsinfo = {'arg1': {'description': 'desc1',
                              'required': True}}
        cargsinfo = {'arg2': {'description': 'desc2',
                              'required': False}}
        dd = driver_base.deploy_step(priority=0, argsinfo=dargsinfo)
        dc = driver_base.clean_step(priority=0, argsinfo=cargsinfo)
        dd(dc(self.method))
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(0, self.method._deploy_step_priority)
        self.assertEqual(dargsinfo, self.method._deploy_step_argsinfo)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(0, self.method._clean_step_priority)
        self.assertFalse(self.method._clean_step_abortable)
        self.assertEqual(cargsinfo, self.method._clean_step_argsinfo)

    def test_clean_and_deploy_step_all_args(self):
        # Opposite ordering, should make no difference.
        dargsinfo = {'arg1': {'description': 'desc1',
                              'required': True}}
        cargsinfo = {'arg2': {'description': 'desc2',
                              'required': False}}
        dd = driver_base.deploy_step(priority=0, argsinfo=dargsinfo)
        dc = driver_base.clean_step(priority=0, argsinfo=cargsinfo)
        dc(dd(self.method))
        self.assertTrue(self.method._is_deploy_step)
        self.assertEqual(0, self.method._deploy_step_priority)
        self.assertEqual(dargsinfo, self.method._deploy_step_argsinfo)
        self.assertTrue(self.method._is_clean_step)
        self.assertEqual(0, self.method._clean_step_priority)
        self.assertFalse(self.method._clean_step_abortable)
        self.assertEqual(cargsinfo, self.method._clean_step_argsinfo)


class DeployStepTestCase(base.TestCase):
    def test_get_and_execute_deploy_steps(self):
        # Create a fake Driver class, create some deploy steps, make sure
        # they are listed correctly, and attempt to execute one of them

        method_mock = mock.MagicMock(spec_set=[])
        method_args_mock = mock.MagicMock(spec_set=[])
        task_mock = mock.MagicMock(spec_set=[])

        class BaseTestClass(driver_base.BaseInterface):
            def get_properties(self):
                return {}

            def validate(self, task):
                pass

        class TestClass(BaseTestClass):
            interface_type = 'test'

            @driver_base.deploy_step(priority=0)
            def deploy_zero(self, task):
                pass

            @driver_base.deploy_step(priority=10)
            def deploy_ten(self, task):
                method_mock(task)

            def not_deploy_method(self, task):
                pass

        class TestClass2(BaseTestClass):
            interface_type = 'test2'

            @driver_base.deploy_step(priority=0)
            def deploy_zero2(self, task):
                pass

            @driver_base.deploy_step(priority=20)
            def deploy_twenty(self, task):
                method_mock(task)

            def not_deploy_method2(self, task):
                pass

        class TestClass3(BaseTestClass):
            interface_type = 'test3'

            @driver_base.deploy_step(priority=0, argsinfo={
                                     'arg1': {'description': 'desc1',
                                              'required': True}})
            def deploy_zero3(self, task, **kwargs):
                method_args_mock(task, **kwargs)

            @driver_base.deploy_step(priority=15, argsinfo={
                                     'arg10': {'description': 'desc10'}})
            def deploy_fifteen(self, task, **kwargs):
                pass

            def not_deploy_method3(self, task):
                pass

        obj = TestClass()
        obj2 = TestClass2()
        obj3 = TestClass3()

        self.assertEqual(2, len(obj.get_deploy_steps(task_mock)))
        # Ensure the steps look correct
        self.assertEqual(10, obj.get_deploy_steps(task_mock)[0]['priority'])
        self.assertEqual('test', obj.get_deploy_steps(
            task_mock)[0]['interface'])
        self.assertEqual('deploy_ten', obj.get_deploy_steps(
            task_mock)[0]['step'])
        self.assertEqual(0, obj.get_deploy_steps(task_mock)[1]['priority'])
        self.assertEqual('test', obj.get_deploy_steps(
            task_mock)[1]['interface'])
        self.assertEqual('deploy_zero', obj.get_deploy_steps(
            task_mock)[1]['step'])

        # Ensure the second obj has different deploy steps
        self.assertEqual(2, len(obj2.get_deploy_steps(task_mock)))
        # Ensure the steps look correct
        self.assertEqual(20, obj2.get_deploy_steps(task_mock)[0]['priority'])
        self.assertEqual('test2', obj2.get_deploy_steps(
            task_mock)[0]['interface'])
        self.assertEqual('deploy_twenty', obj2.get_deploy_steps(
            task_mock)[0]['step'])
        self.assertEqual(0, obj2.get_deploy_steps(task_mock)[1]['priority'])
        self.assertEqual('test2', obj2.get_deploy_steps(
            task_mock)[1]['interface'])
        self.assertEqual('deploy_zero2', obj2.get_deploy_steps(
            task_mock)[1]['step'])
        self.assertIsNone(obj2.get_deploy_steps(task_mock)[0]['argsinfo'])

        # Ensure the third obj has different deploy steps
        self.assertEqual(2, len(obj3.get_deploy_steps(task_mock)))
        self.assertEqual(15, obj3.get_deploy_steps(task_mock)[0]['priority'])
        self.assertEqual('test3', obj3.get_deploy_steps(
            task_mock)[0]['interface'])
        self.assertEqual('deploy_fifteen', obj3.get_deploy_steps(
            task_mock)[0]['step'])
        self.assertEqual({'arg10': {'description': 'desc10'}},
                         obj3.get_deploy_steps(task_mock)[0]['argsinfo'])
        self.assertEqual(0, obj3.get_deploy_steps(task_mock)[1]['priority'])
        self.assertEqual(obj3.interface_type, obj3.get_deploy_steps(
            task_mock)[1]['interface'])
        self.assertEqual('deploy_zero3', obj3.get_deploy_steps(
            task_mock)[1]['step'])
        self.assertEqual({'arg1': {'description': 'desc1', 'required': True}},
                         obj3.get_deploy_steps(task_mock)[1]['argsinfo'])

        # Ensure we can execute the function.
        obj.execute_deploy_step(task_mock, obj.get_deploy_steps(task_mock)[0])
        method_mock.assert_called_once_with(task_mock)

        args = {'arg1': 'val1'}
        deploy_step = {'interface': 'test3', 'step': 'deploy_zero3',
                       'args': args}
        obj3.execute_deploy_step(task_mock, deploy_step)
        method_args_mock.assert_called_once_with(task_mock, **args)


class MyRAIDInterface(driver_base.RAIDInterface):

    def create_configuration(self, task,
                             create_root_volume=True,
                             create_nonroot_volumes=True,
                             delete_existing=True):
        pass

    def delete_configuration(self, task):
        pass


class RAIDInterfaceTestCase(base.TestCase):

    @mock.patch.object(driver_base.RAIDInterface, 'validate_raid_config',
                       autospec=True)
    def test_validate(self, validate_raid_config_mock):
        raid_interface = MyRAIDInterface()
        node_mock = mock.MagicMock(target_raid_config='some_raid_config')
        task_mock = mock.MagicMock(node=node_mock)

        raid_interface.validate(task_mock)

        validate_raid_config_mock.assert_called_once_with(
            raid_interface, task_mock, 'some_raid_config')

    @mock.patch.object(driver_base.RAIDInterface, 'validate_raid_config',
                       autospec=True)
    def test_validate_no_target_raid_config(self, validate_raid_config_mock):
        raid_interface = MyRAIDInterface()
        node_mock = mock.MagicMock(target_raid_config={})
        task_mock = mock.MagicMock(node=node_mock)

        raid_interface.validate(task_mock)

        self.assertFalse(validate_raid_config_mock.called)

    @mock.patch.object(raid, 'validate_configuration', autospec=True)
    def test_validate_raid_config(self, common_validate_mock):
        with open(driver_base.RAID_CONFIG_SCHEMA, 'r') as raid_schema_fobj:
            raid_schema = json.load(raid_schema_fobj)
        raid_interface = MyRAIDInterface()

        raid_interface.validate_raid_config('task', 'some_raid_config')

        common_validate_mock.assert_called_once_with(
            'some_raid_config', raid_schema)

    @mock.patch.object(raid, 'get_logical_disk_properties',
                       autospec=True)
    def test_get_logical_disk_properties(self, get_properties_mock):
        with open(driver_base.RAID_CONFIG_SCHEMA, 'r') as raid_schema_fobj:
            raid_schema = json.load(raid_schema_fobj)
        raid_interface = MyRAIDInterface()
        raid_interface.get_logical_disk_properties()
        get_properties_mock.assert_called_once_with(raid_schema)

    @mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
    @mock.patch.object(MyRAIDInterface, 'validate_raid_config',
                       autospec=True)
    def test_apply_configuration(self, mock_validate, mock_create):
        raid_interface = MyRAIDInterface()
        node_mock = mock.MagicMock(target_raid_config=None)
        task_mock = mock.MagicMock(node=node_mock)
        mock_create.return_value = states.DEPLOYWAIT
        raid_config = 'some_raid_config'

        result = raid_interface.apply_configuration(task_mock, raid_config)

        self.assertEqual(states.DEPLOYWAIT, result)
        mock_validate.assert_called_once_with(raid_interface, task_mock,
                                              raid_config)
        mock_create.assert_called_once_with(raid_interface, task_mock,
                                            create_root_volume=True,
                                            create_nonroot_volumes=True,
                                            delete_existing=True)
        self.assertEqual(raid_config, node_mock.target_raid_config)

    @mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
    @mock.patch.object(MyRAIDInterface, 'validate_raid_config',
                       autospec=True)
    def test_apply_configuration_delete_existing(self, mock_validate,
                                                 mock_create):
        raid_interface = MyRAIDInterface()
        node_mock = mock.MagicMock(target_raid_config=None)
        task_mock = mock.MagicMock(node=node_mock)
        mock_create.return_value = states.DEPLOYWAIT
        raid_config = 'some_raid_config'

        result = raid_interface.apply_configuration(task_mock, raid_config,
                                                    delete_existing=True)

        self.assertEqual(states.DEPLOYWAIT, result)
        mock_validate.assert_called_once_with(raid_interface, task_mock,
                                              raid_config)
        mock_create.assert_called_once_with(raid_interface, task_mock,
                                            create_root_volume=True,
                                            create_nonroot_volumes=True,
                                            delete_existing=True)
        self.assertEqual(raid_config, node_mock.target_raid_config)

    @mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
    @mock.patch.object(MyRAIDInterface, 'validate_raid_config',
                       autospec=True)
    def test_apply_configuration_invalid(self, mock_validate, mock_create):
        raid_interface = MyRAIDInterface()
        node_mock = mock.MagicMock(target_raid_config=None)
        task_mock = mock.MagicMock(node=node_mock)
        mock_validate.side_effect = exception.InvalidParameterValue('bad')
        raid_config = 'some_raid_config'

        self.assertRaises(exception.InvalidParameterValue,
                          raid_interface.apply_configuration, task_mock,
                          raid_config)
        mock_validate.assert_called_once_with(raid_interface, task_mock,
                                              raid_config)
        self.assertFalse(mock_create.called)
        self.assertIsNone(node_mock.target_raid_config)


class TestDeployInterface(base.TestCase):
    @mock.patch.object(driver_base.LOG, 'warning', autospec=True)
    def test_warning_on_heartbeat(self, mock_log):
        # NOTE(dtantsur): FakeDeploy does not override heartbeat
        deploy = fake.FakeDeploy()
        deploy.heartbeat(mock.Mock(node=mock.Mock(uuid='uuid',
                                                  driver='driver')),
                         'url', '3.2.0')
        self.assertTrue(mock_log.called)


class MyBIOSInterface(driver_base.BIOSInterface):

    def get_properties(self):
        pass

    def validate(self, task):
        pass

    @driver_base.cache_bios_settings
    def apply_configuration(self, task, settings):
        return "return_value_apply_configuration"

    @driver_base.cache_bios_settings
    def factory_reset(self, task):
        return "return_value_factory_reset"

    def cache_bios_settings(self, task):
        pass


class TestBIOSInterface(base.TestCase):

    @mock.patch.object(MyBIOSInterface, 'cache_bios_settings', autospec=True)
    def test_apply_configuration_wrapper(self, cache_bios_settings_mock):
        bios = MyBIOSInterface()
        task_mock = mock.MagicMock()

        actual = bios.apply_configuration(task_mock, "")
        cache_bios_settings_mock.assert_called_once_with(bios, task_mock)
        self.assertEqual(actual, "return_value_apply_configuration")

    @mock.patch.object(MyBIOSInterface, 'cache_bios_settings', autospec=True)
    def test_factory_reset_wrapper(self, cache_bios_settings_mock):
        bios = MyBIOSInterface()
        task_mock = mock.MagicMock()

        actual = bios.factory_reset(task_mock)
        cache_bios_settings_mock.assert_called_once_with(bios, task_mock)
        self.assertEqual(actual, "return_value_factory_reset")


class TestBootInterface(base.TestCase):

    def test_validate_rescue_default_impl(self):
        boot = fake.FakeBoot()
        task_mock = mock.MagicMock(spec_set=['node'])

        self.assertRaises(exception.UnsupportedDriverExtension,
                          boot.validate_rescue, task_mock)


class TestManagementInterface(base.TestCase):

    def test_inject_nmi_default_impl(self):
        management = fake.FakeManagement()
        task_mock = mock.MagicMock(spec_set=['node'])

        self.assertRaises(exception.UnsupportedDriverExtension,
                          management.inject_nmi, task_mock)

    def test_get_supported_boot_modes_default_impl(self):
        management = fake.FakeManagement()
        task_mock = mock.MagicMock(spec_set=['node'])

        self.assertRaises(exception.UnsupportedDriverExtension,
                          management.get_supported_boot_modes, task_mock)

    def test_set_boot_mode_default_impl(self):
        management = fake.FakeManagement()
        task_mock = mock.MagicMock(spec_set=['node'])

        self.assertRaises(exception.UnsupportedDriverExtension,
                          management.set_boot_mode, task_mock, 'whatever')

    def test_get_boot_mode_default_impl(self):
        management = fake.FakeManagement()
        task_mock = mock.MagicMock(spec_set=['node'])

        self.assertRaises(exception.UnsupportedDriverExtension,
                          management.get_boot_mode, task_mock)


class TestBareDriver(base.TestCase):

    def test_class_variables(self):
        self.assertEqual(['boot', 'deploy', 'management', 'network', 'power'],
                         driver_base.BareDriver().core_interfaces)
        self.assertEqual(
            ['bios', 'console', 'inspect', 'raid', 'rescue', 'storage'],
            driver_base.BareDriver().optional_interfaces
        )

[((985, 1015), 'ironic.drivers.base.passthru', 'driver_base.passthru', (["['POST']"], {}), "(['POST'])\n", (1005, 1015), True, 'from ironic.drivers import base as driver_base\n'), ((1071, 1108), 'ironic.drivers.base.driver_passthru', 'driver_base.driver_passthru', (["['POST']"], {}), "(['POST'])\n", (1098, 1108), True, 'from ironic.drivers import base as driver_base\n'), ((1171, 1201), 'ironic.drivers.base.passthru', 'driver_base.passthru', (["['POST']"], {}), "(['POST'])\n", (1191, 1201), True, 'from ironic.drivers import base as driver_base\n'), ((1288, 1318), 'ironic.drivers.base.passthru', 'driver_base.passthru', (["['POST']"], {}), "(['POST'])\n", (1308, 1318), True, 'from ironic.drivers import base as driver_base\n'), ((1389, 1449), 'ironic.drivers.base.passthru', 'driver_base.passthru', (["['POST']"], {'require_exclusive_lock': '(False)'}), "(['POST'], require_exclusive_lock=False)\n", (1409, 1449), True, 'from ironic.drivers import base as driver_base\n'), ((1912, 1964), 'mock.patch.object', 'mock.patch.object', (['driver_base', '"""LOG"""'], {'autospec': '(True)'}), "(driver_base, 'LOG', autospec=True)\n", (1929, 1964), False, 'import mock\n'), ((2229, 2281), 'mock.patch.object', 'mock.patch.object', (['driver_base', '"""LOG"""'], {'autospec': '(True)'}), "(driver_base, 'LOG', autospec=True)\n", (2246, 2281), False, 'import mock\n'), ((8378, 8464), 'mock.patch.object', 'mock.patch.object', (['driver_base', '"""_validate_argsinfo"""'], {'spec_set': '(True)', 'autospec': '(True)'}), "(driver_base, '_validate_argsinfo', spec_set=True,\n    autospec=True)\n", (8395, 8464), False, 'import mock\n'), ((15890, 15976), 'mock.patch.object', 'mock.patch.object', (['driver_base', '"""_validate_argsinfo"""'], {'spec_set': '(True)', 'autospec': '(True)'}), "(driver_base, '_validate_argsinfo', spec_set=True,\n    autospec=True)\n", (15907, 15976), False, 'import mock\n'), ((24661, 24748), 'mock.patch.object', 'mock.patch.object', (['driver_base.RAIDInterface', '"""validate_raid_config"""'], {'autospec': '(True)'}), "(driver_base.RAIDInterface, 'validate_raid_config',\n    autospec=True)\n", (24678, 24748), False, 'import mock\n'), ((25161, 25248), 'mock.patch.object', 'mock.patch.object', (['driver_base.RAIDInterface', '"""validate_raid_config"""'], {'autospec': '(True)'}), "(driver_base.RAIDInterface, 'validate_raid_config',\n    autospec=True)\n", (25178, 25248), False, 'import mock\n'), ((25608, 25672), 'mock.patch.object', 'mock.patch.object', (['raid', '"""validate_configuration"""'], {'autospec': '(True)'}), "(raid, 'validate_configuration', autospec=True)\n", (25625, 25672), False, 'import mock\n'), ((26088, 26157), 'mock.patch.object', 'mock.patch.object', (['raid', '"""get_logical_disk_properties"""'], {'autospec': '(True)'}), "(raid, 'get_logical_disk_properties', autospec=True)\n", (26105, 26157), False, 'import mock\n'), ((26547, 26620), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""create_configuration"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'create_configuration', autospec=True)\n", (26564, 26620), False, 'import mock\n'), ((26626, 26699), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""validate_raid_config"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'validate_raid_config', autospec=True)\n", (26643, 26699), False, 'import mock\n'), ((27654, 27727), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""create_configuration"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'create_configuration', autospec=True)\n", (27671, 27727), False, 'import mock\n'), ((27733, 27806), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""validate_raid_config"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'validate_raid_config', autospec=True)\n", (27750, 27806), False, 'import mock\n'), ((28900, 28973), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""create_configuration"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'create_configuration', autospec=True)\n", (28917, 28973), False, 'import mock\n'), ((28979, 29052), 'mock.patch.object', 'mock.patch.object', (['MyRAIDInterface', '"""validate_raid_config"""'], {'autospec': '(True)'}), "(MyRAIDInterface, 'validate_raid_config', autospec=True)\n", (28996, 29052), False, 'import mock\n'), ((29876, 29936), 'mock.patch.object', 'mock.patch.object', (['driver_base.LOG', '"""warning"""'], {'autospec': '(True)'}), "(driver_base.LOG, 'warning', autospec=True)\n", (29893, 29936), False, 'import mock\n'), ((30801, 30873), 'mock.patch.object', 'mock.patch.object', (['MyBIOSInterface', '"""cache_bios_settings"""'], {'autospec': '(True)'}), "(MyBIOSInterface, 'cache_bios_settings', autospec=True)\n", (30818, 30873), False, 'import mock\n'), ((31225, 31297), 'mock.patch.object', 'mock.patch.object', (['MyBIOSInterface', '"""cache_bios_settings"""'], {'autospec': '(True)'}), "(MyBIOSInterface, 'cache_bios_settings', autospec=True)\n", (31242, 31297), False, 'import mock\n'), ((1247, 1281), 'ironic.common.exception.IronicException', 'exception.IronicException', (['"""Fake!"""'], {}), "('Fake!')\n", (1272, 1281), False, 'from ironic.common import exception\n'), ((3673, 3689), 'mock.MagicMock', 'mock.MagicMock', ([], {}), '()\n', (3687, 3689), False, 'import mock\n'), ((3974, 4010), 'ironic.drivers.base._validate_argsinfo', 'driver_base._validate_argsinfo', (['None'], {}), '(None)\n', (4004, 4010), True, 'from ironic.drivers import base as driver_base\n'), ((4019, 4053), 'ironic.drivers.base._validate_argsinfo', 'driver_base._validate_argsinfo', (['{}'], {}), '({})\n', (4049, 4053), True, 'from ironic.drivers import base as driver_base\n'), ((4100, 4166), 'ironic.drivers.base._validate_argsinfo', 'driver_base._validate_argsinfo', (["{'arg1': {'description': 'desc1'}}"], {}), "({'arg1': {'description': 'desc1'}})\n", (4130, 4166), True, 'from ironic.drivers import base as driver_base\n'), ((4200, 4322), 'ironic.drivers.base._validate_argsinfo', 'driver_base._validate_argsinfo', (["{'arg1': {'description': 'desc1', 'required': True}, 'arg2': {'description':\n    'desc2'}}"], {}), "({'arg1': {'description': 'desc1', 'required':\n    True}, 'arg2': {'description': 'desc2'}})\n", (4230, 4322), True, 'from ironic.drivers import base as driver_base\n'), ((6578, 6613), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(10)'}), '(priority=10)\n', (6600, 6613), True, 'from ironic.drivers import base as driver_base\n'), ((7026, 7095), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'abortable': '(True)', 'argsinfo': 'argsinfo'}), '(priority=0, abortable=True, argsinfo=argsinfo)\n', (7048, 7095), True, 'from ironic.drivers import base as driver_base\n'), ((7453, 7490), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '"""hi"""'}), "(priority='hi')\n", (7475, 7490), True, 'from ironic.drivers import base as driver_base\n'), ((7938, 7990), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'abortable': '"""blue"""'}), "(priority=0, abortable='blue')\n", (7960, 7990), True, 'from ironic.drivers import base as driver_base\n'), ((8573, 8611), 'ironic.common.exception.InvalidParameterValue', 'exception.InvalidParameterValue', (['"""bad"""'], {}), "('bad')\n", (8604, 8611), False, 'from ironic.common import exception\n'), ((8624, 8672), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'argsinfo': '(100)'}), '(priority=0, argsinfo=100)\n', (8646, 8672), True, 'from ironic.drivers import base as driver_base\n'), ((9251, 9278), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (9265, 9278), False, 'import mock\n'), ((9306, 9333), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (9320, 9333), False, 'import mock\n'), ((9354, 9381), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (9368, 9381), False, 'import mock\n'), ((14568, 14584), 'mock.MagicMock', 'mock.MagicMock', ([], {}), '()\n', (14582, 14584), False, 'import mock\n'), ((14810, 14846), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(10)'}), '(priority=10)\n', (14833, 14846), True, 'from ironic.drivers import base as driver_base\n'), ((15203, 15257), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)', 'argsinfo': 'argsinfo'}), '(priority=0, argsinfo=argsinfo)\n', (15226, 15257), True, 'from ironic.drivers import base as driver_base\n'), ((15525, 15563), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '"""hi"""'}), "(priority='hi')\n", (15548, 15563), True, 'from ironic.drivers import base as driver_base\n'), ((16086, 16124), 'ironic.common.exception.InvalidParameterValue', 'exception.InvalidParameterValue', (['"""bad"""'], {}), "('bad')\n", (16117, 16124), False, 'from ironic.common import exception\n'), ((16137, 16186), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)', 'argsinfo': '(100)'}), '(priority=0, argsinfo=100)\n', (16160, 16186), True, 'from ironic.drivers import base as driver_base\n'), ((16619, 16635), 'mock.MagicMock', 'mock.MagicMock', ([], {}), '()\n', (16633, 16635), False, 'import mock\n'), ((17047, 17083), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(10)'}), '(priority=10)\n', (17070, 17083), True, 'from ironic.drivers import base as driver_base\n'), ((17097, 17132), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(11)'}), '(priority=11)\n', (17119, 17132), True, 'from ironic.drivers import base as driver_base\n'), ((17846, 17901), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)', 'argsinfo': 'dargsinfo'}), '(priority=0, argsinfo=dargsinfo)\n', (17869, 17901), True, 'from ironic.drivers import base as driver_base\n'), ((17915, 17969), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'argsinfo': 'cargsinfo'}), '(priority=0, argsinfo=cargsinfo)\n', (17937, 17969), True, 'from ironic.drivers import base as driver_base\n'), ((18757, 18812), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)', 'argsinfo': 'dargsinfo'}), '(priority=0, argsinfo=dargsinfo)\n', (18780, 18812), True, 'from ironic.drivers import base as driver_base\n'), ((18826, 18880), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'argsinfo': 'cargsinfo'}), '(priority=0, argsinfo=cargsinfo)\n', (18848, 18880), True, 'from ironic.drivers import base as driver_base\n'), ((19601, 19628), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (19615, 19628), False, 'import mock\n'), ((19656, 19683), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (19670, 19683), False, 'import mock\n'), ((19704, 19731), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': '[]'}), '(spec_set=[])\n', (19718, 19731), False, 'import mock\n'), ((24887, 24940), 'mock.MagicMock', 'mock.MagicMock', ([], {'target_raid_config': '"""some_raid_config"""'}), "(target_raid_config='some_raid_config')\n", (24901, 24940), False, 'import mock\n'), ((24961, 24991), 'mock.MagicMock', 'mock.MagicMock', ([], {'node': 'node_mock'}), '(node=node_mock)\n', (24975, 24991), False, 'import mock\n'), ((25409, 25446), 'mock.MagicMock', 'mock.MagicMock', ([], {'target_raid_config': '{}'}), '(target_raid_config={})\n', (25423, 25446), False, 'import mock\n'), ((25467, 25497), 'mock.MagicMock', 'mock.MagicMock', ([], {'node': 'node_mock'}), '(node=node_mock)\n', (25481, 25497), False, 'import mock\n'), ((26854, 26893), 'mock.MagicMock', 'mock.MagicMock', ([], {'target_raid_config': 'None'}), '(target_raid_config=None)\n', (26868, 26893), False, 'import mock\n'), ((26914, 26944), 'mock.MagicMock', 'mock.MagicMock', ([], {'node': 'node_mock'}), '(node=node_mock)\n', (26928, 26944), False, 'import mock\n'), ((28026, 28065), 'mock.MagicMock', 'mock.MagicMock', ([], {'target_raid_config': 'None'}), '(target_raid_config=None)\n', (28040, 28065), False, 'import mock\n'), ((28086, 28116), 'mock.MagicMock', 'mock.MagicMock', ([], {'node': 'node_mock'}), '(node=node_mock)\n', (28100, 28116), False, 'import mock\n'), ((29215, 29254), 'mock.MagicMock', 'mock.MagicMock', ([], {'target_raid_config': 'None'}), '(target_raid_config=None)\n', (29229, 29254), False, 'import mock\n'), ((29275, 29305), 'mock.MagicMock', 'mock.MagicMock', ([], {'node': 'node_mock'}), '(node=node_mock)\n', (29289, 29305), False, 'import mock\n'), ((29342, 29380), 'ironic.common.exception.InvalidParameterValue', 'exception.InvalidParameterValue', (['"""bad"""'], {}), "('bad')\n", (29373, 29380), False, 'from ironic.common import exception\n'), ((30070, 30087), 'ironic.drivers.modules.fake.FakeDeploy', 'fake.FakeDeploy', ([], {}), '()\n', (30085, 30087), False, 'from ironic.drivers.modules import fake\n'), ((31001, 31017), 'mock.MagicMock', 'mock.MagicMock', ([], {}), '()\n', (31015, 31017), False, 'import mock\n'), ((31419, 31435), 'mock.MagicMock', 'mock.MagicMock', ([], {}), '()\n', (31433, 31435), False, 'import mock\n'), ((31728, 31743), 'ironic.drivers.modules.fake.FakeBoot', 'fake.FakeBoot', ([], {}), '()\n', (31741, 31743), False, 'from ironic.drivers.modules import fake\n'), ((31764, 31797), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': "['node']"}), "(spec_set=['node'])\n", (31778, 31797), False, 'import mock\n'), ((32036, 32057), 'ironic.drivers.modules.fake.FakeManagement', 'fake.FakeManagement', ([], {}), '()\n', (32055, 32057), False, 'from ironic.drivers.modules import fake\n'), ((32078, 32111), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': "['node']"}), "(spec_set=['node'])\n", (32092, 32111), False, 'import mock\n'), ((32317, 32338), 'ironic.drivers.modules.fake.FakeManagement', 'fake.FakeManagement', ([], {}), '()\n', (32336, 32338), False, 'from ironic.drivers.modules import fake\n'), ((32359, 32392), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': "['node']"}), "(spec_set=['node'])\n", (32373, 32392), False, 'import mock\n'), ((32601, 32622), 'ironic.drivers.modules.fake.FakeManagement', 'fake.FakeManagement', ([], {}), '()\n', (32620, 32622), False, 'from ironic.drivers.modules import fake\n'), ((32643, 32676), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': "['node']"}), "(spec_set=['node'])\n", (32657, 32676), False, 'import mock\n'), ((32886, 32907), 'ironic.drivers.modules.fake.FakeManagement', 'fake.FakeManagement', ([], {}), '()\n', (32905, 32907), False, 'from ironic.drivers.modules import fake\n'), ((32928, 32961), 'mock.MagicMock', 'mock.MagicMock', ([], {'spec_set': "['node']"}), "(spec_set=['node'])\n", (32942, 32961), False, 'import mock\n'), ((9654, 9688), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)'}), '(priority=0)\n', (9676, 9688), True, 'from ironic.drivers import base as driver_base\n'), ((9767, 9818), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(10)', 'abortable': '(True)'}), '(priority=10, abortable=True)\n', (9789, 9818), True, 'from ironic.drivers import base as driver_base\n'), ((10060, 10094), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)'}), '(priority=0)\n', (10082, 10094), True, 'from ironic.drivers import base as driver_base\n'), ((10174, 10225), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(20)', 'abortable': '(True)'}), '(priority=20, abortable=True)\n', (10196, 10225), True, 'from ironic.drivers import base as driver_base\n'), ((10469, 10587), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(0)', 'abortable': '(True)', 'argsinfo': "{'arg1': {'description': 'desc1', 'required': True}}"}), "(priority=0, abortable=True, argsinfo={'arg1': {\n    'description': 'desc1', 'required': True}})\n", (10491, 10587), True, 'from ironic.drivers import base as driver_base\n'), ((10782, 10868), 'ironic.drivers.base.clean_step', 'driver_base.clean_step', ([], {'priority': '(15)', 'argsinfo': "{'arg10': {'description': 'desc10'}}"}), "(priority=15, argsinfo={'arg10': {'description':\n    'desc10'}})\n", (10804, 10868), True, 'from ironic.drivers import base as driver_base\n'), ((20004, 20039), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)'}), '(priority=0)\n', (20027, 20039), True, 'from ironic.drivers import base as driver_base\n'), ((20116, 20152), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(10)'}), '(priority=10)\n', (20139, 20152), True, 'from ironic.drivers import base as driver_base\n'), ((20389, 20424), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)'}), '(priority=0)\n', (20412, 20424), True, 'from ironic.drivers import base as driver_base\n'), ((20502, 20538), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(20)'}), '(priority=20)\n', (20525, 20538), True, 'from ironic.drivers import base as driver_base\n'), ((20779, 20881), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(0)', 'argsinfo': "{'arg1': {'description': 'desc1', 'required': True}}"}), "(priority=0, argsinfo={'arg1': {'description':\n    'desc1', 'required': True}})\n", (20802, 20881), True, 'from ironic.drivers import base as driver_base\n'), ((21077, 21164), 'ironic.drivers.base.deploy_step', 'driver_base.deploy_step', ([], {'priority': '(15)', 'argsinfo': "{'arg10': {'description': 'desc10'}}"}), "(priority=15, argsinfo={'arg10': {'description':\n    'desc10'}})\n", (21100, 21164), True, 'from ironic.drivers import base as driver_base\n'), ((25838, 25865), 'json.load', 'json.load', (['raid_schema_fobj'], {}), '(raid_schema_fobj)\n', (25847, 25865), False, 'import json\n'), ((26352, 26379), 'json.load', 'json.load', (['raid_schema_fobj'], {}), '(raid_schema_fobj)\n', (26361, 26379), False, 'import json\n'), ((33270, 33294), 'ironic.drivers.base.BareDriver', 'driver_base.BareDriver', ([], {}), '()\n', (33292, 33294), True, 'from ironic.drivers import base as driver_base\n'), ((33423, 33447), 'ironic.drivers.base.BareDriver', 'driver_base.BareDriver', ([], {}), '()\n', (33445, 33447), True, 'from ironic.drivers import base as driver_base\n'), ((30128, 30167), 'mock.Mock', 'mock.Mock', ([], {'uuid': '"""uuid"""', 'driver': '"""driver"""'}), "(uuid='uuid', driver='driver')\n", (30137, 30167), False, 'import mock\n')]