From ff4f57989e50e2234418a23c24daa75744985f8b Mon Sep 17 00:00:00 2001
From: Benedetto Debora <Debora.Benedetto@hpecds.com>
Date: Mon, 14 Mar 2022 17:13:34 +0100
Subject: [PATCH] Add icg parser, new API definition

---
 .gitignore                                    |   4 +
 api/InfrastructureTemplateController.py       |  51 ++-
 controller/PluginOrchestrator.py              |  24 ++
 controller/__init__.py                        |   0
 icgparser/ModelParser.py                      | 231 ++++++++++++
 icgparser/__init__.py                         |   0
 icgparser/doml/doml.ecore                     | 349 ++++++++++++++++++
 input_file_generated/ir.json                  |  21 ++
 main.py                                       |   2 +
 .../wordpress_azure/terraform/main.tf         | 124 ++++++-
 .../nginx_openstack/terraform/main.tf         |  54 ---
 requirements.txt                              |   3 +-
 .../terraform/open_stack/virtual_machine.tpl  |  18 +-
 13 files changed, 778 insertions(+), 103 deletions(-)
 create mode 100644 controller/PluginOrchestrator.py
 create mode 100644 controller/__init__.py
 create mode 100644 icgparser/ModelParser.py
 create mode 100644 icgparser/__init__.py
 create mode 100644 icgparser/doml/doml.ecore
 create mode 100644 input_file_generated/ir.json

diff --git a/.gitignore b/.gitignore
index 0193e37..eb26650 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
 .idea
