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)) 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 _create_listeners_flow(self): flows = [] flows.append( database_tasks.ReloadLoadBalancer( name=constants.RELOAD_LB_AFTER_AMP_ASSOC_FULL_GRAPH, requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER ) ) flows.append( network_tasks.CalculateDelta( requires=constants.LOADBALANCER, provides=constants.DELTAS ) ) flows.append( network_tasks.HandleNetworkDeltas( requires=constants.DELTAS, provides=constants.ADDED_PORTS ) ) flows.append( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS) ) ) flows.append( self.listener_flows.get_create_all_listeners_flow() ) flows.append( database_tasks.MarkLBActiveInDB( mark_subobjects=True, requires=constants.LOADBALANCER ) ) return flows
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)) # Need to add relaod vThunder logic here #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))) # Get VThunder details from database create_member_flow.add(database_tasks.GetAmphoraeFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.AMPHORA)) create_member_flow.add(a10_database_tasks.GetVThunderByLoadBalancer( requires=constants.LOADBALANCER, provides=a10constants.VTHUNDER)) # managing interface additions here create_member_flow.add(vthunder_tasks.AmphoraePostMemberNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS, a10constants.VTHUNDER))) create_member_flow.add(vthunder_tasks.VThunderComputeConnectivityWait( requires=(a10constants.VTHUNDER, constants.AMPHORA))) create_member_flow.add(vthunder_tasks.EnableInterfaceForMembers( requires=[constants.ADDED_PORTS, constants.LOADBALANCER, a10constants.VTHUNDER])) create_member_flow.add(handler_server.MemberCreate( requires=(constants.MEMBER, a10constants.VTHUNDER, constants.POOL))) 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_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)) # 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
def test_handle_network_deltas(self, mock_get_net_driver): mock_driver = mock.MagicMock() self.db_amphora_mock.to_dict.return_value = { constants.ID: AMPHORA_ID, constants.COMPUTE_ID: COMPUTE_ID} mock_get_net_driver.return_value = mock_driver def _interface(network_id): return [data_models.Interface(network_id=network_id)] net = network_tasks.HandleNetworkDeltas() net.execute({}) self.assertFalse(mock_driver.plug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[], delete_nics=[]).to_dict(recurse=True) net.execute({self.db_amphora_mock.id: delta}) self.assertFalse(mock_driver.plug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=_interface(1), delete_nics=[]).to_dict(recurse=True) net.execute({self.db_amphora_mock.id: delta}) mock_driver.plug_network.assert_called_once_with(COMPUTE_ID, 1) # revert net.execute({self.db_amphora_mock.id: delta}) self.assertFalse(mock_driver.unplug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[], delete_nics=[]).to_dict(recurse=True) net.execute({self.db_amphora_mock.id: delta}) self.assertFalse(mock_driver.unplug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=_interface(1), delete_nics=[]).to_dict(recurse=True) mock_driver.reset_mock() mock_driver.unplug_network.side_effect = net_base.NetworkNotFound mock_driver.reset_mock() mock_driver.unplug_network.side_effect = TestException('test') self.assertRaises(TestException, net.revert, mock.ANY, {self.db_amphora_mock.id: delta}) mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1) mock_driver.reset_mock() net.execute({}) self.assertFalse(mock_driver.unplug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[], delete_nics=[]).to_dict(recurse=True) net.execute({self.db_amphora_mock.id: delta}) self.assertFalse(mock_driver.unplug_network.called) delta = data_models.Delta(amphora_id=self.db_amphora_mock.id, compute_id=self.db_amphora_mock.compute_id, add_nics=[], delete_nics=_interface(1) ).to_dict(recurse=True) net.execute({self.db_amphora_mock.id: delta}) mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1) mock_driver.reset_mock() mock_driver.unplug_network.side_effect = net_base.NetworkNotFound net.execute({self.db_amphora_mock.id: delta}) mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1) # Do a test with a general exception in case behavior changes mock_driver.reset_mock() mock_driver.unplug_network.side_effect = Exception() net.execute({self.db_amphora_mock.id: delta}) mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)