octavia 15.0.0.0rc1__py3-none-any.whl → 16.0.0.0rc1__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.
Files changed (97) hide show
  1. octavia/amphorae/backends/agent/api_server/keepalivedlvs.py +9 -0
  2. octavia/amphorae/backends/agent/api_server/loadbalancer.py +6 -6
  3. octavia/amphorae/backends/agent/api_server/plug.py +1 -1
  4. octavia/amphorae/backends/agent/api_server/util.py +35 -2
  5. octavia/amphorae/backends/health_daemon/status_message.py +1 -2
  6. octavia/amphorae/drivers/haproxy/rest_api_driver.py +12 -7
  7. octavia/api/drivers/amphora_driver/flavor_schema.py +5 -0
  8. octavia/api/drivers/noop_driver/driver.py +2 -1
  9. octavia/api/drivers/utils.py +12 -0
  10. octavia/api/root_controller.py +8 -2
  11. octavia/api/v2/controllers/base.py +8 -4
  12. octavia/api/v2/controllers/listener.py +12 -2
  13. octavia/api/v2/controllers/load_balancer.py +33 -1
  14. octavia/api/v2/controllers/member.py +58 -4
  15. octavia/api/v2/types/load_balancer.py +7 -1
  16. octavia/api/v2/types/member.py +3 -0
  17. octavia/common/base_taskflow.py +19 -10
  18. octavia/common/clients.py +8 -2
  19. octavia/common/config.py +17 -2
  20. octavia/common/constants.py +6 -0
  21. octavia/common/data_models.py +32 -2
  22. octavia/common/exceptions.py +5 -0
  23. octavia/common/utils.py +4 -1
  24. octavia/common/validate.py +16 -0
  25. octavia/compute/drivers/noop_driver/driver.py +30 -1
  26. octavia/controller/healthmanager/health_manager.py +7 -0
  27. octavia/controller/worker/v2/flows/amphora_flows.py +3 -5
  28. octavia/controller/worker/v2/flows/listener_flows.py +2 -1
  29. octavia/controller/worker/v2/flows/load_balancer_flows.py +38 -0
  30. octavia/controller/worker/v2/taskflow_jobboard_driver.py +34 -6
  31. octavia/controller/worker/v2/tasks/compute_tasks.py +9 -5
  32. octavia/controller/worker/v2/tasks/database_tasks.py +26 -6
  33. octavia/controller/worker/v2/tasks/network_tasks.py +118 -70
  34. octavia/db/base_models.py +29 -5
  35. octavia/db/migration/alembic_migrations/versions/3097e55493ae_add_sg_id_to_vip_table.py +39 -0
  36. octavia/db/migration/alembic_migrations/versions/8db7a6443785_add_member_vnic_type.py +36 -0
  37. octavia/db/migration/alembic_migrations/versions/fabf4983846b_add_member_port_table.py +40 -0
  38. octavia/db/models.py +43 -1
  39. octavia/db/repositories.py +88 -9
  40. octavia/network/base.py +29 -12
  41. octavia/network/data_models.py +2 -1
  42. octavia/network/drivers/neutron/allowed_address_pairs.py +55 -46
  43. octavia/network/drivers/neutron/base.py +28 -16
  44. octavia/network/drivers/neutron/utils.py +2 -2
  45. octavia/network/drivers/noop_driver/driver.py +150 -29
  46. octavia/policies/__init__.py +4 -0
  47. octavia/policies/advanced_rbac.py +95 -0
  48. octavia/policies/base.py +5 -101
  49. octavia/policies/keystone_default_roles.py +81 -0
  50. octavia/policies/loadbalancer.py +13 -0
  51. octavia/tests/common/constants.py +2 -1
  52. octavia/tests/common/sample_data_models.py +27 -14
  53. octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +5 -4
  54. octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +2 -1
  55. octavia/tests/functional/api/v2/test_health_monitor.py +1 -1
  56. octavia/tests/functional/api/v2/test_l7policy.py +1 -1
  57. octavia/tests/functional/api/v2/test_listener.py +1 -1
  58. octavia/tests/functional/api/v2/test_load_balancer.py +150 -4
  59. octavia/tests/functional/api/v2/test_member.py +50 -0
  60. octavia/tests/functional/api/v2/test_pool.py +1 -1
  61. octavia/tests/functional/api/v2/test_quotas.py +5 -8
  62. octavia/tests/functional/db/base.py +6 -6
  63. octavia/tests/functional/db/test_models.py +124 -1
  64. octavia/tests/functional/db/test_repositories.py +237 -19
  65. octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +89 -1
  66. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +10 -7
  67. octavia/tests/unit/api/drivers/test_utils.py +6 -1
  68. octavia/tests/unit/certificates/generator/test_local.py +1 -1
  69. octavia/tests/unit/common/test_base_taskflow.py +4 -3
  70. octavia/tests/unit/compute/drivers/noop_driver/test_driver.py +28 -2
  71. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +27 -1
  72. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +28 -6
  73. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +100 -79
  74. octavia/tests/unit/controller/worker/v2/test_taskflow_jobboard_driver.py +8 -0
  75. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +62 -45
  76. octavia/tests/unit/network/drivers/neutron/test_base.py +7 -7
  77. octavia/tests/unit/network/drivers/noop_driver/test_driver.py +55 -42
  78. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/tox.ini +0 -1
  79. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/AUTHORS +3 -0
  80. octavia-16.0.0.0rc1.dist-info/METADATA +156 -0
  81. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/RECORD +95 -90
  82. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/WHEEL +1 -1
  83. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/entry_points.txt +1 -1
  84. octavia-16.0.0.0rc1.dist-info/pbr.json +1 -0
  85. octavia-15.0.0.0rc1.dist-info/METADATA +0 -156
  86. octavia-15.0.0.0rc1.dist-info/pbr.json +0 -1
  87. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/LICENSE +0 -0
  88. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/README.rst +0 -0
  89. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  90. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  91. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  92. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  93. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  94. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  95. {octavia-15.0.0.0rc1.data → octavia-16.0.0.0rc1.data}/scripts/octavia-wsgi +0 -0
  96. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/LICENSE +0 -0
  97. {octavia-15.0.0.0rc1.dist-info → octavia-16.0.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -50,6 +50,9 @@ class SampleDriverDataModels:
50
50
  self.pool_ca_container_ref = uuidutils.generate_uuid()
51
51
  self.pool_crl_container_ref = uuidutils.generate_uuid()
52
52
 
53
+ self.vip_sg_ids = [uuidutils.generate_uuid(),
54
+ uuidutils.generate_uuid()]
55
+
53
56
  self.pool1_id = uuidutils.generate_uuid()
54
57
  self.pool2_id = uuidutils.generate_uuid()
55
58
 
@@ -145,7 +148,8 @@ class SampleDriverDataModels:
145
148
  constants.CREATED_AT: self.created_at,
146
149
  constants.UPDATED_AT: self.updated_at,
147
150
  lib_consts.MONITOR_ADDRESS: '192.0.2.26',
148
- lib_consts.MONITOR_PORT: 81}
151
+ lib_consts.MONITOR_PORT: 81,
152
+ lib_consts.VNIC_TYPE: lib_consts.VNIC_TYPE_NORMAL}
149
153
 
