def get_update_l7policy_flow(self): """Create a flow to update an L7 policy :returns: The flow for updating an L7 policy """ update_l7policy_flow = linear_flow.Flow(constants.UPDATE_L7POLICY_FLOW) update_l7policy_flow.add( lifecycle_tasks.L7PolicyToErrorOnRevertTask(requires=[ constants.L7POLICY, constants.LISTENERS, constants.LOADBALANCER ])) update_l7policy_flow.add( database_tasks.MarkL7PolicyPendingUpdateInDB( requires=constants.L7POLICY)) update_l7policy_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) update_l7policy_flow.add( database_tasks.UpdateL7PolicyInDB( requires=[constants.L7POLICY, constants.UPDATE_DICT])) update_l7policy_flow.add( database_tasks.MarkL7PolicyActiveInDB(requires=constants.L7POLICY)) update_l7policy_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return update_l7policy_flow
def get_delete_pool_flow(self): """Create a flow to delete a pool :returns: The flow for deleting a pool """ delete_pool_flow = linear_flow.Flow(constants.DELETE_POOL_FLOW) delete_pool_flow.add(lifecycle_tasks.PoolToErrorOnRevertTask( requires=[constants.POOL, constants.LISTENERS, constants.LOADBALANCER])) delete_pool_flow.add(database_tasks.MarkPoolPendingDeleteInDB( requires=constants.POOL)) delete_pool_flow.add(database_tasks.CountPoolChildrenForQuota( requires=constants.POOL, provides=constants.POOL_CHILD_COUNT)) delete_pool_flow.add(model_tasks.DeleteModelObject( rebind={constants.OBJECT: constants.POOL})) delete_pool_flow.add(amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) delete_pool_flow.add(database_tasks.DeletePoolInDB( requires=constants.POOL)) delete_pool_flow.add(database_tasks.DecrementPoolQuota( requires=[constants.POOL, constants.POOL_CHILD_COUNT])) delete_pool_flow.add(database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return delete_pool_flow
def get_delete_l7policy_flow(self): """Create a flow to delete an L7 policy :returns: The flow for deleting an L7 policy """ delete_l7policy_flow = linear_flow.Flow(constants.DELETE_L7POLICY_FLOW) delete_l7policy_flow.add( lifecycle_tasks.L7PolicyToErrorOnRevertTask(requires=[ constants.L7POLICY, constants.LISTENERS, constants.LOADBALANCER ])) delete_l7policy_flow.add( database_tasks.MarkL7PolicyPendingDeleteInDB( requires=constants.L7POLICY)) delete_l7policy_flow.add( model_tasks.DeleteModelObject( rebind={constants.OBJECT: constants.L7POLICY})) delete_l7policy_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) delete_l7policy_flow.add( database_tasks.DeleteL7PolicyInDB(requires=constants.L7POLICY)) delete_l7policy_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return delete_l7policy_flow
def get_create_l7rule_flow(self): """Create a flow to create an L7 rule :returns: The flow for creating an L7 rule """ create_l7rule_flow = linear_flow.Flow(constants.CREATE_L7RULE_FLOW) create_l7rule_flow.add( lifecycle_tasks.L7RuleToErrorOnRevertTask(requires=[ constants.L7RULE, constants.LISTENERS, constants.LOADBALANCER ])) create_l7rule_flow.add( database_tasks.MarkL7RulePendingCreateInDB( requires=constants.L7RULE)) create_l7rule_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) create_l7rule_flow.add( database_tasks.MarkL7RuleActiveInDB(requires=constants.L7RULE)) create_l7rule_flow.add( database_tasks.MarkL7PolicyActiveInDB(requires=constants.L7POLICY)) create_l7rule_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return create_l7rule_flow
def test_listener_update(self, mock_driver, mock_generate_uuid, mock_log, mock_get_session, mock_listener_repo_get, mock_listener_repo_update, mock_amphora_repo_update): listener_update_obj = amphora_driver_tasks.ListenersUpdate() listener_update_obj.execute(_load_balancer_mock) mock_driver.update.assert_called_once_with(_load_balancer_mock) # Test the revert amp = listener_update_obj.revert(_load_balancer_mock) repo.ListenerRepository.update.assert_called_once_with( _session_mock, id=LISTENER_ID, provisioning_status=constants.ERROR) self.assertIsNone(amp) # Test the revert with exception repo.ListenerRepository.update.reset_mock() mock_listener_repo_update.side_effect = Exception('fail') amp = listener_update_obj.revert(_load_balancer_mock) repo.ListenerRepository.update.assert_called_once_with( _session_mock, id=LISTENER_ID, provisioning_status=constants.ERROR) self.assertIsNone(amp)
def test_listeners_update(self, mock_driver, mock_generate_uuid, mock_log, mock_get_session, mock_listener_repo_get, mock_listener_repo_update, mock_amphora_repo_update): listeners_update_obj = amphora_driver_tasks.ListenersUpdate() listeners = [data_models.Listener(id='listener1'), data_models.Listener(id='listener2')] vip = data_models.Vip(ip_address='10.0.0.1') lb = data_models.LoadBalancer(id='lb1', listeners=listeners, vip=vip) listeners_update_obj.execute(lb) mock_driver.update.assert_called_once_with(lb) self.assertEqual(1, mock_driver.update.call_count) # Test the revert amp = listeners_update_obj.revert(lb) expected_db_calls = [mock.call(_session_mock, id=listeners[0].id, provisioning_status=constants.ERROR), mock.call(_session_mock, id=listeners[1].id, provisioning_status=constants.ERROR)] repo.ListenerRepository.update.has_calls(expected_db_calls) self.assertEqual(2, repo.ListenerRepository.update.call_count) self.assertIsNone(amp)
def get_update_health_monitor_flow(self): """Create a flow to update a health monitor :returns: The flow for updating a health monitor """ update_hm_flow = linear_flow.Flow(constants.UPDATE_HEALTH_MONITOR_FLOW) update_hm_flow.add( lifecycle_tasks.HealthMonitorToErrorOnRevertTask(requires=[ constants.HEALTH_MON, constants.LISTENERS, constants.LOADBALANCER ])) update_hm_flow.add( database_tasks.MarkHealthMonitorPendingUpdateInDB( requires=constants.HEALTH_MON)) update_hm_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) update_hm_flow.add( database_tasks.UpdateHealthMonInDB( requires=[constants.HEALTH_MON, constants.UPDATE_DICT])) update_hm_flow.add( database_tasks.MarkHealthMonitorActiveInDB( requires=constants.HEALTH_MON)) update_hm_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) update_hm_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return update_hm_flow
def get_delete_member_flow(self): """Create a flow to delete a member :returns: The flow for deleting a member """ delete_member_flow = linear_flow.Flow(constants.DELETE_MEMBER_FLOW) delete_member_flow.add( lifecycle_tasks.MemberToErrorOnRevertTask(requires=[ constants.MEMBER, constants.LISTENERS, constants.LOADBALANCER, constants.POOL ])) delete_member_flow.add( database_tasks.MarkMemberPendingDeleteInDB( requires=constants.MEMBER)) delete_member_flow.add( model_tasks.DeleteModelObject( rebind={constants.OBJECT: constants.MEMBER})) delete_member_flow.add( database_tasks.DeleteMemberInDB(requires=constants.MEMBER)) delete_member_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) delete_member_flow.add( database_tasks.DecrementMemberQuota(requires=constants.MEMBER)) delete_member_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) delete_member_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return delete_member_flow
def get_update_member_flow(self): """Create a flow to update a member :returns: The flow for updating a member """ update_member_flow = linear_flow.Flow(constants.UPDATE_MEMBER_FLOW) update_member_flow.add( lifecycle_tasks.MemberToErrorOnRevertTask(requires=[ constants.MEMBER, constants.LISTENERS, constants.LOADBALANCER, constants.POOL ])) update_member_flow.add( database_tasks.MarkMemberPendingUpdateInDB( requires=constants.MEMBER)) update_member_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) update_member_flow.add( database_tasks.UpdateMemberInDB( requires=[constants.MEMBER, constants.UPDATE_DICT])) update_member_flow.add( database_tasks.MarkMemberActiveInDB(requires=constants.MEMBER)) update_member_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) update_member_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return update_member_flow
def get_create_member_flow(self): """Create a flow to create a member :returns: The flow for creating a member """ create_member_flow = linear_flow.Flow(constants.CREATE_MEMBER_FLOW) create_member_flow.add( lifecycle_tasks.MemberToErrorOnRevertTask(requires=[ constants.MEMBER, constants.LISTENERS, constants.LOADBALANCER, constants.POOL ])) create_member_flow.add( database_tasks.MarkMemberPendingCreateInDB( requires=constants.MEMBER)) create_member_flow.add( network_tasks.CalculateDelta(requires=constants.LOADBALANCER, provides=constants.DELTAS)) create_member_flow.add( network_tasks.HandleNetworkDeltas(requires=constants.DELTAS, provides=constants.ADDED_PORTS)) create_member_flow.add( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) create_member_flow.add( amphora_driver_tasks.ListenersUpdate( requires=(constants.LOADBALANCER, constants.LISTENERS))) create_member_flow.add( database_tasks.MarkMemberActiveInDB(requires=constants.MEMBER)) create_member_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) create_member_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=(constants.LOADBALANCER, constants.LISTENERS))) return create_member_flow
def get_create_listener_flow(self): """Create a flow to create a listener :returns: The flow for creating a listener """ create_listener_flow = linear_flow.Flow(constants.CREATE_LISTENER_FLOW) create_listener_flow.add(lifecycle_tasks.ListenersToErrorOnRevertTask( requires=[constants.LOADBALANCER, constants.LISTENERS])) create_listener_flow.add(amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) create_listener_flow.add(network_tasks.UpdateVIP( requires=constants.LOADBALANCER)) create_listener_flow.add(database_tasks. MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return create_listener_flow
def get_update_load_balancer_flow(self): """Creates a flow to update a load balancer. :returns: The flow for update a load balancer """ update_LB_flow = linear_flow.Flow(constants.UPDATE_LOADBALANCER_FLOW) update_LB_flow.add(lifecycle_tasks.LoadBalancerToErrorOnRevertTask( requires=constants.LOADBALANCER)) update_LB_flow.add(network_tasks.ApplyQos( requires=(constants.LOADBALANCER, constants.UPDATE_DICT))) update_LB_flow.add(amphora_driver_tasks.ListenersUpdate( requires=constants.LOADBALANCER)) update_LB_flow.add(database_tasks.UpdateLoadbalancerInDB( requires=[constants.LOADBALANCER, constants.UPDATE_DICT])) update_LB_flow.add(database_tasks.MarkLBActiveInDB( requires=constants.LOADBALANCER)) return update_LB_flow
def get_update_listener_flow(self): """Create a flow to update a listener :returns: The flow for updating a listener """ update_listener_flow = linear_flow.Flow(constants.UPDATE_LISTENER_FLOW) update_listener_flow.add(lifecycle_tasks.ListenersToErrorOnRevertTask( requires=[constants.LOADBALANCER, constants.LISTENERS])) update_listener_flow.add(amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) update_listener_flow.add(database_tasks.UpdateListenerInDB( requires=[constants.LISTENER, constants.UPDATE_DICT])) update_listener_flow.add(database_tasks. MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return update_listener_flow
def get_create_all_listeners_flow(self): """Create a flow to create all listeners :returns: The flow for creating all listeners """ create_all_listeners_flow = linear_flow.Flow( constants.CREATE_LISTENERS_FLOW) create_all_listeners_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) create_all_listeners_flow.add(database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) create_all_listeners_flow.add(amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) create_all_listeners_flow.add(network_tasks.UpdateVIP( requires=constants.LOADBALANCER)) return create_all_listeners_flow
def get_create_pool_flow(self): """Create a flow to create a pool :returns: The flow for creating a pool """ create_pool_flow = linear_flow.Flow(constants.CREATE_POOL_FLOW) create_pool_flow.add(lifecycle_tasks.PoolToErrorOnRevertTask( requires=[constants.POOL, constants.LISTENERS, constants.LOADBALANCER])) create_pool_flow.add(database_tasks.MarkPoolPendingCreateInDB( requires=constants.POOL)) create_pool_flow.add(amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) create_pool_flow.add(database_tasks.MarkPoolActiveInDB( requires=constants.POOL)) create_pool_flow.add(database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return create_pool_flow
def get_delete_health_monitor_flow(self): """Create a flow to delete a health monitor :returns: The flow for deleting a health monitor """ delete_hm_flow = linear_flow.Flow(constants.DELETE_HEALTH_MONITOR_FLOW) delete_hm_flow.add( lifecycle_tasks.HealthMonitorToErrorOnRevertTask(requires=[ constants.HEALTH_MON, constants.LISTENERS, constants.LOADBALANCER ])) delete_hm_flow.add( database_tasks.MarkHealthMonitorPendingDeleteInDB( requires=constants.HEALTH_MON)) delete_hm_flow.add( model_tasks.DeleteModelObject( rebind={constants.OBJECT: constants.HEALTH_MON})) delete_hm_flow.add( amphora_driver_tasks.ListenersUpdate( requires=[constants.LOADBALANCER, constants.LISTENERS])) delete_hm_flow.add( database_tasks.DeleteHealthMonitorInDB( requires=constants.HEALTH_MON)) delete_hm_flow.add( database_tasks.DecrementHealthMonitorQuota( requires=constants.HEALTH_MON)) delete_hm_flow.add( database_tasks.UpdatePoolMembersOperatingStatusInDB( requires=constants.POOL, inject={constants.OPERATING_STATUS: constants.NO_MONITOR})) delete_hm_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) delete_hm_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=[constants.LOADBALANCER, constants.LISTENERS])) return delete_hm_flow
def get_batch_update_members_flow(self, old_members, new_members, updated_members): """Create a flow to batch update members :returns: The flow for batch updating members """ batch_update_members_flow = linear_flow.Flow( constants.BATCH_UPDATE_MEMBERS_FLOW) unordered_members_flow = unordered_flow.Flow( constants.UNORDERED_MEMBER_UPDATES_FLOW) unordered_members_active_flow = unordered_flow.Flow( constants.UNORDERED_MEMBER_ACTIVE_FLOW) # Delete old members unordered_members_flow.add( lifecycle_tasks.MembersToErrorOnRevertTask( inject={constants.MEMBERS: old_members}, name='{flow}-deleted'.format( flow=constants.MEMBER_TO_ERROR_ON_REVERT_FLOW))) for m in old_members: unordered_members_flow.add( model_tasks.DeleteModelObject( inject={constants.OBJECT: m}, name='{flow}-{id}'.format( id=m.id, flow=constants.DELETE_MODEL_OBJECT_FLOW))) unordered_members_flow.add( database_tasks.DeleteMemberInDB( inject={constants.MEMBER: m}, name='{flow}-{id}'.format( id=m.id, flow=constants.DELETE_MEMBER_INDB))) unordered_members_flow.add( database_tasks.DecrementMemberQuota( inject={constants.MEMBER: m}, name='{flow}-{id}'.format( id=m.id, flow=constants.DECREMENT_MEMBER_QUOTA_FLOW))) # Create new members unordered_members_flow.add( lifecycle_tasks.MembersToErrorOnRevertTask( inject={constants.MEMBERS: new_members}, name='{flow}-created'.format( flow=constants.MEMBER_TO_ERROR_ON_REVERT_FLOW))) for m in new_members: unordered_members_active_flow.add( database_tasks.MarkMemberActiveInDB( inject={constants.MEMBER: m}, name='{flow}-{id}'.format( id=m.id, flow=constants.MARK_MEMBER_ACTIVE_INDB))) # Update existing members unordered_members_flow.add( lifecycle_tasks.MembersToErrorOnRevertTask( # updated_members is a list of (obj, dict), only pass `obj` inject={constants.MEMBERS: [m[0] for m in updated_members]}, name='{flow}-updated'.format( flow=constants.MEMBER_TO_ERROR_ON_REVERT_FLOW))) for m, um in updated_members: um.pop('id', None) unordered_members_active_flow.add( database_tasks.MarkMemberActiveInDB( inject={constants.MEMBER: m}, name='{flow}-{id}'.format( id=m.id, flow=constants.MARK_MEMBER_ACTIVE_INDB))) batch_update_members_flow.add(unordered_members_flow) # Done, do real updates batch_update_members_flow.add( network_tasks.CalculateDelta(requires=constants.LOADBALANCER, provides=constants.DELTAS)) batch_update_members_flow.add( network_tasks.HandleNetworkDeltas(requires=constants.DELTAS, provides=constants.ADDED_PORTS)) batch_update_members_flow.add( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) # Update the Listener (this makes the changes active on the Amp) batch_update_members_flow.add( amphora_driver_tasks.ListenersUpdate( requires=(constants.LOADBALANCER, constants.LISTENERS))) # Mark all the members ACTIVE here, then pool then LB/Listeners batch_update_members_flow.add(unordered_members_active_flow) batch_update_members_flow.add( database_tasks.MarkPoolActiveInDB(requires=constants.POOL)) batch_update_members_flow.add( database_tasks.MarkLBAndListenersActiveInDB( requires=(constants.LOADBALANCER, constants.LISTENERS))) return batch_update_members_flow