octavia 15.0.0__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.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/tox.ini +0 -1
  79. {octavia-15.0.0.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.dist-info → octavia-16.0.0.0rc1.dist-info}/RECORD +95 -90
  82. {octavia-15.0.0.dist-info → octavia-16.0.0.0rc1.dist-info}/WHEEL +1 -1
  83. {octavia-15.0.0.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.dist-info/METADATA +0 -156
  86. octavia-15.0.0.dist-info/pbr.json +0 -1
  87. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/LICENSE +0 -0
  88. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/README.rst +0 -0
  89. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  90. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  91. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  92. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  93. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  94. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  95. {octavia-15.0.0.data → octavia-16.0.0.0rc1.data}/scripts/octavia-wsgi +0 -0
  96. {octavia-15.0.0.dist-info → octavia-16.0.0.0rc1.dist-info}/LICENSE +0 -0
  97. {octavia-15.0.0.dist-info → octavia-16.0.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@ from unittest import mock
16
16
 
17
17
  from octavia_lib.api.drivers import data_models as driver_dm
18
18
  from octavia_lib.api.drivers import exceptions as lib_exceptions
19
+ from oslo_utils import uuidutils
19
20
 
20
21
  from octavia.api.drivers import utils
21
22
  from octavia.common import constants
@@ -109,6 +110,7 @@ class TestUtils(base.TestCase):
109
110
  listener_certs, listener_certs,
110
111
  listener_certs]
111
112
  mock_get_flavor.return_value = {'shaved_ice': 'cherry'}
113
+ sg_id = uuidutils.generate_uuid()
112
114
  test_lb_dict = {'name': 'lb1',
113
115
  'project_id': self.sample_data.project_id,
114
116
  'vip_subnet_id': self.sample_data.subnet_id,
@@ -116,6 +118,7 @@ class TestUtils(base.TestCase):
116
118
  'vip_address': self.sample_data.ip_address,
117
119
  'vip_network_id': self.sample_data.network_id,
118
120
  'vip_qos_policy_id': self.sample_data.qos_policy_id,
121
+ 'vip_sg_ids': [sg_id],
119
122
  'id': self.sample_data.lb_id,
120
123
  'listeners': [],
121
124
  'pools': [],
@@ -136,6 +139,7 @@ class TestUtils(base.TestCase):
136
139
  'vip_port_id': self.sample_data.port_id,
137
140
  'vip_qos_policy_id': self.sample_data.qos_policy_id,
138
141
  'vip_network_id': self.sample_data.network_id,
142
+ 'vip_sg_ids': [sg_id],
139
143
  'pools': self.sample_data.provider_pools,
140
144
  'flavor': {'shaved_ice': 'cherry'},
141
145
  'name': 'lb1'}
@@ -143,7 +147,8 @@ class TestUtils(base.TestCase):
143
147
  network_id=self.sample_data.network_id,
144
148
  port_id=self.sample_data.port_id,
145
149
  subnet_id=self.sample_data.subnet_id,
146
- qos_policy_id=self.sample_data.qos_policy_id)
150
+ qos_policy_id=self.sample_data.qos_policy_id,
151
+ sg_ids=[sg_id])
147
152
 
