Skip to content

Commit fde5b77

Browse files
committed
Add Block Storage Quotas
Like compute before it, we need to tweak quotas to allow services to provision sane amounts. These are typically set at a paltry 100 volumes and 1TB.
1 parent 27ab3ff commit fde5b77

File tree

7 files changed

+211
-6
lines changed

7 files changed

+211
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/dist
2+
/venv
23
/python_unikorn_openstack_policy.egg-info/
34
__pycache__
45
*.swp

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ We need the following to be allowed (non-root):
2020
* Management of quotas
2121
* Provisioning of provider networks in managed projects
2222

23+
### Block Storage Service
24+
25+
We need the following to be allowed (non-root):
26+
27+
* Management of quotas
28+
2329
### Design
2430

2531
Problem with any service that isn't Keystone is, it has zero view of identity hierarchies.
@@ -78,18 +84,25 @@ openstack network create --provider-network-type vlan --provider-physical-networ
7884

7985
### Installation
8086

87+
```bash
88+
python3 -m venv venv
89+
source venv/bin/activate
90+
pip3 install build pylint
91+
```
92+
8193
> [!NOTE]
8294
> Running the following will install all the necessary dependencies.
8395
> This also includes any commands required for the the following sections.
8496
8597
```bash
8698
python3 -m build
87-
pip3 install dist/python_unikorn_openstack_policy-0.1.0-py3-none-any.whl
99+
pip3 install --force-reinstall dist/python_unikorn_openstack_policy-0.1.0-py3-none-any.whl
88100
```
89101

90102
### Generating Policy Files
91103

92104
```bash
105+
oslopolicy-policy-generator --namespace unikorn_openstack_policy_blockstorage
93106
oslopolicy-policy-generator --namespace unikorn_openstack_policy_compute
94107
oslopolicy-policy-generator --namespace unikorn_openstack_policy_network
95108
```

pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@ classifiers = [
2424
"Programming Language :: Python :: 3 :: Only",
2525
]
2626
dependencies = [
27-
"oslo.config",
27+
"cinder",
2828
"neutron",
29-
"nova"
29+
"nova",
30+
"oslo.config",
3031
]
3132

3233
[project.urls]
3334
homepage = "https://github.com/unikorn-cloud/python-unikorn-openstack-policy"
3435

3536
[project.entry-points."oslo.policy.policies"]
37+
unikorn_openstack_policy_blockstorage = "unikorn_openstack_policy.blockstorage:list_rules"
3638
unikorn_openstack_policy_compute = "unikorn_openstack_policy.compute:list_rules"
3739
unikorn_openstack_policy_network = "unikorn_openstack_policy.network:list_rules"
3840

3941
[project.entry-points."oslo.policy.enforcer"]
42+
unikorn_openstack_policy_blockstorage = "unikorn_openstack_policy.blockstorage:get_enforcer"
4043
unikorn_openstack_policy_compute = "unikorn_openstack_policy.compute:get_enforcer"
4144
unikorn_openstack_policy_network = "unikorn_openstack_policy.network:get_enforcer"
4245

