Finally works
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/76aa0843 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/76aa0843 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/76aa0843 Branch: refs/heads/ARIA-254-multiple-nodes-per-template Commit: 76aa0843fc872ed759aa3c7282b45c75e576d82b Parents: 334ea74 Author: Tal Liron <tal.li...@gmail.com> Authored: Fri Jun 16 17:27:05 2017 -0500 Committer: Tal Liron <tal.li...@gmail.com> Committed: Fri Jun 16 17:27:32 2017 -0500 ---------------------------------------------------------------------- aria/modeling/service_template.py | 21 +++++---- aria/parser/presentation/fields.py | 4 -- .../profiles/aria-1.0/aria-1.0.yaml | 2 + .../simple_v1_0/modeling/artifacts.py | 4 +- .../simple_v1_0/modeling/capabilities.py | 47 +++++++++++++------- .../simple_v1_0/modeling/interfaces.py | 8 ++-- .../simple_v1_0/modeling/parameters.py | 5 ++- tests/end2end/test_nodecellar.py | 2 +- .../node-cellar/node-cellar.yaml | 38 +++++++++------- .../node-cellar/types/nodejs.yaml | 1 + 10 files changed, 81 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/aria/modeling/service_template.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py index c9c7c6c..633b5bc 100644 --- a/aria/modeling/service_template.py +++ b/aria/modeling/service_template.py @@ -305,7 +305,6 @@ class ServiceTemplateBase(TemplateModelMixin): utils.instantiate_dict(self, service.meta_data, self.meta_data) for node_template in self.node_templates.itervalues(): - print 'scaling', node_template.name, node_template.scaling['default_instances'] for _ in range(node_template.scaling['default_instances']): node = node_template.instantiate(container) service.nodes[node.name] = node @@ -616,12 +615,11 @@ class NodeTemplateBase(TemplateModelMixin): @property def scaling(self): - scaling = { - 'min_instances': 0, - 'max_instances': 1, - 'default_instances': 1} + scaling = {} def extract_property(properties, name): + if name in scaling: + return prop = properties.get(name) if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None): scaling[name] = prop.value @@ -631,21 +629,28 @@ class NodeTemplateBase(TemplateModelMixin): extract_property(properties, 'max_instances') extract_property(properties, 'default_instances') - # TODO: currently finds the first matches capability or policy; but we should emit a - # validation error if more than one applies to the same node + def default_property(name, value): + if name not in scaling: + scaling[name] = value # From our scaling capabilities for capability_template in self.capability_templates.itervalues(): if capability_template.type.role == 'scaling': extract_properties(capability_template.properties) - # From service scaling policies (will override capabilities) + # From service scaling policies for policy_template in self.service_template.policy_templates.itervalues(): if policy_template.type.role == 'scaling': if policy_template.is_for_node_template(self.name): extract_properties(policy_template.properties) + # Defaults + default_property('min_instances', 0) + default_property('max_instances', 1) + default_property('default_instances', 1) + # Validate + # pylint: disable=too-many-boolean-expressions if (scaling['min_instances'] < 0) or \ (scaling['max_instances'] < 0) or \ (scaling['default_instances'] < 0) or \ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/aria/parser/presentation/fields.py ---------------------------------------------------------------------- diff --git a/aria/parser/presentation/fields.py b/aria/parser/presentation/fields.py index 060c576..7f85723 100644 --- a/aria/parser/presentation/fields.py +++ b/aria/parser/presentation/fields.py @@ -680,10 +680,6 @@ class Field(object): # object dict def _get_object_dict(self, presentation, raw, value, context): - if self.cls.__name__ == 'CapabilityAssignment': - print '>>>>>>>>>>p', presentation._name - print '>>>>>>>>>>v', value - print '>>>>>>>>>>r', raw if not isinstance(value, dict): raise InvalidValueError('%s is not a dict: %s' % (self.full_name, safe_repr(value)), locator=self.get_locator(raw)) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml index d7b0c61..e421150 100644 --- a/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml +++ b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml @@ -93,3 +93,5 @@ policy_types: constraints: - greater_or_equal: 0 required: false + targets: + - tosca.nodes.Root http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py index dd9eeb4..b45615a 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py @@ -21,6 +21,8 @@ from aria.utils.collections import OrderedDict # def get_inherited_artifact_definitions(context, presentation, for_presentation=None): + if for_presentation is None: + for_presentation = presentation if hasattr(presentation, '_get_type'): # In NodeTemplate @@ -30,7 +32,7 @@ def get_inherited_artifact_definitions(context, presentation, for_presentation=N parent = presentation._get_parent(context) # Get artifact definitions from parent - artifacts = get_inherited_artifact_definitions(context, parent, for_presentation=presentation) \ + artifacts = get_inherited_artifact_definitions(context, parent, for_presentation) \ if parent is not None else OrderedDict() # Add/override our artifact definitions http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py index e61fc81..bf75f7d 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py @@ -52,12 +52,13 @@ def get_inherited_capability_definitions(context, presentation, for_presentation Allows overriding all aspects of parent capability properties except data type. """ + if for_presentation is None: + for_presentation = presentation + # Get capability definitions from parent parent = presentation._get_parent(context) - capability_definitions = get_inherited_capability_definitions(context, parent, - for_presentation=presentation) \ - if parent is not None \ - else OrderedDict() + capability_definitions = get_inherited_capability_definitions( + context, parent, for_presentation) if parent is not None else OrderedDict() # Add/merge our capability definitions our_capability_definitions = presentation.capabilities @@ -75,9 +76,8 @@ def get_inherited_capability_definitions(context, presentation, for_presentation .format(type1, type2, presentation._fullname), locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES) - # Already cloned? - #capability_definition = capability_definition._clone(for_presentation) - #capability_definitions[capability_name] = capability_definition + merge_capability_definition(context, presentation, capability_definition, + our_capability_definition) else: capability_definition = our_capability_definition._clone(for_presentation) if isinstance(capability_definition._raw, basestring): @@ -129,20 +129,11 @@ def get_template_capabilities(context, presentation): if capability_name in capability_assignments: capability_assignment = capability_assignments[capability_name] - print - print presentation._name - print 'raw1', our_capability_assignment._raw - print 'raw2', presentation._raw['capabilities'][our_capability_assignment._name] - # Assign properties values = get_assigned_and_defined_parameter_values(context, our_capability_assignment, 'property') - print 'our', [(k, v.value) for k, v in our_capability_assignment.properties.iteritems()] - print 'def', [(k, v.value.value) for k, v in capability_assignment.properties.iteritems()] - print 'val', [(k, v.value) for k, v in values.iteritems()] - if values: capability_assignment._raw['properties'] = values capability_assignment._reset_method_cache() @@ -173,6 +164,30 @@ def convert_capability_from_definition_to_assignment(context, presentation, cont return CapabilityAssignment(name=presentation._name, raw=raw, container=container) +def merge_capability_definition(context, presentation, capability_definition, + from_capability_definition): + raw_properties = OrderedDict() + + # Merge properties from type + from_property_defintions = from_capability_definition.properties + merge_raw_parameter_definitions(context, presentation, raw_properties, from_property_defintions, + 'properties') + + # Merge our properties + merge_raw_parameter_definitions(context, presentation, raw_properties, + capability_definition.properties, 'properties') + + if raw_properties: + capability_definition._raw['properties'] = raw_properties + capability_definition._reset_method_cache() + + # Merge occurrences + occurrences = from_capability_definition._raw.get('occurrences') + if (occurrences is not None) and (capability_definition._raw.get('occurrences') is None): + capability_definition._raw['occurrences'] = \ + deepcopy_with_locators(occurrences) + + def merge_capability_definition_from_type(context, presentation, capability_definition): raw_properties = OrderedDict() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py index e04ac4a..d5f447c 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py @@ -113,9 +113,12 @@ def get_inherited_interface_definitions(context, presentation, type_name, for_pr types. """ + if for_presentation is None: + for_presentation = presentation + # Get interfaces from parent parent = presentation._get_parent(context) - interfaces = get_inherited_interface_definitions(context, parent, type_name, presentation) \ + interfaces = get_inherited_interface_definitions(context, parent, type_name, for_presentation) \ if parent is not None else OrderedDict() # Add/merge interfaces from their types @@ -123,8 +126,7 @@ def get_inherited_interface_definitions(context, presentation, type_name, for_pr # Add/merge our interfaces our_interfaces = presentation.interfaces - merge_interface_definitions(context, interfaces, our_interfaces, presentation, - for_presentation=for_presentation) + merge_interface_definitions(context, interfaces, our_interfaces, presentation, for_presentation) return interfaces http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py index c910956..87c1a3b 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py @@ -33,11 +33,14 @@ def get_inherited_parameter_definitions(context, presentation, field_name, for_p Allows overriding all aspects of parent properties except data type. """ + if for_presentation is None: + for_presentation = presentation + # Get definitions from parent # If we inherit from a primitive, it does not have a parent: parent = presentation._get_parent(context) if hasattr(presentation, '_get_parent') else None definitions = get_inherited_parameter_definitions(context, parent, field_name, - for_presentation=presentation) \ + for_presentation) \ if parent is not None else OrderedDict() # Add/merge our definitions http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/tests/end2end/test_nodecellar.py ---------------------------------------------------------------------- diff --git a/tests/end2end/test_nodecellar.py b/tests/end2end/test_nodecellar.py index a2b6797..e8cfa84 100644 --- a/tests/end2end/test_nodecellar.py +++ b/tests/end2end/test_nodecellar.py @@ -39,4 +39,4 @@ def _verify_deployed_service_in_storage(service_name, model_storage): service = service_templates[0].services[service_name] assert service.name == service_name assert len(service.executions) == 0 # dry executions leave no traces - assert len(service.nodes) == 13 + assert len(service.nodes) == 15 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml index de57d3c..2d39967 100644 --- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml +++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml @@ -155,7 +155,7 @@ topology_template: capabilities: - scalable: properties: - - max_instances: { greater_or_equal: 8 } + - max_instances: { greater_or_equal: 5 } mongodb: description: >- @@ -171,7 +171,7 @@ topology_template: capabilities: - scalable: properties: - - max_instances: { greater_or_equal: 8 } + - max_instances: { greater_or_equal: 5 } relationship: interfaces: Configure: @@ -201,11 +201,6 @@ topology_template: os_users: # map of os.UserInfo root: password: admin123 - capabilities: - scalable: # will be overriden by policy - properties: - max_instances: 5 - default_instances: 3 interfaces: Standard: inputs: @@ -230,7 +225,7 @@ topology_template: capabilities: scalable: properties: - max_instances: 10 + max_instances: 5 # overrides the policy data_host: copy: loadbalancer_host @@ -251,7 +246,7 @@ topology_template: capabilities: scalable: properties: - max_instances: 10 + max_instances: 6 # overrides the policy data_volume: type: openstack.Volume @@ -278,14 +273,23 @@ topology_template: policies: -# scaling: -# type: openstack.Scaling -# properties: -# bandwidth_threshold: 2 GB -# max_instances: 2 -# default_instances: 2 -# targets: # node templates or groups -# - node_cellar_group + app_scaling: + type: aria.Scaling + properties: + max_instances: 10 + default_instances: 2 + targets: + - node_cellar + - nodejs + + host_scaling: + type: openstack.Scaling + properties: + bandwidth_threshold: 2 GB + max_instances: 10 + default_instances: 2 + targets: # node templates or groups + - node_cellar_group juju: description: >- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/76aa0843/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml index 4fd4e72..19cc7b9 100644 --- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml +++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml @@ -51,6 +51,7 @@ node_types: host: # @override type: tosca.capabilities.Container valid_source_types: [ nodejs.Application ] + occurrences: [ 0, 1 ] nodejs.Application: derived_from: tosca.nodes.WebApplication