150
154
  self.test_member1_dict.update(self._common_test_dict)
151
155
 
@@ -154,6 +158,8 @@ class SampleDriverDataModels:
154
158
  self.test_member2_dict[constants.IP_ADDRESS] = '192.0.2.17'
155
159
  self.test_member2_dict[lib_consts.MONITOR_ADDRESS] = '192.0.2.27'
156
160
  self.test_member2_dict[lib_consts.NAME] = 'member2'
161
+ self.test_member2_dict[
162
+ lib_consts.VNIC_TYPE] = lib_consts.VNIC_TYPE_DIRECT
157
163
 
158
164
  self.test_member3_dict = copy.deepcopy(self.test_member1_dict)
159
165
  self.test_member3_dict[lib_consts.ID] = self.member3_id
@@ -182,24 +188,28 @@ class SampleDriverDataModels:
182
188
  self.db_pool1_members = [self.db_member1, self.db_member2]
183
189
  self.db_pool2_members = [self.db_member3, self.db_member4]
184
190
 
185
- self.provider_member1_dict = {lib_consts.ADDRESS: '192.0.2.16',
186
- lib_consts.ADMIN_STATE_UP: True,
187
- lib_consts.MEMBER_ID: self.member1_id,
188
- lib_consts.MONITOR_ADDRESS: '192.0.2.26',
189
- lib_consts.MONITOR_PORT: 81,
190
- lib_consts.NAME: 'member1',
191
- lib_consts.POOL_ID: self.pool1_id,
192
- lib_consts.PROJECT_ID: self.project_id,
193
- lib_consts.PROTOCOL_PORT: 80,
194
- lib_consts.SUBNET_ID: self.subnet_id,
195
- lib_consts.WEIGHT: 0,
196
- lib_consts.BACKUP: False}
191
+ self.provider_member1_dict = {
192
+ lib_consts.ADDRESS: '192.0.2.16',
193
+ lib_consts.ADMIN_STATE_UP: True,
194
+ lib_consts.MEMBER_ID: self.member1_id,
195
+ lib_consts.MONITOR_ADDRESS: '192.0.2.26',
196
+ lib_consts.MONITOR_PORT: 81,
197
+ lib_consts.NAME: 'member1',
198
+ lib_consts.POOL_ID: self.pool1_id,
199
+ lib_consts.PROJECT_ID: self.project_id,
200
+ lib_consts.PROTOCOL_PORT: 80,
201
+ lib_consts.SUBNET_ID: self.subnet_id,
202
+ lib_consts.WEIGHT: 0,
203
+ lib_consts.BACKUP: False,
204
+ lib_consts.VNIC_TYPE: lib_consts.VNIC_TYPE_NORMAL}
197
205
 
