def create_database(): """ Creates any missing tables. """ db, cursor = selexorhelper.connect_to_db() code = open('database_create.sql', 'r').read() for line in code.split(';'): if line.strip(): cursor.execute(line.strip())
def get_request_status(self, authinfo, remoteip): ''' <Purpose> Returns the status of the current request. <Arguments> None <Exceptions> None <Side Effects> None <Return> A dictionary containing the status of each group. 'group_id': 'group_status' ''' db, cursor = selexorhelper.connect_to_db() cursor = db.cursor() data = {'groups':{}} try: username = authinfo.keys()[0] identity = (username, remoteip) if identity not in request_datum: data['status'] = "unknown" return data request_data = request_datum[identity] data['status'] = request_data['status'] for group in request_data['groups'].values(): data['groups'][group['id']] = {} group_data = data['groups'][group['id']] group_data['status'] = group['status'] if 'error' in group: group_data['error'] = group['error'] group_data['vessels_acquired'] = [] for vesseldict in group['acquired']: vesselhandle = vesseldict['handle'] nodeinfo = {} nodekey, nodeinfo['vesselname'] = vesselhandle.split(':') cursor.execute('SELECT ip_addr, node_port FROM nodes WHERE node_key="'+nodekey+'"') nodeinfo['node_ip'], nodeinfo['node_port'] = cursor.fetchone() nodeinfo['handle'] = vesselhandle group_data['vessels_acquired'].append(nodeinfo) group_data['target_num_vessels'] = group['allocate'] except Exception, e: logger.error(str(identity) + ": Error while responding to status query\n" + traceback.format_exc()) data['error'] = str(e)
def serve_request(self, identity, request_data, client): ''' <Purpose> Serves a host request. <Arguments> identity: A user identity. request_data: A requestdict. client: The Seattle Clearinghouse XMLRPC client to use. <Side Effects> Attempts to obtain vessels described in the request_data. This is not guaranteed, depending on the ddata collected in the selexordatabase. <Exceptions> SeattleClearinghouse. InvalidRequestStringError <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. ''' logger.info(str(identity) + ": Request data:\n" + str(request_data)) db, cursor = selexorhelper.connect_to_db() for groupname, group in request_data['groups'].iteritems(): pass_no = 0 while pass_no < 5: try: logger.info(str(identity) + ": Resolving group: " + str(groupname)) group = self.resolve_node(identity, client, group, db, cursor) # We are done here, no need to proceed with the remaining # passes if group['status'] != STATUS_INCOMPLETE: break except seattleclearinghouse_xmlrpc.NotEnoughCreditsError, e: group['status'] = 'error' group['error'] = str(e) logger.info(str(identity) + ": Not enough credits.") request_data['status'] = 'error' return 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
def contact_vessels_and_update_database(nodes_to_check): ''' Of all nodes that need checking, take one node. Obtain its: IP address name of each vessel on it Location For each vessel, obtain: vessel name ports available Finally, update the information about these nodes. ''' db, cursor = selexorhelper.connect_to_db() while nodes_to_check: nodelocation = nodes_to_check.pop() nodeinfo = selexorhelper.get_node_ip_port_from_nodelocation(nodelocation) # We can't use NAT addresses, nor ipv6 if not selexorhelper.is_ipv4_address(nodeinfo['id']): # if nodeinfo['id'].startswith('NAT'): # self._nat_nodes.append(nodeinfo['id']) continue # Used to communicate with the node node_nmhandle = None try: node_nmhandle = nmclient_createhandle(nodeinfo['id'], nodeinfo['port']) node_dict = nmclient_getvesseldict(node_nmhandle) ports = {} for vesselname in node_dict['vessels']: resources_string = nmclient_rawsay(node_nmhandle, "GetVesselResources", vesselname) ports[vesselname] = selexorhelper.get_ports_from_resource_string(resources_string) node_dict['vessels'][vesselname]['acquirable'] = \ selexorhelper.is_resource_acquirable(resources_string) # Retrieve the geographic information try: # We need to some initial value so that it is not undefined when we check it later. geoinfo = None # Only retrieve the geographic information if we don't have it already # The geoip server's data doesn't change, so we don't need to constantly update it. geoinfo_exists = selexorhelper.autoretry_mysql_command(cursor, "SELECT ip_addr FROM location WHERE ip_addr='"+nodeinfo['id']+"'") == 1L if not geoinfo_exists: logger.info("Location data not in database, looking up on geoip: "+nodelocation) geoinfo = geoip_record_by_addr(nodeinfo['id']) except Exception, e: if not "Unable to contact the geoip server" in str(e): raise # The geoip lookup sometimes returns None. if geoinfo is None: geoinfo = {} format_geoinfo(geoinfo) commit_data_to_database(db, cursor, nodeinfo['id'], nodeinfo['port'], node_dict, ports, geoinfo) except NMClientException, e: if not node_nmhandle: nmclient_destroyhandle(node_nmhandle) # self._bad_node_locations.append(nodelocation) errstr = str(e) if ("timed out" in errstr or 'No connection could be made because the target machine actively refused it' in errstr or "Connection refused" in errstr or "Socket closed" in errstr): continue logger.error("Unknown error contacting " + nodelocation + traceback.format_exc())