def _process_query(self, endpoint_name, start): try: self._add_CORS_header() if not self.request.body: self.request.body = {} # extract request data explicitly for caching purpose request_json = self.request.body.decode('utf-8') # Sanitize input data data = _sanitize_request_data(simplejson.loads(request_json)) except Exception as e: err_msg = format_exception(e, "Invalid Input Data") self.error_out(400, err_msg) return try: (po_name, all_endpoint_names) = self._get_actual_model(endpoint_name) # po_name is None if self.py_handler.ps.query_objects.get( # endpoint_name) is None if not po_name: log_error("UnknownURI", endpoint_name=endpoint_name) self.error_out(404, 'UnknownURI', info="Endpoint '%s' does not exist" % endpoint_name) return po_obj = self.py_handler.ps.query_objects.get(po_name) if not po_obj: log_error("UnknownURI", endpoint_name=po_name) self.error_out(404, 'UnknownURI', info="Endpoint '%s' does not exist" % po_name) return if po_name != endpoint_name: log_info("Querying actual model", po_name=po_name) uid = _get_uuid() # record query w/ request ID in query log qry = Query(po_name, request_json) gls_time = 0 # send a query to PythonService and return (gls_time, result) = self._handle_result(po_name, data, qry, uid) # if error occurred, GLS time is None. if not gls_time: return except Exception as e: err_msg = format_exception(e, 'process query') self.error_out(500, 'Error processing query', info=err_msg) return
def _process_query(self, endpoint_name, start): try: self._add_CORS_header() if not self.request.body: self.request.body = {} # extract request data explicitly for caching purpose request_json = self.request.body.decode('utf-8') # Sanitize input data data = _sanitize_request_data(simplejson.loads(request_json)) except Exception as e: err_msg = format_exception(e, "Invalid Input Data") self.error_out(400, err_msg) return try: (po_name, all_endpoint_names) = self._get_actual_model(endpoint_name) ## po_name is None if self.py_handler.ps.query_objects.get(endpoint_name) is None if not po_name: log_error("UnknownURI", endpoint_name = endpoint_name) self.error_out(404, 'UnknownURI', info="Endpoint '%s' does not exist" % endpoint_name) return po_obj = self.py_handler.ps.query_objects.get(po_name) if not po_obj: log_error("UnknownURI", endpoint_name = po_name) self.error_out(404, 'UnknownURI',info="Endpoint '%s' does not exist" % po_name) return if po_name != endpoint_name: log_info("Querying actual model", po_name = po_name) uid = _get_uuid() # record query w/ request ID in query log qry = Query(po_name, request_json) gls_time = 0 # send a query to PythonService and return (gls_time, result) = self._handle_result(po_name, data, qry, uid) # if error occurred, GLS time is None. if not gls_time: return except Exception as e: err_msg = format_exception(e, 'process query') self.error_out(500, 'Error processing query', info = err_msg) return
def query(self, object_uri, params, uid): """Execute a QueryObject query""" try: if not isinstance(params, dict) and not isinstance(params, list): return QueryFailed( uri=object_uri, error="Query parameter needs to be a dictionary or a list. Given value is of type %s." % type(params)) obj_info = self.query_objects.get(object_uri) if obj_info: pred_obj = obj_info['endpoint_obj'] version = obj_info['version'] if not pred_obj: return QueryFailed(uri=object_uri, error= "There is no query object associated to the endpoint: %s" % object_uri) if isinstance(params, dict): result = pred_obj.query(**params) else: result = pred_obj.query(*params) return QuerySuccessful(object_uri, version, result) else: return UnknownURI(object_uri) except Exception as e: err_msg = format_exception(e, '/query') log_error(err_msg) return QueryFailed(uri=object_uri, error=err_msg)
def query(self, object_uri, params, uid): """Execute a QueryObject query""" try: if not isinstance(params, dict) and not isinstance(params, list): return QueryFailed( uri=object_uri, error= "Query parameter needs to be a dictionary or a list. Given value is of type %s." % type(params)) obj_info = self.query_objects.get(object_uri) if obj_info: pred_obj = obj_info['endpoint_obj'] version = obj_info['version'] if not pred_obj: return QueryFailed( uri=object_uri, error= "There is no query object associated to the endpoint: %s" % object_uri) if isinstance(params, dict): result = pred_obj.query(**params) else: result = pred_obj.query(*params) return QuerySuccessful(object_uri, version, result) else: return UnknownURI(object_uri) except Exception as e: err_msg = format_exception(e, '/query') log_error(err_msg) return QueryFailed(uri=object_uri, error=err_msg)
def init_model_evaluator(settings): ''' This will go through all models that the service currently have and initialize them. ''' try: tabpy = settings['tabpy'] py_handler = settings['py_handler'] existing_pos = tabpy.get_endpoints() for (object_name, obj_info) in (existing_pos.items() if sys.version_info > (3,0) else existing_pos.iteritems()): object_version = obj_info['version'] object_type = obj_info['type'] object_path = get_query_object_path( os.environ['TABPY_STATE_PATH'], object_name, object_version) log_info('Load endpoint: %s, version: %s, type: %s' % \ (object_name, object_version, object_type)) if object_type == 'alias': msg = LoadObject(object_name, obj_info['target'], object_version, False, 'alias') else: local_path = object_path msg = LoadObject(object_name, local_path, object_version, False, object_type) py_handler.manage_request(msg) except Exception as e: err_msg = format_exception(e, "Exception encounted when initializing evaluator host:%s" % host_to_initialize) log_error(err_msg)
def init_model_evaluator(settings): ''' This will go through all models that the service currently have and initialize them. ''' try: tabpy = settings['tabpy'] py_handler = settings['py_handler'] existing_pos = tabpy.get_endpoints() for (object_name, obj_info) in (existing_pos.items() if sys.version_info > (3,0) else existing_pos.iteritems()): object_version = obj_info['version'] object_type = obj_info['type'] object_path = get_query_object_path( settings['state_file_path'], object_name, object_version) log_info('Load endpoint: %s, version: %s, type: %s' % \ (object_name, object_version, object_type)) if object_type == 'alias': msg = LoadObject(object_name, obj_info['target'], object_version, False, 'alias') else: local_path = object_path msg = LoadObject(object_name, local_path, object_version, False, object_type) py_handler.manage_request(msg) except Exception as e: err_msg = format_exception(e, "Exception encounted when initializing evaluator host:%s" % host_to_initialize) log_error(err_msg)
def put(self, name): try: if not self.request.body: self.error_out(400, "Input body cannot be empty") self.finish() return try: request_data = simplejson.loads(self.request.body.decode('utf-8')) except: self.error_out(400, "Failed to decode input body") self.finish() return # check if endpoint exists endpoints = self.tabpy.get_endpoints(name) if len(endpoints) == 0: self.error_out(404, "endpoint %s does not exist." % name) self.finish() return new_version = int(endpoints[name]['version']) + 1 log_info('Endpoint info: %s' % request_data) err_msg = yield self._add_or_update_endpoint('update', name, new_version, request_data) if err_msg: self.error_out(400, err_msg) self.finish() else: self.write(self.tabpy.get_endpoints(name)) self.finish() except Exception as e: err_msg = format_exception(e, 'update_endpoint') self.error_out(500, err_msg) self.finish()
def post(self): try: body = simplejson.loads(self.request.body.decode('utf-8')) if 'script' not in body: self.error_out(400, 'Script is empty.') return # Transforming user script into a proper function. user_code = body['script'] arguments = None arguments_str = '' if 'data' in body: arguments = body['data'] if arguments is not None: if not isinstance(arguments, dict): self.error_out(400, 'Script parameters need to be provided as a dictionary.') return else: arguments_expected = [] for i in range(1, len(arguments.keys())+1): arguments_expected.append('_arg'+str(i)) if sorted(arguments_expected)==sorted(arguments.keys()): arguments_str = ', ' + ', '.join(arguments.keys()) else: self.error_out(400, 'Variables names should follow the format _arg1, _arg2, _argN') return function_to_evaluate = 'def _user_script(tabpy' + arguments_str + '):\n' for u in user_code.splitlines(): function_to_evaluate += ' ' + u + '\n' log_info("function to evaluate=%s" % function_to_evaluate) result = yield self.call_subprocess(function_to_evaluate, arguments) if result is None: self.error_out(400, 'Error running script. No return value') else: self.write(simplejson.dumps(result)) self.finish() except Exception as e: err_msg = "%s : " % e.__class__.__name__ err_msg += "%s" % str(e) if err_msg!="KeyError : 'response'": err_msg = format_exception(e, 'POST /evaluate') self.error_out(500, 'Error processing script', info = err_msg) else: self.error_out(404, 'Error processing script', info="The endpoint you're trying to query did not respond. Please make sure the endpoint exists and the correct set of arguments are provided.")
def on_state_change(settings): try: tabpy = settings['tabpy'] py_handler = settings['py_handler'] log_info("Loading state from state file") config = util._get_state_from_file(settings['state_file_path']) new_ps_state = TabPyState(config=config) (has_changes, changes) = _get_latest_service_state(settings, new_ps_state) if not has_changes: log_info("Nothing changed, return.") return new_endpoints = new_ps_state.get_endpoints() for object_name in changes['endpoints']: (object_type, object_version, object_path) = changes['endpoints'][object_name] if not object_path and not object_version: # removal log_info("Removing object", uri=object_name) py_handler.manage_request(DeleteObjects([object_name])) cleanup_endpoint_files(object_name, settings['upload_dir']) else: endpoint_info = new_endpoints[object_name] is_update = object_version > 1 if object_type == 'alias': msg = LoadObject(object_name, endpoint_info['target'], object_version, is_update, 'alias') else: local_path = object_path msg = LoadObject(object_name, local_path, object_version, is_update, object_type) py_handler.manage_request(msg) wait_for_endpoint_loaded(py_handler, object_name) # cleanup old version of endpoint files if object_version > 2: cleanup_endpoint_files( object_name, settings['upload_dir'], [object_version, object_version - 1]) except Exception as e: err_msg = format_exception(e, 'on_state_change') log_warning("Error submitting update model request", error=err_msg)
def post(self): try: body = simplejson.loads(self.request.body.decode('utf-8')) if 'script' not in body: self.error_out(400, 'Script is empty.') return # Transforming user script into a proper function. user_code = body['script'] arguments = None arguments_str = '' if 'data' in body: arguments = body['data'] if arguments is not None: if not isinstance(arguments, dict): self.error_out( 400, 'Script parameters need to be provided as a dictionary.' ) return else: arguments_expected = [] for i in range(1, len(arguments.keys()) + 1): arguments_expected.append('_arg' + str(i)) if sorted(arguments_expected) == sorted(arguments.keys()): arguments_str = ', ' + ', '.join(arguments.keys()) else: self.error_out( 400, 'Variables names should follow the format _arg1, _arg2, _argN' ) return function_to_evaluate = 'def _user_script(tabpy' + arguments_str + '):\n' for u in user_code.splitlines(): function_to_evaluate += ' ' + u + '\n' log_info("function to evaluate=%s" % function_to_evaluate) result = yield self.call_subprocess(function_to_evaluate, arguments) if result is None: self.error_out(400, 'Error running script. No return value') else: self.write(simplejson.dumps(result)) self.finish() except Exception as e: err_msg = format_exception(e, 'POST /evaluate') self.error_out(500, 'Error processing script', info=err_msg)
def on_state_change(settings): try: tabpy = settings['tabpy'] py_handler = settings['py_handler'] log_info("Loading state from state file") state_file_path = os.environ['TABPY_STATE_PATH'] config = util._get_state_from_file(state_file_path) new_ps_state = TabPyState(config=config) (has_changes, changes) = _get_latest_service_state(settings, new_ps_state) if not has_changes: log_info("Nothing changed, return.") return new_endpoints = new_ps_state.get_endpoints() for object_name in changes['endpoints']: (object_type, object_version, object_path) = changes['endpoints'][object_name] if not object_path and not object_version: # removal log_info("Removing object", uri=object_name) py_handler.manage_request(DeleteObjects([object_name])) cleanup_endpoint_files(object_name) else: endpoint_info = new_endpoints[object_name] is_update = object_version > 1 if object_type == 'alias': msg = LoadObject(object_name, endpoint_info['target'], object_version, is_update, 'alias') else: local_path = object_path msg = LoadObject(object_name, local_path, object_version, is_update, object_type) py_handler.manage_request(msg) wait_for_endpoint_loaded(py_handler, object_name) # cleanup old version of endpoint files if object_version > 2: cleanup_endpoint_files(object_name, [object_version, object_version - 1]) except Exception as e: err_msg = format_exception(e, 'on_state_change') log_warning("Error submitting update model request", error=err_msg)
def post(self): try: if not self.request.body: self.error_out(400, "Input body cannot be empty") self.finish() return try: request_data = simplejson.loads( self.request.body.decode('utf-8')) except: self.error_out(400, "Failed to decode input body") self.finish() return if 'name' not in request_data: self.error_out(400, "name is required to add an endpoint.") self.finish() return name = request_data['name'] # check if endpoint already exist if name in self.tabpy.get_endpoints(): self.error_out(400, "endpoint %s already exists." % name) self.finish() return err_msg = yield self._add_or_update_endpoint( 'add', name, 1, request_data) if err_msg: self.error_out(400, err_msg) else: self.set_status(201) self.write(self.tabpy.get_endpoints(name)) self.finish() except Exception as e: err_msg = format_exception(e, '/add_endpoint') self.error_out(500, "error adding endpoint", err_msg) self.finish() return
def post(self): try: if not self.request.body: self.error_out(400, "Input body cannot be empty") self.finish() return try: request_data = simplejson.loads(self.request.body.decode('utf-8')) except: self.error_out(400, "Failed to decode input body") self.finish() return if 'name' not in request_data: self.error_out(400, "name is required to add an endpoint.") self.finish() return name = request_data['name'] # check if endpoint already exist if name in self.tabpy.get_endpoints(): self.error_out(400, "endpoint %s already exists." % name) self.finish() return err_msg = yield self._add_or_update_endpoint('add', name, 1, request_data) if err_msg: self.error_out(400, err_msg) else: self.set_status(201) self.write(self.tabpy.get_endpoints(name)) self.finish() except Exception as e: err_msg = format_exception(e, '/add_endpoint') self.error_out(500, "error adding endpoint", err_msg) self.finish() return
def delete(self, name): try: endpoints = self.tabpy.get_endpoints(name) if len(endpoints) == 0: self.error_out(404, "endpoint %s does not exist." % name) self.finish() return # update state try: endpoint_info = self.tabpy.delete_endpoint(name) except Exception as e: self.error_out(400, "Error when removing endpoint: %s" % e.message) self.finish() return # delete files if endpoint_info['type'] != 'alias': delete_path = get_query_object_path(self.settings['state_file_path'], name, None) try: yield self._delete_po_future(delete_path) except Exception as e: self.error_out(400, "Error while deleting: %s" % e) self.finish() return self.set_status(204) self.finish() except Exception as e: err_msg = format_exception(e, 'delete endpoint') self.error_out(500, err_msg) self.finish() on_state_change(self.settings)