198
206
  self.provider_member2_dict = copy.deepcopy(self.provider_member1_dict)
199
207
  self.provider_member2_dict[lib_consts.MEMBER_ID] = self.member2_id
200
208
  self.provider_member2_dict[lib_consts.ADDRESS] = '192.0.2.17'
201
209
  self.provider_member2_dict[lib_consts.MONITOR_ADDRESS] = '192.0.2.27'
202
210
  self.provider_member2_dict[lib_consts.NAME] = 'member2'
211
+ self.provider_member2_dict[
212
+ lib_consts.VNIC_TYPE] = lib_consts.VNIC_TYPE_DIRECT
203
213
 
204
214
  self.provider_member3_dict = copy.deepcopy(self.provider_member1_dict)
205
215
  self.provider_member3_dict[lib_consts.MEMBER_ID] = self.member3_id
@@ -600,6 +610,7 @@ class SampleDriverDataModels:
600
610
  constants.PORT_ID: self.port_id,
601
611
  lib_consts.SUBNET_ID: self.subnet_id,
602
612
  constants.QOS_POLICY_ID: self.qos_policy_id,
613
+ constants.SG_IDS: self.vip_sg_ids,
603
614
  constants.OCTAVIA_OWNED: None}
604
615
 
605
616
  self.provider_vip_dict = {
@@ -608,6 +619,7 @@ class SampleDriverDataModels:
608
619
  lib_consts.VIP_PORT_ID: self.port_id,
609
620
  lib_consts.VIP_SUBNET_ID: self.subnet_id,
610
621
  lib_consts.VIP_QOS_POLICY_ID: self.qos_policy_id,
622
+ lib_consts.VIP_SG_IDS: self.vip_sg_ids,
611
623
  constants.OCTAVIA_OWNED: None}
612
624
 
613
625
  self.test_additional_vip_dict = {
@@ -627,7 +639,8 @@ class SampleDriverDataModels:
627
639
  network_id=self.network_id,
628
640
  port_id=self.port_id,
629
641
  subnet_id=self.subnet_id,
630
- qos_policy_id=self.qos_policy_id)
642
+ qos_policy_id=self.qos_policy_id,
643
+ sg_ids=self.vip_sg_ids)
631
644
 
632
645
  self.db_additional_vip = data_models.AdditionalVip(
633
646
  ip_address=self.ip_address2,
@@ -12,6 +12,7 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
+ import hashlib
15
16
  import os
16
17
  import random
17
18
  import socket
@@ -22,7 +23,6 @@ from unittest import mock
22
23
  import fixtures
23
24
  from oslo_config import fixture as oslo_fixture
24
25
  from oslo_serialization import jsonutils
25
- from oslo_utils.secretutils import md5
26
26
  from oslo_utils import uuidutils
27
27
  import webob
28
28
 
@@ -740,9 +740,10 @@ class TestServerTestCase(base.TestCase):
740
740
  rv = self.centos_app.get('/' + api_server.VERSION +
741
741
  '/loadbalancer/123/certificates/test.pem')
742
742
  self.assertEqual(200, rv.status_code)
743
- self.assertEqual(dict(md5sum=md5(octavia_utils.b(CONTENT),
744
- usedforsecurity=False).hexdigest()),
745
- jsonutils.loads(rv.data.decode('utf-8')))
743
+ self.assertEqual(
744
+ dict(md5sum=hashlib.md5(octavia_utils.b(CONTENT),
745
+ usedforsecurity=False).hexdigest()),
746
+ jsonutils.loads(rv.data.decode('utf-8')))
746
747
 
747
748
  def test_ubuntu_upload_certificate_md5(self):
748
749
  self._test_upload_certificate_md5(consts.UBUNTU)
@@ -503,7 +503,8 @@ class DriverAgentTest(base.OctaviaDBTestBase):
503
503
  lib_consts.MONITOR_PORT,
504
504
  lib_consts.SUBNET_ID,
505
505
  lib_consts.WEIGHT,
506
- lib_consts.BACKUP):
506
+ lib_consts.BACKUP,
507
+ lib_consts.VNIC_TYPE):
507
508
  self.assertEqual(provider_member_dict.get(key),
508
509
  result_member_dict.get(key))
