def _processMessages(self, node, messages): # Push the messages into the database, recording them for this node. # This should be called in a non-reactor thread with a pre-existing # connection (e.g. via deferToDatabase). if in_transaction(): raise TransactionManagementError( "_processMessages must be called from " "outside of a transaction.") else: # Here we're in a database thread, with a database connection. # We only save the last_ping off the last message in the # list of messages. This removes the number of database saves # required. for idx, message in enumerate(messages): try: self._processMessage(node, message) except: log.err( None, "Failed to process message " "for node: %s" % node.hostname) if idx == len(messages) - 1: try: self._updateLastPing(node, message) except: log.err( None, "Failed to update last ping " "for node: %s" % node.hostname)
def populate_tags(tag): """Evaluate `tag` for all nodes. This returns a `Deferred` that will fire when all tags have been evaluated. The return value is intended FOR TESTING ONLY because: - You must not use the `Deferred` in the calling thread; it must only be manipulated in the reactor thread. Pretending it's not there is safer than chaining code onto it because it's easy to get wrong. - The call may not finish for 10 minutes or more. It is therefore not a good thing to be waiting for in a web request. """ # This function cannot be called inside a transaction. The function manages # its own transaction. if in_transaction(): raise TransactionManagementError( '`populate_tags` cannot be called inside an existing transaction.') logger.debug('Evaluating the "%s" tag for all nodes.', tag.name) clients = getAllClients() if len(clients) == 0: # We have no clients so we need to do the work locally. @transactional def _populate_tag(): return populate_tag_for_multiple_nodes(tag, Node.objects.all()) return _populate_tag() else: # Split the work between the connected rack controllers. @transactional def _generate_work(): node_ids = Node.objects.all().values_list("system_id", flat=True) node_ids = [{"system_id": node_id} for node_id in node_ids] chunked_node_ids = list(chunk_list(node_ids, len(clients))) connected_racks = [] for idx, client in enumerate(clients): rack = RackController.objects.get(system_id=client.ident) token = _get_or_create_auth_token(rack.owner) creds = convert_tuple_to_string(get_creds_tuple(token)) if len(chunked_node_ids) > idx: connected_racks.append({ "system_id": rack.system_id, "hostname": rack.hostname, "client": client, "tag_name": tag.name, "tag_definition": tag.definition, "tag_nsmap": [ {"prefix": prefix, "uri": uri} for prefix, uri in tag_nsmap.items() ], "credentials": creds, "nodes": list(chunked_node_ids[idx]), }) return connected_racks return _do_populate_tags(_generate_work())
def _processMessageNow(self, authorization, message): # This should be called in a non-reactor thread with a pre-existing # connection (e.g. via deferToDatabase). if in_transaction(): raise TransactionManagementError( "_processMessageNow must be called from " "outside of a transaction.") else: try: node = transactional( NodeKey.objects.get_node_for_key)(authorization) except NodeKey.DoesNotExist: # The node that should get this message has already had its # owner cleared or changed and this message cannot be saved. return None else: self._processMessage(node, message)
def _processMessages(self, node, messages): # Push the messages into the database, recording them for this node. # This should be called in a non-reactor thread with a pre-existing # connection (e.g. via deferToDatabase). if in_transaction(): raise TransactionManagementError( "_processMessages must be called from " "outside of a transaction.") else: # Here we're in a database thread, with a database connection. for idx, message in enumerate(messages): try: exists = self._processMessage(node, message) if not exists: # Node has been deleted no reason to continue saving # the events for this node. break except: log.err( None, "Failed to process message " "for node: %s" % node.hostname)