148
153
  provider_lb_dict = utils.lb_dict_to_provider_dict(
149
154
  test_lb_dict, vip=vip, db_pools=self.sample_data.test_db_pools,
@@ -158,7 +158,7 @@ class TestLocalGenerator(local_csr.BaseLocalCSRTestCase):
158
158
 
159
159
  def test_generate_cert_key_pair(self):
160
160
  cn = 'testCN'
161
- bit_length = 512
161
+ bit_length = 1024
162
162
 
163
163
  # Attempt to generate a cert/key pair
164
164
  cert_object = self.cert_generator.generate_cert_key_pair(
@@ -130,12 +130,13 @@ class TestTaskFlowServiceController(base.TestCase):
130
130
  job1.wait.assert_called_once()
131
131
  job2.wait.assert_called_once()
132
132
 
133
- @mock.patch('octavia.common.base_taskflow.RedisDynamicLoggingConductor')
133
+ @mock.patch('octavia.common.base_taskflow.'
134
+ 'ExtendExpiryDynamicLoggingConductor')
134
135
  @mock.patch('octavia.common.base_taskflow.DynamicLoggingConductor')
135
136
  @mock.patch('concurrent.futures.ThreadPoolExecutor')
136
- def test_run_conductor(self, mock_threadpoolexec, dynamiccond, rediscond):
137
+ def test_run_conductor(self, mock_threadpoolexec, dynamiccond, expirycond):
137
138
  self.service_controller.run_conductor("test")
138
- rediscond.assert_called_once_with(
139
+ expirycond.assert_called_once_with(
139
140
  "test", self.jobboard_mock.__enter__(),
140
141
  persistence=self.persistence_mock.__enter__(),
141
142
  engine='parallel',
@@ -11,6 +11,7 @@
11
11
  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
+ from unittest import mock
14
15
 
15
16
  from oslo_utils import uuidutils
16
17
 
@@ -28,7 +29,14 @@ class TestNoopComputeDriver(base.TestCase):
28
29
 
29
30
  def setUp(self):
30
31
  super().setUp()
31
- self.driver = driver.NoopComputeDriver()
32
+ self.mock_engine = mock.MagicMock()
33
+ with mock.patch('octavia.compute.drivers.noop_driver.driver.'
34
+ 'create_engine') as mock_create_engine:
35
+ mock_create_engine.return_value = self.mock_engine
36
+ self.driver = driver.NoopComputeDriver()
37
+ mock_create_engine.assert_called_once_with(
38
+ 'sqlite:////tmp/octavia-network-noop.db',
39
+ isolation_level='SERIALIZABLE')
32
40
 
33
41
  self.name = "amphora_name"
34
42
  self.amphora_flavor = "m1.tiny"
@@ -107,7 +115,15 @@ class TestNoopComputeDriver(base.TestCase):
107
115
  self.driver.driver.computeconfig[
108
116
  self.server_group_id])
109
117
 
110
- def test_attach_network_or_port(self):
118
+ @mock.patch('octavia.compute.drivers.noop_driver.driver.update')
119
+ def test_attach_network_or_port(self, mock_update):
120
+ update_mock = mock.MagicMock()
121
+ mock_update.return_value = update_mock
122
+ connect_mock = mock.MagicMock()
123
+ connection_mock = mock.MagicMock()
124
+ self.mock_engine.connect.return_value = connect_mock
125
+ connect_mock.__enter__.return_value = connection_mock
126
+
111
127
  self.driver.attach_network_or_port(self.amphora_id, self.network_id,
112
128
  self.ip_address, self.port_id)
113
129
  self.assertEqual((self.amphora_id, self.network_id, self.ip_address,
@@ -116,6 +132,16 @@ class TestNoopComputeDriver(base.TestCase):
116
132
  self.amphora_id, self.network_id,
117
133
  self.ip_address, self.port_id)])
118
134
 
135
+ self.mock_engine.connect.assert_called_once()
136
+ interfaces_table = self.driver.driver.interfaces_table
137
+ connection_mock.assert_has_calls([
138
+ mock.call.execute(
139
+ update_mock.where(
140
+ interfaces_table.c.port_id == self.port_id).values(
141
+ compute_id=self.amphora_id)),
142
+ mock.call.commit()])
143
+ connect_mock.__enter__.assert_called_once()
144
+
119
145
  def test_detach_port(self):
120
146
  self.driver.detach_port(self.amphora_id, self.port_id)
121
147
  self.assertEqual((self.amphora_id, self.port_id,
@@ -18,6 +18,7 @@ from oslo_config import cfg
18
18
  from oslo_config import fixture as oslo_fixture
19
19
  from oslo_utils import uuidutils
20
20
  from taskflow.patterns import linear_flow as flow
21
+ from taskflow.patterns import unordered_flow
21
22
 
22
23
  from octavia.common import constants
23
24
  from octavia.common import exceptions
@@ -197,8 +198,9 @@ class TestLoadBalancerFlows(base.TestCase):
197
198
 
198
199
  self.assertIn(constants.LOADBALANCER, lb_flow.requires)
199
200
  self.assertIn(constants.UPDATE_DICT, lb_flow.requires)
201
+ self.assertIn(constants.VIP_SG_ID, lb_flow.provides)
200
202
 
201
- self.assertEqual(0, len(lb_flow.provides))
203
+ self.assertEqual(1, len(lb_flow.provides))
202
204
  self.assertEqual(3, len(lb_flow.requires))
203
205
 
204
206
  @mock.patch('octavia.common.rpc.NOTIFIER',
@@ -543,3 +545,27 @@ class TestLoadBalancerFlows(base.TestCase):
543
545
 
544
546
  self._test_get_failover_LB_flow_no_amps_act_stdby([amphora_dict,
545
547
  amphora2_dict])
548
+
549
+ @mock.patch('octavia.db.repositories.AmphoraMemberPortRepository.'
550
+ 'get_port_ids')
551
+ @mock.patch('octavia.db.repositories.AmphoraRepository.'
552
+ 'get_amphorae_ids_on_lb')
553
+ @mock.patch('octavia.db.api.get_session', return_value=mock.MagicMock())
554
+ def test_get_delete_member_ports_subflow(self,
555
+ mock_session,
556
+ mock_amps_on_lb,
557
+ mock_get_port_ids,
558
+ mock_get_net_driver):
559
+ lb_id = uuidutils.generate_uuid()
560
+ amps = ['fake_amp1', 'fake_amp2']
561
+ port1 = uuidutils.generate_uuid()
562
+ port2 = uuidutils.generate_uuid()
563
+ ports = [port1, port2]
564
+
565
+ mock_amps_on_lb.return_value = amps
566
+ mock_get_port_ids.return_value = ports
567
+
568
+ delete_flow = self.LBFlow.get_delete_member_ports_subflow(lb_id)
569
+
570
+ self.assertIsInstance(delete_flow, unordered_flow.Flow)
571
+ self.assertEqual(8, len(delete_flow))
@@ -184,7 +184,9 @@ class TestDatabaseTasks(base.TestCase):
184
184
 
185
185
  @mock.patch('octavia.db.repositories.AmphoraRepository.create',
186
186
  return_value=_db_amphora_mock)
187
+ @mock.patch('octavia.db.repositories.AmphoraHealthRepository.delete')
187
188
  def test_create_amphora_in_db(self,
189
+ mock_amphora_health_repo_delete,
188
190
  mock_create,
189
191
  mock_generate_uuid,
190
192
  mock_LOG,
@@ -210,23 +212,43 @@ class TestDatabaseTasks(base.TestCase):
210
212
 
211
213
  # Test the revert
212
214
  create_amp_in_db.revert(_tf_failure_mock)
213
- self.assertFalse(mock_amphora_repo_delete.called)
215
+ mock_amphora_repo_delete.assert_not_called()
216
+ mock_amphora_health_repo_delete.assert_not_called()
214
217
 
218
+ amp_id = 'AMP'
215
219
  mock_amphora_repo_delete.reset_mock()
216
- create_amp_in_db.revert(result='AMP')
220
+ mock_amphora_health_repo_delete.reset_mock()
221
+ create_amp_in_db.revert(result=amp_id)
217
222
  self.assertTrue(mock_amphora_repo_delete.called)
223
+ self.assertTrue(mock_amphora_health_repo_delete.called)
218
224
  mock_amphora_repo_delete.assert_called_once_with(
219
225
  mock_session,
220
- id='AMP')
226
+ id=amp_id)
227
+ mock_amphora_health_repo_delete.assert_called_once_with(
228
+ mock_session,
229
+ amphora_id=amp_id)
230
+ mock_LOG.error.assert_not_called()
231
+ mock_LOG.debug.assert_not_called()
221
232
 
222
233
  # Test revert with exception
223
234
  mock_amphora_repo_delete.reset_mock()
224
- mock_amphora_repo_delete.side_effect = Exception('fail')
225
- create_amp_in_db.revert(result='AMP')
235
+ mock_amphora_health_repo_delete.reset_mock()
236
+ err1_msg, err2_msg = ('fail', 'fail2')
237
+ mock_amphora_repo_delete.side_effect = Exception(err1_msg)
238
+ mock_amphora_health_repo_delete.side_effect = Exception(err2_msg)
239
+ create_amp_in_db.revert(result=amp_id)
226
240
  self.assertTrue(mock_amphora_repo_delete.called)
241
+ self.assertTrue(mock_amphora_health_repo_delete.called)
227
242
  mock_amphora_repo_delete.assert_called_once_with(
228
243
  mock_session,
229
- id='AMP')
244
+ id=amp_id)
245
+ mock_amphora_health_repo_delete.assert_called_once_with(
246
+ mock_session,
247
+ amphora_id=amp_id)
248
+ mock_LOG.error.assert_called_once_with(
249
+ "Failed to delete amphora %(amp)s "
250
+ "in the database due to: "
251
+ "%(except)s", {'amp': amp_id, 'except': err1_msg})
230
252
 
231
253
  @mock.patch('octavia.db.repositories.ListenerRepository.delete')
232
254
  def test_delete_listener_in_db(self,
@@ -334,6 +334,7 @@ class TestNetworkTasks(base.TestCase):
334
334
  mock_driver.reset_mock()
335
335
  member_mock = mock.MagicMock()
336
336
  member_mock.subnet_id = member_private_subnet.id
337
+ member_mock.vnic_type = constants.VNIC_TYPE_NORMAL
337
338
  member2_mock = mock.MagicMock()
338
339
  member2_mock.subnet_id = member_private_subnet2.id
339
340
  pool_mock.members = [member_mock]
@@ -351,7 +352,8 @@ class TestNetworkTasks(base.TestCase):
351
352
  network_id=3,
352
353
  fixed_ips=[
353
354
  data_models.FixedIP(
354
- subnet_id=member_private_subnet.id)])],
355
+ subnet_id=member_private_subnet.id)],
356
+ vnic_type=constants.VNIC_TYPE_NORMAL)],
355
357
  delete_nics=[],