509
510
 
@@ -406,7 +406,7 @@ class TestHealthMonitor(base.BaseAPITest):
406
406
  'is_admin_project': True,
407
407
  'service_project_domain_id': None,
408
408
  'service_project_id': None,
409
- 'roles': ['load-balancer_global_observer'],
409
+ 'roles': ['admin'],
410
410
  'user_id': None,
411
411
  'is_admin': False,
412
412
  'service_user_domain_id': None,
@@ -320,7 +320,7 @@ class TestL7Policy(base.BaseAPITest):
320
320
  'is_admin_project': True,
321
321
  'service_project_domain_id': None,
322
322
  'service_project_id': None,
323
- 'roles': ['load-balancer_global_observer'],
323
+ 'roles': ['admin'],
324
324
  'user_id': None,
325
325
  'is_admin': False,
326
326
  'service_user_domain_id': None,
@@ -202,7 +202,7 @@ class TestListener(base.BaseAPITest):
202
202
  'is_admin_project': True,
203
203
  'service_project_domain_id': None,
204
204
  'service_project_id': None,
205
- 'roles': ['load-balancer_global_observer'],
205
+ 'roles': ['admin'],
206
206
  'user_id': None,
207
207
  'is_admin': False,
208
208
  'service_user_domain_id': None,
@@ -1384,7 +1384,7 @@ class TestLoadBalancer(base.BaseAPITest):
1384
1384
  'is_admin_project': True,
1385
1385
  'service_project_domain_id': None,
1386
1386
  'service_project_id': None,
1387
- 'roles': ['load-balancer_global_observer'],
1387
+ 'roles': ['admin'],
1388
1388
  'user_id': None,
1389
1389
  'is_admin': False,
1390
1390
  'service_user_domain_id': None,
@@ -2054,6 +2054,37 @@ class TestLoadBalancer(base.BaseAPITest):
2054
2054
  self.put(self.LB_PATH.format(lb_id=lb_dict.get('id')),
2055
2055
  lb_json, status=400)
2056
2056
 
2057
+ def test_update_with_sg_ids(self):
2058
+ project_id = uuidutils.generate_uuid()
2059
+ sg1_id = uuidutils.generate_uuid()
2060
+ sg2_id = uuidutils.generate_uuid()
2061
+ lb = self.create_load_balancer(uuidutils.generate_uuid(),
2062
+ name='lb1',
2063
+ project_id=project_id,
2064
+ vip_sg_ids=[sg1_id, sg2_id])
2065
+ lb_dict = lb.get(self.root_tag)
2066
+ lb_id = lb_dict.get('id')
2067
+ self.assertEqual(sorted([sg1_id, sg2_id]),
2068
+ sorted(lb_dict['vip_sg_ids']))
2069
+ self.set_lb_status(lb_dict.get('id'))
2070
+
2071
+ lb_json = self._build_body({'vip_sg_ids': [sg2_id]})
2072
+ self.put(self.LB_PATH.format(lb_id=lb_id),
2073
+ lb_json, status=200)
2074
+ self.set_lb_status(lb_dict.get('id'))
2075
+ response = self.get(self.LB_PATH.format(lb_id=lb_id))
2076
+ lb_dict = response.json.get(self.root_tag)
2077
+ self.assertEqual(sorted([sg2_id]),
2078
+ sorted(lb_dict['vip_sg_ids']))
2079
+
2080
+ lb_json = self._build_body({'vip_sg_ids': []})
2081
+ lb = self.put(self.LB_PATH.format(lb_id=lb_dict.get('id')),
2082
+ lb_json, status=200)
2083
+ self.set_lb_status(lb_dict.get('id'))
2084
+ response = self.get(self.LB_PATH.format(lb_id=lb_id))
2085
+ lb_dict = response.json.get(self.root_tag)
2086
+ self.assertEqual(0, len(lb_dict['vip_sg_ids']))
2087
+
2057
2088
  def test_update_bad_lb_id(self):
2058
2089
  path = self.LB_PATH.format(lb_id='SEAN-CONNERY')
2059
2090
  self.put(path, body={}, status=404)
@@ -2503,7 +2534,7 @@ class TestLoadBalancer(base.BaseAPITest):
2503
2534
  'is_admin_project': True,
2504
2535
  'service_project_domain_id': None,
