diff --git a/heat/engine/resources/loadbalancer.py b/heat/engine/resources/loadbalancer.py index be0658bb02..f265265ffe 100644 --- a/heat/engine/resources/loadbalancer.py +++ b/heat/engine/resources/loadbalancer.py @@ -422,7 +422,7 @@ class LoadBalancer(stack_resource.StackResource): servers = [] n = 1 nova_cp = self.client_plugin('nova') - for i in instances: + for i in instances or []: ip = nova_cp.server_to_ipaddress(i) or '0.0.0.0' LOG.debug('haproxy server:%s' % ip) servers.append('%sserver server%d %s:%s %s' % (spaces, n, @@ -481,7 +481,17 @@ class LoadBalancer(stack_resource.StackResource): save it to the db. rely on the cfn-hup to reconfigure HAProxy ''' - if self.INSTANCES in prop_diff: + new_props = json_snippet.properties(self.properties_schema, + self.context) + + # Valid use cases are: + # - Membership controlled by members property in template + # - Empty members property in template; membership controlled by + # "updates" triggered from autoscaling group. + # Mixing the two will lead to undefined behaviour. + if (self.INSTANCES in prop_diff and + (self.properties[self.INSTANCES] is not None or + new_props[self.INSTANCES] is not None)): templ = self.get_parsed_template() cfg = self._haproxy_config(templ, prop_diff[self.INSTANCES]) diff --git a/heat/engine/resources/neutron/loadbalancer.py b/heat/engine/resources/neutron/loadbalancer.py index e9bdbb0cc2..3cb913f477 100644 --- a/heat/engine/resources/neutron/loadbalancer.py +++ b/heat/engine/resources/neutron/loadbalancer.py @@ -640,7 +640,6 @@ class LoadBalancer(resource.Resource): MEMBERS: properties.Schema( properties.Schema.LIST, _('The list of Nova server IDs load balanced.'), - default=[], update_allowed=True ), } @@ -652,7 +651,7 @@ class LoadBalancer(resource.Resource): client = self.neutron() protocol_port = self.properties[self.PROTOCOL_PORT] - for member in self.properties.get(self.MEMBERS): + for member in self.properties[self.MEMBERS] or []: address = self.client_plugin('nova').server_to_ipaddress(member) lb_member = client.create_member({ 'member': { @@ -662,8 +661,18 @@ class LoadBalancer(resource.Resource): self.data_set(member, lb_member['id']) def handle_update(self, json_snippet, tmpl_diff, prop_diff): - if self.MEMBERS in prop_diff: - members = set(prop_diff[self.MEMBERS]) + new_props = json_snippet.properties(self.properties_schema, + self.context) + + # Valid use cases are: + # - Membership controlled by members property in template + # - Empty members property in template; membership controlled by + # "updates" triggered from autoscaling group. + # Mixing the two will lead to undefined behaviour. + if (self.MEMBERS in prop_diff and + (self.properties[self.MEMBERS] is not None or + new_props[self.MEMBERS] is not None)): + members = set(new_props[self.MEMBERS] or []) rd_members = self.data() old_members = set(rd_members.keys()) client = self.neutron() @@ -688,7 +697,7 @@ class LoadBalancer(resource.Resource): def handle_delete(self): client = self.neutron() - for member in self.properties.get(self.MEMBERS): + for member in self.properties[self.MEMBERS] or []: member_id = self.data().get(member) try: client.delete_member(member_id) diff --git a/heat/tests/test_neutron_autoscaling.py b/heat/tests/test_neutron_autoscaling.py index 6105287ed2..4a266c4d63 100644 --- a/heat/tests/test_neutron_autoscaling.py +++ b/heat/tests/test_neutron_autoscaling.py @@ -122,7 +122,6 @@ class AutoScalingTest(HeatTestCase): self.m.StubOutWithMock(neutronclient.Client, 'show_pool') self.m.StubOutWithMock(neutronclient.Client, 'show_vip') self.m.StubOutWithMock(neutronclient.Client, 'create_member') - self.m.StubOutWithMock(neutronclient.Client, 'delete_member') self.m.StubOutWithMock(neutronclient.Client, 'list_members') self.m.StubOutWithMock(nova.NovaClientPlugin, 'server_to_ipaddress') @@ -310,8 +309,6 @@ class AutoScalingTest(HeatTestCase): nova.NovaClientPlugin.server_to_ipaddress( mox.IgnoreArg()).AndReturn('1.2.3.5') - neutronclient.Client.delete_member(mox.IgnoreArg()).AndReturn(None) - neutronclient.Client.create_member(memberb_block).\ AndReturn(memberb_ret_block) @@ -321,12 +318,6 @@ class AutoScalingTest(HeatTestCase): neutronclient.Client.create_member(memberc_block).\ AndReturn(memberc_ret_block) - nova.NovaClientPlugin.server_to_ipaddress( - mox.IgnoreArg()).AndReturn('1.2.3.4') - - neutronclient.Client.create_member(membera_block).\ - AndReturn(membera_ret_block) - self.m.ReplayAll() # Start of stack create