356
358
  add_subnets=[{
357
359
  'subnet_id': member_private_subnet.id,
@@ -431,6 +433,7 @@ class TestNetworkTasks(base.TestCase):
431
433
  mock_driver.reset_mock()
432
434
  member_mock = mock.MagicMock()
433
435
  member_mock.subnet_id = member_private_subnet.id
436
+ member_mock.vnic_type = constants.VNIC_TYPE_NORMAL
434
437
  pool_mock.members = [member_mock]
435
438
  az = {
436
439
  constants.COMPUTE_ZONE: 'foo'
@@ -451,7 +454,8 @@ class TestNetworkTasks(base.TestCase):
451
454
  add_nics=[data_models.Interface(
452
455
  network_id=member_private_net.id,
453
456
  fixed_ips=[data_models.FixedIP(
454
- subnet_id=member_private_subnet.id)])],
457
+ subnet_id=member_private_subnet.id)],
458
+ vnic_type=constants.VNIC_TYPE_NORMAL)],
455
459
  delete_nics=[data_models.Interface(network_id='bad_net')],
456
460
  add_subnets=[{
457
461
  'subnet_id': member_private_subnet.id,
@@ -611,63 +615,6 @@ class TestNetworkTasks(base.TestCase):
611
615
  mock_driver.get_plugged_networks.assert_called_once_with(
612
616
  COMPUTE_ID)
613
617
 
614
- def test_plug_networks(self, mock_get_net_driver):
615
- mock_driver = mock.MagicMock()
616
- mock_get_net_driver.return_value = mock_driver
617
-
618
- def _interface(network_id):
619
- return [data_models.Interface(network_id=network_id)]
620
-
621
- net = network_tasks.PlugNetworks()
622
-
623
- net.execute(self.amphora_mock, None)
624
- self.assertFalse(mock_driver.plug_network.called)
625
-
626
- delta = data_models.Delta(amphora_id=self.db_amphora_mock.id,
627
- compute_id=self.db_amphora_mock.compute_id,
628
- add_nics=[],
629
- delete_nics=[]).to_dict(recurse=True)
630
- net.execute(self.amphora_mock, delta)
631
- self.assertFalse(mock_driver.plug_network.called)
632
-
633
- delta = data_models.Delta(amphora_id=self.db_amphora_mock.id,
634
- compute_id=self.db_amphora_mock.compute_id,
635
- add_nics=_interface(1),
636
- delete_nics=[]).to_dict(recurse=True)
637
- net.execute(self.amphora_mock, delta)
638
- mock_driver.plug_network.assert_called_once_with(COMPUTE_ID, 1)
639
-
640
- # revert
641
- net.revert(self.amphora_mock, None)
642
- self.assertFalse(mock_driver.unplug_network.called)
643
-
644
- delta = data_models.Delta(amphora_id=self.db_amphora_mock.id,
645
- compute_id=self.db_amphora_mock.compute_id,
646
- add_nics=[],
647
- delete_nics=[]).to_dict(recurse=True)
648
- net.revert(self.amphora_mock, delta)
649
- self.assertFalse(mock_driver.unplug_network.called)
650
-
651
- delta = data_models.Delta(amphora_id=self.db_amphora_mock.id,
652
- compute_id=self.db_amphora_mock.compute_id,
653
- add_nics=_interface(1),
654
- delete_nics=[]).to_dict(recurse=True)
655
- net.revert(self.amphora_mock, delta)
656
- mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
657
-
658
- mock_driver.reset_mock()
659
- mock_driver.unplug_network.side_effect = net_base.NetworkNotFound
660
- net.revert(self.amphora_mock, delta) # No exception
661
- mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
662
-
663
- mock_driver.reset_mock()
664
- mock_driver.unplug_network.side_effect = TestException('test')
665
- self.assertRaises(TestException,
666
- net.revert,
667
- self.amphora_mock,
668
- delta)
669
- mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
670
-
671
618
  def test_unplug_networks(self, mock_get_net_driver):
672
619
  mock_driver = mock.MagicMock()
673
620
  mock_get_net_driver.return_value = mock_driver
@@ -755,6 +702,7 @@ class TestNetworkTasks(base.TestCase):
755
702
  nic1.fixed_ips = [data_models.FixedIP(
756
703
  subnet_id=uuidutils.generate_uuid())]
757
704
  nic1.network_id = uuidutils.generate_uuid()
705
+ nic1.nic_type = constants.VNIC_TYPE_NORMAL
758
706
  nic2 = data_models.Interface()
759
707
  nic2.fixed_ips = [data_models.FixedIP(
760
708
  subnet_id=uuidutils.generate_uuid())]
@@ -779,8 +727,18 @@ class TestNetworkTasks(base.TestCase):
779
727
  delete_subnets=[]
780
728
  ).to_dict(recurse=True)
781
729
 
782
- mock_net_driver.plug_network.return_value = interface1
783
- mock_net_driver.get_port.return_value = port1
730
+ mock_net_driver.plug_port.side_effect = [
731
+ interface1,
732
+ exceptions.NotFound(resource='Instance', id='1'),
733
+ exceptions.NotFound(resource='Boom', id='1'),
734
+ Exception("boom")]
735
+ mock_net_driver.create_port.side_effect = [
736
+ port1,
737
+ port1,
738
+ exceptions.NotFound(resource='Network', id='1'),
739
+ port1,
740
+ port1]
741
+
784
742
  fixed_port1 = mock.MagicMock()
785
743
  fixed_port1.network_id = port1.network_id
786
744
  fixed_port1.fixed_ips = [fixed_ip]
@@ -795,20 +753,34 @@ class TestNetworkTasks(base.TestCase):
795
753
  result = handle_net_delta_obj.execute(self.amphora_mock,
796
754
  delta)
797
755
 
798
- mock_net_driver.plug_network.assert_called_once_with(
799
- self.db_amphora_mock.compute_id, nic1.network_id)
800
- mock_net_driver.unplug_fixed_ip.assert_called_once_with(
801
- port_id=interface1.port_id, subnet_id=fixed_ip2.subnet_id)
802
- mock_net_driver.get_port.assert_called_once_with(interface1.port_id)
756
+ mock_net_driver.plug_port.assert_called_once_with(
757
+ self.db_amphora_mock, port1)
803
758
  mock_net_driver.get_network.assert_called_once_with(port1.network_id)
804
- mock_net_driver.get_subnet.assert_called_once_with(fixed_ip.subnet_id)
759
+ mock_net_driver.get_subnet.assert_has_calls(
760
+ [mock.call(fixed_ip.subnet_id), mock.call(fixed_ip2.subnet_id)])
805
761
 
806
- self.assertEqual({self.db_amphora_mock.id: [fixed_port1.to_dict()]},
762
+ self.assertEqual({self.db_amphora_mock.id: [port1.to_dict()]},
807
763
  result)
808
764
 
809
765
  mock_net_driver.unplug_network.assert_called_with(
810
766
  self.db_amphora_mock.compute_id, nic2.network_id)
811
767
 
768
+ self.assertRaises(net_base.AmphoraNotFound,
769
+ handle_net_delta_obj.execute, self.amphora_mock,
770
+ delta)
771
+
772
+ self.assertRaises(net_base.NetworkNotFound,
773
+ handle_net_delta_obj.execute, self.amphora_mock,
774
+ delta)
775
+
776
+ self.assertRaises(net_base.PlugNetworkException,
777
+ handle_net_delta_obj.execute, self.amphora_mock,
778
+ delta)
779
+
780
+ self.assertRaises(net_base.PlugNetworkException,
781
+ handle_net_delta_obj.execute, self.amphora_mock,
782
+ delta)
783
+
812
784
  # Revert
813
785
  delta2 = data_models.Delta(amphora_id=self.db_amphora_mock.id,
814
786
  compute_id=self.db_amphora_mock.compute_id,
@@ -857,12 +829,13 @@ class TestNetworkTasks(base.TestCase):
857
829
  port_id=port_id,
858
830
  fixed_ips=[
859
831
  data_models.FixedIP(
860
- subnet_id=subnet_id)])
832
+ subnet_id=subnet_id)],
833
+ vnic_type=constants.VNIC_TYPE_NORMAL)
861
834
 
