Skip to content

Commit 9631a8f

Browse files
authored
Policies: Restructure and add docs on how to specify version support post-36 (#411)
1 parent 148180e commit 9631a8f

File tree

1 file changed

+110
-52
lines changed

1 file changed

+110
-52
lines changed

docs/operator/policy_packages.md

Lines changed: 110 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -30,46 +30,89 @@ is suffixed with the VO name (for example, `package-vo1` or
3030

3131
## Creating a policy package
3232

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:
3534

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)
3638
- A `permission.py` module implementing permission
3739
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).
4242

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:
5044

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+
```
5560

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.
5961

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.
6780

6881
```python
69-
SUPPORTED_VERSION = [ "1.30", "1.31", "32" ]
82+
SUPPORTED_VERSION = '~=36.0'
7083
```
7184

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
73116
returns a dictionary of custom algorithms implemented within the package.
74117
In fact, this structure should be a "dictionary of dictionaries" where
75118
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
109152
with the name of the virtual organisation that owns the policy package,
110153
to avoid naming conflicts on multi-VO Rucio installations.
111154

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+
112193
### lfn2pfn vs. non_deterministic_pfn algorithms
113194

114195
`lfn2pfn` algorithms and `non_deterministic_pfn` algorithms are
@@ -134,29 +215,6 @@ the config file is used instead. The `non_deterministic_pfn` algorithm
134215
to be used is determined by the `naming_convention` attribute of the
135216
relevant RSE.
136217

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-
160218
## Deploying Policy Packages in containers
161219

162220
It is now common to deploy Rucio using containers managed by software

0 commit comments

Comments
 (0)