Move LB reload logic into scaling library
The lb_reload() logic is moved into a separate module of the scaling library. A new test case is added to test this utility function. Since the revised _lb_reload() method checks if LOAD_BALANCER_NAMES is defined/provided or not, the OpenStack version of AutoScalingGroup doesn't have to implement an empty _lb_reload() method now. partial-blueprint: as-lib partial-blueprint: reorg-asg-code Change-Id: I7387d0f27c6121be29d9a035be4cca0b9bbdf441
This commit is contained in:
parent
1bc2e6c35c
commit
f433cfc73e
@ -11,10 +11,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from heat.common import environment_format
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common.i18n import _
|
||||
from heat.common import timeutils as iso8601utils
|
||||
@ -24,6 +21,7 @@ from heat.engine import properties
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import stack_resource
|
||||
from heat.scaling import lbutils
|
||||
from heat.scaling import template
|
||||
|
||||
|
||||
@ -348,37 +346,10 @@ class InstanceGroup(stack_resource.StackResource):
|
||||
self._lb_reload()
|
||||
|
||||
def _lb_reload(self, exclude=None):
|
||||
'''
|
||||
Notify the LoadBalancer to reload its config to include
|
||||
the changes in instances we have just made.
|
||||
|
||||
This must be done after activation (instance in ACTIVE state),
|
||||
otherwise the instances' IP addresses may not be available.
|
||||
'''
|
||||
exclude = exclude or []
|
||||
if self.properties[self.LOAD_BALANCER_NAMES]:
|
||||
id_list = grouputils.get_member_refids(self, exclude=exclude)
|
||||
for lb in self.properties[self.LOAD_BALANCER_NAMES]:
|
||||
lb_resource = self.stack[lb]
|
||||
|
||||
props = copy.copy(lb_resource.properties.data)
|
||||
if 'Instances' in lb_resource.properties_schema:
|
||||
props['Instances'] = id_list
|
||||
elif 'members' in lb_resource.properties_schema:
|
||||
props['members'] = id_list
|
||||
else:
|
||||
raise exception.Error(
|
||||
_("Unsupported resource '%s' in LoadBalancerNames") %
|
||||
(lb,))
|
||||
|
||||
lb_defn = rsrc_defn.ResourceDefinition(
|
||||
lb_resource.name,
|
||||
lb_resource.type(),
|
||||
properties=props,
|
||||
metadata=lb_resource.t.get('Metadata'),
|
||||
deletion_policy=lb_resource.t.get('DeletionPolicy'))
|
||||
|
||||
scheduler.TaskRunner(lb_resource.update, lb_defn)()
|
||||
lb_names = self.properties.get(self.LOAD_BALANCER_NAMES, None)
|
||||
if lb_names:
|
||||
lb_dict = dict((name, self.stack[name]) for name in lb_names)
|
||||
lbutils.reload_loadbalancers(self, lb_dict, exclude)
|
||||
|
||||
def FnGetRefId(self):
|
||||
return self.physical_resource_name_or_FnGetRefId()
|
||||
|
@ -125,12 +125,6 @@ class AutoScalingResourceGroup(aws_asg.AutoScalingGroup):
|
||||
properties=rsrc.get('properties'),
|
||||
metadata=rsrc.get('metadata'))
|
||||
|
||||
def _lb_reload(self, exclude=None):
|
||||
"""AutoScalingResourceGroup does not maintain load balancer
|
||||
connections, so we just ignore calls to update the LB.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _try_rolling_update(self, prop_diff):
|
||||
if (self.properties[self.ROLLING_UPDATES] and
|
||||
self.RESOURCE in prop_diff):
|
||||
|
51
heat/scaling/lbutils.py
Normal file
51
heat/scaling/lbutils.py
Normal file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
|
||||
|
||||
def reload_loadbalancers(group, load_balancers, exclude=None):
|
||||
'''
|
||||
Notify the LoadBalancer to reload its config.
|
||||
|
||||
This must be done after activation (instance in ACTIVE state), otherwise
|
||||
the instances' IP addresses may not be available.
|
||||
'''
|
||||
exclude = exclude or []
|
||||
id_list = grouputils.get_member_refids(group, exclude=exclude)
|
||||
for name, lb in six.iteritems(load_balancers):
|
||||
props = copy.copy(lb.properties.data)
|
||||
if 'Instances' in lb.properties_schema:
|
||||
props['Instances'] = id_list
|
||||
elif 'members' in lb.properties_schema:
|
||||
props['members'] = id_list
|
||||
else:
|
||||
raise exception.Error(
|
||||
_("Unsupported resource '%s' in LoadBalancerNames") % name)
|
||||
|
||||
lb_defn = rsrc_defn.ResourceDefinition(
|
||||
lb.name,
|
||||
lb.type(),
|
||||
properties=props,
|
||||
metadata=lb.t.get('Metadata'),
|
||||
deletion_policy=lb.t.get('DeletionPolicy'))
|
||||
|
||||
scheduler.TaskRunner(lb.update, lb_defn)()
|
142
heat/tests/autoscaling/test_lbutils.py
Normal file
142
heat/tests/autoscaling/test_lbutils.py
Normal file
@ -0,0 +1,142 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.scaling import lbutils
|
||||
from heat.tests import common
|
||||
from heat.tests import generic_resource
|
||||
from heat.tests import utils
|
||||
|
||||
lb_stack = '''
|
||||
heat_template_version: 2013-05-23
|
||||
resources:
|
||||
neutron_lb_1:
|
||||
type: Mock::Neutron::LB
|
||||
neutron_lb_2:
|
||||
type: Mock::Neutron::LB
|
||||
aws_lb_1:
|
||||
type: Mock::AWS::LB
|
||||
aws_lb_2:
|
||||
type: Mock::AWS::LB
|
||||
non_lb:
|
||||
type: Mock::Not::LB
|
||||
'''
|
||||
|
||||
|
||||
class MockedNeutronLB(generic_resource.GenericResource):
|
||||
properties_schema = {
|
||||
'members': properties.Schema(
|
||||
properties.Schema.LIST,
|
||||
update_allowed=True)
|
||||
}
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
return
|
||||
|
||||
|
||||
class MockedAWSLB(generic_resource.GenericResource):
|
||||
properties_schema = {
|
||||
'Instances': properties.Schema(
|
||||
properties.Schema.LIST,
|
||||
update_allowed=True)
|
||||
}
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
return
|
||||
|
||||
|
||||
class LBUtilsTest(common.HeatTestCase):
|
||||
# need to mock a group so that group_utils.get_member_refids will work
|
||||
# load_balancers is a dict of load_balancer objects, where each lb has
|
||||
# properties for checking
|
||||
|
||||
def setUp(self):
|
||||
super(LBUtilsTest, self).setUp()
|
||||
resource._register_class('Mock::Neutron::LB', MockedNeutronLB)
|
||||
resource._register_class('Mock::AWS::LB', MockedAWSLB)
|
||||
resource._register_class('Mock::Not::LB',
|
||||
generic_resource.GenericResource)
|
||||
|
||||
t = template_format.parse(lb_stack)
|
||||
self.stack = utils.parse_stack(t)
|
||||
|
||||
def test_reload_aws_lb(self):
|
||||
group = mock.Mock()
|
||||
self.patchobject(grouputils, 'get_member_refids',
|
||||
return_value=['ID1', 'ID2', 'ID3'])
|
||||
|
||||
lb1 = self.stack['aws_lb_1']
|
||||
lb2 = self.stack['aws_lb_2']
|
||||
lbs = {
|
||||
'LB_1': lb1,
|
||||
'LB_2': lb2
|
||||
}
|
||||
|
||||
lb1.handle_update = mock.Mock()
|
||||
lb2.handle_update = mock.Mock()
|
||||
prop_diff = {'Instances': ['ID1', 'ID2', 'ID3']}
|
||||
|
||||
lbutils.reload_loadbalancers(group, lbs)
|
||||
|
||||
# For verification's purpose, we just check the prop_diff
|
||||
lb1.handle_update.assert_called_with(mock.ANY, mock.ANY,
|
||||
prop_diff)
|
||||
lb2.handle_update.assert_called_with(mock.ANY, mock.ANY,
|
||||
prop_diff)
|
||||
|
||||
def test_reload_neutron_lb(self):
|
||||
group = mock.Mock()
|
||||
self.patchobject(grouputils, 'get_member_refids',
|
||||
return_value=['ID1', 'ID2', 'ID3'])
|
||||
|
||||
lb1 = self.stack['neutron_lb_1']
|
||||
lb2 = self.stack['neutron_lb_2']
|
||||
lbs = {
|
||||
'LB_1': lb1,
|
||||
'LB_2': lb2
|
||||
}
|
||||
|
||||
lb1.handle_update = mock.Mock()
|
||||
lb2.handle_update = mock.Mock()
|
||||
|
||||
prop_diff = {'members': ['ID1', 'ID2', 'ID3']}
|
||||
|
||||
lbutils.reload_loadbalancers(group, lbs)
|
||||
|
||||
# For verification's purpose, we just check the prop_diff
|
||||
lb1.handle_update.assert_called_with(mock.ANY, mock.ANY,
|
||||
prop_diff)
|
||||
lb2.handle_update.assert_called_with(mock.ANY, mock.ANY,
|
||||
prop_diff)
|
||||
|
||||
def test_reload_non_lb(self):
|
||||
group = mock.Mock()
|
||||
self.patchobject(grouputils, 'get_member_refids',
|
||||
return_value=['ID1', 'ID2', 'ID3'])
|
||||
|
||||
lbs = {
|
||||
'LB_1': self.stack['non_lb'],
|
||||
}
|
||||
|
||||
error = self.assertRaises(exception.Error,
|
||||
lbutils.reload_loadbalancers,
|
||||
group, lbs)
|
||||
self.assertIn("Unsupported resource 'LB_1' in LoadBalancerNames",
|
||||
six.text_type(error))
|
Loading…
Reference in New Issue
Block a user