Пример #1
0
    def test_node_power_action_power_soft_reboot_timeout(self):
        """Test for soft reboot a node."""
        node = obj_utils.create_test_node(self.context,
                                          uuid=uuidutils.generate_uuid(),
                                          driver='fake_soft_power',
                                          power_state=states.POWER_ON)
        task = task_manager.TaskManager(self.context, node.uuid)

        with mock.patch.object(self.driver.power,
                               'get_power_state') as get_power_mock:
            get_power_mock.return_value = states.POWER_ON

            conductor_utils.node_power_action(task,
                                              states.SOFT_REBOOT,
                                              timeout=2)

            node.refresh()
            get_power_mock.assert_called_once_with(mock.ANY)
            self.assertEqual(states.POWER_ON, node['power_state'])
            self.assertIsNone(node['target_power_state'])
            self.assertIsNone(node['last_error'])
Пример #2
0
    def test_upgrade_lock(
            self, get_voltgt_mock, get_volconn_mock, get_portgroups_mock,
            get_ports_mock, build_driver_mock,
            reserve_mock, release_mock, node_get_mock):
        node_get_mock.return_value = self.node
        reserve_mock.return_value = self.node
        with task_manager.TaskManager(self.context, 'fake-node-id',
                                      shared=True, purpose='ham') as task:
            self.assertEqual(self.context, task.context)
            self.assertEqual(self.node, task.node)
            self.assertEqual(get_ports_mock.return_value, task.ports)
            self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
            self.assertEqual(get_volconn_mock.return_value,
                             task.volume_connectors)
            self.assertEqual(get_voltgt_mock.return_value, task.volume_targets)
            self.assertEqual(build_driver_mock.return_value, task.driver)
            self.assertTrue(task.shared)
            self.assertFalse(reserve_mock.called)

            task.upgrade_lock()
            self.assertFalse(task.shared)
            self.assertEqual('ham', task._purpose)
            # second upgrade does nothing except changes the purpose
            task.upgrade_lock(purpose='spam')
            self.assertFalse(task.shared)
            self.assertEqual('spam', task._purpose)

            build_driver_mock.assert_called_once_with(mock.ANY,
                                                      driver_name=None)

        # make sure reserve() was called only once
        reserve_mock.assert_called_once_with(self.context, self.host,
                                             'fake-node-id')
        release_mock.assert_called_once_with(self.context, self.host,
                                             self.node.id)
        node_get_mock.assert_called_once_with(self.context, 'fake-node-id')
        get_ports_mock.assert_called_once_with(self.context, self.node.id)
        get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
        get_volconn_mock.assert_called_once_with(self.context, self.node.id)
        get_voltgt_mock.assert_called_once_with(self.context, self.node.id)
Пример #3
0
    def test_excl_lock_with_driver(
            self, get_portgroups_mock, get_ports_mock, build_driver_mock,
            reserve_mock, release_mock, node_get_mock):
        reserve_mock.return_value = self.node
        with task_manager.TaskManager(self.context, 'fake-node-id',
                                      driver_name='fake-driver') as task:
            self.assertEqual(self.context, task.context)
            self.assertEqual(self.node, task.node)
            self.assertEqual(get_ports_mock.return_value, task.ports)
            self.assertEqual(get_portgroups_mock.return_value, task.portgroups)
            self.assertEqual(build_driver_mock.return_value, task.driver)
            self.assertFalse(task.shared)
            build_driver_mock.assert_called_once_with(
                task, driver_name='fake-driver')

        reserve_mock.assert_called_once_with(self.context, self.host,
                                             'fake-node-id')
        get_ports_mock.assert_called_once_with(self.context, self.node.id)
        get_portgroups_mock.assert_called_once_with(self.context, self.node.id)
        release_mock.assert_called_once_with(self.context, self.host,
                                             self.node.id)
        self.assertFalse(node_get_mock.called)
