def _wrap(*args, **kwargs): if X_AUTH_TOKEN_HEADER not in request.headers: # Unauthorized logger_api.error("No token in header") abort(httplib.UNAUTHORIZED) else: logger_api.info("Checking token: {}...".format( request.headers[X_AUTH_TOKEN_HEADER])) try: token = validate_token( access_token=request.headers[X_AUTH_TOKEN_HEADER]) except Exception as excep: # The exception could be a json message for the application # or text message for the keystone client components. try: data = json.loads(excep.message) abort(data['error']['code'], excep.message) except ValueError: message = { "error": { "message": error_message(excep.message), "code": httplib.BAD_REQUEST } } abort(httplib.BAD_REQUEST, message) kwargs['token'] = token return func(*args, **kwargs)
def _wrap(*args, **kwargs): if X_AUTH_TOKEN_HEADER not in request.headers: # Unauthorized logger_api.error("No token in header") abort(httplib.UNAUTHORIZED) else: logger_api.info("Checking token: {}...".format(request.headers[X_AUTH_TOKEN_HEADER])) try: token = validate_token(access_token=request.headers[X_AUTH_TOKEN_HEADER]) except Exception as excep: # The exception could be a json message for the application # or text message for the keystone client components. try: data = json.loads(excep.message) abort(data['error']['code'], excep.message) except ValueError: message = { "error": { "message": error_message(excep.message), "code": httplib.BAD_REQUEST } } abort(httplib.BAD_REQUEST, message) kwargs['token'] = token return func(*args, **kwargs)
def get_info(): """ Lists information about GlanceSync API version. :return: JSON responses with the detailed information about the Glancesync API """ message = "GET information about glancesync server" logger_api.info(message) message = ''' { "id": "%s", "owner": "%s", "status": "%s", "version": "%s", "updated": "%s", "runningfrom": "%s", "href": "%s" } ''' % (ID, OWNER, STATUS, VERSION, UPDATED, RUNNINGFROM, API_INFO_URL) resp = make_response(message, httplib.OK) resp.headers[SERVER_HEADER] = SERVER resp.headers[CONTENT_TYPE] = JSON_TYPE logger_api.info('Return result: %s', message) return resp
def check_token(self, admin_token, token): """ Checks if a token is valid against a url using an admin token. :param admin_token: The admin token to check the token. :param token: The token to be validated. :return: The result of the validation or error if something was wrong. """ logger_api.info("Starting Authentication of token %s ", token) try: if not token: raise Unauthorized("Token is empty") auth_result = self.get_info_token(admin_token, token) # Here we should check that the tenant id is the id of the project that we want to check return auth_result except Unauthorized as unauth: logger_api.error(unauth) raise unauth except InternalServerError as internalError: logger_api.error("%s", internalError.message) raise AuthorizationFailure("Token could not have enough permissions to access tenant") except Exception as ex: logger_api.error("%s", ex.message) raise ex
def check_token(self, admin_token, token): """ Checks if a token is valid against a url using an admin token. :param admin_token: The admin token to check the token. :param token: The token to be validated. :return: The result of the validation or error if something was wrong. """ logger_api.info("Starting Authentication of token %s ", token) try: if not token: raise Unauthorized("Token is empty") auth_result = self.get_info_token(admin_token, token) # Here we should check that the tenant id is the id of the project that we want to check return auth_result except Unauthorized as unauth: logger_api.error(unauth) raise unauth except InternalServerError as internalError: logger_api.error("%s", internalError.message) raise AuthorizationFailure( "Token could not have enough permissions to access tenant") except Exception as ex: logger_api.error("%s", ex.message) raise ex
def delete_task(regionid, taskid, token=None): """ Delete a synchronized task from the DB. :param regionid: The name of the region. :param taskid: The identity of the task. :param token: The token of the request to be authorized. :return: 200 - Ok if all is Ok ERROR - if the token is invalid, the region is incorrect or the task is not synchronized. """ message = "DELETE, delete the registry of task {} in the region: {}".format(taskid, regionid) logger_api.info(message) users = User.query.filter(User.task_id == taskid).all() if not users: msg = "The requested URL was not found on the server. If you entered the URL manually please" \ " check your spelling and try again." message = { "error": { "message": msg, "code": httplib.NOT_FOUND } } abort(httplib.NOT_FOUND, message) elif len(users) == 1 and users[0].region == regionid and users[0].status != Task.SYNCING: # we can delete iff the status es 'synced' or 'failing' db.session.delete(users[0]) db.session.commit() else: # We cannot delete the task due to the status in syncing msg = { "error": { "message": "Task status is syncing. Unable to delete it.", "code": httplib.BAD_REQUEST } } abort(httplib.BAD_REQUEST, msg) resp = make_response() resp.headers[SERVER_HEADER] = SERVER resp.headers[CONTENT_TYPE] = JSON_TYPE logger_api.info("Deleted task: %s" % taskid) return resp
def _wrap(*args, **kwargs): region_name = kwargs['regionid'] region_management = region() logger_api.info("Checking region: {}...".format(region_name)) result = region_management.validate_region(region_name) if result: return func(*args, **kwargs) else: abort(httplib.BAD_REQUEST, "Invalid region " + region_name)
def _wrap(*args, **kwargs): region_name = kwargs['regionid'] region_management = region() logger_api.info("Checking region: {}...".format(region_name)) result = region_management.validate_region(region_name) if result: return func(*args, **kwargs) else: abort(httplib.BAD_REQUEST, "Invalid region "+region_name)
def handle(self, app, host, port, workers): """ Method to manage the creation of an GUnicorn Application. :param app: The app of the GlanceSync-API :param host: The host in which the gunicorn service will be up. :param port: The port of the gunicorn service. :param workers: The number of concurrent workers to be launched. :return: Nothing """ bind = "%s:%s" % (host, str(port)) workers = WORKERS pid_file = PIDFILE loglevel = LOGLEVEL # We have to be sure that the directory exist in order # to write there the pid file. mkpath(os.path.dirname(pid_file)) if version_info < (0, 9, 0): raise RuntimeError( "Unsupported gunicorn version! Required > 0.9.0") else: class FlaskApplication(Application): def init(self, parser, opts, args): return { 'bind': bind, 'workers': workers, 'pidfile': pid_file, 'loglevel': loglevel, } def load(self): return app # Do not pass any cmdline options to gunicorn sys.argv = sys.argv[:2] logger_api.info("Logging to stderr with loglevel '%s'" % loglevel) logger_api.info("Starting gunicorn...") FlaskApplication().run()
def get_task(regionid, taskid, token=None): """ Get the status of the requested synchronization task. :param regionid: Region name how you can obtain from the Keystone service. Example: Spain2. :param taskid: The identity of the task. :param token: The token of the request to be authorized. :return: 200 - Ok if all is Ok ERROR - if the token is invalid, the region is incorrect or the task does not exist. """ # WARNING # It is for test only, we have to recover this information from the DB # in order to know the status of the synchronization of the task <taskid> message = "GET, obtain the status of the synchronization of a task: {} in the region: {}".format(taskid, regionid) logger_api.info(message) users = User.query.filter(User.task_id == taskid).all() if not users: msg = "The requested URL was not found on the server. If you entered the URL manually please" \ " check your spelling and try again." message = { "error": { "message": msg, "code": httplib.NOT_FOUND } } abort(httplib.NOT_FOUND, message) else: newtask = Task(taskid=users[0].task_id, status=users[0].status) resp = make_response(newtask.dump(), httplib.OK) resp.headers[SERVER_HEADER] = SERVER resp.headers[CONTENT_TYPE] = JSON_TYPE logger_api.info('Return result: %s', newtask.dump()) return resp
def run_in_thread(regionid, user): """ Launch the synchronization in a new Thread :param regionid: region name to sync :param user: an instance of User """ logger_api.info('Sync region {}, running in thread: {}'.format(regionid, threading.currentThread().getName())) try: glancesync = GlanceSync(options_dict=None) glancesync.sync_region(regionid, dry_run=False) row_changed = User.query.filter(User.task_id == user.task_id).one() row_changed.change_status(Task.SYNCED) db.session.commit() except Exception as e: logger_api.warn('Error in thread {}, with error: {}'.format(threading.currentThread().getName(), e.message)) row_changed = User.query.filter(User.task_id == user.task_id).one() row_changed.change_status(Task.FAILED) db.session.commit()
def get_status(regionid, token=None): """ Lists information the status of the synchronization of the images in the region <regionid>. Keep in mind that <regionid> is the name of the region. :param regionid: Region name how you can obtain from the Keystone service. Example: Spain2. :param token: The token of the request to be authorized. :return: JSON response message with the detailed information about the images and the sincronization status. """ message = "GET, get information about the synchronization status in the region: {}".format(regionid) logger_api.info(message) image_name = request.args.get('image') glancesync = GlanceSync(options_dict=None) list_images = glancesync.get_images_region(regionid, only_tenant_images=False) x = Images() for item in list_images: try: if image_name is None or item.name == image_name: x.add([item.id, item.name, item.status, None]) except Exception as e: print(e) if list_images: logger_api.info('Return result: %s', x.dump()) response = make_response(x.dump(), httplib.OK) else: response = make_response('{}', httplib.OK) response.headers[SERVER_HEADER] = SERVER response.headers[CONTENT_TYPE] = JSON_TYPE return response
def synchronize(regionid, token=None): """ Synchronize the images of the corresponding region defined by its regionId. The operation is asynchronous a response a taskId in order that you can follow the execution of the process. :param regionid: Region name how you can obtain from the Keystone service. Example: Spain2. :param token: The token of the request to be authorized. :return: JSON message with the identification of the created task. """ # WARNING # It is for testing only, the functionality of this method is create a new Task, # store the content of the new task with <taskid> in DB with status 'syncing' # and launch a fork to start the execution of the synchronization process. At the # end of the synchronization process, we update the DB registry with the status # 'synced' message = "POST, create a new synchronization task in the region: {}".format(regionid) logger_api.info(message) # Previously to each operation, we have to check if there is a task in the DB # with the status syncing associated to this region. users = User.query.filter(User.region == regionid).all() newtask = None if not users: newtask = Task(status=Task.SYNCING) # name and role should be returned from authorized operation, to be extended in Sprint 16.02 newuser = User(region=regionid, name=token.username, task_id=str(newtask.taskid), role='admin', status=newtask.status) db.session.add(newuser) try: db.session.commit() # Do the stuff to sync the images here... logger_api.debug("new thread") t = threading.Thread(target=run_in_thread, args=(regionid, newuser)) t.start() except Exception as e: message = ''' { "error": { "message": "Please check that you have initialized the DB. See the documentation about it.", "code": %s } } ''' % httplib.BAD_REQUEST abort(httplib.BAD_REQUEST, message) elif len(users) == 1 and users[0].region == regionid and users[0].status == Task.SYNCING: newtask = Task(taskid=users[0].task_id, status=users[0].status) if newtask is None: message = ''' { "error": { "message": "Already exist some task for this region", "code": %s } } ''' % httplib.BAD_REQUEST abort(httplib.BAD_REQUEST, message) resp = make_response(newtask.dump(), httplib.OK) resp.headers[SERVER_HEADER] = SERVER resp.headers[CONTENT_TYPE] = JSON_TYPE logger_api.info('Return result: %s', newtask.dump()) return resp