def getPathPermissions(self, lfns, credDict): """Get permissions for the given user/group to manipulate the given lfns""" res = checkArgumentFormat(lfns) if not res["OK"]: return res lfns = res["Value"] return self.securityManager.getPathPermissions(list(lfns), credDict)
def getPathPermissions(self, lfns, credDict): """ Get permissions for the given user/group to manipulate the given lfns """ res = checkArgumentFormat( lfns ) if not res['OK']: return res lfns = res['Value'] return self.securityManager.getPathPermissions( lfns.keys(), credDict )
def hasAccess(self, opType, paths, credDict): """ Get permissions for the given user/group to execute the given operation on the given paths returns Successful dict with True/False """ res = checkArgumentFormat(paths) if not res['OK']: return res paths = res['Value'] return self.securityManager.hasAccess(opType, paths, credDict)
def hasAccess( self, opType, paths, credDict ): """ Get permissions for the given user/group to execute the given operation on the given paths returns Successful dict with True/False """ res = checkArgumentFormat( paths ) if not res['OK']: return res paths = res['Value'] return self.securityManager.hasAccess( opType, paths, credDict )
def _checkPathPermissions(self, operation, lfns, credDict): res = checkArgumentFormat(lfns) if not res['OK']: return res lfns = res['Value'] res = self.securityManager.hasAccess(operation, lfns.keys(), credDict) if not res['OK']: return res # Do not consider those paths for which we failed to determine access failed = res['Value']['Failed'] for lfn in failed.keys(): lfns.pop(lfn) # Do not consider those paths for which access is denied successful = {} for lfn, access in res['Value']['Successful'].items(): if not access: failed[lfn] = 'Permission denied' else: successful[lfn] = lfns[lfn] return S_OK({'Successful': successful, 'Failed': failed})
def _checkPathPermissions(self, operation, lfns, credDict): res = checkArgumentFormat(lfns) if not res["OK"]: return res lfns = res["Value"] res = self.securityManager.hasAccess(operation, list(lfns), credDict) if not res["OK"]: return res # Do not consider those paths for which we failed to determine access failed = res["Value"]["Failed"] for lfn in failed: lfns.pop(lfn) # Do not consider those paths for which access is denied successful = {} for lfn, access in res["Value"]["Successful"].items(): if not access: failed[lfn] = "Permission denied" else: successful[lfn] = lfns[lfn] return S_OK({"Successful": successful, "Failed": failed})
def _checkPathPermissions( self, operation, lfns, credDict ): res = checkArgumentFormat( lfns ) if not res['OK']: return res lfns = res['Value'] res = self.securityManager.hasAccess( operation, lfns.keys(), credDict ) if not res['OK']: return res # Do not consider those paths for which we failed to determine access failed = res['Value']['Failed'] for lfn in failed.keys(): lfns.pop( lfn ) # Do not consider those paths for which access is denied successful = {} for lfn, access in res['Value']['Successful'].items(): if not access: failed[lfn] = 'Permission denied' else: successful[lfn] = lfns[lfn] return S_OK( {'Successful':successful, 'Failed':failed} )
def w_execute( self, *parms, **kws ): """ Write method executor. If one of the LFNs given as input does not pass a condition defined for the master catalog, we return S_ERROR without trying anything else :param fcConditions: either a dict or a string, to be propagated to the FCConditionParser If it is a string, it is given for all catalogs If it is a dict, it has to be { catalogName: condition}, and only the specific condition for the catalog will be given CAUTION !!! If the method is a write no_lfn method, then the return value are completely different We only return the result of the master catalog """ successful = {} failed = {} failedCatalogs = {} successfulCatalogs = {} specialConditions = kws.pop( 'fcConditions' ) if 'fcConditions' in kws else None allLfns = [] lfnMapDict = {} masterResult = {} parms1 = [] if self.call not in self.no_lfn_methods: fileInfo = parms[0] result = checkArgumentFormat( fileInfo, generateMap = True ) if not result['OK']: return result fileInfo, lfnMapDict = result['Value'] # No need to check the LFNs again in the clients kws['LFNChecking'] = False allLfns = fileInfo.keys() parms1 = parms[1:] for catalogName, oCatalog, master in self.writeCatalogs: # Skip if the method is not implemented in this catalog # NOTE: it is impossible for the master since the write method list is populated # only from the master catalog, and if the method is not there, __getattr__ # would raise an exception if not oCatalog.hasCatalogMethod( self.call ): continue method = getattr( oCatalog, self.call ) if self.call in self.no_lfn_methods: result = method( *parms, **kws ) else: if isinstance( specialConditions, dict ): condition = specialConditions.get( catalogName ) else: condition = specialConditions # Check whether this catalog should be used for this method res = self.condParser( catalogName, self.call, fileInfo, condition = condition ) # condParser never returns S_ERROR condEvals = res['Value']['Successful'] # For a master catalog, ALL the lfns should be valid if master: if any([not valid for valid in condEvals.values()]): gLogger.error( "The master catalog is not valid for some LFNS", condEvals ) return S_ERROR( "The master catalog is not valid for some LFNS %s" % condEvals ) validLFNs = dict( ( lfn, fileInfo[lfn] ) for lfn in condEvals if condEvals[lfn] ) invalidLFNs = [lfn for lfn in condEvals if not condEvals[lfn]] if invalidLFNs: gLogger.debug( "Some LFNs are not valid for operation '%s' on catalog '%s' : %s" % ( self.call, catalogName, invalidLFNs ) ) result = method( validLFNs, *parms1, **kws ) if master: masterResult = result if not result['OK']: if master: # If this is the master catalog and it fails we don't want to continue with the other catalogs self.log.error( "Failed to execute call on master catalog", "%s on %s: %s" % ( self.call, catalogName, result['Message'] ) ) return result else: # Otherwise we keep the failed catalogs so we can update their state later failedCatalogs[catalogName] = result['Message'] else: successfulCatalogs[catalogName] = result['Value'] if allLfns: if result['OK']: for lfn, message in result['Value']['Failed'].items(): # Save the error message for the failed operations failed.setdefault( lfn, {} )[catalogName] = message if master: # If this is the master catalog then we should not attempt the operation on other catalogs fileInfo.pop( lfn, None ) for lfn, result in result['Value']['Successful'].items(): # Save the result return for each file for the successful operations successful.setdefault( lfn, {} )[catalogName] = result if allLfns: # This recovers the states of the files that completely failed i.e. when S_ERROR is returned by a catalog for catalogName, errorMessage in failedCatalogs.items(): for lfn in allLfns: failed.setdefault( lfn, {} )[catalogName] = errorMessage # Restore original lfns if they were changed by normalization if lfnMapDict: for lfn in failed.keys(): failed[lfnMapDict.get( lfn, lfn )] = failed.pop( lfn ) for lfn in successful.keys(): successful[lfnMapDict.get( lfn, lfn )] = successful.pop( lfn ) resDict = {'Failed':failed, 'Successful':successful} return S_OK( resDict ) else: # FIXME: Return just master result here. This is temporary as more detailed # per catalog result needs multiple fixes in various client calls return masterResult
def w_execute(self, *parms, **kws): """Write method executor. If one of the LFNs given as input does not pass a condition defined for the master catalog, we return S_ERROR without trying anything else :param fcConditions: either a dict or a string, to be propagated to the FCConditionParser * If it is a string, it is given for all catalogs * If it is a dict, it has to be { catalogName: condition}, and only the specific condition for the catalog will be given .. warning :: If the method is a write no_lfn method, then the return value are completely different. We only return the result of the master catalog """ successful = {} failed = {} failedCatalogs = {} successfulCatalogs = {} specialConditions = kws.pop("fcConditions") if "fcConditions" in kws else None allLfns = [] lfnMapDict = {} masterResult = {} parms1 = [] if self.call not in self.no_lfn_methods: fileInfo = parms[0] result = checkArgumentFormat(fileInfo, generateMap=True) if not result["OK"]: return result fileInfo, lfnMapDict = result["Value"] # No need to check the LFNs again in the clients kws["LFNChecking"] = False allLfns = list(fileInfo) parms1 = parms[1:] for catalogName, oCatalog, master in self.writeCatalogs: # Skip if the method is not implemented in this catalog # NOTE: it is impossible for the master since the write method list is populated # only from the master catalog, and if the method is not there, __getattr__ # would raise an exception if not oCatalog.hasCatalogMethod(self.call): continue method = getattr(oCatalog, self.call) if self.call in self.no_lfn_methods: result = method(*parms, **kws) else: if isinstance(specialConditions, dict): condition = specialConditions.get(catalogName) else: condition = specialConditions # Check whether this catalog should be used for this method res = self.condParser(catalogName, self.call, fileInfo, condition=condition) # condParser never returns S_ERROR condEvals = res["Value"]["Successful"] # For a master catalog, ALL the lfns should be valid if master: if any([not valid for valid in condEvals.values()]): gLogger.error("The master catalog is not valid for some LFNS", condEvals) return S_ERROR("The master catalog is not valid for some LFNS %s" % condEvals) validLFNs = dict((lfn, fileInfo[lfn]) for lfn in condEvals if condEvals[lfn]) # We can skip the execution without worry, # since at this level it is for sure not a master catalog if not validLFNs: gLogger.debug("No valid LFN, skipping the call") continue invalidLFNs = [lfn for lfn in condEvals if not condEvals[lfn]] if invalidLFNs: gLogger.debug( "Some LFNs are not valid for operation '%s' on catalog '%s' : %s" % (self.call, catalogName, invalidLFNs) ) result = method(validLFNs, *parms1, **kws) if master: masterResult = result if not result["OK"]: if master: # If this is the master catalog and it fails we don't want to continue with the other catalogs self.log.error( "Failed to execute call on master catalog", "%s on %s: %s" % (self.call, catalogName, result["Message"]), ) return result else: # Otherwise we keep the failed catalogs so we can update their state later failedCatalogs[catalogName] = result["Message"] else: successfulCatalogs[catalogName] = result["Value"] if allLfns: if result["OK"]: for lfn, message in result["Value"]["Failed"].items(): # Save the error message for the failed operations failed.setdefault(lfn, {})[catalogName] = message if master: # If this is the master catalog then we should not attempt the operation on other catalogs fileInfo.pop(lfn, None) for lfn, result in result["Value"]["Successful"].items(): # Save the result return for each file for the successful operations successful.setdefault(lfn, {})[catalogName] = result if allLfns: # This recovers the states of the files that completely failed i.e. when S_ERROR is returned by a catalog for catalogName, errorMessage in failedCatalogs.items(): for lfn in allLfns: failed.setdefault(lfn, {})[catalogName] = errorMessage # Restore original lfns if they were changed by normalization if lfnMapDict: for lfn in list(failed): failed[lfnMapDict.get(lfn, lfn)] = failed.pop(lfn) for lfn in list(successful): successful[lfnMapDict.get(lfn, lfn)] = successful.pop(lfn) resDict = {"Failed": failed, "Successful": successful} return S_OK(resDict) else: # FIXME: Return just master result here. This is temporary as more detailed # per catalog result needs multiple fixes in various client calls return masterResult