+*.tar.gz
+icgparser/doml/*domlx
+output_files_generated/nginx_openstack/terraform/*
+output_files_generated/nginx_openstack/ansible/*
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/api/InfrastructureTemplateController.py b/api/InfrastructureTemplateController.py
index ca223f4..6fcdfeb 100644
--- a/api/InfrastructureTemplateController.py
+++ b/api/InfrastructureTemplateController.py
@@ -1,34 +1,47 @@
+import json
 import logging
 import tarfile
+import uuid
 
 from fastapi import APIRouter, Body
 from fastapi.responses import FileResponse
 
-from plugin import TerraformPlugin
-from plugin import AnsiblePlugin
-
+from controller.PluginOrchestrator import create_infrastructure_files
+from icgparser import ModelParser
 
 api_router = APIRouter()
 
+base_compress_file_name = "iac_files_"
+
 @api_router.post("/infrastructure/files")
-def create_infrastructure_files(intermediate_representation: dict = Body(...)):
-    logging.info("Received intermediate representation create_infrastructure_files request")
-    choose_plugin(intermediate_representation)
-    logging.info("Creating compress folder with iac files")
-    output_template_folder = intermediate_representation["output_path"]
-    compress_file_name = "outputIaC.tar.gz"
-    compress_file_path = compress_file(output_template_folder, compress_file_name)
+def create_iac_from_intermediate_representation(intermediate_representation: dict = Body(...)):
+    logging.info("Received intermediate representation create_iac_from_intermediate_representation request")
+    template_generated_folder = create_infrastructure_files(intermediate_representation)
+    compress_file_name = random_file_name_generation(base_compress_file_name)
+    compress_file_path = compress_file(template_generated_folder, compress_file_name)
     return FileResponse(compress_file_path, media_type='application/octet-stream', filename=compress_file_name)
 
-def choose_plugin(parameters):
-    # os.system('rm -f /opt/output_files_generated/*')
-    for step in parameters["steps"]:
-        if step["programming_language"] == "ansible":
-            input_data = step["data"]
-            AnsiblePlugin.create_files(input_data, parameters["output_path"])
-        elif step["programming_language"] == "terraform":
-            input_data = step["data"]
-            TerraformPlugin.create_files(input_data, parameters["output_path"])
+
+@api_router.post("/iac/files")
+def create_iac_from_doml(data: str = Body(..., media_type="application/xml")):
+    logging.info("Received create_iac_from_doml request")
+    temp_model_file_path = "icgparser/doml/nginx-openstack.domlx"
+    logging.info("Writing model file in temp folder '%s' for parsing", temp_model_file_path)
+    f = open(temp_model_file_path, "w")
+    f.write(data)
+    f.close()
+    ModelParser.parse_model(temp_model_file_path)
+    with open("input_file_generated/ir.json") as json_file:
+        data = json.load(json_file)
+        template_generated_folder = create_infrastructure_files(data)
+        compress_file_name = random_file_name_generation(base_compress_file_name)
+        compress_file_folder = compress_file(template_generated_folder, compress_file_name)
+        return FileResponse(compress_file_folder,
+                            media_type='application/octet-stream',
+                            filename=compress_file_name)
+
+def random_file_name_generation(base_name):
+    return base_name + str(uuid.uuid4().hex) + ".tar.gz"
 
 def compress_file(source_folder, dest_file_name):
     # prefix_path = "/opt/"
diff --git a/controller/PluginOrchestrator.py b/controller/PluginOrchestrator.py
new file mode 100644
index 0000000..998f380
--- /dev/null
+++ b/controller/PluginOrchestrator.py
@@ -0,0 +1,24 @@
+import logging
+
+from plugin import AnsiblePlugin, TerraformPlugin
+
+
+def create_infrastructure_files(intermediate_representation: dict):
+    template_generated_folder = intermediate_representation["output_path"]
+    choose_plugin(intermediate_representation, template_generated_folder)
+    logging.info("iac files available at %s", template_generated_folder)
+    return template_generated_folder
+
+
+def choose_plugin(parameters, template_generated_folder):
+    # os.system('rm -f /opt/output_files_generated/*')
+    logging.info("Choosing plugin")
+    for step in parameters["steps"]:
+        if step["programming_language"] == "ansible":
+            logging.info("Ansible Plugin chosen")
+            input_data = step["data"]
+            AnsiblePlugin.create_files(input_data, template_generated_folder)
+        elif step["programming_language"] == "terraform":
+            logging.info("Terraform Plugin chosen")
+            input_data = step["data"]
+            TerraformPlugin.create_files(input_data, template_generated_folder)
diff --git a/controller/__init__.py b/controller/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/icgparser/ModelParser.py b/icgparser/ModelParser.py
new file mode 100644
index 0000000..668f6d0
--- /dev/null
+++ b/icgparser/ModelParser.py
@@ -0,0 +1,231 @@
+# -------------------------------------------------------------------------
+#		PIACERE ICG Parser
+#
+#       This module has been tested with Python v3.7.4
+#       To use it you must first install PyEcore
+#           $ pip install pyecore
+#
+#       Usage: python icgparser.py [-h] [-d dir] [-v] [--single] model
+#           -h          prints usage
+#           -d dir      loads metamodel from <dir>
+#           --single / --single_mmodel   use the single (non-split) metamodel
+#           model       the input model to be translated into the ICG intermediate representation
+#
+#		Author: Lorenzo Blasi
+#		23/2/2022 - created
+#		© Copyright 2022 Hewlett Packard Enterprise Development LP
+# -------------------------------------------------------------------------
+import logging
+import sys
+from pyecore.resources import ResourceSet, URI, global_registry
+import pyecore.ecore as Ecore  # This gets a reference to the Ecore metamodel implementation
+
+# -------------------------------------------------------------------------
+# Utility functions to printout the loaded model
+# -------------------------------------------------------------------------
+newline = "\n"
+spaces = "    "
+comment = "#"
+
+
+def write_to(outchannel, line):
+    # for now we just print on the console
+    if outchannel == "console":
+        print(line)
+    # if the channel is different we don't print at all
+
+
+def print_obj(obj, level=0):
+    #    for x in range(level):
+    #        print("    ", end='')
+    class_name = obj.eClass.name
+    if class_name == 'Property':
+        #        print('Class: {0}\t\t{1} = {2}'.format(class_name, obj.key, obj.value))
+        print(f'{comment}{level * spaces}Class: {class_name}\t\t{obj.key} = {obj.value}')
+        return False
+    if class_name == 'Deployment':
+        print(
+            f'{comment}{level * spaces}Class: {class_name}\t\tcomponent = {obj.component.eClass.name}/{obj.component.name} node = {obj.node.eClass.name}/{obj.node.name}')
+        return False
+    try:
+        obj_name = obj.name
+        print(f'{comment}{level * spaces}Class: {class_name}\t\tObject: {obj_name}')
+        return True
+    except Exception:
+        print(f'{comment}{level * spaces}Class: {class_name}\t\tObject: no name')
+        return False
+
+
+def print_contents_recursive(obj, level=0):
+    if print_obj(obj, level):
+        for x in obj.eContents:
+            print_contents_recursive(x, level + 1)
+
+
+# -------------------------------------------------------------------------
+# Utility functions to produce the output Intermediate Language
+# -------------------------------------------------------------------------
+# --- Helpers
+def extract_image_name(concretevm_obj):
+    # To find the VM image name you could search into the inverse relations of the abstract image generating its related abstract VM, looking for a concrete image object (whose class is VMImage) and extract the value from its contents
+    #   concretevm_obj is a VirtualMachine (nginx-openstack_v2.doml:81, it should have been a OpenStackVM),
+    #   concretevm_obj.maps is a VirtualMachine (the abstract one)
+    #   concretevm_obj.maps.generatedFrom is a VMImage (the abstract one)
+    for x in concretevm_obj.maps.generatedFrom._inverse_rels:
+        if x[0].eClass.name == 'VMImage':
+            return x[0].eContents[0].value
+
+
+def extract_concrete_network_name(abstractnet_obj):
+    for x in abstractnet_obj._inverse_rels:
+        if x[0].eClass.name == 'Network':
+            return x[0].eContents[0].value
+
+
+# --- Handlers
+def model_handler(obj, model_root, level, intermediate_repr):
+    # output prefix
+    append_in_file(intermediate_repr,
+                   f'{level * spaces}{{{newline}{level * spaces}{spaces}"output_path": "output_files_generated/{obj.name}/",')
+    append_in_file(intermediate_repr, f'{level * spaces}{spaces}"steps": [')
+    # handle contents
+    for x in obj.eContents:
+        handle_obj(x, model_root, level + 2, intermediate_repr)
+    # output suffix
+    append_in_file(intermediate_repr, f'{level * spaces}{spaces}]')
+    append_in_file(intermediate_repr, f'{level * spaces}}}')
+
+
+def concrete_infra_handler(obj, model_root, level, intermediate_repr):
+    # output prefix
+    append_in_file(intermediate_repr, f'{level * spaces}{{{newline}{level * spaces}{spaces}"programming_language": "terraform",')
+    # handle contents
+    for x in obj.eContents:
+        handle_obj(x, model_root, level + 1, intermediate_repr)
+    # output suffix
+    append_in_file(intermediate_repr, f'{level * spaces}}}')
+
+
+def network_handler(obj, model_root, level, intermediate_repr):
+    # ignore the concrete network, since its name has been extracted separately and included in the concrete VM
+    logging.warning('Ignoring Network')
+
+
+def property_handler(obj, model_root, level, intermediate_repr):
+    key = obj.key
+    append_in_file(intermediate_repr, f'{level * spaces}"{key}" :     "{obj.value}",')
+
+
+def provider_handler(obj, model_root, level, intermediate_repr):
+    # output prefix
+    append_in_file(intermediate_repr, f'{level * spaces}"data": {{{newline}{level * spaces}{spaces}"provider": "{obj.name}",')
+    # handle contents
+    for x in obj.eContents:
+        handle_obj(x, model_root, level + 1, intermediate_repr)
+    # output suffix
+    append_in_file(intermediate_repr, f'{level * spaces}}}')
+
+
+def concrete_vm_handler(obj, model_root, level, intermediate_repr):
+    # output prefix
+    append_in_file(intermediate_repr, f'{level * spaces}"vm": [{{')  # VMs can be more than one: I need an example...
+    level = level + 1
+    # print(f'{level * spaces}# maps {obj.maps.name}')
+    logging.warning(f"Ignoring map {obj.maps.name}")
+    # handle contents
+    for x in obj.eContents:
+        handle_obj(x, model_root, level, intermediate_repr)
+    # add other attributes defined elsewhere: image name, address, ...
+    append_in_file(intermediate_repr, f'{level * spaces}"image" :     "{extract_image_name(obj)}",')
+    for iface in obj.maps.ifaces:
+        append_in_file(intermediate_repr, f'{level * spaces}"address" :     "{iface.endPoint}",')
+        append_in_file(intermediate_repr, f'{level * spaces}"network_name" :     "{extract_concrete_network_name(iface.belongsTo)}"')
+    # output suffix
+    level = level - 1
+    append_in_file(intermediate_repr, f'{level * spaces}}}]')
+
+
+def vm_image_handler(obj, model_root, level, intermediate_repr):
+    # ignore the concrete image, since its image name has been extracted separately and included in the concrete VM
+    logging.warning(f'Ignoring VMImage')
+
+
+class_handler = {
+
+    "DOMLModel": model_handler,
+    "ConcreteInfrastructure": concrete_infra_handler,
+    "Network": network_handler,
+    "Property": property_handler,
+    "RuntimeProvider": provider_handler,
+    "VirtualMachine": concrete_vm_handler,  # Warning: the class here might change to some concrete VM class
+    "VMImage": vm_image_handler
+}
+
+
+def handle_obj(obj, model_root, level, intermediate_repr):
+    if obj.eClass.name in class_handler:
+        class_handler[obj.eClass.name](obj, model_root, level, intermediate_repr)
+    else:
+        logging.warning(f'Class {obj.eClass.name} has no handler')
+
+
+# -------------------------------------------------------------------------
+# Parse parameters
+# -------------------------------------------------------------------------
+skip_next = False
+doml_directory = "icgparser/doml"
+
+
+# -------------------------------------------------------------------------
+# Load each part of the DOML metamodel and register them
+# -------------------------------------------------------------------------
+def load_metamodel(load_split_model):
+    global_registry[Ecore.nsURI] = Ecore  # Load the Ecore metamodel first
+    rset = ResourceSet()
+    if load_split_model:
+        mm_parts = ["doml", "commons", "application", "infrastructure", "concrete", "optimization"]
+        for mm_filename in mm_parts:
+            resource = rset.get_resource(URI(f"{doml_directory}/{mm_filename}.ecore"))
+            mm_root = resource.contents[0]  # Get the root of the MetaModel (EPackage)
+            rset.metamodel_registry[mm_root.nsURI] = mm_root
+    else:
+        resource = rset.get_resource(URI(f"{doml_directory}/doml.ecore"))
+        mm_root = resource.contents[0]  # Get the root of the MetaModel (EPackage)
+        rset.metamodel_registry[mm_root.nsURI] = mm_root
+        for subp in mm_root.eSubpackages:
+            rset.metamodel_registry[subp.nsURI] = subp
+    return rset
+
+
+# -------------------------------------------------------------------------
+# Finally load the model and print it out
+# -------------------------------------------------------------------------
+
+def parse_model(model):
+    load_split_model = None
+    rset = load_metamodel(load_split_model)
+    doml_model_resource = rset.get_resource(URI(model))
+    doml_model = doml_model_resource.contents[0]
+    single = "single-file (doml.ecore)"
+    split = "split"
+    dash = "-"
+    logging.info(f'{comment}{80 * dash}')
+    logging.info(f'{comment} Using {split if load_split_model else single} metamodel from directory {doml_directory}')
+    print(f'{comment} Model loaded from file {model}:')
+    print(f'{comment}{80 * dash}')
+    print_contents_recursive(doml_model)
+    print(f'{comment}{80 * dash}{newline}{comment} Generated Intermediate Representation follows:{newline}{comment}')
+    intermediate_repr_file_path = "input_file_generated/ir.json"
+    create_file("input_file_generated/ir.json")
+    handle_obj(doml_model, doml_model, 0, intermediate_repr_file_path)
+
+def create_file(file_name):
+    f = open(file_name, "w")
+    f.write("")
+    f.close()
+
+def append_in_file(file_name, data):
+    f = open(file_name, "a")
+    f.write(data)
+    f.write("\n")
+    f.close()
diff --git a/icgparser/__init__.py b/icgparser/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/icgparser/doml/doml.ecore b/icgparser/doml/doml.ecore
new file mode 100644
index 0000000..e8cc0d6
--- /dev/null
+++ b/icgparser/doml/doml.ecore
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="doml" nsURI="http://www.piacere-project.eu/doml" nsPrefix="doml">
+  <eAnnotations source="emf.gen">
+    <details key="basePackage" value="eu.piacere.doml"/>
+    <details key="fileExtensions" value="domlx"/>
+    <details key="complianceLevel" value="JDK80"/>
+  </eAnnotations>
+  <eSubpackages name="commons" nsURI="http://www.piacere-project.eu/doml/commons"
+      nsPrefix="commons">
+    <eClassifiers xsi:type="ecore:EClass" name="DOMLModel" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="application" eType="#//application/ApplicationLayer"
+          containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="infrastructure" eType="#//infrastructure/InfrastructureLayer"
+          containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="concretizations" upperBound="-1"
+          eType="#//concrete/ConcreteInfrastructure" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="optimization" eType="#//optimization/OptimizationLayer"
+          containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="configurations" upperBound="-1"
+          eType="#//commons/Configuration" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="activeConfiguration"
+          eType="#//commons/Configuration"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="activeInfrastructure"
+          eType="#//concrete/ConcreteInfrastructure"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="functionalRequirements"
+          upperBound="-1" eType="#//commons/Requirement" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Property">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="key" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="reference" eType="#//commons/DOMLElement"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ExtensionElement" abstract="true">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="metaclassName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="DOMLElement" abstract="true">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="description" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="annotations" upperBound="-1"
+          eType="#//commons/Property" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="contributesTo" upperBound="-1"
+          eType="#//commons/Requirement" eOpposite="#//commons/Requirement/predicatesOn"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Configuration" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="deployments" upperBound="-1"
+          eType="#//commons/Deployment" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Deployment">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="component" lowerBound="1"
+          eType="#//application/ApplicationComponent"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="node" lowerBound="1"
+          eType="#//infrastructure/InfrastructureElement"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Requirement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="identifier" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="description" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="property" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="predicatesOn" upperBound="-1"
+          eType="#//commons/DOMLElement" eOpposite="#//commons/DOMLElement/contributesTo"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="RangedRequirement" eSuperTypes="#//commons/Requirement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="min" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="max" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="EnumeratedRequirement" eSuperTypes="#//commons/Requirement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="values" upperBound="-1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="DeploymentRequirement" abstract="true"
+        eSuperTypes="#//commons/Requirement"/>
+    <eClassifiers xsi:type="ecore:EClass" name="DeploymentToNodeTypeRequirement" eSuperTypes="#//commons/DeploymentRequirement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="validTypes" upperBound="-1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="DeploymentToNodeWithPropertyRequirement"
+        eSuperTypes="#//commons/DeploymentRequirement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="min" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="max" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="values" upperBound="-1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="DeploymentToSpecificNodeRequirement"
+        eSuperTypes="#//commons/DeploymentRequirement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="validElements" upperBound="-1"
+          eType="#//infrastructure/InfrastructureElement"/>
+    </eClassifiers>
+  </eSubpackages>
+  <eSubpackages name="application" nsURI="http://www.piacere-project.eu/doml/application"
+      nsPrefix="app">
+    <eClassifiers xsi:type="ecore:EClass" name="ApplicationLayer" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="components" upperBound="-1"
+          eType="#//application/ApplicationComponent" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ApplicationComponent" abstract="true"
+        eSuperTypes="#//commons/DOMLElement"/>
+    <eClassifiers xsi:type="ecore:EClass" name="SoftwareComponent" eSuperTypes="#//application/ApplicationComponent">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="isPersistent" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBooleanObject"
+          defaultValueLiteral="false"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="licenseCost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="configFile" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="exposedInterfaces" upperBound="-1"
+          eType="#//application/SoftwareInterface" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="consumedInterfaces" upperBound="-1"
+          eType="#//application/SoftwareInterface"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="DBMS" eSuperTypes="#//application/SoftwareComponent"/>
+    <eClassifiers xsi:type="ecore:EClass" name="SaaS" eSuperTypes="#//application/ApplicationComponent">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="licenseCost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="exposedInterfaces" upperBound="-1"
+          eType="#//application/SoftwareInterface" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="SaaSDBMS" eSuperTypes="#//application/SaaS"/>
+    <eClassifiers xsi:type="ecore:EClass" name="SoftwareInterface" eSuperTypes="#//application/ApplicationComponent">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="endPoint" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ExtApplicationComponent" eSuperTypes="#//application/ApplicationComponent #//commons/ExtensionElement"/>
+  </eSubpackages>
+  <eSubpackages name="infrastructure" nsURI="http://www.piacere-project.eu/doml/infrastructure"
+      nsPrefix="infra">
+    <eClassifiers xsi:type="ecore:EClass" name="InfrastructureLayer" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1"
+          eType="#//infrastructure/ComputingNode" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="networks" upperBound="-1"
+          eType="#//infrastructure/VPC" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="secGroups" upperBound="-1"
+          eType="#//infrastructure/SecurityGroup" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="generators" upperBound="-1"
+          eType="#//infrastructure/ComputingNodeGenerator" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="storages" upperBound="-1"
+          eType="#//infrastructure/Storage" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="faas" upperBound="-1"
+          eType="#//infrastructure/FunctionAsAService" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="credentials" upperBound="-1"
+          eType="#//infrastructure/Credentials" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ComputingGroup" abstract="true" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="groupedNodes" upperBound="-1"
+          eType="#//infrastructure/ComputingNode" eOpposite="#//infrastructure/ComputingNode/group"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="AutoScalingGroup" eSuperTypes="#//infrastructure/ComputingNode">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="machineDefinition" lowerBound="1"
+          eType="#//infrastructure/VirtualMachine" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="min" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"
+          defaultValueLiteral="1"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="max" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"
+          defaultValueLiteral="1"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="deploymentNetwork" eType="#//infrastructure/Network"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="securityGroup" eType="#//infrastructure/SecurityGroup"
+          containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="loadBalancer" eType="#//infrastructure/LoadBalancerKind"
+          defaultValueLiteral="DEFAULT"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EEnum" name="LoadBalancerKind">
+      <eLiterals name="DEFAULT"/>
+      <eLiterals name="INTERNAL" value="1"/>
+      <eLiterals name="EXTERNAL" value="2"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Rule" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" eType="#//infrastructure/RuleKind"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="protocol" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="fromPort" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="toPort" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="addressRanges" upperBound="-1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EEnum" name="RuleKind">
+      <eLiterals name="EGRESS"/>
+      <eLiterals name="INGRESS" value="1"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="SecurityGroup" eSuperTypes="#//infrastructure/ComputingGroup">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="rules" upperBound="-1"
+          eType="#//infrastructure/Rule" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="ifaces" upperBound="-1"
+          eType="#//infrastructure/NetworkInterface" eOpposite="#//infrastructure/NetworkInterface/associated"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="AvailabilityGroup" eSuperTypes="#//infrastructure/ComputingGroup"/>
+    <eClassifiers xsi:type="ecore:EClass" name="InfrastructureElement" abstract="true"
+        eSuperTypes="#//commons/DOMLElement"/>
+    <eClassifiers xsi:type="ecore:EClass" name="ComputingNode" abstract="true" eSuperTypes="#//infrastructure/InfrastructureElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="architecture" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="os" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="memory" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="storage" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="cpu" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="ifaces" upperBound="-1"
+          eType="#//infrastructure/NetworkInterface" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="location" eType="#//infrastructure/Location"
+          containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="credentials" eType="#//infrastructure/Credentials"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="group" eType="#//infrastructure/ComputingGroup"
+          eOpposite="#//infrastructure/ComputingGroup/groupedNodes"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ComputingNodeGenerator" abstract="true"
+        eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="uri" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" eType="#//infrastructure/GeneratorKind"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EEnum" name="GeneratorKind">
+      <eLiterals name="SCRIPT"/>
+      <eLiterals name="IMAGE" value="1"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="VMImage" eSuperTypes="#//infrastructure/ComputingNodeGenerator">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="generatedVMs" upperBound="-1"
+          eType="#//infrastructure/VirtualMachine" eOpposite="#//infrastructure/VirtualMachine/generatedFrom"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ContainerImage" eSuperTypes="#//infrastructure/ComputingNodeGenerator">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="generatedContainers"
+          upperBound="-1" eType="#//infrastructure/Container" eOpposite="#//infrastructure/Container/generatedFrom"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="PhysicalComputingNode" eSuperTypes="#//infrastructure/ComputingNode"/>
+    <eClassifiers xsi:type="ecore:EClass" name="VirtualMachine" eSuperTypes="#//infrastructure/ComputingNode">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="sizeDescription" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="generatedFrom" eType="#//infrastructure/VMImage"
+          eOpposite="#//infrastructure/VMImage/generatedVMs"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Location" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="region" lowerBound="1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="zone" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Container" eSuperTypes="#//infrastructure/ComputingNode">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="generatedFrom" eType="#//infrastructure/ContainerImage"
+          eOpposite="#//infrastructure/ContainerImage/generatedContainers"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="host" eType="#//infrastructure/ComputingNode"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Network" abstract="true" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="protocol" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="addressRange" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="connectedIfaces" upperBound="-1"
+          eType="#//infrastructure/NetworkInterface" eOpposite="#//infrastructure/NetworkInterface/belongsTo"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="igws" upperBound="-1"
+          eType="#//infrastructure/InternetGateway" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="VPC" eSuperTypes="#//infrastructure/Network">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="subnets" upperBound="-1"
+          eType="#//infrastructure/Subnet" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Subnet" eSuperTypes="#//infrastructure/Network">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="connectedTo" upperBound="-1"
+          eType="#//infrastructure/Subnet"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="NetworkInterface" eSuperTypes="#//infrastructure/InfrastructureElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="speed" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="endPoint" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="belongsTo" eType="#//infrastructure/Network"
+          eOpposite="#//infrastructure/Network/connectedIfaces"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="associated" eType="#//infrastructure/SecurityGroup"
+          eOpposite="#//infrastructure/SecurityGroup/ifaces"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="InternetGateway" eSuperTypes="#//infrastructure/NetworkInterface"/>
+    <eClassifiers xsi:type="ecore:EClass" name="Storage" eSuperTypes="#//infrastructure/InfrastructureElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="storage" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="ifaces" upperBound="-1"
+          eType="#//infrastructure/NetworkInterface" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="FunctionAsAService" eSuperTypes="#//infrastructure/InfrastructureElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="ifaces" upperBound="-1"
+          eType="#//infrastructure/NetworkInterface" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Credentials" abstract="true" eSuperTypes="#//commons/DOMLElement"/>
+    <eClassifiers xsi:type="ecore:EClass" name="KeyPair" eSuperTypes="#//infrastructure/Credentials">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="algorithm" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="bits" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="UserPass" eSuperTypes="#//infrastructure/Credentials">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="username" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="password" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ExtInfrastructureElement" eSuperTypes="#//infrastructure/InfrastructureElement #//commons/ExtensionElement"/>
+  </eSubpackages>
+  <eSubpackages name="concrete" nsURI="http://www.piacere-project.eu/doml/concrete"
+      nsPrefix="concrete">
+    <eClassifiers xsi:type="ecore:EClass" name="ConcreteInfrastructure" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="providers" upperBound="-1"
+          eType="#//concrete/RuntimeProvider" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="RuntimeProvider" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="vms" upperBound="-1"
+          eType="#//concrete/VirtualMachine" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="vmImages" upperBound="-1"
+          eType="#//concrete/VMImage" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="containerImages" upperBound="-1"
+          eType="#//concrete/ContainerImage" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="networks" upperBound="-1"
+          eType="#//concrete/Network" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="storages" upperBound="-1"
+          eType="#//concrete/Storage" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="faas" upperBound="-1"
+          eType="#//concrete/FunctionAsAService" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="group" upperBound="-1"
+          eType="#//concrete/ComputingGroup" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ConcreteElement" abstract="true" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="configurationScript"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="VirtualMachine" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/VirtualMachine"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="VMImage" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/VMImage"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ContainerImage" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/ContainerImage"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Network" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/Network"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="Storage" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/Storage"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="FunctionAsAService" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/FunctionAsAService"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ComputingGroup" eSuperTypes="#//concrete/ConcreteElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/ComputingGroup"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="ExtConcreteElement" eSuperTypes="#//concrete/ConcreteElement #//commons/ExtensionElement"/>
+  </eSubpackages>
+  <eSubpackages name="optimization" nsURI="http://www.piacere-project.eu/doml/optimization"
+      nsPrefix="optimization">
+    <eClassifiers xsi:type="ecore:EClass" name="OptimizationLayer" eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EReference" name="startingHint" eType="#//commons/Configuration"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="solutions" upperBound="-1"
+          eType="#//optimization/OptimizationSolution" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="objectives" upperBound="-1"
+          eType="#//optimization/OptimizationObjective" containment="true"/>
+      <eStructuralFeatures xsi:type="ecore:EReference" name="nonfunctionalRequirements"
+          upperBound="-1" eType="#//commons/Requirement" containment="true"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="OptimizationSolution" eSuperTypes="#//commons/Configuration"/>
+    <eClassifiers xsi:type="ecore:EClass" name="OptimizationObjective" abstract="true"
+        eSuperTypes="#//commons/DOMLElement">
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" lowerBound="1"
+          eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
+          defaultValueLiteral="Max"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="property" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+    </eClassifiers>
+    <eClassifiers xsi:type="ecore:EClass" name="CountObjective" eSuperTypes="#//optimization/OptimizationObjective"/>
+    <eClassifiers xsi:type="ecore:EClass" name="MeasurableObjective" eSuperTypes="#//optimization/OptimizationObjective"/>
+    <eClassifiers xsi:type="ecore:EClass" name="ExtOptimizationObjective" eSuperTypes="#//optimization/OptimizationObjective #//commons/ExtensionElement"/>
+  </eSubpackages>
+</ecore:EPackage>
diff --git a/input_file_generated/ir.json b/input_file_generated/ir.json
new file mode 100644
index 0000000..5345a84
--- /dev/null
+++ b/input_file_generated/ir.json
@@ -0,0 +1,21 @@
+{
+    "output_path": "output_files_generated/nginx_openstack/",
+    "steps": [
+        {
+            "programming_language": "terraform",
+            "data": {
+                "provider": "openstack",
+                "vm": [{
+                    "vm_name" :     "nginx-host",
+                    "vm_flavor" :     "small",
+                    "vm_key_name" :     "user1",
+                    "ssh_user" :     "ubuntu",
+                    "ssh_key_file" :     "/home/user1/.ssh/openstack.key",
+                    "image" :     "ubuntu-20.04.3",
+                    "address" :     "16.0.0.1",
+                    "network_name" :     "ostack2"
+                }]
+            }
+        }
+    ]
+}
diff --git a/main.py b/main.py
index 098ca34..2b9b630 100644
--- a/main.py
+++ b/main.py
@@ -1,6 +1,7 @@
 import logging
 from fastapi import FastAPI
 import api.InfrastructureTemplateController
+from icgparser import ModelParser
 
 fast_api = FastAPI()
 
@@ -9,3 +10,4 @@ logging.getLogger().setLevel(logging.INFO)
 
 if __name__ == '__main__':
     logging.info("Starting ICG application")
+    ModelParser.parse_model("icgparser/doml/nginx-openstack_v2.domlx")
diff --git a/output_file_example/wordpress_azure/terraform/main.tf b/output_file_example/wordpress_azure/terraform/main.tf
index 004ee38..d0e68ef 100644
--- a/output_file_example/wordpress_azure/terraform/main.tf
+++ b/output_file_example/wordpress_azure/terraform/main.tf
@@ -13,37 +13,121 @@ provider "azurerm" {
   features {}
 }
 
+resource "azurerm_resource_group" "rg" {
+  name     = "TerraformTesting"
+  location = "eastus" ## REQUIRED
+}
+
 ## VIRTUAL NETWORK
-resource "azurerm_virtual_network" "wordpress_net_vnetwork" {
-  name                = "wordpress_net"
+resource "azurerm_virtual_network" "vnet" {
+  name                = "vNet"
   address_space       = ["10.0.0.0/16"]
-  location            = azurerm_resource_group.wordpress-example.location
-  resource_group_name = azurerm_resource_group.wordpress-example.name
+  location            = azurerm_resource_group.rg.location
+  resource_group_name = azurerm_resource_group.rg.name
 }
 
-## SUBNET
-resource "azurerm_subnet" "wordpress_net_subnet" {
+resource "azurerm_subnet" "subnet" {
   name                 = "internal"
-  resource_group_name  = azurerm_resource_group.wordpress-example.name
-  virtual_network_name = azurerm_virtual_network.wordpress_net_vnetwork.name
+  resource_group_name  = azurerm_resource_group.rg.name
+  virtual_network_name = azurerm_virtual_network.vnet.name
   address_prefixes       = ["10.0.2.0/24"]
 }
 
+## WORDPRESS PUBLIC IP
+resource "azurerm_public_ip" "wordpress_public_ip" {
+  name = "wordpress_public_ip"
+  location = azurerm_resource_group.rg.location
+  resource_group_name = azurerm_resource_group.rg.name
+  allocation_method = "Dynamic" ##REQUIRED??
+  sku = "Basic"
+}
+
+## WORDPRESS NETWORK INTERFACE
+resource "azurerm_network_interface" "wordpress_nic" {
+  name                = "wordpress_nic"
+  location            = azurerm_resource_group.rg.location
+  resource_group_name = azurerm_resource_group.rg.name
 
-## VIRTUAL NETWORK
-resource "azurerm_virtual_network" "mysql_net_vnetwork" {
-  name                = "mysql_net"
-  address_space       = ["10.0.0.0/16"]
-  location            = azurerm_resource_group.mysql-example.location
-  resource_group_name = azurerm_resource_group.mysql-example.name
+  ip_configuration {
+    name                          = "ipconfig1"
+    subnet_id                     = azurerm_subnet.subnet.id
+    private_ip_address_allocation = "Dynamic"
+    public_ip_address_id = azurerm_public_ip.wordpress_public_ip.id
+  }
 }
 
-## SUBNET
-resource "azurerm_subnet" "mysql_net_subnet" {
-  name                 = "internal"
-  resource_group_name  = azurerm_resource_group.mysql-example.name
-  virtual_network_name = azurerm_virtual_network.mysql_net_vnetwork.name
-  address_prefixes       = ["10.0.2.0/24"]
+## WORDPRESS VM
+resource "azurerm_linux_virtual_machine" "wordpress" { ## REQUIRED
+  resource_group_name = azurerm_resource_group.rg.name
+  ## instance details
+  name                = "wordpress-machine"
+  location            = azurerm_resource_group.rg.location
+  size                = "Standard_B1s" ## REQUIRED
+  ## administrator account
+  admin_username      = "adminuser"
+  admin_password      = "P@$$w0rd1234!" ##For Bastion Connection
+  disable_password_authentication = false
+  #availability_set_id = azurerm_availability_set.DemoAset.id
+  network_interface_ids = [
+    azurerm_network_interface.wordpress_nic.id
+  ]
+
+  os_disk {
+    caching              = "None"
+    storage_account_type = "Standard_LRS" ## REQUIRED
+  }
+
+  admin_ssh_key {
+    username = "adminuser"
+    public_key = file("${path.module}/ssh_keys/wordpress_rsa.pub")
+  }
+
+  source_image_reference {
+    publisher = "Canonical"
+    offer     = "UbuntuServer"
+    sku       = "18.04-LTS"
+    version   = "latest"
+  }
 }
 
+## MYSQL NETWORK INTERFACE
+resource "azurerm_network_interface" "mysql_nic" {
+  name                = "mysql_nic"
+  location            = azurerm_resource_group.rg.location
+  resource_group_name = azurerm_resource_group.rg.name
+
+  ip_configuration {
+    name                          = "internal"
+    subnet_id                     = azurerm_subnet.subnet.id
+    private_ip_address_allocation = "Dynamic"
+  }
+}
 
+## MYSQL VM
+resource "azurerm_linux_virtual_machine" "mysql" { ## REQUIRED
+  resource_group_name = azurerm_resource_group.rg.name
+  ## instance details
+  name                = "mysql-machine"
+  location            = azurerm_resource_group.rg.location
+  size                = "Standard_B1s" ## REQUIRED
+  ## administrator account
+  admin_username      = "adminuser"
+  admin_password      = "P@$$w0rd1234!"
+  disable_password_authentication = false
+  #availability_set_id = azurerm_availability_set.DemoAset.id
+  network_interface_ids = [
+    azurerm_network_interface.mysql_nic.id
+  ]
+
+  os_disk {
+    caching              = "None"
+    storage_account_type = "Standard_LRS"
+  }
+
+  source_image_reference {
+    publisher = "Canonical"
+    offer     = "UbuntuServer"
+    sku       = "18.04-LTS"
+    version   = "latest"
+  }
+}
diff --git a/output_files_generated/nginx_openstack/terraform/main.tf b/output_files_generated/nginx_openstack/terraform/main.tf
index a91ec88..791f405 100644
--- a/output_files_generated/nginx_openstack/terraform/main.tf
+++ b/output_files_generated/nginx_openstack/terraform/main.tf
@@ -45,57 +45,3 @@ resource "openstack_compute_floatingip_associate_v2" "nginx-host_floating_ip_ass
   instance_id = openstack_compute_instance_v2.nginx-host.id
 }
 
-## Network
-
-# Create Network
-resource "openstack_networking_network_v2" "ostack2" {
-  name = "ostack2"
-}
-
-# Create Subnet
-resource "openstack_networking_subnet_v2" "ostack2_subnet" {
-  name            = "ostack2_subnet"
-  network_id      = openstack_networking_network_v2.ostack2.id
-  cidr            = "16.0.0.0/24"
-  dns_nameservers = ["8.8.8.8", "8.8.8.4"]
-}
-
-# Attach networking port
-resource "openstack_networking_port_v2" "ostack2" {
-  name           = "ostack2"
-  network_id     = openstack_networking_network_v2.ostack2.id
-  admin_state_up = true
-  security_group_ids = [
-    
-    openstack_compute_secgroup_v2.rule_1_secgroup.id,
-    
-    openstack_compute_secgroup_v2.rule_2_secgroup.id,
-    
-  ]
-  fixed_ip {
-    subnet_id = openstack_networking_subnet_v2.ostack2_subnet.id
-  }
-}
-
-resource "openstack_compute_secgroup_v2" "rule_1_secgroup" {
-  name        = "rule_1"
-  description  = "Security group rule for port 80-80"
-  rule {
-    from_port   = 80
-    to_port     = 80
-    ip_protocol = "tcp"
-    cidr        = "0.0.0.0/0"
-  }
-}
-
-resource "openstack_compute_secgroup_v2" "rule_2_secgroup" {
-  name        = "rule_2"
-  description  = "Security group rule for port 22-22"
-  rule {
-    from_port   = 22
-    to_port     = 22
-    ip_protocol = "tcp"
-    cidr        = "0.0.0.0/0"
-  }
-}
-
diff --git a/requirements.txt b/requirements.txt
index 5d502ac..7637f4d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
 Jinja2==3.0.3
 PyYAML==6.0
 fastapi~=0.74.1
-uvicorn==0.17.5
\ No newline at end of file
+uvicorn==0.17.5
+pyecore~=0.12.2
\ No newline at end of file
diff --git a/templates/terraform/open_stack/virtual_machine.tpl b/templates/terraform/open_stack/virtual_machine.tpl
index 50b203c..0d9d143 100644
--- a/templates/terraform/open_stack/virtual_machine.tpl
+++ b/templates/terraform/open_stack/virtual_machine.tpl
@@ -1,28 +1,28 @@
 # Create virtual machine
-resource "openstack_compute_instance_v2" "{{ name }}" {
-  name        = "{{ name }}"
+resource "openstack_compute_instance_v2" "{{ vm_name }}" {
+  name        = "{{ vm_name }}"
   image_name  = "{{ image }}"
-  flavor_name = "{{ flavor }}"
-  key_pair    = openstack_compute_keypair_v2.{{ name ~ "_ssh_key" }}.name
+  flavor_name = "{{ vm_flavor }}"
+  key_pair    = openstack_compute_keypair_v2.{{ vm_name ~ "_ssh_key" }}.name
   network {
     port = openstack_networking_port_v2.{{ network_name }}.id
   }
 }
 
 # Create ssh keys
-resource "openstack_compute_keypair_v2" "{{ name ~ "_ssh_key" }}" {
+resource "openstack_compute_keypair_v2" "{{ vm_name ~ "_ssh_key" }}" {
   name       = "{{ ssh_user }}"
   public_key = "{{ ssh_key_file }}"
 }
 
 # Create floating ip
-resource "openstack_networking_floatingip_v2" "{{name ~ "_floating_ip"}}" {
+resource "openstack_networking_floatingip_v2" "{{vm_name ~ "_floating_ip"}}" {
   pool = "external"
   # fixed_ip = "{{ address }}"
 }
 
 # Attach floating ip to instance
-resource "openstack_compute_floatingip_associate_v2" "{{ name ~ "_floating_ip_association" }}" {
-  floating_ip = openstack_networking_floatingip_v2.{{ name ~ "_floating_ip" }}.address
-  instance_id = openstack_compute_instance_v2.{{ name }}.id
+resource "openstack_compute_floatingip_associate_v2" "{{ vm_name ~ "_floating_ip_association" }}" {
+  floating_ip = openstack_networking_floatingip_v2.{{ vm_name ~ "_floating_ip" }}.address
+  instance_id = openstack_compute_instance_v2.{{ vm_name }}.id
 }
-- 
GitLab