862
835
  net = network_tasks.HandleNetworkDeltas()
863
836
 
864
837
  net.execute({}, self.load_balancer_mock)
865
- self.assertFalse(mock_driver.plug_network.called)
838
+ self.assertFalse(mock_driver.create_port.called)
866
839
 
867
840
  delta = data_models.Delta(amphora_id=self.db_amphora_mock.id,
868
841
  compute_id=self.db_amphora_mock.compute_id,
@@ -871,7 +844,7 @@ class TestNetworkTasks(base.TestCase):
871
844
  add_subnets=[],
872
845
  delete_subnets=[]).to_dict(recurse=True)
873
846
  net.execute({self.db_amphora_mock.id: delta}, self.load_balancer_mock)
874
- self.assertFalse(mock_driver.plug_network.called)
847
+ self.assertFalse(mock_driver.create_port.called)
875
848
 
876
849
  # Adding a subnet on a new network
877
850
  port = data_models.Port(
@@ -879,7 +852,7 @@ class TestNetworkTasks(base.TestCase):
879
852
  network_id=network1,
880
853
  fixed_ips=[
881
854
  data_models.FixedIP(subnet_id=subnet1)])
882
- mock_driver.get_port.return_value = port
855
+ mock_driver.create_port.return_value = port
883
856
  mock_driver.plug_fixed_ip.return_value = port
