def renew_vessels(geniuser, vessel_list): """ <Purpose> Extend the expiration dates of vessels acquired by a user. <Arguments> geniuser The GeniUser whose vessels are to be renewed. vessel_list A list of vessels to be renewed. <Exceptions> InvalidRequestError If any of the vessels in the vessel_list are not currently acquired by geniuser or if the list of vessels is empty. InsufficientUserResourcesError If the user is currently over their limit of acquired resources. <Side Effects> The vessels are renewed to the maximum time vessels can be acquired for, regardless of their previous individual expiration times. <Returns> None """ assert_geniuser(geniuser) assert_list(vessel_list) for vessel in vessel_list: assert_vessel(vessel) if not vessel_list: raise InvalidRequestError("The list of vessels cannot be empty.") # Lock the user. lockserver_handle = lockserver.create_lockserver_handle() lockserver.lock_user(lockserver_handle, geniuser.username) try: # Make sure the user still exists now that we hold the lock. Also makes # sure that we see any changes made to the user before we obtained the lock. try: geniuser = maindb.get_user(geniuser.username) except DoesNotExistError: raise InternalError(traceback.format_exc()) # Ensure the user is not over their limit of acquired vessels due to # donations of theirs having gone offline. This call will raise an # InsufficientUserResourcesError if the user is currently over their # limit. vesselcount = 0 maindb.require_user_can_acquire_resources(geniuser, vesselcount) # The vessels.renew_vessels function is responsible for ensuring that the # vessels belong to this user. We let the other function do the check # because we want to hold locks on the vessels' nodes before checking. vessels.renew_vessels(lockserver_handle, geniuser, vessel_list) finally: # Unlock the user. lockserver.unlock_user(lockserver_handle, geniuser.username) lockserver.destroy_lockserver_handle(lockserver_handle)
def acquire_specific_vessels(geniuser, vessel_list): """ <Purpose> Attempt to acquire specific vessels for a user. <Arguments> geniuser The GeniUser which will be assigned the vessels. vessel_list A list of vessels to be acquired for the user. <Exceptions> InsufficientUserResourcesError The user does not have enough vessel credits to acquire the number of vessels requested. InvalidRequestError If the list of vessels is empty. <Side Effects> Zero or more of the vessels in vessel_list have been acquired by the user. <Returns> A list of the vessels acquired as a result of this function call. The length of this list may be less than the length of vessel_list if one or more of the vessels in vessel_list could not be acquired. """ assert_geniuser(geniuser) assert_list(vessel_list) for vessel in vessel_list: assert_vessel(vessel) if not vessel_list: raise InvalidRequestError("The list of vessels cannot be empty.") # Lock the user. lockserver_handle = lockserver.create_lockserver_handle() lockserver.lock_user(lockserver_handle, geniuser.username) try: # Make sure the user still exists now that we hold the lock. Also makes # sure that we see any changes made to the user before we obtained the lock. try: geniuser = maindb.get_user(geniuser.username) except DoesNotExistError: raise InternalError(traceback.format_exc()) # Ensure the user is allowed to acquire these resources. This call will # raise an InsufficientUserResourcesError if the additional vessels would # cause the user to be over their limit. maindb.require_user_can_acquire_resources(geniuser, len(vessel_list)) return vessels.acquire_specific_vessels_best_effort(lockserver_handle, geniuser, vessel_list) finally: # Unlock the user. lockserver.unlock_user(lockserver_handle, geniuser.username) lockserver.destroy_lockserver_handle(lockserver_handle)
def acquire_vessels(geniuser, vesselcount, vesseltype): """ <Purpose> Acquire unused vessels of a given type for a user. For information on how the specified vesseltype affects which vessels will be considered to satisfy the request, see the type-specific functions that are called by this function. <Arguments> geniuser The GeniUser which will be assigned the vessels. vesselcount The number of vessels to acquire (a positive integer). vesseltype The type of vessels to acquire. One of either 'lan', 'wan', 'nat', or 'rand'. <Exceptions> UnableToAcquireResourcesError If not able to acquire the requested vessels (in this case, no vessels will be acquired). InsufficientUserResourcesError The user does not have enough vessel credits to acquire the number of vessels requested. <Side Effects> A total of 'vesselcount' previously-unassigned vessels of the specified vesseltype have been acquired by the user. <Returns> A list of the vessels as a result of this function call. """ assert_geniuser(geniuser) assert_positive_int(vesselcount) assert_str(vesseltype) # Lock the user. lockserver_handle = lockserver.create_lockserver_handle() lockserver.lock_user(lockserver_handle, geniuser.username) try: # Make sure the user still exists now that we hold the lock. Also makes # sure that we see any changes made to the user before we obtained the lock. try: geniuser = maindb.get_user(geniuser.username) except DoesNotExistError: raise InternalError(traceback.format_exc()) # Ensure the user is allowed to acquire these resources. This call will # raise an InsufficientUserResourcesError if the additional vessels would # cause the user to be over their limit. maindb.require_user_can_acquire_resources(geniuser, vesselcount) if vesseltype == 'wan': acquired_list = vessels.acquire_wan_vessels(lockserver_handle, geniuser, vesselcount) elif vesseltype == 'lan': acquired_list = vessels.acquire_lan_vessels(lockserver_handle, geniuser, vesselcount) elif vesseltype == 'nat': acquired_list = vessels.acquire_nat_vessels(lockserver_handle, geniuser, vesselcount) elif vesseltype == 'rand': acquired_list = vessels.acquire_rand_vessels(lockserver_handle, geniuser, vesselcount) else: raise ProgrammerError("Vessel type '%s' is not a valid type" % vesseltype) return acquired_list finally: # Unlock the user. lockserver.unlock_user(lockserver_handle, geniuser.username) lockserver.destroy_lockserver_handle(lockserver_handle)