コード例 #1
0
ファイル: CampaignActions.py プロジェクト: franzoni/cmsPdmV
    def get_cmsDriver(self, data):
        try:
            camp_mcm = campaign(json_input=data)
        except campaign.IllegalAttributeName as ex:
            return {"results":''}

        return {"results":camp_mcm.build_cmsDrivers()}
コード例 #2
0
ファイル: CampaignActions.py プロジェクト: franzoni/cmsPdmV
    def create_campaign(self, data):
        db = database('campaigns')
        try:
            camp_mcm = campaign(json_input=threaded_loads(data))
        except campaign.IllegalAttributeName as ex:
            return {"results":False}

        #id = RequestPrepId().generate_prepid(self.json['pwg'], self.json['member_of_campaign'])
        #self.json['prepid'] = loads(id)['prepid']
        if not camp_mcm.get_attribute('prepid'):
            self.logger.error('Invalid prepid: Prepid returned None')
            return {"results":False}

        if '_' in camp_mcm.get_attribute('prepid'):
            self.logger.error('Invalid campaign name %s'%(camp_mcm.get_attribute('prepid')))
            return {"results":False}

        camp_mcm.set_attribute('_id', camp_mcm.get_attribute('prepid'))

        camp_mcm.update_history({'action':'created'})

        ## this is to create, not to update
        if db.document_exists( camp_mcm.get_attribute('prepid') ):
            return {"results":False}

        # save to db
        if not db.save(camp_mcm.json()):
            self.logger.error('Could not save object to database')
            return {"results":False}

        # create dedicated chained campaign
        self.create_chained_campaign(camp_mcm.get_attribute('_id'), db)

        return {"results":True}
コード例 #3
0
ファイル: RequestPrepId.py プロジェクト: gourangakole/cmsPdmV
 def next_prepid(self, pwg, camp):
     if not pwg or not camp:
         return None
     with locker.lock("{0}-{1}".format(pwg, camp)):
         db = database(self.db_name)
         query_results = db.raw_query('serial_number', {
             'group': True,
             'key': [camp, pwg]
         })
         sn = 1
         if query_results:
             sn = query_results[0]['value'] + 1
         pid = '%s-%s-%05d' % (pwg, camp, sn)
         if sn == 1:
             self.logger.info('Beginning new prepid family: %s-%s' %
                              (pwg, camp))
         db_camp = database('campaigns', cache_enabled=True)
         req_camp = campaign(db_camp.get(camp))
         new_request = request(
             req_camp.add_request({
                 '_id': pid,
                 'prepid': pid,
                 'pwg': pwg,
                 'member_of_campaign': camp
             }))
         new_request.update_history({'action': 'created'})
         db.save(new_request.json())
         self.logger.info('New prepid : %s ' % pid)
         return pid
コード例 #4
0
ファイル: CampaignActions.py プロジェクト: cms-PdmV/cmsPdmV
    def post(self):
        """
        Change campaign hold status. Content type 'application/json' must be set.
        Request is a JSON with 'prepid' and 'on_hold' (0/1) attributes.
        """
        data = flask.request.data
        try:
            data_json = loads(data)
            campaign_name = data_json['prepid']
            campaign_hold = int(data_json['on_hold'])
        except:
            return self.form_response({'error': 'Request must have \'prepid\' and \'on_hold\' attributes'}, code=400)

        if campaign_hold != 0 and campaign_hold != 1:
            return self.form_response({'error': 'campaign_hold must be (0/1) or (true/false)'}, code=400)

        db = database('campaigns')
        if not db.document_exists(campaign_name):
            return self.form_response({'error': 'Campaign %s is not found' % (campaign_name)}, code=404)

        camp = campaign(json_input=db.get(campaign_name))
        camp.set_attribute('on_hold', campaign_hold)
        result = db.update(camp.json())
        if result:
            return self.form_response({'result': 'success'}, code=200)
        else:
            return self.form_response({'result': 'failure'}, code=500)
コード例 #5
0
 def are_campaigns_correct(self, next_c, allowed_c, cdb):
     if next_c:
         if not cdb.document_exists(next_c):
             return {
                 "results":
                 False,
                 "message":
                 '{0} is not a valid campaign for next'.format(next_c)
             }
         next_mcm_c = campaign(cdb.get(next_c))
         if not self.is_energy_consistent(next_mcm_c, allowed_c, cdb):
             return {
                 "results":
                 False,
                 "message":
                 'Next campaign {0} and allowed campaigns have inconsistent energies'
                 .format(next_c)
             }
         ##consistency check
         if next_c in allowed_c:
             return {
                 "results": False,
                 "message":
                 "Cannot have next campaign in the allowed campaign"
             }
     return True
コード例 #6
0
    def update_campaign(self, data):
        if '_rev' not in data:
            return {
                "results": False,
                'message': 'There is no previous revision provided'
            }
        try:
            camp_mcm = campaign(json_input=data)
        except campaign.IllegalAttributeName:
            return {"results": False}

        if not camp_mcm.get_attribute('prepid') and not camp_mcm.get_attribute(
                '_id'):
            raise ValueError('Prepid returned was None')

        # cast schema evolution of sequences
        sequences = camp_mcm.get_attribute('sequences')
        for steps in sequences:
            for label in steps:
                steps[label] = sequence(steps[label]).json()
        camp_mcm.set_attribute('sequences', sequences)

        # create dedicated chained campaign
        self.create_chained_campaign(camp_mcm.get_attribute('_id'),
                                     camp_mcm.get_attribute('root'))
        camp_mcm.update_history({'action': 'update'})
        return self.save_campaign(camp_mcm)
コード例 #7
0
    def create_campaign(self, data):
        db = database('campaigns')
        try:
            camp_mcm = campaign(json_input=loads(data))
        except campaign.IllegalAttributeName as ex:
            return {"results": False}

        if not camp_mcm.get_attribute('prepid'):
            self.logger.error('Invalid prepid: Prepid returned None')
            return {"results": False}

        if '_' in camp_mcm.get_attribute('prepid'):
            self.logger.error('Invalid campaign name %s' %
                              (camp_mcm.get_attribute('prepid')))
            return {"results": False}

        camp_mcm.set_attribute('_id', camp_mcm.get_attribute('prepid'))

        camp_mcm.update_history({'action': 'created'})

        # this is to create, not to update
        if db.document_exists(camp_mcm.get_attribute('prepid')):
            return {"results": False}

        # save to db
        if not db.save(camp_mcm.json()):
            self.logger.error('Could not save object to database')
            return {"results": False}

        # create dedicated chained campaign
        self.create_chained_campaign(camp_mcm.get_attribute('_id'), db)

        return {"results": True}
コード例 #8
0
    def get_cmsDriver(self, data):
        try:
            camp_mcm = campaign(json_input=data)
        except campaign.IllegalAttributeName:
            return {"results": ''}

        return {"results": camp_mcm.build_cmsDrivers()}
コード例 #9
0
    def toggle_campaign(self, rid):
        db = database('campaigns')
        if not db.document_exists(rid):
            return {"results": 'Error: The given campaign id does not exist.'}
        camp = campaign(json_input=db.get(rid))
        camp.toggle_approval()

        return {"results": db.update(camp.json())}
コード例 #10
0
ファイル: CampaignActions.py プロジェクト: franzoni/cmsPdmV
    def toggle_campaign(self,  rid):
        db = database('campaigns')
        if not db.document_exists(rid):
            return {"results":'Error: The given campaign id does not exist.'}
        camp = campaign(json_input=db.get(rid))
        camp.toggle_approval()

        return {"results":db.update(camp.json())}
コード例 #11
0
ファイル: FlowActions.py プロジェクト: franzoni/cmsPdmV
 def is_energy_consistent(self, next_c, allowed_c, cdb):
     """
     Checks if the energy of campaigns is consistent (it cannot differ)
     """
     next_energy = next_c.get_attribute('energy')
     for camp in allowed_c:
         mcm_c = campaign(cdb.get(camp))
         if mcm_c.get_attribute('energy') != next_energy:
             return False
     return True
コード例 #12
0
ファイル: CampaignActions.py プロジェクト: franzoni/cmsPdmV
 def toggle_campaign(self,  rid,  index):
     db = database('campaigns')
     if not db.document_exists(rid):
         return {"prepid": rid,  "results":'Error: The given campaign id does not exist.'}
     camp = campaign(json_input=db.get(rid))
     camp.approve(int(index))
     if int(index)==0:
         camp.set_status(0)
     res=db.update(camp.json())
     return {"prepid": rid, "results": res, "approval" : camp.get_attribute('approval')}
コード例 #13
0
 def is_energy_consistent(self, next_c, allowed_c, cdb):
     """
     Checks if the energy of campaigns is consistent (it cannot differ)
     """
     next_energy = next_c.get_attribute('energy')
     for camp in allowed_c:
         mcm_c = campaign(cdb.get(camp))
         if mcm_c.get_attribute('energy') != next_energy:
             return False
     return True
コード例 #14
0
ファイル: FlowActions.py プロジェクト: franzoni/cmsPdmV
 def are_campaigns_correct(self, next_c, allowed_c, cdb):
     if next_c:
         if not cdb.document_exists(next_c):
             return {"results": False, "message": '{0} is not a valid campaign for next'.format(next_c)}
         next_mcm_c = campaign(cdb.get(next_c))
         if not self.is_energy_consistent(next_mcm_c, allowed_c, cdb):
             return {"results": False,
                     "message": 'Next campaign {0} and allowed campaigns have inconsistent energies'.format(next_c)}
         ##consistency check
         if next_c in allowed_c:
             return {"results": False, "message": "Cannot have next campaign in the allowed campaign"}
     return True
コード例 #15
0
    def toggle_campaign(self, rid):
        db = database('campaigns')
        if not db.document_exists(rid):
            return {"results": 'Error: The given campaign id does not exist.'}
        camp = campaign(json_input=db.get(rid))
        try:
            camp.toggle_status()
            saved = db.update(camp.json())
            if saved:
                return {"results": True}
            else:
                return {"results": False, "message": "Could not save request"}

        except Exception as ex:
            return {"results": False, "message": str(ex)}
コード例 #16
0
ファイル: CampaignActions.py プロジェクト: franzoni/cmsPdmV
    def toggle_campaign(self,  rid):
        db = database('campaigns')
        if not db.document_exists(rid):
            return {"results":'Error: The given campaign id does not exist.'}
        camp = campaign(json_input=db.get(rid))
        try:
            camp.toggle_status()
            saved = db.update(camp.json())
            if saved:
                return {"results":True}
            else:
                return {"results":False, "message":"Could not save request"}

        except Exception as ex:
            return {"results":False, "message": str(ex) }
コード例 #17
0
 def toggle_campaign(self, rid, index):
     db = database('campaigns')
     if not db.document_exists(rid):
         return {
             "prepid": rid,
             "results": 'Error: The given campaign id does not exist.'
         }
     camp = campaign(json_input=db.get(rid))
     camp.approve(int(index))
     if int(index) == 0:
         camp.set_status(0)
     res = db.update(camp.json())
     return {
         "prepid": rid,
         "results": res,
         "approval": camp.get_attribute('approval')
     }
コード例 #18
0
ファイル: RequestPrepId.py プロジェクト: srimanob/cmsPdmV
 def next_prepid(self, pwg, camp):
     if not pwg or not camp:
         return None
     with locker.lock("{0}-{1}".format(pwg, camp)):
         db = database(self.db_name)
         query_results = db.raw_query('serial_number', {'group':True, 'key':[camp, pwg]})
         sn = 1
         if query_results:
             sn = query_results[0]['value']+1
         pid='%s-%s-%05d'%( pwg, camp , sn)
         if sn==1:
             self.logger.log('Beginning new prepid family: %s-%s' %( pwg, camp))
         db_camp = database('campaigns', cache=True)
         req_camp = campaign(db_camp.get(camp))
         new_request = request(req_camp.add_request({'_id':pid, 'prepid':pid, 'pwg':pwg, 'member_of_campaign':camp}))
         new_request.update_history({'action':'created'})
         db.save(new_request.json())
         self.logger.log('New prepid : %s '%pid)
         return pid
コード例 #19
0
ファイル: CampaignActions.py プロジェクト: cms-PdmV/cmsPdmV
    def update_campaign(self, data):
        if '_rev' not in data:
            return {"results": False, 'message': 'There is no previous revision provided'}
        try:
            camp_mcm = campaign(json_input=data)
        except campaign.IllegalAttributeName:
            return {"results": False}

        if not camp_mcm.get_attribute('prepid') and not camp_mcm.get_attribute('_id'):
            raise ValueError('Prepid returned was None')

        # cast schema evolution of sequences
        sequences = camp_mcm.get_attribute('sequences')
        for steps in sequences:
            for label in steps:
                steps[label] = sequence(steps[label]).json()
        camp_mcm.set_attribute('sequences', sequences)

        # create dedicated chained campaign
        self.create_chained_campaign(camp_mcm.get_attribute('_id'), camp_mcm.get_attribute('root'))
        camp_mcm.update_history({'action': 'update'})
        return self.save_campaign(camp_mcm)
コード例 #20
0
ファイル: FlowActions.py プロジェクト: srimanob/cmsPdmV
    def update_campaigns(self, next_c, allowed, cdb):
        # check to see if next_c is legal
        if not cdb.document_exists(next_c):
            raise ValueError('Campaign ' + str(next_c) + ' does not exist.')

        if not next_c:
            return

        n = cdb.get(next_c)
        if n['root'] == 0:
            raise ValueError('Campaign ' + str(next_c) + ' is a root campaign.')

        # iterate through all allowed campaigns and update the next_c field
        for c in allowed:
            camp = campaign(json_input=cdb.get(c))
            try:
                # append campaign
                camp.add_next(next_c)
            except campaign.CampaignExistsException:
                pass

            # save to database
            cdb.update(camp.json())
コード例 #21
0
    def flow_to_next_step(self,
                          input_dataset='',
                          block_black_list=None,
                          block_white_list=None,
                          check_stats=True,
                          reserve=False):
        if not block_white_list: block_white_list = []
        if not block_black_list: block_black_list = []
        self.logger.log('Flowing chained_request %s to next step...' %
                        (self.get_attribute('_id')))
        if not self.get_attribute('chain'):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'chained_request %s has got no root' %
                (self.get_attribute('_id')))

        # check on the approval of the chained request before all
        ## let it be flowing regardless
        #if self.get_attribute('approval') == 'none':
        #    raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
        #                                                 'The approval of the chained request is none, and therefore flow cannot happen')

        #this operation requires to access all sorts of objects
        rdb = database('requests')
        cdb = database('campaigns')
        ccdb = database('chained_campaigns')
        crdb = database('chained_requests')
        fdb = database('flows')
        adb = database('actions')

        l_type = locator()

        current_step = len(self.get_attribute(
            'chain')) - 1 if reserve else self.get_attribute('step')
        current_id = self.get_attribute('chain')[current_step]
        next_step = current_step + 1

        if not rdb.document_exists(current_id):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'the request %s does not exist' % current_id)

        current_request = request(rdb.get(current_id))
        current_campaign = campaign(
            cdb.get(current_request.get_attribute('member_of_campaign')))

        if not ccdb.document_exists(self.get_attribute('member_of_campaign')):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'the chain request %s is member of %s that does not exist' %
                (self.get_attribute('_id'),
                 self.get_attribute('member_of_campaign')))
        mcm_cc = ccdb.get(self.get_attribute('member_of_campaign'))
        if next_step >= len(mcm_cc['campaigns']):
            if reserve: return False
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'chained_campaign %s does not allow any further flowing.' %
                (self.get_attribute('member_of_campaign')))

        if not reserve:
            ## is the current request in the proper approval
            allowed_request_approvals = ['submit']
            if current_request.get_attribute(
                    'approval') not in allowed_request_approvals:
                raise self.NotApprovedException(
                    current_request.get_attribute('prepid'),
                    current_request.get_attribute('approval'),
                    allowed_request_approvals)
            ## is the current request in the proper status
            allowed_request_statuses = ['submitted', 'done']
            if current_request.get_attribute(
                    'status') not in allowed_request_statuses:
                raise self.NotInProperStateException(
                    current_request.get_attribute('prepid'),
                    current_request.get_attribute('status'),
                    allowed_request_statuses)

        original_action_id = self.get_attribute('chain')[0]

        original_action_item = self.retrieve_original_action_item(
            adb, original_action_id)

        ## what is the campaign to go to next and with which flow
        (next_campaign_id, flow_name) = mcm_cc['campaigns'][next_step]
        if not fdb.document_exists(flow_name):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'The flow %s does not exist' % flow_name)

        mcm_f = flow(fdb.get(flow_name))
        if not 'sequences' in mcm_f.get_attribute('request_parameters'):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'The flow %s does not contain sequences information.' %
                (flow_name))

        if not cdb.document_exists(next_campaign_id):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'The next campaign %s does not exist' % next_campaign_id)

        next_campaign = campaign(cdb.get(next_campaign_id))
        if len(next_campaign.get_attribute('sequences')) != len(
                mcm_f.get_attribute('request_parameters')['sequences']):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'the sequences changes in flow %s are not consistent with the next campaign %s'
                % (flow_name, next_campaign_id))

        if next_campaign.get_attribute(
                'energy') != current_campaign.get_attribute('energy'):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'cannot flow any further. Request {0} has inconsistent energy.'
                .format(next_campaign.get_attribute("prepid")))

        if not next_campaign.is_release_greater_or_equal_to(
                current_campaign.get_attribute('cmssw_release')):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute("_id"),
                'cannot flow any further. Request {0} has lower release version.'
                .format(next_campaign.get_attribute("prepid")))

        if next_campaign.get_attribute('type') == 'MCReproc' and (
                not 'time_event' in mcm_f.get_attribute('request_parameters')):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'the flow is getting into a MCReproc campaign but not time per event is specified'
            )

        if next_campaign.get_attribute('type') == 'MCReproc' and (
                not 'size_event' in mcm_f.get_attribute('request_parameters')):
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'the flow is getting into a MCReproc campaign but not size per event is specified'
            )

        ## check that it is allowed to flow
        allowed_flow_approvals = ['flow', 'submit']
        ###### cascade of checks
        """
        if not reserve and not mcm_f.get_attribute('approval') in allowed_flow_approvals:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The flow (%s) is not in proper approval state (%s)'%( 
                                                            mcm_f.get_attribute('prepid'),
                                                            mcm_f.get_attribute('approval')))

        if not reserve and not self.get_attribute('approval') in allowed_flow_approvals:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The chained request (%s) is not in the proper approval state (%s)'% (
                                                            self.get_attribute('_id'),
                                                            self.get_attribute('approval')))
        """
        if not reserve and not mcm_f.get_attribute(
                'approval') in allowed_flow_approvals:
            if not self.get_attribute('approval') in allowed_flow_approvals:
                raise self.ChainedRequestCannotFlowException(
                    self.get_attribute('_id'),
                    'Neither the flow (%s) nor the chained request (%s) approvals allow for flowing'
                    % (mcm_f.get_attribute('approval'),
                       self.get_attribute('approval')))

        if next_campaign.get_attribute('status') == 'stopped':
            raise self.CampaignStoppedException(next_campaign_id)

        #what is going to be the required number of events for the next request
        #update the stats to its best
        if not reserve:
            current_request.get_stats()
            next_total_events = current_request.get_attribute(
                'completed_events')
            ## get the original expected events and allow a margin of 5% less statistics
            statistics_fraction = settings().get_value('statistics_fraction')
            current_eff_error = 1. - current_request.get_efficiency_error()
            statistics_fraction = min(statistics_fraction, current_eff_error)
            completed_events_to_pass = int(
                current_request.get_attribute('total_events') *
                statistics_fraction)

            notify_on_fail = True  ## to be tuned according to the specific cases
            if current_request.get_attribute('completed_events') <= 0:
                raise self.ChainedRequestCannotFlowException(
                    self.get_attribute('_id'),
                    'The number of events completed is negative or null')
            else:
                allowed_request_statuses = ['done']
                ## determine if this is a root -> non-root transition to potentially apply staged number
                at_a_transition = (current_campaign.get_attribute('root') != 1
                                   and next_campaign.get_attribute('root')
                                   == 1)
                if ('staged' in original_action_item or 'threshold'
                        in original_action_item) and at_a_transition:
                    allowed_request_statuses.append('submitted')
                ##check status
                if not current_request.get_attribute(
                        'status') in allowed_request_statuses:
                    raise self.NotInProperStateException(
                        current_request.get_attribute('prepid'),
                        current_request.get_attribute('status'),
                        allowed_request_statuses)
                ##special check at transition that the statistics is good enough
                if at_a_transition:
                    # at a root -> non-root transition only does the staged/threshold functions !
                    if 'staged' in original_action_item:
                        next_total_events = int(original_action_item['staged'])
                        completed_events_to_pass = next_total_events
                    if 'threshold' in original_action_item:
                        next_total_events = int(
                            current_request.get_attribute('total_events') *
                            float(original_action_item['threshold'] / 100.))
                        completed_events_to_pass = next_total_events

            if check_stats and (
                    current_request.get_attribute('completed_events') <
                    completed_events_to_pass):
                if notify_on_fail:
                    current_request.notify(
                        'Flowing %s with not enough statistics' %
                        (current_request.get_attribute('prepid')),
                        'For the request %s, the completed statistics %s is not enough to fullfill the requirement to the next level : need at least %s in chain %s \n\n Please report to the operation HN or at the next MccM what action should be taken.\n\n %srequests?prepid=%s\n%schained_requests?contains=%s\n%schained_requests?prepid=%s '
                        % (current_request.get_attribute('prepid'),
                           current_request.get_attribute('completed_events'),
                           completed_events_to_pass,
                           self.get_attribute('prepid'), l_type.baseurl(),
                           current_request.get_attribute('prepid'),
                           l_type.baseurl(),
                           current_request.get_attribute('prepid'),
                           l_type.baseurl(), self.get_attribute('prepid')),
                        accumulate=True)
                raise self.ChainedRequestCannotFlowException(
                    self.get_attribute('_id'),
                    'The number of events completed (%s) is not enough for the requirement (%s)'
                    % (current_request.get_attribute('completed_events'),
                       completed_events_to_pass))

        ## select what is to happened : [create, patch, use]
        next_id = None
        approach = None
        next_request = None
        if next_step != len(self.get_attribute('chain')):
            #not at the end
            next_id = self.get_attribute('chain')[next_step]
            if not rdb.document_exists(next_id):
                raise self.ChainedRequestCannotFlowException(
                    self.get_attribute('_id'),
                    'The next request (%s) according to the step (%s) does not exist'
                    % (next_id, next_step))
            next_request = request(rdb.get(next_id))
            if next_request.get_attribute('status') == 'new':
                #most likely a rewind + resub
                approach = 'patch'
            else:
                ##this is always the case in chains reserved from existing things: so use the next request
                approach = 'use'
                #raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                #'This should never happen. (%s) is next according to step (%s), but is not in new status (%s)' % (
                #next_id, next_step, next_request.get_attribute('status')))
        else:
            ## look in *other* chained campaigns whether you can suck in an existing request
            ## look up all chained requests that start from the same root request
            ## remove <pwg>-chain_ and the -serial number, replacing _ with a .
            toMatch = '.'.join(
                self.get_attribute('prepid').split('_')[1:][0:next_step +
                                                            1]).split('-')[0]
            ## make sure they get ordered by prepid
            related_crs = sorted(crdb.queries(
                ['root_request==%s' % original_action_id]),
                                 key=lambda cr: cr['prepid'])

            vetoed_last = []
            for existing_cr in related_crs:
                ## exclude itself
                if existing_cr['prepid'] == self.get_attribute('prepid'):
                    continue
                ## prevent from using a request from within the same exact chained_campaigns
                if existing_cr['member_of_campaign'] == self.get_attribute(
                        'member_of_campaign'):
                    mcm_cr = chained_request(crdb.get(existing_cr['prepid']))
                    if len(mcm_cr.get_attribute('chain')) > next_step:
                        ## one existing request in the very same chained campaign has already something used, make sure it is not going to be used
                        vetoed_last.append(
                            mcm_cr.get_attribute('chain')[next_step])
                    continue
                else:
                    continue
            for existing_cr in related_crs:
                ## exclude itself
                if existing_cr['prepid'] == self.get_attribute('prepid'):
                    continue
                ## prevent from using a request from within the same exact chained_campaigns
                if existing_cr['member_of_campaign'] == self.get_attribute(
                        'member_of_campaign'):
                    continue
                truncated = '.'.join(
                    existing_cr['prepid'].split('_')[1:][0:next_step +
                                                         1]).split('-')[0]
                self.logger.error('to match : %s , this one %s' %
                                  (toMatch, truncated))
                if truncated == toMatch:
                    #we found a chained request that starts with all same steps
                    mcm_cr = chained_request(crdb.get(existing_cr['prepid']))
                    if len(mcm_cr.get_attribute('chain')) <= next_step:
                        #found one, but it has not enough content either
                        continue
                    if mcm_cr.get_attribute('chain')[next_step] in vetoed_last:
                        continue
                    next_id = mcm_cr.get_attribute('chain')[next_step]
                    break
            if next_id:
                approach = 'use'
            else:
                approach = 'create'

        if approach == 'create':
            from rest_api.RequestPrepId import RequestPrepId

            next_id = RequestPrepId().next_prepid(
                current_request.get_attribute('pwg'), next_campaign_id)
            next_request = request(rdb.get(next_id))
            request.transfer(current_request, next_request)
            self.request_join(next_request)
        elif approach == 'use':
            ## there exists a request in another chained campaign that can be re-used here.
            # take this one. advance and go on
            next_request = request(rdb.get(next_id))
            if not reserve:
                self.set_attribute('step', next_step)
                self.set_attribute('last_status',
                                   next_request.get_attribute('status'))
                self.update_history({'action': 'flow', 'step': str(next_id)})
                self.set_attribute('status', 'processing')

            if not self.get_attribute("prepid") in next_request.get_attribute(
                    "member_of_chain"):
                ## register the chain to the next request
                self.request_join(next_request)
                saved = rdb.update(next_request.json())
                if not saved:
                    raise self.ChainedRequestCannotFlowException(
                        self.get_attribute('_id'),
                        'Unable to save %s with updated member_of_chains' %
                        next_id)
            return True
        elif approach == 'patch':
            ## there exists already a request in the chain (step!=last) and it is usable for the next stage
            next_request = request(next_campaign.add_request(rdb.get(next_id)))
            ## propagate again some of the fields of the previous request.
            request.transfer(current_request, next_request)
        else:
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'Unrecognized approach %s' % approach)

        #current_request -> next_request
        #current_campaign -> next_campaign

        ##determine whether we have an input dataset for the next request
        if len(current_request.get_attribute('reqmgr_name')):
            last_wma = current_request.get_attribute('reqmgr_name')[-1]
            if 'content' in last_wma and 'pdmv_dataset_name' in last_wma[
                    'content']:
                input_dataset = last_wma['content']['pdmv_dataset_name']
            else:
                statsDB = database('stats',
                                   url='http://cms-pdmv-stats.cern.ch:5984/')
                if statsDB.document_exists(last_wma['name']):
                    latestStatus = statsDB.get(last_wma['name'])
                    input_dataset = latestStatus['pdmv_dataset_name']
        if input_dataset:
            next_request.set_attribute('input_dataset', input_dataset)

        ## set blocks restriction if any
        if block_black_list:
            next_request.set_attribute('block_black_list', block_black_list)
        if block_white_list:
            next_request.set_attribute('block_white_list', block_white_list)

        ## register the flow to the request
        next_request.set_attribute('flown_with', flow_name)

        ##assemble the campaign+flow => request
        request.put_together(next_campaign, mcm_f, next_request)
        if not reserve:
            #already taking stage and threshold into account
            next_request.set_attribute('total_events', next_total_events)

            next_request.update_history({
                'action': 'flow',
                'step': self.get_attribute('prepid')
            })
        request_saved = rdb.save(next_request.json())

        if not request_saved:
            raise self.ChainedRequestCannotFlowException(
                self.get_attribute('_id'),
                'Could not save the new request %s' %
                (next_request.get_attribute('prepid')))

        ## inspect priority
        self.set_priority(original_action_item['block_number'])
        if not reserve:
            # sync last status
            self.set_attribute('last_status',
                               next_request.get_attribute('status'))
            # we can only be processing at this point
            self.set_attribute('status', 'processing')
            # set to next step
            self.set_attribute('step', next_step)
            self.update_history({
                'action': 'flow',
                'step': next_request.get_attribute('prepid')
            })

        if not reserve:
            notification_subject = 'Flow for request %s in %s' % (
                current_request.get_attribute('prepid'), next_campaign_id)
            notification_text = 'The request %s has been flown within:\n \t %s \n into campaign:\n \t %s \n using:\n \t %s \n creating the new request:\n \t %s \n as part of:\n \t %s \n and from the produced dataset:\n %s \n\n%srequests?prepid=%s \n%srequests?prepid=%s \n' % (
                current_request.get_attribute('prepid'),
                self.get_attribute('member_of_campaign'), next_campaign_id,
                flow_name, next_request.get_attribute('prepid'),
                self.get_attribute('prepid'),
                next_request.get_attribute('input_dataset'), l_type.baseurl(),
                current_request.get_attribute('prepid'), l_type.baseurl(),
                next_request.get_attribute('prepid'))
            current_request.notify(notification_subject,
                                   notification_text,
                                   accumulate=True)
        else:
            notification_subject = 'Reservation of request {0}'.format(
                next_request.get_attribute('prepid'))
            notification_text = 'The request {0} of campaign \n\t{2}\nhas been reserved as part of \n\t{1}\nas the next step for {4}\n\n{3}requests?prepid={4}\n{5}requests?prepid={6}\n'.format(
                next_request.get_attribute('prepid'),
                self.get_attribute('prepid'),
                next_campaign_id,
                l_type.baseurl(),
                current_request.get_attribute('prepid'),
                l_type.baseurl(),
                next_request.get_attribute('prepid'),
            )
            next_request.notify(notification_subject,
                                notification_text,
                                accumulate=True)
        return True
コード例 #22
0
ファイル: chained_request.py プロジェクト: srimanob/cmsPdmV
    def flow_to_next_step(self, input_dataset='', block_black_list=None, block_white_list=None, check_stats=True, reserve=False):
        if not block_white_list: block_white_list = []
        if not block_black_list: block_black_list = []
        self.logger.log('Flowing chained_request %s to next step...' % (self.get_attribute('_id')))
        if not self.get_attribute('chain'):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'chained_request %s has got no root' % (
                                                             self.get_attribute('_id')))

        # check on the approval of the chained request before all
        ## let it be flowing regardless
        #if self.get_attribute('approval') == 'none':
        #    raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
        #                                                 'The approval of the chained request is none, and therefore flow cannot happen')

        #this operation requires to access all sorts of objects
        rdb = database('requests')
        cdb = database('campaigns')
        ccdb = database('chained_campaigns')
        crdb = database('chained_requests')
        fdb = database('flows')
        adb = database('actions')

        l_type=locator()

        current_step = len(self.get_attribute('chain'))-1 if reserve else self.get_attribute('step')
        current_id = self.get_attribute('chain')[current_step]
        next_step = current_step + 1

        if not rdb.document_exists(current_id):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'the request %s does not exist' % current_id)

        current_request = request(rdb.get(current_id))
        current_campaign = campaign(cdb.get(current_request.get_attribute('member_of_campaign')))

        if not ccdb.document_exists(self.get_attribute('member_of_campaign')):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'the chain request %s is member of %s that does not exist' % (
                                                             self.get_attribute('_id'),
                                                             self.get_attribute('member_of_campaign')))
        mcm_cc = ccdb.get(self.get_attribute('member_of_campaign'))
        if next_step >= len(mcm_cc['campaigns']):
            if reserve: return False
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'chained_campaign %s does not allow any further flowing.' % (
                                                             self.get_attribute('member_of_campaign')))

        if not reserve:
            ## is the current request in the proper approval
            allowed_request_approvals = ['submit']
            if current_request.get_attribute('approval') not in allowed_request_approvals:
                raise self.NotApprovedException(current_request.get_attribute('prepid'),
                                                current_request.get_attribute('approval'), allowed_request_approvals)
            ## is the current request in the proper status
            allowed_request_statuses = ['submitted', 'done']
            if current_request.get_attribute('status') not in allowed_request_statuses:
                raise self.NotInProperStateException(current_request.get_attribute('prepid'),
                                                     current_request.get_attribute('status'),
                                                     allowed_request_statuses)

        original_action_id = self.get_attribute('chain')[0]

        original_action_item = self.retrieve_original_action_item(adb, original_action_id)

        ## what is the campaign to go to next and with which flow
        (next_campaign_id, flow_name) = mcm_cc['campaigns'][next_step]
        if not fdb.document_exists(flow_name):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The flow %s does not exist' % flow_name )

        mcm_f = flow(fdb.get(flow_name))
        if not 'sequences' in mcm_f.get_attribute('request_parameters'):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The flow %s does not contain sequences information.' % (
                                                             flow_name))

        if not cdb.document_exists(next_campaign_id):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The next campaign %s does not exist' % next_campaign_id)

        next_campaign = campaign(cdb.get(next_campaign_id))
        if len(next_campaign.get_attribute('sequences')) != len(mcm_f.get_attribute('request_parameters')['sequences']):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'the sequences changes in flow %s are not consistent with the next campaign %s' % (
                                                             flow_name, next_campaign_id))

        if next_campaign.get_attribute('energy') != current_campaign.get_attribute('energy'):
            raise self.EnergyInconsistentException(next_campaign.get_attribute('prepid'))

        if next_campaign.get_attribute('type') == 'MCReproc' and (not 'time_event' in mcm_f.get_attribute('request_parameters')):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'the flow is getting into a MCReproc campaign but not time per event is specified')

        if next_campaign.get_attribute('type') == 'MCReproc' and (not 'size_event' in mcm_f.get_attribute('request_parameters')):
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'the flow is getting into a MCReproc campaign but not size per event is specified')


        
        ## check that it is allowed to flow
        allowed_flow_approvals = ['flow', 'submit']
        ###### cascade of checks
        """
        if not reserve and not mcm_f.get_attribute('approval') in allowed_flow_approvals:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The flow (%s) is not in proper approval state (%s)'%( 
                                                            mcm_f.get_attribute('prepid'),
                                                            mcm_f.get_attribute('approval')))

        if not reserve and not self.get_attribute('approval') in allowed_flow_approvals:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'The chained request (%s) is not in the proper approval state (%s)'% (
                                                            self.get_attribute('_id'),
                                                            self.get_attribute('approval')))
        """
        if not reserve and not mcm_f.get_attribute('approval') in allowed_flow_approvals:
            if not self.get_attribute('approval') in allowed_flow_approvals:
                raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                             'Neither the flow (%s) nor the chained request (%s) approvals allow for flowing' % (
                                                               mcm_f.get_attribute('approval'),
                                                               self.get_attribute('approval')))

        if next_campaign.get_attribute('status') == 'stopped':
            raise self.CampaignStoppedException(next_campaign_id)

        #what is going to be the required number of events for the next request
        #update the stats to its best
        if not reserve:
            current_request.get_stats()
            next_total_events=current_request.get_attribute('completed_events')

            notify_on_fail=True ## to be tuned according to the specific cases
            if current_request.get_attribute('completed_events') <= 0:
                raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                             'The number of events completed is negative or null')
            else:
                allowed_request_statuses = ['done']
                ## determine if this is a root -> non-root transition to potentially apply staged number
                at_a_transition=(current_campaign.get_attribute('root') != 1 and next_campaign.get_attribute('root') == 1)
                if ('staged' in original_action_item or 'threshold' in original_action_item) and at_a_transition:
                    allowed_request_statuses.append('submitted')
                ##check status
                if not current_request.get_attribute('status') in allowed_request_statuses:
                    raise self.NotInProperStateException(current_request.get_attribute('prepid'),
                                                         current_request.get_attribute('status'),
                                                         allowed_request_statuses)
                ##special check at transition that the statistics is good enough
                if at_a_transition:
                    # at a root -> non-root transition only does the staged/threshold functions !
                    if 'staged' in original_action_item:
                        next_total_events = int(original_action_item['staged'])
                    if 'threshold' in original_action_item:
                        next_total_events = int(current_request.get_attribute('total_events') * float(original_action_item['threshold'] / 100.))

                    completed_events_to_pass = next_total_events
                else:
                    ## get the original expected events and allow a margin of 5% less statistics
                    completed_events_to_pass = int(current_request.get_attribute('total_events') * 0.95)

            if check_stats and (current_request.get_attribute('completed_events') < completed_events_to_pass):
                if notify_on_fail:
                    current_request.notify('Flowing for %s: not enough statistics'%( current_request.get_attribute('prepid')),
                                           'For this request, the completed statistics %s is not enough to fullfill the requirement to the next level : need at least %s \n\n %srequests?prepid=%s'%( current_request.get_attribute('completed_events'),
                                                                                                                                                                                                      completed_events_to_pass,
                                                                                                                                                                                                      l_type.baseurl(),
                                                                                                                                                                                                      current_request.get_attribute('prepid')))
                raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                             'The number of events completed (%s) is not enough for the requirement (%s)'%(current_request.get_attribute('completed_events'), completed_events_to_pass))

        ## select what is to happened : [create, patch, use]
        next_id = None
        approach = None
        next_request = None
        if next_step != len(self.get_attribute('chain')):
            #not at the end
            next_id = self.get_attribute('chain')[next_step]
            if not rdb.document_exists(next_id):
                raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                             'The next request (%s) according to the step (%s) does not exist' % (
                                                                 next_id, next_step))
            next_request = request(rdb.get(next_id))
            if next_request.get_attribute('status') == 'new':
                #most likely a rewind + resub
                approach = 'patch'
            else:
                raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                             'This should never happen. (%s) is next according to step (%s), but is not in new status (%s)' % (
                                                                 next_id, next_step, next_request.get_attribute('status')))
        else:
            ## look in *other* chained campaigns whether you can suck in an existing request
            ## look up all chained requests that start from the same root request
            ## remove <pwg>-chain_ and the -serial number, replacing _ with a .
            toMatch = '.'.join(self.get_attribute('prepid').split('_')[1:][0:next_step + 1]).split('-')[0]
            ## make sure they get ordered by prepid
            related_crs = sorted(crdb.queries(['root_request==%s' % original_action_id]), key=lambda cr : cr['prepid'])
            
            

            vetoed_last=[]
            for existing_cr in related_crs:
                ## exclude itself
                if existing_cr['prepid']==self.get_attribute('prepid'):
                    continue
                ## prevent from using a request from within the same exact chained_campaigns
                if existing_cr['member_of_campaign'] == self.get_attribute('member_of_campaign'):
                    mcm_cr = chained_request(crdb.get(existing_cr['prepid']))
                    if len(mcm_cr.get_attribute('chain')) > next_step:
                        ## one existing request in the very same chained campaign has already something used, make sure it is not going to be used
                        vetoed_last.append( mcm_cr.get_attribute('chain')[next_step])
                    continue
                else:
                    continue
            for existing_cr in related_crs:
                ## exclude itself
                if existing_cr['prepid']==self.get_attribute('prepid'):
                    continue
                ## prevent from using a request from within the same exact chained_campaigns
                if existing_cr['member_of_campaign'] == self.get_attribute('member_of_campaign'):
                    continue
                truncated = '.'.join(existing_cr['prepid'].split('_')[1:][0:next_step + 1]).split('-')[0]
                self.logger.error('to match : %s , this one %s' % ( toMatch, truncated ))
                if truncated == toMatch:
                    #we found a chained request that starts with all same steps          
                    mcm_cr = chained_request(crdb.get(existing_cr['prepid']))
                    if len(mcm_cr.get_attribute('chain')) <= next_step:
                        #found one, but it has not enough content either
                        continue
                    if mcm_cr.get_attribute('chain')[next_step] in vetoed_last:
                        continue
                    next_id = mcm_cr.get_attribute('chain')[next_step]
                    break
            if next_id:
                approach = 'use'
            else:
                approach = 'create'

        if approach == 'create':
            from rest_api.RequestPrepId import RequestPrepId

            next_id = RequestPrepId().next_prepid(current_request.get_attribute('pwg'), next_campaign_id)
            next_request = request(rdb.get(next_id))
            request.transfer( current_request, next_request)
            self.request_join(next_request)

        elif approach == 'use':
            ## there exists a request in another chained campaign that can be re-used here.
            # take this one. advance and go on
            next_request = request(rdb.get(next_id))
            if not reserve:
                self.set_attribute('step', next_step)
                self.set_attribute('last_status', next_request.get_attribute('status'))
                self.update_history({'action': 'flow', 'step': str(next_step)})
                self.set_attribute('status', 'processing')

            if not self.get_attribute("prepid") in next_request.get_attribute("member_of_chain"):
                ## register the chain to the next request
                self.request_join(next_request)
                saved = rdb.update(next_request.json())
                if not saved:
                    raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                                 'Unable to save %s with updated member_of_chains' % next_id)
                return True
        elif approach == 'patch':
            ## there exists already a request in the chain (step!=last) and it is usable for the next stage
            next_request = request( next_campaign.add_request( rdb.get(next_id)))
            ### shouldn't this be added ?
            #transfer( current_request, next_request)

        else:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'Unrecognized approach %s' %  approach )

        #current_request -> next_request
        #current_campaign -> next_campaign

        ##determine whether we have an input dataset for the next request
        if len(current_request.get_attribute('reqmgr_name')):
            last_wma = current_request.get_attribute('reqmgr_name')[-1]
            if 'content' in last_wma and 'pdmv_dataset_name' in last_wma['content']:
                input_dataset = last_wma['content']['pdmv_dataset_name']
            else:
                statsDB = database('stats', url='http://cms-pdmv-stats.cern.ch:5984/')
                if statsDB.document_exists(last_wma['name']):
                    latestStatus = statsDB.get(last_wma['name'])
                    input_dataset = latestStatus['pdmv_dataset_name']
        if input_dataset:
            next_request.set_attribute('input_filename', input_dataset)



        ## set blocks restriction if any
        if block_black_list:
            next_request.set_attribute('block_black_list', block_black_list)
        if block_white_list:
            next_request.set_attribute('block_white_list', block_white_list)

        ## register the flow to the request
        next_request.set_attribute('flown_with', flow_name)

        ##assemble the campaign+flow => request
        request.put_together(next_campaign, mcm_f, next_request)
        if not reserve:
            #already taking stage and threshold into account
            next_request.set_attribute('total_events', next_total_events)

            next_request.update_history({'action': 'flow', 'step': self.get_attribute('prepid')})
        request_saved = rdb.save(next_request.json())

        if not request_saved:
            raise self.ChainedRequestCannotFlowException(self.get_attribute('_id'),
                                                         'Could not save the new request %s' % (
                                                             next_request.get_attribute('prepid')))

        ## inspect priority
        self.set_priority(original_action_item['block_number'])
        if not reserve:
            # sync last status
            self.set_attribute('last_status', next_request.get_attribute('status'))
            # we can only be processing at this point
            self.set_attribute('status', 'processing')
            # set to next step
            self.set_attribute('step', next_step)
        if not reserve:
            notification_subject = 'Flow for request %s in %s' % (current_request.get_attribute('prepid'), next_campaign_id)
            notification_text = 'The request %s has been flown within:\n \t %s \n into campaign:\n \t %s \n using:\n \t %s \n creating the new request:\n \t %s \n as part of:\n \t %s \n and from the produced dataset:\n %s \n\n%srequests?prepid=%s \n%srequests?prepid=%s \n' % (
                current_request.get_attribute('prepid'),
                self.get_attribute('member_of_campaign'),
                next_campaign_id,
                flow_name,
                next_request.get_attribute('prepid'),
                self.get_attribute('prepid'),
                next_request.get_attribute('input_filename'),
                l_type.baseurl(),
                current_request.get_attribute('prepid'),
                l_type.baseurl(),
                next_request.get_attribute('prepid')
            )
            current_request.notify(notification_subject, notification_text)
        else:
            notification_subject = 'Reservation of request {0}'.format(next_request.get_attribute('prepid'))
            notification_text = 'The request {0} of campaign \n\t{2}\nhas been reserved as part of \n\t{1}\nas the next step for {4}\n\n{3}requests?prepid={4}\n{5}requests?prepid={6}\n'.format(
                next_request.get_attribute('prepid'),
                self.get_attribute('prepid'),
                next_campaign_id,
                l_type.baseurl(), current_request.get_attribute('prepid'),
                l_type.baseurl(), next_request.get_attribute('prepid'),
                )
            next_request.notify(notification_subject, notification_text)
        return True