Make compute_api use InstanceAction object
This makes the compute_api instance action code use objects instead of direct-to-database calls. This should open the door for deprecating some conductor proxies for compute_api that help compute manager avoid the database hit required for the instance action to complete. Related to blueprint compute-api-objects Change-Id: If622d8079ca2897b0d5094e9341e29cde7c1ff59
This commit is contained in:
parent
845c1deb38
commit
8a13967f12
|
@ -53,6 +53,7 @@ from nova.network.security_group import security_group_base
|
||||||
from nova import notifications
|
from nova import notifications
|
||||||
from nova.objects import base as obj_base
|
from nova.objects import base as obj_base
|
||||||
from nova.objects import instance as instance_obj
|
from nova.objects import instance as instance_obj
|
||||||
|
from nova.objects import instance_action
|
||||||
from nova.objects import instance_info_cache
|
from nova.objects import instance_info_cache
|
||||||
from nova.objects import security_group
|
from nova.objects import security_group
|
||||||
from nova.openstack.common import excutils
|
from nova.openstack.common import excutils
|
||||||
|
@ -277,9 +278,10 @@ class API(base.Base):
|
||||||
return instance_ref
|
return instance_ref
|
||||||
|
|
||||||
def _record_action_start(self, context, instance, action):
|
def _record_action_start(self, context, instance, action):
|
||||||
act = compute_utils.pack_action_start(context, instance['uuid'],
|
instance_action.InstanceAction.action_start(context,
|
||||||
action)
|
instance['uuid'],
|
||||||
self.db.action_start(context, act)
|
action,
|
||||||
|
want_result=False)
|
||||||
|
|
||||||
def _check_injected_file_quota(self, context, injected_files):
|
def _check_injected_file_quota(self, context, injected_files):
|
||||||
"""Enforce quota limits on injected files.
|
"""Enforce quota limits on injected files.
|
||||||
|
@ -2949,14 +2951,16 @@ class InstanceActionAPI(base.Base):
|
||||||
"""Sub-set of the Compute Manager API for managing instance actions."""
|
"""Sub-set of the Compute Manager API for managing instance actions."""
|
||||||
|
|
||||||
def actions_get(self, context, instance):
|
def actions_get(self, context, instance):
|
||||||
return self.db.actions_get(context, instance['uuid'])
|
return instance_action.InstanceActionList.get_by_instance_uuid(
|
||||||
|
context, instance['uuid'])
|
||||||
|
|
||||||
def action_get_by_request_id(self, context, instance, request_id):
|
def action_get_by_request_id(self, context, instance, request_id):
|
||||||
return self.db.action_get_by_request_id(context, instance['uuid'],
|
return instance_action.InstanceAction.get_by_request_id(
|
||||||
request_id)
|
context, instance['uuid'], request_id)
|
||||||
|
|
||||||
def action_events_get(self, context, instance, action_id):
|
def action_events_get(self, context, instance, action_id):
|
||||||
return self.db.action_events_get(context, action_id)
|
return instance_action.InstanceActionEventList.get_by_action(
|
||||||
|
context, action_id)
|
||||||
|
|
||||||
|
|
||||||
class AggregateAPI(base.Base):
|
class AggregateAPI(base.Base):
|
||||||
|
|
|
@ -36,13 +36,14 @@ FAKE_REQUEST_ID = fake_instance_actions.FAKE_REQUEST_ID1
|
||||||
|
|
||||||
def format_action(action):
|
def format_action(action):
|
||||||
'''Remove keys that aren't serialized.'''
|
'''Remove keys that aren't serialized.'''
|
||||||
if 'id' in action:
|
to_delete = ('id', 'finish_time', 'created_at', 'updated_at', 'deleted_at',
|
||||||
del(action['id'])
|
'deleted')
|
||||||
if 'finish_time' in action:
|
for key in to_delete:
|
||||||
del(action['finish_time'])
|
if key in action:
|
||||||
|
del(action[key])
|
||||||
if 'start_time' in action:
|
if 'start_time' in action:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified
|
||||||
action['start_time'] = str(action['start_time'])
|
action['start_time'] = str(action['start_time'].replace(tzinfo=None))
|
||||||
for event in action.get('events', []):
|
for event in action.get('events', []):
|
||||||
format_event(event)
|
format_event(event)
|
||||||
return action
|
return action
|
||||||
|
@ -50,14 +51,17 @@ def format_action(action):
|
||||||
|
|
||||||
def format_event(event):
|
def format_event(event):
|
||||||
'''Remove keys that aren't serialized.'''
|
'''Remove keys that aren't serialized.'''
|
||||||
if 'id' in event:
|
to_delete = ('id', 'created_at', 'updated_at', 'deleted_at', 'deleted',
|
||||||
del(event['id'])
|
'action_id')
|
||||||
|
for key in to_delete:
|
||||||
|
if key in event:
|
||||||
|
del(event[key])
|
||||||
if 'start_time' in event:
|
if 'start_time' in event:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified
|
||||||
event['start_time'] = str(event['start_time'])
|
event['start_time'] = str(event['start_time'].replace(tzinfo=None))
|
||||||
if 'finish_time' in event:
|
if 'finish_time' in event:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified
|
||||||
event['finish_time'] = str(event['finish_time'])
|
event['finish_time'] = str(event['finish_time'].replace(tzinfo=None))
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,8 +160,6 @@ class InstanceActionsTest(test.TestCase):
|
||||||
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
|
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
|
||||||
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||||
fake_events = self.fake_events[fake_action['id']]
|
fake_events = self.fake_events[fake_action['id']]
|
||||||
fake_events = [format_event(event) for event in fake_events]
|
|
||||||
fake_action = format_action(fake_action)
|
|
||||||
fake_action['events'] = fake_events
|
fake_action['events'] = fake_events
|
||||||
self.assertEqual(format_action(fake_action),
|
self.assertEqual(format_action(fake_action),
|
||||||
format_action(res_dict['instanceAction']))
|
format_action(res_dict['instanceAction']))
|
||||||
|
@ -239,7 +241,7 @@ class InstanceActionsSerializerTest(test.TestCase):
|
||||||
serializer = instance_actions.InstanceActionTemplate()
|
serializer = instance_actions.InstanceActionTemplate()
|
||||||
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||||
event = self.fake_events[action['id']][0]
|
event = self.fake_events[action['id']][0]
|
||||||
action['events'] = [event, event]
|
action['events'] = [dict(event), dict(event)]
|
||||||
text = serializer.serialize({'instanceAction': action})
|
text = serializer.serialize({'instanceAction': action})
|
||||||
tree = etree.fromstring(text)
|
tree = etree.fromstring(text)
|
||||||
|
|
||||||
|
|
|
@ -36,13 +36,15 @@ FAKE_REQUEST_ID = fake_instance_actions.FAKE_REQUEST_ID1
|
||||||
|
|
||||||
def format_action(action):
|
def format_action(action):
|
||||||
'''Remove keys that aren't serialized.'''
|
'''Remove keys that aren't serialized.'''
|
||||||
if 'id' in action:
|
to_delete = ('id', 'finish_time', 'created_at', 'updated_at', 'deleted_at',
|
||||||
del(action['id'])
|
'deleted')
|
||||||
if 'finish_time' in action:
|
for key in to_delete:
|
||||||
del(action['finish_time'])
|
if key in action:
|
||||||
|
del(action[key])
|
||||||
if 'start_time' in action:
|
if 'start_time' in action:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||||
action['start_time'] = str(action['start_time'])
|
# and objects will have added a timezone, so strip that for comparison
|
||||||
|
action['start_time'] = str(action['start_time'].replace(tzinfo=None))
|
||||||
for event in action.get('events', []):
|
for event in action.get('events', []):
|
||||||
format_event(event)
|
format_event(event)
|
||||||
return action
|
return action
|
||||||
|
@ -50,14 +52,19 @@ def format_action(action):
|
||||||
|
|
||||||
def format_event(event):
|
def format_event(event):
|
||||||
'''Remove keys that aren't serialized.'''
|
'''Remove keys that aren't serialized.'''
|
||||||
if 'id' in event:
|
to_delete = ('id', 'created_at', 'updated_at', 'deleted_at', 'deleted',
|
||||||
del(event['id'])
|
'action_id')
|
||||||
|
for key in to_delete:
|
||||||
|
if key in event:
|
||||||
|
del(event[key])
|
||||||
if 'start_time' in event:
|
if 'start_time' in event:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||||
event['start_time'] = str(event['start_time'])
|
# and objects will have added a timezone, so strip that for comparison
|
||||||
|
event['start_time'] = str(event['start_time'].replace(tzinfo=None))
|
||||||
if 'finish_time' in event:
|
if 'finish_time' in event:
|
||||||
# NOTE(danms): Without WSGI above us, these will be just stringified
|
# NOTE(danms): Without WSGI above us, these will be just stringified,
|
||||||
event['finish_time'] = str(event['finish_time'])
|
# and objects will have added a timezone, so strip that for comparison
|
||||||
|
event['finish_time'] = str(event['finish_time'].replace(tzinfo=None))
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,7 +167,6 @@ class InstanceActionsTest(test.TestCase):
|
||||||
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
|
res_dict = self.controller.show(req, FAKE_UUID, FAKE_REQUEST_ID)
|
||||||
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
fake_action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||||
fake_events = self.fake_events[fake_action['id']]
|
fake_events = self.fake_events[fake_action['id']]
|
||||||
fake_events = [format_event(event) for event in fake_events]
|
|
||||||
fake_action['events'] = fake_events
|
fake_action['events'] = fake_events
|
||||||
self.assertEqual(format_action(fake_action),
|
self.assertEqual(format_action(fake_action),
|
||||||
format_action(res_dict['instance_action']))
|
format_action(res_dict['instance_action']))
|
||||||
|
@ -251,7 +257,7 @@ class InstanceActionsSerializerTest(test.TestCase):
|
||||||
serializer = instance_actions.InstanceActionTemplate()
|
serializer = instance_actions.InstanceActionTemplate()
|
||||||
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
action = self.fake_actions[FAKE_UUID][FAKE_REQUEST_ID]
|
||||||
event = self.fake_events[action['id']][0]
|
event = self.fake_events[action['id']][0]
|
||||||
action['events'] = [event, event]
|
action['events'] = [dict(event), dict(event)]
|
||||||
text = serializer.serialize({'instance_action': action})
|
text = serializer.serialize({'instance_action': action})
|
||||||
tree = etree.fromstring(text)
|
tree = etree.fromstring(text)
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,10 @@ FAKE_ACTIONS = {
|
||||||
2012, 12, 5, 0, 0, 0, 0),
|
2012, 12, 5, 0, 0, 0, 0),
|
||||||
'finish_time': None,
|
'finish_time': None,
|
||||||
'message': '',
|
'message': '',
|
||||||
|
'created_at': None,
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'deleted': False,
|
||||||
},
|
},
|
||||||
FAKE_REQUEST_ID2: {'id': FAKE_ACTION_ID2,
|
FAKE_REQUEST_ID2: {'id': FAKE_ACTION_ID2,
|
||||||
'action': 'resize',
|
'action': 'resize',
|
||||||
|
@ -48,12 +52,17 @@ FAKE_ACTIONS = {
|
||||||
2012, 12, 5, 1, 0, 0, 0),
|
2012, 12, 5, 1, 0, 0, 0),
|
||||||
'finish_time': None,
|
'finish_time': None,
|
||||||
'message': '',
|
'message': '',
|
||||||
|
'created_at': None,
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'deleted': False,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FAKE_EVENTS = {
|
FAKE_EVENTS = {
|
||||||
FAKE_ACTION_ID1: [{'id': 1,
|
FAKE_ACTION_ID1: [{'id': 1,
|
||||||
|
'action_id': FAKE_ACTION_ID1,
|
||||||
'event': 'schedule',
|
'event': 'schedule',
|
||||||
'start_time': datetime.datetime(
|
'start_time': datetime.datetime(
|
||||||
2012, 12, 5, 1, 0, 2, 0),
|
2012, 12, 5, 1, 0, 2, 0),
|
||||||
|
@ -61,8 +70,13 @@ FAKE_EVENTS = {
|
||||||
2012, 12, 5, 1, 2, 0, 0),
|
2012, 12, 5, 1, 2, 0, 0),
|
||||||
'result': 'Success',
|
'result': 'Success',
|
||||||
'traceback': '',
|
'traceback': '',
|
||||||
|
'created_at': None,
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'deleted': False,
|
||||||
},
|
},
|
||||||
{'id': 2,
|
{'id': 2,
|
||||||
|
'action_id': FAKE_ACTION_ID1,
|
||||||
'event': 'compute_create',
|
'event': 'compute_create',
|
||||||
'start_time': datetime.datetime(
|
'start_time': datetime.datetime(
|
||||||
2012, 12, 5, 1, 3, 0, 0),
|
2012, 12, 5, 1, 3, 0, 0),
|
||||||
|
@ -70,16 +84,25 @@ FAKE_EVENTS = {
|
||||||
2012, 12, 5, 1, 4, 0, 0),
|
2012, 12, 5, 1, 4, 0, 0),
|
||||||
'result': 'Success',
|
'result': 'Success',
|
||||||
'traceback': '',
|
'traceback': '',
|
||||||
|
'created_at': None,
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'deleted': False,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
FAKE_ACTION_ID2: [{'id': 3,
|
FAKE_ACTION_ID2: [{'id': 3,
|
||||||
|
'action_id': FAKE_ACTION_ID2,
|
||||||
'event': 'schedule',
|
'event': 'schedule',
|
||||||
'start_time': datetime.datetime(
|
'start_time': datetime.datetime(
|
||||||
2012, 12, 5, 3, 0, 0, 0),
|
2012, 12, 5, 3, 0, 0, 0),
|
||||||
'finish_time': datetime.datetime(
|
'finish_time': datetime.datetime(
|
||||||
2012, 12, 5, 3, 2, 0, 0),
|
2012, 12, 5, 3, 2, 0, 0),
|
||||||
'result': 'Error',
|
'result': 'Error',
|
||||||
'traceback': ''
|
'traceback': '',
|
||||||
|
'created_at': None,
|
||||||
|
'updated_at': None,
|
||||||
|
'deleted_at': None,
|
||||||
|
'deleted': False,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue