def getData(self): DN = self.__disetConfig.getDN() group = self.__disetConfig.getGroup() credDict = self.__getCredDict(DN, group) data = { 'menu': self.__getGroupMenu(credDict, group), 'user': credDict, 'validGroups': [], 'setup': self.__disetConfig.getSetup() or gConfig.getValue("/DIRAC/Setup", ""), 'validSetups': gConfig.getSections("/DIRAC/Setups")['Value'], 'extensions': self.__extensions, 'extVersion': self.getExtJSVersion() } if 'properties' in credDict: credDict.pop('properties') #Add valid groups if known if DN: result = Registry.getGroupsForDN(DN) if result['OK']: data['validGroups'] = result['Value'] #Calculate baseURL baseURL = [ Conf.rootURL().strip("/"), "s:%s" % data['setup'], "g:%s" % credDict.get('group', 'anon') ] data['baseURL'] = "/%s" % "/".join(baseURL) return data
def completeDelegation(self, requestId, userDN, delegatedPem): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest(requestId, userDN) if not retVal['OK']: return retVal request = retVal['Value'] chain = X509Chain(keyObj=request.getPKey()) retVal = chain.loadChainFromString(delegatedPem) if not retVal['OK']: return retVal retVal = chain.isValidProxy(ignoreDefault=True) noGroupFlag = False if not retVal['OK']: if retVal['Message'] == "Proxy does not have an explicit group": noGroupFlag = True else: return retVal result = chain.isVOMS() if result['OK'] and result['Value']: return S_ERROR( "Proxies with VOMS extensions are not allowed to be uploaded") retVal = request.checkChain(chain) if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Received chain does not match request: %s" % retVal['Message']) retVal = chain.getDIRACGroup() if not retVal['OK']: return retVal userGroup = retVal['Value'] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN(userDN) if not retVal['OK']: return retVal if not userGroup in retVal['Value']: return S_ERROR("%s group is not valid for %s" % (userGroup, userDN)) # For proxies without embedded DIRAC group only one default is allowed # Cleaning all the proxies for this DN if any before uploading the new one. if noGroupFlag: retVal = self.deleteProxy(userDN) if not retVal['OK']: return retVal retVal = self.storeProxy(userDN, userGroup, chain) if not retVal['OK']: return retVal retVal = self.deleteRequest(requestId) if not retVal['OK']: return retVal return S_OK()
def getGroupsToUpload( self ): uploadGroups = [] if self.__piParams.uploadProxy or Registry.getGroupOption( self.__piParams.diracGroup, "AutoUploadProxy", False ): uploadGroups.append( self.__piParams.diracGroup ) if not self.__piParams.uploadPilot: if not Registry.getGroupOption( self.__piParams.diracGroup, "AutoUploadPilotProxy", False ): return uploadGroups issuerCert = self.getIssuerCert() resultUserDN = issuerCert.getSubjectDN() #pylint: disable=no-member if not resultUserDN['OK']: return resultUserDN userDN = resultUserDN[ 'Value' ] resultGroups = Registry.getGroupsForDN( userDN ) if not resultGroups[ 'OK' ]: gLogger.error( "No groups defined for DN %s" % userDN ) return [] availableGroups = resultGroups[ 'Value' ] for group in availableGroups: groupProps = Registry.getPropertiesForGroup( group ) if Properties.PILOT in groupProps or Properties.GENERIC_PILOT in groupProps: uploadGroups.append( group ) return uploadGroups
def getGroupsToUpload(self): uploadGroups = [] if self.__piParams.uploadProxy or Registry.getGroupOption( self.__piParams.diracGroup, "AutoUploadProxy", False): uploadGroups.append(self.__piParams.diracGroup) if not self.__piParams.uploadPilot: if not Registry.getGroupOption(self.__piParams.diracGroup, "AutoUploadPilotProxy", False): return uploadGroups issuerCert = self.getIssuerCert() userDN = issuerCert.getSubjectDN()['Value'] result = Registry.getGroupsForDN(userDN) if not result['OK']: gLogger.error("No groups defined for DN %s" % userDN) return [] availableGroups = result['Value'] pilotGroups = [] for group in availableGroups: groupProps = Registry.getPropertiesForGroup(group) if Properties.PILOT in groupProps or Properties.GENERIC_PILOT in groupProps: uploadGroups.append(group) return uploadGroups
def __getPUSProxy(self, userDN, userGroup, requiredLifetime, requestedVOMSAttr=None): result = Registry.getGroupsForDN(userDN) if not result['OK']: return result validGroups = result['Value'] if not userGroup in validGroups: return S_ERROR('Invalid group %s for user' % userGroup) voName = Registry.getVOForGroup(userGroup) if not voName: return S_ERROR('Can not determine VO for group %s' % userGroup) retVal = self.__getVOMSAttribute(userGroup, requestedVOMSAttr) if not retVal['OK']: return retVal vomsAttribute = retVal['Value']['attribute'] vomsVO = retVal['Value']['VOMSVO'] puspServiceURL = Registry.getVOOption(voName, 'PUSPServiceURL') if not puspServiceURL: return S_ERROR('Can not determine PUSP service URL for VO %s' % voName) user = userDN.split(":")[-1] puspURL = "%s?voms=%s:%s&proxy-renewal=false&disable-voms-proxy=false" \ "&rfc-proxy=true&cn-label=user:%s" % ( puspServiceURL, vomsVO, vomsAttribute, user ) try: proxy = urllib.urlopen(puspURL).read() except Exception as e: return S_ERROR('Failed to get proxy from the PUSP server') chain = X509Chain() chain.loadChainFromString(proxy) chain.loadKeyFromString(proxy) result = chain.getCredentials() if not result['OK']: return S_ERROR('Failed to get a valid PUSP proxy') credDict = result['Value'] if credDict['identity'] != userDN: return S_ERROR( 'Requested DN does not match the obtained one in the PUSP proxy' ) timeLeft = credDict['secondsLeft'] result = chain.generateProxyToString(lifeTime=timeLeft, diracGroup=userGroup) if not result['OK']: return result proxyString = result['Value'] return S_OK((proxyString, timeLeft))
def completeDelegation( self, requestId, userDN, delegatedPem ): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest( requestId, userDN ) if not retVal[ 'OK' ]: return retVal request = retVal[ 'Value' ] chain = X509Chain( keyObj = request.getPKey() ) retVal = chain.loadChainFromString( delegatedPem ) if not retVal[ 'OK' ]: return retVal retVal = chain.isValidProxy( ignoreDefault = True ) noGroupFlag = False if not retVal[ 'OK' ]: if DErrno.cmpError( retVal, DErrno.ENOGROUP ): noGroupFlag = True else: return retVal result = chain.isVOMS() if result[ 'OK' ] and result[ 'Value' ]: return S_ERROR( "Proxies with VOMS extensions are not allowed to be uploaded" ) retVal = request.checkChain( chain ) if not retVal[ 'OK' ]: return retVal if not retVal[ 'Value' ]: return S_ERROR( "Received chain does not match request: %s" % retVal[ 'Message' ] ) retVal = chain.getDIRACGroup() if not retVal[ 'OK' ]: return retVal userGroup = retVal[ 'Value' ] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN( userDN ) if not retVal[ 'OK' ]: return retVal if not userGroup in retVal[ 'Value' ]: return S_ERROR( "%s group is not valid for %s" % ( userGroup, userDN ) ) # For proxies without embedded DIRAC group only one default is allowed # Cleaning all the proxies for this DN if any before uploading the new one. if noGroupFlag: retVal = self.deleteProxy( userDN ) if not retVal[ 'OK' ]: return retVal retVal = self.storeProxy( userDN, userGroup, chain ) if not retVal[ 'OK' ]: return retVal retVal = self.deleteRequest( requestId ) if not retVal[ 'OK' ]: return retVal return S_OK()
def __getGroups( self, DN = False ): if not DN: credDict = self.getClientCredentials() if not credDict: return WErr( 401, "No certificate received to issue a token" ) DN = credDict[ 'subject' ] if not credDict[ 'validDN' ]: return WErr( 401, "Unknown DN %s" % DN ) result = Registry.getGroupsForDN( DN ) if not result[ 'OK' ]: return WErr( 500, result[ 'Message' ] ) return WOK( { 'groups' : result[ 'Value' ] } )
def __getPUSProxy( self, userDN, userGroup, requiredLifetime, requestedVOMSAttr = None ): result = Registry.getGroupsForDN( userDN ) if not result['OK']: return result validGroups = result['Value'] if not userGroup in validGroups: return S_ERROR( 'Invalid group %s for user' % userGroup ) voName = Registry.getVOForGroup( userGroup ) if not voName: return S_ERROR( 'Can not determine VO for group %s' % userGroup ) retVal = self.__getVOMSAttribute( userGroup, requestedVOMSAttr ) if not retVal[ 'OK' ]: return retVal vomsAttribute = retVal[ 'Value' ][ 'attribute' ] vomsVO = retVal[ 'Value' ][ 'VOMSVO' ] puspServiceURL = Registry.getVOOption( voName, 'PUSPServiceURL' ) if not puspServiceURL: return S_ERROR( 'Can not determine PUSP service URL for VO %s' % voName ) user = userDN.split(":")[-1] puspURL = "%s?voms=%s:%s&proxy-renewal=false&disable-voms-proxy=false" \ "&rfc-proxy=true&cn-label=user:%s" % ( puspServiceURL, vomsVO, vomsAttribute, user ) try: proxy = urllib.urlopen( puspURL ).read() except Exception as e: return S_ERROR( 'Failed to get proxy from the PUSP server' ) chain = X509Chain() chain.loadChainFromString( proxy ) chain.loadKeyFromString( proxy ) result = chain.getCredentials() if not result['OK']: return S_ERROR( 'Failed to get a valid PUSP proxy' ) credDict = result['Value'] if credDict['identity'] != userDN: return S_ERROR( 'Requested DN does not match the obtained one in the PUSP proxy' ) timeLeft = credDict['secondsLeft'] result = chain.generateProxyToString( lifeTime = timeLeft, diracGroup = userGroup ) if not result['OK']: return result proxyString = result['Value'] return S_OK( ( proxyString, timeLeft ) )
def completeDelegation(self, requestId, userDN, delegatedPem): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest(requestId, userDN) if not retVal['OK']: return retVal request = retVal['Value'] chain = X509Chain(keyObj=request.getPKey()) retVal = chain.loadChainFromString(delegatedPem) if not retVal['OK']: return retVal retVal = chain.isValidProxy() if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Chain received is not a valid proxy: %s" % retVal['Message']) retVal = request.checkChain(chain) if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Received chain does not match request: %s" % retVal['Message']) retVal = chain.getDIRACGroup() if not retVal['OK']: return retVal userGroup = retVal['Value'] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN(userDN) if not retVal['OK']: return retVal if not userGroup in retVal['Value']: return S_ERROR("%s group is not valid for %s" % (userGroup, userDN)) retVal = self.__checkVOMSisAlignedWithGroup(userGroup, chain) if not retVal['OK']: return retVal retVal = self.storeProxy(userDN, userGroup, chain) if not retVal['OK']: return retVal retVal = self.deleteRequest(requestId) if not retVal['OK']: return retVal return S_OK()
def completeDelegation(self, requestId, userDN, delegatedPem): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest(requestId, userDN) if not retVal['OK']: return retVal request = retVal['Value'] chain = X509Chain(keyObj=request.getPKey()) retVal = chain.loadChainFromString(delegatedPem) if not retVal['OK']: return retVal retVal = chain.isValidProxy(ignoreDefault=True) if not retVal['OK']: return retVal result = chain.isVOMS() if result['OK'] and result['Value']: return S_ERROR( "Proxies with VOMS extensions are not allowed to be uploaded") retVal = request.checkChain(chain) if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Received chain does not match request: %s" % retVal['Message']) retVal = chain.getDIRACGroup() if not retVal['OK']: return retVal userGroup = retVal['Value'] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN(userDN) if not retVal['OK']: return retVal if not userGroup in retVal['Value']: return S_ERROR("%s group is not valid for %s" % (userGroup, userDN)) retVal = self.storeProxy(userDN, userGroup, chain) if not retVal['OK']: return retVal retVal = self.deleteRequest(requestId) if not retVal['OK']: return retVal return S_OK()
def completeDelegation( self, requestId, userDN, delegatedPem ): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest( requestId, userDN ) if not retVal[ 'OK' ]: return retVal request = retVal[ 'Value' ] chain = X509Chain( keyObj = request.getPKey() ) retVal = chain.loadChainFromString( delegatedPem ) if not retVal[ 'OK' ]: return retVal retVal = chain.isValidProxy() if not retVal[ 'OK' ]: return retVal if not retVal[ 'Value' ]: return S_ERROR( "Chain received is not a valid proxy: %s" % retVal[ 'Message' ] ) retVal = request.checkChain( chain ) if not retVal[ 'OK' ]: return retVal if not retVal[ 'Value' ]: return S_ERROR( "Received chain does not match request: %s" % retVal[ 'Message' ] ) retVal = chain.getDIRACGroup() if not retVal[ 'OK' ]: return retVal userGroup = retVal[ 'Value' ] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN( userDN ) if not retVal[ 'OK' ]: return retVal if not userGroup in retVal[ 'Value' ]: return S_ERROR( "%s group is not valid for %s" % ( userGroup, userDN ) ) retVal = self.__checkVOMSisAlignedWithGroup( userGroup, chain ) if not retVal[ 'OK' ]: return retVal retVal = self.storeProxy( userDN, userGroup, chain ) if not retVal[ 'OK' ]: return retVal retVal = self.deleteRequest( requestId ) if not retVal[ 'OK' ]: return retVal return S_OK()
def _checkCredentials(self, resourceDict, credDict): """ Check if we can get a job given the passed credentials """ if Properties.GENERIC_PILOT in credDict['properties']: # You can only match groups in the same VO if credDict['group'] == "hosts": # for the host case the VirtualOrganization parameter # is mandatory in resourceDict vo = resourceDict.get('VirtualOrganization', '') else: vo = Registry.getVOForGroup(credDict['group']) if 'OwnerGroup' not in resourceDict: result = Registry.getGroupsForVO(vo) if result['OK']: resourceDict['OwnerGroup'] = result['Value'] else: raise RuntimeError(result['Message']) else: # If it's a private pilot, the DN has to be the same if Properties.PILOT in credDict['properties']: self.log.notice( "Setting the resource DN to the credentials DN") resourceDict['OwnerDN'] = credDict['DN'] # If it's a job sharing. The group has to be the same and just check that the DN (if any) # belongs to the same group elif Properties.JOB_SHARING in credDict['properties']: resourceDict['OwnerGroup'] = credDict['group'] self.log.notice( "Setting the resource group to the credentials group") if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN'] != credDict['DN']: ownerDN = resourceDict['OwnerDN'] result = Registry.getGroupsForDN(resourceDict['OwnerDN']) if not result['OK']: raise RuntimeError(result['Message']) if credDict['group'] not in result['Value']: # DN is not in the same group! bad boy. self.log.warn( "You cannot request jobs from this DN, as it does not belong to your group!", "(%s)" % ownerDN) resourceDict['OwnerDN'] = credDict['DN'] # Nothing special, group and DN have to be the same else: resourceDict['OwnerDN'] = credDict['DN'] resourceDict['OwnerGroup'] = credDict['group'] return resourceDict
def completeDelegation( self, requestId, userDN, delegatedPem ): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest( requestId, userDN ) if not retVal[ 'OK' ]: return retVal request = retVal[ 'Value' ] chain = X509Chain( keyObj = request.getPKey() ) retVal = chain.loadChainFromString( delegatedPem ) if not retVal[ 'OK' ]: return retVal retVal = chain.isValidProxy( ignoreDefault = True ) if not retVal[ 'OK' ]: return retVal result = chain.isVOMS() if result[ 'OK' ] and result[ 'Value' ]: return S_ERROR( "Proxies with VOMS extensions are not allowed to be uploaded" ) retVal = request.checkChain( chain ) if not retVal[ 'OK' ]: return retVal if not retVal[ 'Value' ]: return S_ERROR( "Received chain does not match request: %s" % retVal[ 'Message' ] ) retVal = chain.getDIRACGroup() if not retVal[ 'OK' ]: return retVal userGroup = retVal[ 'Value' ] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN( userDN ) if not retVal[ 'OK' ]: return retVal if not userGroup in retVal[ 'Value' ]: return S_ERROR( "%s group is not valid for %s" % ( userGroup, userDN ) ) retVal = self.storeProxy( userDN, userGroup, chain ) if not retVal[ 'OK' ]: return retVal retVal = self.deleteRequest( requestId ) if not retVal[ 'OK' ]: return retVal return S_OK()
def _checkCredentials(self, resourceDict, credDict): """ Check if we can get a job given the passed credentials """ if Properties.GENERIC_PILOT in credDict['properties']: # You can only match groups in the same VO if credDict['group'] == "hosts": # for the host case the VirtualOrganization parameter # is mandatory in resourceDict vo = resourceDict.get('VirtualOrganization', '') else: vo = Registry.getVOForGroup(credDict['group']) if 'OwnerGroup' not in resourceDict: result = Registry.getGroupsForVO(vo) if result['OK']: resourceDict['OwnerGroup'] = result['Value'] else: raise RuntimeError(result['Message']) else: # If it's a private pilot, the DN has to be the same if Properties.PILOT in credDict['properties']: self.log.notice("Setting the resource DN to the credentials DN") resourceDict['OwnerDN'] = credDict['DN'] # If it's a job sharing. The group has to be the same and just check that the DN (if any) # belongs to the same group elif Properties.JOB_SHARING in credDict['properties']: resourceDict['OwnerGroup'] = credDict['group'] self.log.notice("Setting the resource group to the credentials group") if 'OwnerDN' in resourceDict and resourceDict['OwnerDN'] != credDict['DN']: ownerDN = resourceDict['OwnerDN'] result = Registry.getGroupsForDN(resourceDict['OwnerDN']) if not result['OK']: raise RuntimeError(result['Message']) if credDict['group'] not in result['Value']: # DN is not in the same group! bad boy. self.log.notice("You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN) resourceDict['OwnerDN'] = credDict['DN'] # Nothing special, group and DN have to be the same else: resourceDict['OwnerDN'] = credDict['DN'] resourceDict['OwnerGroup'] = credDict['group'] return resourceDict
def getData( self ): data = { 'menu' : self.__getGroupMenu(), 'user' : self.__credDict, 'validGroups' : [], 'setup' : self.__setup, 'validSetups' : gConfig.getSections( "/DIRAC/Setups" )[ 'Value' ], 'extensions' : self.__extensions, 'extVersion' : self.getExtJSVersion() } #Add valid groups if known DN = self.__credDict.get( "DN", "" ) if DN: result = Registry.getGroupsForDN( DN ) if result[ 'OK' ]: data[ 'validGroups' ] = result[ 'Value' ] #Calculate baseURL baseURL = [ Conf.rootURL().strip( "/" ), "s:%s" % data[ 'setup' ], "g:%s" % self.__credDict.get( 'group', '' ) ] data[ 'baseURL' ] = "/%s" % "/".join( baseURL ) return data
def getPilotGroupsToUpload( self ): pilotUpload = Registry.getGroupOption( self.__piParams.diracGroup, "AutoUploadPilotProxy", self.__piParams.uploadPilot ) if not pilotUpload: return [] issuerCert = self.getIssuerCert() userDN = issuerCert.getSubjectDN()[ 'Value' ] result = Registry.getGroupsForDN( userDN ) if not result[ 'OK' ]: gLogger.error( "No groups defined for DN %s" % userDN ) return [] availableGroups = result[ 'Value' ] pilotGroups = [] for group in availableGroups: groupProps = Registry.getPropertiesForGroup( group ) if Properties.PILOT in groupProps or Properties.GENERIC_PILOT in groupProps: pilotGroups.append( group ) return pilotGroups
def _checkCredentials( self, resourceDict, credDict ): """ Check if we can get a job given the passed credentials """ # Check credentials if not generic pilot if Properties.GENERIC_PILOT in credDict[ 'properties' ]: # You can only match groups in the same VO vo = Registry.getVOForGroup( credDict[ 'group' ] ) result = Registry.getGroupsForVO( vo ) if result[ 'OK' ]: resourceDict[ 'OwnerGroup' ] = result[ 'Value' ] else: raise RuntimeError( result['Message'] ) else: # If it's a private pilot, the DN has to be the same if Properties.PILOT in credDict[ 'properties' ]: self.log.notice( "Setting the resource DN to the credentials DN" ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] # If it's a job sharing. The group has to be the same and just check that the DN (if any) # belongs to the same group elif Properties.JOB_SHARING in credDict[ 'properties' ]: resourceDict[ 'OwnerGroup' ] = credDict[ 'group' ] self.log.notice( "Setting the resource group to the credentials group" ) if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN' ] != credDict[ 'DN' ]: ownerDN = resourceDict[ 'OwnerDN' ] result = Registry.getGroupsForDN( resourceDict[ 'OwnerDN' ] ) if not result[ 'OK' ]: raise RuntimeError( result['Message'] ) if credDict[ 'group' ] not in result[ 'Value' ]: # DN is not in the same group! bad boy. self.log.notice( "You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] # Nothing special, group and DN have to be the same else: resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] resourceDict[ 'OwnerGroup' ] = credDict[ 'group' ] return resourceDict
def getData(self): data = { 'menu': self.__getGroupMenu(), 'user': self.__credDict, 'validGroups': [], 'setup': self.__setup, 'validSetups': gConfig.getSections("/DIRAC/Setups")['Value'], 'extensions': self.__extensions, 'extVersion': self.getExtJSVersion() } #Add valid groups if known DN = self.__credDict.get("DN", "") if DN: result = Registry.getGroupsForDN(DN) if result['OK']: data['validGroups'] = result['Value'] #Calculate baseURL baseURL = [ Conf.rootURL().strip("/"), "s:%s" % data['setup'], "g:%s" % self.__credDict.get('group', '') ] data['baseURL'] = "/%s" % "/".join(baseURL) return data
def getData( self ): DN = self.__disetConfig.getDN() group = self.__disetConfig.getGroup() credDict = self.__getCredDict( DN, group ) data = { 'menu' : self.__getGroupMenu( credDict, group ), 'user' : credDict, 'validGroups' : [], 'setup' : self.__disetConfig.getSetup() or gConfig.getValue( "/DIRAC/Setup", "" ), 'validSetups' : gConfig.getSections( "/DIRAC/Setups" )[ 'Value' ], 'extensions' : self.__extensions, 'extVersion' : self.getExtJSVersion() } if 'properties' in credDict: credDict.pop( 'properties' ) #Add valid groups if known if DN: result = Registry.getGroupsForDN( DN ) if result[ 'OK' ]: data[ 'validGroups' ] = result[ 'Value' ] #Calculate baseURL baseURL = [ Conf.rootURL().strip( "/" ), "s:%s" % data[ 'setup' ], "g:%s" % credDict.get( 'group', 'anon' ) ] data[ 'baseURL' ] = "/%s" % "/".join( baseURL ) return data
def selectJob( self, resourceDescription ): """ Main job selection function to find the highest priority job matching the resource capacity """ startTime = time.time() resourceDict = self.__processResourceDescription( resourceDescription ) credDict = self.getRemoteCredentials() #Check credentials if Properties.GENERIC_PILOT not in credDict[ 'properties' ]: #Not a generic pilot and requires a DN??? This smells fishy if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN' ] != credDict[ 'DN' ]: ownerDN = resourceDict[ 'OwnerDN' ] if Properties.JOB_SHARING in credDict[ 'properties' ]: #Job sharing, is the DN in the same group? result = Registry.getGroupsForDN( ownerDN ) if not result[ 'OK' ]: return S_ERROR( "Requested owner DN %s does not have any group!" % ownerDN ) groups = result[ 'Value' ] if credDict[ 'group' ] not in groups: #DN is not in the same group! bad body. gLogger.notice( "You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] else: #No generic pilot and not JobSharing? DN has to be the same! gLogger.notice( "You can only match jobs for your DN (%s)" % credDict[ 'DN' ] ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] if Properties.PILOT not in credDict[ 'properties' ]: #No pilot? Group has to be the same! if 'OwnerGroup' in resourceDict and resourceDict[ 'OwnerGroup' ] != credDict[ 'group' ]: gLogger.notice( "You can only match jobs for your group (%s)" % credDict[ 'group' ] ) resourceDict[ 'OwnerGroup' ] = credDict[ 'group' ] # Check the pilot DIRAC version if self.checkPilotVersion: if not 'DIRACVersion' in resourceDict: return S_ERROR( 'Version check requested and not provided by Pilot' ) # Check if the matching Request provides a VirtualOrganization if 'VirtualOrganization' in resourceDict: voName = resourceDict['VirtualOrganization'] # Check if the matching Request provides an OwnerGroup elif 'OwnerGroup' in resourceDict: voName = Registry.getVOForGroup( resourceDict['OwnerGroup'] ) # else take the default VirtualOrganization for the installation else: voName = Registry.getVOForGroup( '' ) self.pilotVersion = gConfig.getValue( '/Operations/%s/%s/Versions/PilotVersion' % ( voName, self.setup ), '' ) if self.pilotVersion and resourceDict['DIRACVersion'] != self.pilotVersion: return S_ERROR( 'Pilot version does not match the production version %s:%s' % \ ( resourceDict['DIRACVersion'], self.pilotVersion ) ) # Get common site mask and check the agent site result = gJobDB.getSiteMask( siteState = 'Active' ) if result['OK']: maskList = result['Value'] else: return S_ERROR( 'Internal error: can not get site mask' ) if not 'Site' in resourceDict: return S_ERROR( 'Missing Site Name in Resource JDL' ) siteName = resourceDict['Site'] if resourceDict['Site'] not in maskList: if 'GridCE' in resourceDict: del resourceDict['Site'] else: return S_ERROR( 'Site not in mask and GridCE not specified' ) resourceDict['Setup'] = self.serviceInfoDict['clientSetup'] if DEBUG: print "Resource description:" for key, value in resourceDict.items(): print key.rjust( 20 ), value # Check if Job Limits are imposed onto the site extraConditions = {} if self.siteJobLimits: result = self.getExtraConditions( siteName ) if result['OK']: extraConditions = result['Value'] if extraConditions: gLogger.info( 'Job Limits for site %s are: %s' % ( siteName, str( extraConditions ) ) ) result = gTaskQueueDB.matchAndGetJob( resourceDict, extraConditions = extraConditions ) if DEBUG: print result if not result['OK']: return result result = result['Value'] if not result['matchFound']: return S_ERROR( 'No match found' ) jobID = result['jobId'] resAtt = gJobDB.getJobAttributes( jobID, ['OwnerDN', 'OwnerGroup', 'Status'] ) if not resAtt['OK']: return S_ERROR( 'Could not retrieve job attributes' ) if not resAtt['Value']: return S_ERROR( 'No attributes returned for job' ) if not resAtt['Value']['Status'] == 'Waiting': gLogger.error( 'Job %s matched by the TQ is not in Waiting state' % str( jobID ) ) result = gTaskQueueDB.deleteJob( jobID ) result = gJobDB.setJobStatus( jobID, status = 'Matched', minor = 'Assigned' ) result = gJobLoggingDB.addLoggingRecord( jobID, status = 'Matched', minor = 'Assigned', source = 'Matcher' ) result = gJobDB.getJobJDL( jobID ) if not result['OK']: return S_ERROR( 'Failed to get the job JDL' ) resultDict = {} resultDict['JDL'] = result['Value'] resultDict['JobID'] = jobID matchTime = time.time() - startTime gLogger.info( "Match time: [%s]" % str( matchTime ) ) gMonitor.addMark( "matchTime", matchTime ) # Get some extra stuff into the response returned resOpt = gJobDB.getJobOptParameters( jobID ) if resOpt['OK']: for key, value in resOpt['Value'].items(): resultDict[key] = value resAtt = gJobDB.getJobAttributes( jobID, ['OwnerDN', 'OwnerGroup'] ) if not resAtt['OK']: return S_ERROR( 'Could not retrieve job attributes' ) if not resAtt['Value']: return S_ERROR( 'No attributes returned for job' ) resultDict['DN'] = resAtt['Value']['OwnerDN'] resultDict['Group'] = resAtt['Value']['OwnerGroup'] return S_OK( resultDict )
def selectJob(self, resourceDescription): """ Main job selection function to find the highest priority job matching the resource capacity """ startTime = time.time() resourceDict = self.__processResourceDescription(resourceDescription) credDict = self.getRemoteCredentials() #Check credentials if Properties.GENERIC_PILOT not in credDict['properties']: #Not a generic pilot and requires a DN??? This smells fishy if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN'] != credDict['DN']: ownerDN = resourceDict['OwnerDN'] if Properties.JOB_SHARING in credDict['properties']: #Job sharing, is the DN in the same group? result = Registry.getGroupsForDN(ownerDN) if not result['OK']: return S_ERROR( "Requested owner DN %s does not have any group!" % ownerDN) groups = result['Value'] if credDict['group'] not in groups: #DN is not in the same group! bad body. gLogger.notice( "You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN) resourceDict['OwnerDN'] = credDict['DN'] else: #No generic pilot and not JobSharing? DN has to be the same! gLogger.notice("You can only match jobs for your DN (%s)" % credDict['DN']) resourceDict['OwnerDN'] = credDict['DN'] if Properties.PILOT not in credDict['properties']: #No pilot? Group has to be the same! if 'OwnerGroup' in resourceDict and resourceDict[ 'OwnerGroup'] != credDict['group']: gLogger.notice( "You can only match jobs for your group (%s)" % credDict['group']) resourceDict['OwnerGroup'] = credDict['group'] # Check the pilot DIRAC version if self.checkPilotVersion: if not 'DIRACVersion' in resourceDict: return S_ERROR( 'Version check requested and not provided by Pilot') # Check if the matching Request provides a VirtualOrganization if 'VirtualOrganization' in resourceDict: voName = resourceDict['VirtualOrganization'] # Check if the matching Request provides an OwnerGroup elif 'OwnerGroup' in resourceDict: voName = Registry.getVOForGroup(resourceDict['OwnerGroup']) # else take the default VirtualOrganization for the installation else: voName = Registry.getVOForGroup('') self.pilotVersion = gConfig.getValue( '/Operations/%s/%s/Versions/PilotVersion' % (voName, self.setup), '') if self.pilotVersion and resourceDict[ 'DIRACVersion'] != self.pilotVersion: return S_ERROR( 'Pilot version does not match the production version %s:%s' % \ ( resourceDict['DIRACVersion'], self.pilotVersion ) ) # Get common site mask and check the agent site result = gJobDB.getSiteMask(siteState='Active') if result['OK']: maskList = result['Value'] else: return S_ERROR('Internal error: can not get site mask') if not 'Site' in resourceDict: return S_ERROR('Missing Site Name in Resource JDL') siteName = resourceDict['Site'] if resourceDict['Site'] not in maskList: if 'GridCE' in resourceDict: del resourceDict['Site'] else: return S_ERROR('Site not in mask and GridCE not specified') resourceDict['Setup'] = self.serviceInfoDict['clientSetup'] if DEBUG: print "Resource description:" for key, value in resourceDict.items(): print key.rjust(20), value # Check if Job Limits are imposed onto the site extraConditions = {} if self.siteJobLimits: result = self.getExtraConditions(siteName) if result['OK']: extraConditions = result['Value'] if extraConditions: gLogger.info('Job Limits for site %s are: %s' % (siteName, str(extraConditions))) result = gTaskQueueDB.matchAndGetJob(resourceDict, extraConditions=extraConditions) if DEBUG: print result if not result['OK']: return result result = result['Value'] if not result['matchFound']: return S_ERROR('No match found') jobID = result['jobId'] resAtt = gJobDB.getJobAttributes(jobID, ['OwnerDN', 'OwnerGroup', 'Status']) if not resAtt['OK']: return S_ERROR('Could not retrieve job attributes') if not resAtt['Value']: return S_ERROR('No attributes returned for job') if not resAtt['Value']['Status'] == 'Waiting': gLogger.error('Job %s matched by the TQ is not in Waiting state' % str(jobID)) result = gTaskQueueDB.deleteJob(jobID) result = gJobDB.setJobStatus(jobID, status='Matched', minor='Assigned') result = gJobLoggingDB.addLoggingRecord(jobID, status='Matched', minor='Assigned', source='Matcher') result = gJobDB.getJobJDL(jobID) if not result['OK']: return S_ERROR('Failed to get the job JDL') resultDict = {} resultDict['JDL'] = result['Value'] resultDict['JobID'] = jobID matchTime = time.time() - startTime gLogger.info("Match time: [%s]" % str(matchTime)) gMonitor.addMark("matchTime", matchTime) # Get some extra stuff into the response returned resOpt = gJobDB.getJobOptParameters(jobID) if resOpt['OK']: for key, value in resOpt['Value'].items(): resultDict[key] = value resAtt = gJobDB.getJobAttributes(jobID, ['OwnerDN', 'OwnerGroup']) if not resAtt['OK']: return S_ERROR('Could not retrieve job attributes') if not resAtt['Value']: return S_ERROR('No attributes returned for job') resultDict['DN'] = resAtt['Value']['OwnerDN'] resultDict['Group'] = resAtt['Value']['OwnerGroup'] return S_OK(resultDict)
def selectJob( self, resourceDescription ): """ Main job selection function to find the highest priority job matching the resource capacity """ startTime = time.time() resourceDict = self.__processResourceDescription( resourceDescription ) credDict = self.getRemoteCredentials() #Check credentials if not generic pilot if Properties.GENERIC_PILOT in credDict[ 'properties' ]: #You can only match groups in the same VO vo = Registry.getVOForGroup( credDict[ 'group' ] ) result = Registry.getGroupsForVO( vo ) if result[ 'OK' ]: resourceDict[ 'OwnerGroup' ] = result[ 'Value' ] else: #If it's a private pilot, the DN has to be the same if Properties.PILOT in credDict[ 'properties' ]: gLogger.notice( "Setting the resource DN to the credentials DN" ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] #If it's a job sharing. The group has to be the same and just check that the DN (if any) # belongs to the same group elif Properties.JOB_SHARING in credDict[ 'properties' ]: resourceDict[ 'OwnerGroup' ] = credDict[ 'group' ] gLogger.notice( "Setting the resource group to the credentials group" ) if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN' ] != credDict[ 'DN' ]: ownerDN = resourceDict[ 'OwnerDN' ] result = Registry.getGroupsForDN( resourceDict[ 'OwnerDN' ] ) if not result[ 'OK' ] or credDict[ 'group' ] not in result[ 'Value' ]: #DN is not in the same group! bad boy. gLogger.notice( "You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN ) resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] #Nothing special, group and DN have to be the same else: resourceDict[ 'OwnerDN' ] = credDict[ 'DN' ] resourceDict[ 'OwnerGroup' ] = credDict[ 'group' ] # Check the pilot DIRAC version if self.__opsHelper.getValue( "Pilot/CheckVersion", True ): if 'ReleaseVersion' not in resourceDict: if not 'DIRACVersion' in resourceDict: return S_ERROR( 'Version check requested and not provided by Pilot' ) else: pilotVersion = resourceDict['DIRACVersion'] else: pilotVersion = resourceDict['ReleaseVersion'] validVersions = self.__opsHelper.getValue( "Pilot/Version", [] ) if validVersions and pilotVersion not in validVersions: return S_ERROR( 'Pilot version does not match the production version %s not in ( %s )' % \ ( pilotVersion, ",".join( validVersions ) ) ) #Check project if requested validProject = self.__opsHelper.getValue( "Pilot/Project", "" ) if validProject: if 'ReleaseProject' not in resourceDict: return S_ERROR( "Version check requested but expected project %s not received" % validProject ) if resourceDict[ 'ReleaseProject' ] != validProject: return S_ERROR( "Version check requested but expected project %s != received %s" % ( validProject, resourceDict[ 'ReleaseProject' ] ) ) # Update pilot information pilotInfoReported = False pilotReference = resourceDict.get( 'PilotReference', '' ) if pilotReference: if "PilotInfoReportedFlag" in resourceDict and not resourceDict['PilotInfoReportedFlag']: gridCE = resourceDict.get( 'GridCE', 'Unknown' ) site = resourceDict.get( 'Site', 'Unknown' ) benchmark = benchmark = resourceDict.get( 'PilotBenchmark', 0.0 ) gLogger.verbose('Reporting pilot info for %s: gridCE=%s, site=%s, benchmark=%f' % (pilotReference,gridCE,site,benchmark) ) result = gPilotAgentsDB.setPilotStatus( pilotReference, status = 'Running', gridSite = site, destination = gridCE, benchmark = benchmark ) if result['OK']: pilotInfoReported = True #Check the site mask if not 'Site' in resourceDict: return S_ERROR( 'Missing Site Name in Resource JDL' ) # Get common site mask and check the agent site result = gJobDB.getSiteMask( siteState = 'Active' ) if not result['OK']: return S_ERROR( 'Internal error: can not get site mask' ) maskList = result['Value'] siteName = resourceDict['Site'] if siteName not in maskList: # if 'GridCE' not in resourceDict: # return S_ERROR( 'Site not in mask and GridCE not specified' ) # Even if the site is banned, if it defines a CE, it must be able to check it # del resourceDict['Site'] # Banned site can only take Test jobs resourceDict['JobType'] = 'Test' resourceDict['Setup'] = self.serviceInfoDict['clientSetup'] gLogger.verbose( "Resource description:" ) for key in resourceDict: gLogger.verbose( "%s : %s" % ( key.rjust( 20 ), resourceDict[ key ] ) ) negativeCond = self.__limiter.getNegativeCondForSite( siteName ) result = gTaskQueueDB.matchAndGetJob( resourceDict, negativeCond = negativeCond ) if DEBUG: print result if not result['OK']: return result result = result['Value'] if not result['matchFound']: return S_ERROR( 'No match found' ) jobID = result['jobId'] resAtt = gJobDB.getJobAttributes( jobID, ['OwnerDN', 'OwnerGroup', 'Status'] ) if not resAtt['OK']: return S_ERROR( 'Could not retrieve job attributes' ) if not resAtt['Value']: return S_ERROR( 'No attributes returned for job' ) if not resAtt['Value']['Status'] == 'Waiting': gLogger.error( 'Job matched by the TQ is not in Waiting state', str( jobID ) ) result = gTaskQueueDB.deleteJob( jobID ) if not result[ 'OK' ]: return result return S_ERROR( "Job %s is not in Waiting state" % str( jobID ) ) attNames = ['Status','MinorStatus','ApplicationStatus','Site'] attValues = ['Matched','Assigned','Unknown',siteName] result = gJobDB.setJobAttributes( jobID, attNames, attValues ) # result = gJobDB.setJobStatus( jobID, status = 'Matched', minor = 'Assigned' ) result = gJobLoggingDB.addLoggingRecord( jobID, status = 'Matched', minor = 'Assigned', source = 'Matcher' ) result = gJobDB.getJobJDL( jobID ) if not result['OK']: return S_ERROR( 'Failed to get the job JDL' ) resultDict = {} resultDict['JDL'] = result['Value'] resultDict['JobID'] = jobID matchTime = time.time() - startTime gLogger.info( "Match time: [%s]" % str( matchTime ) ) gMonitor.addMark( "matchTime", matchTime ) # Get some extra stuff into the response returned resOpt = gJobDB.getJobOptParameters( jobID ) if resOpt['OK']: for key, value in resOpt['Value'].items(): resultDict[key] = value resAtt = gJobDB.getJobAttributes( jobID, ['OwnerDN', 'OwnerGroup'] ) if not resAtt['OK']: return S_ERROR( 'Could not retrieve job attributes' ) if not resAtt['Value']: return S_ERROR( 'No attributes returned for job' ) if self.__opsHelper.getValue( "JobScheduling/CheckMatchingDelay", True ): self.__limiter.updateDelayCounters( siteName, jobID ) # Report pilot-job association if pilotReference: result = gPilotAgentsDB.setCurrentJobID( pilotReference, jobID ) result = gPilotAgentsDB.setJobForPilot( jobID, pilotReference, updateStatus=False ) resultDict['DN'] = resAtt['Value']['OwnerDN'] resultDict['Group'] = resAtt['Value']['OwnerGroup'] resultDict['PilotInfoReportedFlag'] = pilotInfoReported return S_OK( resultDict )
def selectJob(self, resourceDescription): """ Main job selection function to find the highest priority job matching the resource capacity """ startTime = time.time() resourceDict = self.__processResourceDescription(resourceDescription) credDict = self.getRemoteCredentials() #Check credentials if not generic pilot if Properties.GENERIC_PILOT in credDict['properties']: #You can only match groups in the same VO vo = Registry.getVOForGroup(credDict['group']) result = Registry.getGroupsForVO(vo) if result['OK']: resourceDict['OwnerGroup'] = result['Value'] else: #If it's a private pilot, the DN has to be the same if Properties.PILOT in credDict['properties']: gLogger.notice("Setting the resource DN to the credentials DN") resourceDict['OwnerDN'] = credDict['DN'] #If it's a job sharing. The group has to be the same and just check that the DN (if any) # belongs to the same group elif Properties.JOB_SHARING in credDict['properties']: resourceDict['OwnerGroup'] = credDict['group'] gLogger.notice( "Setting the resource group to the credentials group") if 'OwnerDN' in resourceDict and resourceDict[ 'OwnerDN'] != credDict['DN']: ownerDN = resourceDict['OwnerDN'] result = Registry.getGroupsForDN(resourceDict['OwnerDN']) if not result['OK'] or credDict['group'] not in result[ 'Value']: #DN is not in the same group! bad boy. gLogger.notice( "You cannot request jobs from DN %s. It does not belong to your group!" % ownerDN) resourceDict['OwnerDN'] = credDict['DN'] #Nothing special, group and DN have to be the same else: resourceDict['OwnerDN'] = credDict['DN'] resourceDict['OwnerGroup'] = credDict['group'] # Check the pilot DIRAC version if self.__opsHelper.getValue("Pilot/CheckVersion", True): if 'ReleaseVersion' not in resourceDict: if not 'DIRACVersion' in resourceDict: return S_ERROR( 'Version check requested and not provided by Pilot') else: pilotVersion = resourceDict['DIRACVersion'] else: pilotVersion = resourceDict['ReleaseVersion'] validVersions = self.__opsHelper.getValue("Pilot/Version", []) if validVersions and pilotVersion not in validVersions: return S_ERROR( 'Pilot version does not match the production version %s not in ( %s )' % \ ( pilotVersion, ",".join( validVersions ) ) ) #Check project if requested validProject = self.__opsHelper.getValue("Pilot/Project", "") if validProject: if 'ReleaseProject' not in resourceDict: return S_ERROR( "Version check requested but expected project %s not received" % validProject) if resourceDict['ReleaseProject'] != validProject: return S_ERROR( "Version check requested but expected project %s != received %s" % (validProject, resourceDict['ReleaseProject'])) # Update pilot information pilotInfoReported = resourceDict.get('PilotInfoReportedFlag', False) pilotReference = resourceDict.get('PilotReference', '') if pilotReference and not pilotInfoReported: gridCE = resourceDict.get('GridCE', 'Unknown') site = resourceDict.get('Site', 'Unknown') benchmark = benchmark = resourceDict.get('PilotBenchmark', 0.0) gLogger.verbose( 'Reporting pilot info for %s: gridCE=%s, site=%s, benchmark=%f' % (pilotReference, gridCE, site, benchmark)) result = gPilotAgentsDB.setPilotStatus(pilotReference, status='Running', gridSite=site, destination=gridCE, benchmark=benchmark) if result['OK']: pilotInfoReported = True #Check the site mask if not 'Site' in resourceDict: return S_ERROR('Missing Site Name in Resource JDL') # Get common site mask and check the agent site result = gJobDB.getSiteMask(siteState='Active') if not result['OK']: return S_ERROR('Internal error: can not get site mask') maskList = result['Value'] siteName = resourceDict['Site'] if siteName not in maskList: # if 'GridCE' not in resourceDict: # return S_ERROR( 'Site not in mask and GridCE not specified' ) # Even if the site is banned, if it defines a CE, it must be able to check it # del resourceDict['Site'] # Banned site can only take Test jobs resourceDict['JobType'] = 'Test' resourceDict['Setup'] = self.serviceInfoDict['clientSetup'] gLogger.verbose("Resource description:") for key in resourceDict: gLogger.verbose("%s : %s" % (key.rjust(20), resourceDict[key])) negativeCond = self.__limiter.getNegativeCondForSite(siteName) result = gTaskQueueDB.matchAndGetJob(resourceDict, negativeCond=negativeCond) if DEBUG: print result if not result['OK']: return result result = result['Value'] if not result['matchFound']: return S_ERROR('No match found') jobID = result['jobId'] resAtt = gJobDB.getJobAttributes(jobID, ['OwnerDN', 'OwnerGroup', 'Status']) if not resAtt['OK']: return S_ERROR('Could not retrieve job attributes') if not resAtt['Value']: return S_ERROR('No attributes returned for job') if not resAtt['Value']['Status'] == 'Waiting': gLogger.error('Job matched by the TQ is not in Waiting state', str(jobID)) result = gTaskQueueDB.deleteJob(jobID) if not result['OK']: return result return S_ERROR("Job %s is not in Waiting state" % str(jobID)) attNames = ['Status', 'MinorStatus', 'ApplicationStatus', 'Site'] attValues = ['Matched', 'Assigned', 'Unknown', siteName] result = gJobDB.setJobAttributes(jobID, attNames, attValues) # result = gJobDB.setJobStatus( jobID, status = 'Matched', minor = 'Assigned' ) result = gJobLoggingDB.addLoggingRecord(jobID, status='Matched', minor='Assigned', source='Matcher') result = gJobDB.getJobJDL(jobID) if not result['OK']: return S_ERROR('Failed to get the job JDL') resultDict = {} resultDict['JDL'] = result['Value'] resultDict['JobID'] = jobID matchTime = time.time() - startTime gLogger.info("Match time: [%s]" % str(matchTime)) gMonitor.addMark("matchTime", matchTime) # Get some extra stuff into the response returned resOpt = gJobDB.getJobOptParameters(jobID) if resOpt['OK']: for key, value in resOpt['Value'].items(): resultDict[key] = value resAtt = gJobDB.getJobAttributes(jobID, ['OwnerDN', 'OwnerGroup']) if not resAtt['OK']: return S_ERROR('Could not retrieve job attributes') if not resAtt['Value']: return S_ERROR('No attributes returned for job') if self.__opsHelper.getValue("JobScheduling/CheckMatchingDelay", True): self.__limiter.updateDelayCounters(siteName, jobID) # Report pilot-job association if pilotReference: result = gPilotAgentsDB.setCurrentJobID(pilotReference, jobID) result = gPilotAgentsDB.setJobForPilot(jobID, pilotReference, updateStatus=False) resultDict['DN'] = resAtt['Value']['OwnerDN'] resultDict['Group'] = resAtt['Value']['OwnerGroup'] resultDict['PilotInfoReportedFlag'] = pilotInfoReported return S_OK(resultDict)
def getProxy(self, userDict): """ Generate user proxy :param dict userDict: user description dictionary with possible fields: FullName, UserName, DN, EMail, DiracGroup :return: S_OK(basestring)/S_ERROR() -- basestring is a proxy string """ userDN = userDict.get('DN') if not userDN: return S_ERROR('Incomplete user information') diracGroup = userDict.get('DiracGroup') if not diracGroup: return S_ERROR('Incomplete user information') result = Registry.getGroupsForDN(userDN) if not result['OK']: return result validGroups = result['Value'] if diracGroup not in validGroups: return S_ERROR('Invalid group %s for user' % diracGroup) voName = Registry.getVOForGroup(diracGroup) if not voName: return S_ERROR('Can not determine VO for group %s' % diracGroup) csVOMSMapping = Registry.getVOMSAttributeForGroup(diracGroup) if not csVOMSMapping: return S_ERROR("No VOMS mapping defined for group %s in the CS" % diracGroup) vomsAttribute = csVOMSMapping vomsVO = Registry.getVOMSVOForGroup(diracGroup) puspServiceURL = self.parameters.get('ServiceURL') if not puspServiceURL: return S_ERROR('Can not determine PUSP service URL for VO %s' % voName) user = userDN.split(":")[-1] puspURL = "%s?voms=%s:%s&proxy-renewal=false&disable-voms-proxy=false" \ "&rfc-proxy=true&cn-label=user:%s" % (puspServiceURL, vomsVO, vomsAttribute, user) try: proxy = urllib.urlopen(puspURL).read() except Exception as e: return S_ERROR('Failed to get proxy from the PUSP server') chain = X509Chain() chain.loadChainFromString(proxy) chain.loadKeyFromString(proxy) result = chain.getCredentials() if not result['OK']: return S_ERROR('Failed to get a valid PUSP proxy') credDict = result['Value'] if credDict['identity'] != userDN: return S_ERROR( 'Requested DN does not match the obtained one in the PUSP proxy' ) timeLeft = credDict['secondsLeft'] result = chain.generateProxyToString(lifeTime=timeLeft, diracGroup=diracGroup) if not result['OK']: return result proxyString = result['Value'] return S_OK((proxyString, timeLeft))