def test_get_amphorae_network_configs(self, mock_driver): net_task = network_tasks.GetAmphoraeNetworkConfigs() net_task.execute(LB) mock_driver.get_subnet.assert_called_once_with(SUBNET_ID) mock_driver.get_port.assert_called_once_with(PORT_ID) mock_driver.reset_mock() self.amphora_mock.status = constants.DELETED self.load_balancer_mock.amphorae = [self.amphora_mock] net_task = network_tasks.GetAmphoraeNetworkConfigs() configs = net_task.execute(self.load_balancer_mock) self.assertEqual({}, configs) mock_driver.reset_mock() self.vip_mock.port_id = 1 self.amphora_mock.status = constants.ACTIVE self.amphora_mock.vrrp_port_id = 2 self.amphora_mock.vrrp_ip = "10.0.0.1" self.amphora_mock.ha_port_id = 3 self.amphora_mock.ha_ip = "10.0.0.2" self.load_balancer_mock.amphorae = [self.amphora_mock] net_task = network_tasks.GetAmphoraeNetworkConfigs() configs = net_task.execute(self.load_balancer_mock) vip_port_id = mock.call(1) vrrp_port_id_call = mock.call(2) ha_port_id_call = mock.call(3) vrrp_port_subnet_call = mock.call().get_subnet_id('10.0.0.1') ha_port_subnet_call = mock.call().get_subnet_id('10.0.0.2') mock_driver.get_port.assert_has_calls([ vip_port_id, vrrp_port_id_call, vrrp_port_subnet_call, ha_port_id_call, ha_port_subnet_call ]) self.assertEqual(1, len(configs))
def get_new_LB_networking_subflow(self): """Create a sub-flow to setup networking. :returns: The flow to setup networking for a new amphora """ new_LB_net_subflow = linear_flow.Flow(constants. LOADBALANCER_NETWORKING_SUBFLOW) new_LB_net_subflow.add(network_tasks.AllocateVIP( requires=constants.LOADBALANCER, provides=constants.VIP)) new_LB_net_subflow.add(database_tasks.UpdateVIPAfterAllocation( requires=(constants.LOADBALANCER_ID, constants.VIP), provides=constants.LOADBALANCER)) new_LB_net_subflow.add(network_tasks.PlugVIP( requires=constants.LOADBALANCER, provides=constants.AMPS_DATA)) new_LB_net_subflow.add(database_tasks.UpdateAmphoraVIPData( requires=constants.AMPS_DATA)) new_LB_net_subflow.add(database_tasks.ReloadLoadBalancer( name=constants.RELOAD_LB_AFTER_PLUG_VIP, requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) new_LB_net_subflow.add(network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) new_LB_net_subflow.add(amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) return new_LB_net_subflow
def test_get_amphorae_network_configs(self, mock_get_net_driver): mock_driver = mock.MagicMock() mock_get_net_driver.return_value = mock_driver lb = o_data_models.LoadBalancer() net_task = network_tasks.GetAmphoraeNetworkConfigs() net_task.execute(lb) mock_driver.get_network_configs.assert_called_once_with(lb)
def get_vrrp_subflow(self, prefix): sf_name = prefix + '-' + constants.GET_VRRP_SUBFLOW vrrp_subflow = linear_flow.Flow(sf_name) vrrp_subflow.add( network_tasks.GetAmphoraeNetworkConfigs( name=sf_name + '-' + constants.GET_AMP_NETWORK_CONFIG, requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) vrrp_subflow.add( amphora_driver_tasks.AmphoraUpdateVRRPInterface( name=sf_name + '-' + constants.AMP_UPDATE_VRRP_INTF, requires=constants.LOADBALANCER, provides=constants.LOADBALANCER)) vrrp_subflow.add( database_tasks.CreateVRRPGroupForLB( name=sf_name + '-' + constants.CREATE_VRRP_GROUP_FOR_LB, requires=constants.LOADBALANCER, provides=constants.LOADBALANCER)) vrrp_subflow.add( amphora_driver_tasks.AmphoraVRRPUpdate( name=sf_name + '-' + constants.AMP_VRRP_UPDATE, requires=(constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) vrrp_subflow.add( amphora_driver_tasks.AmphoraVRRPStart( name=sf_name + '-' + constants.AMP_VRRP_START, requires=constants.LOADBALANCER)) return vrrp_subflow
def get_failover_flow(self, role=constants.ROLE_STANDALONE, status=constants.AMPHORA_READY): """Creates a flow to failover a stale amphora :returns: The flow for amphora failover """ failover_amphora_flow = linear_flow.Flow( constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add(lifecycle_tasks.AmphoraToErrorOnRevertTask( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # Delete the old amphora failover_amphora_flow.add( database_tasks.MarkAmphoraPendingDeleteInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraHealthBusy( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add(compute_tasks.ComputeDelete( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add(network_tasks.WaitForPortDetach( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add(database_tasks.MarkAmphoraDeletedInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # If this is an unallocated amp (spares pool), we're done if status != constants.AMPHORA_ALLOCATED: return failover_amphora_flow # Save failed amphora details for later failover_amphora_flow.add( database_tasks.GetAmphoraDetails( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA, provides=constants.AMP_DATA)) # Get a new amphora # Note: Role doesn't matter here. We will update it later. get_amp_subflow = self.get_amphora_for_lb_subflow( prefix=constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add(get_amp_subflow) # Update the new amphora with the failed amphora details failover_amphora_flow.add(database_tasks.UpdateAmpFailoverDetails( requires=(constants.AMPHORA, constants.AMP_DATA))) failover_amphora_flow.add(database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) failover_amphora_flow.add(network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) failover_amphora_flow.add(database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) failover_amphora_flow.add(amphora_driver_tasks.ListenersUpdate( requires=(constants.LOADBALANCER, constants.LISTENERS))) # Plug the VIP ports into the new amphora failover_amphora_flow.add(network_tasks.PlugVIPPort( requires=(constants.AMPHORA, constants.AMPHORAE_NETWORK_CONFIG))) failover_amphora_flow.add(amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.AMPHORA, constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) # Plug the member networks into the new amphora failover_amphora_flow.add(network_tasks.CalculateDelta( requires=constants.LOADBALANCER, provides=constants.DELTAS)) failover_amphora_flow.add(network_tasks.HandleNetworkDeltas( requires=constants.DELTAS, provides=constants.ADDED_PORTS)) failover_amphora_flow.add(amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) # Handle the amphora role and VRRP if necessary if role == constants.ROLE_MASTER: failover_amphora_flow.add(database_tasks.MarkAmphoraMasterInDB( name=constants.MARK_AMP_MASTER_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_BACKUP: failover_amphora_flow.add(database_tasks.MarkAmphoraBackupInDB( name=constants.MARK_AMP_BACKUP_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_STANDALONE: failover_amphora_flow.add( database_tasks.MarkAmphoraStandAloneInDB( name=constants.MARK_AMP_STANDALONE_INDB, requires=constants.AMPHORA)) failover_amphora_flow.add(amphora_driver_tasks.ListenersStart( requires=(constants.LOADBALANCER, constants.LISTENERS))) return failover_amphora_flow
def get_failover_flow(self, role=constants.ROLE_STANDALONE, load_balancer=None): """Creates a flow to failover a stale amphora :returns: The flow for amphora failover """ failover_amphora_flow = linear_flow.Flow( constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add( lifecycle_tasks.AmphoraToErrorOnRevertTask( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # Note: It seems intuitive to boot an amphora prior to deleting # the old amphora, however this is a complicated issue. # If the target host (due to anit-affinity) is resource # constrained, this will fail where a post-delete will # succeed. Since this is async with the API it would result # in the LB ending in ERROR though the amps are still alive. # Consider in the future making this a complicated # try-on-failure-retry flow, or move upgrade failovers to be # synchronous with the API. For now spares pool and act/stdby # will mitigate most of this delay. # Delete the old amphora failover_amphora_flow.add( database_tasks.MarkAmphoraPendingDeleteInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraHealthBusy( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( compute_tasks.ComputeDelete( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( network_tasks.WaitForPortDetach( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraDeletedInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # If this is an unallocated amp (spares pool), we're done if not load_balancer: failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) return failover_amphora_flow # Save failed amphora details for later failover_amphora_flow.add( database_tasks.GetAmphoraDetails( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA, provides=constants.AMP_DATA)) # Get a new amphora # Note: Role doesn't matter here. We will update it later. get_amp_subflow = self.get_amphora_for_lb_subflow( prefix=constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add(get_amp_subflow) # Update the new amphora with the failed amphora details failover_amphora_flow.add( database_tasks.UpdateAmpFailoverDetails( requires=(constants.AMPHORA, constants.AMP_DATA))) # Update the data stored in the flow from the database failover_amphora_flow.add( database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) failover_amphora_flow.add( database_tasks.ReloadAmphora(requires=constants.AMPHORA_ID, provides=constants.AMPHORA)) # Prepare to reconnect the network interface(s) failover_amphora_flow.add( network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) failover_amphora_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) failover_amphora_flow.add( database_tasks.GetAmphoraeFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.AMPHORAE)) # Plug the VIP ports into the new amphora # The reason for moving these steps here is the udp listeners want to # do some kernel configuration before Listener update for forbidding # failure during rebuild amphora. failover_amphora_flow.add( network_tasks.PlugVIPPort( requires=(constants.AMPHORA, constants.AMPHORAE_NETWORK_CONFIG))) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.AMPHORA, constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) # Listeners update needs to be run on all amphora to update # their peer configurations. So parallelize this with an # unordered subflow. update_amps_subflow = unordered_flow.Flow( constants.UPDATE_AMPS_SUBFLOW) timeout_dict = { constants.CONN_MAX_RETRIES: CONF.haproxy_amphora.active_connection_max_retries, constants.CONN_RETRY_INTERVAL: CONF.haproxy_amphora.active_connection_rety_interval } # Setup parallel flows for each amp. We don't know the new amp # details at flow creation time, so setup a subflow for each # amp on the LB, they let the task index into a list of amps # to find the amphora it should work on. amp_index = 0 for amp in load_balancer.amphorae: if amp.status == constants.DELETED: continue update_amps_subflow.add( amphora_driver_tasks.AmpListenersUpdate( name=constants.AMP_LISTENER_UPDATE + '-' + str(amp_index), requires=(constants.LISTENERS, constants.AMPHORAE), inject={ constants.AMPHORA_INDEX: amp_index, constants.TIMEOUT_DICT: timeout_dict })) amp_index += 1 failover_amphora_flow.add(update_amps_subflow) # Plug the member networks into the new amphora failover_amphora_flow.add( network_tasks.CalculateAmphoraDelta( requires=(constants.LOADBALANCER, constants.AMPHORA), provides=constants.DELTA)) failover_amphora_flow.add( network_tasks.HandleNetworkDelta(requires=(constants.AMPHORA, constants.DELTA), provides=constants.ADDED_PORTS)) failover_amphora_flow.add( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) failover_amphora_flow.add( database_tasks.ReloadLoadBalancer( name='octavia-failover-LB-reload-2', requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) # Handle the amphora role and VRRP if necessary if role == constants.ROLE_MASTER: failover_amphora_flow.add( database_tasks.MarkAmphoraMasterInDB( name=constants.MARK_AMP_MASTER_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_BACKUP: failover_amphora_flow.add( database_tasks.MarkAmphoraBackupInDB( name=constants.MARK_AMP_BACKUP_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_STANDALONE: failover_amphora_flow.add( database_tasks.MarkAmphoraStandAloneInDB( name=constants.MARK_AMP_STANDALONE_INDB, requires=constants.AMPHORA)) failover_amphora_flow.add( amphora_driver_tasks.ListenersStart( requires=(constants.LOADBALANCER, constants.LISTENERS, constants.AMPHORA))) failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) return failover_amphora_flow
def get_failover_flow(self, role=constants.ROLE_STANDALONE, load_balancer_id=None): """Creates a flow to failover a stale amphora :returns: The flow for amphora failover """ failover_amphora_flow = linear_flow.Flow( constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add( lifecycle_tasks.AmphoraToErrorOnRevertTask( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # Note: It seems intuitive to boot an amphora prior to deleting # the old amphora, however this is a complicated issue. # If the target host (due to anit-affinity) is resource # constrained, this will fail where a post-delete will # succeed. Since this is async with the API it would result # in the LB ending in ERROR though the amps are still alive. # Consider in the future making this a complicated # try-on-failure-retry flow, or move upgrade failovers to be # synchronous with the API. For now spares pool and act/stdby # will mitigate most of this delay. # Delete the old amphora failover_amphora_flow.add( database_tasks.MarkAmphoraPendingDeleteInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraHealthBusy( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( compute_tasks.ComputeDelete( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( network_tasks.WaitForPortDetach( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraDeletedInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # If this is an unallocated amp (spares pool), we're done if not load_balancer_id: failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) return failover_amphora_flow # Save failed amphora details for later failover_amphora_flow.add( database_tasks.GetAmphoraDetails( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA, provides=constants.AMP_DATA)) # Get a new amphora # Note: Role doesn't matter here. We will update it later. get_amp_subflow = self.get_amphora_for_lb_subflow( prefix=constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add(get_amp_subflow) # Update the new amphora with the failed amphora details failover_amphora_flow.add( database_tasks.UpdateAmpFailoverDetails( requires=(constants.AMPHORA, constants.AMP_DATA))) # Update the data stored in the flow from the database failover_amphora_flow.add( database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) failover_amphora_flow.add( database_tasks.ReloadAmphora(requires=constants.AMPHORA_ID, provides=constants.AMPHORA)) # Prepare to reconnect the network interface(s) failover_amphora_flow.add( network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) failover_amphora_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) failover_amphora_flow.add( amphora_driver_tasks.ListenersUpdate( requires=(constants.LOADBALANCER, constants.LISTENERS))) # Plug the VIP ports into the new amphora failover_amphora_flow.add( network_tasks.PlugVIPPort( requires=(constants.AMPHORA, constants.AMPHORAE_NETWORK_CONFIG))) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.AMPHORA, constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) # Plug the member networks into the new amphora failover_amphora_flow.add( network_tasks.CalculateDelta(requires=constants.LOADBALANCER, provides=constants.DELTAS)) failover_amphora_flow.add( network_tasks.HandleNetworkDeltas(requires=constants.DELTAS, provides=constants.ADDED_PORTS)) failover_amphora_flow.add( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) # Handle the amphora role and VRRP if necessary if role == constants.ROLE_MASTER: failover_amphora_flow.add( database_tasks.MarkAmphoraMasterInDB( name=constants.MARK_AMP_MASTER_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_BACKUP: failover_amphora_flow.add( database_tasks.MarkAmphoraBackupInDB( name=constants.MARK_AMP_BACKUP_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_STANDALONE: failover_amphora_flow.add( database_tasks.MarkAmphoraStandAloneInDB( name=constants.MARK_AMP_STANDALONE_INDB, requires=constants.AMPHORA)) failover_amphora_flow.add( amphora_driver_tasks.ListenersStart( requires=(constants.LOADBALANCER, constants.LISTENERS))) failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) return failover_amphora_flow
def get_failover_flow(self, role=constants.ROLE_STANDALONE): """Creates a flow to failover a stale amphora :returns: The flow for amphora failover """ failover_amphora_flow = linear_flow.Flow( constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add( network_tasks.RetrievePortIDsOnAmphoraExceptLBNetwork( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA, provides=constants.PORTS)) failover_amphora_flow.add( network_tasks.FailoverPreparationForAmphora( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # Delete the old amphora failover_amphora_flow.add( database_tasks.MarkAmphoraPendingDeleteInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraHealthBusy( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( compute_tasks.ComputeDelete( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.DisableAmphoraHealthMonitoring( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraDeletedInDB( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA)) # Save failed amphora details for later failover_amphora_flow.add( database_tasks.GetAmphoraDetails( rebind={constants.AMPHORA: constants.FAILED_AMPHORA}, requires=constants.AMPHORA, provides=constants.AMP_DATA)) # Get a new amphora # Note: Role doesn't matter here. We will update it later. get_amp_subflow = self.get_amphora_for_lb_subflow( prefix=constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add(get_amp_subflow) # Update the new amphora with the failed amphora details failover_amphora_flow.add( database_tasks.UpdateAmpFailoverDetails( requires=(constants.AMPHORA, constants.AMP_DATA))) failover_amphora_flow.add( database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) failover_amphora_flow.add( network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) failover_amphora_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) failover_amphora_flow.add( database_tasks.GetVipFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.VIP)) failover_amphora_flow.add( amphora_driver_tasks.ListenersUpdate( requires=(constants.LOADBALANCER, constants.LISTENERS))) failover_amphora_flow.add( network_tasks.PlugPorts(requires=(constants.AMPHORA, constants.PORTS))) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) failover_amphora_flow.add( network_tasks.GetMemberPorts(requires=(constants.LOADBALANCER, constants.AMPHORA), provides=constants.MEMBER_PORTS)) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostNetworkPlug( rebind={constants.PORTS: constants.MEMBER_PORTS}, requires=(constants.AMPHORA, constants.PORTS))) # Handle the amphora role and VRRP if necessary if role == constants.ROLE_MASTER: failover_amphora_flow.add( database_tasks.MarkAmphoraMasterInDB( name=constants.MARK_AMP_MASTER_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_BACKUP: failover_amphora_flow.add( database_tasks.MarkAmphoraBackupInDB( name=constants.MARK_AMP_BACKUP_INDB, requires=constants.AMPHORA)) vrrp_subflow = self.get_vrrp_subflow(role) failover_amphora_flow.add(vrrp_subflow) elif role == constants.ROLE_STANDALONE: failover_amphora_flow.add( database_tasks.MarkAmphoraStandAloneInDB( name=constants.MARK_AMP_STANDALONE_INDB, requires=constants.AMPHORA)) failover_amphora_flow.add( amphora_driver_tasks.ListenersStart( requires=(constants.LOADBALANCER, constants.LISTENERS))) return failover_amphora_flow
def get_extension_flow(self, distributor): """Extend a amphora for load balancer. :returns: The flow for loadbalancer extension """ extension_flow = linear_flow.Flow( constants.EXTENSION_LOADBALANCER_FLOW) get_amp_subflow = self.get_amphora_for_lb_subflow( prefix=constants.EXTENSION_LOADBALANCER_FLOW, role=constants.ROLE_ACTIVE) extension_flow.add(get_amp_subflow) # Update the data stored in the flow from the database extension_flow.add( database_tasks.ReloadLoadBalancer( name='first', requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) extension_flow.add( network_tasks.PlugAmphoraVIP(requires=(constants.AMPHORA, constants.LOADBALANCER), provides=constants.AMPS_DATA)) extension_flow.add( database_tasks.UpdateAmphoraVIPData(requires=constants.AMPS_DATA)) # Update the data stored in the flow from the database extension_flow.add( database_tasks.ReloadLoadBalancer( name='second', requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) extension_flow.add( database_tasks.ReloadAmphora(requires=constants.AMPHORA_ID, provides=constants.AMPHORA)) # Prepare to reconnect the network interface(s) extension_flow.add( network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) extension_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) extension_flow.add( database_tasks.GetAmphoraeFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.AMPHORAE)) extension_flow.add( amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.AMPHORA, constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) timeout_dict = { constants.CONN_MAX_RETRIES: CONF.haproxy_amphora.active_connection_max_retries, constants.CONN_RETRY_INTERVAL: CONF.haproxy_amphora.active_connection_rety_interval } extension_flow.add( amphora_driver_tasks.AmpsListenersUpdate( name=constants.AMP_LISTENER_UPDATE, requires=(constants.LISTENERS, constants.LOADBALANCER), inject=({ constants.TIMEOUT_DICT: timeout_dict }))) # Plug the member networks into the new amphora extension_flow.add( network_tasks.CalculateAmphoraDelta( requires=(constants.LOADBALANCER, constants.AMPHORA), provides=constants.DELTA)) extension_flow.add( network_tasks.HandleNetworkDelta(requires=(constants.AMPHORA, constants.DELTA), provides=constants.ADDED_PORTS)) extension_flow.add( amphora_driver_tasks.AmphoraePostNetworkPlug( requires=(constants.LOADBALANCER, constants.ADDED_PORTS))) extension_flow.add( database_tasks.ReloadLoadBalancer( name='octavia-extension-LB-reload-2', requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) extension_flow.add( self.get_distributor_flows('octavia-extension-distributor-flow', distributor)) extension_flow.add( amphora_driver_tasks.ListenersStart( requires=(constants.LOADBALANCER, constants.LISTENERS, constants.AMPHORA))) return extension_flow
def get_failover_flow(self): """Creates a flow to failover a stale amphora :returns: The flow for amphora failover """ failover_amphora_flow = linear_flow.Flow( constants.FAILOVER_AMPHORA_FLOW) failover_amphora_flow.add( network_tasks.RetrievePortIDsOnAmphoraExceptLBNetwork( requires=constants.AMPHORA, provides=constants.PORTS)) failover_amphora_flow.add( network_tasks.FailoverPreparationForAmphora( requires=constants.AMPHORA)) failover_amphora_flow.add( compute_tasks.ComputeDelete(requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.MarkAmphoraDeletedInDB(requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.CreateAmphoraInDB(provides=constants.AMPHORA_ID)) failover_amphora_flow.add( database_tasks.GetUpdatedFailoverAmpNetworkDetailsAsList( requires=(constants.AMPHORA_ID, constants.AMPHORA), provides=constants.AMPS_DATA)) if self.REST_AMPHORA_DRIVER: failover_amphora_flow.add( cert_task.GenerateServerPEMTask(provides=constants.SERVER_PEM)) failover_amphora_flow.add( compute_tasks.CertComputeCreate( requires=(constants.AMPHORA_ID, constants.SERVER_PEM), provides=constants.COMPUTE_ID)) else: failover_amphora_flow.add( compute_tasks.ComputeCreate(requires=constants.AMPHORA_ID, provides=constants.COMPUTE_ID)) failover_amphora_flow.add( database_tasks.UpdateAmphoraComputeId( requires=(constants.AMPHORA_ID, constants.COMPUTE_ID))) failover_amphora_flow.add( database_tasks.AssociateFailoverAmphoraWithLBID( requires=(constants.AMPHORA_ID, constants.LOADBALANCER_ID))) failover_amphora_flow.add( database_tasks.MarkAmphoraBootingInDB( requires=(constants.AMPHORA_ID, constants.COMPUTE_ID))) wait_flow = linear_flow.Flow( constants.WAIT_FOR_AMPHORA, retry=retry.Times(CONF.controller_worker.amp_active_retries)) wait_flow.add( compute_tasks.ComputeWait(requires=constants.COMPUTE_ID, provides=constants.COMPUTE_OBJ)) wait_flow.add( database_tasks.UpdateAmphoraInfo(requires=(constants.AMPHORA_ID, constants.COMPUTE_OBJ), provides=constants.AMPHORA)) failover_amphora_flow.add(wait_flow) failover_amphora_flow.add( database_tasks.ReloadAmphora(requires=constants.AMPHORA_ID, provides=constants.FAILOVER_AMPHORA)) failover_amphora_flow.add( amphora_driver_tasks.AmphoraFinalize( rebind={constants.AMPHORA: constants.FAILOVER_AMPHORA}, requires=constants.AMPHORA)) failover_amphora_flow.add( database_tasks.UpdateAmphoraVIPData(requires=constants.AMPS_DATA)) failover_amphora_flow.add( database_tasks.ReloadLoadBalancer( requires=constants.LOADBALANCER_ID, provides=constants.LOADBALANCER)) failover_amphora_flow.add( network_tasks.GetAmphoraeNetworkConfigs( requires=constants.LOADBALANCER, provides=constants.AMPHORAE_NETWORK_CONFIG)) failover_amphora_flow.add( database_tasks.GetListenersFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.LISTENERS)) failover_amphora_flow.add( database_tasks.GetVipFromLoadbalancer( requires=constants.LOADBALANCER, provides=constants.VIP)) failover_amphora_flow.add( amphora_driver_tasks.ListenersUpdate(requires=(constants.LISTENERS, constants.VIP))) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostVIPPlug( requires=(constants.LOADBALANCER, constants.AMPHORAE_NETWORK_CONFIG))) failover_amphora_flow.add( network_tasks.GetMemberPorts( rebind={constants.AMPHORA: constants.FAILOVER_AMPHORA}, requires=(constants.LOADBALANCER, constants.AMPHORA), provides=constants.MEMBER_PORTS)) failover_amphora_flow.add( amphora_driver_tasks.AmphoraPostNetworkPlug( rebind={ constants.AMPHORA: constants.FAILOVER_AMPHORA, constants.PORTS: constants.MEMBER_PORTS }, requires=(constants.AMPHORA, constants.PORTS))) failover_amphora_flow.add( amphora_driver_tasks.ListenersStart(requires=(constants.LISTENERS, constants.VIP))) failover_amphora_flow.add( database_tasks.MarkAmphoraAllocatedInDB( rebind={constants.AMPHORA: constants.FAILOVER_AMPHORA}, requires=(constants.AMPHORA, constants.LOADBALANCER_ID))) return failover_amphora_flow