requirements.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright 2024 the Unikorn Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
Defines Oslo Policy Rules.
17+
"""
18+
19+
# pylint: disable=line-too-long
20+
21+
from cinder import policies
22+
from cinder.policies import quotas
23+
from oslo_config import cfg
24+
from oslo_policy import policy
25+
from unikorn_openstack_policy import base
26+
27+
rules = [
28+
# The domain manager needs to be able to alter the default quotas
29+
# or it won't we able to fulfill any cluster creation requests.
30+
policy.RuleDefault(
31+
name=quotas.UPDATE_POLICY,
32+
check_str='rule:is_project_manager',
33+
description='Update the block storage quotas',
34+
)
35+
]
36+
37+
38+
def list_rules():
39+
"""Implements the "oslo.policy.policies" entry point"""
40+
41+
# For every defined rule, look for a corresponding one sourced directly
42+
# from nova, this means we can augment the exact rule defined for a
43+
# specific version of nova,
44+
return base.inherit_rules(rules, list(policies.list_rules()))
45+
46+
47+
def get_enforcer():
48+
"""Implements the "oslo.policy.enforcer" entry point"""
49+
50+
enforcer = policy.Enforcer(conf=cfg.CONF)
51+
enforcer.register_defaults(list_rules())
52+
53+
return enforcer
54+
55+
56+
# vi: ts=4 et:

unikorn_openstack_policy/compute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
policy.RuleDefault(
3030
name='os_compute_api:os-quota-sets:update',
3131
check_str='rule:is_project_manager',
32-
description='Update the quotas',
32+
description='Update the compute quotas',
3333
)
3434
]
3535

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Copyright 2024 the Unikorn Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
Unit tests for OpenStack policies.
17+
"""
18+
19+
from cinder.policies import quotas
20+
from oslo_policy import policy
21+
22+
from unikorn_openstack_policy import blockstorage
23+
from unikorn_openstack_policy.tests import base
24+
25+
class ProjectAdminBlockStoragePolicyTests(base.PolicyTestsBase):
26+
"""
27+
Checks policy enforcement for project scoped admin role.
28+
"""
29+
30+
# Request context.
31+
context = None
32+
33+
def setUp(self):
34+
"""Perform setup actions for all tests"""
35+
self.setup(blockstorage.get_enforcer())
36+
self.context = self.project_admin_context
37+
38+
def test_update_quota_sets(self):
39+
"""Admin can update quota sets"""
40+
self.assertTrue(self.enforce(
41+
quotas.UPDATE_POLICY, self.target, self.context))
42+
43+
44+
class DomainAdminBlockStoragePolicyTests(ProjectAdminBlockStoragePolicyTests):
45+
"""
46+
Checks policy enforcement for domain scoped admin role
47+
"""
48+
49+
def setUp(self):
50+
self.setup(blockstorage.get_enforcer())
51+
self.context = self.domain_admin_context
52+
53+
54+
class ProjectManagerBlockStoragePolicyTests(base.PolicyTestsBase):
55+
"""
56+
Checks policy enforcement for project scoped manager role
57+
"""
58+
59+
# Request context.
60+
context = None
61+
62+
def setUp(self):
63+
"""Perform setup actions for all tests"""
64+
self.setup(blockstorage.get_enforcer())
65+
self.context = self.project_manager_context
66+
67+
def test_update_quota_sets(self):
68+
"""Project manager can update quota sets"""
69+
self.assertTrue(self.enforce(
70+
quotas.UPDATE_POLICY, self.target, self.context))
71+
self.assertRaises(
72+
policy.PolicyNotAuthorized,
73+
self.enforce,
74+
quotas.UPDATE_POLICY, self.alt_target, self.context)
75+
76+
77+
class DomainManagerBlockStoragePolicyTests(base.PolicyTestsBase):
78+
"""
79+
Checks policy enforcement for the manager role.
80+
"""
81+
82+
def setUp(self):
83+
"""Perform setup actions for all tests"""
84+
self.setup(blockstorage.get_enforcer())
85+
self.context = self.domain_manager_context
86+
87+
def test_update_quota_sets(self):
88+
"""Domain manager cannot update quota sets"""
89+
self.assertRaises(
90+
policy.PolicyNotAuthorized,
91+
self.enforce,
92+
quotas.UPDATE_POLICY, self.target, self.context)
93+
self.assertRaises(
94+
policy.PolicyNotAuthorized,
95+
self.enforce,
96+
quotas.UPDATE_POLICY, self.alt_target, self.context)
97+
98+
99+
class ProjectMemberBlockStoragePolicyTests(base.PolicyTestsBase):
100+
"""
101+
Checks policy enforcement for the member role.
102+
"""
103+
104+
def setUp(self):
105+
"""Perform setup actions for all tests"""
106+
self.setup(blockstorage.get_enforcer())
107+
self.context = self.project_member_context
108+
109+
def test_update_quota_sets(self):
110+
"""Project member cannot create quota sets"""
111+
self.assertRaises(
112+
policy.PolicyNotAuthorized,
113+
self.enforce,
114+
quotas.UPDATE_POLICY, self.target, self.context)
115+
116+
117+
class DomainMemberBlockStoragePolicyTests(base.PolicyTestsBase):
118+
"""
119+
Checks policy enforcement for the member role.
120+
"""
121+
122+
def setUp(self):
123+
"""Perform setup actions for all tests"""
124+
self.setup(blockstorage.get_enforcer())
125+
self.context = self.domain_member_context
126+
127+
def test_update_quota_sets(self):
128+
"""Domain member cannot create quota sets"""
129+
self.assertRaises(
130+
policy.PolicyNotAuthorized,
131+
self.enforce,
132+
quotas.UPDATE_POLICY, self.target, self.context)
133+
134+
# vi: ts=4 et:

0 commit comments

Comments
 (0)