Пример #4
0
    def test__do_node_deploy_unexpected_prepare_error(self, mock_prepare,
                                                      mock_deploy):
        self._start_service()
        # test when driver.deploy.prepare raises an exception
        mock_prepare.side_effect = RuntimeError('test')
        node = obj_utils.create_test_node(self.context, driver='fake-hardware',
                                          provision_state=states.DEPLOYING,
                                          target_provision_state=states.ACTIVE)
        task = task_manager.TaskManager(self.context, node.uuid)

        self.assertRaises(RuntimeError,
                          deployments.do_node_deploy, task,
                          self.service.conductor.id)
        node.refresh()
        self.assertEqual(states.DEPLOYFAIL, node.provision_state)
        # NOTE(tenbrae): failing a deploy does not clear the target state
        #             any longer. Instead, it is cleared when the instance
        #             is deleted.
        self.assertEqual(states.ACTIVE, node.target_provision_state)
        self.assertIsNotNone(node.last_error)
        self.assertTrue(mock_prepare.called)
        self.assertFalse(mock_deploy.called)
Пример #5
0
    def test__do_next_deploy_step_async(self, mock_execute):
        driver_internal_info = {'deploy_step_index': None,
                                'deploy_steps': self.deploy_steps}
        self._start_service()
        node = obj_utils.create_test_node(
            self.context, driver='fake-hardware',
            driver_internal_info=driver_internal_info,
            deploy_step={})
        mock_execute.return_value = states.DEPLOYWAIT
        expected_first_step = node.driver_internal_info['deploy_steps'][0]
        task = task_manager.TaskManager(self.context, node.uuid)
        task.process_event('deploy')

        deployments.do_next_deploy_step(task, 0)

        node.refresh()
        self.assertEqual(states.DEPLOYWAIT, node.provision_state)
        self.assertEqual(states.ACTIVE, node.target_provision_state)
        self.assertEqual(expected_first_step, node.deploy_step)
        self.assertEqual(0, node.driver_internal_info['deploy_step_index'])
        mock_execute.assert_called_once_with(mock.ANY, task,
                                             self.deploy_steps[0])
Пример #6
0
    def test_node_power_action_failed_getting_state(self):
        """Test for exception when we can't get the current power state."""
        node = obj_utils.create_test_node(self.context,
                                          uuid=uuidutils.generate_uuid(),
                                          driver='fake',
                                          power_state=states.POWER_ON)
        task = task_manager.TaskManager(self.context, node.uuid)

        with mock.patch.object(self.driver.power,
                               'get_power_state') as get_power_state_mock:
            get_power_state_mock.side_effect = (
                exception.InvalidParameterValue('failed getting power state'))

            self.assertRaises(exception.InvalidParameterValue,
                              conductor_utils.node_power_action, task,
                              states.POWER_ON)

            node.refresh()
            get_power_state_mock.assert_called_once_with(mock.ANY)
            self.assertEqual(states.POWER_ON, node['power_state'])
            self.assertIsNone(node['target_power_state'])
            self.assertIsNotNone(node['last_error'])
Пример #7
0
    def _test__do_next_deploy_step_last_step_done(self,
                                                  mock_execute,
                                                  mock_console,
                                                  console_enabled=False,
                                                  console_error=False):
        # Resume where last_step is the last deploy step that was executed
        driver_internal_info = {
            'deploy_step_index': 1,
            'deploy_steps': self.deploy_steps
        }
        self._start_service()
        node = obj_utils.create_test_node(
            self.context,
            driver='fake-hardware',
            provision_state=states.DEPLOYWAIT,
            target_provision_state=states.ACTIVE,
            driver_internal_info=driver_internal_info,
            deploy_step=self.deploy_steps[1],
            console_enabled=console_enabled)
        mock_execute.return_value = None
        if console_error:
            mock_console.side_effect = exception.ConsoleError()

        task = task_manager.TaskManager(self.context, node.uuid)
        task.process_event('resume')

        deployments.do_next_deploy_step(task, None, self.service.conductor.id)
        node.refresh()
        # Deploying should be complete without calling additional steps
        self.assertEqual(states.ACTIVE, node.provision_state)
        self.assertEqual(states.NOSTATE, node.target_provision_state)
        self.assertEqual({}, node.deploy_step)
        self.assertNotIn('deploy_step_index', node.driver_internal_info)
        self.assertIsNone(node.driver_internal_info['deploy_steps'])
        self.assertFalse(mock_execute.called)
        if console_enabled:
            mock_console.assert_called_once_with(mock.ANY, task)
        else:
            self.assertFalse(mock_console.called)