884
857
  mock_driver.get_network.return_value = data_models.Network(
885
858
  id=network1)
@@ -900,8 +873,8 @@ class TestNetworkTasks(base.TestCase):
900
873
  delete_subnets=[]).to_dict(recurse=True)
901
874
  updated_ports = net.execute({self.db_amphora_mock.id: delta},
902
875
  self.load_balancer_mock)
903
- mock_driver.plug_network.assert_called_once_with(
904
- self.db_amphora_mock.compute_id, network1)
876
+ mock_driver.plug_port.assert_called_once_with(
877
+ self.db_amphora_mock, port)
905
878
  mock_driver.unplug_network.assert_not_called()
906
879
 
907
880
  self.assertEqual(1, len(updated_ports))
@@ -949,7 +922,6 @@ class TestNetworkTasks(base.TestCase):
949
922
  delete_subnets=[]).to_dict(recurse=True)
950
923
  updated_ports = net.execute({self.db_amphora_mock.id: delta},
951
924
  self.load_balancer_mock)
952
- mock_driver.plug_network.assert_not_called()
953
925
  mock_driver.unplug_network.assert_not_called()
954
926
  mock_driver.get_port.assert_not_called()
955
927
  mock_driver.plug_fixed_ip.assert_called_once_with(port_id=port1,
@@ -989,7 +961,6 @@ class TestNetworkTasks(base.TestCase):
989
961
  updated_ports = net.execute({self.db_amphora_mock.id: delta},
990
962
  self.load_balancer_mock)
991
963
  mock_driver.delete_port.assert_not_called()
992
- mock_driver.plug_network.assert_not_called()
993
964
  mock_driver.plug_fixed_ip.assert_not_called()
994
965
  mock_driver.unplug_fixed_ip.assert_called_once_with(
995
966
  port_id=port1, subnet_id=subnet1)
@@ -1014,7 +985,6 @@ class TestNetworkTasks(base.TestCase):
1014
985
  net.execute({self.db_amphora_mock.id: delta},
1015
986
  self.load_balancer_mock)
1016
987
  mock_driver.delete_port.assert_not_called()
1017
- mock_driver.plug_network.assert_not_called()
1018
988
  mock_driver.plug_fixed_ip.assert_not_called()
1019
989
  mock_driver.unplug_fixed_ip.assert_not_called()
1020
990
 
@@ -1043,7 +1013,6 @@ class TestNetworkTasks(base.TestCase):
1043
1013
  updated_ports = net.execute({self.db_amphora_mock.id: delta},
1044
1014
  self.load_balancer_mock)
1045
1015
  mock_driver.delete_port.assert_called_once_with(port1)
1046
- mock_driver.plug_network.assert_not_called()
1047
1016
  mock_driver.plug_fixed_ip.assert_not_called()
1048
1017
  self.assertEqual(1, len(updated_ports))
1049
1018
  self.assertEqual(0, len(updated_ports[self.db_amphora_mock.id]))
@@ -1526,6 +1495,57 @@ class TestNetworkTasks(base.TestCase):
1526
1495
  mock_driver.unplug_aap_port.assert_called_once_with(
1527
1496
  LB.vip, self.db_amphora_mock, mockSubnet)
1528
1497
 
1498
+ @mock.patch('octavia.db.repositories.AmphoraRepository.get')
1499
+ @mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
1500
+ @mock.patch('octavia.db.api.get_session', return_value=_session_mock)
1501
+ def test_revert_plug_vip_amphora_subnet_not_found(
1502
+ self, mock_session, mock_lb_get, mock_get, mock_get_net_driver):
1503
+ mock_driver = mock.MagicMock()
1504
+ mock_lb_get.return_value = LB
1505
+ mock_get.return_value = self.db_amphora_mock
1506
+ mock_get_net_driver.return_value = mock_driver
1507
+ net = network_tasks.PlugVIPAmphora()
1508
+ amphora = {constants.ID: AMPHORA_ID,
1509
+ constants.LB_NETWORK_IP: IP_ADDRESS}
1510
+ subnet = {constants.ID: SUBNET_ID}
1511
+ err_msg = 'Subnet not found'
1512
+ mock_driver.get_subnet.side_effect = net_base.SubnetNotFound(err_msg)
1513
+ result = AMPS_DATA[0].to_dict()
1514
+ net.revert(result, self.load_balancer_mock, amphora, subnet)
1515
+ mock_driver.unplug_aap_port.assert_not_called()
1516
+ network_tasks.LOG.error.assert_called_once_with(
1517
+ 'Failed to unplug AAP port for load balancer: %s. '
1518
+ 'Resources may still be in use for VRRP port: %s. '
1519
+ 'Due to error: %s',
1520
+ self.load_balancer_mock[constants.LOADBALANCER_ID],
1521
+ result[constants.VRRP_PORT_ID], err_msg
1522
+ )
1523
+
1524
+ @mock.patch('octavia.db.repositories.AmphoraRepository.get')
1525
+ @mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
1526
+ @mock.patch('octavia.db.api.get_session', return_value=_session_mock)
1527
+ def test_revert_plug_vip_amphora_raise_db_error(
1528
+ self, mock_session, mock_lb_get, mock_get, mock_get_net_driver):
1529
+ mock_driver = mock.MagicMock()
1530
+ mock_lb_get.return_value = LB
1531
+ err_msg = 'Some Error'
1532
+ mock_get.side_effect = Exception(err_msg)
1533
+ net = network_tasks.PlugVIPAmphora()
1534
+ amphora = {constants.ID: AMPHORA_ID,
1535
+ constants.LB_NETWORK_IP: IP_ADDRESS}
1536
+ subnet = {constants.ID: SUBNET_ID}
1537
+ result = AMPS_DATA[0].to_dict()
1538
+ net.revert(result, self.load_balancer_mock, amphora, subnet)
1539
+ mock_driver.unplug_aap_port.assert_not_called()
1540
+ mock_lb_get.assert_not_called()
1541
+ network_tasks.LOG.error.assert_called_once_with(
1542
+ 'Failed to unplug AAP port for load balancer: %s. '
1543
+ 'Resources may still be in use for VRRP port: %s. '
1544
+ 'Due to error: %s',
1545
+ self.load_balancer_mock[constants.LOADBALANCER_ID],
1546
+ result[constants.VRRP_PORT_ID], err_msg
1547
+ )
1548
+
1529
1549
  @mock.patch('octavia.controller.worker.v2.tasks.network_tasks.DeletePort.'
1530
1550
  'update_progress')
1531
1551
  def test_delete_port(self, mock_update_progress, mock_get_net_driver):
@@ -1626,7 +1646,8 @@ class TestNetworkTasks(base.TestCase):
1626
1646
  vip_dict = {constants.IP_ADDRESS: VIP_IP_ADDRESS,
1627
1647
  constants.NETWORK_ID: VIP_NETWORK_ID,
1628
1648
  constants.QOS_POLICY_ID: VIP_QOS_ID,
1629
- constants.SUBNET_ID: VIP_SUBNET_ID}
1649
+ constants.SUBNET_ID: VIP_SUBNET_ID,
1650
+ constants.SG_IDS: []}
1630
1651
  port_mock = mock.MagicMock()
