def set_tombstone(rse, scope, name, issuer, vo='def'): """ Sets a tombstone on one replica. :param rse: name of the RSE. :param scope: scope of the replica DID. :param name: name of the replica DID. :param issuer: The issuer account :param vo: The VO to act on. """ rse_id = get_rse_id(rse, vo=vo) if not permission.has_permission(issuer=issuer, vo=vo, action='set_tombstone', kwargs={}): raise exception.AccessDenied('Account %s can not set tombstones' % (issuer)) scope = InternalScope(scope, vo=vo) replica.set_tombstone(rse_id, scope, name)
def set_rse_limits(rse, name, value, issuer, vo='def'): """ Set RSE limits. :param rse: The RSE name. :param name: The name of the limit. :param value: The feature value. :param issuer: The issuer account. :param vo: The VO to act on. :returns: True if successful, otherwise false. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse': rse, 'rse_id': rse_id} if not permission.has_permission(issuer=issuer, vo=vo, action='set_rse_limits', kwargs=kwargs): raise exception.AccessDenied('Account %s can not update RSE limits for RSE %s' % (issuer, rse)) return rse_module.set_rse_limits(rse_id=rse_id, name=name, value=value)
def get_auth_token_ssh(account, signature, appid, ip=None): """ Authenticate a Rucio account temporarily via SSH key exchange. The token lifetime is 1 hour. :param account: Account identifier as a string. :param signature: Response to challenge token signed with SSH private key as a base64 encoded string. :param appid: The application identifier as a string. :param ip: IP address of the client as a string. :returns: Authentication token as a variable-length string. """ kwargs = {'account': account, 'signature': signature} if not permission.has_permission(issuer=account, action='get_auth_token_ssh', kwargs=kwargs): raise exception.AccessDenied('User with provided signature can not log to account %s' % account) return authentication.get_auth_token_ssh(account, signature, appid, ip)
def update_rse(rse, parameters, issuer, vo='def'): """ Update RSE properties like availability or name. :param rse: the name of the new rse. :param parameters: A dictionnary with property (name, read, write, delete as keys). :param issuer: The issuer account. :param vo: The VO to act on. :raises RSENotFound: If RSE is not found. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse': rse, 'rse_id': rse_id} if not permission.has_permission( issuer=issuer, vo=vo, action='update_rse', kwargs=kwargs): raise exception.AccessDenied('Account %s can not update RSE' % (issuer)) return rse_module.update_rse(rse_id=rse_id, parameters=parameters)
def get_auth_token_gss(account, gsscred, appid, ip=None): """ Authenticate a Rucio account temporarily via a GSS token. The tokens lifetime is 1 hour. :param account: Account identifier as a string. :param gsscred: GSS principal@REALM as a string. :param appid: The application identifier as a string. :param ip: IP address of the client as a string. :returns: Authentication token as a variable-length string. """ kwargs = {'account': account, 'gsscred': gsscred} if not permission.has_permission(issuer=account, action='get_auth_token_gss', kwargs=kwargs): raise exception.AccessDenied('User with identity %s can not log to account %s' % (gsscred, account)) return authentication.get_auth_token_gss(account, gsscred, appid, ip)
def set_rse_limits(rse, name, value, issuer): """ Set RSE limits. :param rse: The RSE name. :param name: The name of the limit. :param value: The feature value. Set to -1 to remove the limit. :param issuer: The issuer account. :returns: True if successful, otherwise false. """ kwargs = {'rse': rse} if not permission.has_permission( issuer=issuer, action='set_rse_limits', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not update RSE limits for RSE %s' % (issuer, rse)) return rse_module.set_rse_limits(rse=rse, name=name, value=value)
def list_requests(src_rses, dst_rses, states, issuer): """ List all requests in a specific state from a source RSE to a destination RSE. :param src_rses: source RSEs. :param dst_rses: destination RSEs. :param states: list of request states. :param issuer: Issuing account as a string. """ src_rse_ids = [get_rse_id(rse=rse) for rse in src_rses] dst_rse_ids = [get_rse_id(rse=rse) for rse in dst_rses] kwargs = {'src_rse_id': src_rse_ids, 'dst_rse_id': dst_rse_ids, 'issuer': issuer} if not permission.has_permission(issuer=issuer, action='list_requests', kwargs=kwargs): raise exception.AccessDenied('%(issuer)s cannot list requests from RSE %(src_rse)s to RSE %(dst_rse)s' % locals()) for req in request.list_requests(src_rse_ids, dst_rse_ids, states): yield api_update_return_dict(req)
def delete_qos_policy(rse, qos_policy, issuer, vo='def'): """ Delete a QoS policy from an RSE. :param rse: The name of the RSE. :param qos_policy: The QoS policy to delete. :param issuer: The issuer account. :param vo: The VO to act on. :returns: True if successful, silent failure if QoS policy does not exist. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse_id': rse} if not permission.has_permission(issuer=issuer, action='delete_qos_policy', kwargs=kwargs): raise exception.AccessDenied('Account %s cannot delete QoS policies from RSE %s' % (issuer, rse)) return rse_module.delete_qos_policy(rse_id, qos_policy)
def sections(issuer=None, vo='def', session=None): """ Return a list of the sections available. :param issuer: The issuer account. :param vo: The VO to act on. :param session: The database session in use. :returns: ['section_name', ...] """ kwargs = {'issuer': issuer} if not permission.has_permission(issuer=issuer, vo=vo, action='config_sections', kwargs=kwargs, session=session): raise exception.AccessDenied('%s cannot retrieve sections' % issuer) return config.sections(session=session)
def list_vos(issuer, vo='def', session=None): ''' List the VOs. :param issuer: The user issuing the command. :param vo: The vo of the user issuing the command. :param session: The database session in use. ''' kwargs = {} if not has_permission(issuer=issuer, action='list_vos', kwargs=kwargs, vo=vo, session=session): raise exception.AccessDenied( 'Account {} cannot list VOs'.format(issuer)) return vo_core.list_vos(session=session)
def add_rse_attribute(rse, key, value, issuer, vo='def'): """ Adds a RSE attribute. :param rse: the rse name. :param key: the key name. :param value: the value name. :param issuer: The issuer account. :param vo: The VO to act on. returns: True if successful, False otherwise. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse': rse, 'rse_id': rse_id, 'key': key, 'value': value} if not permission.has_permission(issuer=issuer, vo=vo, action='add_rse_attribute', kwargs=kwargs): raise exception.AccessDenied('Account %s can not add RSE attributes' % (issuer)) return rse_module.add_rse_attribute(rse_id=rse_id, key=key, value=value)
def del_rse_attribute(rse, key, issuer, vo='def'): """ Delete a RSE attribute. :param rse: the name of the rse_module. :param key: the attribute key. :param vo: The VO to act on. :return: True if RSE attribute was deleted successfully, False otherwise. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse': rse, 'rse_id': rse_id, 'key': key} if not permission.has_permission(issuer=issuer, vo=vo, action='del_rse_attribute', kwargs=kwargs): raise exception.AccessDenied('Account %s can not delete RSE attributes' % (issuer)) return rse_module.del_rse_attribute(rse_id=rse_id, key=key)
def get_next(request_type, state, issuer, account, vo='def'): """ Retrieve the next request matching the request type and state. :param request_type: Type of the request as a string. :param state: State of the request as a string. :param issuer: Issuing account as a string. :param account: Account identifier as a string. :param vo: The VO to act on. :returns: Request as a dictionary. """ kwargs = {'account': account, 'issuer': issuer, 'request_type': request_type, 'state': state} if not permission.has_permission(issuer=issuer, vo=vo, action='get_next', kwargs=kwargs): raise exception.AccessDenied('%(account)s cannot get the next request of type %(request_type)s in state %(state)s' % locals()) reqs = request.get_next(request_type, state) return [api_update_return_dict(r) for r in reqs]
def update_exception(exception_id, state, issuer, vo='def'): """ Update exceptions state to Lifetime Model. :param id: The id of the exception. :param state: The states to filter. :param issuer: The issuer account. :param vo: The VO to act on. """ kwargs = {'exception_id': exception_id, 'vo': vo} if not permission.has_permission(issuer=issuer, vo=vo, action='update_lifetime_exceptions', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not update lifetime exceptions' % (issuer)) return lifetime_exception.update_exception(exception_id=exception_id, state=state)
def del_protocols(rse, scheme, issuer, vo='def', hostname=None, port=None): """ Deletes all matching protocol entries for the given RSE.. :param rse: The RSE name. :param issuer: The issuer account. :param vo: The VO to act on. :param scheme: The protocol identifier. :param hostname: The hostname (to be used if more then one protocol using the same identifier are present) :param port: The port (to be used if more than one protocol using the same identifier and hostname are present) """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse': rse, 'rse_id': rse_id} if not permission.has_permission(issuer=issuer, vo=vo, action='del_protocol', kwargs=kwargs): raise exception.AccessDenied('Account %s can not delete protocols from RSE %s' % (issuer, rse)) rse_module.del_protocols(rse_id=rse_id, scheme=scheme, hostname=hostname, port=port)
def list_heartbeats(issuer=None, vo='def', session=None): """ Return a list of tuples of all heartbeats. :param issuer: The issuer account. :param vo: the VO for the issuer. :param session: The database session in use. :returns: List of tuples [('Executable', 'Hostname', ...), ...] """ kwargs = {'issuer': issuer} if not permission.has_permission(issuer=issuer, vo=vo, action='list_heartbeats', kwargs=kwargs, session=session): raise exception.AccessDenied('%s cannot list heartbeats' % issuer) return heartbeat.list_heartbeats(session=session)
def declare_suspicious_file_replicas(pfns, reason, issuer): """ Declare a list of bad replicas. :param pfns: The list of PFNs. :param reason: The reason of the loss. :param issuer: The issuer account. """ kwargs = {} if not permission.has_permission(issuer=issuer, action='declare_suspicious_file_replicas', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not declare suspicious replicas' % (issuer)) return replica.declare_bad_file_replicas(pfns=pfns, reason=reason, issuer=issuer, status=BadFilesStatus.SUSPICIOUS)
def del_identity(identity_key, id_type, issuer, vo='def'): """ Deletes a user identity. :param identity_key: The identity key name. For example x509 DN, or a username. :param id_type: The type of the authentication (x509, gss, userpass, ssh, saml). :param issuer: The issuer account. :param vo: the VO of the issuer. """ id_type = IdentityType[id_type.upper()] kwargs = { 'accounts': identity.list_accounts_for_identity(identity_key, id_type) } if not permission.has_permission( issuer=issuer, vo=vo, action='del_identity', kwargs=kwargs): raise exception.AccessDenied('Account %s can not delete identity' % (issuer)) return identity.del_identity(identity_key, id_type)
def del_account_identity(identity_key, id_type, account, issuer): """ Removes a membership association between identity and account. :param identity_key: The identity key name. For example x509 DN, or a username. :param id_type: The type of the authentication (x509, gss, userpass, ssh). :param account: The account name. :param issuer: The issuer account. """ kwargs = {'account': account} if not permission.has_permission( issuer=issuer, action='del_account_identity', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not delete account identity' % (issuer)) return identity.del_account_identity(identity_key, IdentityType.from_sym(id_type), account)
def delete_replicas(rse, files, issuer, ignore_availability=False, vo='def', session=None): """ Bulk delete file replicas. :param rse: The RSE name. :param files: The list of files. :param issuer: The issuer account. :param ignore_availability: Ignore blocked RSEs. :param vo: The VO to act on. :param session: The database session in use. :returns: True is successful, False otherwise """ validate_schema(name='r_dids', obj=files, vo=vo) rse_id = get_rse_id(rse=rse, vo=vo, session=session) kwargs = {'rse': rse, 'rse_id': rse_id} if not permission.has_permission(issuer=issuer, vo=vo, action='delete_replicas', kwargs=kwargs, session=session): raise exception.AccessDenied( 'Account %s can not delete file replicas on %s' % (issuer, rse)) if not permission.has_permission(issuer=issuer, vo=vo, action='skip_availability_check', kwargs=kwargs, session=session): ignore_availability = False for f in files: f['scope'] = InternalScope(f['scope'], vo=vo) replica.delete_replicas(rse_id=rse_id, files=files, ignore_availability=ignore_availability, session=session)
def add_bad_pfns(pfns, issuer, state, reason=None, expires_at=None, vo='def', session=None): """ Add bad PFNs. :param pfns: the list of new files. :param issuer: The issuer account. :param state: One of the possible states : BAD, SUSPICIOUS, TEMPORARY_UNAVAILABLE. :param reason: A string describing the reason of the loss. :param expires_at: Specify a timeout for the TEMPORARY_UNAVAILABLE replicas. None for BAD files. :param vo: The VO to act on. :param session: The database session in use. :returns: True is successful. """ kwargs = {'state': state} if not permission.has_permission(issuer=issuer, vo=vo, action='add_bad_pfns', kwargs=kwargs, session=session): raise exception.AccessDenied('Account %s can not declare bad PFNs' % (issuer)) if expires_at and datetime.datetime.utcnow( ) <= expires_at and expires_at > datetime.datetime.utcnow( ) + datetime.timedelta(days=30): raise exception.InputValidationError( 'The given duration of %s days exceeds the maximum duration of 30 days.' % (expires_at - datetime.datetime.utcnow()).days) issuer = InternalAccount(issuer, vo=vo) return replica.add_bad_pfns(pfns=pfns, account=issuer, state=state, reason=reason, expires_at=expires_at, session=session)
def declare_bad_file_replicas(pfns, reason, issuer, vo='def'): """ Declare a list of bad replicas. :param pfns: Either a list of PFNs (string) or a list of replicas {'scope': <scope>, 'name': <name>, 'rse_id': <rse_id>}. :param reason: The reason of the loss. :param issuer: The issuer account. :param vo: The VO to act on. """ kwargs = {} rse_map = {} if not permission.has_permission(issuer=issuer, vo=vo, action='declare_bad_file_replicas', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not declare bad replicas' % (issuer)) issuer = InternalAccount(issuer, vo=vo) type_ = type(pfns[0]) if len(pfns) > 0 else None for pfn in pfns: if not isinstance(pfn, type_): raise exception.InvalidType( 'The PFNs must be either a list of string or list of dict') if type_ == dict: rse = pfn['rse'] if rse not in rse_map: rse_id = get_rse_id(rse=rse, vo=vo) rse_map[rse] = rse_id pfn['rse_id'] = rse_map[rse] pfn['scope'] = InternalScope(pfn['scope'], vo=vo) replicas = replica.declare_bad_file_replicas(pfns=pfns, reason=reason, issuer=issuer, status=BadFilesStatus.BAD) for k in list(replicas): try: rse = get_rse_name(rse_id=k) replicas[rse] = replicas.pop(k) except exception.RSENotFound: pass return replicas
def add_distance(source, destination, issuer, vo='def', ranking=None, distance=None, geoip_distance=None, active=None, submitted=None, finished=None, failed=None, transfer_speed=None): """ Add a src-dest distance. :param source: The source. :param destination: The destination. :param issuer: The issuer account. :param vo: The VO to act on. :param ranking: Ranking as an integer. :param distance: Distance as an integer. :param geoip_distance: GEOIP Distance as an integer. :param active: Active FTS transfers as an integer. :param submitted: Submitted FTS transfers as an integer. :param finished: Finished FTS transfers as an integer. :param failed: Failed FTS transfers as an integer. :param transfer_speed: FTS transfer speed as an integer. """ kwargs = {'source': source, 'destination': destination} if not permission.has_permission( issuer=issuer, vo=vo, action='add_distance', kwargs=kwargs): raise exception.AccessDenied('Account %s can not add RSE distances' % (issuer)) return distance_module.add_distance( src_rse_id=rse_module.get_rse_id(source, vo=vo), dest_rse_id=rse_module.get_rse_id(destination, vo=vo), ranking=ranking, agis_distance=distance, geoip_distance=geoip_distance, active=active, submitted=submitted, finished=finished, failed=failed, transfer_speed=transfer_speed)
def get_auth_token_user_pass(account, username, password, appid, ip=None): """ Authenticate a Rucio account temporarily via username and password. The token lifetime is 1 hour. :param account: Account identifier as a string. :param username: Username as a string. :param password: SHA1 hash of the password as a string. :param appid: The application identifier as a string. :param ip: IP address of the client as a string. :returns: Authentication token as a variable-length string. """ kwargs = {'account': account, 'username': username, 'password': password} if not permission.has_permission(issuer=account, action='get_auth_token_user_pass', kwargs=kwargs): raise exception.AccessDenied('User with identity %s can not log to account %s' % (username, account)) return authentication.get_auth_token_user_pass(account, username, password, appid, ip)
def delete_replicas(rse, files, issuer, ignore_availability=False): """ Bulk delete file replicas. :param rse: The RSE name. :param files: The list of files. :param issuer: The issuer account. :param ignore_availability: Ignore the RSE blacklisting. :returns: True is successful, False otherwise """ validate_schema(name='r_dids', obj=files) kwargs = {'rse': rse} if not permission.has_permission(issuer=issuer, action='delete_replicas', kwargs=kwargs): raise exception.AccessDenied('Account %s can not delete file replicas on %s' % (issuer, rse)) if not permission.has_permission(issuer=issuer, action='skip_availability_check', kwargs=kwargs): ignore_availability = False replica.delete_replicas(rse=rse, files=files, ignore_availability=ignore_availability)
def get_ssh_challenge_token(account, appid, ip=None): """ Get a challenge token for subsequent SSH public key authentication. The challenge token lifetime is 5 seconds. :param account: Account identifier as a string. :param appid: The application identifier as a string. :param ip: IP address of the client as a string. :returns: Challenge token as a variable-length string. """ kwargs = {'account': account} if not permission.has_permission( issuer=account, action='get_ssh_challenge_token', kwargs=kwargs): raise exception.AccessDenied( 'User can not get challenge token for account %s' % account) return authentication.get_ssh_challenge_token(account, appid, ip)
def add_qos_policy(rse, qos_policy, issuer, vo='def'): """ Add a QoS policy from an RSE. :param rse: The name of the RSE. :param qos_policy: The QoS policy to add. :param issuer: The issuer account. :param vo: The VO to act on. :raises Duplicate: If the QoS policy already exists. :returns: True if successful, except otherwise. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo) kwargs = {'rse_id': rse_id} if not permission.has_permission(issuer=issuer, action='add_qos_policy', kwargs=kwargs): raise exception.AccessDenied('Account %s cannot add QoS policies to RSE %s' % (issuer, rse)) return rse_module.add_qos_policy(rse_id, qos_policy)
def add_section(section, issuer=None, vo='def', session=None): """ Add a section to the configuration. :param section: The name of the section. :param issuer: The issuer account. :param session: The database session in use. :param vo: The VO to act on. """ kwargs = {'issuer': issuer, 'section': section} if not permission.has_permission(issuer=issuer, vo=vo, action='config_add_section', kwargs=kwargs, session=session): raise exception.AccessDenied('%s cannot add section %s' % (issuer, section)) return config.add_section(section, session=session)
def del_rse(rse, issuer, vo='def', session=None): """ Disables an RSE with the provided RSE name. :param rse: The RSE name. :param issuer: The issuer account. :param vo: The VO to act on. :param session: The database session in use. """ rse_id = rse_module.get_rse_id(rse=rse, vo=vo, session=session) kwargs = {'rse': rse, 'rse_id': rse_id} if not permission.has_permission( issuer=issuer, vo=vo, action='del_rse', kwargs=kwargs, session=session): raise exception.AccessDenied('Account %s can not delete RSE' % (issuer)) return rse_module.del_rse(rse_id, session=session)
def get_request_by_did(scope, name, rse, issuer): """ Retrieve a request by its DID for a destination RSE. :param scope: The scope of the data identifier as a string. :param name: The name of the data identifier as a string. :param rse: The destination RSE of the request as a string. :param issuer: Issuing account as a string. :returns: Request as a dictionary. """ kwargs = {'scope': scope, 'name': name, 'rse': rse, 'issuer': issuer} if not permission.has_permission( issuer=issuer, action='get_request_by_did', kwargs=kwargs): raise exception.AccessDenied( '%(issuer)s cannot retrieve the request DID %(scope)s:%(name)s to RSE %(rse)s' % locals()) return request.get_request_by_did(scope, name, rse)