Пример #8
0
    def test_node_power_action_already_being_processed(self):
        """Test node power action after aborted power action.

        The target_power_state is expected to be None so it isn't
        checked in the code. This is what happens if it is not None.
        (Eg, if a conductor had died during a previous power-off
        attempt and left the target_power_state set to states.POWER_OFF,
        and the user is attempting to power-off again.)
        """
        node = obj_utils.create_test_node(self.context,
                                          uuid=uuidutils.generate_uuid(),
                                          driver='fake',
                                          power_state=states.POWER_ON,
                                          target_power_state=states.POWER_OFF)
        task = task_manager.TaskManager(self.context, node.uuid)

        conductor_utils.node_power_action(task, states.POWER_OFF)

        node.refresh()
        self.assertEqual(states.POWER_OFF, node['power_state'])
        self.assertEqual(states.NOSTATE, node['target_power_state'])
        self.assertIsNone(node['last_error'])
Пример #9
0
    def test_node_power_action_power_on_notify(self, mock_notif):
        """Test node_power_action to power on node and send notification."""
        self.config(notification_level='info')
        self.config(host='my-host')
        # Required for exception handling
        mock_notif.__name__ = 'NodeSetPowerStateNotification'
        node = obj_utils.create_test_node(self.context,
                                          uuid=uuidutils.generate_uuid(),
                                          driver='fake',
                                          power_state=states.POWER_OFF)
        task = task_manager.TaskManager(self.context, node.uuid)

        with mock.patch.object(self.driver.power,
                               'get_power_state') as get_power_mock:
            get_power_mock.return_value = states.POWER_OFF

            conductor_utils.node_power_action(task, states.POWER_ON)

            node.refresh()
            get_power_mock.assert_called_once_with(mock.ANY)
            self.assertEqual(states.POWER_ON, node.power_state)
            self.assertIsNone(node.target_power_state)
            self.assertIsNone(node.last_error)

            # 2 notifications should be sent: 1 .start and 1 .end
            self.assertEqual(2, mock_notif.call_count)
            self.assertEqual(2, mock_notif.return_value.emit.call_count)

            first_notif_args = mock_notif.call_args_list[0][1]
            second_notif_args = mock_notif.call_args_list[1][1]

            self.assertNotificationEqual(first_notif_args, 'ironic-conductor',
                                         CONF.host,
                                         'baremetal.node.power_set.start',
                                         obj_fields.NotificationLevel.INFO)
            self.assertNotificationEqual(second_notif_args, 'ironic-conductor',
                                         CONF.host,
                                         'baremetal.node.power_set.end',
                                         obj_fields.NotificationLevel.INFO)
Пример #10
0
    def _check_deploy_timeouts(self, context):
        if not CONF.conductor.deploy_callback_timeout:
            return

        filters = {'reserved': False, 'maintenance': False}
        columns = ['uuid', 'driver', 'provision_state', 'provision_updated_at']
        node_list = self.dbapi.get_nodeinfo_list(columns=columns,
                                                 filters=filters)

        for (node_uuid, driver, state, update_time) in node_list:
            mapped_hosts = self.driver_rings[driver].get_hosts(node_uuid)
            if self.host not in mapped_hosts:
                continue

            if state == states.DEPLOYWAIT:
                limit = (timeutils.utcnow() - datetime.timedelta(
                    seconds=CONF.conductor.deploy_callback_timeout))
                if timeutils.normalize_time(update_time) <= limit:
                    try:
                        task = task_manager.TaskManager(context, node_uuid)
                    except (exception.NodeLocked, exception.NodeNotFound):
                        continue

                    node = task.node
                    node.provision_state = states.DEPLOYFAIL
                    node.target_provision_state = states.NOSTATE
                    msg = (_('Timeout reached when waiting callback for '
                             'node %s') % node_uuid)
                    node.last_error = msg
                    LOG.error(msg)
                    node.save(task.context)

                    try:
                        thread = self._spawn_worker(
                            utils.cleanup_after_timeout, task)
                        thread.link(lambda t: task.release_resources())
                    except exception.NoFreeConductorWorker:
                        task.release_resources()
