rucio 37.2.0__py3-none-any.whl → 37.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/common/plugins.py +1 -1
- rucio/core/did.py +2 -3
- rucio/core/replica.py +1 -1
- rucio/db/sqla/util.py +1 -1
- rucio/gateway/authentication.py +58 -88
- rucio/gateway/config.py +63 -75
- rucio/gateway/did.py +245 -329
- rucio/gateway/dirac.py +33 -34
- rucio/gateway/exporter.py +27 -30
- rucio/gateway/importer.py +12 -14
- rucio/gateway/lifetime_exception.py +16 -24
- rucio/gateway/lock.py +27 -40
- rucio/gateway/replica.py +223 -226
- rucio/gateway/rse.py +191 -218
- rucio/gateway/rule.py +115 -146
- rucio/gateway/scope.py +18 -25
- rucio/gateway/trace.py +48 -0
- rucio/vcsversion.py +3 -3
- rucio/web/rest/flaskapi/v1/accounts.py +2 -2
- rucio/web/rest/flaskapi/v1/auth.py +15 -0
- rucio/web/rest/flaskapi/v1/common.py +3 -0
- rucio/web/rest/flaskapi/v1/config.py +7 -7
- rucio/web/rest/flaskapi/v1/dids.py +55 -55
- rucio/web/rest/flaskapi/v1/dirac.py +2 -2
- rucio/web/rest/flaskapi/v1/export.py +1 -1
- rucio/web/rest/flaskapi/v1/import.py +1 -1
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +5 -5
- rucio/web/rest/flaskapi/v1/locks.py +4 -4
- rucio/web/rest/flaskapi/v1/main.py +17 -10
- rucio/web/rest/flaskapi/v1/replicas.py +29 -28
- rucio/web/rest/flaskapi/v1/rses.py +37 -37
- rucio/web/rest/flaskapi/v1/rules.py +15 -15
- rucio/web/rest/flaskapi/v1/scopes.py +3 -3
- rucio/web/rest/flaskapi/v1/traces.py +75 -77
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/METADATA +1 -1
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/RECORD +95 -94
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/WHEEL +1 -1
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/requirements.server.txt +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-admin +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-atropos +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-auditor +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-automatix +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-cache-client +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-receiver +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-dumper +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-follower +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-hermes +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-kronos +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-minos +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-minos-temporary-expiration +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-necromancer +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-reaper +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-transmogrifier +0 -0
- {rucio-37.2.0.data → rucio-37.3.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-37.2.0.dist-info → rucio-37.3.0.dist-info}/top_level.txt +0 -0
rucio/gateway/config.py
CHANGED
|
@@ -12,17 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import
|
|
15
|
+
from typing import Any
|
|
16
16
|
|
|
17
17
|
from rucio.common import exception
|
|
18
18
|
from rucio.common.config import convert_to_any_type
|
|
19
19
|
from rucio.core import config
|
|
20
|
-
from rucio.db.sqla.
|
|
20
|
+
from rucio.db.sqla.constants import DatabaseOperationType
|
|
21
|
+
from rucio.db.sqla.session import db_session
|
|
21
22
|
from rucio.gateway import permission
|
|
22
23
|
|
|
23
|
-
if TYPE_CHECKING:
|
|
24
|
-
from sqlalchemy.orm import Session
|
|
25
|
-
|
|
26
24
|
"""
|
|
27
25
|
ConfigParser compatible interface.
|
|
28
26
|
|
|
@@ -31,82 +29,77 @@ ConfigParser compatible interface.
|
|
|
31
29
|
"""
|
|
32
30
|
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
def sections(issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> list[str]:
|
|
32
|
+
def sections(issuer: str, vo: str = 'def') -> list[str]:
|
|
36
33
|
"""
|
|
37
34
|
Return a list of the sections available.
|
|
38
35
|
|
|
39
36
|
:param issuer: The issuer account.
|
|
40
37
|
:param vo: The VO to act on.
|
|
41
|
-
:param session: The database session in use.
|
|
42
38
|
:returns: ['section_name', ...]
|
|
43
39
|
"""
|
|
44
40
|
|
|
45
41
|
kwargs = {'issuer': issuer}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
43
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_sections', kwargs=kwargs, session=session)
|
|
44
|
+
if not auth_result.allowed:
|
|
45
|
+
raise exception.AccessDenied('%s cannot retrieve sections. %s' % (issuer, auth_result.message))
|
|
46
|
+
return config.sections(session=session)
|
|
50
47
|
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
def add_section(section: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> None:
|
|
49
|
+
def add_section(section: str, issuer: str, vo: str = 'def') -> None:
|
|
54
50
|
"""
|
|
55
51
|
Add a section to the configuration.
|
|
56
52
|
|
|
57
53
|
:param section: The name of the section.
|
|
58
54
|
:param issuer: The issuer account.
|
|
59
|
-
:param session: The database session in use.
|
|
60
55
|
:param vo: The VO to act on.
|
|
61
56
|
"""
|
|
62
57
|
|
|
63
58
|
kwargs = {'issuer': issuer, 'section': section}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
60
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_add_section', kwargs=kwargs, session=session)
|
|
61
|
+
if not auth_result.allowed:
|
|
62
|
+
raise exception.AccessDenied('%s cannot add section %s. %s' % (issuer, section, auth_result.message))
|
|
63
|
+
return config.add_section(section, session=session)
|
|
68
64
|
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
def has_section(section: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> bool:
|
|
66
|
+
def has_section(section: str, issuer: str, vo: str = 'def') -> bool:
|
|
72
67
|
"""
|
|
73
68
|
Indicates whether the named section is present in the configuration.
|
|
74
69
|
|
|
75
70
|
:param section: The name of the section.
|
|
76
71
|
:param issuer: The issuer account.
|
|
77
72
|
:param vo: The VO to act on.
|
|
78
|
-
:param session: The database session in use.
|
|
79
73
|
:returns: True/False
|
|
80
74
|
"""
|
|
81
75
|
|
|
82
76
|
kwargs = {'issuer': issuer, 'section': section}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
78
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_has_section', kwargs=kwargs, session=session)
|
|
79
|
+
if not auth_result.allowed:
|
|
80
|
+
raise exception.AccessDenied('%s cannot check existence of section %s. %s' % (issuer, section, auth_result.message))
|
|
81
|
+
return config.has_section(section, session=session)
|
|
87
82
|
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
def options(section: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> list[str]:
|
|
84
|
+
def options(section: str, issuer: str, vo: str = 'def') -> list[str]:
|
|
91
85
|
"""
|
|
92
86
|
Returns a list of options available in the specified section.
|
|
93
87
|
|
|
94
88
|
:param section: The name of the section.
|
|
95
89
|
:param issuer: The issuer account.
|
|
96
90
|
:param vo: The VO to act on.
|
|
97
|
-
:param session: The database session in use.
|
|
98
91
|
:returns: ['option', ...]
|
|
99
92
|
"""
|
|
100
93
|
|
|
101
94
|
kwargs = {'issuer': issuer, 'section': section}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
96
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_options', kwargs=kwargs, session=session)
|
|
97
|
+
if auth_result.allowed:
|
|
98
|
+
raise exception.AccessDenied('%s cannot retrieve options from section %s. %s' % (issuer, section, auth_result.message))
|
|
99
|
+
return config.options(section, session=session)
|
|
106
100
|
|
|
107
101
|
|
|
108
|
-
|
|
109
|
-
def has_option(section: str, option: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> bool:
|
|
102
|
+
def has_option(section: str, option: str, issuer: str, vo: str = 'def') -> bool:
|
|
110
103
|
"""
|
|
111
104
|
Check if the given section exists and contains the given option.
|
|
112
105
|
|
|
@@ -114,19 +107,18 @@ def has_option(section: str, option: str, issuer: Optional[str] = None, vo: str
|
|
|
114
107
|
:param option: The name of the option.
|
|
115
108
|
:param issuer: The issuer account.
|
|
116
109
|
:param vo: The VO to act on.
|
|
117
|
-
:param session: The database session in use.
|
|
118
110
|
:returns: True/False
|
|
119
111
|
"""
|
|
120
112
|
|
|
121
113
|
kwargs = {'issuer': issuer, 'section': section, 'option': option}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
114
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
115
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_has_option', kwargs=kwargs, session=session)
|
|
116
|
+
if not auth_result.allowed:
|
|
117
|
+
raise exception.AccessDenied('%s cannot check existence of option %s from section %s. %s' % (issuer, option, section, auth_result.message))
|
|
118
|
+
return config.has_option(section, option, session=session)
|
|
126
119
|
|
|
127
120
|
|
|
128
|
-
|
|
129
|
-
def get(section: str, option: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> Any:
|
|
121
|
+
def get(section: str, option: str, issuer: str, vo: str = 'def') -> Any:
|
|
130
122
|
"""
|
|
131
123
|
Get an option value for the named section. Value can be auto-coerced to int, float, and bool; string otherwise.
|
|
132
124
|
|
|
@@ -137,19 +129,18 @@ def get(section: str, option: str, issuer: Optional[str] = None, vo: str = 'def'
|
|
|
137
129
|
:param option: The name of the option.
|
|
138
130
|
:param issuer: The issuer account.
|
|
139
131
|
:param vo: The VO to act on.
|
|
140
|
-
:param session: The database session in use.
|
|
141
132
|
:returns: The auto-coerced value.
|
|
142
133
|
"""
|
|
143
134
|
|
|
144
135
|
kwargs = {'issuer': issuer, 'section': section, 'option': option}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
136
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
137
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_get', kwargs=kwargs, session=session)
|
|
138
|
+
if not auth_result.allowed:
|
|
139
|
+
raise exception.AccessDenied('%s cannot retrieve option %s from section %s. %s' % (issuer, option, section, auth_result.message))
|
|
140
|
+
return config.get(section, option, session=session, convert_type_fnc=convert_to_any_type)
|
|
149
141
|
|
|
150
142
|
|
|
151
|
-
|
|
152
|
-
def items(section: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> list[tuple[str, Any]]:
|
|
143
|
+
def items(section: str, issuer: str, vo: str = 'def') -> list[tuple[str, Any]]:
|
|
153
144
|
"""
|
|
154
145
|
Return a list of (option, value) pairs for each option in the given section. Values are auto-coerced as in get().
|
|
155
146
|
|
|
@@ -157,19 +148,18 @@ def items(section: str, issuer: Optional[str] = None, vo: str = 'def', *, sessio
|
|
|
157
148
|
:param value: The content of the value.
|
|
158
149
|
:param issuer: The issuer account.
|
|
159
150
|
:param vo: The VO to act on.
|
|
160
|
-
:param session: The database session in use.
|
|
161
151
|
:returns: [('option', auto-coerced value), ...]
|
|
162
152
|
"""
|
|
163
153
|
|
|
164
154
|
kwargs = {'issuer': issuer, 'section': section}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
155
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
156
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_items', kwargs=kwargs, session=session)
|
|
157
|
+
if not auth_result.allowed:
|
|
158
|
+
raise exception.AccessDenied('%s cannot retrieve options and values from section %s. %s' % (issuer, section, auth_result.message))
|
|
159
|
+
return config.items(section, session=session, convert_type_fnc=convert_to_any_type)
|
|
169
160
|
|
|
170
161
|
|
|
171
|
-
|
|
172
|
-
def set(section: str, option: str, value: Any, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> None:
|
|
162
|
+
def set(section: str, option: str, value: Any, issuer: str, vo: str = 'def') -> None:
|
|
173
163
|
"""
|
|
174
164
|
Set the given option to the specified value.
|
|
175
165
|
|
|
@@ -178,37 +168,35 @@ def set(section: str, option: str, value: Any, issuer: Optional[str] = None, vo:
|
|
|
178
168
|
:param value: The content of the value.
|
|
179
169
|
:param issuer: The issuer account.
|
|
180
170
|
:param vo: The VO to act on.
|
|
181
|
-
:param session: The database session in use.
|
|
182
171
|
"""
|
|
183
172
|
|
|
184
173
|
kwargs = {'issuer': issuer, 'section': section, 'option': option, 'value': value}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
174
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
175
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_set', kwargs=kwargs, session=session)
|
|
176
|
+
if not auth_result.allowed:
|
|
177
|
+
raise exception.AccessDenied('%s cannot set option %s to %s in section %s. %s' % (issuer, option, value, section, auth_result.message))
|
|
178
|
+
return config.set(section, option, value, session=session)
|
|
189
179
|
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
def remove_section(section: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> bool:
|
|
181
|
+
def remove_section(section: str, issuer: str, vo: str = 'def') -> bool:
|
|
193
182
|
"""
|
|
194
183
|
Remove the specified option from the specified section.
|
|
195
184
|
|
|
196
185
|
:param section: The name of the section.
|
|
197
186
|
:param issuer: The issuer account.
|
|
198
187
|
:param vo: The VO to act on.
|
|
199
|
-
:param session: The database session in use.
|
|
200
188
|
:returns: True/False.
|
|
201
189
|
"""
|
|
202
190
|
|
|
203
191
|
kwargs = {'issuer': issuer, 'section': section}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
192
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
193
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_remove_section', kwargs=kwargs, session=session)
|
|
194
|
+
if not auth_result.allowed:
|
|
195
|
+
raise exception.AccessDenied('%s cannot remove section %s. %s' % (issuer, section, auth_result.message))
|
|
196
|
+
return config.remove_section(section, session=session)
|
|
208
197
|
|
|
209
198
|
|
|
210
|
-
|
|
211
|
-
def remove_option(section: str, option: str, issuer: Optional[str] = None, vo: str = 'def', *, session: "Session") -> bool:
|
|
199
|
+
def remove_option(section: str, option: str, issuer: str, vo: str = 'def') -> bool:
|
|
212
200
|
"""
|
|
213
201
|
Remove the specified section from the configuration.
|
|
214
202
|
|
|
@@ -216,12 +204,12 @@ def remove_option(section: str, option: str, issuer: Optional[str] = None, vo: s
|
|
|
216
204
|
:param option: The name of the option.
|
|
217
205
|
:param issuer: The issuer account.
|
|
218
206
|
:param vo: The VO to act on.
|
|
219
|
-
:param session: The database session in use.
|
|
220
207
|
:returns: True/False
|
|
221
208
|
"""
|
|
222
209
|
|
|
223
210
|
kwargs = {'issuer': issuer, 'section': section, 'option': option}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
211
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
212
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='config_remove_option', kwargs=kwargs, session=session)
|
|
213
|
+
if not auth_result.allowed:
|
|
214
|
+
raise exception.AccessDenied('%s cannot remove option %s from section %s. %s' % (issuer, option, section, auth_result.message))
|
|
215
|
+
return config.remove_option(section, option, session=session)
|