2505
2536
  'service_project_id': None,
2506
- 'roles': ['load-balancer_admin'],
2537
+ 'roles': ['admin'],
2507
2538
  'user_id': None,
2508
2539
  'is_admin': False,
2509
2540
  'service_user_domain_id': None,
@@ -2735,8 +2766,13 @@ class TestLoadBalancerGraph(base.BaseAPITest):
2735
2766
  expected_additional_vips = expected_graph.pop('additional_vips', [])
2736
2767
  observed_additional_vips = observed_graph_copy.pop('additional_vips',
2737
2768
  [])
2769
+ expected_vip_sg_ids = expected_graph.pop('vip_sg_ids', [])
2770
+ observed_vip_sg_ids = observed_graph_copy.pop('vip_sg_ids', [])
2738
2771
  self.assertEqual(expected_graph, observed_graph_copy)
2739
2772
 
2773
+ self.assertEqual(sorted(expected_vip_sg_ids),
2774
+ sorted(observed_vip_sg_ids))
2775
+
2740
2776
  self.assertEqual(len(expected_pools), len(observed_pools))
2741
2777
 
2742
2778
  self.assertEqual(len(expected_listeners), len(observed_listeners))
@@ -2800,7 +2836,8 @@ class TestLoadBalancerGraph(base.BaseAPITest):
2800
2836
  self.assertIn(observed_add_vip, expected_additional_vips)
2801
2837
 
2802
2838
  def _get_lb_bodies(self, create_listeners, expected_listeners,
2803
- create_pools=None, additional_vips=None):
2839
+ create_pools=None, additional_vips=None,
2840
+ vip_sg_ids=None, flavor_id=None, sriov=False):
2804
2841
  create_lb = {
2805
2842
  'name': 'lb1',
2806
2843
  'project_id': self._project_id,
@@ -2811,6 +2848,8 @@ class TestLoadBalancerGraph(base.BaseAPITest):
2811
2848
  'listeners': create_listeners,
2812
2849
  'pools': create_pools or []
2813
2850
  }
2851
+ if vip_sg_ids:
2852
+ create_lb['vip_sg_ids'] = vip_sg_ids
2814
2853
  if additional_vips:
2815
2854
  create_lb.update({'additional_vips': additional_vips})
2816
2855
  expected_lb = {
@@ -2830,7 +2869,13 @@ class TestLoadBalancerGraph(base.BaseAPITest):
2830
2869
  'provider': 'noop_driver',
2831
2870
  'tags': [],
2832
2871
  'vip_vnic_type': constants.VNIC_TYPE_NORMAL,
2872
+ 'vip_sg_ids': vip_sg_ids or [],
2833
2873
  }
2874
+ if flavor_id:
2875
+ create_lb['flavor_id'] = flavor_id
2876
+ expected_lb['flavor_id'] = flavor_id
2877
+ if sriov:
2878
+ expected_lb['vip_vnic_type'] = constants.VNIC_TYPE_DIRECT
2834
2879
  expected_lb.update(create_lb)
2835
2880
  expected_lb['listeners'] = expected_listeners
2836
2881
  expected_lb['pools'] = create_pools or []
@@ -3003,7 +3048,7 @@ class TestLoadBalancerGraph(base.BaseAPITest):
3003
3048
  expected_pool['healthmonitor'] = expected_hm
3004
3049
  return create_pool, expected_pool
3005
3050
 
3006
- def _get_member_bodies(self, protocol_port=80):
3051
+ def _get_member_bodies(self, protocol_port=80, sriov=False):
3007
3052
  create_member = {
3008
3053
  'address': '10.0.0.1',
3009
3054
  'protocol_port': protocol_port
@@ -3016,6 +3061,9 @@ class TestLoadBalancerGraph(base.BaseAPITest):
3016
3061
  'project_id': self._project_id,
3017
3062
  'tags': []
3018
3063
  }
3064
+ if sriov:
3065
+ create_member[constants.REQUEST_SRIOV] = True
3066
+ expected_member[constants.VNIC_TYPE] = constants.VNIC_TYPE_DIRECT
3019
3067
  expected_member.update(create_member)
3020
3068
  return create_member, expected_member
3021
3069
 
@@ -3211,6 +3259,16 @@ class TestLoadBalancerGraph(base.BaseAPITest):
3211
3259
  api_lb = response.json.get(self.root_tag)
3212
3260
  self._assert_graphs_equal(expected_lb, api_lb)
3213
3261
 