Пример #11
0
    def test_start_deploy(self, mock_iwdi, mock_validate_traits,
                          mock_validate_templates, mock_deploy_validate,
                          mock_power_validate, mock_process_event):
        self._start_service()
        mock_iwdi.return_value = False
        node = obj_utils.create_test_node(self.context, driver='fake-hardware',
                                          provision_state=states.AVAILABLE,
                                          target_provision_state=states.ACTIVE)
        task = task_manager.TaskManager(self.context, node.uuid)

        deployments.start_deploy(task, self.service, configdrive=None,
                                 event='deploy')
        node.refresh()
        self.assertTrue(mock_iwdi.called)
        mock_power_validate.assert_called_once_with(task.driver.power, task)
        mock_deploy_validate.assert_called_once_with(task.driver.deploy, task)
        mock_validate_traits.assert_called_once_with(task.node)
        mock_validate_templates.assert_called_once_with(
            task, skip_missing=True)
        mock_process_event.assert_called_with(
            mock.ANY, 'deploy', call_args=(
                deployments.do_node_deploy, task, 1, None),
            callback=mock.ANY, err_handler=mock.ANY)
Пример #12
0
 def test__do_node_deploy_configdrive_db_error(self, mock_prepare):
     self._start_service()
     node = obj_utils.create_test_node(self.context, driver='fake-hardware',
                                       provision_state=states.DEPLOYING,
                                       target_provision_state=states.ACTIVE)
     task = task_manager.TaskManager(self.context, node.uuid)
     task.node.save()
     expected_instance_info = dict(node.instance_info)
     with mock.patch.object(dbapi.IMPL, 'update_node',
                            autospec=True) as mock_db:
         db_node = self.dbapi.get_node_by_uuid(node.uuid)
         mock_db.side_effect = [db_exception.DBDataError('DB error'),
                                db_node, db_node, db_node]
         self.assertRaises(db_exception.DBDataError,
                           deployments.do_node_deploy, task,
                           self.service.conductor.id,
                           configdrive=b'fake config drive')
         expected_instance_info.update(configdrive=b'fake config drive')
         expected_calls = [
             mock.call(node.uuid,
                       {'version': mock.ANY,
                        'instance_info': expected_instance_info,
                        'driver_internal_info': mock.ANY}),
             mock.call(node.uuid,
                       {'version': mock.ANY,
                        'last_error': mock.ANY}),
             mock.call(node.uuid,
                       {'version': mock.ANY,
                        'deploy_step': {},
                        'driver_internal_info': mock.ANY}),
             mock.call(node.uuid,
                       {'version': mock.ANY,
                        'provision_state': states.DEPLOYFAIL,
                        'target_provision_state': states.ACTIVE}),
         ]
         self.assertEqual(expected_calls, mock_db.mock_calls)
         self.assertFalse(mock_prepare.called)
