Set instance.availability_zone whenever we schedule

This ensures that instance.availability_zone reflects what AZ the
instance is actually in. In the case where no AZ was requested at
boot, previously this would always be some default value, which
isn't as useful to the things that need to consider what AZ the
instance is actually in (without doing all the aggregate math to
determine it on the fly).

Related to blueprint cells-aware-api
Change-Id: I8d426f2635232ffc4b510548a905794ca88d7f99
This commit is contained in:
Dan Smith 2017-03-15 08:34:04 -07:00
parent b9d4bc94ab
commit 03b4c67b22
47 changed files with 104 additions and 69 deletions

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":"2012-10-29T13:42:11Z", "deleted_at":"2012-10-29T13:42:11Z",
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":null, "architecture":null,
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture": null, "architecture": null,
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":null, "architecture":null,
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -62,7 +62,7 @@
"os_type": null, "os_type": null,
"uuid": "b271fcb9-75c3-4c76-84eb-6ccad1150ece", "uuid": "b271fcb9-75c3-4c76-84eb-6ccad1150ece",
"locked": false, "locked": false,
"availability_zone": null, "availability_zone": "nova",
"ramdisk_id": "", "ramdisk_id": "",
"architecture": null, "architecture": null,
"progress": 0, "progress": 0,

View File

