def execute(self, process_name, host_name): def _wait_for_disable(): service_disabled = self.novaclient.is_service_down( self.context, host_name, process_name) if service_disabled: raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_disable) try: msg = "Confirming compute service is disabled on host: '%s'" % ( host_name) self.update_details(msg) # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_service_update, periodic_call.wait) msg = "Confirmed compute service is disabled on host: '%s'" % ( host_name) self.update_details(msg, 1.0) except etimeout.Timeout: msg = "Failed to disable service %(process_name)s" % { 'process_name': process_name } self.update_details(msg, 1.0) raise exception.ProcessRecoveryFailureException( message=msg) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop()
def _stop_after_evacuation(self, context, instance): def _wait_for_stop_confirmation(): old_vm_state, new_vm_state, _ = ( self._get_state_and_host_of_instance(context, instance)) if new_vm_state == 'stopped': raise loopingcall.LoopingCallDone() periodic_call_stopped = loopingcall.FixedIntervalLoopingCall( _wait_for_stop_confirmation) try: self.novaclient.stop_server(context, instance.id) # confirm instance is stopped after recovery periodic_call_stopped.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_power_off, periodic_call_stopped.wait) except etimeout.Timeout: with excutils.save_and_reraise_exception(): msg = ("Instance '%s' is successfully evacuated but " "failed to stop.") LOG.warning(msg, instance.id) finally: periodic_call_stopped.stop()
def _wait_for_power_off(self, instance_name, time_limit): """Waiting for a VM to be in a disabled state. :return: True if the instance is shutdown within time_limit, False otherwise. """ desired_vm_states = [constants.HYPERV_VM_STATE_DISABLED] def _check_vm_status(instance_name): if self._get_vm_state(instance_name) in desired_vm_states: raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall(_check_vm_status, instance_name) try: # add a timeout to the periodic call. periodic_call.start(interval=SHUTDOWN_TIME_INCREMENT) etimeout.with_timeout(time_limit, periodic_call.wait) except etimeout.Timeout: # VM did not shutdown in the expected time_limit. return False finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop() return True
def execute(self, instance_uuid): def _wait_for_active(): new_instance = self.novaclient.get_server(self.context, instance_uuid) vm_state = getattr(new_instance, 'OS-EXT-STS:vm_state') if vm_state == 'active': raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_active) try: msg = "Confirming instance '%s' vm_state is ACTIVE" % instance_uuid self.update_details(msg) # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_power_on, periodic_call.wait) msg = "Confirmed instance '%s' vm_state is ACTIVE" % instance_uuid self.update_details(msg, 1.0) except etimeout.Timeout: msg = "Failed to start instance %(instance)s" % { 'instance': instance_uuid } self.update_details(msg, 1.0) raise exception.InstanceRecoveryFailureException( message=msg) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop()
def _wait_for_power_off(self, instance_name, time_limit): """Waiting for a VM to be in a disabled state. :return: True if the instance is shutdown within time_limit, False otherwise. """ desired_vm_states = [constants.HYPERV_VM_STATE_DISABLED] def _check_vm_status(instance_name): if self._get_vm_state(instance_name) in desired_vm_states: raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _check_vm_status, instance_name) try: # add a timeout to the periodic call. periodic_call.start(interval=SHUTDOWN_TIME_INCREMENT) etimeout.with_timeout(time_limit, periodic_call.wait) except etimeout.Timeout: # VM did not shutdown in the expected time_limit. return False finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop() return True
def wait_for_power_state(instance, power_state, time_limit): """Waiting for a virtual machine to be in required power state. :param instance: nova.objects.instance.Instance :param power_state: nova.compute.power_state :param time_limit: (int) time limit for this task :return: True if the instance is in required power state within time_limit, False otherwise. """ def _check_power_state(instance): current_state = get_power_state(instance) LOG.debug("Wait for soft shutdown: (%s, %s)", current_state, power_state) if current_state == power_state: raise loopingcall.LoopingCallDone() response = True periodic_call = loopingcall.FixedIntervalLoopingCall(_check_power_state, instance) try: # add a timeout to the periodic call. periodic_call.start(interval=constants.SHUTDOWN_RETRY_INTERVAL) etimeout.with_timeout(time_limit, periodic_call.wait) except etimeout.Timeout: # Virtual machine did not shutdown in the expected time_limit. response = False finally: # Stop the periodic call, in case of exceptions or Timeout. periodic_call.stop() return response
def test_with_timeout(self): self.assertRaises(timeout.Timeout, timeout.with_timeout, DELAY, greenthread.sleep, DELAY*10) X = object() r = timeout.with_timeout(DELAY, greenthread.sleep, DELAY*10, timeout_value=X) self.assert_(r is X, (r, X)) r = timeout.with_timeout(DELAY*10, greenthread.sleep, DELAY, timeout_value=X) self.assert_(r is None, r)
def test_with_timeout(self): self.assertRaises(timeout.Timeout, timeout.with_timeout, DELAY, greenthread.sleep, DELAY*10) X = object() r = timeout.with_timeout(DELAY, greenthread.sleep, DELAY*10, timeout_value=X) assert r is X, (r, X) r = timeout.with_timeout(DELAY*10, greenthread.sleep, DELAY, timeout_value=X) assert r is None, r
def execute(self, context, instance_uuid): """Stop the instance for recovery.""" instance = self.novaclient.get_server(context, instance_uuid) # If an instance is not HA_Enabled and "process_all_instances" config # option is also disabled, then there is no need to take any recovery # action. if not CONF.instance_failure.process_all_instances and not ( strutils.bool_from_string( instance.metadata.get('HA_Enabled', False))): LOG.info( "Skipping recovery for instance: %s as it is " "not Ha_Enabled.", instance_uuid) raise exception.SkipInstanceRecoveryException() vm_state = getattr(instance, 'OS-EXT-STS:vm_state') if vm_state in ['paused', 'rescued']: msg = _("Recovery of instance '%(instance_uuid)s' is ignored as" " it is in '%(vm_state)s' state.") % { 'instance_uuid': instance_uuid, 'vm_state': vm_state } LOG.warning(msg) raise exception.IgnoreInstanceRecoveryException(msg) if vm_state != 'stopped': if vm_state == 'resized': self.novaclient.reset_instance_state(context, instance.id, 'active') self.novaclient.stop_server(context, instance.id) def _wait_for_power_off(): new_instance = self.novaclient.get_server(context, instance_uuid) vm_state = getattr(new_instance, 'OS-EXT-STS:vm_state') if vm_state == 'stopped': raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_power_off) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_power_off, periodic_call.wait) except etimeout.Timeout: msg = _("Failed to stop instance %(instance)s") % { 'instance': instance.id } raise exception.InstanceRecoveryFailureException(message=msg) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop()
def execute(self, context, instance_uuid): """Stop the instance for recovery.""" instance = self.novaclient.get_server(context, instance_uuid) # If an instance is not HA_Enabled and "process_all_instances" config # option is also disabled, then there is no need to take any recovery # action. if not CONF.instance_failure.process_all_instances and not ( strutils.bool_from_string( instance.metadata.get('HA_Enabled', False))): LOG.info("Skipping recovery for instance: %s as it is " "not Ha_Enabled.", instance_uuid) raise exception.SkipInstanceRecoveryException() vm_state = getattr(instance, 'OS-EXT-STS:vm_state') if vm_state in ['paused', 'rescued']: msg = _("Recovery of instance '%(instance_uuid)s' is ignored as" " it is in '%(vm_state)s' state.") % { 'instance_uuid': instance_uuid, 'vm_state': vm_state} LOG.warning(msg) raise exception.IgnoreInstanceRecoveryException(msg) if vm_state != 'stopped': if vm_state == 'resized': self.novaclient.reset_instance_state( context, instance.id, 'active') self.novaclient.stop_server(context, instance.id) def _wait_for_power_off(): new_instance = self.novaclient.get_server(context, instance_uuid) vm_state = getattr(new_instance, 'OS-EXT-STS:vm_state') if vm_state == 'stopped': raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_power_off) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_power_off, periodic_call.wait) except etimeout.Timeout: msg = _("Failed to stop instance %(instance)s") % { 'instance': instance.id } raise exception.InstanceRecoveryFailureException(message=msg) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop()
def send_request(timeout): try: start = time.clock() server = httplib.HTTPConnection(server_ip.strip()) with_timeout(timeout, server.request, 'GET', '/') delta = time.clock() - start response = server.getresponse() assert response.status == 200 assert response.read() == 'Pong!' log(str(delta)) except Timeout: log('-') except AssertionError: log('!')
def _wait_for_evacuation(): periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation_confirmation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_evacuation, periodic_call.wait) except etimeout.Timeout: # Instance is not evacuated in the expected time_limit. failed_evacuation_instances.append(instance.id) else: # stop the periodic call, in case of exceptions or # Timeout. periodic_call.stop()
def put(self, key, value): echo('Put {0}: {1}'.format(key, value)) tid = self.unique_id() other_services = map(lambda x: self.__dict__['s' + str(x)], range(SERVICES - 1)) replies = [] for service in other_services: reply = service.prepare. async (tid, key, value) replies.append(reply) get_all_results = lambda replies: map(lambda x: x.result(), replies) rvs = with_timeout(TIMEOUT, get_all_results, replies, timeout_value=None) if None in rvs: for service in other_services: rv = service.abort(tid) assert rv == True return False for service in other_services: rv = service.commit(tid) assert rv == True self.storage[key] = value return True
def put(self, key, value): echo('put [{0}: {1}]'.format(key, value)) tid = self.unique_id() other_services = map(lambda x: self.__dict__['s' + str(x)], range(SERVICES - 1)) replies = [] for service in other_services: reply = service.prepare.async(tid, key, value) assert reply != None replies.append(reply) get_all_results = lambda replies: map(lambda x: x.result(), replies) # t1 = time.time() rvs = with_timeout(TIMEOUT, get_all_results, replies, timeout_value=None) # t2 = time.time() # echo('! ' + str(t2 - t1)) if rvs == None: echo('Timeout!') for service in other_services: rv = service.abort(tid) assert rv == True return False for service in other_services: rv = service.commit(tid) assert rv == True self.storage[key] = value return True
def _wait_for_evacuation(): periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation_confirmation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_evacuation, periodic_call.wait) except etimeout.Timeout: # Instance is not evacuated in the expected time_limit. failed_evacuation_instances.append(instance.id) else: # stop the periodic call, in case of exceptions or # Timeout. periodic_call.stop()
def result(self, timeout=None): get = self._greenthread.wait if timeout is not None: get = with_timeout(timeout, get) try: return get() except Timeout as e: raise TimeoutError(e)
def _wait_for_evacuation(): periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation_confirmation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_evacuation, periodic_call.wait) except etimeout.Timeout: with excutils.save_and_reraise_exception(): msg = ("Timeout for instance '%(uuid)s' evacuation." % {'uuid': instance.id}) LOG.warning(msg) finally: # stop the periodic call, in case of exceptions or # Timeout. periodic_call.stop()
def wait(self, timeout=None): pool = self._pool if pool is None: return wait = pool.waitall if timeout is not None: wait = with_timeout(timeout, wait) try: wait() except Timeout as e: raise TimeoutError(e)
def execute(self, context, process_name, host_name): def _wait_for_disable(): service_disabled = self.novaclient.is_service_down( context, host_name, process_name) if service_disabled: raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall(_wait_for_disable) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_service_update, periodic_call.wait) except etimeout.Timeout: msg = _("Failed to disable service %(process_name)s") % { 'process_name': process_name } raise exception.ProcessRecoveryFailureException(message=msg) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop()
def execute(self, context, instance_list, host_name): failed_evacuation_instances = [] for instance in instance_list: def _wait_for_evacuation(): new_instance = self.novaclient.get_server(context, instance.id) instance_host = getattr(new_instance, "OS-EXT-SRV-ATTR:hypervisor_hostname") old_vm_state = getattr(instance, "OS-EXT-STS:vm_state") new_vm_state = getattr(new_instance, "OS-EXT-STS:vm_state") if instance_host != host_name: if ((old_vm_state == 'error' and new_vm_state == 'active') or old_vm_state == new_vm_state): raise loopingcall.LoopingCallDone() periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout(CONF.wait_period_after_evacuation, periodic_call.wait) except etimeout.Timeout: # Instance is not evacuated in the expected time_limit. failed_evacuation_instances.append(instance.id) finally: # stop the periodic call, in case of exceptions or Timeout. periodic_call.stop() if failed_evacuation_instances: msg = _("Failed to evacuate instances %(instances)s from " "host %(host_name)s.") % { 'instances': failed_evacuation_instances, 'host_name': host_name } raise exception.HostRecoveryFailureException(message=msg)
def _evacuate_and_confirm(self, context, instance, host_name, failed_evacuation_instances, reserved_host=None): # Before locking the instance check whether it is already locked # by user, if yes don't lock the instance instance_already_locked = self.novaclient.get_server( context, instance.id).locked if not instance_already_locked: # lock the instance so that until evacuation and confirmation # is not complete, user won't be able to perform any actions # on the instance. self.novaclient.lock_server(context, instance.id) def _wait_for_evacuation_confirmation(): old_vm_state, new_vm_state, instance_host = ( self._get_state_and_host_of_instance(context, instance)) if instance_host != host_name: if ((old_vm_state == 'error' and new_vm_state == 'active') or old_vm_state == new_vm_state): raise loopingcall.LoopingCallDone() try: vm_state = getattr(instance, "OS-EXT-STS:vm_state") # Nova evacuates an instance only when vm_state is in active, # stopped or error state. If an instance is in other than active, # error and stopped vm_state, masakari resets the instance state # to *error* so that the instance can be evacuated. stop_instance = True if vm_state not in ['active', 'error', 'stopped']: self.novaclient.reset_instance_state(context, instance.id) instance = self.novaclient.get_server(context, instance.id) power_state = getattr(instance, "OS-EXT-STS:power_state") if vm_state == 'resized' and power_state != SHUTDOWN: stop_instance = False vm_state = getattr(instance, "OS-EXT-STS:vm_state") # evacuate the instance self.novaclient.evacuate_instance( context, instance.id, target=reserved_host.name if reserved_host else None) periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation_confirmation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_evacuation, periodic_call.wait) if vm_state not in ['active', 'stopped']: if stop_instance: self._stop_after_evacuation(context, instance) # If the instance was in 'error' state before failure # it should be set to 'error' after recovery. if vm_state == 'error': self.novaclient.reset_instance_state( context, instance.id) except etimeout.Timeout: # Instance is not evacuated in the expected time_limit. failed_evacuation_instances.append(instance.id) finally: # stop the periodic call, in case of exceptions or # Timeout. periodic_call.stop() except Exception: # Exception is raised while resetting instance state or # evacuating the instance itself. failed_evacuation_instances.append(instance.id) finally: if not instance_already_locked: # Unlock the server after evacuation and confirmation self.novaclient.unlock_server(context, instance.id)
def longer_timeout(): # this should not catch the outer timeout's exception return timeout.with_timeout(DELAY * 10, greenthread.sleep, DELAY * 20, timeout_value='b')
def _evacuate_and_confirm(self, context, instance, host_name, failed_evacuation_instances, reserved_host=None): # Before locking the instance check whether it is already locked # by user, if yes don't lock the instance instance_already_locked = self.novaclient.get_server( context, instance.id).locked if not instance_already_locked: # lock the instance so that until evacuation and confirmation # is not complete, user won't be able to perform any actions # on the instance. self.novaclient.lock_server(context, instance.id) def _wait_for_evacuation_confirmation(): old_vm_state, new_vm_state, instance_host = ( self._get_state_and_host_of_instance(context, instance)) if instance_host != host_name: if ((old_vm_state == 'error' and new_vm_state == 'active') or old_vm_state == new_vm_state): raise loopingcall.LoopingCallDone() try: vm_state = getattr(instance, "OS-EXT-STS:vm_state") task_state = getattr(instance, "OS-EXT-STS:task_state") # Nova evacuates an instance only when vm_state is in active, # stopped or error state. If an instance is in other than active, # error and stopped vm_state, masakari resets the instance state # to *error* so that the instance can be evacuated. stop_instance = True if vm_state not in ['active', 'error', 'stopped']: self.novaclient.reset_instance_state(context, instance.id) instance = self.novaclient.get_server(context, instance.id) power_state = getattr(instance, "OS-EXT-STS:power_state") if vm_state == 'resized' and power_state != SHUTDOWN: stop_instance = False vm_state = getattr(instance, "OS-EXT-STS:vm_state") elif task_state is not None: # Nova fails evacuation when the instance's task_state is not # none. In this case, masakari resets the instance's vm_state # to 'error' and task_state to none. self.novaclient.reset_instance_state(context, instance.id) instance = self.novaclient.get_server(context, instance.id) if vm_state == 'active': stop_instance = False # evacuate the instance self.novaclient.evacuate_instance( context, instance.id, target=reserved_host.name if reserved_host else None) periodic_call = loopingcall.FixedIntervalLoopingCall( _wait_for_evacuation_confirmation) try: # add a timeout to the periodic call. periodic_call.start(interval=CONF.verify_interval) etimeout.with_timeout( CONF.wait_period_after_evacuation, periodic_call.wait) if vm_state != 'active': if stop_instance: self._stop_after_evacuation(context, instance) # If the instance was in 'error' state before failure # it should be set to 'error' after recovery. if vm_state == 'error': self.novaclient.reset_instance_state( context, instance.id) except etimeout.Timeout: # Instance is not evacuated in the expected time_limit. failed_evacuation_instances.append(instance.id) finally: # stop the periodic call, in case of exceptions or # Timeout. periodic_call.stop() except Exception: # Exception is raised while resetting instance state or # evacuating the instance itself. failed_evacuation_instances.append(instance.id) finally: if not instance_already_locked: # Unlock the server after evacuation and confirmation self.novaclient.unlock_server(context, instance.id)