Пример #13
0
    def _test__do_node_deploy_ok(self, mock_store, configdrive=None,
                                 expected_configdrive=None, fast_track=False):
        if fast_track:
            self.config(fast_track=True, group='deploy')
        expected_configdrive = expected_configdrive or configdrive
        self._start_service()
        with mock.patch.object(fake.FakeDeploy,
                               'deploy', autospec=True) as mock_deploy:
            mock_deploy.return_value = None
            self.node = obj_utils.create_test_node(
                self.context, driver='fake-hardware', name=None,
                provision_state=states.DEPLOYING,
                target_provision_state=states.ACTIVE,
                driver_internal_info={'agent_url': 'url',
                                      'agent_secret_token': 'token'})
            task = task_manager.TaskManager(self.context, self.node.uuid)

            deployments.do_node_deploy(task, self.service.conductor.id,
                                       configdrive=configdrive)
            self.node.refresh()
            self.assertEqual(states.ACTIVE, self.node.provision_state)
            self.assertEqual(states.NOSTATE, self.node.target_provision_state)
            self.assertIsNone(self.node.last_error)
            mock_deploy.assert_called_once_with(mock.ANY, mock.ANY)
            if configdrive:
                mock_store.assert_called_once_with(task.node,
                                                   expected_configdrive)
            else:
                self.assertFalse(mock_store.called)
            self.assertEqual(
                fast_track,
                bool(task.node.driver_internal_info.get('agent_url')))
            self.assertEqual(
                fast_track,
                bool(task.node.driver_internal_info.get('agent_secret_token')))
            self.assertEqual(self.service.conductor.id,
                             task.node.conductor_affinity)
Пример #14
0
    def test__do_next_deploy_step_fast_track(self, mock_execute):
        self.config(fast_track=True, group='deploy')
        # Run all steps from start to finish (all synchronous)
        driver_internal_info = {
            'deploy_step_index': None,
            'deploy_steps': self.deploy_steps,
            'agent_url': 'url',
            'agent_secret_token': 'token'
        }
        self._start_service()
        node = obj_utils.create_test_node(
            self.context,
            driver='fake-hardware',
            driver_internal_info=driver_internal_info,
            deploy_step={})
        mock_execute.return_value = None

        task = task_manager.TaskManager(self.context, node.uuid)
        task.process_event('deploy')

        deployments.do_next_deploy_step(task, 1, self.service.conductor.id)

        # Deploying should be complete
        node.refresh()
        self.assertEqual(states.ACTIVE, node.provision_state)
        self.assertEqual(states.NOSTATE, node.target_provision_state)
        self.assertEqual({}, node.deploy_step)
        self.assertNotIn('deploy_step_index', node.driver_internal_info)
        self.assertIsNone(node.driver_internal_info['deploy_steps'])
        mock_execute.assert_has_calls = [
            mock.call(self.deploy_steps[0]),
            mock.call(self.deploy_steps[1])
        ]
        self.assertEqual('url', node.driver_internal_info['agent_url'])
        self.assertEqual('token',
                         node.driver_internal_info['agent_secret_token'])
Пример #15
0
    def test_node_power_action_invalid_driver_info(self):
        """Test if an exception is thrown when the driver validation
        fails.
        """
        ndict = utils.get_test_node(uuid=cmn_utils.generate_uuid(),
                                    driver='fake',
                                    power_state=states.POWER_ON)
        node = self.dbapi.create_node(ndict)
        task = task_manager.TaskManager(self.context, node.uuid)

        with mock.patch.object(self.driver.power, 'validate') \
                as validate_mock:
            validate_mock.side_effect = exception.InvalidParameterValue(
                'wrong power driver info')

            self.assertRaises(exception.InvalidParameterValue,
                              conductor_utils.node_power_action, task,
                              task.node, states.POWER_ON)

            node.refresh(self.context)
            validate_mock.assert_called_once_with(mock.ANY, mock.ANY)
            self.assertEqual(states.POWER_ON, node['power_state'])
            self.assertIsNone(node['target_power_state'])
            self.assertIsNotNone(node['last_error'])
Пример #16
0
 def test_task_manager_gets_node(self):
     node_uuid = self.uuids[0]
     task = task_manager.TaskManager(self.context, node_uuid)
     self.assertEqual(node_uuid, task.node.uuid)
