def _acquire_method_lock(self, method, this): method_id = id(method) if method.is_static: this_id = id(method.declaring_type) else: this_id = this.object_id thread_id = helpers.get_current_thread_id() while True: event, event_owner = self._locks.get((method_id, this_id), (None, None)) if event: if event_owner == thread_id: event = None break else: event.wait() else: event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_id) break try: yield finally: if event is not None: del self._locks[(method_id, this_id)] event.send()
def _acquire_method_lock(self, method, this): method_id = id(method) if method.is_static: this_id = id(method.declaring_type) else: this_id = this.object_id thread_id = helpers.get_current_thread_id() while True: event, event_owner = self._locks.get( (method_id, this_id), (None, None)) if event: if event_owner == thread_id: event = None break else: event.wait() else: event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_id) break try: yield finally: if event is not None: del self._locks[(method_id, this_id)] event.send()
def _invoke_method_implementation(self, method, this, murano_class, context, params): body = method.body if not body: return None current_thread = eventlet.greenthread.getcurrent() if not hasattr(current_thread, '_murano_dsl_thread_marker'): thread_marker = current_thread._murano_dsl_thread_marker = \ uuid.uuid4().hex else: thread_marker = current_thread._murano_dsl_thread_marker method_id = id(body) this_id = this.object_id event, marker = self._locks.get((method_id, this_id), (None, None)) if event: if marker == thread_marker: return self._invoke_method_implementation_gt( body, this, params, murano_class, context) event.wait() event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_marker) gt = eventlet.spawn(self._invoke_method_implementation_gt, body, this, params, murano_class, context, thread_marker) result = gt.wait() del self._locks[(method_id, this_id)] event.send() return result
def _acquire_method_lock(self, func, this): method_id = id(func) if isinstance(this, dsl_types.MuranoClass): this_id = id(this) else: this_id = this.object_id thread_id = helpers.get_current_thread_id() while True: event, event_owner = self._locks.get( (method_id, this_id), (None, None)) if event: if event_owner == thread_id: event = None break else: event.wait() else: event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_id) break try: yield finally: if event is not None: del self._locks[(method_id, this_id)] event.send()
def _invoke_method_implementation(self, method, this, murano_class, context, params): body = method.body if not body: return None current_thread = eventlet.greenthread.getcurrent() if not hasattr(current_thread, "_murano_dsl_thread_marker"): thread_marker = current_thread._murano_dsl_thread_marker = uuid.uuid4().hex else: thread_marker = current_thread._murano_dsl_thread_marker method_id = id(body) this_id = this.object_id event, marker = self._locks.get((method_id, this_id), (None, None)) if event: if marker == thread_marker: return self._invoke_method_implementation_gt(body, this, params, murano_class, context) event.wait() event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_marker) gt = eventlet.spawn( self._invoke_method_implementation_gt, body, this, params, murano_class, context, thread_marker ) result = gt.wait() del self._locks[(method_id, this_id)] event.send() return result
def _invoke_method_implementation(self, method, this, context, params): body = method.body if not body: return None murano_class = method.murano_class current_thread = eventlet.greenthread.getcurrent() if not hasattr(current_thread, '_muranopl_thread_marker'): thread_marker = current_thread._muranopl_thread_marker = \ uuid.uuid4().hex else: thread_marker = current_thread._muranopl_thread_marker method_id = id(body) this_id = this.object_id while True: event, marker = self._locks.get((method_id, this_id), (None, None)) if event: if marker == thread_marker: return self._invoke_method_implementation_gt( body, this, params, murano_class, context) event.wait() else: break event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_marker) # noinspection PyProtectedMember method_info = '{0}.{1} ({2})'.format(murano_class.name, method._name, hash((method_id, this_id))) # Prepare caller information caller_ctx = helpers.get_caller_context(context) if caller_ctx: caller_info = trace.compose_stack_frame(caller_ctx) LOG.debug('{0}: Begin execution: {1} called from {2}'.format( thread_marker, method_info, trace.format_frame(caller_info))) else: LOG.debug('{0}: Begin execution: {1}'.format( thread_marker, method_info)) try: gt = eventlet.spawn(self._invoke_method_implementation_gt, body, this, params, murano_class, context, thread_marker) result = gt.wait() except Exception as e: LOG.debug("{0}: End execution: {1} with exception {2}".format( thread_marker, method_info, e)) raise else: LOG.debug("{0}: End execution: {1}".format(thread_marker, method_info)) finally: del self._locks[(method_id, this_id)] event.send() return result
def _invoke_method_implementation(self, method, this, context, params): body = method.body if not body: return None murano_class = method.murano_class current_thread = eventlet.greenthread.getcurrent() if not hasattr(current_thread, '_muranopl_thread_marker'): thread_marker = current_thread._muranopl_thread_marker = \ uuid.uuid4().hex else: thread_marker = current_thread._muranopl_thread_marker method_id = id(body) this_id = this.object_id while True: event, marker = self._locks.get((method_id, this_id), (None, None)) if event: if marker == thread_marker: return self._invoke_method_implementation_gt( body, this, params, murano_class, context) event.wait() else: break event = eventlet.event.Event() self._locks[(method_id, this_id)] = (event, thread_marker) # noinspection PyProtectedMember method_info = '{0}.{1} ({2})'.format(murano_class.name, method._name, hash((method_id, this_id))) # Prepare caller information caller_ctx = helpers.get_caller_context(context) if caller_ctx: caller_info = trace.compose_stack_frame(caller_ctx) LOG.debug( '{0}: Begin execution: {1} called from {2}'.format( thread_marker, method_info, trace.format_frame( caller_info))) else: LOG.debug( '{0}: Begin execution: {1}'.format( thread_marker, method_info)) gt = eventlet.spawn(self._invoke_method_implementation_gt, body, this, params, murano_class, context, thread_marker) result = gt.wait() del self._locks[(method_id, this_id)] LOG.debug( "{0}: End execution: {1}".format(thread_marker, method_info)) event.send() return result
def _send(self, template, wait_results, timeout): """Send a message over the MQ interface.""" msg_id = template.get('ID', uuid.uuid4().hex) if wait_results: event = eventlet.event.Event() listener = self._environment['agentListener'] listener().subscribe(msg_id, event) msg = self._prepare_message(template, msg_id) with common.create_rmq_client(self._environment) as client: client.send(message=msg, key=self._queue) if wait_results: try: with eventlet.Timeout(timeout): result = event.wait() except eventlet.Timeout: listener().unsubscribe(msg_id) raise exceptions.TimeoutException( 'The murano-agent did not respond ' 'within {0} seconds'.format(timeout)) if not result: return None if result.get('FormatVersion', '1.0.0').startswith('1.'): return self._process_v1_result(result) else: return self._process_v2_result(result) else: return None
def _send(self, template, wait_results, timeout): """Send a message over the MQ interface.""" msg_id = template.get('ID', uuid.uuid4().hex) if wait_results: event = eventlet.event.Event() listener = self._environment['agentListener'] listener().subscribe(msg_id, event) msg = self._prepare_message(template, msg_id) with common.create_rmq_client() as client: client.send(message=msg, key=self._queue) if wait_results: try: with eventlet.Timeout(timeout): result = event.wait() except eventlet.Timeout: listener().unsubscribe(msg_id) raise exceptions.TimeoutException( 'The murano-agent did not respond ' 'within {0} seconds'.format(timeout)) if not result: return None if result.get('FormatVersion', '1.0.0').startswith('1.'): return self._process_v1_result(result) else: return self._process_v2_result(result) else: return None
def _send(self, template, wait_results, timeout, _context): """Send a message over the MQ interface.""" msg_id = template.get("ID", uuid.uuid4().hex) if wait_results: event = eventlet.event.Event() listener = self._environment.agentListener listener.subscribe(msg_id, event, _context) msg = self._prepare_message(template, msg_id) with common.create_rmq_client() as client: client.send(message=msg, key=self._queue) if wait_results: try: with eventlet.Timeout(timeout): result = event.wait() except eventlet.Timeout: listener.unsubscribe(msg_id) raise exceptions.TimeoutException("The Agent does not respond" "within {0} seconds".format(timeout)) if not result: return None if result.get("FormatVersion", "1.0.0").startswith("1."): return self._process_v1_result(result) else: return self._process_v2_result(result) else: return None
def _send(self, template, wait_results): msg_id = template.get('ID', uuid.uuid4().hex) if wait_results: event = eventlet.event.Event() listener = self._environment.agentListener listener.subscribe(msg_id, event) listener.start() msg = messaging.Message() msg.body = template msg.id = msg_id with common.create_rmq_client() as client: client.declare(self._queue, enable_ha=True, ttl=86400000) client.send(message=msg, key=self._queue) if wait_results: result = event.wait() if not result: return None if result.get('FormatVersion', '1.0.0').startswith('1.'): return self._process_v1_result(result) else: return self._process_v2_result(result) else: return None
def wait_for_instance_event(self, instance, event_names, deadline=300, error_callback=None): """Plan to wait for some events, run some code, then wait. This context manager will first create plans to wait for the provided event_names, yield, and then wait for all the scheduled events to complete. Note that this uses an eventlet.timeout.Timeout to bound the operation, so callers should be prepared to catch that failure and handle that situation appropriately. If the event is not received by the specified timeout deadline, eventlet.timeout.Timeout is raised. If the event is received but did not have a 'completed' status, a NovaException is raised. If an error_callback is provided, instead of raising an exception as detailed above for the failure case, the callback will be called with the event_name and instance, and can return True to continue waiting for the rest of the events, False to stop processing, or raise an exception which will bubble up to the waiter. :param instance: The instance for which an event is expected :param event_names: A list of event names. Each element can be a string event name or tuple of strings to indicate (name, tag). :param deadline: Maximum number of seconds we should wait for all of the specified events to arrive. :param error_callback: A function to be called if an event arrives """ if error_callback is None: error_callback = self._default_error_callback events = {} for event_name in event_names: if isinstance(event_name, tuple): name, tag = event_name event_name = objects.InstanceExternalEvent.make_key( name, tag) try: events[event_name] = ( self._compute.instance_events.prepare_for_instance_event( instance, event_name)) except exception.NovaException: error_callback(event_name, instance) # NOTE(danms): Don't wait for any of the events. They # should all be canceled and fired immediately below, # but don't stick around if not. deadline = 0 yield with eventlet.timeout.Timeout(deadline): for event_name, event in events.items(): actual_event = event.wait() if actual_event.status == 'completed': continue decision = error_callback(event_name, instance) if decision is False: break
def _acquire_method_lock(self, method, this, arg_val_dict): if this is None: if not arg_val_dict: # if neither "this" nor argument values are set then no # locking is needed key = None else: # if only the argument values are passed then find the lock # list only by the method key = (None, id(method)) else: if method.is_static: # find the lock list by the type and method key = (id(method.declaring_type), id(method)) else: # find the lock list by the object and method key = (this.object_id, id(method)) thread_id = helpers.get_current_thread_id() while True: event, event_owner = None, None if key is None: # no locking needed break lock_list = self._locks.setdefault(key, []) # lock list contains a list of tuples: # first item of each tuple is a dict with the values of locking # arguments (it is used for argument values comparison), # second item is an event to wait on, # third one is the owner thread id # If this lock list is empty it means no locks on this object and # method at all. for arg_vals, l_event, l_event_owner in lock_list: if arg_vals == arg_val_dict: event = l_event event_owner = l_event_owner break if event: if event_owner == thread_id: # this means a re-entrant lock: the tuple with the same # value of the first element exists in the list, but it was # acquired by the same green thread. We may proceed with # the call in this case event = None break else: event.wait() else: # this means either the lock list was empty or didn't contain a # tuple with the first element equal to arg_val_dict. # Then let's acquire a lock, i.e. create a new tuple and place # it into the list event = eventlet.event.Event() event_owner = thread_id lock_list.append((arg_val_dict, event, event_owner)) break try: yield finally: if event is not None: lock_list.remove((arg_val_dict, event, event_owner)) if len(lock_list) == 0: del self._locks[key] event.send()