@ -4,7 +4,7 @@
"nova_object.name": "InstanceActionPayload", "nova_object.name": "InstanceActionPayload",
"nova_object.data": { "nova_object.data": {
"state": "active", "state": "active",
"availability_zone": null, "availability_zone": "nova",
"kernel_id": "", "kernel_id": "",
"host_name": "some-server", "host_name": "some-server",
"progress": 0, "progress": 0,

View File

@ -64,7 +64,7 @@
} }
], ],
"tenant_id": "6f70656e737461636b20342065766572", "tenant_id": "6f70656e737461636b20342065766572",
"availability_zone": null, "availability_zone": "nova",
"host": "compute", "host": "compute",
"image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c", "image_uuid": "a2459075-d96c-40d5-893e-577ff92e721c",
"state": "active", "state": "active",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -3,7 +3,7 @@
"payload":{ "payload":{
"nova_object.data":{ "nova_object.data":{
"architecture":"x86_64", "architecture":"x86_64",
"availability_zone":null, "availability_zone": "nova",
"created_at":"2012-10-29T13:42:11Z", "created_at":"2012-10-29T13:42:11Z",
"deleted_at":null, "deleted_at":null,
"display_name":"some-server", "display_name":"some-server",

View File

@ -11,7 +11,7 @@
"nova_object.namespace": "nova", "nova_object.namespace": "nova",
"nova_object.version": "1.0" "nova_object.version": "1.0"
}, },
"availability_zone": null, "availability_zone": "nova",
"bandwidth": [], "bandwidth": [],
"created_at": "2012-10-29T13:42:11Z", "created_at": "2012-10-29T13:42:11Z",
"deleted_at": null, "deleted_at": null,

View File

@ -3,7 +3,7 @@
"payload": { "payload": {
"nova_object.data": { "nova_object.data": {
"architecture": "x86_64", "architecture": "x86_64",
"availability_zone": null, "availability_zone": "nova",
"created_at": "2012-10-29T13:42:11Z", "created_at": "2012-10-29T13:42:11Z",
"deleted_at": null, "deleted_at": null,
"display_name": "some-server", "display_name": "some-server",

View File

@ -3,7 +3,7 @@
"payload": { "payload": {
"nova_object.data": { "nova_object.data": {
"architecture": "x86_64", "architecture": "x86_64",
"availability_zone": null, "availability_zone": "nova",
"created_at": "2012-10-29T13:42:11Z", "created_at": "2012-10-29T13:42:11Z",
"deleted_at": null, "deleted_at": null,
"display_name": "some-server", "display_name": "some-server",

View File

@ -3,7 +3,7 @@
"payload": { "payload": {
"nova_object.data": { "nova_object.data": {
"architecture": "x86_64", "architecture": "x86_64",
"availability_zone": null, "availability_zone": "nova",
"created_at": "2012-10-29T13:42:11Z", "created_at": "2012-10-29T13:42:11Z",
"deleted_at": null, "deleted_at": null,
"display_name": "some-server", "display_name": "some-server",

View File

@ -25,6 +25,7 @@ from oslo_utils import excutils
from oslo_utils import versionutils from oslo_utils import versionutils
import six import six
from nova import availability_zones
from nova.compute import instance_actions from nova.compute import instance_actions
from nova.compute import rpcapi as compute_rpcapi from nova.compute import rpcapi as compute_rpcapi
from nova.compute import task_states from nova.compute import task_states
@ -575,8 +576,13 @@ class ComputeTaskManager(base.Base):
return return
for (instance, host) in six.moves.zip(instances, hosts): for (instance, host) in six.moves.zip(instances, hosts):
instance.availability_zone = (
availability_zones.get_host_availability_zone(context,
host['host']))
try: try:
instance.refresh() # NOTE(danms): This saves the az change above, refreshes our
# instance, and tells us if it has been deleted underneath us
instance.save()
except (exception.InstanceNotFound, except (exception.InstanceNotFound,
exception.InstanceInfoCacheNotFound): exception.InstanceInfoCacheNotFound):
LOG.debug('Instance deleted during build', instance=instance) LOG.debug('Instance deleted during build', instance=instance)
@ -698,6 +704,9 @@ class ComputeTaskManager(base.Base):
scheduler_utils.populate_filter_properties( scheduler_utils.populate_filter_properties(
filter_properties, host_state) filter_properties, host_state)
(host, node) = (host_state['host'], host_state['nodename']) (host, node) = (host_state['host'], host_state['nodename'])
instance.availability_zone = (
availability_zones.get_host_availability_zone(
context, host))
self.compute_rpcapi.unshelve_instance( self.compute_rpcapi.unshelve_instance(
context, instance, host, image=image, context, instance, host, image=image,
filter_properties=filter_properties, node=node) filter_properties=filter_properties, node=node)
@ -790,6 +799,10 @@ class ComputeTaskManager(base.Base):
compute_utils.notify_about_instance_usage( compute_utils.notify_about_instance_usage(
self.notifier, context, instance, "rebuild.scheduled") self.notifier, context, instance, "rebuild.scheduled")
instance.availability_zone = (
availability_zones.get_host_availability_zone(
context, host))
self.compute_rpcapi.rebuild_instance(context, self.compute_rpcapi.rebuild_instance(context,
instance=instance, instance=instance,
new_pass=new_pass, new_pass=new_pass,
@ -947,6 +960,9 @@ class ComputeTaskManager(base.Base):
'was already deleted.', instance=instance) 'was already deleted.', instance=instance)
continue continue
else: else:
instance.availability_zone = (
availability_zones.get_host_availability_zone(
context, host['host']))
with obj_target_cell(instance, cell): with obj_target_cell(instance, cell):
instance.create() instance.create()

View File

@ -12,6 +12,7 @@
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from nova import availability_zones
from nova.conductor.tasks import base from nova.conductor.tasks import base
from nova import objects from nova import objects
from nova.scheduler import utils as scheduler_utils from nova.scheduler import utils as scheduler_utils
@ -67,6 +68,10 @@ class MigrationTask(base.TaskBase):
(host, node) = (host_state['host'], host_state['nodename']) (host, node) = (host_state['host'], host_state['nodename'])
self.instance.availability_zone = (
availability_zones.get_host_availability_zone(
self.context, host))
# FIXME(sbauza): Serialize/Unserialize the legacy dict because of # FIXME(sbauza): Serialize/Unserialize the legacy dict because of
# oslo.messaging #1529084 to transform datetime values into strings. # oslo.messaging #1529084 to transform datetime values into strings.
# tl;dr: datetimes in dicts are not accepted as correct values by the # tl;dr: datetimes in dicts are not accepted as correct values by the

View File

@ -54,14 +54,17 @@ class MigrationTaskTestCase(test.NoDBTestCase):
compute_rpcapi.ComputeAPI(), compute_rpcapi.ComputeAPI(),
scheduler_client.SchedulerClient()) scheduler_client.SchedulerClient())
@mock.patch('nova.availability_zones.get_host_availability_zone')
@mock.patch.object(objects.RequestSpec, 'from_components') @mock.patch.object(objects.RequestSpec, 'from_components')
@mock.patch.object(scheduler_utils, 'setup_instance_group') @mock.patch.object(scheduler_utils, 'setup_instance_group')
@mock.patch.object(scheduler_client.SchedulerClient, 'select_destinations') @mock.patch.object(scheduler_client.SchedulerClient, 'select_destinations')
@mock.patch.object(compute_rpcapi.ComputeAPI, 'prep_resize') @mock.patch.object(compute_rpcapi.ComputeAPI, 'prep_resize')
@mock.patch.object(objects.Quotas, 'from_reservations') @mock.patch.object(objects.Quotas, 'from_reservations')
def test_execute(self, quotas_mock, prep_resize_mock, def test_execute(self, quotas_mock, prep_resize_mock,
sel_dest_mock, sig_mock, request_spec_from_components): sel_dest_mock, sig_mock, request_spec_from_components,
az_mock):
sel_dest_mock.return_value = self.hosts sel_dest_mock.return_value = self.hosts
az_mock.return_value = 'myaz'
task = self._generate_task() task = self._generate_task()
request_spec_from_components.return_value = self.request_spec request_spec_from_components.return_value = self.request_spec
legacy_request_spec = self.request_spec.to_legacy_request_spec_dict() legacy_request_spec = self.request_spec.to_legacy_request_spec_dict()
@ -74,7 +77,7 @@ class MigrationTaskTestCase(test.NoDBTestCase):
self.context, self.instance.uuid, self.request_spec.image, self.context, self.instance.uuid, self.request_spec.image,
task.flavor, self.instance.numa_topology, task.flavor, self.instance.numa_topology,
self.instance.pci_requests, expected_props, None, self.instance.pci_requests, expected_props, None,
self.instance.availability_zone) None)
quotas_mock.assert_called_once_with(self.context, self.reservations, quotas_mock.assert_called_once_with(self.context, self.reservations,
instance=self.instance) instance=self.instance)
sig_mock.assert_called_once_with(self.context, legacy_request_spec, sig_mock.assert_called_once_with(self.context, legacy_request_spec,
@ -88,6 +91,7 @@ class MigrationTaskTestCase(test.NoDBTestCase):
filter_properties=self.filter_properties, filter_properties=self.filter_properties,
node=self.hosts[0]['nodename'], clean_shutdown=self.clean_shutdown) node=self.hosts[0]['nodename'], clean_shutdown=self.clean_shutdown)
self.assertFalse(quotas_mock.return_value.rollback.called) self.assertFalse(quotas_mock.return_value.rollback.called)
az_mock.assert_called_once_with(self.context, 'host1')
def test_rollback(self): def test_rollback(self):
task = self._generate_task() task = self._generate_task()

View File

@ -379,8 +379,9 @@ class _BaseTaskTestCase(object):
def test_cold_migrate_forced_shutdown(self): def test_cold_migrate_forced_shutdown(self):
self._test_cold_migrate(clean_shutdown=False) self._test_cold_migrate(clean_shutdown=False)
@mock.patch('nova.objects.Instance.refresh') @mock.patch('nova.availability_zones.get_host_availability_zone')
def test_build_instances(self, mock_refresh): @mock.patch('nova.objects.Instance.save')
def test_build_instances(self, mock_save, mock_getaz):
instance_type = flavors.get_default_flavor() instance_type = flavors.get_default_flavor()
# NOTE(danms): Avoid datetime timezone issues with converted flavors # NOTE(danms): Avoid datetime timezone issues with converted flavors
instance_type.created_at = None instance_type.created_at = None
@ -455,6 +456,8 @@ class _BaseTaskTestCase(object):
# build_instances() is a cast, we need to wait for it to complete # build_instances() is a cast, we need to wait for it to complete
self.useFixture(cast_as_call.CastAsCall(self.stubs)) self.useFixture(cast_as_call.CastAsCall(self.stubs))
mock_getaz.return_value = 'myaz'
self.conductor.build_instances(self.context, self.conductor.build_instances(self.context,
instances=instances, instances=instances,
image={'fake_data': 'should_pass_silently'}, image={'fake_data': 'should_pass_silently'},
@ -465,6 +468,9 @@ class _BaseTaskTestCase(object):
security_groups='security_groups', security_groups='security_groups',
block_device_mapping='block_device_mapping', block_device_mapping='block_device_mapping',
legacy_bdm=False) legacy_bdm=False)
mock_getaz.assert_has_calls([
mock.call(self.context, 'host1'),
mock.call(self.context, 'host2')])
@mock.patch.object(scheduler_utils, 'build_request_spec') @mock.patch.object(scheduler_utils, 'build_request_spec')
@mock.patch.object(scheduler_utils, 'setup_instance_group') @mock.patch.object(scheduler_utils, 'setup_instance_group')
@ -608,7 +614,7 @@ class _BaseTaskTestCase(object):
state_mock.assert_has_calls(set_state_calls) state_mock.assert_has_calls(set_state_calls)
cleanup_mock.assert_has_calls(cleanup_network_calls) cleanup_mock.assert_has_calls(cleanup_network_calls)
@mock.patch.object(objects.Instance, 'refresh') @mock.patch.object(objects.Instance, 'save')
@mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid', @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid',
side_effect=exc.InstanceMappingNotFound(uuid='fake')) side_effect=exc.InstanceMappingNotFound(uuid='fake'))
@mock.patch.object(objects.HostMapping, 'get_by_host') @mock.patch.object(objects.HostMapping, 'get_by_host')
@ -618,7 +624,7 @@ class _BaseTaskTestCase(object):
'_set_vm_state_and_notify') '_set_vm_state_and_notify')
def test_build_instances_no_instance_mapping(self, _mock_set_state, def test_build_instances_no_instance_mapping(self, _mock_set_state,
mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid, mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid,
_mock_refresh): _mock_save):
mock_select_dests.return_value = [ mock_select_dests.return_value = [
{'host': 'host1', 'nodename': 'node1', 'limits': []}, {'host': 'host1', 'nodename': 'node1', 'limits': []},
@ -649,7 +655,7 @@ class _BaseTaskTestCase(object):
mock.call(self.context, instances[1].uuid)]) mock.call(self.context, instances[1].uuid)])
self.assertFalse(mock_get_by_host.called) self.assertFalse(mock_get_by_host.called)
@mock.patch.object(objects.Instance, 'refresh') @mock.patch.object(objects.Instance, 'save')
@mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid') @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid')
@mock.patch.object(objects.HostMapping, 'get_by_host', @mock.patch.object(objects.HostMapping, 'get_by_host',
side_effect=exc.HostMappingNotFound(name='fake')) side_effect=exc.HostMappingNotFound(name='fake'))
@ -659,7 +665,7 @@ class _BaseTaskTestCase(object):
'_set_vm_state_and_notify') '_set_vm_state_and_notify')
def test_build_instances_no_host_mapping(self, _mock_set_state, def test_build_instances_no_host_mapping(self, _mock_set_state,
mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid, mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid,
_mock_refresh): _mock_save):
mock_select_dests.return_value = [ mock_select_dests.return_value = [
{'host': 'host1', 'nodename': 'node1', 'limits': []}, {'host': 'host1', 'nodename': 'node1', 'limits': []},
@ -698,7 +704,7 @@ class _BaseTaskTestCase(object):
mock_get_by_host.assert_has_calls([mock.call(self.context, 'host1'), mock_get_by_host.assert_has_calls([mock.call(self.context, 'host1'),
mock.call(self.context, 'host2')]) mock.call(self.context, 'host2')])
@mock.patch.object(objects.Instance, 'refresh') @mock.patch.object(objects.Instance, 'save')
@mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid') @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid')
@mock.patch.object(objects.HostMapping, 'get_by_host') @mock.patch.object(objects.HostMapping, 'get_by_host')
@mock.patch.object(scheduler_client.SchedulerClient, @mock.patch.object(scheduler_client.SchedulerClient,
@ -707,7 +713,7 @@ class _BaseTaskTestCase(object):
'_set_vm_state_and_notify') '_set_vm_state_and_notify')
def test_build_instances_update_instance_mapping(self, _mock_set_state, def test_build_instances_update_instance_mapping(self, _mock_set_state,
mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid, mock_select_dests, mock_get_by_host, mock_get_inst_map_by_uuid,
_mock_refresh): _mock_save):
mock_select_dests.return_value = [ mock_select_dests.return_value = [
{'host': 'host1', 'nodename': 'node1', 'limits': []}, {'host': 'host1', 'nodename': 'node1', 'limits': []},
@ -751,7 +757,7 @@ class _BaseTaskTestCase(object):
mock_get_by_host.assert_has_calls([mock.call(self.context, 'host1'), mock_get_by_host.assert_has_calls([mock.call(self.context, 'host1'),
mock.call(self.context, 'host2')]) mock.call(self.context, 'host2')])
@mock.patch.object(objects.Instance, 'refresh', new=mock.MagicMock()) @mock.patch.object(objects.Instance, 'save', new=mock.MagicMock())
@mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid') @mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid')
@mock.patch.object(scheduler_client.SchedulerClient, @mock.patch.object(scheduler_client.SchedulerClient,
'select_destinations') 'select_destinations')
@ -796,7 +802,7 @@ class _BaseTaskTestCase(object):
for build_req in build_req_mocks: for build_req in build_req_mocks:
build_req.destroy.assert_called_once_with() build_req.destroy.assert_called_once_with()
@mock.patch.object(objects.Instance, 'refresh', new=mock.MagicMock()) @mock.patch.object(objects.Instance, 'save', new=mock.MagicMock())
@mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid', @mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid',
side_effect=exc.BuildRequestNotFound(uuid='fake')) side_effect=exc.BuildRequestNotFound(uuid='fake'))
@mock.patch.object(scheduler_client.SchedulerClient, @mock.patch.object(scheduler_client.SchedulerClient,
@ -839,7 +845,7 @@ class _BaseTaskTestCase(object):
do_test() do_test()
@mock.patch.object(objects.Service, 'get_minimum_version', return_value=12) @mock.patch.object(objects.Service, 'get_minimum_version', return_value=12)
@mock.patch.object(objects.Instance, 'refresh', new=mock.MagicMock()) @mock.patch.object(objects.Instance, 'save', new=mock.MagicMock())
@mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid', @mock.patch.object(objects.BuildRequest, 'get_by_instance_uuid',
side_effect=exc.BuildRequestNotFound(uuid='fake')) side_effect=exc.BuildRequestNotFound(uuid='fake'))
@mock.patch.object(scheduler_client.SchedulerClient, @mock.patch.object(scheduler_client.SchedulerClient,
@ -886,7 +892,7 @@ class _BaseTaskTestCase(object):
mock_service_version.assert_called_once_with(self.context, mock_service_version.assert_called_once_with(self.context,
'nova-osapi_compute') 'nova-osapi_compute')
@mock.patch.object(objects.Instance, 'refresh', new=mock.MagicMock()) @mock.patch.object(objects.Instance, 'save', new=mock.MagicMock())
@mock.patch.object(scheduler_client.SchedulerClient, @mock.patch.object(scheduler_client.SchedulerClient,
'select_destinations') 'select_destinations')
@mock.patch.object(conductor_manager.ComputeTaskManager, @mock.patch.object(conductor_manager.ComputeTaskManager,
@ -1432,13 +1438,16 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
objects=[bdm]) objects=[bdm])
self.params = params self.params = params
@mock.patch('nova.availability_zones.get_host_availability_zone')
@mock.patch('nova.compute.rpcapi.ComputeAPI.build_and_run_instance') @mock.patch('nova.compute.rpcapi.ComputeAPI.build_and_run_instance')
@mock.patch('nova.scheduler.rpcapi.SchedulerAPI.select_destinations') @mock.patch('nova.scheduler.rpcapi.SchedulerAPI.select_destinations')
def test_schedule_and_build_instances(self, select_destinations, def test_schedule_and_build_instances(self, select_destinations,
build_and_run_instance): build_and_run_instance,
get_az):
select_destinations.return_value = [{'host': 'fake-host', select_destinations.return_value = [{'host': 'fake-host',
'nodename': 'fake-nodename', 'nodename': 'fake-nodename',
'limits': None}] 'limits': None}]
get_az.return_value = 'myaz'
params = self.params params = self.params
details = {} details = {}
@ -1453,6 +1462,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
build_and_run_instance.side_effect = _build_and_run_instance build_and_run_instance.side_effect = _build_and_run_instance
self.conductor.schedule_and_build_instances(**params) self.conductor.schedule_and_build_instances(**params)
self.assertTrue(build_and_run_instance.called) self.assertTrue(build_and_run_instance.called)
get_az.assert_called_once_with(mock.ANY, 'fake-host')
instance_uuid = details['instance'].uuid instance_uuid = details['instance'].uuid
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
@ -2227,8 +2237,8 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
def test_build_instances_instance_not_found(self): def test_build_instances_instance_not_found(self):
instances = [fake_instance.fake_instance_obj(self.context) instances = [fake_instance.fake_instance_obj(self.context)
for i in range(2)] for i in range(2)]
self.mox.StubOutWithMock(instances[0], 'refresh') self.mox.StubOutWithMock(instances[0], 'save')
self.mox.StubOutWithMock(instances[1], 'refresh') self.mox.StubOutWithMock(instances[1], 'save')
image = {'fake-data': 'should_pass_silently'} image = {'fake-data': 'should_pass_silently'}
spec = {'fake': 'specs', spec = {'fake': 'specs',
'instance_properties': instances[0]} 'instance_properties': instances[0]}
@ -2244,9 +2254,9 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
spec, filter_properties).AndReturn( spec, filter_properties).AndReturn(
[{'host': 'host1', 'nodename': 'node1', 'limits': []}, [{'host': 'host1', 'nodename': 'node1', 'limits': []},
{'host': 'host2', 'nodename': 'node2', 'limits': []}]) {'host': 'host2', 'nodename': 'node2', 'limits': []}])
instances[0].refresh().AndRaise( instances[0].save().AndRaise(
exc.InstanceNotFound(instance_id=instances[0].uuid)) exc.InstanceNotFound(instance_id=instances[0].uuid))
instances[1].refresh() instances[1].save()
self.conductor_manager.compute_rpcapi.build_and_run_instance( self.conductor_manager.compute_rpcapi.build_and_run_instance(
self.context, instance=instances[1], host='host2', self.context, instance=instances[1], host='host2',
image={'fake-data': 'should_pass_silently'}, request_spec=spec, image={'fake-data': 'should_pass_silently'}, request_spec=spec,
@ -2289,16 +2299,16 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
'instance_properties': instances[0]} 'instance_properties': instances[0]}
build_request_spec.return_value = spec build_request_spec.return_value = spec
with test.nested( with test.nested(
mock.patch.object(instances[0], 'refresh', mock.patch.object(instances[0], 'save',
side_effect=exc.InstanceInfoCacheNotFound( side_effect=exc.InstanceInfoCacheNotFound(
instance_uuid=instances[0].uuid)), instance_uuid=instances[0].uuid)),
mock.patch.object(instances[1], 'refresh'), mock.patch.object(instances[1], 'save'),
mock.patch.object(objects.RequestSpec, 'from_primitives'), mock.patch.object(objects.RequestSpec, 'from_primitives'),
mock.patch.object(self.conductor_manager.scheduler_client, mock.patch.object(self.conductor_manager.scheduler_client,
'select_destinations', return_value=destinations), 'select_destinations', return_value=destinations),
mock.patch.object(self.conductor_manager.compute_rpcapi, mock.patch.object(self.conductor_manager.compute_rpcapi,
'build_and_run_instance') 'build_and_run_instance')
) as (inst1_refresh, inst2_refresh, from_primitives, ) as (inst1_save, inst2_save, from_primitives,
select_destinations, select_destinations,
build_and_run_instance): build_and_run_instance):