3262
+ def test_with_sg_ids(self):
3263
+ create_lb, expected_lb = self._get_lb_bodies(
3264
+ [], [], vip_sg_ids=[uuidutils.generate_uuid(),
3265
+ uuidutils.generate_uuid()])
3266
+
3267
+ body = self._build_body(create_lb)
3268
+ response = self.post(self.LBS_PATH, body)
3269
+ api_lb = response.json.get(self.root_tag)
3270
+ self._assert_graphs_equal(expected_lb, api_lb)
3271
+
3214
3272
  def test_with_one_listener(self):
3215
3273
  create_listener, expected_listener = self._get_listener_bodies()
3216
3274
  create_lb, expected_lb = self._get_lb_bodies([create_listener],
@@ -3220,6 +3278,53 @@ class TestLoadBalancerGraph(base.BaseAPITest):
3220
3278
  api_lb = response.json.get(self.root_tag)
3221
3279
  self._assert_graphs_equal(expected_lb, api_lb)
3222
3280
 
3281
+ def test_with_one_listener_sg_ids(self):
3282
+ create_listener, expected_listener = self._get_listener_bodies()
3283
+ create_lb, expected_lb = self._get_lb_bodies(
3284
+ [create_listener], [expected_listener],
3285
+ vip_sg_ids=[uuidutils.generate_uuid(),
3286
+ uuidutils.generate_uuid()])
3287
+
3288
+ body = self._build_body(create_lb)
3289
+ response = self.post(self.LBS_PATH, body)
3290
+ api_lb = response.json.get(self.root_tag)
3291
+ self._assert_graphs_equal(expected_lb, api_lb)
3292
+
3293
+ @mock.patch('octavia.api.v2.controllers.load_balancer.'
3294
+ 'LoadBalancersController._apply_flavor_to_lb_dict',
3295
+ return_value={constants.SRIOV_VIP: True})
3296
+ def test_with_vip_vnic_type_direct_and_sg_ids(self, mock_flavor_dict):
3297
+ create_lb, expected_lb = self._get_lb_bodies(
3298
+ [], [],
3299
+ vip_sg_ids=[uuidutils.generate_uuid(),
3300
+ uuidutils.generate_uuid()])
3301
+ expected_lb[constants.VIP_VNIC_TYPE] = constants.VNIC_TYPE_DIRECT
3302
+
3303
+ body = self._build_body(create_lb)
3304
+
3305
+ response = self.post(self.LBS_PATH, body, status=400,
3306
+ expect_errors=True)
3307
+ error_text = response.json.get('faultstring')
3308
+ self.assertIn("VIP Security Groups are not allowed with VNIC "
3309
+ "direct type", error_text)
3310
+
3311
+ def test_with_one_listener_sg_ids_and_allowed_cidrs(self):
3312
+ allowed_cidrs = ['10.0.1.0/24']
3313
+ create_listener, expected_listener = self._get_listener_bodies(
3314
+ create_allowed_cidrs=allowed_cidrs,
3315
+ expected_allowed_cidrs=allowed_cidrs)
3316
+ create_lb, expected_lb = self._get_lb_bodies(
3317
+ [create_listener], [expected_listener],
3318
+ vip_sg_ids=[uuidutils.generate_uuid(),
3319
+ uuidutils.generate_uuid()])
3320
+
3321
+ body = self._build_body(create_lb)
3322
+ response = self.post(self.LBS_PATH, body, status=400,
3323
+ expect_errors=True)
3324
+ error_text = response.json.get('faultstring')
3325
+ self.assertIn("Allowed CIDRs are not allowed when using custom "
3326
+ "VIP Security Groups", error_text)
3327
+
3223
3328
  def test_with_one_listener_with_default_timeouts(self):
3224
3329
  self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
3225
3330
  self.conf.config(group='haproxy_amphora', timeout_client_data=20)
@@ -3299,6 +3404,47 @@ class TestLoadBalancerGraph(base.BaseAPITest):
3299
3404
  api_lb = response.json.get(self.root_tag)
3300
3405
  self._assert_graphs_equal(expected_lb, api_lb)
3301
3406
 
3407
+ def test_with_one_listener_one_member_sriov(self):
3408
+ flavor_profile = self.create_flavor_profile(
3409
+ 'sriov-graph-create', 'noop_driver',
3410
+ f'{{"{constants.ALLOW_MEMBER_SRIOV}": true, '
3411
+ f'"{constants.SRIOV_VIP}": true}}')
3412
+
3413
+ flavor = self.create_flavor('sriov-graph-create', '',
3414
+ flavor_profile['id'], True)
3415
+
3416
+ create_member, expected_member = self._get_member_bodies(sriov=True)
3417
+ create_pool, expected_pool = self._get_pool_bodies(
3418
+ create_members=[create_member],
3419
+ expected_members=[expected_member])
3420
+ create_listener, expected_listener = self._get_listener_bodies(
3421
+ create_default_pool_name=create_pool['name'])
3422
+ create_lb, expected_lb = self._get_lb_bodies(
3423
+ create_listeners=[create_listener],
3424
+ expected_listeners=[expected_listener],
3425
+ create_pools=[create_pool], flavor_id=flavor['id'], sriov=True)
3426
+ body = self._build_body(create_lb)
3427
+ response = self.post(self.LBS_PATH, body)
3428
+ api_lb = response.json.get(self.root_tag)
3429
+ self._assert_graphs_equal(expected_lb, api_lb)
3430
+
3431
+ def test_with_one_listener_one_member_sriov_disabled(self):
3432
+ create_member, expected_member = self._get_member_bodies(sriov=True)
3433
+ create_pool, expected_pool = self._get_pool_bodies(
3434
+ create_members=[create_member],
3435
+ expected_members=[expected_member])
3436
+ create_listener, expected_listener = self._get_listener_bodies(
3437
+ create_default_pool_name=create_pool['name'])
3438
+ create_lb, expected_lb = self._get_lb_bodies(
3439
+ create_listeners=[create_listener],
3440
+ expected_listeners=[expected_listener],
3441
+ create_pools=[create_pool])
3442
+ body = self._build_body(create_lb)
3443
+ response = self.post(self.LBS_PATH, body, status=400)
3444
+ error_text = response.json.get('faultstring')
3445
+ self.assertIn('flavor does not allow SR-IOV member ports.',
3446
+ error_text)
3447
+
3302
3448
  def test_with_one_listener_one_hm(self):
3303
3449
  create_hm, expected_hm = self._get_hm_bodies()
3304
3450
  create_pool, expected_pool = self._get_pool_bodies(
@@ -18,6 +18,7 @@ from octavia_lib.api.drivers import data_models as driver_dm
18
18
  from oslo_config import cfg
19
19
  from oslo_config import fixture as oslo_fixture
20
20
  from oslo_utils import uuidutils
21
+ from sqlalchemy.orm import exc as sa_exception
21
22
 
22
23
  from octavia.api.drivers import utils as driver_utils
23
24
  from octavia.common import constants
@@ -623,6 +624,55 @@ class TestMember(base.BaseAPITest):
623
624
  self.assertIn('Provider \'bad_driver\' reports error: broken',
624
625
  response.get('faultstring'))
625
626
 
627
+ def test_create_with_sriov(self):
628
+ flavor_profile = self.create_flavor_profile(
629
+ 'sriov-member-create', 'noop_driver',
630
+ f'{{"{constants.ALLOW_MEMBER_SRIOV}": true}}')
631
+
632
+ flavor = self.create_flavor('sriov-member-create', '',
633
+ flavor_profile['id'], True)
634
+
635
+ vip_subnet_id = uuidutils.generate_uuid()
636
+ lb = self.create_load_balancer(vip_subnet_id, flavor_id=flavor['id'])
637
+ lb_id = lb.get('loadbalancer').get('id')
638
+ self.set_lb_status(lb_id)
639
+
640
+ listener = self.create_listener(
641
+ constants.PROTOCOL_HTTP, 80,
642
+ lb_id=lb_id)
643
+ listener_id = listener.get('listener').get('id')
644
+ self.set_lb_status(lb_id)
645
+
646
+ pool_with_listener = self.create_pool(
647
+ lb_id, constants.PROTOCOL_HTTP,
648
+ constants.LB_ALGORITHM_ROUND_ROBIN, listener_id=listener_id)
649
+ pool_with_listener_id = pool_with_listener.get('pool').get('id')
650
+ self.set_lb_status(lb_id)
651
+
652
+ api_member = self.create_member(
653
+ pool_with_listener_id, '192.0.2.1',
654
+ 80, request_sriov=True).get(self.root_tag)
655
+ self.assertEqual(constants.VNIC_TYPE_DIRECT,
656
+ api_member[constants.VNIC_TYPE])
657
+
658
+ def test_create_with_sriov_disabled(self):
659
+ # Test with no flavor enabling SR-IOV members
660
+ response = self.create_member(
661
+ self.pool_id, '192.0.2.1',
662
+ 80, request_sriov=True, status=400)
663
+ self.assertIn('flavor does not allow SR-IOV member ports',
664
+ response.get('faultstring'))
665
+
666
+ @mock.patch('octavia.db.repositories.FlavorRepository.'
667
+ 'get_flavor_metadata_dict')
668
+ def test_create_with_sriov_missing_flavor(self, mock_get_flavor):
669
+ mock_get_flavor.side_effect = sa_exception.NoResultFound()
670
+ response = self.create_member(
671
+ self.pool_id, '192.0.2.1',
672
+ 80, request_sriov=True, status=400)
673
+ self.assertIn('flavor does not allow SR-IOV member ports',
674
+ response.get('faultstring'))
675
+
626
676
  @mock.patch('octavia.api.drivers.driver_factory.get_driver')
627
677
  @mock.patch('octavia.api.drivers.utils.call_provider')
628
678
  def test_full_batch_members(self, mock_provider, mock_get_driver):
@@ -340,7 +340,7 @@ class TestPool(base.BaseAPITest):
340
340
  'is_admin_project': True,
341
341
  'service_project_domain_id': None,
342
342
  'service_project_id': None,
343
- 'roles': ['load-balancer_global_observer'],
343
+ 'roles': ['admin'],
344
344
  'user_id': None,
345
345
  'is_admin': False,
346
346
  'service_user_domain_id': None,
@@ -298,7 +298,7 @@ class TestQuotas(base.BaseAPITest):
298
298
  'is_admin_project': True,
299
299
  'service_project_domain_id': None,
300
300
  'service_project_id': None,
301
- 'roles': ['load-balancer_global_observer'],
301
+ 'roles': ['admin'],
302
302
  'user_id': None,
303
303
  'is_admin': False,
304
304
  'service_user_domain_id': None,
@@ -345,7 +345,7 @@ class TestQuotas(base.BaseAPITest):
345
345
  'is_admin_project': True,
346
346
  'service_project_domain_id': None,
347
347
  'service_project_id': None,
348
- 'roles': ['load-balancer_quota_admin'],
348
+ 'roles': ['admin'],
349
349
  'user_id': None,
350
350
  'is_admin': False,
351
351
  'service_user_domain_id': None,
@@ -485,11 +485,8 @@ class TestQuotas(base.BaseAPITest):
485
485
  def test_get_Authorized_observer(self):
486
486
  self._test_get_Authorized(['load-balancer_observer', 'reader'])
487
487
 
488
- def test_get_Authorized_global_observer(self):
489
- self._test_get_Authorized(['load-balancer_global_observer'])
490
-
491
488
  def test_get_Authorized_quota_admin(self):
492
- self._test_get_Authorized(['load-balancer_quota_admin'])
489
+ self._test_get_Authorized(['admin'])
493
490
 
494
491
  def _test_get_Authorized(self, roles):
495
492
  project1_id = uuidutils.generate_uuid()
@@ -759,7 +756,7 @@ class TestQuotas(base.BaseAPITest):
759
756
  'is_admin_project': True,
760
757
  'service_project_domain_id': None,
761
758
  'service_project_id': None,
762
- 'roles': ['load-balancer_quota_admin'],
759
+ 'roles': ['admin'],
763
760
  'user_id': None,
764
761
  'is_admin': False,
765
762
  'service_user_domain_id': None,
@@ -871,7 +868,7 @@ class TestQuotas(base.BaseAPITest):
871
868
  'is_admin_project': True,
872
869
  'service_project_domain_id': None,
873
870
  'service_project_id': None,
874
- 'roles': ['load-balancer_quota_admin'],
871
+ 'roles': ['admin'],
875
872
  'user_id': None,
876
873
  'is_admin': False,
877
874
  'service_user_domain_id': None,
@@ -14,9 +14,8 @@
14
14
 
15
15
  import os
16
16
 
17
- from oslo_config import cfg
18
17
  from oslo_config import fixture as oslo_fixture
19
- from oslo_db.sqlalchemy import session as db_session
18
+ from oslo_db.sqlalchemy import enginefacade
20
19
  from oslotest import base as test_base
21
20
 
22
21
  from octavia.common import config
@@ -71,10 +70,11 @@ class OctaviaDBTestBase(test_base.BaseTestCase):
71
70
  # don't use the _FACADE singleton. Some tests will use in-memory
72
71
  # sqlite, some will use a file backed sqlite.
73
72
  if 'sqlite:///' in self.connection_string:
74
- facade = db_session.EngineFacade.from_config(cfg.CONF,
75
- sqlite_fk=True)
76
- engine = facade.get_engine()
77
- session = facade.get_session(expire_on_commit=True)
73
+ facade = enginefacade.transaction_context()
74
+ facade.configure(sqlite_fk=True, expire_on_commit=True)
75
+ engine = facade.writer.get_engine()
76
+ sessionmaker = facade.writer.get_sessionmaker()
77
+ session = sessionmaker()
78
78
  self.facade = facade
79
79
  else:
80
80
  engine = db_api.get_engine()