Пример #17
0
 def _test_it():
     with task_manager.TaskManager(self.context, 'node-id') as task:
         task.set_spawn_error_hook(on_error_handler, 'fake-argument')
         task.spawn_after(spawn_mock, 1, 2, foo='bar', cat='meow')
         task.release_resources = task_release_mock
Пример #18
0
 def _test_it():
     with task_manager.TaskManager(self.context, 'node-id') as task:
         task.spawn_after(spawn_mock, 1, 2, foo='bar', cat='meow')
         task._thread_release_resources = thr_release_mock
         task.release_resources = task_release_mock
Пример #19
0
 def _test_it():
     with task_manager.TaskManager(self.context, 'node-id') as task:
         task.spawn_after(spawn_mock, 1, 2, foo='bar', cat='meow')
         task.release_resources = task_release_mock
         raise exception.IronicException('foo')
Пример #20
0
    def test_excl_nested_acquire(self, get_voltgt_mock, get_volconn_mock,
                                 get_portgroups_mock, get_ports_mock,
                                 build_driver_mock, reserve_mock, release_mock,
                                 node_get_mock):
        node2 = obj_utils.create_test_node(self.context,
                                           uuid=uuidutils.generate_uuid(),
                                           driver='fake-hardware')

        reserve_mock.return_value = self.node
        get_ports_mock.return_value = mock.sentinel.ports1
        get_portgroups_mock.return_value = mock.sentinel.portgroups1
        get_volconn_mock.return_value = mock.sentinel.volconn1
        get_voltgt_mock.return_value = mock.sentinel.voltgt1
        build_driver_mock.return_value = mock.sentinel.driver1

        with task_manager.TaskManager(self.context, 'node-id1') as task:
            reserve_mock.return_value = node2
            get_ports_mock.return_value = mock.sentinel.ports2
            get_portgroups_mock.return_value = mock.sentinel.portgroups2
            get_volconn_mock.return_value = mock.sentinel.volconn2
            get_voltgt_mock.return_value = mock.sentinel.voltgt2
            build_driver_mock.return_value = mock.sentinel.driver2
            with task_manager.TaskManager(self.context, 'node-id2') as task2:
                self.assertEqual(self.context, task.context)
                self.assertEqual(self.node, task.node)
                self.assertEqual(mock.sentinel.ports1, task.ports)
                self.assertEqual(mock.sentinel.portgroups1, task.portgroups)
                self.assertEqual(mock.sentinel.volconn1,
                                 task.volume_connectors)
                self.assertEqual(mock.sentinel.voltgt1, task.volume_targets)
                self.assertEqual(mock.sentinel.driver1, task.driver)
                self.assertFalse(task.shared)
                self.assertEqual(self.context, task2.context)
                self.assertEqual(node2, task2.node)
                self.assertEqual(mock.sentinel.ports2, task2.ports)
                self.assertEqual(mock.sentinel.portgroups2, task2.portgroups)
                self.assertEqual(mock.sentinel.volconn2,
                                 task2.volume_connectors)
                self.assertEqual(mock.sentinel.voltgt2, task2.volume_targets)
                self.assertEqual(mock.sentinel.driver2, task2.driver)
                self.assertFalse(task2.shared)

                self.assertEqual(
                    [mock.call(task), mock.call(task2)],
                    build_driver_mock.call_args_list)

        self.assertEqual([
            mock.call(self.context, 'node-id1'),
            mock.call(self.context, 'node-id2')
        ], node_get_mock.call_args_list)
        self.assertEqual([
            mock.call(self.context, self.host, 'node-id1'),
            mock.call(self.context, self.host, 'node-id2')
        ], reserve_mock.call_args_list)
        self.assertEqual([
            mock.call(self.context, self.node.id),
            mock.call(self.context, node2.id)
        ], get_ports_mock.call_args_list)
        # release should be in reverse order
        self.assertEqual([
            mock.call(self.context, self.host, node2.id),
            mock.call(self.context, self.host, self.node.id)
        ], release_mock.call_args_list)