From dced117ea919b74d9521ff422b4eb8a880474a0d Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Wed, 13 Mar 2013 14:45:49 -0400 Subject: Generalize console error handling during build. There is a race condition where you can create an instance and then quickly request a VNC or Spice console before the instance is ready. The way this went down was different depending on the virt driver in use. The libvirt driver would raise InstanceNotFound. The xenapi driver would raise InstanceNotReady. This patch moves the handling of this race that was in the xenapi driver up to the compute manager. Now, all of the virt drivers that support this method (libvirt, xenapi, vmware) will all raise InstanceNotFound in this case, and the compute manager will convert it into InstanceNotReady IFF the vm_state is BUILDING. Related to bug 1154327. Change-Id: I68f4a6db8aac26c6f731c985d97299ee38c34448 --- nova/compute/manager.py | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 3d3a094a2..2ced60da3 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2580,7 +2580,8 @@ class ComputeManager(manager.SchedulerDependentManager): else: return '\n'.join(log.split('\n')[-int(length):]) - @rpc_common.client_exceptions(exception.ConsoleTypeInvalid) + @rpc_common.client_exceptions(exception.ConsoleTypeInvalid, + exception.InstanceNotReady, exception.InstanceNotFound) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @wrap_instance_fault def get_vnc_console(self, context, console_type, instance): @@ -2601,15 +2602,21 @@ class ComputeManager(manager.SchedulerDependentManager): else: raise exception.ConsoleTypeInvalid(console_type=console_type) - # Retrieve connect info from driver, and then decorate with our - # access info token - connect_info = self.driver.get_vnc_console(instance) - connect_info['token'] = token - connect_info['access_url'] = access_url + try: + # Retrieve connect info from driver, and then decorate with our + # access info token + connect_info = self.driver.get_vnc_console(instance) + connect_info['token'] = token + connect_info['access_url'] = access_url + except exception.InstanceNotFound: + if instance['vm_state'] != vm_states.BUILDING: + raise + raise exception.InstanceNotReady(instance_id=instance['uuid']) return connect_info - @rpc_common.client_exceptions(exception.ConsoleTypeInvalid) + @rpc_common.client_exceptions(exception.ConsoleTypeInvalid, + exception.InstanceNotReady, exception.InstanceNotFound) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @wrap_instance_fault def get_spice_console(self, context, console_type, instance): @@ -2629,14 +2636,21 @@ class ComputeManager(manager.SchedulerDependentManager): else: raise exception.ConsoleTypeInvalid(console_type=console_type) - # Retrieve connect info from driver, and then decorate with our - # access info token - connect_info = self.driver.get_spice_console(instance) - connect_info['token'] = token - connect_info['access_url'] = access_url + try: + # Retrieve connect info from driver, and then decorate with our + # access info token + connect_info = self.driver.get_spice_console(instance) + connect_info['token'] = token + connect_info['access_url'] = access_url + except exception.InstanceNotFound: + if instance['vm_state'] != vm_states.BUILDING: + raise + raise exception.InstanceNotReady(instance_id=instance['uuid']) return connect_info + @rpc_common.client_exceptions(exception.ConsoleTypeInvalid, + exception.InstanceNotReady, exception.InstanceNotFound) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @wrap_instance_fault def validate_console_port(self, ctxt, instance, port, console_type): -- cgit