Esempio n. 1
0
    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 ['']
Esempio n. 2
0
    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
Esempio n. 3
0
    def add_user_to_cloud_storage(self, storage_name, start_response):
        """
        Add a user or a VO credentials to the storage
        """
        storage = Session.query(CloudStorage).get(storage_name)
        if not storage:
            raise HTTPNotFound('The storage does not exist')

        input_dict = get_input_as_dict(request)
        if not input_dict.get('user_dn', None) and not input_dict.get('vo_name', None):
            raise HTTPBadRequest('One of user_dn or vo_name must be specified')
        elif input_dict.get('user_dn', None) and input_dict.get('vo_name', None):
            raise HTTPBadRequest('Only one of user_dn or vo_name must be specified')

        cuser = CloudStorageUser(
            user_dn=input_dict.get('user_dn', ''),
            storage_name=storage_name,
            access_token=input_dict.get('access_key', input_dict.get('access_token', None)),
            access_token_secret=input_dict.get('secret_key', input_dict.get('access_token_secret', None)),
            request_token=input_dict.get('request_token'),
            request_token_secret=input_dict.get('request_token_secret'),
            vo_name=input_dict.get('vo_name', ''),
        )

        try:
            Session.merge(cuser)
            Session.commit()
        except:
            Session.rollback()
            raise

        start_response('201 Created', [])
        return dict(storage_name=cuser.storage_name, user_dn=cuser.user_dn, vo_name=cuser.vo_name)
Esempio n. 4
0
    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 ['']
Esempio n. 5
0
    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))
Esempio n. 6
0
    def submit(self):
        """
        Submits a new job

        It returns the information about the new submitted job. To know the format for the
        submission, /api-docs/schema/submit gives the expected format encoded as a JSON-schema.
        It can be used to validate (i.e in Python, jsonschema.validate)
        """
        # First, the request has to be valid JSON
        submitted_dict = get_input_as_dict(request)

        # The auto-generated delegation id must be valid
        user = request.environ['fts3.User.Credentials']
        credential = Session.query(Credential).get((user.delegation_id, user.user_dn))
        if credential is None:
            raise HTTPAuthenticationTimeout('No delegation found for "%s"' % user.user_dn)
        if credential.expired():
            remaining = credential.remaining()
            seconds = abs(remaining.seconds + remaining.days * 24 * 3600)
            raise HTTPAuthenticationTimeout(
                'The delegated credentials expired %d seconds ago (%s)' % (seconds, user.delegation_id)
            )
        if user.method != 'oauth2' and credential.remaining() < timedelta(hours=1):
            raise HTTPAuthenticationTimeout(
                'The delegated credentials has less than one hour left (%s)' % user.delegation_id
            )

        # Populate the job and files
        populated = JobBuilder(user, **submitted_dict)

        log.info("%s (%s) is submitting a transfer job" % (user.user_dn, user.vos[0]))

        # Insert the job
        try:
            try:
                Session.execute(Job.__table__.insert(), [populated.job])
            except IntegrityError:
                raise HTTPConflict('The sid provided by the user is duplicated')
            if len(populated.files):
                Session.execute(File.__table__.insert(), populated.files)
            if len(populated.datamanagement):
                Session.execute(DataManagement.__table__.insert(), populated.datamanagement)
            Session.flush()
            Session.commit()
        except IntegrityError as err:
            Session.rollback()
            raise HTTPConflict('The submission is duplicated '+ str(err))
        except:
            Session.rollback()
            raise

        # Send messages
        # Need to re-query so we get the file ids
        job = Session.query(Job).get(populated.job_id)
        for i in range(len(job.files)):
            try:
                submit_state_change(job, job.files[i], populated.files[0]['file_state'])
            except Exception, e:
                log.warning("Failed to write state message to disk: %s" % e.message)
Esempio n. 7
0
    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)
Esempio n. 8
0
 def list_authz(self):
     """
     List granted accesses
     """
     input_dict = get_input_as_dict(request, from_query=True)
     dn = input_dict.get('dn')
     op = input_dict.get('operation')
     authz = Session.query(AuthorizationByDn)
     if dn:
         authz = authz.filter(AuthorizationByDn.dn == dn)
     if op:
         authz = authz.filter(AuthorizationByDn.operation == op)
     return authz.all()
Esempio n. 9
0
    def set_optimizer_values(self):
        """
        Set the number of actives and streams
        """
        input_dict = get_input_as_dict(request)
        source_se = input_dict.get('source_se', None)
        dest_se = input_dict.get('dest_se', None)
        rationale = input_dict.get('rationale', None)

        current_time = datetime.utcnow()
        if not source_se or not dest_se:
            raise HTTPBadRequest('Missing source and/or destination')

        try:
            active = int(input_dict.get('active', 2))
        except Exception, e:
            raise HTTPBadRequest('Active must be an integer (%s)' % str(e))
Esempio n. 10
0
    def delete_vo_global_config(self, start_response):
        """
        Delete the global configuration for the given VO
        """
        input_dict = get_input_as_dict(request, from_query=True)
        vo_name = input_dict.get('vo_name')
        if not vo_name or vo_name == '*':
            raise HTTPBadRequest('Missing VO name')

        try:
            Session.query(ServerConfig).filter(
                ServerConfig.vo_name == vo_name).delete()
            Session.commit()
        except:
            Session.rollback()
            raise

        start_response('204 No Content', [])
Esempio n. 11
0
    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
Esempio n. 12
0
    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))
Esempio n. 13
0
    def set_cloud_storage(self, start_response):
        """
        Add or modify a cloud storage entry
        """
        input_dict = get_input_as_dict(request)
        if 'storage_name' not in input_dict:
            raise HTTPBadRequest('Missing storage name')

        storage = CloudStorage(
            storage_name=input_dict.get('storage_name'),
            app_key=input_dict.get('app_key', None),
            app_secret=input_dict.get('app_secret', None),
            service_api_url=input_dict.get('service_api_url', None)
        )
        try:
            Session.merge(storage)
            Session.commit()
        except:
            Session.rollback()
            raise
        start_response('201 Created', [])
        return storage.storage_name
Esempio n. 14
0
    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
Esempio n. 15
0
    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()
Esempio n. 16
0
                else:
                    setattr(job, 'http_status', '304 Not Modified')
                    setattr(job, 'http_message',
                            'The job is in a terminal state')
                    log.warning(
                        "The job %s can not be modified, since it is %s" %
                        (job_id, job.job_state))
                    responses.append(job)
            except HTTPClientError, e:
                responses.append(
                    dict(job_id=job_id,
                         http_status="%s %s" % (e.code, e.title),
                         http_message=e.detail))

        # Now, modify those that can be
        modification = get_input_as_dict(request)

        priority = None
        try:
            priority = int(modification['params']['priority'])
        except KeyError:
            pass
        except ValueError:
            raise HTTPBadRequest('Invalid priority value')

        try:
            for job in modifiable_jobs:
                if priority:
                    for file in job.files:
                        file.priority = priority
                        file = Session.merge(file)