1631
1652
  port_mock.id = PORT_ID
1632
1653
  additional_vips = [{constants.IP_ADDRESS: VIP_IP_ADDRESS2}]
@@ -33,6 +33,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
33
33
  'board': 'redis',
34
34
  'host': '127.0.0.1',
35
35
  'port': 6379,
36
+ 'db': 0,
36
37
  'namespace': 'octavia_jobboard',
37
38
  'sentinel': None,
38
39
  'sentinel_fallbacks': [],
@@ -65,6 +66,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
65
66
  'board': 'redis',
66
67
  'host': '127.0.0.1',
67
68
  'port': 6379,
69
+ 'db': 0,
68
70
  'namespace': 'octavia_jobboard',
69
71
  'password': 'redispass',
70
72
  'sentinel': None,
@@ -100,6 +102,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
100
102
  'board': 'redis',
101
103
  'host': '127.0.0.1',
102
104
  'port': 6379,
105
+ 'db': 0,
103
106
  'namespace': 'octavia_jobboard',
104
107
  'username': 'redisuser',
105
108
  'password': 'redispass',
@@ -142,6 +145,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
142
145
  'board': 'redis',
143
146
  'host': '127.0.0.1',
144
147
  'port': 6379,
148
+ 'db': 0,
145
149
  'namespace': 'octavia_jobboard',
