From 8b0280d4087143e2f067bb8c911b494e49d3d532 Mon Sep 17 00:00:00 2001 From: Debora Benedetto <debora.benedetto@hpecds.com> Date: Thu, 7 Apr 2022 15:04:41 +0200 Subject: [PATCH] refactoring --- api/InfrastructureTemplateController.py | 65 ++------- controller/Orchestrator.py | 123 ++++++++++++++++++ controller/PluginOrchestrator.py | 24 ---- icgparser/ModelParser.py | 3 +- input_file_generated/ir.json | 45 +------ main.py | 33 +++-- .../nginx_openstack/terraform/main.tf | 108 +++------------ 7 files changed, 174 insertions(+), 227 deletions(-) create mode 100644 controller/Orchestrator.py delete mode 100644 controller/PluginOrchestrator.py diff --git a/api/InfrastructureTemplateController.py b/api/InfrastructureTemplateController.py index fac0f46..a40c56d 100644 --- a/api/InfrastructureTemplateController.py +++ b/api/InfrastructureTemplateController.py @@ -1,12 +1,7 @@ import logging -import json -import tarfile -import uuid - from fastapi import APIRouter, Body from fastapi.responses import FileResponse -from controller.PluginOrchestrator import create_infrastructure_files -from icgparser import ModelParser +from controller import Orchestrator api_router = APIRouter() @@ -16,58 +11,16 @@ base_compress_file_name = "iac_files_" @api_router.post("/infrastructure/files") 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) + compress_folder_info = Orchestrator.create_iac_from_intermediate_representation(intermediate_representation) + return FileResponse(compress_folder_info.file_path, media_type='application/octet-stream', + filename=compress_folder_info.filename) @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() - intermediate_representation = ModelParser.parse_model(model_path=temp_model_file_path) - intermediate_representation = reorganize_info(intermediate_representation) - save(intermediate_representation, "input_file_generated/ir.json") - template_generated_folder = create_infrastructure_files(intermediate_representation) - 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/" - prefix_path = "" - logging.info("Compressing folder %s into destination %s", prefix_path + source_folder, - prefix_path + dest_file_name) - with tarfile.open(prefix_path + dest_file_name, "w:gz") as tar: - tar.add(source_folder, arcname='.') - return prefix_path + dest_file_name - - -def save(data, file_path): - file = open(file_path, "w") - if isinstance(data, dict): - data = json.dumps(data, indent=2, sort_keys=True) - print(data) - file.write(data) - file.close() - -def reorganize_info(intermediate_repr): - computing_group_list = [] - groups = intermediate_repr["steps"][0]["data"]["computingGroup"][0] - for key in groups: - if not key == "name": - computing_group_list.append(groups[key]) - intermediate_repr["steps"][0]["data"]["computingGroup"] = computing_group_list - return intermediate_repr + compress_folder_info = Orchestrator.create_iac_from_doml(model=data, metamodel_directory="icgparser/doml", + is_multiecore_metamodel=False) + logging.info(f"file_path: {compress_folder_info.file_path}, filename: {compress_folder_info.filename}") + return FileResponse(path=compress_folder_info.filename, media_type='application/octet-stream', ## TODO change path into compress_folder_info.file_path + filename=compress_folder_info.filename) diff --git a/controller/Orchestrator.py b/controller/Orchestrator.py new file mode 100644 index 0000000..cea3b02 --- /dev/null +++ b/controller/Orchestrator.py @@ -0,0 +1,123 @@ +import json +import logging +import tarfile +import uuid +from icgparser import ModelParser +from plugin import AnsiblePlugin, TerraformPlugin + + +class CompressFolder: + def __init__(self, file_path, filename): + self.file_path = file_path, + self.filename = filename + +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) + + +def create_temp_file_for_model(model, output_folder): + logging.info(f"Writing model file in temp folder at {output_folder} for parsing") + + +def save_file(data, file_path): + logging.info(f"Saving data at: {file_path}") + file = open(file_path, "w") + if isinstance(data, dict): + data = json.dumps(data, indent=2, sort_keys=True) + print(data) + file.write(data) + file.close() + + +def reorganize_info(intermediate_repr): + logging.info("Reorganizing intermediate representation") + computing_group_list = [] + if "computingGroup" in intermediate_repr["steps"][0]["data"].keys(): + groups = intermediate_repr["steps"][0]["data"]["computingGroup"][0] + for key in groups: + if not key == "name": + computing_group_list.append(groups[key]) + intermediate_repr["steps"][0]["data"]["computingGroup"] = computing_group_list + return intermediate_repr + + +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/" + prefix_path = "" + folder_path = prefix_path + dest_file_name + "" + logging.info(f"Compressing folder {source_folder} into destination {folder_path}") + with tarfile.open(folder_path, "w:gz") as tar: + tar.add(source_folder, arcname='.') + return folder_path + + +def create_temp_model_file(model_xml): + logging.info("Saving model in temp file") + temp_model_file_path = "icgparser/doml/nginx-openstack.domlx" + save_file(model_xml, temp_model_file_path) + logging.info(f"Successfully saved model in temp file at {temp_model_file_path}") + return temp_model_file_path + +def create_intermediate_representation(model_path, is_multiecore_metamodel, metamodel_directory): + logging.info("Calling ICG Parser for creating intermediate representation") + intermediate_representation = ModelParser.parse_model(model_path=model_path, + is_multiecore_metamodel=is_multiecore_metamodel, + metamodel_directory=metamodel_directory) + intermediate_representation = reorganize_info(intermediate_representation) + logging.info("Successfully created intermediate representation") + intermediate_representation_path = "input_file_generated/ir.json" + save_file(intermediate_representation, intermediate_representation_path) + logging.info(f"Saved intermediate representation at {intermediate_representation_path}") + return intermediate_representation + + +def compress_iac_folder(template_generated_folder): + base_compress_file_name = "iac_files_" + compress_file_name = random_file_name_generation(base_compress_file_name) + compress_file_folder_path = compress_file(template_generated_folder, compress_file_name) + logging.info(f"Successfully created iac files, available at {compress_file_folder_path}") + compress_folder_info = CompressFolder(file_path=compress_file_folder_path, filename=compress_file_name) + logging.info(f"######################### {compress_folder_info.file_path}") ## TODO fix, is tuple instead of string + return compress_folder_info + +def create_iac_from_intermediate_representation(intermediate_representation): + logging.info("Creating iac files") + template_generated_folder = create_infrastructure_files(intermediate_representation) + return template_generated_folder + +def create_iac_from_doml(model, is_multiecore_metamodel, metamodel_directory): + logging.info("Creating iac files: parse and plugins will be called") + model_path = create_temp_model_file(model_xml=model) + intermediate_representation = create_intermediate_representation(model_path, is_multiecore_metamodel, + metamodel_directory) + template_generated_folder = create_iac_from_intermediate_representation(intermediate_representation) + compress_folder_info = compress_iac_folder(template_generated_folder) + return compress_folder_info + +def create_iac_from_doml_path(model_path, is_multiecore_metamodel, metamodel_directory): + intermediate_representation = create_intermediate_representation(model_path, is_multiecore_metamodel, + metamodel_directory) + template_generated_folder = create_iac_from_intermediate_representation(intermediate_representation) + compress_folder_info = compress_iac_folder(template_generated_folder) + return compress_folder_info diff --git a/controller/PluginOrchestrator.py b/controller/PluginOrchestrator.py deleted file mode 100644 index 998f380..0000000 --- a/controller/PluginOrchestrator.py +++ /dev/null @@ -1,24 +0,0 @@ -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/icgparser/ModelParser.py b/icgparser/ModelParser.py index 6c7e060..6b5b072 100644 --- a/icgparser/ModelParser.py +++ b/icgparser/ModelParser.py @@ -88,4 +88,5 @@ def parse_model(model_path, is_multiecore_metamodel, metamodel_directory): rset = DomlParserUtilities.load_metamodel(metamodel_directory=metamodel_directory, is_multiecore=is_multiecore_metamodel) doml_model = DomlParserUtilities.load_model(model_path, rset) - create_intermediate_representation(doml_model) + intermediate_representation = create_intermediate_representation(doml_model) + return intermediate_representation diff --git a/input_file_generated/ir.json b/input_file_generated/ir.json index 3b81dd2..51d42f2 100644 --- a/input_file_generated/ir.json +++ b/input_file_generated/ir.json @@ -3,48 +3,11 @@ "steps": [ { "data": { - "computingGroup": [ + "credentials": [ { - "addressRanges": [ - "0.0.0.0/0", - "::/0" - ], - "kind": "EGRESS", - "name": "out_all", - "protocol": "-1" - }, - { - "addressRanges": [ - "0.0.0.0/0", - "::/0" - ], - "fromPort": 80, - "kind": "INGRESS", - "name": "http", - "protocol": "tcp", - "toPort": 80 - }, - { - "addressRanges": [ - "0.0.0.0/0", - "::/0" - ], - "fromPort": 443, - "kind": "INGRESS", - "name": "https", - "protocol": "tcp", - "toPort": 443 - }, - { - "addressRanges": [ - "0.0.0.0/0", - "::/0" - ], - "fromPort": 22, - "kind": "INGRESS", - "name": "ssh", - "protocol": "tcp", - "toPort": 22 + "algorithm": "RSA", + "bits": 4096, + "name": "ssh_key" } ], "networks": [ diff --git a/main.py b/main.py index 619fe71..f0686dd 100644 --- a/main.py +++ b/main.py @@ -1,47 +1,48 @@ -import json import logging import sys - from fastapi import FastAPI - import api.InfrastructureTemplateController -from api.InfrastructureTemplateController import compress_file -from controller.PluginOrchestrator import create_infrastructure_files -from icgparser import ModelParser, ModelPrinter +from controller import Orchestrator +from icgparser import ModelPrinter fast_api = FastAPI() fast_api.include_router(api.InfrastructureTemplateController.api_router) logging.getLogger().setLevel(logging.INFO) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # Parse parameters -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- skip_next = False doml_directory = "./doml" model_filename = "./nginx-openstack_v2_multiecores.domlx" load_split_model = True output_file_name = "iac_files.tar.gz" + # get metamodel directory from command line def param_dir(pos, list): global doml_directory global skip_next - doml_directory = list[pos+1] + doml_directory = list[pos + 1] print(f" doml_directory = {doml_directory} model_filename = {model_filename}") skip_next = True + def param_help(pos, list): print(f"\nUsage: {sys.argv[0]} [-h] [-d <doml_directory>] [--single] <model_filename>\n") sys.exit() + # indicate to load the single-file metamodel (doml.ecore) instead of the split one def param_single(pos, list): global load_split_model print(f"--> param_single({pos},{list}") load_split_model = False -options = {'-d': param_dir, '-h': param_help, '--single_mmodel': param_single, '--single': param_single, '--output': output_file_name} + +options = {'-d': param_dir, '-h': param_help, '--single_mmodel': param_single, '--single': param_single, + '--output': output_file_name} argc = len(sys.argv) paramlist = sys.argv[1:] for i, param in enumerate(paramlist): @@ -57,10 +58,8 @@ for i, param in enumerate(paramlist): if __name__ == '__main__': ModelPrinter.print_model(model_path=model_filename, is_multiecore_metamodel=load_split_model, - metamodel_directory=doml_directory) - # ModelParser.parse_model(model_path=model_filename, is_multiecore_metamodel=load_split_model, - # metamodel_directory=doml_directory) - # with open("input_file_generated/ir.json") as json_file: - # data = json.load(json_file) - # template_generated_folder = create_infrastructure_files(data) - # compress_file_folder = compress_file(template_generated_folder, output_file_name) + metamodel_directory=doml_directory) + compress_folder_info = Orchestrator.create_iac_from_doml_path(model_path=model_filename, + is_multiecore_metamodel=load_split_model, + metamodel_directory=doml_directory) + diff --git a/output_files_generated/nginx_openstack/terraform/main.tf b/output_files_generated/nginx_openstack/terraform/main.tf index 13429e8..4b0f48d 100644 --- a/output_files_generated/nginx_openstack/terraform/main.tf +++ b/output_files_generated/nginx_openstack/terraform/main.tf @@ -35,72 +35,33 @@ data "openstack_networking_secgroup_v2" "default" { name = "default" tenant_id = data.openstack_identity_project_v3.test_tenant.id } -resource "openstack_compute_secgroup_v2" "out_all" { - name = "out_all" - description = "Security group rule for port -" - rule { - from_port = - to_port = - ip_protocol = "-1" - cidr = [ - - 0.0.0.0/0, - - ::/0, - - ] +# Create virtual machine +resource "openstack_compute_instance_v2" "vm1" { + name = "nginx-host" + image_name = "i1" + flavor_name = "small" + key_pair = openstack_compute_keypair_v2.ssh_key.name + network { + port = openstack_networking_port_v2.net1.id } } -resource "openstack_compute_secgroup_v2" "http" { - name = "http" - description = "Security group rule for port -" - rule { - from_port = 80 - to_port = 80 - ip_protocol = "tcp" - cidr = [ - - 0.0.0.0/0, - - ::/0, - - ] - } +# Create ssh keys +resource "openstack_compute_keypair_v2" "ssh_key" { + name = "ubuntu" + public_key = "/home/user1/.ssh/openstack.key" } -resource "openstack_compute_secgroup_v2" "https" { - name = "https" - description = "Security group rule for port -" - rule { - from_port = 443 - to_port = 443 - ip_protocol = "tcp" - cidr = [ - - 0.0.0.0/0, - - ::/0, - - ] - } +# Create floating ip +resource "openstack_networking_floatingip_v2" "vm1_floating_ip" { + pool = "external" + # fixed_ip = "" } -resource "openstack_compute_secgroup_v2" "ssh" { - name = "ssh" - description = "Security group rule for port -" - rule { - from_port = 22 - to_port = 22 - ip_protocol = "tcp" - cidr = [ - - 0.0.0.0/0, - - ::/0, - - ] - } +# Attach floating ip to instance +resource "openstack_compute_floatingip_associate_v2" "vm1_floating_ip_association" { + floating_ip = openstack_networking_floatingip_v2.vm1_floating_ip.address + instance_id = openstack_compute_instance_v2.vm1.id } ## Network @@ -142,32 +103,3 @@ resource "openstack_networking_router_interface_v2" "net1_router_interface" { subnet_id = openstack_networking_subnet_v2.net1_subnet.id } -# Create virtual machine -resource "openstack_compute_instance_v2" "vm1" { - name = "nginx-host" - image_name = "i1" - flavor_name = "small" - key_pair = openstack_compute_keypair_v2.ssh_key.name - network { - port = openstack_networking_port_v2.net1.id - } -} - -# Create ssh keys -resource "openstack_compute_keypair_v2" "ssh_key" { - name = "ubuntu" - public_key = "/home/user1/.ssh/openstack.key" -} - -# Create floating ip -resource "openstack_networking_floatingip_v2" "vm1_floating_ip" { - pool = "external" - # fixed_ip = "" -} - -# Attach floating ip to instance -resource "openstack_compute_floatingip_associate_v2" "vm1_floating_ip_association" { - floating_ip = openstack_networking_floatingip_v2.vm1_floating_ip.address - instance_id = openstack_compute_instance_v2.vm1.id -} - -- GitLab