def _cleanup_single_vessel(vessel): """ This function is passed by cleanup_vessels() as the function argument to run_parallelized(). """ # This does seem wasteful of lockserver communication to require four # round-trips with the lockserver (get handle, lock, unlock, release handle), # but if we really want to fix that then I think the best thing to do would # be to allow obtaining a lockhandle and releasing a lockhandle to be done # in the same calls as lock acquisition and release. node_id = maindb.get_node_identifier_from_vessel(vessel) lockserver_handle = lockserver.create_lockserver_handle() # Lock the node that the vessels is on. lockserver.lock_node(lockserver_handle, node_id) try: # Get a new vessel object from the db in case it was modified in the db # before the lock was obtained. vessel = maindb.get_vessel(node_id, vessel.name) # Now that we have a lock on the node that this vessel is on, find out # if we should still clean up this vessel (e.g. maybe a node state # transition script moved the node to a new state and this vessel was # removed). needscleanup, reasonwhynot = maindb.does_vessel_need_cleanup(vessel) if not needscleanup: log.info("[_cleanup_single_vessel] Vessel " + str(vessel) + " no longer needs cleanup: " + reasonwhynot) return nodeid = maindb.get_node_identifier_from_vessel(vessel) nodehandle = _get_node_handle_from_nodeid(nodeid) try: log.info("[_cleanup_single_vessel] About to ChangeUsers on vessel " + str(vessel)) nodemanager.change_users(nodehandle, vessel.name, ['']) log.info("[_cleanup_single_vessel] About to ResetVessel on vessel " + str(vessel)) nodemanager.reset_vessel(nodehandle, vessel.name) except NodemanagerCommunicationError: # We don't pass this exception up. Maybe the node is offline now. At some # point, it will be marked in the database as offline (should we be doing # that here?). At that time, the dirty vessels on that node will not be # in the cleanup list anymore. log.info("[_cleanup_single_vessel] Failed to cleanup vessel " + str(vessel) + ". " + traceback.format_exc()) return # We only mark it as clean if no exception was raised when trying to # perform the above nodemanager operations. maindb.mark_vessel_as_clean(vessel) log.info("[_cleanup_single_vessel] Successfully cleaned up vessel " + str(vessel)) finally: # Unlock the node. lockserver.unlock_node(lockserver_handle, node_id) lockserver.destroy_lockserver_handle(lockserver_handle)
def SetVesselUsers(*args): """ This is a public function of the XMLRPC server. See the module comments at the top of the file for a description of how it is used. """ _assert_number_of_arguments('SetVesselUsers', args, 3) (nodeid, vesselname, userkeylist) = args assert_str(nodeid) assert_str(vesselname) assert_list(userkeylist) for userkey in userkeylist: assert_str(userkey) # Note: The nodemanager checks whether each key is a valid key and will # raise an exception if it is not. # Raises a DoesNotExistError if there is no node with this nodeid. nodehandle = _get_node_handle_from_nodeid(nodeid) # Raises NodemanagerCommunicationError if it fails. nodemanager.change_users(nodehandle, vesselname, userkeylist)
def _sync_user_keys_of_single_vessel(vessel): """ This function is passed by sync_user_keys_of_vessels() as the function argument to run_parallelized(). """ # This does seem wasteful of lockserver communication to require four # round-trips with the lockserver (get handle, lock, unlock, release handle), # but if we really want to fix that then I think the best thing to do would # be to allow obtaining a lockhandle and releasing a lockhandle to be done # in the same calls as lock acquisition and release. node_id = maindb.get_node_identifier_from_vessel(vessel) lockserver_handle = lockserver.create_lockserver_handle() # Lock the node that the vessels is on. lockserver.lock_node(lockserver_handle, node_id) try: # Get a new vessel object from the db in case it was modified in the db # before the lock was obtained. vessel = maindb.get_vessel(node_id, vessel.name) # Now that we have a lock on the node that this vessel is on, find out # if we should still sync user keys on this vessel (e.g. maybe a node state # transition script moved the node to a new state and this vessel was # removed). needssync, reasonwhynot = maindb.does_vessel_need_user_key_sync(vessel) if not needssync: log.info("[_sync_user_keys_of_single_vessel] Vessel " + str(vessel) + " no longer needs user key sync: " + reasonwhynot) return nodeid = maindb.get_node_identifier_from_vessel(vessel) nodehandle = _get_node_handle_from_nodeid(nodeid) # The list returned from get_users_with_access_to_vessel includes the key of # the user who has acquired the vessel along with any other users they have # given access to. user_list = maindb.get_users_with_access_to_vessel(vessel) key_list = [] for user in user_list: key_list.append(user.user_pubkey) if len(key_list) == 0: raise InternalError("InternalError: Empty user key list for vessel " + str(vessel)) try: log.info("[_sync_user_keys_of_single_vessel] About to ChangeUsers on vessel " + str(vessel)) nodemanager.change_users(nodehandle, vessel.name, key_list) except NodemanagerCommunicationError: # We don't pass this exception up. Maybe the node is offline now. At some # point, it will be marked in the database as offline and won't show up in # our list of vessels to sync user keys of anymore. log.info("[_sync_user_keys_of_single_vessel] Failed to sync user keys of vessel " + str(vessel) + ". " + traceback.format_exc()) return # We only mark it as sync'd if no exception was raised when trying to perform # the above nodemanager operations. maindb.mark_vessel_as_not_needing_user_key_sync(vessel) log.info("[_sync_user_keys_of_single_vessel] Successfully sync'd user keys of vessel " + str(vessel)) finally: # Unlock the node. lockserver.unlock_node(lockserver_handle, node_id) lockserver.destroy_lockserver_handle(lockserver_handle)
def _sync_user_keys_of_single_vessel(vessel): """ This function is passed by sync_user_keys_of_vessels() as the function argument to run_parallelized(). """ # This does seem wasteful of lockserver communication to require four # round-trips with the lockserver (get handle, lock, unlock, release handle), # but if we really want to fix that then I think the best thing to do would # be to allow obtaining a lockhandle and releasing a lockhandle to be done # in the same calls as lock acquisition and release. node_id = maindb.get_node_identifier_from_vessel(vessel) lockserver_handle = lockserver.create_lockserver_handle() # Lock the node that the vessels is on. lockserver.lock_node(lockserver_handle, node_id) try: # Get a new vessel object from the db in case it was modified in the db # before the lock was obtained. vessel = maindb.get_vessel(node_id, vessel.name) # Now that we have a lock on the node that this vessel is on, find out # if we should still sync user keys on this vessel (e.g. maybe a node state # transition script moved the node to a new state and this vessel was # removed). needssync, reasonwhynot = maindb.does_vessel_need_user_key_sync(vessel) if not needssync: log.info("[_sync_user_keys_of_single_vessel] Vessel " + str(vessel) + " no longer needs user key sync: " + reasonwhynot) return nodeid = maindb.get_node_identifier_from_vessel(vessel) nodehandle = _get_node_handle_from_nodeid(nodeid) # The list returned from get_users_with_access_to_vessel includes the key of # the user who has acquired the vessel along with any other users they have # given access to. user_list = maindb.get_users_with_access_to_vessel(vessel) key_list = [] for user in user_list: key_list.append(user.user_pubkey) if len(key_list) == 0: raise InternalError( "InternalError: Empty user key list for vessel " + str(vessel)) try: log.info( "[_sync_user_keys_of_single_vessel] About to ChangeUsers on vessel " + str(vessel)) nodemanager.change_users(nodehandle, vessel.name, key_list) except NodemanagerCommunicationError: # We don't pass this exception up. Maybe the node is offline now. At some # point, it will be marked in the database as offline and won't show up in # our list of vessels to sync user keys of anymore. log.info( "[_sync_user_keys_of_single_vessel] Failed to sync user keys of vessel " + str(vessel) + ". " + traceback.format_exc()) return # We only mark it as sync'd if no exception was raised when trying to perform # the above nodemanager operations. maindb.mark_vessel_as_not_needing_user_key_sync(vessel) log.info( "[_sync_user_keys_of_single_vessel] Successfully sync'd user keys of vessel " + str(vessel)) finally: # Unlock the node. lockserver.unlock_node(lockserver_handle, node_id) lockserver.destroy_lockserver_handle(lockserver_handle)
def _cleanup_single_vessel(vessel): """ This function is passed by cleanup_vessels() as the function argument to run_parallelized(). """ # This does seem wasteful of lockserver communication to require four # round-trips with the lockserver (get handle, lock, unlock, release handle), # but if we really want to fix that then I think the best thing to do would # be to allow obtaining a lockhandle and releasing a lockhandle to be done # in the same calls as lock acquisition and release. node_id = maindb.get_node_identifier_from_vessel(vessel) lockserver_handle = lockserver.create_lockserver_handle() # Lock the node that the vessels is on. lockserver.lock_node(lockserver_handle, node_id) try: # Get a new vessel object from the db in case it was modified in the db # before the lock was obtained. vessel = maindb.get_vessel(node_id, vessel.name) # Now that we have a lock on the node that this vessel is on, find out # if we should still clean up this vessel (e.g. maybe a node state # transition script moved the node to a new state and this vessel was # removed). needscleanup, reasonwhynot = maindb.does_vessel_need_cleanup(vessel) if not needscleanup: log.info("[_cleanup_single_vessel] Vessel " + str(vessel) + " no longer needs cleanup: " + reasonwhynot) return nodeid = maindb.get_node_identifier_from_vessel(vessel) nodehandle = _get_node_handle_from_nodeid(nodeid) try: log.info( "[_cleanup_single_vessel] About to ChangeUsers on vessel " + str(vessel)) nodemanager.change_users(nodehandle, vessel.name, ['']) log.info( "[_cleanup_single_vessel] About to ResetVessel on vessel " + str(vessel)) nodemanager.reset_vessel(nodehandle, vessel.name) except NodemanagerCommunicationError: # We don't pass this exception up. Maybe the node is offline now. At some # point, it will be marked in the database as offline (should we be doing # that here?). At that time, the dirty vessels on that node will not be # in the cleanup list anymore. log.info("[_cleanup_single_vessel] Failed to cleanup vessel " + str(vessel) + ". " + traceback.format_exc()) return # We only mark it as clean if no exception was raised when trying to # perform the above nodemanager operations. maindb.mark_vessel_as_clean(vessel) log.info("[_cleanup_single_vessel] Successfully cleaned up vessel " + str(vessel)) finally: # Unlock the node. lockserver.unlock_node(lockserver_handle, node_id) lockserver.destroy_lockserver_handle(lockserver_handle)