146
150
  'sentinel': None,
147
151
  'sentinel_fallbacks': [],
@@ -179,6 +183,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
179
183
  'board': 'redis',
180
184
  'host': 'host1',
181
185
  'port': 26379,
186
+ 'db': 0,
182
187
  'namespace': 'octavia_jobboard',
183
188
  'sentinel': 'mymaster',
184
189
  'sentinel_fallbacks': ['host2:26379', 'host3:26379'],
@@ -220,6 +225,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
220
225
  'board': 'redis',
221
226
  'host': 'host1',
222
227
  'port': 26379,
228
+ 'db': 0,
223
229
  'namespace': 'octavia_jobboard',
224
230
  'password': 'redispass',
225
231
  'sentinel': 'mymaster',
@@ -267,6 +273,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
267
273
  'board': 'redis',
268
274
  'host': 'host1',
269
275
  'port': 26379,
276
+ 'db': 0,
270
277
  'namespace': 'octavia_jobboard',
271
278
  'username': 'redisuser',
272
279
  'password': 'redispass',
@@ -328,6 +335,7 @@ class TestRedisTaskFlowDriver(base.TestCase):
328
335
  'board': 'redis',
329
336
  'host': 'host1',
330
337
  'port': 26379,
338
+ 'db': 0,
331
339
  'namespace': 'octavia_jobboard',
332
340
  'sentinel': 'mymaster',
333
341
  'sentinel_fallbacks': ['host2:26379', 'host3:26379'],