예제 #1
0
    def _assemble_for_rolling_update(
        self, total_capacity, max_updates, include_all=False, template_version=("heat_template_version", "2015-04-30")
    ):
        names = list(self._resource_names(total_capacity))
        name_blacklist = self._name_blacklist()

        valid_resources = [(n, d) for n, d in grouputils.get_member_definitions(self) if n not in name_blacklist]

        targ_cap = self.get_size()

        def replace_priority(res_item):
            name, defn = res_item
            try:
                index = names.index(name)
            except ValueError:
                # High priority - delete immediately
                return 0
            else:
                if index < targ_cap:
                    # Update higher indices first
                    return targ_cap - index
                else:
                    # Low priority - don't update
                    return total_capacity

        old_resources = sorted(valid_resources, key=replace_priority)
        existing_names = set(n for n, d in valid_resources)
        new_names = six.moves.filterfalse(lambda n: n in existing_names, names)
        res_def = self.get_resource_def(include_all)
        definitions = scl_template.member_definitions(
            old_resources, res_def, total_capacity, max_updates, lambda: next(new_names), self.build_resource_definition
        )
        return scl_template.make_template(definitions, version=template_version)
예제 #2
0
    def _create_template(self,
                         num_instances,
                         num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """
        Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = self._get_instance_templates()
        definitions = template.member_definitions(old_resources,
                                                  instance_definition,
                                                  num_instances, num_replace,
                                                  short_id.generate_id)

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(),
            item_to_remove=self.resource_info)

        return template.make_template(definitions,
                                      version=template_version,
                                      child_env=child_env)
예제 #3
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func, res_func = 'get_attr', 'get_resource'
        if att_func not in tmpl.functions or res_func not in tmpl.functions:
            att_func, res_func = 'Fn::GetAtt', 'Ref'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        get_res = functools.partial(tmpl.functions[res_func], None, res_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr, get_res):
            tmpl.add_output(odefn)

        return tmpl
예제 #4
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func = 'get_attr'
        if att_func not in tmpl.functions:
            att_func = 'Fn::GetAtt'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr):
            tmpl.add_output(odefn)

        return tmpl
 def test_create_template(self):
     """
     When creating a template from scratch, an empty list is accepted as
     the "old" resources and new resources are created up to num_resource.
     """
     templates = template.member_definitions([], {'type': 'Foo'}, 2, 0,
                                             self.next_id)
     expected = [
         ('stubbed-id-0', {'type': 'Foo'}),
         ('stubbed-id-1', {'type': 'Foo'})]
     self.assertEqual(expected, list(templates))
 def test_replace_template(self):
     """
     If num_replace is the number of old resources, then all of the
     resources will be replaced.
     """
     old_resources = [
         ('old-id-0', {'type': 'Foo'}),
         ('old-id-1', {'type': 'Foo'})]
     templates = template.member_definitions(old_resources, {'type': 'Bar'},
                                             1, 2, self.next_id)
     expected = [('old-id-1', {'type': 'Bar'})]
     self.assertEqual(expected, list(templates))
 def test_replace_some_units(self):
     """
     If the resource definition changes, only the number of replacements
     specified will be made; beyond that, the original templates are used.
     """
     old_resources = [
         ('old-id-0', {'type': 'Foo'}),
         ('old-id-1', {'type': 'Foo'})]
     new_spec = {'type': 'Bar'}
     templates = template.member_definitions(old_resources, new_spec, 2, 1,
                                             self.next_id)
     expected = [
         ('old-id-0', {'type': 'Bar'}),
         ('old-id-1', {'type': 'Foo'})]
     self.assertEqual(expected, list(templates))
 def test_replace_units_some_already_up_to_date(self):
     """
     If some of the old resources already have the new resource definition,
     then they won't be considered for replacement, and the next resource
     that is out-of-date will be replaced.
     """
     old_resources = [
         ('old-id-0', {'type': 'Bar'}),
         ('old-id-1', {'type': 'Foo'})]
     new_spec = {'type': 'Bar'}
     templates = template.member_definitions(old_resources, new_spec, 2, 1,
                                             self.next_id)
     second_batch_expected = [
         ('old-id-0', {'type': 'Bar'}),
         ('old-id-1', {'type': 'Bar'})]
     self.assertEqual(second_batch_expected, list(templates))
예제 #9
0
    def _create_template(
        self, num_instances, num_replace=0, template_version=("HeatTemplateFormatVersion", "2012-12-12")
    ):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self, include_failed=True)
        definitions = template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace, short_id.generate_id
        )

        child_env = environment.get_child_environment(
            self.stack.env, self.child_params(), item_to_remove=self.resource_info
        )

        return template.make_template(definitions, version=template_version, child_env=child_env)
예제 #10
0
    def _assemble_for_rolling_update(self, total_capacity, max_updates,
                                     include_all=False,
                                     template_version=('heat_template_version',
                                                       '2015-04-30')):
        names = list(self._resource_names(total_capacity))
        name_blacklist = self._name_blacklist()

        valid_resources = [(n, d) for n, d in
                           grouputils.get_member_definitions(self)
                           if n not in name_blacklist]

        targ_cap = self.get_size()

        def replace_priority(res_item):
            name, defn = res_item
            try:
                index = names.index(name)
            except ValueError:
                # High priority - delete immediately
                return 0
            else:
                if index < targ_cap:
                    # Update higher indices first
                    return targ_cap - index
                else:
                    # Low priority - don't update
                    return total_capacity

        old_resources = sorted(valid_resources, key=replace_priority)
        existing_names = set(n for n, d in valid_resources)
        new_names = six.moves.filterfalse(lambda n: n in existing_names,
                                          names)
        res_def = self.get_resource_def(include_all)
        definitions = scl_template.member_definitions(
            old_resources, res_def,
            total_capacity,
            max_updates,
            lambda: next(new_names),
            self.build_resource_definition)
        tmpl = scl_template.make_template(definitions,
                                          version=template_version)
        self._add_output_defns_to_template(tmpl, names)
        return tmpl
 def test_growth_counts_as_replacement(self):
     """
     If we grow the template and replace some elements at the same time, the
     number of replacements to perform is reduced by the number of new
     resources to be created.
     """
     spec = {'type': 'Foo'}
     old_resources = [
         ('old-id-0', spec),
         ('old-id-1', spec)]
     new_spec = {'type': 'Bar'}
     templates = template.member_definitions(old_resources, new_spec, 4, 2,
                                             self.next_id)
     expected = [
         ('old-id-0', spec),
         ('old-id-1', spec),
         ('stubbed-id-0', new_spec),
         ('stubbed-id-1', new_spec)]
     self.assertEqual(expected, list(templates))
예제 #12
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        # WRS: Detect a scale down.  Issue a vote
        # If any vote is rejected, set new_resources to be same size as old
        existing = grouputils.get_members(self)
        if num_instances < len(existing):
            LOG.info("WRS downscale detected, vote initiated")
            for i in range(num_instances, len(existing)):
                if existing[i].wrs_vote() is False:
                    LOG.info("WRS downscale blocked by vote")
                    num_instances = len(existing)
                    break

        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id, delete_oldest=False))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func = 'get_attr'
        if att_func not in tmpl.functions:
            att_func = 'Fn::GetAtt'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr):
            tmpl.add_output(odefn)

        return tmpl
예제 #13
0
    def _assemble_for_rolling_update(self, total_capacity, max_updates,
                                     include_all=False):
        names = list(self._resource_names(total_capacity))
        name_blacklist = self._name_blacklist()

        valid_resources = [(n, d) for n, d in self._get_resources()
                           if n not in name_blacklist]

        targ_cap = self.get_size()

        def replace_priority(res_item):
            name, defn = res_item
            try:
                index = names.index(name)
            except ValueError:
                # High priority - delete immediately
                return 0
            else:
                if index < targ_cap:
                    # Update higher indices first
                    return targ_cap - index
                else:
                    # Low priority - don't update
                    return total_capacity

        old_resources = sorted(valid_resources, key=replace_priority)

        existing_names = set(n for n, d in valid_resources)
        new_names = six.moves.filterfalse(lambda n: n in existing_names,
                                          names)

        res_def = self._build_resource_definition(include_all)
        resources = scale_template.member_definitions(old_resources, res_def,
                                                      total_capacity,
                                                      max_updates,
                                                      lambda: next(new_names),
                                                      self._do_prop_replace)

        child_template = copy.deepcopy(template_template)
        child_template['resources'] = dict(resources)
        return child_template
예제 #14
0
    def _assemble_for_rolling_update(self, total_capacity, max_updates,
                                     include_all=False):
        names = list(self._resource_names(total_capacity))
        name_blacklist = self._name_blacklist()

        valid_resources = [(n, d) for n, d in self._get_resources()
                           if n not in name_blacklist]

        num_creating = max(total_capacity - len(valid_resources), 0)
        new_names = iter(names[total_capacity - num_creating:])
        targ_cap = self.get_size()

        def replace_priority(res_item):
            name, defn = res_item
            try:
                index = names.index(name)
            except ValueError:
                # High priority - delete immediately
                return 0
            else:
                if index < targ_cap:
                    # Update higher indices first
                    return targ_cap - index
                else:
                    # Low priority - don't update
                    return total_capacity

        old_resources = sorted(valid_resources, key=replace_priority)

        res_def = self._build_resource_definition(include_all)
        resources = scale_template.member_definitions(old_resources, res_def,
                                                      total_capacity,
                                                      max_updates,
                                                      lambda: next(new_names),
                                                      self._do_prop_replace)

        child_template = copy.deepcopy(template_template)
        child_template['resources'] = dict(resources)
        return child_template