Skip to content

Commit a2a4201

Browse files
authored
Add Block Storage Quotas (#10)
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 a2a4201

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)