|
1 commit 40a37269c52977a718e91012cfd4580b2e31ec65 |
|
2 Author: He Jie Xu <[email protected]> |
|
3 Date: Fri Nov 7 23:29:18 2014 +0800 |
|
4 |
|
5 Set vm state error when raising unexpected exception in live migrate |
|
6 |
|
7 The instance stuck at migrating task_state when unexpected exception. |
|
8 This is confuse for user, this patch set the vm_state to error. |
|
9 |
|
10 Change-Id: Ib1b97452bc5e777c66c4d368f71156dbe1e116b7 |
|
11 Partial-Bug: 1397153 |
|
12 |
|
13 --- nova-2014.2.2/nova/conductor/manager.py.~2~ 2015-12-01 04:57:58.583807338 -0800 |
|
14 +++ nova-2014.2.2/nova/conductor/manager.py 2015-12-01 05:00:43.319845439 -0800 |
|
15 @@ -558,6 +558,19 @@ class ComputeTaskManager(base.Base): |
|
16 def _live_migrate(self, context, instance, scheduler_hint, |
|
17 block_migration, disk_over_commit): |
|
18 destination = scheduler_hint.get("host") |
|
19 + |
|
20 + def _set_vm_state(context, instance, ex, vm_state=None, |
|
21 + task_state=None): |
|
22 + request_spec = {'instance_properties': { |
|
23 + 'uuid': instance['uuid'], }, |
|
24 + } |
|
25 + scheduler_utils.set_vm_state_and_notify(context, |
|
26 + 'compute_task', 'migrate_server', |
|
27 + dict(vm_state=vm_state, |
|
28 + task_state=task_state, |
|
29 + expected_task_state=task_states.MIGRATING,), |
|
30 + ex, request_spec, self.db) |
|
31 + |
|
32 try: |
|
33 live_migrate.execute(context, instance, destination, |
|
34 block_migration, disk_over_commit) |
|
35 @@ -575,20 +588,14 @@ class ComputeTaskManager(base.Base): |
|
36 exception.LiveMigrationWithOldNovaNotSafe) as ex: |
|
37 with excutils.save_and_reraise_exception(): |
|
38 # TODO(johngarbutt) - eventually need instance actions here |
|
39 - request_spec = {'instance_properties': { |
|
40 - 'uuid': instance['uuid'], }, |
|
41 - } |
|
42 - scheduler_utils.set_vm_state_and_notify(context, |
|
43 - 'compute_task', 'migrate_server', |
|
44 - dict(vm_state=instance['vm_state'], |
|
45 - task_state=None, |
|
46 - expected_task_state=task_states.MIGRATING,), |
|
47 - ex, request_spec, self.db) |
|
48 + _set_vm_state(context, instance, ex, instance['vm_state']) |
|
49 except Exception as ex: |
|
50 LOG.error(_('Migration of instance %(instance_id)s to host' |
|
51 ' %(dest)s unexpectedly failed.'), |
|
52 {'instance_id': instance['uuid'], 'dest': destination}, |
|
53 exc_info=True) |
|
54 + _set_vm_state(context, instance, ex, vm_states.ERROR, |
|
55 + instance['task_state']) |
|
56 raise exception.MigrationError(reason=six.text_type(ex)) |
|
57 |
|
58 def build_instances(self, context, instances, image, filter_properties, |
|
59 --- nova-2014.2.2/nova/tests/conductor/test_conductor.py.~2~ 2015-12-01 04:57:58.599204982 -0800 |
|
60 +++ nova-2014.2.2/nova/tests/conductor/test_conductor.py 2015-12-01 05:04:39.416251458 -0800 |
|
61 @@ -1704,27 +1704,28 @@ class ConductorTaskTestCase(_BaseTaskTes |
|
62 ex = exc.LiveMigrationWithOldNovaNotSafe(server='dummy') |
|
63 self._test_migrate_server_deals_with_expected_exceptions(ex) |
|
64 |
|
65 - def test_migrate_server_deals_with_unexpected_exceptions(self): |
|
66 + @mock.patch.object(scheduler_utils, 'set_vm_state_and_notify') |
|
67 + @mock.patch.object(live_migrate, 'execute') |
|
68 + def test_migrate_server_deals_with_unexpected_exceptions(self, |
|
69 + mock_live_migrate, mock_set_state): |
|
70 + expected_ex = IOError('fake error') |
|
71 + mock_live_migrate.side_effect = expected_ex |
|
72 instance = fake_instance.fake_db_instance() |
|
73 inst_obj = objects.Instance._from_db_object( |
|
74 self.context, objects.Instance(), instance, []) |
|
75 - self.mox.StubOutWithMock(live_migrate, 'execute') |
|
76 - self.mox.StubOutWithMock(scheduler_utils, |
|
77 - 'set_vm_state_and_notify') |
|
78 - |
|
79 - expected_ex = IOError('fake error') |
|
80 - live_migrate.execute(self.context, mox.IsA(objects.Instance), |
|
81 - 'destination', 'block_migration', |
|
82 - 'disk_over_commit').AndRaise(expected_ex) |
|
83 - self.mox.ReplayAll() |
|
84 - |
|
85 - self.conductor = utils.ExceptionHelper(self.conductor) |
|
86 - |
|
87 ex = self.assertRaises(exc.MigrationError, |
|
88 self.conductor.migrate_server, self.context, inst_obj, |
|
89 {'host': 'destination'}, True, False, None, 'block_migration', |
|
90 'disk_over_commit') |
|
91 - self.assertEqual(ex.kwargs['reason'], six.text_type(expected_ex)) |
|
92 + request_spec = {'instance_properties': { |
|
93 + 'uuid': instance['uuid'], }, |
|
94 + } |
|
95 + mock_set_state.assert_called_once_with(self.context, |
|
96 + 'compute_task', 'migrate_server', |
|
97 + dict(vm_state=vm_states.ERROR, |
|
98 + task_state=inst_obj.task_state, |
|
99 + expected_task_state=task_states.MIGRATING,), |
|
100 + expected_ex, request_spec, self.conductor.db) |
|
101 |
|
102 def test_set_vm_state_and_notify(self): |
|
103 self.mox.StubOutWithMock(scheduler_utils, |