nova boot failure while the vm state/task_state is set by sync code

For spawning, it will loop to check the powervc vm instance status,
there will be a timing window that the VM because active, then the sync
is running here, but the driver's spawning is till sleeping, then after
this sync code run, nova framework will fail with above exception..

This sync code need to be retained there as the VM might stick with
build/spawning state like the nova-powervc is abnormal killed...,
the fix solution can be:
1. create a dict in sync code, and put such state instance id to
this dict,
2. in next sync sycle, check if the instance is still in build/spawning,
 but the powervc state is in acitve/none, then update status and remove
the id from the dict, this will delay the state updating in sync
process to avoid the time window that driver.spawning is sleeping
to poll the powervc instance state.

Change-Id: I7fe9f5f2b48c9758bc102ebf209d631c0308a316
Closes-Bug: 1388683
This commit is contained in:
Jerry Cai 2014-11-03 11:13:20 +08:00
parent 40e90593e3
commit 9492f9637e
1 changed files with 35 additions and 14 deletions

View File

@ -77,6 +77,8 @@ class PowerVCCloudManager(manager.Manager):
LOG.error(_("Unable to load the PowerVC driver: %s") % (e))
sys.exit(1)
# Defer update local vm when powervc vm ids in spawning status
self.defer_update_local_vm_in_spawning_ids = []
# The variable used to cache the volume data
self.cache_volume = utills.VolumeCache(self.driver)
self.compute_api = compute.API()
@ -1622,26 +1624,45 @@ class PowerVCCloudManager(manager.Manager):
pvc_instance)
return True
local_id = local_instance.get('uuid')
if (pvc_task_state is None and
(pvc_vm_state == vm_states.ACTIVE or
pvc_vm_state == vm_states.ERROR) and
local_task_state == task_states.SPAWNING):
LOG.info(_('Update %(pvc_ins)s to %(local_ins)s, when'
'pvc_task_state is %(pvc_task_state)s,'
'pvc_vm_state is %(pvc_vm_state)s,'
'local_task_state is %(local_task_state)s,'
'local_vm_state is %(local_vm_state)s'
% {'pvc_ins': pvc_instance,
'local_ins': local_instance,
'pvc_task_state': pvc_task_state,
'pvc_vm_state': pvc_vm_state,
'local_task_state': local_task_state,
'local_vm_state': local_vm_state}))
# Defer update local vm when powervc vm ids in spawning status
if local_id in self.defer_update_local_vm_in_spawning_ids:
LOG.info(_('Update %(pvc_ins)s to %(local_ins)s, when'
'pvc_task_state is %(pvc_task_state)s,'
'pvc_vm_state is %(pvc_vm_state)s,'
'local_task_state is %(local_task_state)s,'
'local_vm_state is %(local_vm_state)s'
% {'pvc_ins': pvc_instance,
'local_ins': local_instance,
'pvc_task_state': pvc_task_state,
'pvc_vm_state': pvc_vm_state,
'local_task_state': local_task_state,
'local_vm_state': local_vm_state}))
self._sync_existing_instance(context,
local_instance,
pvc_instance)
# send out event for instance create finished
compute.utils.notify_about_instance_usage(self.notifier,
context,
local_instance,
"create.sync",
network_info={},
system_metadata={},
extra_usage_info={})
self.defer_update_local_vm_in_spawning_ids.remove(local_id)
else:
self.defer_update_local_vm_in_spawning_ids.append(local_id)
LOG.info(_('VM: %(uuid)s is in spawning status, defer update.'
' Just add uuid to list and will update next time.'
% {'uuid': local_id}))
self._sync_existing_instance(context,
local_instance,
pvc_instance)
return True
LOG.debug(_('Skip update %(pvc_ins)s to %(local_ins)s, because'