def set_activity_shares(self): """ Set a new/modify an activity share """ input_dict = get_input_as_dict(request) if not input_dict.get('vo', None): raise HTTPBadRequest('Missing VO') if not input_dict.get('share', None): raise HTTPBadRequest('Missing share') if 'active' not in input_dict: input_dict['active'] = True input_dict['share'] = _normalize_activity_share_format( input_dict['share']) # Make sure the share weights are numbers for entry in input_dict['share']: for key, value in entry.iteritems(): if not type(value) in (float, int): raise HTTPBadRequest('Share weight must be a number') try: activity_share = ActivityShare(vo=input_dict['vo'], active=input_dict['active'], activity_share=input_dict['share']) Session.merge(activity_share) audit_configuration('activity-share', json.dumps(input_dict)) Session.commit() except ValueError, e: raise HTTPBadRequest(str(e))
def remove_authz(self, start_response): """ Revoke access for a DN for a given operation, or all """ input_dict = get_input_as_dict(request, from_query=True) dn = input_dict.get('dn') op = input_dict.get('operation') if not dn: raise HTTPBadRequest('Missing DN parameter') to_be_removed = Session.query(AuthorizationByDn).filter( AuthorizationByDn.dn == dn) if op: to_be_removed = to_be_removed.filter( AuthorizationByDn.operation == op) try: to_be_removed.delete() if op: audit_configuration('revoke', '%s revoked for "%s"' % (op, dn)) else: audit_configuration('revoke', 'All revoked for "%s"' % dn) Session.commit() except: Session.rollback() raise start_response('204 No Content', []) return ['']
def set_drain(self): """ Set the drain status of a server """ input_dict = get_input_as_dict(request) hostname = input_dict.get('hostname', None) drain = input_dict.get('drain', True) if not isinstance(drain, bool) or not isinstance(hostname, basestring): raise HTTPBadRequest('Invalid drain request') entries = Session.query(Host).filter(Host.hostname == hostname).all() if not entries: raise HTTPBadRequest('Host not found') try: audit_configuration( 'drain', 'Turning drain %s the drain mode for %s' % (drain, hostname)) for entry in entries: entry.drain = drain Session.merge(entry) Session.commit() except: Session.rollback() raise
def delete_share(self, start_response): """ Delete a share """ input_dict = get_input_as_dict(request, from_query=True) source = input_dict.get('source') destination = input_dict.get('destination') vo = input_dict.get('vo') if not source or not destination or not vo: raise HTTPBadRequest('Missing source, destination and/or vo') try: share = Session.query(ShareConfig).get((source, destination, vo)) if share: Session.delete(share) audit_configuration( 'share-delete', 'Share %s, %s, %s has been deleted' % (source, destination, vo)) Session.commit() except: Session.rollback() raise start_response('204 No Content', []) return ['']
def ban_dn(self): """ Ban a user """ if request.content_type == 'application/json': try: input_dict = json.loads(request.body) except Exception: raise HTTPBadRequest('Malformed input') else: input_dict = request.params user = request.environ['fts3.User.Credentials'] dn = input_dict.get('user_dn', None) if not dn: raise HTTPBadRequest('Missing dn parameter') if dn == user.user_dn: raise HTTPConflict('The user tried to ban (her|his)self') _ban_dn(dn, input_dict.get('message', '')) affected = _cancel_jobs(dn=dn) audit_configuration('ban-dn', "User %s banned" % (dn)) log.warn("User %s banned, %d jobs affected" % (dn, len(affected))) return affected
def set_se_config(self): """ Set the configuration parameters for a given SE """ input_dict = get_input_as_dict(request) try: for storage, cfg in input_dict.iteritems(): if not storage or storage.isspace(): raise ValueError se_info = None se_info_new = cfg.get('se_info', None) if se_info_new: se_info = Session.query(Se).get(storage) if not se_info: se_info = Se(storage=storage) for key, value in se_info_new.iteritems(): #value = validate_type(Se, key, value) setattr(se_info, key, value) audit_configuration( 'set-se-config', 'Set config %s: %s' % (storage, json.dumps(cfg))) Session.merge(se_info) # Operation limits operations = cfg.get('operations', None) if operations: for vo, limits in operations.iteritems(): for op, limit in limits.iteritems(): limit = int(limit) new_limit = Session.query(OperationConfig).get( (vo, storage, op)) if limit > 0: if not new_limit: new_limit = OperationConfig( vo_name=vo, host=storage, operation=op) new_limit.concurrent_ops = limit Session.merge(new_limit) elif new_limit: Session.delete(new_limit) audit_configuration( 'set-se-limits', 'Set limits for %s: %s' % (storage, json.dumps(operations))) Session.commit() except (AttributeError, ValueError): Session.rollback() raise HTTPBadRequest('Malformed configuration') except: Session.rollback() raise return (se_info, operations)
def delete_link_config(self,sym_name, start_response): """ Deletes an existing link configuration """ try: sym_name = urllib.unquote(sym_name) Session.query(LinkConfig).filter(LinkConfig.symbolicname == sym_name).delete() audit_configuration('link-delete', 'Link %s has been deleted' % sym_name) Session.commit() except: Session.rollback() raise start_response('204 No Content', []) return ['']
def delete_activity_shares(self, vo_name, start_response): """ Delete an existing activity share """ activity_share = Session.query(ActivityShare).get(vo_name) if activity_share is None: raise HTTPNotFound('No activity shares for %s' % vo_name) try: Session.delete(activity_share) audit_configuration('activity-share', 'Activity share removed for "%s"' % (vo_name)) Session.commit() except: Session.rollback() raise start_response('204 No Content', []) return ['']
def set_share(self, start_response): """ Add or modify a share """ input_dict = get_input_as_dict(request) source = input_dict.get('source') destination = input_dict.get('destination') vo = input_dict.get('vo') try: share = int(input_dict.get('share')) if share < 0: raise HTTPBadRequest('Shares values cannot be negative') except: raise HTTPBadRequest('Bad share value') if not source or not destination or not vo or not share: raise HTTPBadRequest( 'Missing source, destination, vo and/or share') source = urlparse(source) if not source.scheme or not source.hostname: raise HTTPBadRequest('Invalid source') source = "%s://%s" % (source.scheme, source.hostname) destination = urlparse(destination) if not destination.scheme or not destination.hostname: raise HTTPBadRequest('Invalid source') destination = "%s://%s" % (destination.scheme, destination.hostname) try: share_cfg = ShareConfig(source=source, destination=destination, vo=vo, share=share) Session.merge(share_cfg) audit_configuration( 'share-set', 'Share %s, %s, %s has been set to %d' % (source, destination, vo, share)) Session.commit() except: Session.rollback() raise return share
def ban_se(self): """ Ban a storage element. Returns affected jobs ids. """ if request.content_type == 'application/json': try: input_dict = json.loads(request.body) except Exception: raise HTTPBadRequest('Malformed input') else: input_dict = request.params storage = input_dict.get('storage', None) if not storage: raise HTTPBadRequest('Missing storage parameter') user = request.environ['fts3.User.Credentials'] vo_name = user.vos[0] allow_submit = bool(input_dict.get('allow_submit', False)) status = input_dict.get('status', 'cancel').upper() if status not in ['CANCEL', 'WAIT']: raise HTTPBadRequest('status can only be cancel or wait') if allow_submit and status == 'CANCEL': raise HTTPBadRequest( 'allow_submit and status = CANCEL can not be combined') _ban_se(storage, vo_name, allow_submit, status, input_dict.get('message', '')) audit_configuration( 'ban-se', "Storage %s for %s banned (%s)" % (storage, vo_name, status)) if status == 'CANCEL': affected = _cancel_transfers(storage=storage, vo_name=vo_name) else: affected = _set_to_wait(storage=storage, vo_name=vo_name) log.warn("Storage %s banned (%s), %d jobs affected" % (storage, status, len(affected))) return affected
def unban_se(self, start_response): """ Unban a storage element """ storage = request.params.get('storage', None) if not storage: raise HTTPBadRequest('Missing storage parameter') job_ids = [] try: user = request.environ['fts3.User.Credentials'] vo_name = user.vos[0] Session.query(BannedSE).filter(BannedSE.se == storage, BannedSE.vo == vo_name).delete() job_ids = _reenter_queue(storage, vo_name) Session.commit() except Exception: Session.rollback() raise HTTPBadRequest('Storage not found') log.warn("Storage %s unbanned" % storage) audit_configuration('unban-se', "Storage %s unbanned" % storage) start_response('204 No Content', []) return job_ids
def add_authz(self): """ Give special access to someone """ input_dict = get_input_as_dict(request) dn = input_dict.get('dn') op = input_dict.get('operation') if not dn or not op: raise HTTPBadRequest('Missing dn and/or operation') try: authz = Session.query(AuthorizationByDn).get((dn, op)) if not authz: authz = AuthorizationByDn(dn=dn, operation=op) audit_configuration('authorize', '%s granted to "%s"' % (op, dn)) Session.merge(authz) Session.commit() except: Session.rollback() raise return authz
def unban_dn(self, start_response): """ Unban a user """ dn = request.params.get('user_dn', None) if not dn: raise HTTPBadRequest('Missing user_dn parameter') banned = Session.query(BannedDN).get(dn) if banned: try: Session.delete(banned) Session.commit() except Exception: Session.rollback() log.warn("User %s unbanned" % dn) else: log.warn("Unban of user %s without effect" % dn) audit_configuration('unban-dn', "User %s unbanned" % (dn)) start_response('204 No Content', []) return ['']
def set_global_config(self): """ Set the global configuration """ cfg = get_input_as_dict(request) vo_name = cfg.get('vo_name', '*') db_cfg = Session.query(ServerConfig).get(vo_name) if not db_cfg: db_cfg = ServerConfig(vo_name=vo_name) for key, value in cfg.iteritems(): value = validate_type(ServerConfig, key, value) setattr(db_cfg, key, value) Session.merge(db_cfg) audit_configuration('set-globals', to_json(db_cfg, indent=None)) try: Session.commit() except: Session.rollback() raise return self.get_global_config()
class LinkConfigController(BaseController): """ Link configuration """ @doc.response(400, 'Invalid values passed in the request') @doc.response(403, 'The user is not allowed to query the configuration') @authorize(CONFIG) @jsonify def set_link_config(self): """ Set the configuration for a given link """ input_dict = get_input_as_dict(request) source = input_dict.get('source', '*') destination = input_dict.get('destination', '*') symbolicname = input_dict.get('symbolicname', None) if not symbolicname: raise HTTPBadRequest('Missing symbolicname') link_cfg = Session.query(LinkConfig).filter(LinkConfig.symbolicname == symbolicname).first() try: min_active = int(input_dict.get('min_active', 2)) max_active = int(input_dict.get('max_active', 2)) except Exception, e: raise HTTPBadRequest('Active must be an integer (%s)' % str(e)) if not source or not destination: raise HTTPBadRequest('Missing source and/or destination') if min_active is None: raise HTTPBadRequest('Missing min_active') if max_active is None: raise HTTPBadRequest('Missing max_active') if min_active > max_active: raise HTTPBadRequest('max_active is lower than min_active') if not link_cfg: link_cfg = LinkConfig( source=source, destination=destination, symbolicname=symbolicname, min_active = min_active, max_active = max_active ) for key, value in input_dict.iteritems(): #value = validate_type(LinkConfig, key, value) setattr(link_cfg, key, value) audit_configuration('link', json.dumps(input_dict)) Session.merge(link_cfg) try: Session.commit() except: Session.rollback() raise return link_cfg