@@ -30,46 +30,89 @@ is suffixed with the VO name (for example, `package-vo1` or
30
30
31
31
## Creating a policy package
32
32
33
- The structure of a policy package is very simple. It can contain the
34
- following:
33
+ The basic elements of a policy package are the following:
35
34
35
+ - An ` __init__.py ` file that:
36
+ - indicates the supported Rucio version via the ` SUPPORTED_VERSION ` field;
37
+ - indicates the algorithms provided by the package (optional)
36
38
- A ` permission.py ` module implementing permission
37
39
customisations (optional).
38
- - A ` schema.py ` module implementing schema customisations (optional).
39
- - An ` __init__.py ` file that can optionally return a dictionary of
40
- algorithms provided by the package.
41
- - It should also contain a SUPPORTED_VERSION field.
40
+ - A ` schema.py ` module implementing schema customization (optional).
41
+ - One or more files for experiment-specific algorithms (optional).
42
42
43
- The ` permission.py ` and ` schema.py ` modules are optional; an experiment
44
- that does not need to customise these modules can omit one or both of
45
- them from the policy package and the Rucio generic versions will be
46
- used instead. If these modules are required, the easiest way to create
47
- them is to modify the generic versions from the Rucio codebase. These
48
- can be found in ` lib/rucio/core/permission/generic.py ` and
49
- ` lib/rucio/common/schema/generic.py ` respectively.
43
+ The recommended Python package layouts can be found [ here] ( https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/ ) . An example ` src ` -layout based policy package is as such:
50
44
51
- The ` has_permission ` function in the permission module may return ` None `
52
- if your experiment does not implement a custom permission check for a
53
- particular action. In this case, the generic permission module will be
54
- called for this action instead.
45
+ ```
46
+ experiment-rucio-policy-package
47
+ │ README.md
48
+ │ pyproject.toml
49
+ │
50
+ └───src
51
+ │ │
52
+ │ └───experiment-rucio-policy-package
53
+ │ │ __init__.py # required
54
+ │ │ permission.py # optional
55
+ │ │ schema.py # optional
56
+ │ │ pfn2lfn.py # optional (deterministic scope translation algorithm)
57
+ │ │ non_deterministic_pfn.py # optional (non-deterministic scope translation algorithm)
58
+ │ │ ...
59
+ ```
55
60
56
- The schema module of a policy package does not need to define all of
57
- the schema values. Any missing ones will automatically be loaded from
58
- the generic schema module instead.
59
61
60
- ` __init__.py ` should include a
61
- ` SUPPORTED_VERSION ` field indicating the major version(s) of Rucio
62
- that your package supports. This is checked against the Rucio server
63
- version to ensure compatibility when loading the policy package. This
64
- field can be a string if the policy package only supports a single
65
- Rucio version, or a list of strings if it supports multiple versions.
66
- Example:
62
+ ### ` __init__.py `
63
+
64
+ #### ` SUPPORTED_VERSION `
65
+
66
+ ` __init__.py ` should define a ` str | list[str] ` called ` SUPPORTED_VERSION ` ,
67
+ indicating the version(s) of Rucio that your package supports.
68
+
69
+ This is checked against the Rucio server
70
+ version to ensure compatibility when loading the policy package.
71
+
72
+ ##### From Rucio 36
73
+ From Rucio 36, version checking was modified
74
+ to use [ PEP-compliant version specifiers] ( https://peps.python.org/pep-0440/#version-specifiers ) .
75
+
76
+ For example, to specify support for the entire Rucio 36 release line (so 36.1.0, 36.2.0...)
77
+ without yet supporting Rucio 37,
78
+ the [ ** compatible release** operator] ( https://peps.python.org/pep-0440/#compatible-release ) ` ~= `
79
+ can be used, as seen below.
67
80
68
81
``` python
69
- SUPPORTED_VERSION = [ " 1.30 " , " 1.31 " , " 32 " ]
82
+ SUPPORTED_VERSION = ' ~=36.0 '
70
83
```
71
84
72
- It can also contain an optional function called ` get_algorithms ` that
85
+ Multiple constraints can be specified, either as a string:
86
+
87
+ ``` python
88
+ SUPPORTED_VERSION = ' ~=36.0,!=36.4.0'
89
+ ```
90
+
91
+ Or as a list:
92
+
93
+ ``` python
94
+ SUPPORTED_VERSION = [' ~=36.0' ,' !=36.4.0' ]
95
+ ```
96
+
97
+ ##### Before Rucio 36
98
+
99
+ On Rucio versions older than 36, only major versions can be specified.
100
+ This can be done as either a string:
101
+
102
+ ``` python
103
+ SUPPORTED_VERSION = ' 35'
104
+ ```
105
+
106
+ Or as a list, to indicate support for multiple major versions:
107
+
108
+ ``` python
109
+ SUPPORTED_VERSION = [' 34' , ' 35' ]
110
+ ```
111
+
112
+ #### ` get_algorithms `
113
+
114
+ The ` __init__.py ` file can also contain
115
+ an optional function called ` get_algorithms ` that
73
116
returns a dictionary of custom algorithms implemented within the package.
74
117
In fact, this structure should be a "dictionary of dictionaries" where
75
118
the outer dictionary contains algorithm types, and each inner
@@ -109,6 +152,44 @@ In all cases the names used to register the functions (e.g. `voname_extract_scop
109
152
with the name of the virtual organisation that owns the policy package,
110
153
to avoid naming conflicts on multi-VO Rucio installations.
111
154
155
+ ### Permission and schema modules
156
+
157
+ The ` permission.py ` and ` schema.py ` modules are optional; an experiment
158
+ that does not need to customise these modules can omit one or both of
159
+ them from the policy package and the Rucio generic versions will be
160
+ used instead. If these modules are required, the easiest way to create
161
+ them is to modify the generic versions from the Rucio codebase. These
162
+ can be found in
163
+ [ ` lib/rucio/core/permission/generic.py ` ] ( https://github.com/rucio/rucio/blob/master/lib/rucio/core/permission/generic.py )
164
+ and [ ` lib/rucio/common/schema/generic.py ` ] ( https://github.com/rucio/rucio/blob/master/lib/rucio/common/schema/generic.py ) respectively.
165
+
166
+ The ` has_permission ` function in the permission module may return ` None `
167
+ if your experiment does not implement a custom permission check for a
168
+ particular action. In this case, the generic permission module will be
169
+ called for this action instead.
170
+
171
+ The schema module of a policy package does not need to define all of
172
+ the schema values. Any missing ones will automatically be loaded from
173
+ the generic schema module instead.
174
+
175
+ ## Policy algorithms
176
+
177
+ ### Adding a new algorithm class
178
+
179
+ The system for registering algorithms within policy packages is
180
+ intended to be extensible so that new algorithm classes can be added
181
+ relatively easily. The basic workflow is as follows:
182
+
183
+ - The ` get_algorithms ` function within the policy package (see above)
184
+ should return a dictionary of functions of the new class, indexed
185
+ by name
186
+ - The core Rucio code should maintain a dictionary of functions of the
187
+ new class, ready to be called when required. The details of this
188
+ will differ depending on what the new class actually does and how it
189
+ integrates with the Rucio code, but typically the algorithm name to
190
+ be used will be selected by a value in the config file, as for the
191
+ current ` lfn2pfn ` and ` non_deterministic_pfn ` algorithm types.
192
+
112
193
### lfn2pfn vs. non_deterministic_pfn algorithms
113
194
114
195
` lfn2pfn ` algorithms and ` non_deterministic_pfn ` algorithms are
@@ -134,29 +215,6 @@ the config file is used instead. The `non_deterministic_pfn` algorithm
134
215
to be used is determined by the ` naming_convention ` attribute of the
135
216
relevant RSE.
136
217
137
- ## Adding a new algorithm class
138
-
139
- The system for registering algorithms within policy packages is
140
- intended to be extensible so that new algorithm classes can be added
141
- relatively easily. The basic workflow is as follows:
142
-
143
- - The ` get_algorithms ` function within the policy package (see above)
144
- should return a dictionary of functions of the new class, indexed
145
- by name
146
- - The core Rucio code should maintain a dictionary of functions of the
147
- new class, ready to be called when required. The details of this
148
- will differ depending on what the new class actually does and how it
149
- integrates with the Rucio code, but typically the algorithm name to
150
- be used will be selected by a value in the config file, as for the
151
- current ` lfn2pfn ` and ` non_deterministic_pfn ` algorithm types.
152
- - Before the algorithm is called for the first time, the core Rucio
153
- code should call ` rucio.common.utils.register_policy_package_algorithms `
154
- to import the algorithms for this class from the policy package and
155
- store them in its internal dictionary. This function takes care of
156
- the complexities of interfacing with the policy package, such as
157
- importing the package if necessary, and dealing with multiple
158
- packages in multi-VO Rucio installations.
159
-
160
218
## Deploying Policy Packages in containers
161
219
162
220
It is now common to deploy Rucio using containers managed by software
0 commit comments