-
Notifications
You must be signed in to change notification settings - Fork 110
default stageout commands for protocols #12367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,7 @@ | |
| import re | ||
|
|
||
| from builtins import str, range | ||
|
|
||
| from urllib.parse import urlparse | ||
|
|
||
| class RucioFileCatalog(dict): | ||
| """ | ||
|
|
@@ -37,7 +37,7 @@ def addMapping(self, protocol, match, result, | |
| """ | ||
| Add an lfn to pfn mapping to this instance | ||
| :param protocol: name of protocol, for example XRootD | ||
| :param match: regular expression string to perform path matching | ||
| :param match: regular expression string to perform path matching | ||
| :param result: result of the path matching | ||
| :param chain: name of chained protocol | ||
| :param mapping_type: type of path matching | ||
|
|
@@ -52,11 +52,14 @@ def addMapping(self, protocol, match, result, | |
|
|
||
| def _doMatch(self, protocol, path, style, caller): | ||
| """ | ||
| Generalised way of building up the mappings. | ||
| Generalised way of building up the mappings. | ||
| :param protocol: the name of a protocol, for example XRootD | ||
| :path: a LFN path, for example /store/abc/xyz.root | ||
| :style: type of conversion. lfn-to-pfn is to convert LFN to PFN and pfn-to-pfn is for PFN to LFN | ||
| :caller is the method from there this method was called. It's used for resolving chained rules. When a rule is chained, the path translation of protocol defined in "chain" attribute should be applied first before the one specified in this rule. Here is an example. In this storage description, https://gitlab.cern.ch/SITECONF/T1_DE_KIT/-/blob/master/storage.json, the rule of protocol WebDAV of volume KIT_MSS is chained to the protocol pnfs of the same volume. The path translation of WebDAV rule must be done by applying the path translation of pnfs rule first before its own path translation is applied. | ||
| :caller: is the method from there this method was called. It's used for resolving chained rules. | ||
| When a rule is chained, the path translation of protocol defined in "chain" attribute should be applied first before the one specified in this rule. Here is an example. | ||
| In this storage description, https://gitlab.cern.ch/SITECONF/T1_DE_KIT/-/blob/master/storage.json, the rule of protocol WebDAV of volume KIT_MSS is chained to the protocol pnfs of the same volume. | ||
| The path translation of WebDAV rule must be done by applying the path translation of pnfs rule first before its own path translation is applied. | ||
| """ | ||
| for mapping in self[style]: | ||
| if mapping['protocol'] != protocol: | ||
|
|
@@ -136,7 +139,7 @@ def storageJsonPath(currentSite, currentSubsite, storageSite): | |
| # return path override if it is defined and exists | ||
| siteConfigPathOverride = os.getenv('WMAGENT_RUCIO_CATALOG_OVERRIDE', None) | ||
| if siteConfigPathOverride and os.path.exists(siteConfigPathOverride): | ||
| return siteConfigPathOverride | ||
| return siteConfigPathOverride | ||
|
|
||
| # get site config | ||
| siteConfigPath = os.getenv('SITECONFIG_PATH', None) | ||
|
|
@@ -182,7 +185,7 @@ def readRFC(filename, storageSite, volume, protocol): | |
| except Exception as ex: | ||
| msg = "Error reading storage description file: %s\n" % filename | ||
| msg += str(ex) | ||
| raise RuntimeError(msg) | ||
| raise RuntimeError(msg) from ex | ||
| # now loop over elements, select the one matched with inputs (storageSite, volume, protocol) and fill lfn-to-pfn | ||
| for jsElement in jsElements: | ||
| # check to see if the storageSite and volume matchs with "site" and "volume" in storage.json | ||
|
|
@@ -239,9 +242,61 @@ def rseName(currentSite, currentSubsite, storageSite, volume): | |
| except Exception as ex: | ||
| msg = "RucioFileCatalog.py:rseName() Error reading storage.json: %s\n" % storageJsonName | ||
| msg += str(ex) | ||
| raise RuntimeError(msg) | ||
| raise RuntimeError(msg) from ex | ||
| for jsElement in jsElements: | ||
| if jsElement['site'] == storageSite and jsElement['volume'] == volume: | ||
| rse = jsElement['rse'] | ||
| break | ||
| return rse | ||
|
|
||
| def get_default_cmd(currentSite, currentSubsite, storageSite, volume, protocolName): | ||
| """ | ||
| Return default command for a protocol, for example: | ||
| https://gitlab.cern.ch/SITECONF/T1_DE_KIT/-/blob/master/storage.json?ref_type=heads#L17 | ||
| :currentSite is the site where jobs are executing | ||
| :currentSubsite is the sub site if jobs are running here | ||
| :storageSite is the site for storage | ||
| :volume is the volume name, for example: | ||
| https://gitlab.cern.ch/SITECONF/T1_DE_KIT/-/blob/master/storage.json?ref_type=heads#L3 | ||
| :protocolName is the 'protocol' in site-local-config.xml under stageOut | ||
| """ | ||
|
|
||
| storageJsonName = storageJsonPath(currentSite, currentSubsite, storageSite) | ||
| try: | ||
| with open(storageJsonName, encoding="utf-8") as jsonFile: | ||
| jsElements = json.load(jsonFile) | ||
| except Exception as ex: | ||
| msg = "RucioFileCatalog.py:getDefaultCmd() Error reading storage.json: %s\n" % storageJsonName | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please update this error message to keep consistent with the actual method name? |
||
| msg += str(ex) | ||
| raise RuntimeError(msg) from ex | ||
|
|
||
| url_scheme = '' | ||
|
|
||
| for entry in jsElements: | ||
| if entry.get('site') != storageSite or entry.get('volume') != volume: | ||
| continue | ||
|
|
||
| for proto in entry.get("protocols", []): | ||
| if proto.get("protocol") != protocolName: | ||
| continue | ||
|
|
||
| # First try rules | ||
| rules = proto.get("rules", []) | ||
| if rules: | ||
| pfn = rules[0].get("pfn", "") | ||
| url_scheme = urlparse(pfn).scheme | ||
|
|
||
| # If no rules try 'prefix' | ||
| if not url_scheme and "prefix" in proto: | ||
| url_scheme = urlparse(proto["prefix"]).scheme | ||
|
|
||
| # Map scheme to command | ||
| return { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest moving this map to the top of this module, as a global variable, such that it is easier to identify this map in the code. Perhaps: |
||
| 'root': 'xrdcp', | ||
| 'davs': 'gfal2', | ||
| 'file': 'cp' | ||
| }.get(url_scheme, 'gfal2') | ||
|
|
||
| break # matching site+volume found and processed | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest adding a log record here to say that the json was processed but no matches were found. |
||
|
|
||
| return None #no matched protocol so command is None | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for this line, I would add a logging.ERROR report lack of information (site/volume etc).
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @amaltaro, I addressed all your comments |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean "where" instead of "there"?