def _check_available_vessels(self, data, remoteip): ''' Connects to the clearinghouse and returns a response_dict containing the following keys: 'status': 'ok' on success /'error' on failure 'max_hosts': The remaining number of hosts that the user can acquire. On failure, this is '?'. 'default_port': The user's assigned userport. 'error': A description of the error that occurred. This only exists if an error happened. ''' response_dict = {} try: client = selexorhelper.connect_to_clearinghouse(data) accinfo = client.get_account_info() acquired_resources = client.get_resource_info() response_dict['status'] = 'ok' response_dict['max_hosts'] = accinfo['max_vessels'] - len(acquired_resources) response_dict['default_port'] = accinfo['user_port'] except seattleclearinghouse_xmlrpc.AuthenticationError, e: response_dict['status'] = 'error' response_dict['error'] = str(e) response_dict['max_hosts'] = "?"
def handle_request(self, authinfo, request, remoteip): ''' <Purpose> Handles a host request for the specified user. <Arguments> userdata: A dictionary representing the user's authentication information. It should contain the following: 'username': The user's username. 'api_key': The user's API key. 'clearinghouse_uri': The target Clearinghouse to connect to. request: A string representing a user request. This string must not contain any spaces (except for a parameter value) nor newlines. Groups are separated with semicolons. Each group must have a group ID, number of vessels, and optionally rules, all colon separated. The group ID should be an integer. Rules are also colon separated. Rules should have a rule type, followed by their list of parameters, comma separated. Parameters are in the format of parameter_name~parameter_value. Each parameter may only have one value. Example (split across multiple lines for readability): 0:3:location_specific,city~?,country~USA:location_different,num_locations~4,location_type~city; 1:2:latency_average,min_latency~40ms,max_latency~200ms; remoteip: The IP address where this request originated from. <Side Effects> Attempts to obtain vessels described in the request_data. This is not guaranteed, depending on the ddata collected in the selexordatabase. <Exceptions> None <Returns> Returns the status of the request, as a string. 'timeout': The request did not finish in the allocated time. 'complete': Selexor successfully finished the request. ''' if not self._accepting_requests: return {'error': "Server is not accepting requests."} # Get ready to handle the request username = authinfo.keys()[0] identity = (username, remoteip) request_datum[identity] = {'status': 'processing'} logger.info(str(identity) + ": Obtained request: " + str(request)) # Make sure the request is valid request_data = self._validate_request(identity, request) request_datum[identity] = request_data logger.info(str(identity) + ": Generated Request data: " + str(request_data)) if request_data['status'] == 'accepted': try: client = selexorhelper.connect_to_clearinghouse(authinfo) except selexorexceptions.SelexorException, e: request_data['status'] = 'error' request_data['error'] = str(e) raise except:
def release_vessels(self, authdata, vessels_to_release, remoteip): ''' <Purpose> Returns the # of vessels released <Arguments> authdata: An authdict. See module documentation for more information. vessels: A list of dictionaries containing vessel information of the vessels to release. These dictionaries should either contain the vessel handle, or node_ip:node_port:vesselname. remoteip: The remote IP address of the client. This is used for client identification. <Exceptions> None <Side Effects> None <Return> A dictionary containing the status of each group. 'group_id': 'group_status' ''' try: username = authdata.keys()[0] identity = (username, remoteip) logger.info(str(identity) + "> Release: " + str(vessels_to_release)) # There's nothing to do if there aren't any vessels to release if not vessels_to_release: return 0 handles_of_vessels_to_release = [] for vesseldict in vessels_to_release: if 'node_handle' in vesseldict: handles_of_vessels_to_release.append(vesseldict['node_handle']) else: # Do we have this information in the database? db, cursor = selexorhelper.connect_to_db() # If it is found, the lookup returns a 1L. node_in_db = 1L == cursor.execute("SELECT node_key FROM nodes WHERE ip_addr='"+vesseldict['node_ip']+"' AND node_port="+str(vesseldict['node_port'])) if node_in_db: [node_key] = cursor.fetchone() logger.debug('\n'.join([ str(identity), "Found node in database: "+vesseldict['node_ip']+':'+str(int(vesseldict['node_port']))+':'+vesseldict['vesselname']+" with key:", node_key])) handles_of_vessels_to_release.append(node_key+':'+vesseldict['vesselname']) else: # Try to connect to that node to get the handle vessel_location = vesseldict['node_ip']+':'+str(int(vesseldict['node_port']))+':'+vesseldict['vesselname'] try: handles_of_vessels_to_release.append(get_handle_from_nodehandle(vessel_location)) except fastnmclient.NMClientException, e: logger.info("Failed to look up vessel "+vessel_location+' through nodemanager: '+ str(e)) client = selexorhelper.connect_to_clearinghouse(authdata) # Release the remaining vessels for vessel in handles_of_vessels_to_release: # Do we need to check if a vessel failed to release? # Maybe it means that a vessel has gone offline/is now invalid. client.release_resources([vessel]) # Assume all the vessels were released successfully num_released = len(handles_of_vessels_to_release) # Remove vessel entries from the groups tables. if identity in request_datum: for group in request_datum[identity]['groups']: for vesselhandle in handles_of_vessels_to_release: if vesselhandle in request_datum[identity]['groups'][group]['acquired']: request_datum[identity]['groups'][group]['acquired'].remove(vesselhandle) request_datum[identity]['groups'][group]['allocate'] -= 1