Fix formula for calc update_timeout in instance group

The old formula (probably) supposed to be
(self.stack.timeout_secs() - pause_sec * (batch_cnt - 1)) / batch_cnt,
that have a wrong assumption that every update should take the same
amount of
time. It will be more correct to calculate update_time as the maximum
time
that we can spent on particular update. Maximum timeout for every batch
can't
be greater than
(whole stack timeout) - (time we should spent on all pauses)
otherwise we can't perform some pause (guaranted). It is better to fail
earlier
in such cases when we can predict that further updates will fail at the
some point of time.

Change-Id: I0d965f3e5359e0352dfb31a0e46ff5f1ccd4481b
This commit is contained in:
Oleksii Chuprykov 2015-07-28 09:41:28 -04:00
parent f9117d24a8
commit 395e627de7
2 changed files with 19 additions and 7 deletions

View File

@ -280,6 +280,16 @@ class InstanceGroup(stack_resource.StackResource):
policy[self.MAX_BATCH_SIZE],
pause_sec)
def _update_timeout(self, efft_capacity, efft_bat_sz, pause_sec):
batch_cnt = (efft_capacity + efft_bat_sz - 1) // efft_bat_sz
if pause_sec * (batch_cnt - 1) >= self.stack.timeout_secs():
msg = _('The current %s will result in stack update '
'timeout.') % rsrc_defn.UPDATE_POLICY
raise ValueError(msg)
update_timeout = self.stack.timeout_secs() - (
pause_sec * (batch_cnt - 1))
return update_timeout
def _replace(self, min_in_service, batch_size, pause_sec):
"""
Replace the instances in the group using updated launch configuration
@ -306,13 +316,8 @@ class InstanceGroup(stack_resource.StackResource):
# effective capacity includes temporary capacity added to accommodate
# the minimum number of instances in service during update
efft_capacity = max(capacity - efft_bat_sz, efft_min_sz) + efft_bat_sz
batch_cnt = (efft_capacity + efft_bat_sz - 1) // efft_bat_sz
if pause_sec * (batch_cnt - 1) >= self.stack.timeout_secs():
msg = _('The current %s will result in stack update '
'timeout.') % rsrc_defn.UPDATE_POLICY
raise ValueError(msg)
update_timeout = (self.stack.timeout_secs() - (
pause_sec * (batch_cnt - 1)) / batch_cnt)
update_timeout = self._update_timeout(efft_capacity,
efft_bat_sz, pause_sec)
try:
remainder = capacity
while remainder > 0 or efft_capacity > capacity:

View File

@ -41,6 +41,13 @@ class TestInstanceGroup(common.HeatTestCase):
self.instance_group = instgrp.InstanceGroup('asg',
self.defn, self.stack)
def test_update_timeout(self):
self.stack.timeout_secs = mock.Mock(return_value=100)
# there are 3 batches, so we need 2 pauses by 20 sec
# result timeout should be 100 - 2 * 20 = 60
self.assertEqual(60, self.instance_group._update_timeout(
efft_capacity=9, efft_bat_sz=3, pause_sec=20))
def test_child_template(self):
self.instance_group._create_template = mock.Mock(return_value='tpl')
self.assertEqual('tpl', self.instance_group.child_template())