RIFT OSM R1 Initial Submission
[osm/SO.git] / common / python / rift / mano / yang_translator / rwmano / syntax / tosca_template.py
diff --git a/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py b/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py
new file mode 100644 (file)
index 0000000..7c31df5
--- /dev/null
@@ -0,0 +1,135 @@
+# Copyright 2016 RIFT.io Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from collections import OrderedDict
+
+import textwrap
+
+from rift.mano.yang_translator.common.utils import _
+from rift.mano.yang_translator.rwmano.syntax.tosca_resource \
+    import ToscaResource
+
+import yaml
+
+
+class ToscaTemplate(object):
+    '''Container for full RIFT.io TOSCA template.'''
+
+    KEYS = (TOSCA, FILES) = ('tosca', 'files')
+
+    def __init__(self, log):
+        self.log = log
+        self.resources = []
+
+    def output_to_tosca(self):
+        self.log.debug(_('Converting translated output to tosca template.'))
+
+        templates = {}
+
+        for resource in self.resources:
+            # Each NSD should generate separate templates
+            if resource.type == 'nsd':
+                tmpl = resource.generate_tosca_type()
+                tmpl = resource.generate_tosca_template(tmpl)
+                self.log.debug(_("TOSCA template generated for {0}:\n{1}").
+                               format(resource.name, tmpl))
+                templates[resource.name] = {self.TOSCA: self.output_to_yaml(tmpl)}
+                files = resource.get_supporting_files()
+                if len(files):
+                    templates[resource.name][self.FILES] = files
+
+        return templates
+
+    def represent_ordereddict(self, dumper, data):
+        nodes = []
+        for key, value in data.items():
+            node_key = dumper.represent_data(key)
+            node_value = dumper.represent_data(value)
+            nodes.append((node_key, node_value))
+        return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', nodes)
+
+    def ordered_node(self, node):
+        order = [ToscaResource.TYPE, ToscaResource.DERIVED_FROM,
+                 ToscaResource.DESC, ToscaResource.MEMBERS,
+                 ToscaResource.PROPERTIES, ToscaResource.CAPABILITIES,
+                 ToscaResource.REQUIREMENTS,ToscaResource.ARTIFACTS,
+                 ToscaResource.INTERFACES]
+        new_node = OrderedDict()
+        for ent in order:
+            if ent in node:
+                new_node.update({ent: node.pop(ent)})
+
+        # Check if we missed any entry
+        if len(node):
+            self.log.warn(_("Did not sort these entries: {0}").
+                          format(node))
+            new_node.update(node)
+
+        return new_node
+
+    def ordered_nodes(self, nodes):
+        new_nodes = OrderedDict()
+        if isinstance(nodes, dict):
+            for name, node in nodes.items():
+                new_nodes.update({name: self.ordered_node(node)})
+            return new_nodes
+        else:
+            return nodes
+
+    def output_to_yaml(self, tosca):
+        self.log.debug(_('Converting translated output to yaml format.'))
+        dict_output = OrderedDict()
+
+        dict_output.update({'tosca_definitions_version':
+                            tosca['tosca_definitions_version']})
+        # Description
+        desc_str = ""
+        if ToscaResource.DESC in tosca:
+            # Wrap the text to a new line if the line exceeds 80 characters.
+            wrapped_txt = "\n  ". \
+                          join(textwrap.wrap(tosca[ToscaResource.DESC], 80))
+            desc_str = ToscaResource.DESC + ": >\n  " + \
+                       wrapped_txt + "\n\n"
+        dict_output.update({ToscaResource.DESC: tosca[ToscaResource.DESC]})
+
+        if ToscaResource.METADATA in tosca:
+            dict_output.update({ToscaResource.METADATA:
+                               tosca[ToscaResource.METADATA]})
+
+        # Add all types
+        types_list = [ToscaResource.DATA_TYPES, ToscaResource.CAPABILITY_TYPES,
+                      ToscaResource.NODE_TYPES,
+                      ToscaResource.GROUP_TYPES, ToscaResource.POLICY_TYPES]
+        for typ in types_list:
+            if typ in tosca:
+                dict_output.update({typ: self.ordered_nodes(tosca[typ])})
+
+        # Add topology template
+        topo_list = [ToscaResource.INPUTS, ToscaResource.NODE_TMPL,
+                     ToscaResource.GROUPS, ToscaResource.POLICIES,
+                     ToscaResource.OUTPUTS]
+        if ToscaResource.TOPOLOGY_TMPL in tosca:
+            tmpl = OrderedDict()
+            for typ in tosca[ToscaResource.TOPOLOGY_TMPL]:
+                tmpl.update({typ:
+                             self.ordered_nodes(
+                                 tosca[ToscaResource.TOPOLOGY_TMPL][typ])})
+            dict_output.update({ToscaResource.TOPOLOGY_TMPL: tmpl})
+
+        yaml.add_representer(OrderedDict, self.represent_ordereddict)
+        yaml_string = yaml.dump(dict_output, default_flow_style=False)
+        # get rid of the '' from yaml.dump around numbers
+        yaml_string = yaml_string.replace('\'', '')
+        self.log.debug(_("YAML output:\n{0}").format(yaml_string))
+        return yaml_string