octavia 15.0.0__py3-none-any.whl → 16.0.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.
- octavia/amphorae/backends/agent/api_server/keepalivedlvs.py +9 -0
- octavia/amphorae/backends/agent/api_server/loadbalancer.py +6 -6
- octavia/amphorae/backends/agent/api_server/plug.py +1 -1
- octavia/amphorae/backends/agent/api_server/util.py +35 -2
- octavia/amphorae/backends/health_daemon/status_message.py +1 -2
- octavia/amphorae/drivers/haproxy/rest_api_driver.py +12 -7
- octavia/api/drivers/amphora_driver/flavor_schema.py +5 -0
- octavia/api/drivers/noop_driver/driver.py +2 -1
- octavia/api/drivers/utils.py +12 -0
- octavia/api/root_controller.py +8 -2
- octavia/api/v2/controllers/base.py +8 -4
- octavia/api/v2/controllers/listener.py +12 -2
- octavia/api/v2/controllers/load_balancer.py +33 -1
- octavia/api/v2/controllers/member.py +58 -4
- octavia/api/v2/types/load_balancer.py +7 -1
- octavia/api/v2/types/member.py +3 -0
- octavia/common/base_taskflow.py +19 -10
- octavia/common/clients.py +8 -2
- octavia/common/config.py +17 -2
- octavia/common/constants.py +6 -0
- octavia/common/data_models.py +32 -2
- octavia/common/exceptions.py +5 -0
- octavia/common/utils.py +4 -1
- octavia/common/validate.py +16 -0
- octavia/compute/drivers/noop_driver/driver.py +30 -1
- octavia/controller/healthmanager/health_manager.py +7 -0
- octavia/controller/worker/v2/flows/amphora_flows.py +3 -5
- octavia/controller/worker/v2/flows/listener_flows.py +2 -1
- octavia/controller/worker/v2/flows/load_balancer_flows.py +38 -0
- octavia/controller/worker/v2/taskflow_jobboard_driver.py +34 -6
- octavia/controller/worker/v2/tasks/compute_tasks.py +9 -5
- octavia/controller/worker/v2/tasks/database_tasks.py +26 -6
- octavia/controller/worker/v2/tasks/network_tasks.py +118 -70
- octavia/db/base_models.py +29 -5
- octavia/db/migration/alembic_migrations/versions/3097e55493ae_add_sg_id_to_vip_table.py +39 -0
- octavia/db/migration/alembic_migrations/versions/8db7a6443785_add_member_vnic_type.py +36 -0
- octavia/db/migration/alembic_migrations/versions/fabf4983846b_add_member_port_table.py +40 -0
- octavia/db/models.py +43 -1
- octavia/db/repositories.py +88 -9
- octavia/network/base.py +29 -12
- octavia/network/data_models.py +2 -1
- octavia/network/drivers/neutron/allowed_address_pairs.py +55 -46
- octavia/network/drivers/neutron/base.py +28 -16
- octavia/network/drivers/neutron/utils.py +2 -2
- octavia/network/drivers/noop_driver/driver.py +150 -29
- octavia/policies/__init__.py +4 -0
- octavia/policies/advanced_rbac.py +95 -0
- octavia/policies/base.py +5 -101
- octavia/policies/keystone_default_roles.py +81 -0
- octavia/policies/loadbalancer.py +13 -0
- octavia/tests/common/constants.py +2 -1
- octavia/tests/common/sample_data_models.py +27 -14
- octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +5 -4
- octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +2 -1
- octavia/tests/functional/api/v2/test_health_monitor.py +1 -1
- octavia/tests/functional/api/v2/test_l7policy.py +1 -1
- octavia/tests/functional/api/v2/test_listener.py +1 -1
- octavia/tests/functional/api/v2/test_load_balancer.py +150 -4
- octavia/tests/functional/api/v2/test_member.py +50 -0
- octavia/tests/functional/api/v2/test_pool.py +1 -1
- octavia/tests/functional/api/v2/test_quotas.py +5 -8
- octavia/tests/functional/db/base.py +6 -6
- octavia/tests/functional/db/test_models.py +124 -1
- octavia/tests/functional/db/test_repositories.py +237 -19
- octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +89 -1
- octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +10 -7
- octavia/tests/unit/api/drivers/test_utils.py +6 -1
- octavia/tests/unit/certificates/generator/test_local.py +1 -1
- octavia/tests/unit/common/test_base_taskflow.py +4 -3
- octavia/tests/unit/compute/drivers/noop_driver/test_driver.py +28 -2
- octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +27 -1
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +28 -6
- octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +100 -79
- octavia/tests/unit/controller/worker/v2/test_taskflow_jobboard_driver.py +8 -0
- octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +62 -45
- octavia/tests/unit/network/drivers/neutron/test_base.py +7 -7
- octavia/tests/unit/network/drivers/noop_driver/test_driver.py +55 -42
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/tox.ini +0 -1
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/AUTHORS +3 -0
- octavia-16.0.0.dist-info/METADATA +156 -0
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/RECORD +95 -90
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/WHEEL +1 -1
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/entry_points.txt +1 -1
- octavia-16.0.0.dist-info/pbr.json +1 -0
- octavia-15.0.0.dist-info/METADATA +0 -156
- octavia-15.0.0.dist-info/pbr.json +0 -1
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/LICENSE +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/README.rst +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/README.rst +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/data/share/octavia/diskimage-create/version.txt +0 -0
- {octavia-15.0.0.data → octavia-16.0.0.data}/scripts/octavia-wsgi +0 -0
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/LICENSE +0 -0
- {octavia-15.0.0.dist-info → octavia-16.0.0.dist-info}/top_level.txt +0 -0
@@ -12,14 +12,28 @@
|
|
12
12
|
# License for the specific language governing permissions and limitations
|
13
13
|
# under the License.
|
14
14
|
|
15
|
+
import typing
|
16
|
+
|
15
17
|
from oslo_log import log as logging
|
16
18
|
from oslo_utils import uuidutils
|
19
|
+
from sqlalchemy import Column
|
20
|
+
from sqlalchemy import create_engine
|
21
|
+
from sqlalchemy import delete
|
22
|
+
from sqlalchemy import event
|
23
|
+
from sqlalchemy import insert
|
24
|
+
from sqlalchemy import MetaData
|
25
|
+
from sqlalchemy import select
|
26
|
+
from sqlalchemy import String
|
27
|
+
from sqlalchemy import Table
|
17
28
|
|
18
29
|
from octavia.common import constants
|
19
30
|
from octavia.common import data_models
|
20
31
|
from octavia.network import base as driver_base
|
21
32
|
from octavia.network import data_models as network_models
|
22
33
|
|
34
|
+
if typing.TYPE_CHECKING:
|
35
|
+
from octavia.common import context
|
36
|
+
|
23
37
|
LOG = logging.getLogger(__name__)
|
24
38
|
|
25
39
|
_NOOP_MANAGER_VARS = {
|
@@ -38,6 +52,39 @@ class NoopManager:
|
|
38
52
|
self.networkconfigconfig = {}
|
39
53
|
self._qos_extension_enabled = True
|
40
54
|
|
55
|
+
# The controller worker can run with multiple processes, so we
|
56
|
+
# need to have a persistent and shared store for the no-op driver.
|
57
|
+
self.engine = create_engine('sqlite:////tmp/octavia-network-noop.db')
|
58
|
+
|
59
|
+
# TODO(johnsom) work around pysqlite locking issues per:
|
60
|
+
# https://github.com/sqlalchemy/sqlalchemy/discussions/12330
|
61
|
+
@event.listens_for(self.engine, "connect")
|
62
|
+
def do_connect(dbapi_connection, connection_record):
|
63
|
+
# disable pysqlite's emitting of the BEGIN statement entirely.
|
64
|
+
# also stops it from emitting COMMIT before any DDL.
|
65
|
+
dbapi_connection.isolation_level = None
|
66
|
+
|
67
|
+
@event.listens_for(self.engine, "begin")
|
68
|
+
def do_begin(conn):
|
69
|
+
conn.exec_driver_sql("BEGIN EXCLUSIVE")
|
70
|
+
|
71
|
+
metadata_obj = MetaData()
|
72
|
+
|
73
|
+
self.interfaces_table = Table(
|
74
|
+
'interfaces',
|
75
|
+
metadata_obj,
|
76
|
+
Column('port_id', String(36)),
|
77
|
+
Column('network_id', String(36)),
|
78
|
+
Column('compute_id', String(36)),
|
79
|
+
Column('vnic_type', String(6)))
|
80
|
+
self.fixed_ips_table = Table(
|
81
|
+
'fixed_ips',
|
82
|
+
metadata_obj,
|
83
|
+
Column('port_id', String(36)),
|
84
|
+
Column('subnet_id', String(36)),
|
85
|
+
Column('ip_address', String(64)))
|
86
|
+
metadata_obj.create_all(self.engine)
|
87
|
+
|
41
88
|
def allocate_vip(self, loadbalancer):
|
42
89
|
LOG.debug("Network %s no-op, allocate_vip loadbalancer %s",
|
43
90
|
self.__class__.__name__, loadbalancer)
|
@@ -82,6 +129,18 @@ class NoopManager:
|
|
82
129
|
vip.ip_address)] = (load_balancer, vip,
|
83
130
|
'update_vip_sg')
|
84
131
|
|
132
|
+
def update_aap_port_sg(self,
|
133
|
+
load_balancer: data_models.LoadBalancer,
|
134
|
+
amphora: data_models.Amphora,
|
135
|
+
vip: data_models.Vip):
|
136
|
+
LOG.debug("Network %s no-op, update_aap_port_sg load_balancer %s, "
|
137
|
+
" vip %s, amphora %s", self.__class__.__name__,
|
138
|
+
load_balancer.id, vip.ip_address, amphora)
|
139
|
+
self.networkconfigconfig[(amphora.id,
|
140
|
+
vip.ip_address)] = (load_balancer, vip,
|
141
|
+
amphora,
|
142
|
+
'update_aap_port_sg')
|
143
|
+
|
85
144
|
def plug_aap_port(self, load_balancer, vip, amphora, subnet):
|
86
145
|
LOG.debug("Network %s no-op, plug_aap_port loadbalancer %s, vip %s,"
|
87
146
|
" amphora %s, subnet %s",
|
@@ -91,12 +150,34 @@ class NoopManager:
|
|
91
150
|
vip.ip_address)] = (
|
92
151
|
load_balancer, vip, amphora, subnet,
|
93
152
|
'plug_aap_port')
|
153
|
+
|
154
|
+
fixed_ips = [network_models.FixedIP(subnet_id=subnet.id,
|
155
|
+
ip_address=vip.ip_address)]
|
156
|
+
|
157
|
+
port_id = uuidutils.generate_uuid()
|
158
|
+
LOG.debug("Network %s no-op, plug_aap_port loadbalancer %s is using "
|
159
|
+
"base port ID %s",
|
160
|
+
self.__class__.__name__,
|
161
|
+
load_balancer.id, port_id)
|
162
|
+
|
163
|
+
# Store the interface information in the no-op DB
|
164
|
+
with self.engine.connect() as connection:
|
165
|
+
connection.execute(insert(self.interfaces_table).values(
|
166
|
+
port_id=port_id, network_id=vip.network_id,
|
167
|
+
compute_id=amphora.compute_id,
|
168
|
+
vnic_type=constants.VNIC_TYPE_NORMAL))
|
169
|
+
for fixed_ip in fixed_ips:
|
170
|
+
connection.execute(insert(self.fixed_ips_table).values(
|
171
|
+
port_id=port_id, subnet_id=fixed_ip.subnet_id,
|
172
|
+
ip_address=fixed_ip.ip_address))
|
173
|
+
connection.commit()
|
174
|
+
|
94
175
|
return data_models.Amphora(
|
95
176
|
id=amphora.id,
|
96
177
|
compute_id=amphora.compute_id,
|
97
178
|
vrrp_ip='198.51.100.1',
|
98
179
|
ha_ip='198.51.100.1',
|
99
|
-
vrrp_port_id=
|
180
|
+
vrrp_port_id=port_id,
|
100
181
|
ha_port_id=uuidutils.generate_uuid()
|
101
182
|
)
|
102
183
|
|
@@ -117,42 +198,45 @@ class NoopManager:
|
|
117
198
|
vip.ip_address)] = (vip, amphora, subnet,
|
118
199
|
'unplug_aap_port')
|
119
200
|
|
120
|
-
def plug_network(self, compute_id, network_id):
|
121
|
-
LOG.debug("Network %s no-op, plug_network compute_id %s, network_id "
|
122
|
-
"%s", self.__class__.__name__, compute_id,
|
123
|
-
network_id)
|
124
|
-
self.networkconfigconfig[(compute_id, network_id)] = (
|
125
|
-
compute_id, network_id, 'plug_network')
|
126
|
-
interface = network_models.Interface(
|
127
|
-
id=uuidutils.generate_uuid(),
|
128
|
-
compute_id=compute_id,
|
129
|
-
network_id=network_id,
|
130
|
-
fixed_ips=[],
|
131
|
-
port_id=uuidutils.generate_uuid()
|
132
|
-
)
|
133
|
-
_NOOP_MANAGER_VARS['ports'][interface.port_id] = (
|
134
|
-
network_models.Port(
|
135
|
-
id=interface.port_id,
|
136
|
-
network_id=network_id))
|
137
|
-
_NOOP_MANAGER_VARS['interfaces'][(network_id, compute_id)] = (
|
138
|
-
interface)
|
139
|
-
return interface
|
140
|
-
|
141
201
|
def unplug_network(self, compute_id, network_id):
|
142
202
|
LOG.debug("Network %s no-op, unplug_network compute_id %s, "
|
143
203
|
"network_id %s",
|
144
204
|
self.__class__.__name__, compute_id, network_id)
|
145
205
|
self.networkconfigconfig[(compute_id, network_id)] = (
|
146
206
|
compute_id, network_id, 'unplug_network')
|
147
|
-
_NOOP_MANAGER_VARS['interfaces'].pop((network_id, compute_id), None)
|
148
207
|
|
149
208
|
def get_plugged_networks(self, compute_id):
|
150
|
-
LOG.debug("Network %s no-op, get_plugged_networks
|
209
|
+
LOG.debug("Network %s no-op, get_plugged_networks compute_id %s",
|
151
210
|
self.__class__.__name__, compute_id)
|
152
211
|
self.networkconfigconfig[compute_id] = (
|
153
212
|
compute_id, 'get_plugged_networks')
|
154
|
-
|
155
|
-
|
213
|
+
|
214
|
+
# Retrieve the interfaces from the no-op DB for this compute_id
|
215
|
+
interfaces = []
|
216
|
+
with self.engine.connect() as connection:
|
217
|
+
int_results = connection.execute(
|
218
|
+
select(self.interfaces_table)
|
219
|
+
.where(self.interfaces_table.c.compute_id == compute_id))
|
220
|
+
# Walk through the matching interfaces
|
221
|
+
for interface in int_results:
|
222
|
+
fixed_ips = []
|
223
|
+
# Get the fixed IPs on each interface
|
224
|
+
fixed_ip_results = connection.execute(
|
225
|
+
select(self.fixed_ips_table)
|
226
|
+
.where(
|
227
|
+
self.fixed_ips_table.c.port_id == interface.port_id))
|
228
|
+
# Build the FixedIP objects for the interface
|
229
|
+
for fixed_ip in fixed_ip_results:
|
230
|
+
fixed_ips.append(network_models.FixedIP(
|
231
|
+
subnet_id=fixed_ip.subnet_id,
|
232
|
+
ip_address=fixed_ip.ip_address))
|
233
|
+
# Add the interface object to the list
|
234
|
+
interfaces.append(network_models.Interface(
|
235
|
+
compute_id=interface.compute_id,
|
236
|
+
network_id=interface.network_id,
|
237
|
+
port_id=interface.port_id, fixed_ips=fixed_ips,
|
238
|
+
vnic_type=interface.vnic_type))
|
239
|
+
return interfaces
|
156
240
|
|
157
241
|
def update_vip(self, loadbalancer, for_delete=False):
|
158
242
|
LOG.debug("Network %s no-op, update_vip loadbalancer %s "
|
@@ -228,6 +312,14 @@ class NoopManager:
|
|
228
312
|
_NOOP_MANAGER_VARS['ports'][port_id] = port
|
229
313
|
return port
|
230
314
|
|
315
|
+
def get_security_group_by_id(self, sg_id: str,
|
316
|
+
context: 'context.RequestContext' = None) -> (
|
317
|
+
'network_models.SecurityGroup'):
|
318
|
+
LOG.debug("Network %s no-op, get_security_group_by_id %s",
|
319
|
+
self.__class__.__name__, sg_id)
|
320
|
+
self.networkconfigconfig[sg_id] = (sg_id, 'get_security_group_by_id')
|
321
|
+
return network_models.SecurityGroup(id=sg_id)
|
322
|
+
|
231
323
|
def get_network_by_name(self, network_name):
|
232
324
|
LOG.debug("Network %s no-op, get_network_by_name network_name %s",
|
233
325
|
self.__class__.__name__, network_name)
|
@@ -374,6 +466,16 @@ class NoopManager:
|
|
374
466
|
self.__class__.__name__, port_id)
|
375
467
|
self.networkconfigconfig[port_id] = (port_id, 'delete_port')
|
376
468
|
|
469
|
+
# Remove the port from the no-op DB
|
470
|
+
with self.engine.connect() as connection:
|
471
|
+
connection.execute(delete(self.interfaces_table)
|
472
|
+
.where(
|
473
|
+
self.interfaces_table.c.port_id == port_id))
|
474
|
+
connection.execute(delete(self.fixed_ips_table)
|
475
|
+
.where(
|
476
|
+
self.fixed_ips_table.c.port_id == port_id))
|
477
|
+
connection.commit()
|
478
|
+
|
377
479
|
def set_port_admin_state_up(self, port_id, state):
|
378
480
|
LOG.debug("Network %s no-op, set_port_admin_state_up port_id %s, "
|
379
481
|
"state %s", self.__class__.__name__, port_id, state)
|
@@ -410,6 +512,17 @@ class NoopManager:
|
|
410
512
|
self.networkconfigconfig[(network_id, 'create_port')] = (
|
411
513
|
network_id, name, fixed_ip_obj_list, secondary_ips,
|
412
514
|
security_group_ids, admin_state_up, qos_policy_id, vnic_type)
|
515
|
+
|
516
|
+
# Store the interface information in the no-op DB
|
517
|
+
with self.engine.connect() as connection:
|
518
|
+
connection.execute(insert(self.interfaces_table).values(
|
519
|
+
port_id=port_id, network_id=network_id, vnic_type=vnic_type))
|
520
|
+
for fixed_ip in fixed_ip_obj_list:
|
521
|
+
connection.execute(insert(self.fixed_ips_table).values(
|
522
|
+
port_id=port_id, subnet_id=fixed_ip.subnet_id,
|
523
|
+
ip_address=fixed_ip.ip_address))
|
524
|
+
connection.commit()
|
525
|
+
|
413
526
|
return network_models.Port(
|
414
527
|
id=port_id, name=name, device_id='no-op-device-id',
|
415
528
|
device_owner='Octavia', mac_address='00:00:5E:00:53:05',
|
@@ -454,9 +567,6 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
|
454
567
|
def unplug_vip(self, loadbalancer, vip):
|
455
568
|
self.driver.unplug_vip(loadbalancer, vip)
|
456
569
|
|
457
|
-
def plug_network(self, compute_id, network_id):
|
458
|
-
return self.driver.plug_network(compute_id, network_id)
|
459
|
-
|
460
570
|
def unplug_network(self, compute_id, network_id):
|
461
571
|
self.driver.unplug_network(compute_id, network_id)
|
462
572
|
|
@@ -475,6 +585,11 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
|
475
585
|
def get_port(self, port_id, context=None):
|
476
586
|
return self.driver.get_port(port_id)
|
477
587
|
|
588
|
+
def get_security_group_by_id(self, sg_id: str,
|
589
|
+
context: 'context.RequestContext' = None) -> (
|
590
|
+
'network_models.SecurityGroup'):
|
591
|
+
return self.driver.get_security_group_by_id(sg_id, context=context)
|
592
|
+
|
478
593
|
def get_qos_policy(self, qos_policy_id):
|
479
594
|
return self.driver.get_qos_policy(qos_policy_id)
|
480
595
|
|
@@ -508,6 +623,12 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
|
508
623
|
def update_vip_sg(self, load_balancer, vip):
|
509
624
|
self.driver.update_vip_sg(load_balancer, vip)
|
510
625
|
|
626
|
+
def update_aap_port_sg(self,
|
627
|
+
load_balancer: data_models.LoadBalancer,
|
628
|
+
amphora: data_models.Amphora,
|
629
|
+
vip: data_models.Vip):
|
630
|
+
self.driver.update_aap_port_sg(load_balancer, amphora, vip)
|
631
|
+
|
511
632
|
def plug_aap_port(self, load_balancer, vip, amphora, subnet):
|
512
633
|
return self.driver.plug_aap_port(load_balancer, vip, amphora, subnet)
|
513
634
|
|
octavia/policies/__init__.py
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
|
14
14
|
import itertools
|
15
15
|
|
16
|
+
from octavia.policies import advanced_rbac
|
16
17
|
from octavia.policies import amphora
|
17
18
|
from octavia.policies import availability_zone
|
18
19
|
from octavia.policies import availability_zone_profile
|
@@ -20,6 +21,7 @@ from octavia.policies import base
|
|
20
21
|
from octavia.policies import flavor
|
21
22
|
from octavia.policies import flavor_profile
|
22
23
|
from octavia.policies import healthmonitor
|
24
|
+
from octavia.policies import keystone_default_roles
|
23
25
|
from octavia.policies import l7policy
|
24
26
|
from octavia.policies import l7rule
|
25
27
|
from octavia.policies import listener
|
@@ -35,6 +37,8 @@ from octavia.policies import quota
|
|
35
37
|
def list_rules():
|
36
38
|
return itertools.chain(
|
37
39
|
base.list_rules(),
|
40
|
+
keystone_default_roles.list_rules(),
|
41
|
+
advanced_rbac.list_rules(),
|
38
42
|
flavor.list_rules(),
|
39
43
|
flavor_profile.list_rules(),
|
40
44
|
availability_zone.list_rules(),
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
2
|
+
# not use this file except in compliance with the License. You may obtain
|
3
|
+
# a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10
|
+
# License for the specific language governing permissions and limitations
|
11
|
+
# under the License.
|
12
|
+
|
13
|
+
from oslo_log import versionutils
|
14
|
+
from oslo_policy import policy
|
15
|
+
|
16
|
+
from octavia.common import constants
|
17
|
+
|
18
|
+
# Octavia specific Advanced RBAC rules
|
19
|
+
|
20
|
+
# The default is to not allow access unless the auth_strategy is 'noauth'.
|
21
|
+
# Users must be a member of one of the following roles to have access to
|
22
|
+
# the load-balancer API:
|
23
|
+
#
|
24
|
+
# role:load-balancer_observer
|
25
|
+
# User has access to load-balancer read-only APIs
|
26
|
+
# role:load-balancer_global_observer
|
27
|
+
# User has access to load-balancer read-only APIs including resources
|
28
|
+
# owned by others.
|
29
|
+
# role:load-balancer_member
|
30
|
+
# User has access to load-balancer read and write APIs
|
31
|
+
# role:load-balancer_admin
|
32
|
+
# User is considered an admin for all load-balancer APIs including
|
33
|
+
# resources owned by others.
|
34
|
+
|
35
|
+
deprecated_context_is_admin = policy.DeprecatedRule(
|
36
|
+
name='context_is_admin',
|
37
|
+
check_str='role:admin or '
|
38
|
+
'role:load-balancer_admin',
|
39
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
40
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
41
|
+
)
|
42
|
+
|
43
|
+
# Note: 'is_admin:True' is a policy rule that takes into account the
|
44
|
+
# auth_strategy == noauth configuration setting.
|
45
|
+
# It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
|
46
|
+
|
47
|
+
deprecated_admin = policy.DeprecatedRule(
|
48
|
+
name='load-balancer:admin',
|
49
|
+
check_str='is_admin:True or '
|
50
|
+
'role:admin or '
|
51
|
+
'role:load-balancer_admin',
|
52
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
53
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
54
|
+
)
|
55
|
+
|
56
|
+
deprecated_global_observer = policy.DeprecatedRule(
|
57
|
+
name='load-balancer:global_observer',
|
58
|
+
check_str='role:load-balancer_global_observer',
|
59
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
60
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
61
|
+
)
|
62
|
+
|
63
|
+
deprecated_member_and_owner = policy.DeprecatedRule(
|
64
|
+
name='load-balancer:member_and_owner',
|
65
|
+
check_str='role:load-balancer_member and '
|
66
|
+
'rule:load-balancer:owner',
|
67
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
68
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
69
|
+
)
|
70
|
+
|
71
|
+
deprecated_observer_and_owner = policy.DeprecatedRule(
|
72
|
+
name='load-balancer:observer_and_owner',
|
73
|
+
check_str='role:load-balancer_observer and '
|
74
|
+
'rule:load-balancer:owner',
|
75
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
76
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
77
|
+
)
|
78
|
+
|
79
|
+
deprecated_quota_admin = policy.DeprecatedRule(
|
80
|
+
name='load-balancer:quota-admin',
|
81
|
+
check_str='role:load-balancer_quota_admin',
|
82
|
+
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
83
|
+
deprecated_since=versionutils.deprecated.WALLABY,
|
84
|
+
)
|
85
|
+
|
86
|
+
rules = [
|
87
|
+
policy.RuleDefault(
|
88
|
+
name='load-balancer:owner',
|
89
|
+
check_str='project_id:%(project_id)s',
|
90
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
91
|
+
]
|
92
|
+
|
93
|
+
|
94
|
+
def list_rules():
|
95
|
+
return rules
|
octavia/policies/base.py
CHANGED
@@ -10,112 +10,16 @@
|
|
10
10
|
# License for the specific language governing permissions and limitations
|
11
11
|
# under the License.
|
12
12
|
|
13
|
-
from oslo_log import versionutils
|
14
13
|
from oslo_policy import policy
|
15
14
|
|
16
15
|
from octavia.common import constants
|
17
16
|
|
18
|
-
deprecated_context_is_admin = policy.DeprecatedRule(
|
19
|
-
name='context_is_admin',
|
20
|
-
check_str='role:admin or '
|
21
|
-
'role:load-balancer_admin',
|
22
|
-
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
23
|
-
deprecated_since=versionutils.deprecated.WALLABY,
|
24
|
-
)
|
25
|
-
deprecated_observer_and_owner = policy.DeprecatedRule(
|
26
|
-
name='load-balancer:observer_and_owner',
|
27
|
-
check_str='role:load-balancer_observer and '
|
28
|
-
'rule:load-balancer:owner',
|
29
|
-
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
30
|
-
deprecated_since=versionutils.deprecated.WALLABY,
|
31
|
-
)
|
32
|
-
deprecated_member_and_owner = policy.DeprecatedRule(
|
33
|
-
name='load-balancer:member_and_owner',
|
34
|
-
check_str='role:load-balancer_member and '
|
35
|
-
'rule:load-balancer:owner',
|
36
|
-
deprecated_reason=constants.RBAC_ROLES_DEPRECATED_REASON,
|
37
|
-
deprecated_since=versionutils.deprecated.WALLABY,
|
38
|
-
)
|
39
17
|
|
40
18
|
rules = [
|
41
19
|
|
42
|
-
# OpenStack wide scoped rules
|
43
|
-
|
44
|
-
# Project scoped Member
|
45
|
-
policy.RuleDefault(
|
46
|
-
name='project-member',
|
47
|
-
check_str='role:member and '
|
48
|
-
'project_id:%(project_id)s',
|
49
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
50
|
-
|
51
|
-
# Project scoped Reader
|
52
|
-
policy.RuleDefault(
|
53
|
-
name='project-reader',
|
54
|
-
check_str='role:reader and '
|
55
|
-
'project_id:%(project_id)s',
|
56
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
57
|
-
|
58
|
-
# Octavia specific Advanced RBAC rules
|
59
|
-
|
60
|
-
# The default is to not allow access unless the auth_strategy is 'noauth'.
|
61
|
-
# Users must be a member of one of the following roles to have access to
|
62
|
-
# the load-balancer API:
|
63
|
-
#
|
64
|
-
# role:load-balancer_observer
|
65
|
-
# User has access to load-balancer read-only APIs
|
66
|
-
# role:load-balancer_global_observer
|
67
|
-
# User has access to load-balancer read-only APIs including resources
|
68
|
-
# owned by others.
|
69
|
-
# role:load-balancer_member
|
70
|
-
# User has access to load-balancer read and write APIs
|
71
|
-
# role:load-balancer_admin
|
72
|
-
# User is considered an admin for all load-balancer APIs including
|
73
|
-
# resources owned by others.
|
74
|
-
|
75
|
-
policy.RuleDefault(
|
76
|
-
name='context_is_admin',
|
77
|
-
check_str='role:load-balancer_admin or '
|
78
|
-
'role:admin',
|
79
|
-
deprecated_rule=deprecated_context_is_admin,
|
80
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
81
|
-
|
82
|
-
# Note: 'is_admin:True' is a policy rule that takes into account the
|
83
|
-
# auth_strategy == noauth configuration setting.
|
84
|
-
# It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
|
85
|
-
|
86
|
-
policy.RuleDefault(
|
87
|
-
name='load-balancer:owner',
|
88
|
-
check_str='project_id:%(project_id)s',
|
89
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
90
|
-
|
91
|
-
# API access roles
|
92
|
-
policy.RuleDefault(
|
93
|
-
name='load-balancer:observer_and_owner',
|
94
|
-
check_str='role:load-balancer_observer and '
|
95
|
-
'rule:project-reader',
|
96
|
-
deprecated_rule=deprecated_observer_and_owner,
|
97
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
98
|
-
|
99
|
-
policy.RuleDefault(
|
100
|
-
name='load-balancer:global_observer',
|
101
|
-
check_str='role:load-balancer_global_observer',
|
102
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
103
|
-
|
104
|
-
policy.RuleDefault(
|
105
|
-
name='load-balancer:member_and_owner',
|
106
|
-
check_str='role:load-balancer_member and '
|
107
|
-
'rule:project-member',
|
108
|
-
deprecated_rule=deprecated_member_and_owner,
|
109
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
110
|
-
|
111
20
|
# API access methods
|
112
|
-
|
113
|
-
|
114
|
-
name='load-balancer:admin',
|
115
|
-
check_str='is_admin:True or '
|
116
|
-
'role:load-balancer_admin or '
|
117
|
-
'role:admin',
|
118
|
-
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
21
|
+
#
|
22
|
+
# These are the only rules that should be applied to API endpoints.
|
119
23
|
|
120
24
|
policy.RuleDefault(
|
121
25
|
name='load-balancer:read',
|
@@ -142,20 +46,20 @@ rules = [
|
|
142
46
|
check_str='rule:load-balancer:observer_and_owner or '
|
143
47
|
'rule:load-balancer:global_observer or '
|
144
48
|
'rule:load-balancer:member_and_owner or '
|
145
|
-
'
|
49
|
+
'rule:load-balancer:quota-admin or '
|
146
50
|
'rule:load-balancer:admin',
|
147
51
|
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
148
52
|
|
149
53
|
policy.RuleDefault(
|
150
54
|
name='load-balancer:read-quota-global',
|
151
55
|
check_str='rule:load-balancer:global_observer or '
|
152
|
-
'
|
56
|
+
'rule:load-balancer:quota-admin or '
|
153
57
|
'rule:load-balancer:admin',
|
154
58
|
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
155
59
|
|
156
60
|
policy.RuleDefault(
|
157
61
|
name='load-balancer:write-quota',
|
158
|
-
check_str='
|
62
|
+
check_str='rule:load-balancer:quota-admin or '
|
159
63
|
'rule:load-balancer:admin',
|
160
64
|
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
161
65
|
]
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
2
|
+
# not use this file except in compliance with the License. You may obtain
|
3
|
+
# a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
9
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
10
|
+
# License for the specific language governing permissions and limitations
|
11
|
+
# under the License.
|
12
|
+
|
13
|
+
from oslo_policy import policy
|
14
|
+
|
15
|
+
from octavia.common import constants
|
16
|
+
from octavia.policies import advanced_rbac
|
17
|
+
|
18
|
+
rules = [
|
19
|
+
|
20
|
+
# OpenStack keystone default roles
|
21
|
+
|
22
|
+
# Project scoped Member
|
23
|
+
policy.RuleDefault(
|
24
|
+
name='project-member',
|
25
|
+
check_str='role:member and '
|
26
|
+
'project_id:%(project_id)s',
|
27
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
28
|
+
|
29
|
+
# Project scoped Reader
|
30
|
+
policy.RuleDefault(
|
31
|
+
name='project-reader',
|
32
|
+
check_str='role:reader and '
|
33
|
+
'project_id:%(project_id)s',
|
34
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
35
|
+
|
36
|
+
policy.RuleDefault(
|
37
|
+
name='context_is_admin',
|
38
|
+
check_str='role:admin',
|
39
|
+
deprecated_rule=advanced_rbac.deprecated_context_is_admin,
|
40
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
41
|
+
|
42
|
+
# API access roles
|
43
|
+
policy.RuleDefault(
|
44
|
+
name='load-balancer:admin',
|
45
|
+
check_str='is_admin:True or '
|
46
|
+
'role:admin',
|
47
|
+
deprecated_rule=advanced_rbac.deprecated_admin,
|
48
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
49
|
+
|
50
|
+
# Note: 'is_admin:True' is a policy rule that takes into account the
|
51
|
+
# auth_strategy == noauth configuration setting.
|
52
|
+
# It is equivalent to 'rule:context_is_admin or {auth_strategy == noauth}'
|
53
|
+
|
54
|
+
policy.RuleDefault(
|
55
|
+
name='load-balancer:global_observer',
|
56
|
+
check_str='role:admin',
|
57
|
+
deprecated_rule=advanced_rbac.deprecated_global_observer,
|
58
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
59
|
+
|
60
|
+
policy.RuleDefault(
|
61
|
+
name='load-balancer:member_and_owner',
|
62
|
+
check_str='rule:project-member',
|
63
|
+
deprecated_rule=advanced_rbac.deprecated_member_and_owner,
|
64
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
65
|
+
|
66
|
+
policy.RuleDefault(
|
67
|
+
name='load-balancer:observer_and_owner',
|
68
|
+
check_str='rule:project-reader',
|
69
|
+
deprecated_rule=advanced_rbac.deprecated_observer_and_owner,
|
70
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
71
|
+
|
72
|
+
policy.RuleDefault(
|
73
|
+
name='load-balancer:quota-admin',
|
74
|
+
check_str='role:admin',
|
75
|
+
deprecated_rule=advanced_rbac.deprecated_quota_admin,
|
76
|
+
scope_types=[constants.RBAC_SCOPE_PROJECT]),
|
77
|
+
]
|
78
|
+
|
79
|
+
|
80
|
+
def list_rules():
|
81
|
+
return rules
|
octavia/policies/loadbalancer.py
CHANGED
@@ -34,6 +34,12 @@ rules = [
|
|
34
34
|
"Create a Load Balancer",
|
35
35
|
[{'method': 'POST', 'path': '/v2/lbaas/loadbalancers'}]
|
36
36
|
),
|
37
|
+
policy.DocumentedRuleDefault(
|
38
|
+
f'{constants.RBAC_LOADBALANCER}{constants.RBAC_POST}:vip_sg_ids',
|
39
|
+
constants.RULE_API_WRITE,
|
40
|
+
"Create a Load Balancer with VIP Security Groups",
|
41
|
+
[{'method': 'POST', 'path': '/v2/lbaas/loadbalancers'}]
|
42
|
+
),
|
37
43
|
policy.DocumentedRuleDefault(
|
38
44
|
f'{constants.RBAC_LOADBALANCER}{constants.RBAC_GET_ONE}',
|
39
45
|
constants.RULE_API_READ,
|
@@ -48,6 +54,13 @@ rules = [
|
|
48
54
|
[{'method': 'PUT',
|
49
55
|
'path': '/v2/lbaas/loadbalancers/{loadbalancer_id}'}]
|
50
56
|
),
|
57
|
+
policy.DocumentedRuleDefault(
|
58
|
+
f'{constants.RBAC_LOADBALANCER}{constants.RBAC_PUT}:vip_sg_ids',
|
59
|
+
constants.RULE_API_WRITE,
|
60
|
+
"Update the VIP Security Groups of a Load Balancer",
|
61
|
+
[{'method': 'PUT',
|
62
|
+
'path': '/v2/lbaas/loadbalancers/{loadbalancer_id}'}]
|
63
|
+
),
|
51
64
|
policy.DocumentedRuleDefault(
|
52
65
|
f'{constants.RBAC_LOADBALANCER}{constants.RBAC_DELETE}',
|
53
66
|
constants.RULE_API_WRITE,
|
@@ -139,7 +139,8 @@ MOCK_NEUTRON_PORT = Port(**{'network_id': MOCK_NETWORK_ID,
|
|
139
139
|
'mac_address': MOCK_MAC_ADDR,
|
140
140
|
'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS,
|
141
141
|
'subnet_id': MOCK_SUBNET_ID}],
|
142
|
-
'security_groups': [MOCK_SECURITY_GROUP_ID]
|
142
|
+
'security_groups': [MOCK_SECURITY_GROUP_ID],
|
143
|
+
'binding_vnic_type': constants.VNIC_TYPE_NORMAL})
|
143
144
|
MOCK_NEUTRON_QOS_POLICY_ID = 'mock-qos-id'
|
144
145
|
MOCK_QOS_POLICY_ID1 = 'qos1-id'
|
145
146
|
MOCK_QOS_POLICY_ID2 = 'qos2-id'
|