def _cooldown_timestamp(self, reason): # Save resource metadata with a timestamp and reason # If we wanted to implement the AutoScaling API like AWS does, # we could maintain event history here, but since we only need # the latest event for cooldown, just store that for now metadata = {timeutils.strtime(): reason} self.metadata = metadata
def test_scaling_policy_cooldown_none(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names()) # Create the scaling policy no Cooldown property, should behave the # same as when Cooldown==0 properties = t['Resources']['WebServerScaleUpPolicy']['Properties'] del(properties['Cooldown']) self._stub_lb_reload(2) now = timeutils.utcnow() self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.StubOutWithMock(asc.ScalingPolicy, 'keystone') asc.ScalingPolicy.keystone().MultipleTimes().AndReturn( self.fc) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.signal() self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'], rsrc.get_instance_names()) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg() ).AndReturn(previous_meta) self._stub_lb_reload(3, unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.signal() self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], rsrc.get_instance_names()) rsrc.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_ok(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names()) # Scale up one self._stub_lb_reload(2) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.StubOutWithMock(asc.ScalingPolicy, 'keystone') asc.ScalingPolicy.keystone().MultipleTimes().AndReturn( self.fc) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.signal() self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'], rsrc.get_instance_names()) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg() ).AndReturn(previous_meta) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload(3, unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.signal() self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], rsrc.get_instance_names()) rsrc.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_toosoon(self): t = template_format.parse(as_template) stack = parse_stack(t, params=self.params) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual('WebServerGroup-0', rsrc.resource_id) # Scale up one self._stub_lb_reload(2) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.StubOutWithMock(asc.ScalingPolicy, 'keystone') asc.ScalingPolicy.keystone().MultipleTimes().AndReturn( self.fc) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.signal() self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().MultipleTimes().AndReturn(now) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) self.m.ReplayAll() up_policy.signal() self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) rsrc.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_none(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0', resource.resource_id) # Create the scaling policy no Cooldown property, should behave the # same as when Cooldown==0 properties = t['Resources']['WebServerScaleUpPolicy']['Properties'] del (properties['Cooldown']) self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) self._stub_lb_reload( ['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_none(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 1") self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = rsrc self.assertEqual(["WebServerGroup-0"], rsrc.get_instance_names()) # Create the scaling policy no Cooldown property, should behave the # same as when Cooldown==0 properties = t["Resources"]["WebServerScaleUpPolicy"]["Properties"] del (properties["Cooldown"]) self._stub_lb_reload(2) now = timeutils.utcnow() self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.StubOutWithMock(asc.ScalingPolicy, "keystone") asc.ScalingPolicy.keystone().MultipleTimes().AndReturn(self.fc) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, "WebServerScaleUpPolicy") up_policy.signal() self.assertEqual(["WebServerGroup-0", "WebServerGroup-1"], rsrc.get_instance_names()) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): "ChangeInCapacity : 1"} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg()).AndReturn(previous_meta) # stub for the metadata accesses while creating the addtional instance Metadata.__get__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) self._stub_lb_reload(3, unset=False) self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.ReplayAll() up_policy.signal() self.assertEqual(["WebServerGroup-0", "WebServerGroup-1", "WebServerGroup-2"], rsrc.get_instance_names()) rsrc.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_ok(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group, 2 instances, Cooldown 60s properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '60' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_create(2) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() resource.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) # Now move time on 61 seconds - Cooldown in template is 60 # so this should update the policy metadata, and the # scaling group instances updated previous_meta = { timeutils.strtime(now): 'PercentChangeInCapacity : -50' } self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=61) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) # raise by 200%, should work self._stub_lb_reload( ['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_create(2) self._stub_meta_expected(now, 'PercentChangeInCapacity : 200') self.m.ReplayAll() resource.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete()
def test_scaling_group_cooldown_ok(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group, 2 instances, Cooldown 60s properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '60' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_create(2) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() resource.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) # Now move time on 61 seconds - Cooldown in template is 60 # so this should update the policy metadata, and the # scaling group instances updated previous_meta = {timeutils.strtime(now): 'PercentChangeInCapacity : -50'} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=61) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg() ).AndReturn(previous_meta) # raise by 200%, should work self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_create(2) self._stub_meta_expected(now, 'PercentChangeInCapacity : 200') self.m.ReplayAll() resource.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete()
def test_scaling_policy_cooldown_none(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0', resource.resource_id) # Create the scaling policy no Cooldown property, should behave the # same as when Cooldown==0 properties = t['Resources']['WebServerScaleUpPolicy']['Properties'] del(properties['Cooldown']) self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg() ).AndReturn(previous_meta) self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_toosoon(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group, 2 instances, Cooldown 60s properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '60' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self._stub_create(2) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() resource.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = { timeutils.strtime(now): 'PercentChangeInCapacity : -50' } self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().AndReturn(now) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) self.m.ReplayAll() # raise by 200%, too soon for Cooldown so there should be no change resource.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) resource.delete()
def test_scaling_group_cooldown_toosoon(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group, 2 instances, Cooldown 60s properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '60' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self._stub_create(2) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() resource.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = {timeutils.strtime(now): 'PercentChangeInCapacity : -50'} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().AndReturn(now) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg() ).AndReturn(previous_meta) self.m.ReplayAll() # raise by 200%, too soon for Cooldown so there should be no change resource.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) resource.delete()
def _stub_meta_expected(self, now, data, nmeta=1): # Stop time at now self.m.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().MultipleTimes().AndReturn(now) # Then set a stub to ensure the metadata update is as # expected based on the timestamp and data self.m.StubOutWithMock(Metadata, '__set__') expected = {timeutils.strtime(now): data} # Note for ScalingPolicy, we expect to get a metadata # update for the policy and autoscaling group, so pass nmeta=2 for x in range(nmeta): Metadata.__set__(mox.IgnoreArg(), expected).AndReturn(None)
def test_scaling_group_cooldown_ok(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group, 2 instances, Cooldown 60s properties = t["Resources"]["WebServerGroup"]["Properties"] properties["DesiredCapacity"] = "2" properties["Cooldown"] = "60" self._stub_lb_reload(2) self._stub_create(2) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 2") self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = rsrc self.assertEqual(["WebServerGroup-0", "WebServerGroup-1"], rsrc.get_instance_names()) # reduce by 50% self._stub_lb_reload(1) self._stub_validate() self._stub_meta_expected(now, "PercentChangeInCapacity : -50") self.m.ReplayAll() rsrc.adjust(-50, "PercentChangeInCapacity") self.assertEqual(["WebServerGroup-0"], rsrc.get_instance_names()) # Now move time on 61 seconds - Cooldown in template is 60 # so this should update the policy metadata, and the # scaling group instances updated previous_meta = {timeutils.strtime(now): "PercentChangeInCapacity : -50"} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=61) self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg()).AndReturn(previous_meta) # stub for the metadata accesses while creating the two instances Metadata.__get__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) Metadata.__get__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) # raise by 200%, should work self._stub_lb_reload(3, unset=False) self._stub_create(2) self._stub_meta_expected(now, "PercentChangeInCapacity : 200") self.m.ReplayAll() rsrc.adjust(200, "PercentChangeInCapacity") self.assertEqual(["WebServerGroup-0", "WebServerGroup-1", "WebServerGroup-2"], rsrc.get_instance_names()) rsrc.delete()
def test_scaling_policy_cooldown_ok(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0', resource.resource_id) # Scale up one self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload( ['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_zero(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group, 2 instances, Cooldown 0 properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '0' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self._stub_create(2) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() resource.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', resource.resource_id) # Don't move time, since cooldown is zero, it should work previous_meta = { timeutils.strtime(now): 'PercentChangeInCapacity : -50' } self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) # raise by 200%, should work self._stub_lb_reload( ['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'PercentChangeInCapacity : 200') self._stub_create(2) self.m.ReplayAll() resource.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_ok(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0', resource.resource_id) # Scale up one self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg() ).AndReturn(previous_meta) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_toosoon(self): t = self.load_template() stack = self.parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = resource self.assertEqual('WebServerGroup-0', resource.resource_id) # Scale up one self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().AndReturn(now) self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_zero(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group, 2 instances, Cooldown 0 properties = t['Resources']['WebServerGroup']['Properties'] properties['DesiredCapacity'] = '2' properties['Cooldown'] = '0' self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 2') self._stub_create(2) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) # reduce by 50% self._stub_lb_reload(['WebServerGroup-0']) self._stub_meta_expected(now, 'PercentChangeInCapacity : -50') self.m.ReplayAll() rsrc.adjust(-50, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0', rsrc.resource_id) # Don't move time, since cooldown is zero, it should work previous_meta = {timeutils.strtime(now): 'PercentChangeInCapacity : -50'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg() ).AndReturn(previous_meta) # raise by 200%, should work self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2'], unset=False) self._stub_meta_expected(now, 'PercentChangeInCapacity : 200') self._stub_create(2) self.m.ReplayAll() rsrc.adjust(200, 'PercentChangeInCapacity') self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', rsrc.resource_id) rsrc.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_toosoon(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group, 2 instances, Cooldown 60s properties = t["Resources"]["WebServerGroup"]["Properties"] properties["DesiredCapacity"] = "2" properties["Cooldown"] = "60" self._stub_lb_reload(2) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 2") self._stub_create(2) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = rsrc self.assertEqual(["WebServerGroup-0", "WebServerGroup-1"], rsrc.get_instance_names()) # reduce by 50% self._stub_lb_reload(1) self._stub_validate() self._stub_meta_expected(now, "PercentChangeInCapacity : -50") self.m.ReplayAll() rsrc.adjust(-50, "PercentChangeInCapacity") self.assertEqual(["WebServerGroup-0"], rsrc.get_instance_names()) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = {timeutils.strtime(now): "PercentChangeInCapacity : -50"} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, "utcnow") timeutils.utcnow().MultipleTimes().AndReturn(now) self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg()).AndReturn(previous_meta) self.m.ReplayAll() # raise by 200%, too soon for Cooldown so there should be no change rsrc.adjust(200, "PercentChangeInCapacity") self.assertEqual(["WebServerGroup-0"], rsrc.get_instance_names()) rsrc.delete()
def test_scaling_policy_cooldown_zero(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual('WebServerGroup-0', rsrc.resource_id) # Create the scaling policy (with Cooldown=0) and scale up one properties = t['Resources']['WebServerScaleUpPolicy']['Properties'] properties['Cooldown'] = '0' self._stub_lb_reload(2) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg() ).AndReturn(previous_meta) self._stub_lb_reload(3, unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2', rsrc.resource_id) rsrc.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_none(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group self._stub_lb_reload(["WebServerGroup-0"]) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 1") self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = resource self.assertEqual("WebServerGroup-0", resource.resource_id) # Create the scaling policy no Cooldown property, should behave the # same as when Cooldown==0 properties = t["Resources"]["WebServerScaleUpPolicy"]["Properties"] del (properties["Cooldown"]) self._stub_lb_reload(["WebServerGroup-0", "WebServerGroup-1"]) now = timeutils.utcnow() self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, "WebServerScaleUpPolicy") up_policy.alarm() self.assertEqual("WebServerGroup-0,WebServerGroup-1", resource.resource_id) # Now trigger another scale-up without changing time, should work previous_meta = {timeutils.strtime(now): "ChangeInCapacity : 1"} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) self._stub_lb_reload(["WebServerGroup-0", "WebServerGroup-1", "WebServerGroup-2"], unset=False) self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.ReplayAll() up_policy.alarm() self.assertEqual("WebServerGroup-0,WebServerGroup-1,WebServerGroup-2", resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_policy_cooldown_toosoon(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group self._stub_lb_reload(["WebServerGroup-0"]) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 1") self._stub_create(1) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = resource self.assertEqual("WebServerGroup-0", resource.resource_id) # Scale up one self._stub_lb_reload(["WebServerGroup-0", "WebServerGroup-1"]) self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.ReplayAll() up_policy = self.create_scaling_policy(t, stack, "WebServerScaleUpPolicy") up_policy.alarm() self.assertEqual("WebServerGroup-0,WebServerGroup-1", resource.resource_id) # Now move time on 10 seconds - Cooldown in template is 60 # so this should not update the policy metadata, and the # scaling group instances should be unchanged # Note we have to stub Metadata.__get__ since up_policy isn't # stored in the DB (because the stack hasn't really been created) previous_meta = {timeutils.strtime(now): "ChangeInCapacity : 1"} self.m.VerifyAll() self.m.UnsetStubs() now = now + datetime.timedelta(seconds=10) self.m.StubOutWithMock(timeutils, "utcnow") timeutils.utcnow().AndReturn(now) self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) self.m.ReplayAll() up_policy.alarm() self.assertEqual("WebServerGroup-0,WebServerGroup-1", resource.resource_id) resource.delete() self.m.VerifyAll()
def test_scaling_group_cooldown_zero(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group, 2 instances, Cooldown 0 properties = t["Resources"]["WebServerGroup"]["Properties"] properties["DesiredCapacity"] = "2" properties["Cooldown"] = "0" self._stub_lb_reload(["WebServerGroup-0", "WebServerGroup-1"]) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 2") self._stub_create(2) self.m.ReplayAll() resource = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = resource self.assertEqual("WebServerGroup-0,WebServerGroup-1", resource.resource_id) # reduce by 50% self._stub_lb_reload(["WebServerGroup-0"]) self._stub_meta_expected(now, "PercentChangeInCapacity : -50") self.m.ReplayAll() resource.adjust(-50, "PercentChangeInCapacity") self.assertEqual("WebServerGroup-0", resource.resource_id) # Don't move time, since cooldown is zero, it should work previous_meta = {timeutils.strtime(now): "PercentChangeInCapacity : -50"} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg()).AndReturn(previous_meta) # raise by 200%, should work self._stub_lb_reload(["WebServerGroup-0", "WebServerGroup-1", "WebServerGroup-2"], unset=False) self._stub_meta_expected(now, "PercentChangeInCapacity : 200") self._stub_create(2) self.m.ReplayAll() resource.adjust(200, "PercentChangeInCapacity") self.assertEqual("WebServerGroup-0,WebServerGroup-1,WebServerGroup-2", resource.resource_id) resource.delete() self.m.VerifyAll()
def test_signal_with_cooldown(self): self.parsed['resources']['my-policy']['properties']['cooldown'] = 60 stack = utils.parse_stack(self.parsed) stack.create() policy = stack['my-policy'] group = stack['my-group'] self.assertEqual(1, len(group.get_instance_names())) policy.signal() self.assertEqual(2, len(group.get_instance_names())) policy.signal() # The second signal shouldn't have changed it because of cooldown self.assertEqual(2, len(group.get_instance_names())) past = timeutils.strtime(timeutils.utcnow() - datetime.timedelta(seconds=65)) policy.metadata_set({past: 'ChangeInCapacity : 1'}) policy.signal() self.assertEqual(3, len(group.get_instance_names()))
def test_signal_with_cooldown(self): self.parsed['resources']['my-policy']['properties']['cooldown'] = 60 stack = utils.parse_stack(self.parsed) stack.create() policy = stack['my-policy'] group = stack['my-group'] self.assertEqual(1, len(group.get_instance_names())) policy.signal() self.assertEqual(2, len(group.get_instance_names())) policy.signal() # The second signal shouldn't have changed it because of cooldown self.assertEqual(2, len(group.get_instance_names())) past = timeutils.strtime(timeutils.utcnow() - datetime.timedelta(seconds=65)) policy.metadata = {past: 'ChangeInCapacity : 1'} policy.signal() self.assertEqual(3, len(group.get_instance_names()))
def to_primitive(value, convert_instances=False, convert_datetime=True, level=0, max_depth=3): """Convert a complex object into primitives. Handy for JSON serialization. We can optionally handle instances, but since this is a recursive function, we could have cyclical data structures. To handle cyclical data structures we could track the actual objects visited in a set, but not all objects are hashable. Instead we just track the depth of the object inspections and don't go too deep. Therefore, convert_instances=True is lossy ... be aware. """ # handle obvious types first - order of basic types determined by running # full tests on nova project, resulting in the following counts: # 572754 <type 'NoneType'> # 460353 <type 'int'> # 379632 <type 'unicode'> # 274610 <type 'str'> # 199918 <type 'dict'> # 114200 <type 'datetime.datetime'> # 51817 <type 'bool'> # 26164 <type 'list'> # 6491 <type 'float'> # 283 <type 'tuple'> # 19 <type 'long'> if isinstance(value, _simple_types): return value if isinstance(value, datetime.datetime): if convert_datetime: return timeutils.strtime(value) else: return value # value of itertools.count doesn't get caught by nasty_type_tests # and results in infinite loop when list(value) is called. if type(value) == itertools.count: return six.text_type(value) # FIXME(vish): Workaround for LP bug 852095. Without this workaround, # tests that raise an exception in a mocked method that # has a @wrap_exception with a notifier will fail. If # we up the dependency to 0.5.4 (when it is released) we # can remove this workaround. if getattr(value, '__module__', None) == 'mox': return 'mock' if level > max_depth: return '?' # The try block may not be necessary after the class check above, # but just in case ... try: recursive = functools.partial(to_primitive, convert_instances=convert_instances, convert_datetime=convert_datetime, level=level, max_depth=max_depth) if isinstance(value, dict): return dict((k, recursive(v)) for k, v in six.iteritems(value)) elif isinstance(value, (list, tuple)): return [recursive(lv) for lv in value] # It's not clear why xmlrpclib created their own DateTime type, but # for our purposes, make it a datetime type which is explicitly # handled if isinstance(value, xmlrpclib.DateTime): value = datetime.datetime(*tuple(value.timetuple())[:6]) if convert_datetime and isinstance(value, datetime.datetime): return timeutils.strtime(value) elif isinstance(value, gettextutils.Message): return value.data elif hasattr(value, 'iteritems'): return recursive(dict(value.iteritems()), level=level + 1) elif hasattr(value, '__iter__'): return recursive(list(value)) elif convert_instances and hasattr(value, '__dict__'): # Likely an instance of something. Watch for cycles. # Ignore class member vars. return recursive(value.__dict__, level=level + 1) elif netaddr and isinstance(value, netaddr.IPAddress): return six.text_type(value) else: if any(test(value) for test in _nasty_type_tests): return six.text_type(value) return value except TypeError: # Class objects are tricky since they may define something like # __iter__ defined but it isn't callable as list(). return six.text_type(value)
def to_primitive(value, convert_instances=False, level=0): """Convert a complex object into primitives. Handy for JSON serialization. We can optionally handle instances, but since this is a recursive function, we could have cyclical data structures. To handle cyclical data structures we could track the actual objects visited in a set, but not all objects are hashable. Instead we just track the depth of the object inspections and don't go too deep. Therefore, convert_instances=True is lossy ... be aware. """ nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod, inspect.isfunction, inspect.isgeneratorfunction, inspect.isgenerator, inspect.istraceback, inspect.isframe, inspect.iscode, inspect.isbuiltin, inspect.isroutine, inspect.isabstract] for test in nasty: if test(value): return unicode(value) # value of itertools.count doesn't get caught by inspects # above and results in infinite loop when list(value) is called. if type(value) == itertools.count: return unicode(value) # FIXME(vish): Workaround for LP bug 852095. Without this workaround, # tests that raise an exception in a mocked method that # has a @wrap_exception with a notifier will fail. If # we up the dependency to 0.5.4 (when it is released) we # can remove this workaround. if getattr(value, '__module__', None) == 'mox': return 'mock' if level > 3: return '?' # The try block may not be necessary after the class check above, # but just in case ... try: # It's not clear why xmlrpclib created their own DateTime type, but # for our purposes, make it a datetime type which is explicitly # handled if isinstance(value, xmlrpclib.DateTime): value = datetime.datetime(*tuple(value.timetuple())[:6]) if isinstance(value, (list, tuple)): o = [] for v in value: o.append(to_primitive(v, convert_instances=convert_instances, level=level)) return o elif isinstance(value, dict): o = {} for k, v in value.iteritems(): o[k] = to_primitive(v, convert_instances=convert_instances, level=level) return o elif isinstance(value, datetime.datetime): return timeutils.strtime(value) elif hasattr(value, 'iteritems'): return to_primitive(dict(value.iteritems()), convert_instances=convert_instances, level=level) elif hasattr(value, '__iter__'): return to_primitive(list(value), level) elif convert_instances and hasattr(value, '__dict__'): # Likely an instance of something. Watch for cycles. # Ignore class member vars. return to_primitive(value.__dict__, convert_instances=convert_instances, level=level + 1) else: return value except TypeError, e: # Class objects are tricky since they may define something like # __iter__ defined but it isn't callable as list(). return unicode(value)
def test_scaling_policy_update(self): t = template_format.parse(as_template) stack = utils.parse_stack(t, params=self.params) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, "ExactCapacity : 1") self._stub_create(1) self.m.StubOutWithMock(asc.ScalingPolicy, "keystone") asc.ScalingPolicy.keystone().MultipleTimes().AndReturn(self.fc) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, "WebServerGroup") stack.resources["WebServerGroup"] = rsrc self.assertEqual(["WebServerGroup-0"], rsrc.get_instance_names()) # Create initial scaling policy up_policy = self.create_scaling_policy(t, stack, "WebServerScaleUpPolicy") # Scale up one self._stub_lb_reload(2) self._stub_meta_expected(now, "ChangeInCapacity : 1", 2) self._stub_create(1) self.m.ReplayAll() # Trigger alarm up_policy.signal() self.assertEqual(["WebServerGroup-0", "WebServerGroup-1"], rsrc.get_instance_names()) # Update scaling policy update_snippet = copy.deepcopy(up_policy.parsed_template()) update_snippet["Properties"]["ScalingAdjustment"] = "2" self.assertEqual(None, up_policy.update(update_snippet)) self.assertEqual("2", up_policy.properties["ScalingAdjustment"]) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): "ChangeInCapacity : 1"} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, "__get__") Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg()).AndReturn(previous_meta) # stub for the metadata accesses while creating the two instances Metadata.__get__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) Metadata.__get__(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload(4, unset=False) self._stub_meta_expected(now, "ChangeInCapacity : 2", 2) self._stub_create(2) self.m.ReplayAll() # Trigger alarm up_policy.signal() self.assertEqual( ["WebServerGroup-0", "WebServerGroup-1", "WebServerGroup-2", "WebServerGroup-3"], rsrc.get_instance_names() ) rsrc.delete() self.m.VerifyAll()
def test_scaling_policy_update(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group self._stub_lb_reload(1) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual('WebServerGroup-0', rsrc.resource_id) # Create initial scaling policy up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') # Scale up one self._stub_lb_reload(2) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() # Trigger alarm up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) # Update scaling policy update_snippet = copy.deepcopy(up_policy.parsed_template()) update_snippet['Properties']['ScalingAdjustment'] = '2' self.assertEqual(None, up_policy.update(update_snippet)) self.assertEqual('2', up_policy.properties['ScalingAdjustment']) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() ).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg() ).AndReturn(previous_meta) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload(4, unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 2', 2) self._stub_create(2) self.m.ReplayAll() # Trigger alarm up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1,' 'WebServerGroup-2,WebServerGroup-3', rsrc.resource_id) rsrc.delete() self.m.VerifyAll()
def to_primitive(value, convert_instances=False, level=0): """Convert a complex object into primitives. Handy for JSON serialization. We can optionally handle instances, but since this is a recursive function, we could have cyclical data structures. To handle cyclical data structures we could track the actual objects visited in a set, but not all objects are hashable. Instead we just track the depth of the object inspections and don't go too deep. Therefore, convert_instances=True is lossy ... be aware. """ nasty = [ inspect.ismodule, inspect.isclass, inspect.ismethod, inspect.isfunction, inspect.isgeneratorfunction, inspect.isgenerator, inspect.istraceback, inspect.isframe, inspect.iscode, inspect.isbuiltin, inspect.isroutine, inspect.isabstract ] for test in nasty: if test(value): return unicode(value) # value of itertools.count doesn't get caught by inspects # above and results in infinite loop when list(value) is called. if type(value) == itertools.count: return unicode(value) # FIXME(vish): Workaround for LP bug 852095. Without this workaround, # tests that raise an exception in a mocked method that # has a @wrap_exception with a notifier will fail. If # we up the dependency to 0.5.4 (when it is released) we # can remove this workaround. if getattr(value, '__module__', None) == 'mox': return 'mock' if level > 3: return '?' # The try block may not be necessary after the class check above, # but just in case ... try: # It's not clear why xmlrpclib created their own DateTime type, but # for our purposes, make it a datetime type which is explicitly # handled if isinstance(value, xmlrpclib.DateTime): value = datetime.datetime(*tuple(value.timetuple())[:6]) if isinstance(value, (list, tuple)): o = [] for v in value: o.append( to_primitive(v, convert_instances=convert_instances, level=level)) return o elif isinstance(value, dict): o = {} for k, v in value.iteritems(): o[k] = to_primitive(v, convert_instances=convert_instances, level=level) return o elif isinstance(value, datetime.datetime): return timeutils.strtime(value) elif hasattr(value, 'iteritems'): return to_primitive(dict(value.iteritems()), convert_instances=convert_instances, level=level + 1) elif hasattr(value, '__iter__'): return to_primitive(list(value), convert_instances=convert_instances, level=level) elif convert_instances and hasattr(value, '__dict__'): # Likely an instance of something. Watch for cycles. # Ignore class member vars. return to_primitive(value.__dict__, convert_instances=convert_instances, level=level + 1) else: return value except TypeError, e: # Class objects are tricky since they may define something like # __iter__ defined but it isn't callable as list(). return unicode(value)
def test_scaling_policy_update(self): t = template_format.parse(as_template) stack = parse_stack(t) # Create initial group self._stub_lb_reload(['WebServerGroup-0']) now = timeutils.utcnow() self._stub_meta_expected(now, 'ExactCapacity : 1') self._stub_create(1) self.m.ReplayAll() rsrc = self.create_scaling_group(t, stack, 'WebServerGroup') stack.resources['WebServerGroup'] = rsrc self.assertEqual('WebServerGroup-0', rsrc.resource_id) # Create initial scaling policy up_policy = self.create_scaling_policy(t, stack, 'WebServerScaleUpPolicy') # Scale up one self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) self._stub_create(1) self.m.ReplayAll() # Trigger alarm up_policy.alarm() self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id) # Update scaling policy update_snippet = copy.deepcopy(up_policy.parsed_template()) update_snippet['Properties']['ScalingAdjustment'] = '2' self.assertEqual(None, up_policy.update(update_snippet)) self.assertEqual('2', up_policy.properties['ScalingAdjustment']) # Now move time on 61 seconds - Cooldown in template is 60 # so this should trigger a scale-up previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} self.m.VerifyAll() self.m.UnsetStubs() self.m.StubOutWithMock(Metadata, '__get__') Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg()).AndReturn(previous_meta) Metadata.__get__(mox.IgnoreArg(), rsrc, mox.IgnoreArg()).AndReturn(previous_meta) now = now + datetime.timedelta(seconds=61) self._stub_lb_reload([ 'WebServerGroup-0', 'WebServerGroup-1', 'WebServerGroup-2', 'WebServerGroup-3' ], unset=False) self._stub_meta_expected(now, 'ChangeInCapacity : 2', 2) self._stub_create(2) self.m.ReplayAll() # Trigger alarm up_policy.alarm() self.assertEqual( 'WebServerGroup-0,WebServerGroup-1,' 'WebServerGroup-2,WebServerGroup-3', rsrc.resource_id) rsrc.delete() self.m.VerifyAll()