from heat.common import exception
from heat.engine import resource
from heat.engine import signal_responder
-from heat.engine import scheduler
from heat.openstack.common import log as logging
from heat.openstack.common import timeutils
from heat.engine.properties import Properties
+from heat.engine import stack_resource
logger = logging.getLogger(__name__)
self.metadata = metadata
-class InstanceGroup(resource.Resource):
+class InstanceGroup(stack_resource.StackResource):
tags_schema = {'Key': {'Type': 'String',
'Required': True},
'Value': {'Type': 'String',
"(Heat extension)")
}
- def handle_create(self):
- return self.resize(int(self.properties['Size']), raise_on_error=True)
+ def get_instance_names(self):
+ """Get a list of resource names of the instances in this InstanceGroup.
+
+ Deleted resources will be ignored.
+ """
+ return sorted(x.name for x in self.get_instances())
- def check_create_complete(self, creator):
- if creator is None:
- return True
+ def get_instances(self):
+ """Get a set of all the instance resources managed by this group."""
+ return [resource for resource in self.nested()
+ if resource.state[0] != resource.DELETE]
+
+ def handle_create(self):
+ """Create a nested stack and add the initial resources to it."""
+ num_instances = int(self.properties['Size'])
+ initial_template = self._create_template(num_instances)
+ return self.create_with_template(initial_template, {})
- return creator.step()
+ def check_create_complete(self, task):
+ """
+ When stack creation is done, update the load balancer.
- def _wait_for_activation(self, creator):
- if creator is not None:
- creator.run_to_completion()
+ If any instances failed to be created, delete them.
+ """
+ try:
+ done = super(InstanceGroup, self).check_create_complete(task)
+ except exception.Error as exc:
+ for resource in self.nested():
+ if resource.state == ('CREATE', 'FAILED'):
+ resource.destroy()
+ raise
+ if done and len(self.get_instances()):
+ self._lb_reload()
+ return done
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
- # If Properties has changed, update self.properties, so we
- # get the new values during any subsequent adjustment
+ """
+ If Properties has changed, update self.properties, so we
+ get the new values during any subsequent adjustment.
+ """
if prop_diff:
self.properties = Properties(self.properties_schema,
json_snippet.get('Properties', {}),
# Get the current capacity, we may need to adjust if
# Size has changed
if 'Size' in prop_diff:
- inst_list = []
- if self.resource_id is not None:
- inst_list = sorted(self.resource_id.split(','))
-
+ inst_list = self.get_instances()
if len(inst_list) != int(self.properties['Size']):
- creator = self.resize(int(self.properties['Size']),
- raise_on_error=True)
- self._wait_for_activation(creator)
-
- def _make_instance(self, name):
- # We look up and subclass the class for AWS::EC2::Instance instead of
- # just importing Instance, so that if someone overrides that resource
- # we'll use the custom one.
- Instance = resource.get_class('AWS::EC2::Instance',
- resource_name=name,
- environment=self.stack.env)
-
- class GroupedInstance(Instance):
- '''
- Subclass Instance to suppress event transitions, since the
- scaling-group instances are not "real" resources, ie defined in the
- template, which causes problems for event handling since we can't
- look up the resources via parser.Stack
- '''
- def state_set(self, action, status, reason="state changed"):
- self._store_or_update(action, status, reason)
-
- conf = self.properties['LaunchConfigurationName']
- instance_definition = self.stack.t['Resources'][conf]
-
- # honour the Tags property in the InstanceGroup and AutoScalingGroup
- instance_definition['Properties']['Tags'] = self._tags()
- return GroupedInstance(name, instance_definition, self.stack)
+ self.resize(int(self.properties['Size']))
def _tags(self):
"""
return tags + [{'Key': 'metering.groupname',
'Value': self.FnGetRefId()}]
- def _instances(self):
- '''
- Convert the stored instance list into a list of GroupedInstance objects
- '''
- gi_list = []
- if self.resource_id is not None:
- inst_list = self.resource_id.split(',')
- for i in inst_list:
- gi_list.append(self._make_instance(i))
- return gi_list
-
def handle_delete(self):
- for inst in self._instances():
- logger.debug('handle_delete %s' % inst.name)
- inst.destroy()
-
- def handle_suspend(self):
- cookie_list = []
- for inst in self._instances():
- logger.debug('handle_suspend %s' % inst.name)
- inst_cookie = inst.handle_suspend()
- cookie_list.append((inst, inst_cookie))
- return cookie_list
-
- def check_suspend_complete(self, cookie_list):
- for inst, inst_cookie in cookie_list:
- if not inst.check_suspend_complete(inst_cookie):
- return False
- return True
-
- def handle_resume(self):
- cookie_list = []
- for inst in self._instances():
- logger.debug('handle_resume %s' % inst.name)
- inst_cookie = inst.handle_resume()
- cookie_list.append((inst, inst_cookie))
- return cookie_list
-
- def check_resume_complete(self, cookie_list):
- for inst, inst_cookie in cookie_list:
- if not inst.check_resume_complete(inst_cookie):
- return False
- return True
-
- @scheduler.wrappertask
- def _scale(self, instance_task, indices):
- group = scheduler.PollingTaskGroup.from_task_with_args(instance_task,
- indices)
- yield group()
-
- # When all instance tasks are complete, reload the LB config
- self._lb_reload()
+ return self.delete_nested()
- def resize(self, new_capacity, raise_on_error=False):
- inst_list = []
- if self.resource_id is not None:
- inst_list = sorted(self.resource_id.split(','))
+ def _create_template(self, num_instances):
+ """
+ Create a template with a number of instance definitions based on the
+ launch configuration.
+ """
+ conf_name = self.properties['LaunchConfigurationName']
+ instance_definition = self.stack.t['Resources'][conf_name].copy()
+ instance_definition['Type'] = 'AWS::EC2::Instance'
+ instance_definition['Properties']['Tags'] = self._tags()
+ resources = {}
+ for i in range(num_instances):
+ resources["%s-%d" % (self.name, i)] = instance_definition
+ return {"Resources": resources}
- capacity = len(inst_list)
- if new_capacity == capacity:
- logger.debug('no change in capacity %d' % capacity)
- return
- logger.debug('adjusting capacity from %d to %d' % (capacity,
- new_capacity))
-
- @scheduler.wrappertask
- def create_instance(index):
- name = '%s-%d' % (self.name, index)
- inst = self._make_instance(name)
-
- logger.debug('Creating %s instance %d' % (str(self), index))
-
- try:
- yield inst.create()
- except exception.ResourceFailure as ex:
- if raise_on_error:
- raise
- # Handle instance creation failure locally by destroying the
- # failed instance to avoid orphaned instances costing user
- # extra memory
- logger.warn('Creating %s instance %d failed %s, destroying'
- % (str(self), index, str(ex)))
- inst.destroy()
- else:
- inst_list.append(name)
- self.resource_id_set(','.join(inst_list))
-
- if new_capacity > capacity:
- # grow
- creator = scheduler.TaskRunner(self._scale,
- create_instance,
- xrange(capacity, new_capacity))
- creator.start()
- return creator
- else:
- # shrink (kill largest numbered first)
- del_list = inst_list[new_capacity:]
- for victim in reversed(del_list):
- inst = self._make_instance(victim)
- inst.destroy()
- inst_list.remove(victim)
- # If we shrink to zero, set resource_id back to None
- self.resource_id_set(','.join(inst_list) or None)
+ def resize(self, new_capacity):
+ """
+ Resize the instance group to the new capacity.
- self._lb_reload()
+ When shrinking, the newest instances will be removed.
+ """
+ new_template = self._create_template(new_capacity)
+ result = self.update_with_template(new_template, {})
+ for resource in self.nested():
+ if resource.state == ('CREATE', 'FAILED'):
+ resource.destroy()
+ self._lb_reload()
+ return result
def _lb_reload(self):
'''
- Notify the LoadBalancer to reload it's config to include
+ 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.
'''
if self.properties['LoadBalancerNames']:
- inst_list = []
- if self.resource_id is not None:
- inst_list = sorted(self.resource_id.split(','))
- # convert the list of instance names into a list of instance id's
- id_list = []
- for inst_name in inst_list:
- inst = self._make_instance(inst_name)
- id_list.append(inst.FnGetRefId())
-
+ id_list = [inst.FnGetRefId() for inst in self.get_instances()]
for lb in self.properties['LoadBalancerNames']:
self.stack[lb].json_snippet['Properties']['Instances'] = \
id_list
ip addresses.
'''
if name == 'InstanceList':
- if self.resource_id is None:
- return None
- name_list = sorted(self.resource_id.split(','))
- inst_list = []
- for name in name_list:
- inst = self._make_instance(name)
- inst_list.append(inst.FnGetAtt('PublicIp'))
- return unicode(','.join(inst_list))
+ ips = [inst.FnGetAtt('PublicIp')
+ for inst in self._nested.resources.values()]
+ if ips:
+ return unicode(','.join(ips))
class AutoScalingGroup(InstanceGroup, CooldownMixin):
num_to_create = int(self.properties['DesiredCapacity'])
else:
num_to_create = int(self.properties['MinSize'])
+ initial_template = self._create_template(num_to_create)
+ return self.create_with_template(initial_template, {})
- return self._adjust(num_to_create)
+ def check_create_complete(self, task):
+ """Invoke the cooldown after creation succeeds."""
+ done = super(AutoScalingGroup, self).check_create_complete(task)
+ if done:
+ self._cooldown_timestamp(
+ "%s : %s" % ('ExactCapacity', len(self.get_instances())))
+ return done
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
- # If Properties has changed, update self.properties, so we
- # get the new values during any subsequent adjustment
+ """
+ If Properties has changed, update self.properties, so we get the new
+ values during any subsequent adjustment.
+ """
if prop_diff:
self.properties = Properties(self.properties_schema,
json_snippet.get('Properties', {}),
# Get the current capacity, we may need to adjust if
# MinSize or MaxSize has changed
- inst_list = []
- if self.resource_id is not None:
- inst_list = sorted(self.resource_id.split(','))
-
- capacity = len(inst_list)
+ capacity = len(self.get_instances())
# Figure out if an adjustment is required
new_capacity = None
if capacity > int(self.properties['MaxSize']):
new_capacity = int(self.properties['MaxSize'])
if 'DesiredCapacity' in prop_diff:
- if self.properties['DesiredCapacity']:
- new_capacity = int(self.properties['DesiredCapacity'])
+ if self.properties['DesiredCapacity']:
+ new_capacity = int(self.properties['DesiredCapacity'])
if new_capacity is not None:
- creator = self._adjust(new_capacity)
- self._wait_for_activation(creator)
+ self.adjust(new_capacity, adjustment_type='ExactCapacity')
def adjust(self, adjustment, adjustment_type='ChangeInCapacity'):
- creator = self._adjust(adjustment, adjustment_type, False)
- self._wait_for_activation(creator)
-
- def _adjust(self, adjustment, adjustment_type='ExactCapacity',
- raise_on_error=True):
-
+ """
+ Adjust the size of the scaling group if the cooldown permits.
+ """
if self._cooldown_inprogress():
logger.info("%s NOT performing scaling adjustment, cooldown %s" %
(self.name, self.properties['Cooldown']))
return
- inst_list = []
- if self.resource_id is not None:
- inst_list = sorted(self.resource_id.split(','))
-
- capacity = len(inst_list)
+ capacity = len(self.get_instances())
if adjustment_type == 'ChangeInCapacity':
new_capacity = capacity + adjustment
elif adjustment_type == 'ExactCapacity':
logger.debug('no change in capacity %d' % capacity)
return
- result = self.resize(new_capacity, raise_on_error=raise_on_error)
+ result = self.resize(new_capacity)
self._cooldown_timestamp("%s : %s" % (adjustment_type, adjustment))
}
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
- # If Properties has changed, update self.properties, so we
- # get the new values during any subsequent adjustment
+ """
+ If Properties has changed, update self.properties, so we get the new
+ values during any subsequent adjustment.
+ """
if prop_diff:
self.properties = Properties(self.properties_schema,
json_snippet.get('Properties', {}),
now = timeutils.utcnow()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual(None, rsrc.resource_id)
+ self.assertEqual(None, rsrc.FnGetAtt("InstanceList"))
rsrc.delete()
self.m.VerifyAll()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
+
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Reduce the min size to 0, should complete without adjusting
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['MinSize'] = '0'
self.assertEqual(None, rsrc.update(update_snippet))
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
- # trigger adjustment to reduce to 0, resource_id should be None
+ # trigger adjustment to reduce to 0, there should be no more instances
self._stub_lb_reload(0)
self._stub_meta_expected(now, 'ChangeInCapacity : -1')
self.m.ReplayAll()
rsrc.adjust(-1)
- self.assertEqual(None, rsrc.resource_id)
+ self.assertEqual([], rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['LaunchConfigurationName'] = 'foo'
self.assertRaises(resource.UpdateReplace,
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
self.m.ReplayAll()
rsrc.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
+ for i in rsrc.nested().resources.values():
+ i.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
scheduler.TaskRunner(rsrc.resume)()
self.assertEqual(rsrc.state, (rsrc.RESUME, rsrc.COMPLETE))
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0,WebServerGroup-1', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
self.m.ReplayAll()
rsrc.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
+ for i in rsrc.nested().resources.values():
+ i.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
scheduler.TaskRunner(rsrc.resume)()
self.assertEqual(rsrc.state, (rsrc.RESUME, rsrc.COMPLETE))
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
sus_task = scheduler.TaskRunner(rsrc.suspend)
self.assertRaises(exception.ResourceFailure, sus_task, ())
self.assertEqual(rsrc.state, (rsrc.SUSPEND, rsrc.FAILED))
- self.assertEqual(rsrc.status_reason, 'Exception: oops')
+ self.assertEqual(rsrc.status_reason,
+ 'Error: Resource suspend failed: Exception: oops')
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.assertEqual(rsrc.state, (rsrc.CREATE, rsrc.COMPLETE))
self.m.VerifyAll()
self.m.ReplayAll()
rsrc.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
+ for i in rsrc.nested().resources.values():
+ i.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
sus_task = scheduler.TaskRunner(rsrc.resume)
self.assertRaises(exception.ResourceFailure, sus_task, ())
self.assertEqual(rsrc.state, (rsrc.RESUME, rsrc.FAILED))
- self.assertEqual(rsrc.status_reason, 'Exception: oops')
+ self.assertEqual(rsrc.status_reason,
+ 'Error: Resource resume failed: Exception: oops')
rsrc.delete()
self.m.VerifyAll()
scheduler.TaskRunner(rsrc.create))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
- self.assertEqual(None, rsrc.resource_id)
+ self.assertEqual([], rsrc.get_instance_names())
self.m.VerifyAll()
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Reduce the max size to 2, should complete without adjusting
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['MaxSize'] = '2'
self.assertEqual(None, rsrc.update(update_snippet))
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.assertEqual('2', rsrc.properties['MaxSize'])
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Increase min size to 2, should trigger an ExactCapacity adjust
self._stub_lb_reload(2)
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['MinSize'] = '2'
self.assertEqual(None, rsrc.update(update_snippet))
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.assertEqual('2', rsrc.properties['MinSize'])
rsrc.delete()
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Increase min size to 2 via DesiredCapacity, should adjust
self._stub_lb_reload(2)
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['DesiredCapacity'] = '2'
self.assertEqual(None, rsrc.update(update_snippet))
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.assertEqual('2', rsrc.properties['DesiredCapacity'])
self._stub_create(2)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# Remove DesiredCapacity from the updated template, which should
# have no effect, it's an optional parameter
update_snippet = copy.deepcopy(rsrc.parsed_template())
del(update_snippet['Properties']['DesiredCapacity'])
self.assertEqual(None, rsrc.update(update_snippet))
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.assertEqual(None, rsrc.properties['DesiredCapacity'])
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['Cooldown'] = '61'
self.assertEqual(None, rsrc.update(update_snippet))
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual('WebServerGroup', rsrc.FnGetRefId())
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
update_snippet = copy.deepcopy(rsrc.parsed_template())
update_snippet['Properties']['Cooldown'] = '61'
self.assertEqual(None, rsrc.update(update_snippet))
self._stub_create(3)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
# reduce to 1
self._stub_lb_reload(1)
self._stub_meta_expected(now, 'ChangeInCapacity : -2')
self.m.ReplayAll()
rsrc.adjust(-2)
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# raise to 3
self._stub_lb_reload(3)
self._stub_create(2)
self.m.ReplayAll()
rsrc.adjust(2)
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
# set to 2
self._stub_lb_reload(2)
self._stub_meta_expected(now, 'ExactCapacity : 2')
self.m.ReplayAll()
rsrc.adjust(2, 'ExactCapacity')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
self.m.VerifyAll()
def test_scaling_group_scale_up_failure(self):
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.m.VerifyAll()
self.m.UnsetStubs()
# Scale up one 1 instance with resource failure
self.m.StubOutWithMock(instance.Instance, 'handle_create')
instance.Instance.handle_create().AndRaise(Exception)
- self.m.StubOutWithMock(instance.Instance, 'destroy')
- instance.Instance.destroy()
self._stub_lb_reload(1, unset=False, nochange=True)
self.m.ReplayAll()
rsrc.adjust(1)
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# raise above the max
rsrc.adjust(4)
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# lower below the min
rsrc.adjust(-2)
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# no change
rsrc.adjust(0)
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# reduce by 50%
self._stub_lb_reload(1)
self._stub_meta_expected(now, 'PercentChangeInCapacity : -50')
self.m.ReplayAll()
rsrc.adjust(-50, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'],
+ rsrc.get_instance_names())
# raise by 200%
self._stub_lb_reload(3)
self._stub_create(2)
self.m.ReplayAll()
rsrc.adjust(200, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# reduce by 50%
self._stub_lb_reload(1)
self._stub_meta_expected(now, 'PercentChangeInCapacity : -50')
self.m.ReplayAll()
rsrc.adjust(-50, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0',
- rsrc.resource_id)
+ 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
# raise by 200%, too soon for Cooldown so there should be no change
rsrc.adjust(200, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
rsrc.delete()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# reduce by 50%
self._stub_lb_reload(1)
self._stub_meta_expected(now, 'PercentChangeInCapacity : -50')
self.m.ReplayAll()
rsrc.adjust(-50, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0',
- rsrc.resource_id)
+ 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
self._stub_meta_expected(now, 'PercentChangeInCapacity : 200')
self.m.ReplayAll()
rsrc.adjust(200, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# reduce by 50%
self._stub_lb_reload(1)
self._stub_meta_expected(now, 'PercentChangeInCapacity : -50')
self.m.ReplayAll()
rsrc.adjust(-50, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'],
+ rsrc.get_instance_names())
# Don't move time, since cooldown is zero, it should work
previous_meta = {timeutils.strtime(now):
self._stub_create(2)
self.m.ReplayAll()
rsrc.adjust(200, 'PercentChangeInCapacity')
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Scale up one
self._stub_lb_reload(2)
alarm_url = up_policy.FnGetAtt('AlarmUrl')
self.assertNotEqual(None, alarm_url)
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# Scale down one
self._stub_lb_reload(1)
down_policy = self.create_scaling_policy(t, stack,
'WebServerScaleDownPolicy')
down_policy.signal()
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Scale up one
self._stub_lb_reload(2)
up_policy = self.create_scaling_policy(t, stack,
'WebServerScaleUpPolicy')
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ 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
self.m.ReplayAll()
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Scale up one
self._stub_lb_reload(2)
up_policy = self.create_scaling_policy(t, stack,
'WebServerScaleUpPolicy')
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ 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
self.m.ReplayAll()
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Create the scaling policy (with Cooldown=0) and scale up one
properties = t['Resources']['WebServerScaleUpPolicy']['Properties']
up_policy = self.create_scaling_policy(t, stack,
'WebServerScaleUpPolicy')
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ 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.ReplayAll()
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Create the scaling policy no Cooldown property, should behave the
# same as when Cooldown==0
up_policy = self.create_scaling_policy(t, stack,
'WebServerScaleUpPolicy')
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ 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.ReplayAll()
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,WebServerGroup-2',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
stack.resources['WebServerGroup'] = rsrc
- self.assertEqual('WebServerGroup-0', rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
# Create initial scaling policy
up_policy = self.create_scaling_policy(t, stack,
# Trigger alarm
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
+ rsrc.get_instance_names())
# Update scaling policy
update_snippet = copy.deepcopy(up_policy.parsed_template())
# Trigger alarm
up_policy.signal()
- self.assertEqual('WebServerGroup-0,WebServerGroup-1,'
- 'WebServerGroup-2,WebServerGroup-3',
- rsrc.resource_id)
+ self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1',
+ 'WebServerGroup-2', 'WebServerGroup-3'],
+ rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()