def test_optimize_clb_adds_maintain_unique_ports(self): """ Multiple ports can be specified for the same address and LB ID when adding to a CLB. """ steps = pbag([ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=8080)))) ]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.1', CLBDescription(lb_id='5', port=8080)))) ]))
def test_optimize_clb_adds_maintain_unique_ports(self): """ Multiple ports can be specified for the same address and LB ID when adding to a CLB. """ steps = pbag([ AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=8080))))]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.1', CLBDescription(lb_id='5', port=8080))))]))
def test_filters_clb_types(self): """ Only one CLB step is returned per CLB """ steps = pbag([ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), # Unoptimizable step CreateServer(server_config=pmap({})), ]) # returned steps could be pbag of any of the 2 lists below depending # on how `one_clb_step` iterates over the steps. Since it is pbag the # order of elements is not guaranteed list1 = [ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), CreateServer(server_config=pmap({})) ] list2 = [ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), CreateServer(server_config=pmap({})) ] self.assertEqual( matches(MatchesAny(Equals(pbag(list1)), Equals(pbag(list2)))), optimize_steps(steps))
def test_rcv3_mixed(self): """ Multiple BulkAddToRCv3 and BulkRemoveFromRCv3 steps are combined into one BulkAddToRCv3 step and one BulkRemoveFromRCv3 step """ steps = [ BulkAddToRCv3( lb_node_pairs=pset([("l1", "s1"), ("l1", "s2")])), # Same pair for different class does not conflict BulkRemoveFromRCv3(lb_node_pairs=pset([("l1", "s1")])), BulkAddToRCv3(lb_node_pairs=pset([("l1", "s3")])), BulkRemoveFromRCv3( lb_node_pairs=pset([("l3", "s3"), ("l2", "s3")])) ] self.assertEqual( optimize_steps(steps), pbag([ BulkAddToRCv3( lb_node_pairs=pset([ ("l1", "s1"), ("l1", "s2"), ("l1", "s3")])), BulkRemoveFromRCv3( lb_node_pairs=pset([ ("l1", "s1"), ("l3", "s3"), ("l2", "s3")])) ]) )
def test_filters_clb_types(self): """ Only one CLB step is returned per CLB """ steps = pbag([ AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), # Unoptimizable step CreateServer(server_config=pmap({})), ]) # returned steps could be pbag of any of the 2 lists below depending # on how `one_clb_step` iterates over the steps. Since it is pbag the # order of elements is not guaranteed list1 = [ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), CreateServer(server_config=pmap({})) ] list2 = [ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), CreateServer(server_config=pmap({})) ] self.assertEqual( matches(MatchesAny(Equals(pbag(list1)), Equals(pbag(list2)))), optimize_steps(steps) )
def plan(desired_group_state, servers, lb_nodes, now, build_timeout): """ Get an optimized convergence plan. Takes the same arguments as :func:`converge`. """ steps = converge(desired_group_state, servers, lb_nodes, now, timeout=build_timeout) steps = limit_steps_by_count(steps) return optimize_steps(steps)
def test_mixed_optimization(self): """ Mixes of optimizable and unoptimizable steps still get optimized correctly. """ steps = pbag([ # CLB adds AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s(('1.1.1.1', CLBDescription(lb_id='6', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s(('1.1.1.2', CLBDescription(lb_id='6', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3')), RemoveNodesFromCLB(lb_id='6', node_ids=s('4')), # Unoptimizable steps CreateServer(server_config=pmap({})), ]) self.assertEqual( optimize_steps(steps), pbag([ # Optimized CLB adds AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s(('1.1.1.1', CLBDescription(lb_id='6', port=80)), ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3', '4')), # Unoptimizable steps CreateServer(server_config=pmap({})) ]))
def plan_launch_stack(desired_group_state, now, build_timeout, stacks): """ Get an optimized convergence plan. The arguments `now` and `build_timeout` are ignored and only necessary to match those of `plan_launch_server`. The arguments `desired_group_state` and `stacks` are the same as in `converge_launch_stack`. """ steps = converge_launch_stack(desired_group_state, stacks) steps = limit_steps_by_count(steps) return optimize_steps(steps)
def plan_launch_server(desired_group_state, now, build_timeout, step_limits, servers, lb_nodes, lbs): """ Get an optimized convergence plan. Takes the same arguments as :func:`converge_launch_server` except `step_limits` which is dict of step class -> limit """ steps = converge_launch_server(desired_group_state, servers, lb_nodes, lbs, now, timeout=build_timeout) steps = limit_steps_by_count(steps, step_limits) return optimize_steps(steps)
def _test_rcv3_step(self, step_class): steps = [ step_class(lb_node_pairs=pset([("l1", "s1"), ("l1", "s2")])), step_class(lb_node_pairs=pset([("l2", "s1")])), step_class(lb_node_pairs=pset([("l1", "s3"), ("l2", "s3")])) ] self.assertEqual( optimize_steps(steps), pbag([ step_class(lb_node_pairs=pset([("l1", "s1"), ( "l1", "s2"), ("l2", "s1"), ("l1", "s3"), ("l2", "s3")])) ]))
def test_mixed_optimization(self): """ Mixes of optimizable and unoptimizable steps still get optimized correctly. """ steps = pbag([ # CLB adds AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='6', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='6', port=80)))), AddNodesToCLB(lb_id='6', address_configs=s( ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3')), RemoveNodesFromCLB(lb_id='6', node_ids=s('4')), # Unoptimizable steps CreateServer(server_config=pmap({})), ]) self.assertEqual( optimize_steps(steps), pbag([ # Optimized CLB adds AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='6', port=80)), ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3', '4')), # Unoptimizable steps CreateServer(server_config=pmap({})) ]))
def plan_launch_stack(desired_group_state, now, build_timeout, step_limits, stacks): """ Get an optimized convergence plan. The arguments `now` and `build_timeout` are ignored and only necessary to match those of `plan_launch_server`. The arguments `desired_group_state` and `stacks` are the same as in `converge_launch_stack`. `step_limits` is dict of step class -> limit """ steps = converge_launch_stack(desired_group_state, stacks) steps = limit_steps_by_count(steps, step_limits) return optimize_steps(steps)
def test_optimize_clb_removes(self): """ Aggregation is done on a per-load-balancer basis when remove nodes from a CLB. """ steps = pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='5', node_ids=s('3')), RemoveNodesFromCLB(lb_id='5', node_ids=s('4'))]) self.assertEqual( optimize_steps(steps), pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2', '3', '4')) ]))
def test_clb_remove_multiple_load_balancers(self): """ Multiple :class:`RemoveNodesFromCLB` steps for the same LB are merged into one. """ steps = pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3')), RemoveNodesFromCLB(lb_id='6', node_ids=s('4'))]) self.assertEqual( optimize_steps(steps), pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3', '4')) ]))
def test_optimize_clb_removes(self): """ Aggregation is done on a per-load-balancer basis when remove nodes from a CLB. """ steps = pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='5', node_ids=s('3')), RemoveNodesFromCLB(lb_id='5', node_ids=s('4')) ]) self.assertEqual( optimize_steps(steps), pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2', '3', '4')) ]))
def _test_rcv3_step(self, step_class): steps = [ step_class( lb_node_pairs=pset([("l1", "s1"), ("l1", "s2")])), step_class(lb_node_pairs=pset([("l2", "s1")])), step_class(lb_node_pairs=pset([("l1", "s3"), ("l2", "s3")])) ] self.assertEqual( optimize_steps(steps), pbag([ step_class( lb_node_pairs=pset([ ("l1", "s1"), ("l1", "s2"), ("l2", "s1"), ("l1", "s3"), ("l2", "s3") ]) ) ]) )
def test_clb_remove_multiple_load_balancers(self): """ Multiple :class:`RemoveNodesFromCLB` steps for the same LB are merged into one. """ steps = pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), RemoveNodesFromCLB(lb_id='5', node_ids=s('2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3')), RemoveNodesFromCLB(lb_id='6', node_ids=s('4')) ]) self.assertEqual( optimize_steps(steps), pbag([ RemoveNodesFromCLB(lb_id='5', node_ids=s('1', '2')), RemoveNodesFromCLB(lb_id='6', node_ids=s('3', '4')) ]))
def test_optimize_leaves_other_steps(self): """ Unoptimizable steps pass the optimizer unchanged. """ steps = pbag([ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), RemoveNodesFromCLB(lb_id='6', node_ids=s('1')), CreateServer(server_config=pmap({})), BulkRemoveFromRCv3(lb_node_pairs=pset([("lb-1", "node-a")])), BulkAddToRCv3(lb_node_pairs=pset([("lb-2", "node-b")])) # Note that the add & remove pair should not be the same; # the optimizer might reasonably optimize opposite # operations away in the future. ]) self.assertEqual(optimize_steps(steps), steps)
def test_optimize_leaves_other_steps(self): """ Unoptimizable steps pass the optimizer unchanged. """ steps = pbag([ AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), RemoveNodesFromCLB(lb_id='5', node_ids=s('1')), CreateServer(server_config=pmap({})), BulkRemoveFromRCv3(lb_node_pairs=pset([("lb-1", "node-a")])), BulkAddToRCv3(lb_node_pairs=pset([("lb-2", "node-b")])) # Note that the add & remove pair should not be the same; # the optimizer might reasonably optimize opposite # operations away in the future. ]) self.assertEqual( optimize_steps(steps), steps)
def test_optimize_clb_adds(self): """ Multiple :class:`AddNodesToCLB` steps for the same LB are merged into one. """ steps = pbag([ AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='5', address_configs=s(('1.2.3.4', CLBDescription(lb_id='5', port=80))))]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.2.3.4', CLBDescription(lb_id='5', port=80))) )]))
def test_optimize_clb_adds(self): """ Multiple :class:`AddNodesToCLB` steps for the same LB are merged into one. """ steps = pbag([ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='5', address_configs=s( ('1.2.3.4', CLBDescription(lb_id='5', port=80)))) ]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.2.3.4', CLBDescription(lb_id='5', port=80)))) ]))
def test_clb_adds_multiple_load_balancers(self): """ Aggregation is done on a per-load-balancer basis when adding to a CLB. """ steps = pbag([ AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='5', address_configs=s(('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s(('1.1.1.1', CLBDescription(lb_id='6', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s(('1.1.1.2', CLBDescription(lb_id='6', port=80)))), ]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='6', port=80)), ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), ]))
def test_clb_adds_multiple_load_balancers(self): """ Aggregation is done on a per-load-balancer basis when adding to a CLB. """ steps = pbag([ AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='5', address_configs=s( ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB(lb_id='6', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='6', port=80)))), AddNodesToCLB(lb_id='6', address_configs=s( ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), ]) self.assertEqual( optimize_steps(steps), pbag([ AddNodesToCLB( lb_id='5', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='5', port=80)), ('1.1.1.2', CLBDescription(lb_id='5', port=80)))), AddNodesToCLB( lb_id='6', address_configs=s( ('1.1.1.1', CLBDescription(lb_id='6', port=80)), ('1.1.1.2', CLBDescription(lb_id='6', port=80)))), ]))
def test_rcv3_mixed(self): """ Multiple BulkAddToRCv3 and BulkRemoveFromRCv3 steps are combined into one BulkAddToRCv3 step and one BulkRemoveFromRCv3 step """ steps = [ BulkAddToRCv3(lb_node_pairs=pset([("l1", "s1"), ("l1", "s2")])), # Same pair for different class does not conflict BulkRemoveFromRCv3(lb_node_pairs=pset([("l1", "s1")])), BulkAddToRCv3(lb_node_pairs=pset([("l1", "s3")])), BulkRemoveFromRCv3(lb_node_pairs=pset([("l3", "s3"), ("l2", "s3")])) ] self.assertEqual( optimize_steps(steps), pbag([ BulkAddToRCv3(lb_node_pairs=pset([("l1", "s1"), ("l1", "s2"), ("l1", "s3")])), BulkRemoveFromRCv3( lb_node_pairs=pset([("l1", "s1"), ("l3", "s3"), ("l2", "s3")])) ]))