def GET(self, rule_id): """ get analysis for given rule. HTTP Success: 200 OK HTTP Error: 404 Not Found 406 Not Acceptable 500 InternalError :returns: JSON dict containing informations about the requested user. """ header('Content-Type', 'application/json') try: analysis = examine_replication_rule(rule_id) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error) return render_json(**analysis)
def GET(self, scope, name): """ Return all associated rules of a file. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found :param scope: The scope name. """ header('Content-Type', 'application/x-json-stream') try: for rule in list_associated_replication_rules_for_file(scope=scope, name=name): yield dumps(rule, cls=APIEncoder) + '\n' except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error)
def GET(self, rse): """ Get RSE usage information. :param rse: the RSE name. """ header('Content-Type', 'application/x-json-stream') source = None if ctx.query: params = parse_qs(ctx.query[1:]) if 'source' in params: source = params['source'][0] try: for usage in list_rse_usage_history(rse=rse, issuer=ctx.env.get('issuer'), source=source): yield render_json(**usage) + '\n' except RSENotFound as error: raise generate_http_error(404, 'RSENotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error)
class ReplicasRSE(RucioController): def GET(self, rse): """ List dataset replicas replicas. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 500 InternalError :returns: A dictionary containing all replicas on the RSE. """ header('Content-Type', 'application/x-json-stream') try: for row in list_datasets_per_rse(rse=rse): yield dumps(row, cls=APIEncoder) + '\n' except RucioException, e: raise generate_http_error(500, e.__class__.__name__, e.args[0][0]) except Exception, e: print format_exc() raise InternalError(e)
def GET(self): """ Retrieve all exceptions. HTTP Success: 200 OK HTTP Error: 404 Not Found 406 Not Acceptable 500 Internal Error """ header('Content-Type', 'application/x-json-stream') try: for exception in list_exceptions(): yield dumps(exception, cls=APIEncoder) + '\n' except LifetimeExceptionNotFound as error: raise generate_http_error(404, 'LifetimeExceptionNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error)
def GET(self, account=None, name=None): """ Retrieve a subscription. HTTP Success: 200 OK HTTP Error: 404 Not Found 500 Internal Error :param account: The account name. :param name: The subscription name. """ header('Content-Type', 'application/x-json-stream') try: for subscription in list_subscriptions(name=name, account=account): yield dumps(subscription, cls=APIEncoder) + '\n' except SubscriptionNotFound as error: raise generate_http_error(404, 'SubscriptionNotFound', error.args[0]) except Exception as error: raise InternalError(error)
def GET(self, rse): """ List dataset replicas replicas. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 500 InternalError :returns: A dictionary containing all replicas on the RSE. """ header('Content-Type', 'application/x-json-stream') try: for row in list_datasets_per_rse(rse=rse, vo=ctx.env.get('vo')): yield dumps(row, cls=APIEncoder) + '\n' except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error)
def DELETE(self, scope, name): """ Mark the input DID as not followed HTTP Success: 200 OK HTTP Error: 401 Unauthorized 500 InternalError :param scope: The scope of the input DID. :param name: The name of the input DID. """ try: json_data = loads(data()) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') try: remove_did_from_followed(scope=scope, name=name, account=json_data['account'], issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except DataIdentifierNotFound as error: raise generate_http_error(404, 'DataIdentifierNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise OK()
def GET(self, rule_id): """ get rule information for given rule id. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found 406 Not Acceptable 500 InternalError :returns: JSON dict containing informations about the requested user. """ header('Content-Type', 'application/json') try: estimate_ttc = False json_data = data() params = loads(json_data) if 'estimate_ttc' in params: estimate_ttc = params['estimate_ttc'] except ValueError: estimate_ttc = False try: rule = get_replication_rule(rule_id, estimate_ttc=estimate_ttc, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except RuleNotFound as error: raise generate_http_error(404, 'RuleNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error) return render_json(**rule)
def DELETE(self, rule_id): """ Delete a new replication rule. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found 500 Internal Error """ json_data = data() try: purge_replicas = None params = loads(json_data) if 'purge_replicas' in params: purge_replicas = params['purge_replicas'] except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') try: delete_replication_rule(rule_id=rule_id, purge_replicas=purge_replicas, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except UnsupportedOperation as error: raise generate_http_error(401, 'UnsupportedOperation', error.args[0]) except RuleNotFound as error: raise generate_http_error(404, 'RuleNotFound', error.args[0]) except Exception as error: raise InternalError(error) raise OK()
class BadReplicasSummary(RucioController): def GET(self): """ Return a summary of the bad replicas by incident. HTTP Success: 200 OK HTTP Error: 500 InternalError """ header('Content-Type', 'application/x-json-stream') result = [] rse_expression, from_date, to_date = None, None, None if ctx.query: try: params = loads(unquote(ctx.query[1:])) except ValueError: params = parse_qs(ctx.query[1:]) if 'rse_expression' in params: rse_expression = params['rse_expression'][0] if 'from_date' in params: from_date = datetime.strptime(params['from_date'][0], "%Y-%m-%d") if 'to_date' in params: to_date = datetime.strptime(params['to_date'][0], "%Y-%m-%d") try: result = get_bad_replicas_summary(rse_expression=rse_expression, from_date=from_date, to_date=to_date) except RucioException, e: raise generate_http_error(500, e.__class__.__name__, e.args[0][0]) except Exception, e: print format_exc() raise InternalError(e)
def rucio_loadhook(): """ Rucio load Hook to authenticate, timing, etc. """ # Allow cross-site scripting header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') if ctx.env.get('REQUEST_METHOD') == 'OPTIONS': raise OK if ctx.env.get('REQUEST_METHOD') == 'GET': header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') else: header('Content-Type', 'application/octet-stream') auth_token = ctx.env.get('HTTP_X_RUCIO_AUTH_TOKEN') try: auth = validate_auth_token(auth_token) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if auth is None: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate with given credentials') # Propagate the issuer, request_id and start_time to the controller ctx.env['vo'] = auth.get('vo', 'def') ctx.env['issuer'] = auth.get('account') ctx.env['identity'] = auth.get('identity') ctx.env['request_id'] = generate_uuid() ctx.env['start_time'] = time()
def POST(self): header('Content-Type', 'application/octet-stream') header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') try: payload = json.loads(data()) # generate entry timestamp payload['traceTimeentry'] = datetime.datetime.utcnow() payload['traceTimeentryUnix'] = calendar.timegm( payload['traceTimeentry'].timetuple( )) + payload['traceTimeentry'].microsecond / 1e6 # guess client IP payload['traceIp'] = ctx.env.get('HTTP_X_FORWARDED_FOR') if payload['traceIp'] is None: payload[ 'traceIp'] = ctx.ip # quand meme, cela peut etre None aussi # generate unique ID payload['traceId'] = str(uuid.uuid4()).replace('-', '').lower() trace(payload=payload) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') except Exception as error: print(traceback.format_exc()) raise InternalError(error) raise Created()
def GET(self, account, rse): """ Return the account usage of the account. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found 406 Not Acceptable 500 Internal Error :param account: The account name. :param rse: The rse. """ header('Content-Type', 'application/json') try: usage = get_usage_history(account=account, rse=rse, issuer=ctx.env.get('issuer')) except AccountNotFound as error: raise generate_http_error(404, 'AccountNotFound', error.args[0]) except CounterNotFound as error: raise generate_http_error(404, 'CounterNotFound', error.args[0]) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) for entry in usage: for key, value in entry.items(): if isinstance(value, datetime): entry[key] = value.strftime('%Y-%m-%dT%H:%M:%S') return dumps(usage)
def GET(self, rse): """ List all supported protocols of the given RSE. HTTP Success: 200 OK HTTP Error: 404 Resource not Found 406 Not Acceptable 500 InternalError :returns: A list containing all supported protocols and all their attributes. """ header('Content-Type', 'application/json') p_list = None try: p_list = get_rse_protocols(rse, issuer=ctx.env.get('issuer')) except RSEOperationNotSupported as error: raise generate_http_error(404, 'RSEOperationNotSupported', error.args[0]) except RSENotFound as error: raise generate_http_error(404, 'RSENotFound', error.args[0]) except RSEProtocolNotSupported as error: raise generate_http_error(404, 'RSEProtocolNotSupported', error.args[0]) except RSEProtocolDomainNotSupported as error: raise generate_http_error(404, 'RSEProtocolDomainNotSupported', error.args[0]) except Exception as error: print(error) print(format_exc()) raise InternalError(error) if len(p_list['protocols']): return dumps(p_list['protocols']) else: raise generate_http_error(404, 'RSEProtocolNotSupported', 'No prptocols found for this RSE')
def POST(self): """ Set a tombstone on a list of replicas. HTTP Success: 201 OK HTTP Error: 401 Unauthorized 404 ReplicaNotFound 500 InternalError """ json_data = data() replicas = [] try: params = parse_response(json_data) if 'replicas' in params: replicas = params['replicas'] except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') try: for replica in replicas: set_tombstone(replica['rse'], replica['scope'], replica['name'], issuer=ctx.env.get('issuer')) except ReplicaNotFound as error: raise generate_http_error(404, 'ReplicaNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise Created()
def GET(self, account, name): """ Return all rules of a given subscription id. HTTP Success: 200 OK HTTP Error: 404 Not Found 406 Not Acceptable 500 Internal Error :param scope: The scope name. """ header('Content-Type', 'application/x-json-stream') state = None if ctx.query: params = parse_qs(ctx.query[1:]) if 'state' in params: state = params['state'][0] try: subscriptions = [subscription['id'] for subscription in list_subscriptions(name=name, account=account, vo=ctx.env.get('vo'))] if len(subscriptions) > 0: if state: for rule in list_replication_rules({'subscription_id': subscriptions[0], 'state': state}, vo=ctx.env.get('vo')): yield dumps(rule, cls=APIEncoder) + '\n' else: for rule in list_replication_rules({'subscription_id': subscriptions[0]}, vo=ctx.env.get('vo')): yield dumps(rule, cls=APIEncoder) + '\n' except RuleNotFound as error: raise generate_http_error(404, 'RuleNotFound', error.args[0]) except SubscriptionNotFound as error: raise generate_http_error(404, 'SubscriptionNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error)
def POST(self): """ List the DIDs associated to a list of replicas. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 500 InternalError :returns: A list of dictionaries containing the mAPPing PFNs to DIDs. """ json_data = data() rse, pfns = None, [] header('Content-Type', 'application/x-json-stream') rse = None try: params = parse_response(json_data) if 'pfns' in params: pfns = params['pfns'] if 'rse' in params: rse = params['rse'] except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') try: for pfn in get_did_from_pfns(pfns, rse, vo=ctx.env.get('vo')): yield dumps(pfn) + '\n' except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error)
def PUT(self, scope, name): """ Update data identifier status. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 500 InternalError :param scope: data identifier scope. :param name: data identifier name. """ json_data = data() try: kwargs = loads(json_data) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json data parameter') try: set_status(scope=scope, name=name, issuer=ctx.env.get('issuer'), **kwargs) except DataIdentifierNotFound as error: raise generate_http_error(404, 'DataIdentifierNotFound', error.args[0]) except UnsupportedStatus as error: raise generate_http_error(409, 'UnsupportedStatus', error.args[0]) except UnsupportedOperation as error: raise generate_http_error(409, 'UnsupportedOperation', error.args[0]) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise OK()
def POST(self, source, destination): """ Create distance information between source RSE and destination RSE. HTTP Success: 200 Updated HTTP Error: 400 Bad Request 401 Unauthorized 404 Not Found 409 Conflict 500 Internal Error :param rse: The RSE name. """ header('Content-Type', 'application/json') json_data = data().decode() try: parameter = loads(json_data) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter dictionary') try: add_distance(source=source, destination=destination, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo'), **parameter) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except RSENotFound as error: raise generate_http_error(404, 'RSENotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise Created()
def PUT(self, account): """ update a parameter for a given account name HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found 500 InternalError """ json_data = data() try: parameter = loads(json_data) except ValueError: raise generate_http_error( 400, 'ValueError', 'cannot decode json parameter dictionary') for key, value in parameter.items(): try: update_account(account, key=key, value=value, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except ValueError: raise generate_http_error(400, 'ValueError', 'Unknown value %s' % value) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except AccountNotFound as error: raise generate_http_error(404, 'AccountNotFound', error.args[0]) except Exception as error: raise InternalError(error) raise OK()
def GET(self, subscription_id): """ Retrieve a subscription matching the given subscription id HTTP Success: 200 OK HTTP Error: 401 Unauthorized 404 Not Found 406 Not Acceptable """ header('Content-Type', 'application/json') try: subscription = get_subscription_by_id(subscription_id, vo=ctx.env.get('vo')) except SubscriptionNotFound as error: raise generate_http_error(404, 'SubscriptionNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error) return render_json(**subscription)
def GET(self): """ Return a summary of the bad replicas by incident. HTTP Success: 200 OK HTTP Error: 406 Not Acceptable 500 InternalError """ header('Content-Type', 'application/x-json-stream') result = [] rse_expression, from_date, to_date = None, None, None if ctx.query: try: params = loads(unquote(ctx.query[1:])) except ValueError: params = parse_qs(ctx.query[1:]) if 'rse_expression' in params: rse_expression = params['rse_expression'][0] if 'from_date' in params and params['from_date'][0]: from_date = datetime.strptime(params['from_date'][0], "%Y-%m-%d") if 'to_date' in params: to_date = datetime.strptime(params['to_date'][0], "%Y-%m-%d") try: result = get_bad_replicas_summary(rse_expression=rse_expression, from_date=from_date, to_date=to_date, vo=ctx.env.get('vo')) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) for row in result: yield dumps(row, cls=APIEncoder) + '\n'
def GET(self): """ List the suspicious replicas on a lsit of RSEs. HTTP Success: 200 OK HTTP Error: 406 Not Acceptable 500 InternalError """ header('Content-Type', 'application/json') result = [] rse_expression, younger_than, nattempts = None, None, None if ctx.query: try: params = loads(unquote(ctx.query[1:])) except ValueError: params = parse_qs(ctx.query[1:]) print(params) if 'rse_expression' in params: rse_expression = params['rse_expression'][0] if 'younger_than' in params and params['younger_than'][0]: younger_than = datetime.strptime(params['younger_than'][0], "%Y-%m-%dT%H:%M:%S") if 'nattempts' in params: nattempts = int(params['nattempts'][0]) try: result = get_suspicious_files(rse_expression=rse_expression, younger_than=younger_than, nattempts=nattempts, vo=ctx.env.get('vo')) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) return render_json_list(result)
def POST(self): """ Declare a list of suspicious replicas. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 500 InternalError """ json_data = data() pfns = [] header('Content-Type', 'application/json') try: params = parse_response(json_data) if 'pfns' in params: pfns = params['pfns'] if 'reason' in params: reason = params['reason'] except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') not_declared_files = {} try: not_declared_files = declare_suspicious_file_replicas(pfns=pfns, reason=reason, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise Created(dumps(not_declared_files))
def DELETE(self): """ Delete file replicas at a given RSE. HTTP Success: 200 Ok HTTP Error: 401 Unauthorized 409 Conflict 500 Internal Error """ json_data = data() try: parameters = parse_response(json_data) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter list') try: delete_replicas(rse=parameters['rse'], files=parameters['files'], issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo'), ignore_availability=parameters.get('ignore_availability', False)) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except RSENotFound as error: raise generate_http_error(404, 'RSENotFound', error.args[0]) except ResourceTemporaryUnavailable as error: raise generate_http_error(503, 'ResourceTemporaryUnavailable', error.args[0]) except ReplicaNotFound as error: raise generate_http_error(404, 'ReplicaNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) raise OK()
def GET(self, guid): """ Return the file associated to a GUID. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 404 Not Found :param scope: The scope name. """ header('Content-Type', 'application/x-json-stream') try: for dataset in get_dataset_by_guid(guid): yield dumps(dataset, cls=APIEncoder) + '\n' except DataIdentifierNotFound as error: raise generate_http_error(404, 'DataIdentifierNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error)
def GET(self, scope, name): """ Return all rules of a given DID. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 404 Not Found :param scope: The scope name. """ header('Content-Type', 'application/x-json-stream') try: for rule in list_replication_rules({'scope': scope, 'name': name}): yield dumps(rule, cls=APIEncoder) + '\n' except RuleNotFound as error: raise generate_http_error(404, 'RuleNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: raise InternalError(error)
def GET(self, scope, name): """ List all parents of a data identifier. HTTP Success: 200 OK HTTP Error: 401 Unauthorized 406 Not Acceptable 500 InternalError :returns: A list of dictionary containing all dataset information. """ header('Content-Type', 'application/x-json-stream') try: for dataset in list_parent_dids(scope=scope, name=name): yield render_json(**dataset) + "\n" except DataIdentifierNotFound as error: raise generate_http_error(404, 'DataIdentifierNotFound', error.args[0]) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error)
def POST(self, rse, key): """ create rse with given RSE name. HTTP Success: 201 Created HTTP Error: 400 Bad request 401 Unauthorized 500 Internal Error :param rse: RSE name. :param key: Key attribute. """ json_data = data().decode() try: parameter = loads(json_data) except ValueError: raise generate_http_error(400, 'ValueError', 'Cannot decode json parameter dictionary') try: value = parameter['value'] except KeyError as error: raise generate_http_error(400, 'KeyError', '%s not defined' % str(error)) try: add_rse_attribute(rse=rse, key=key, value=value, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except Duplicate as error: raise generate_http_error(409, 'Duplicate', error.args[0]) except Exception as error: raise InternalError(error) raise Created()