diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index ec70a1bd1d504f2770f92b4316a7b016964148c1..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,91 +0,0 @@ -include: - - project: piacere/private/t23-ci-setup - ref: main - file: - - gitlab-ci-scripts/utils.gitlab-ci.yml - - # Image tag variables generation job ------------- - # Stage: variable-generation --------------------- - - gitlab-ci-scripts/generate-variables.gitlab-ci.yml - - # Downstream t23-ci-setup pipeline trigger job --- - # Stage: integration-tests-publish-deploy -------- - - gitlab-ci-scripts/trigger-downstream.gitlab-ci.yml - -variables: - # ------------------------ - # Component image tag data - # ------------------------ - COMPONENT_WP: wp4 - DMC_IMAGE_NAME: dmc - - # ------------------------------------------ - # Space-separated component image abbreviation list - # used to generate image tags and related variables. - # It is also passed to the downstream integration tests, - # publication and deployment pipeline - # ------------------------------------------ - IMAGE_NAMES: "$DMC_IMAGE_NAME" - -stages: - - variable-generation - - build - - security - - functional-tests - - integration-tests-publish-deploy - -# Build jobs ---------------------- - -build-temp-dmc: - stage: build - variables: - TMP_IMAGE: "$TMP_IMAGE_DMC" - DOCKERFILE_PATH: "." - trigger: !reference [.trigger-build] - rules: - - if: $CI_COMMIT_BRANCH =~ /^y3/ - -# Security job ------------------------ - -security-trivy-dmc: - stage: security - variables: - TMP_IMAGE: "$TMP_IMAGE_DMC" - trigger: !reference [.trigger-security-trivy] - needs: - - job: build-temp-dmc - - job: generate-variables - artifacts: true - rules: - - if: $CI_COMMIT_BRANCH =~ /^y3/ - -# functional tests job ------------------------ - -run-functional-tests: - image: $DOCKER_IMAGE - stage: functional-tests - services: - - $DOCKER_DIND_IMAGE - variables: - TESTS_CONTAINER_NAME: functional-tester - before_script: - - !reference [.artifactory-login] - script: - # Tests assume port 8080, while the Dockerfile CMD runs the server on port 80. - # Thus, we need to override the command so that the server is run on port 8080. - - docker run --name $TESTS_CONTAINER_NAME -d -e "UVICORN_PORT=8080" $TMP_IMAGE_DMC - # Install everything required for the tests. - - docker exec -i $TESTS_CONTAINER_NAME /bin/bash -c - "pip install -r requirements.txt" - # Run the tests. - - docker exec -i $TESTS_CONTAINER_NAME /bin/bash -c "python -m pytest tests/test_mc_openapi.py -n auto" - # Stop the tests container. - - docker stop $TESTS_CONTAINER_NAME - needs: - - job: build-temp-dmc - - job: generate-variables - artifacts: true - tags: - - docker - rules: - - if: $CI_COMMIT_BRANCH =~ /^y3/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000000000000000000000000000000000..cc65e73eb882dcfc036c5cda2f27f06747bb1254 --- /dev/null +++ b/.python-version @@ -0,0 +1,2 @@ +piacere-dmc +3.11.6 \ No newline at end of file diff --git a/docs/reference_index.rst b/docs/reference_index.rst index 78cb54ba0472be1c76f7ac94a5382137c34e2793..2d27fe271987ba543e7a96d578911e3e3fe54f89 100644 --- a/docs/reference_index.rst +++ b/docs/reference_index.rst @@ -15,3 +15,5 @@ For a comprehensive list of all the classes, attributes and associations support ----------------------------------------------- :doc:`Reference for DOML v3.0 <reference_v3.0>` ----------------------------------------------- +:doc:`Reference for DOML v3.1 <reference_v3.1>` +----------------------------------------------- diff --git a/docs/reference_v3.1.rst b/docs/reference_v3.1.rst new file mode 100644 index 0000000000000000000000000000000000000000..5fcd3814cd7eb584c3ce417cee2d80ca39d517b2 --- /dev/null +++ b/docs/reference_v3.1.rst @@ -0,0 +1,696 @@ +DOML v3.1 Reference +============================= + + +commons +^^^^^^^ + +.. _v3.1_commons_BProperty: + +BProperty +""""""""" +*Inherits from* :ref:`Property <v3.1_commons_Property>` + +* Attributes: + * ``value`` [Boolean] + +.. _v3.1_commons_Configuration: + +Configuration +""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``deployments`` → Deployment [0..*] + +.. _v3.1_commons_Credentials: + +Credentials +""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + + +.. _v3.1_commons_DOMLElement: + +DOMLElement +""""""""""" +* Associations: + * ``annotations`` → Property [0..*] +* Attributes: + * ``name`` [String] + * ``description`` [String] + +.. _v3.1_commons_DeployableElement: + +DeployableElement +""""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + + +.. _v3.1_commons_Deployment: + +Deployment +"""""""""" +* Associations: + * ``component`` → DeployableElement [1..1] + * ``node`` → InfrastructureElement [1..1] + +.. _v3.1_commons_FProperty: + +FProperty +""""""""" +*Inherits from* :ref:`Property <v3.1_commons_Property>` + +* Attributes: + * ``value`` [String] + +.. _v3.1_commons_IProperty: + +IProperty +""""""""" +*Inherits from* :ref:`Property <v3.1_commons_Property>` + +* Attributes: + * ``value`` [Integer] + +.. _v3.1_commons_KeyPair: + +KeyPair +""""""" +*Inherits from* :ref:`Credentials <v3.1_commons_Credentials>` + +* Attributes: + * ``user`` [String] + * ``key`` [String] + * ``algorithm`` [String] + * ``bits`` [Integer] + +.. _v3.1_commons_ListProperty: + +ListProperty +"""""""""""" +*Inherits from* :ref:`Property <v3.1_commons_Property>` + +* Associations: + * ``values`` → Property [0..*] + +.. _v3.1_commons_Property: + +Property +"""""""" +* Associations: + * ``reference`` → DOMLElement [0..1] +* Attributes: + * ``key`` [String] + +.. _v3.1_commons_SProperty: + +SProperty +""""""""" +*Inherits from* :ref:`Property <v3.1_commons_Property>` + +* Attributes: + * ``value`` [String] + +.. _v3.1_commons_Source: + +Source +"""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``entry`` [String] + * ``inventory`` [String] + * ``backend`` [String] + +.. _v3.1_commons_UserPass: + +UserPass +"""""""" +*Inherits from* :ref:`Credentials <v3.1_commons_Credentials>` + +* Attributes: + * ``username`` [String] + * ``password`` [String] + +application +^^^^^^^^^^^ + +.. _v3.1_application_ApplicationComponent: + +ApplicationComponent +"""""""""""""""""""" +*Inherits from* :ref:`DeployableElement <v3.1_commons_DeployableElement>` + + +.. _v3.1_application_ApplicationLayer: + +ApplicationLayer +"""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``components`` → ApplicationComponent [0..*] + +.. _v3.1_application_DBMS: + +DBMS +"""" +*Inherits from* :ref:`SoftwareComponent <v3.1_application_SoftwareComponent>` + + +.. _v3.1_application_SaaS: + +SaaS +"""" +*Inherits from* :ref:`ApplicationComponent <v3.1_application_ApplicationComponent>` + +* Associations: + * ``exposedInterfaces`` → SoftwareInterface [0..*] +* Attributes: + * ``licenseCost`` [String] + +.. _v3.1_application_SaaSDBMS: + +SaaSDBMS +"""""""" +*Inherits from* :ref:`SaaS <v3.1_application_SaaS>` + +* Attributes: + * ``databaseName`` [String] + * ``engine`` [String] + * ``engineVersion`` [String] + +.. _v3.1_application_SoftwareComponent: + +SoftwareComponent +""""""""""""""""" +*Inherits from* :ref:`ApplicationComponent <v3.1_application_ApplicationComponent>` + +* Associations: + * ``exposedInterfaces`` → SoftwareInterface [0..*] + * ``consumedInterfaces`` → SoftwareInterface [0..*] + * ``src`` → Source [0..1] +* Attributes: + * ``isPersistent`` [Boolean] + * ``licenseCost`` [String] + +.. _v3.1_application_SoftwareInterface: + +SoftwareInterface +""""""""""""""""" +*Inherits from* :ref:`ApplicationComponent <v3.1_application_ApplicationComponent>` + +* Attributes: + * ``endPoint`` [String] + +infrastructure +^^^^^^^^^^^^^^ + +.. _v3.1_infrastructure_AutoScalingGroup: + +AutoScalingGroup +"""""""""""""""" +*Inherits from* :ref:`ComputingGroup <v3.1_infrastructure_ComputingGroup>` + +* Associations: + * ``machineDefinition`` → VirtualMachine [1..1] +* Attributes: + * ``min`` [Integer] + * ``max`` [Integer] + * ``loadBalancer`` [String] + +.. _v3.1_infrastructure_ComputingGroup: + +ComputingGroup +"""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``groupedNodes`` → ComputingNode [0..*] + +.. _v3.1_infrastructure_ComputingNode: + +ComputingNode +""""""""""""" +*Inherits from* :ref:`Node <v3.1_infrastructure_Node>` + +* Associations: + * ``location`` → Location [0..1] + * ``credentials`` → Credentials [0..1] + * ``group`` → ComputingGroup [0..1] + * ``nodeSpecificMonitoring`` → MonitoringRule [0..1] +* Attributes: + * ``architecture`` [String] + * ``os`` [String] + * ``memory_mb`` [Integer] + * ``memory_kb`` [Integer] + * ``storage`` [Integer] + * ``cpu_count`` [Integer] + * ``cost`` [Integer] + * ``disabledMonitorings`` [String] + +.. _v3.1_infrastructure_ComputingNodeGenerator: + +ComputingNodeGenerator +"""""""""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``uri`` [String] + * ``kind`` [GeneratorKind] + +.. _v3.1_infrastructure_Container: + +Container +""""""""" +*Inherits from* :ref:`ComputingNode <v3.1_infrastructure_ComputingNode>` + +* Associations: + * ``generatedFrom`` → ContainerImage [0..1] + * ``hostConfigs`` → ContainerHostConfig [0..*] + * ``networks`` → ContainerNetwork [0..*] + * ``volumes`` → ContainerVolume [0..*] + * ``dependsOn`` → Container [0..*] + +.. _v3.1_infrastructure_ContainerConfig: + +ContainerConfig +""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``iface`` → NetworkInterface [0..1] +* Attributes: + * ``container_port`` [Integer] + * ``vm_port`` [Integer] + +.. _v3.1_infrastructure_ContainerGroup: + +ContainerGroup +"""""""""""""" +*Inherits from* :ref:`ComputingGroup <v3.1_infrastructure_ComputingGroup>` + +* Associations: + * ``services`` → Container [1..*] + * ``networks`` → ContainerNetwork [0..*] + * ``volumes`` → ContainerVolume [0..*] + +.. _v3.1_infrastructure_ContainerHostConfig: + +ContainerHostConfig +""""""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``environment_variables`` → SProperty [0..*] + * ``host`` → ComputingNode [0..1] + * ``configurations`` → ContainerConfig [0..*] + +.. _v3.1_infrastructure_ContainerImage: + +ContainerImage +"""""""""""""" +*Inherits from* :ref:`ComputingNodeGenerator <v3.1_infrastructure_ComputingNodeGenerator>` + +* Associations: + * ``generatedContainers`` → Container [0..*] + +.. _v3.1_infrastructure_ContainerNetwork: + +ContainerNetwork +"""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``containerNetworkName`` [String] + +.. _v3.1_infrastructure_ContainerVolume: + +ContainerVolume +""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``containerVolumeName`` [String] + * ``path`` [String] + +.. _v3.1_infrastructure_ExecutionEnvironment: + +ExecutionEnvironment +"""""""""""""""""""" +*Inherits from* :ref:`InfrastructureElement <v3.1_infrastructure_InfrastructureElement>` + +* Associations: + * ``location`` → Location [0..1] + * ``network`` → Network [0..1] + * ``securityGroups`` → SecurityGroup [0..*] +* Attributes: + * ``size`` [Integer] + * ``maxSize`` [Integer] + +.. _v3.1_infrastructure_ExtInfrastructureElement: + +ExtInfrastructureElement +"""""""""""""""""""""""" +*Inherits from* :ref:`InfrastructureElement <v3.1_infrastructure_InfrastructureElement>` + + +.. _v3.1_infrastructure_FunctionAsAService: + +FunctionAsAService +"""""""""""""""""" +*Inherits from* :ref:`InfrastructureElement <v3.1_infrastructure_InfrastructureElement>` + +* Attributes: + * ``cost`` [Integer] + +.. _v3.1_infrastructure_InfrastructureElement: + +InfrastructureElement +""""""""""""""""""""" +*Inherits from* :ref:`DeployableElement <v3.1_commons_DeployableElement>` + + +.. _v3.1_infrastructure_InfrastructureLayer: + +InfrastructureLayer +""""""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``nodes`` → ComputingNode [0..*] + * ``generators`` → ComputingNodeGenerator [0..*] + * ``storages`` → Storage [0..*] + * ``faas`` → FunctionAsAService [0..*] + * ``credentials`` → Credentials [0..*] + * ``groups`` → ComputingGroup [0..*] + * ``securityGroups`` → SecurityGroup [0..*] + * ``networks`` → Network [0..*] + * ``rules`` → MonitoringRule [0..*] + * ``executionEnvironments`` → ExecutionEnvironment [0..*] + +.. _v3.1_infrastructure_InternetGateway: + +InternetGateway +""""""""""""""" +*Inherits from* :ref:`Node <v3.1_infrastructure_Node>` + +* Attributes: + * ``address`` [String] + +.. _v3.1_infrastructure_Location: + +Location +"""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``region`` [String] + * ``zone`` [String] + +.. _v3.1_infrastructure_MonitoringRule: + +MonitoringRule +"""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``condition`` [String] + * ``strategy`` [String] + * ``strategyConfigurationString`` [String] + +.. _v3.1_infrastructure_Network: + +Network +""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``connectedIfaces`` → NetworkInterface [0..*] + * ``gateways`` → InternetGateway [0..*] + * ``subnets`` → Subnet [0..*] +* Attributes: + * ``protocol`` [String] + * ``cidr`` [Integer] + +.. _v3.1_infrastructure_NetworkInterface: + +NetworkInterface +"""""""""""""""" +*Inherits from* :ref:`InfrastructureElement <v3.1_infrastructure_InfrastructureElement>` + +* Associations: + * ``belongsTo`` → Network [0..1] + * ``associated`` → SecurityGroup [0..1] +* Attributes: + * ``endPoint`` [Integer] + * ``speed`` [String] + +.. _v3.1_infrastructure_Node: + +Node +"""" +*Inherits from* :ref:`InfrastructureElement <v3.1_infrastructure_InfrastructureElement>` + +* Associations: + * ``ifaces`` → NetworkInterface [0..*] + +.. _v3.1_infrastructure_PhysicalComputingNode: + +PhysicalComputingNode +""""""""""""""""""""" +*Inherits from* :ref:`ComputingNode <v3.1_infrastructure_ComputingNode>` + +* Associations: + * ``configInterface`` → NetworkInterface [0..1] + +.. _v3.1_infrastructure_Rule: + +Rule +"""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Attributes: + * ``kind`` [String] + * ``protocol`` [String] + * ``fromPort`` [Integer] + * ``toPort`` [Integer] + * ``cidr`` [String] + +.. _v3.1_infrastructure_SecurityGroup: + +SecurityGroup +""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``rules`` → Rule [0..*] + * ``ifaces`` → NetworkInterface [0..*] + +.. _v3.1_infrastructure_Storage: + +Storage +""""""" +*Inherits from* :ref:`Node <v3.1_infrastructure_Node>` + +* Attributes: + * ``label`` [String] + * ``size_gb`` [Integer] + * ``cost`` [Integer] + +.. _v3.1_infrastructure_Subnet: + +Subnet +"""""" +*Inherits from* :ref:`Network <v3.1_infrastructure_Network>` + +* Associations: + * ``connectedTo`` → Network [0..*] + +.. _v3.1_infrastructure_Swarm: + +Swarm +""""" +*Inherits from* :ref:`ComputingGroup <v3.1_infrastructure_ComputingGroup>` + +* Associations: + * ``roles`` → SwarmRole [0..*] + +.. _v3.1_infrastructure_SwarmRole: + +SwarmRole +""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``nodes`` → ComputingNode [0..*] +* Attributes: + * ``kind`` [String] + +.. _v3.1_infrastructure_VMImage: + +VMImage +""""""" +*Inherits from* :ref:`ComputingNodeGenerator <v3.1_infrastructure_ComputingNodeGenerator>` + +* Associations: + * ``generatedVMs`` → VirtualMachine [0..*] + +.. _v3.1_infrastructure_VirtualMachine: + +VirtualMachine +"""""""""""""" +*Inherits from* :ref:`ComputingNode <v3.1_infrastructure_ComputingNode>` + +* Associations: + * ``generatedFrom`` → VMImage [0..1] + * ``configInterface`` → NetworkInterface [0..1] +* Attributes: + * ``sizeDescription`` [String] + +concrete +^^^^^^^^ + +.. _v3.1_concrete_AutoScalingGroup: + +AutoScalingGroup +"""""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → AutoScalingGroup [0..1] +* Attributes: + * ``vm_type`` [String] + +.. _v3.1_concrete_ConcreteElement: + +ConcreteElement +""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``refs`` → ConcreteElement [0..*] +* Attributes: + * ``resourceName`` [String] + * ``configurationScript`` [String] + * ``preexisting`` [Boolean] + +.. _v3.1_concrete_ConcreteInfrastructure: + +ConcreteInfrastructure +"""""""""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``providers`` → RuntimeProvider [0..*] + +.. _v3.1_concrete_ContainerImage: + +ContainerImage +"""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → ContainerImage [0..1] + +.. _v3.1_concrete_ExecutionEnvironment: + +ExecutionEnvironment +"""""""""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → ExecutionEnvironment [0..1] +* Attributes: + * ``instance_type`` [String] + * ``storage_type`` [String] + +.. _v3.1_concrete_FunctionAsAService: + +FunctionAsAService +"""""""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → FunctionAsAService [0..1] + +.. _v3.1_concrete_GenericResource: + +GenericResource +""""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Attributes: + * ``type`` [String] + +.. _v3.1_concrete_Network: + +Network +""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``subnets`` → Subnet [0..*] + * ``maps`` → Network [0..1] +* Attributes: + * ``protocol`` [String] + * ``addressRange`` [String] + +.. _v3.1_concrete_RuntimeProvider: + +RuntimeProvider +""""""""""""""" +*Inherits from* :ref:`DOMLElement <v3.1_commons_DOMLElement>` + +* Associations: + * ``resources`` → GenericResource [0..*] + * ``vms`` → VirtualMachine [0..*] + * ``executionEnvironments`` → ExecutionEnvironment [0..*] + * ``vmImages`` → VMImage [0..*] + * ``containerImages`` → ContainerImage [0..*] + * ``networks`` → Network [0..*] + * ``storages`` → Storage [0..*] + * ``faas`` → FunctionAsAService [0..*] + * ``autoScalingGroups`` → AutoScalingGroup [0..*] + +.. _v3.1_concrete_Storage: + +Storage +""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → Storage [0..1] + +.. _v3.1_concrete_Subnet: + +Subnet +"""""" +*Inherits from* :ref:`Network <v3.1_concrete_Network>` + + +.. _v3.1_concrete_VMImage: + +VMImage +""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → VMImage [0..1] +* Attributes: + * ``image_name`` [String] + +.. _v3.1_concrete_VirtualMachine: + +VirtualMachine +"""""""""""""" +*Inherits from* :ref:`ConcreteElement <v3.1_concrete_ConcreteElement>` + +* Associations: + * ``maps`` → VirtualMachine [0..1] +* Attributes: + * ``vm_type`` [String] + + + diff --git a/mc_openapi/__init__.py b/mc_openapi/__init__.py index 41566c9ed937ae6860dbedce2f23f01db5039b8c..dc0a25b72c93dd2fc3e20ee0638423e5037c330a 100644 --- a/mc_openapi/__init__.py +++ b/mc_openapi/__init__.py @@ -1 +1 @@ -__version__ = '2.6.2' +__version__ = '3.1.3' diff --git a/mc_openapi/__main__.py b/mc_openapi/__main__.py index 3c7a2e811cd96c2d9ea11229ae6e7830ffe55787..7b91937b4b38b5b12bc986b33eae6790d7e13528 100644 --- a/mc_openapi/__main__.py +++ b/mc_openapi/__main__.py @@ -3,6 +3,7 @@ import argparse import logging from logging.config import dictConfig import re +import traceback from tabulate import tabulate import uvicorn @@ -83,42 +84,56 @@ else: # Read DOML file from path doml_xmi = xmif.read() - # Read DOMLR from path - domlr_src = None - if domlr_path: - with open(domlr_path, "r") as domlr_file: - # Read the user requirements written in DSL - domlr_src = domlr_file.read() - - # Config the model checker - dmc = init_model(doml_xmi, doml_ver) - - ####### END OF INIT STEP ####### - if not args.synth: # Verify Model/CSP Compatibility - - # Check CSP Compatibility - if args.csp: - csp = verify_csp_compatibility(dmc) - print_csp_results(csp) - else: - res = verify_model(dmc, domlr_src, args.threads, args.consistency, args.skip_builtin) - - print("[RESULT]") - if res['result'] == MCResult.sat.name: - print(res['description']) + try: + # Read DOMLR from path + domlr_src = None + if domlr_path: + with open(domlr_path, "r") as domlr_file: + # Read the user requirements written in DSL + domlr_src = domlr_file.read() + + # Config the model checker + dmc = init_model(doml_xmi, doml_ver) + ####### END OF INIT STEP ####### + if not args.synth: # Verify Model/CSP Compatibility + + # Check CSP Compatibility + if args.csp: + csp = verify_csp_compatibility(dmc) + print_csp_results(csp) else: - print(res['result']) - print("[ERRORS]") - print("\033[91m{}\033[00m".format(res['description'])) - - csp_res = res.get('csp') - if csp_res: - print("[CSP COMPATIBILITY RESULTS]") - print_csp_results(csp_res) - - - - else: # Synthesis - synthesize_model(dmc, domlr_src, args.tries) - # TODO: Do something with the results + + res = verify_model(dmc, domlr_src, args.threads, args.consistency, args.skip_builtin) + + print("[RESULT]") + if res['result'] == MCResult.sat.name: + print(res['description']) + + print("[STATS]") + for result in res['all_reqs']: + print(f"\t{result['id']} - {result['time']} - {result['result']}") + else: + print(res['result']) + print("[ERRORS]") + print("\033[91m{}\033[00m".format(res['description'])) + + print("[STATS]") + for result in res['all_reqs']: + print(f"\t{result['id']} - {result['time']} - {result['result']}") + + csp_res = res.get('csp') + if csp_res: + print("[CSP COMPATIBILITY RESULTS]") + print_csp_results(csp_res) + else: # Synthesis + synthesize_model(dmc, domlr_src, args.tries) + # TODO: Do something with the results + except Exception as e: + MSG_ERR_GENERIC = "An unknown error has occurred!\nTry with '-t 1' to get more detailed logs!\n\n" + err_msg = (e.message + if hasattr(e, 'message') + else MSG_ERR_GENERIC + traceback.format_exc()) + print(f"\033[91m[ERROR]\n{err_msg}\033[00m") + + \ No newline at end of file diff --git a/mc_openapi/api.py b/mc_openapi/api.py index f08700a05527b6107179eec9964971e48fe28b77..435f36a480fa4ade358d4988ba84bb2f6e328e5f 100644 --- a/mc_openapi/api.py +++ b/mc_openapi/api.py @@ -1,5 +1,7 @@ import logging +from logging.config import dictConfig import os +import sys import traceback from importlib.resources import files @@ -8,6 +10,7 @@ from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi.encoders import jsonable_encoder +from fastapi.logger import logger import mc_openapi.assets as ASSETS from mc_openapi.doml_mc import (init_model, verify_csp_compatibility, @@ -15,12 +18,16 @@ from mc_openapi.doml_mc import (init_model, verify_csp_compatibility, from mc_openapi.doml_mc.exceptions import * from mc_openapi.doml_mc.intermediate_model.metamodel import DOMLVersion from mc_openapi.doml_mc.mc import ModelChecker +import time assets = files(ASSETS) static_path = assets / "static" templates_path = assets / "templates" app = FastAPI() +print(">>> FastAPI+Uvicorn is incredibly asinine when it comes to logs, so lines prefixed with '>>>' are actually print(...)") +print(">>> API starting up...") + app.mount("/static", StaticFiles(directory=static_path), name="static") templates = Jinja2Templates(directory=templates_path) @@ -32,26 +39,42 @@ async def root(request: Request): def handleDOMLX(doml_xmi: bytes, callback) -> dict: doml_version_str: str = None doml_version: DOMLVersion = None + start_time = time.time() + + print(">>> Received DOMLX. Beginning validation...") + try: # First try to infer DOML version from ENV, then query params doml_version_str = os.environ.get("DOML_VERSION") if doml_version_str: doml_version = DOMLVersion.get(doml_version_str) - logging.info(f"Forcing DOML {doml_version.value}") + print(f">>> Forcing DOML {doml_version.value}") dmc = init_model(doml_xmi, doml_version) res = callback(dmc) - return res + elapsed_time_in_seconds = f"{time.time() - start_time:.4f}" + + print(f">>> Validation complete. It took {elapsed_time_in_seconds}s.") + res['elapsed_time'] = elapsed_time_in_seconds + return res + except KeyError as e: + ERR_MSG = f"Error: Key '{e.args[0]}' not found.\nVery likely, in the Model Checker requirements, the relationship '{e.args[0]}' is unknown.\nPerhaps this was parsed with the wrong DOML version, otherwise the DOML version you're using is currently unsupported." + logging.exception(e) + return { + "type": "error", + "message": ERR_MSG, + "debug_message": traceback.format_exc() + } except (RuntimeError, Exception) as e: ERR_MSG = "An error has occurred.\nIt could be an error within your DOML file.\nIf it persist, try specifying DOML version manually." logging.exception(e) return { "type": "error", - "message": e.message or ERR_MSG, + "message": e.message if hasattr(e, 'message') else ERR_MSG, "debug_message": traceback.format_exc() } diff --git a/mc_openapi/assets/csp/arch.yml b/mc_openapi/assets/csp/arch.yml index 41ae12f44a1c13755477aa1dddc50acf36f64c57..bfdc5f2611d9b7d1676fad1d337a398df10c38a8 100644 --- a/mc_openapi/assets/csp/arch.yml +++ b/mc_openapi/assets/csp/arch.yml @@ -12,5 +12,5 @@ azure: - x86 - ARM -bad_csp: - - PowerPC +# bad_csp: +# - PowerPC diff --git a/mc_openapi/assets/csp/keypair.yml b/mc_openapi/assets/csp/keypair.yml index 151293ed41ddff6e51f5cee3fa8c9d2b698d868c..b9083df88b50130dc3bd1362223cb0e50f4db2a5 100644 --- a/mc_openapi/assets/csp/keypair.yml +++ b/mc_openapi/assets/csp/keypair.yml @@ -7,10 +7,18 @@ aws: azure: - RSA - + - RSA1_5 + - RSA-OAEP + - RSA-OAEP-256 + - EC + - P-256 + - P-256K + - P-384 + - P-521 gcp: - Elliptic Curve - RSA + - ECDSA -bad_csp: - - OLD_ALGO +# bad_csp: +# - OLD_ALGO diff --git a/mc_openapi/assets/csp/minimum_setup.yml b/mc_openapi/assets/csp/minimum_setup.yml index 64e591c690ab151807cb54f5301241363159b632..05448f3eb52dace7f685f17d2a57cc53a80dc360 100644 --- a/mc_openapi/assets/csp/minimum_setup.yml +++ b/mc_openapi/assets/csp/minimum_setup.yml @@ -1,15 +1,16 @@ aws: - infrastructure_ComputingNode::os # AMI # - an Instance Type - - [infrastructure_ComputingNode::ifaces, infrastructure_NetworkInterface::associated] # NetworkInterface + # - [infrastructure_Node::ifaces, infrastructure_NetworkInterface::associated] # NetworkInterface + - [infrastructure_Node::ifaces, infrastructure_NetworkInterface::belongsTo] # NetworkInterface - infrastructure_ComputingNode::credentials # KeyPair azure: - infrastructure_ComputingNode::os # OS Image - - [infrastructure_ComputingNode::ifaces, infrastructure_NetworkInterface::belongsTo] # NetworkInterface + - [infrastructure_Node::ifaces, infrastructure_NetworkInterface::belongsTo] # NetworkInterface - infrastructure_ComputingNode::storage # Storage/VMSize gcp: - - infrastructure_ComputingNode::location + # - infrastructure_ComputingNode::location - infrastructure_ComputingNode::os # OS Image - infrastructure_ComputingNode::architecture \ No newline at end of file diff --git a/mc_openapi/assets/metamodels/doml_meta_v3.1.yaml b/mc_openapi/assets/metamodels/doml_meta_v3.1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c2dd82b4935821cb9d105ca2a249726a4bcc4b3f --- /dev/null +++ b/mc_openapi/assets/metamodels/doml_meta_v3.1.yaml @@ -0,0 +1,677 @@ +commons: + DOMLElement: + attributes: + name: + type: String + multiplicity: "0..1" + description: + type: String + multiplicity: "0..1" + associations: + annotations: + class: commons_Property + multiplicity: "0..*" + Property: + attributes: + key: + type: String + multiplicity: "0..1" + associations: + reference: + class: commons_DOMLElement + multiplicity: "0..1" + ListProperty: + superclass: commons_Property + associations: + values: + class: commons_Property + multiplicity: "0..*" + IProperty: + superclass: commons_Property + attributes: + value: + type: Integer + multiplicity: "0..1" + SProperty: + superclass: commons_Property + attributes: + value: + type: String + multiplicity: "0..1" + FProperty: + superclass: commons_Property + attributes: + value: + type: String + multiplicity: "0..1" + BProperty: + superclass: commons_Property + attributes: + value: + type: Boolean + multiplicity: "0..1" + Configuration: + superclass: commons_DOMLElement + associations: + deployments: + class: commons_Deployment + multiplicity: "0..*" + Credentials: + abstract: true + superclass: commons_DOMLElement + DeployableElement: + abstract: true + superclass: commons_DOMLElement # It's not present in the ECore, but without it breaks. + Deployment: + associations: + component: + class: commons_DeployableElement + multiplicity: "1" + node: + class: infrastructure_InfrastructureElement + multiplicity: "1" + KeyPair: + superclass: commons_Credentials + attributes: + user: + type: String + multiplicity: "0..1" + key: + type: String + multiplicity: "0..1" + algorithm: + type: String + multiplicity: "0..1" + bits: + type: Integer + multiplicity: "0..1" + UserPass: + superclass: commons_Credentials + attributes: + username: + type: String + multiplicity: "0..1" + password: + type: String + multiplicity: "0..1" + Source: + superclass: commons_DOMLElement + attributes: + entry: + type: String + multiplicity: "0..1" + inventory: + type: String + multiplicity: "0..1" + backend: + type: String + multiplicity: "0..1" +application: + ApplicationLayer: + superclass: commons_DOMLElement + associations: + components: + class: application_ApplicationComponent + multiplicity: "0..*" + ApplicationComponent: + superclass: commons_DeployableElement # and commons_DOMLElement too, but that's definitely wrong; keeping discarding DOMLElement since DeplElem inherits it. + SoftwareComponent: + superclass: application_ApplicationComponent + attributes: + isPersistent: + type: Boolean + multiplicity: "1" + default: false + licenseCost: + type: String + multiplicity: "0..1" + associations: + exposedInterfaces: + class: application_SoftwareInterface + multiplicity: "0..*" + consumedInterfaces: + class: application_SoftwareInterface + multiplicity: "0..*" + src: + class: commons_Source + multiplicity: "0..1" + SaaS: + superclass: application_ApplicationComponent + attributes: + licenseCost: + type: String + multiplicity: "0..1" + associations: + exposedInterfaces: + class: application_SoftwareInterface + multiplicity: "0..*" + SoftwareInterface: + superclass: application_ApplicationComponent + attributes: + endPoint: + type: String + multiplicity: "0..1" + DBMS: + superclass: application_SoftwareComponent + SaaSDBMS: + superclass: application_SaaS + attributes: + databaseName: + type: String + multiplicity: "0..1" + engine: + type: String + multiplicity: "0..1" + engineVersion: + type: String + multiplicity: "0..1" +infrastructure: + InfrastructureLayer: + superclass: commons_DOMLElement + associations: + nodes: + class: infrastructure_ComputingNode + multiplicity: "0..*" + generators: + class: infrastructure_ComputingNodeGenerator + multiplicity: "0..*" + storages: + class: infrastructure_Storage + multiplicity: "0..*" + faas: + class: infrastructure_FunctionAsAService + multiplicity: "0..*" + credentials: + class: commons_Credentials + multiplicity: "0..*" + groups: + class: infrastructure_ComputingGroup + multiplicity: "0..*" + securityGroups: + class: infrastructure_SecurityGroup + multiplicity: "0..*" + networks: + class: infrastructure_Network + multiplicity: "0..*" + rules: + class: infrastructure_MonitoringRule + multiplicity: "0..*" + executionEnvironments: + class: infrastructure_ExecutionEnvironment + multiplicity: "0..*" + MonitoringRule: + superclass: commons_DOMLElement + attributes: + condition: + type: String + multiplicity: "1" + strategy: + type: String + multiplicity: "1" + strategyConfigurationString: + type: String + multiplicity: "0..1" + InfrastructureElement: + superclass: commons_DeployableElement + Node: + superclass: infrastructure_InfrastructureElement + associations: + ifaces: + class: infrastructure_NetworkInterface + multiplicity: "0..*" + ComputingNode: + superclass: infrastructure_Node + attributes: + architecture: + type: String + multiplicity: "0..1" + os: + type: String + multiplicity: "0..1" + memory_mb: + type: Integer + multiplicity: "0..1" + memory_kb: # Missing in official Ecore, added by parser + type: Integer + multiplicity: "0..1" + storage: + type: Integer + multiplicity: "0..1" + cpu_count: + type: Integer + multiplicity: "0..1" + cost: + type: Integer # in cents + multiplicity: "0..1" + disabledMonitorings: + type: String + multiplicity: "0..1" + associations: + location: + class: infrastructure_Location + multiplicity: "0..1" + credentials: + class: commons_Credentials + multiplicity: "0..1" + group: + class: infrastructure_ComputingGroup + multiplicity: "0..1" + inverse_of: infrastructure_ComputingGroup::groupedNodes + nodeSpecificMonitoring: + class: infrastructure_MonitoringRule + multiplicity: "0..1" + PhysicalComputingNode: + superclass: infrastructure_ComputingNode + associations: + configInterface: + class: infrastructure_NetworkInterface + multiplicity: "0..1" + VirtualMachine: + superclass: infrastructure_ComputingNode + attributes: + sizeDescription: + type: String + multiplicity: "0..1" + associations: + generatedFrom: + class: infrastructure_VMImage + multiplicity: "0..1" + configInterface: + class: infrastructure_NetworkInterface + multiplicity: "0..1" + Location: + superclass: commons_DOMLElement + attributes: + region: + type: String + multiplicity: "0..1" + zone: + type: String + multiplicity: "0..1" + ContainerConfig: + superclass: commons_DOMLElement + attributes: + container_port: + type: Integer + multiplicity: "0..1" + vm_port: + type: Integer + multiplicity: "0..1" + associations: + iface: + class: infrastructure_NetworkInterface + multiplicity: "0..1" + ContainerHostConfig: + superclass: commons_DOMLElement + associations: + environment_variables: + class: commons_SProperty + multiplicity: "0..*" + host: + class: infrastructure_ComputingNode + multiplicity: "0..1" + configurations: + class: infrastructure_ContainerConfig + multiplicity: "0..*" + Container: + superclass: infrastructure_ComputingNode + associations: + generatedFrom: + class: infrastructure_ContainerImage + multiplicity: "0..1" + hostConfigs: + class: infrastructure_ContainerHostConfig + multiplicity: "0..*" + networks: + class: infrastructure_ContainerNetwork + multiplicity: "0..*" + volumes: + class: infrastructure_ContainerVolume + multiplicity: "0..*" + dependsOn: + class: infrastructure_Container + multiplicity: "0..*" + ContainerGroup: + superclass: infrastructure_ComputingGroup + associations: + services: + class: infrastructure_Container + multiplicity: "1..*" + networks: + class: infrastructure_ContainerNetwork + multiplicity: "0..*" + volumes: + class: infrastructure_ContainerVolume + multiplicity: "0..*" + ContainerNetwork: + superclass: commons_DOMLElement + attributes: + containerNetworkName: + type: String + multiplicity: "0..1" + ContainerVolume: + superclass: commons_DOMLElement + attributes: + containerVolumeName: + type: String + multiplicity: "0..1" + path: + type: String + multiplicity: "0..1" + ExecutionEnvironment: + superclass: infrastructure_InfrastructureElement + attributes: + size: + type: Integer + multiplicity: "0..1" + maxSize: + type: Integer + multiplicity: "0..1" + associations: + location: + class: infrastructure_Location + multiplicity: "0..1" + network: + class: infrastructure_Network + multiplicity: "0..1" + securityGroups: + class: infrastructure_SecurityGroup + multiplicity: "0..*" + ComputingNodeGenerator: + superclass: commons_DOMLElement + attributes: + uri: + type: String + multiplicity: "0..1" + kind: + type: GeneratorKind # enum { SCRIPT, IMAGE } + VMImage: + superclass: infrastructure_ComputingNodeGenerator + associations: + generatedVMs: + class: infrastructure_VirtualMachine + multiplicity: "0..*" + inverse_of: infrastructure_VirtualMachine::generatedFrom + ContainerImage: + superclass: infrastructure_ComputingNodeGenerator + associations: + generatedContainers: + class: infrastructure_Container + multiplicity: "0..*" + inverse_of: infrastructure_Container::generatedFrom + AutoScalingGroup: + superclass: infrastructure_ComputingGroup + attributes: + min: + type: Integer + multiplicity: "0..1" + max: + type: Integer + multiplicity: "0..1" + loadBalancer: + type: String + multiplicity: "0..1" + associations: + machineDefinition: + class: infrastructure_VirtualMachine + multiplicity: "1" + Storage: + superclass: infrastructure_Node + attributes: + label: + type: String + multiplicity: "0..1" + size_gb: + type: Integer # in GBs + multiplicity: "0..1" + cost: + type: Integer # in cents + multiplicity: "0..1" + FunctionAsAService: + superclass: infrastructure_InfrastructureElement + attributes: + cost: + type: Integer # in cents + multiplicity: "0..1" + Network: + superclass: commons_DOMLElement + attributes: + protocol: + type: String + multiplicity: "0..1" + default: "TCP/IP" + cidr: + type: Integer + multiplicity: "0..1" + associations: + connectedIfaces: + class: infrastructure_NetworkInterface + multiplicity: "0..*" + inverse_of: infrastructure_NetworkInterface::belongsTo + gateways: + class: infrastructure_InternetGateway + multiplicity: "0..*" + subnets: + class: infrastructure_Subnet + multiplicity: "0..*" + Subnet: + superclass: infrastructure_Network + associations: + connectedTo: + class: infrastructure_Network + multiplicity: "0..*" + NetworkInterface: + superclass: infrastructure_InfrastructureElement + attributes: + endPoint: + type: Integer + multiplicity: "0..1" + speed: + type: String + multiplicity: "0..1" + associations: + belongsTo: + class: infrastructure_Network + multiplicity: "0..1" # This should be "1", but it would break InternetGateway + associated: + class: infrastructure_SecurityGroup + multiplicity: "0..1" + InternetGateway: + superclass: infrastructure_Node + attributes: + address: + type: String + multiplicity: "1" + ComputingGroup: + superclass: commons_DOMLElement + associations: + groupedNodes: + class: infrastructure_ComputingNode + multiplicity: "0..*" + inverse_of: infrastructure_ComputingNode::group + SecurityGroup: + superclass: commons_DOMLElement + associations: + rules: + class: infrastructure_Rule + multiplicity: "0..*" + ifaces: + class: infrastructure_NetworkInterface + multiplicity: "0..*" + inverse_of: infrastructure_NetworkInterface::associated + Rule: + superclass: commons_DOMLElement + attributes: + kind: + type: String + multiplicity: "1" + protocol: + type: String + multiplicity: "1" + fromPort: + type: Integer + multiplicity: "1" + toPort: + type: Integer + multiplicity: "1" + cidr: + type: String + multiplicity: "0..*" + SwarmRole: + superclass: commons_DOMLElement + attributes: + kind: + type: String + multiplicity: "1" + associations: + nodes: + class: infrastructure_ComputingNode + multiplicity: "0..*" + Swarm: + superclass: infrastructure_ComputingGroup + associations: + roles: + class: infrastructure_SwarmRole + multiplicity: "0..*" + ExtInfrastructureElement: + superclass: infrastructure_InfrastructureElement + +concrete: + ConcreteInfrastructure: + superclass: commons_DOMLElement + associations: + providers: + class: concrete_RuntimeProvider + multiplicity: "0..*" + ConcreteElement: + superclass: commons_DOMLElement + associations: + refs: + class: concrete_ConcreteElement + multiplicity: "0..*" + attributes: + resourceName: + type: String + multiplicity: "0..1" + configurationScript: + type: String + multiplicity: "0..1" + preexisting: + multiplicity: "1" + type: Boolean + default: false + RuntimeProvider: + superclass: commons_DOMLElement + associations: + resources: + class: concrete_GenericResource + multiplicity: "0..*" + vms: + class: concrete_VirtualMachine + multiplicity: "0..*" + executionEnvironments: + class: concrete_ExecutionEnvironment + multiplicity: "0..*" + vmImages: + class: concrete_VMImage + multiplicity: "0..*" + containerImages: + class: concrete_ContainerImage + multiplicity: "0..*" + networks: + class: concrete_Network + multiplicity: "0..*" + storages: + class: concrete_Storage + multiplicity: "0..*" + faas: + class: concrete_FunctionAsAService + multiplicity: "0..*" + autoScalingGroups: + class: concrete_AutoScalingGroup + multiplicity: "0..*" + VirtualMachine: + superclass: concrete_ConcreteElement + attributes: + vm_type: + type: String + multiplicity: "0..1" + associations: + maps: + class: infrastructure_VirtualMachine + multiplicity: "0..1" + VMImage: + superclass: concrete_ConcreteElement + attributes: + image_name: + type: String + multiplicity: "1" + associations: + maps: + class: infrastructure_VMImage + multiplicity: "0..1" + ContainerImage: + superclass: concrete_ConcreteElement + associations: + maps: + class: infrastructure_ContainerImage + multiplicity: "0..1" + ExecutionEnvironment: + superclass: concrete_ConcreteElement + attributes: + instance_type: + type: String + multiplicity: "0..1" + storage_type: + type: String + multiplicity: "0..1" + associations: + maps: + class: infrastructure_ExecutionEnvironment + multiplicity: "0..1" + Network: + superclass: concrete_ConcreteElement + attributes: + protocol: + type: String + multiplicity: "0..1" + addressRange: + type: String + multiplicity: "0..1" + associations: + subnets: + class: concrete_Subnet + multiplicity: "0..*" + maps: + class: infrastructure_Network + multiplicity: "0..1" + Subnet: + superclass: concrete_Network + Storage: + superclass: concrete_ConcreteElement + associations: + maps: + class: infrastructure_Storage + multiplicity: "0..1" + FunctionAsAService: + superclass: concrete_ConcreteElement + associations: + maps: + class: infrastructure_FunctionAsAService + multiplicity: "0..1" + AutoScalingGroup: + superclass: concrete_ConcreteElement + attributes: + vm_type: + type: String + multiplicity: "0..1" + associations: + maps: + class: infrastructure_AutoScalingGroup + multiplicity: "0..1" + GenericResource: + superclass: concrete_ConcreteElement + attributes: + type: + type: "String" + multiplicity: "1" diff --git a/mc_openapi/assets/metamodels/doml_v3.1.ecore b/mc_openapi/assets/metamodels/doml_v3.1.ecore new file mode 100644 index 0000000000000000000000000000000000000000..ce4f02e1e1cd9b8186b33d6ab0dd5a2452c699e8 --- /dev/null +++ b/mc_openapi/assets/metamodels/doml_v3.1.ecore @@ -0,0 +1,489 @@ +<?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:EAttribute" name="version" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" + defaultValueLiteral="3.1"/> + <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" abstract="true"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="key" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ListProperty" eSuperTypes="#//commons/Property"> + <eStructuralFeatures xsi:type="ecore:EReference" name="values" upperBound="-1" + eType="#//commons/Property" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="IProperty" eSuperTypes="#//commons/Property"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="SProperty" eSuperTypes="#//commons/Property"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="FProperty" eSuperTypes="#//commons/Property"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="BProperty" eSuperTypes="#//commons/Property"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBooleanObject"/> + </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="DeployableElement" abstract="true"/> + <eClassifiers xsi:type="ecore:EClass" name="Deployment"> + <eStructuralFeatures xsi:type="ecore:EReference" name="component" lowerBound="1" + eType="#//commons/DeployableElement"/> + <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="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> + <eClassifiers xsi:type="ecore:EClass" name="Credentials" abstract="true" eSuperTypes="#//commons/DOMLElement"/> + <eClassifiers xsi:type="ecore:EClass" name="KeyPair" eSuperTypes="#//commons/Credentials"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="user" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="key" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <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="#//commons/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="Source" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="entry" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="inventory" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="backend" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </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 #//commons/DeployableElement"/> + <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:EReference" name="exposedInterfaces" upperBound="-1" + eType="#//application/SoftwareInterface" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="consumedInterfaces" upperBound="-1" + eType="#//application/SoftwareInterface"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="src" eType="#//commons/Source" + containment="true"/> + </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"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="databaseName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="engine" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="engineVersion" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <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="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="#//commons/Credentials" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="executionEnvironments" + upperBound="-1" eType="#//infrastructure/ExecutionEnvironment" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="groups" upperBound="-1" + eType="#//infrastructure/ComputingGroup" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="securityGroups" upperBound="-1" + eType="#//infrastructure/SecurityGroup" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="networks" upperBound="-1" + eType="#//infrastructure/Network" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="rules" upperBound="-1" + eType="#//infrastructure/MonitoringRule" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="MonitoringRule" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="condition" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="strategy" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="strategyConfigurationString" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </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/ComputingGroup"> + <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: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="cidr" 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="#//commons/DOMLElement"> + <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="InfrastructureElement" abstract="true" + eSuperTypes="#//commons/DOMLElement #//commons/DeployableElement"/> + <eClassifiers xsi:type="ecore:EClass" name="Node" abstract="true" eSuperTypes="#//infrastructure/InfrastructureElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="ifaces" upperBound="-1" + eType="#//infrastructure/NetworkInterface" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ComputingNode" abstract="true" eSuperTypes="#//infrastructure/Node"> + <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_mb" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="storage" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="cpu_count" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="location" eType="#//infrastructure/Location" + containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="credentials" eType="#//commons/Credentials"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="group" eType="#//infrastructure/ComputingGroup" + eOpposite="#//infrastructure/ComputingGroup/groupedNodes"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="nodeSpecificMonitoring" + upperBound="-1" eType="#//infrastructure/MonitoringRule"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="disabledMonitorings" + upperBound="-1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </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"> + <eStructuralFeatures xsi:type="ecore:EReference" name="configInterface" eType="#//infrastructure/NetworkInterface"/> + </eClassifiers> + <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"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="configInterface" eType="#//infrastructure/NetworkInterface"/> + </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="ContainerConfig" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="container_port" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="vm_port" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EIntegerObject"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="iface" eType="#//infrastructure/NetworkInterface"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ContainerHostConfig" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="environment_variables" + upperBound="-1" eType="#//commons/SProperty" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="host" eType="#//infrastructure/ComputingNode"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="configurations" upperBound="-1" + eType="#//infrastructure/ContainerConfig" containment="true"/> + </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="hostConfigs" upperBound="-1" + eType="#//infrastructure/ContainerHostConfig" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="networks" upperBound="-1" + eType="#//infrastructure/ContainerNetwork"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="volumes" upperBound="-1" + eType="#//infrastructure/ContainerVolume"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="dependsOn" upperBound="-1" + eType="#//infrastructure/Container"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ContainerGroup" eSuperTypes="#//infrastructure/ComputingGroup"> + <eStructuralFeatures xsi:type="ecore:EReference" name="services" lowerBound="1" + upperBound="-1" eType="#//infrastructure/Container" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="networks" upperBound="-1" + eType="#//infrastructure/ContainerNetwork" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="volumes" upperBound="-1" + eType="#//infrastructure/ContainerVolume" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ContainerNetwork" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="containerNetworkName" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ContainerVolume" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="containerVolumeName" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="path" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ExecutionEnvironment" eSuperTypes="#//infrastructure/InfrastructureElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="size" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="maxSize" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="location" eType="#//infrastructure/Location" + containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="network" eType="#//infrastructure/Network"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="securityGroups" upperBound="-1" + eType="#//infrastructure/SecurityGroup"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Network" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="protocol" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" + defaultValueLiteral="TCP/IP"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="connectedIfaces" upperBound="-1" + eType="#//infrastructure/NetworkInterface" eOpposite="#//infrastructure/NetworkInterface/belongsTo"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="gateways" upperBound="-1" + eType="#//infrastructure/InternetGateway" containment="true"/> + <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" upperBound="-1" + eType="#//infrastructure/SecurityGroup" eOpposite="#//infrastructure/SecurityGroup/ifaces"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="InternetGateway" eSuperTypes="#//infrastructure/Node"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="address" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Storage" eSuperTypes="#//infrastructure/InfrastructureElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="label" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="size_gb" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + </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#//EFloatObject"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EEnum" name="RoleKind"> + <eLiterals name="NONE"/> + <eLiterals name="MANAGER" value="1"/> + <eLiterals name="WORKER" value="2"/> + <eLiterals name="MASTER" value="3"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="SwarmRole" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" eType="#//infrastructure/RoleKind"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1" + eType="#//infrastructure/ComputingNode" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Swarm" eSuperTypes="#//infrastructure/ComputingGroup"> + <eStructuralFeatures xsi:type="ecore:EReference" name="roles" upperBound="-1" + eType="#//infrastructure/SwarmRole" containment="true"/> + </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="resources" upperBound="-1" + eType="#//concrete/GenericResource" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="vms" upperBound="-1" + eType="#//concrete/VirtualMachine" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="executionEnvironments" + upperBound="-1" eType="#//concrete/ExecutionEnvironment" 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="autoScalingGroups" upperBound="-1" + eType="#//concrete/AutoScalingGroup" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ConcreteElement" abstract="true" eSuperTypes="#//commons/DOMLElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="resourceName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="configurationScript" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="preexisting" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBooleanObject" + defaultValueLiteral="false"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="refs" upperBound="-1" + eType="#//concrete/ConcreteElement"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="GenericResource" eSuperTypes="#//concrete/ConcreteElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" 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:EAttribute" name="vm_type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <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:EAttribute" name="image_name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <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="ExecutionEnvironment" eSuperTypes="#//concrete/ConcreteElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="instance_type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="storage_type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/ExecutionEnvironment"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Network" eSuperTypes="#//concrete/ConcreteElement"> + <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="subnets" upperBound="-1" + eType="#//concrete/Subnet" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/Network"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Subnet" eSuperTypes="#//concrete/Network"/> + <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="AutoScalingGroup" eSuperTypes="#//concrete/ConcreteElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="vm_type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="maps" eType="#//infrastructure/AutoScalingGroup"/> + </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="opt"> + <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"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="runtime" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="ObjectiveValue"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="cost" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="availability" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="performance" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloatObject"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="OptimizationSolution" eSuperTypes="#//commons/Configuration"> + <eStructuralFeatures xsi:type="ecore:EReference" name="objectives" eType="#//optimization/ObjectiveValue" + containment="true"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="decisions" upperBound="-1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <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/mc_openapi/assets/templates/mc.html b/mc_openapi/assets/templates/mc.html index 4c39aee609fe99f66c29627330dc183468c78b12..019b39595d705c827852170d4a4f68012bb7c913 100644 --- a/mc_openapi/assets/templates/mc.html +++ b/mc_openapi/assets/templates/mc.html @@ -1,7 +1,12 @@ {% extends "base.html" %} {% block content %} -<h1 class="title">DOML Model Checker Results</h1> +<h1 class="title">DOML Model Checker Results + <span class="tags has-addons"> + <span class="tag is-dark">DOML Version</span> + <span class="tag is-info">{{doml_version}}</span> + </span> +</h1> <div class="box"> <h2 class="title is-4">Result: {% if result == "sat" %} @@ -11,13 +16,8 @@ {% endif %} </h2> <div class="control"> - <div class="tags has-addons"> - <span class="tag is-dark">DOML Version</span> - <span class="tag is-info">{{doml_version}}</span> - </div> + <p>Model validated in {{elapsed_time}}s.</p> </div> - {% if result != "sat" %} - {% if all_reqs %} <label class="checkbox my-4"> <input type="checkbox" id="show-sat-reqs"> @@ -48,15 +48,15 @@ {% else %} <li class="message is-success sat-req is-hidden"> <div class="message-header"> - <p> - Satisfied ({{req.time}}s) - </p> <p> <span class="tag is-family-monospace is-success is-light"> {{req.id}} </span> <span class="tag is-success is-light">{{req.type}}</span> </p> + <p> + satisfied ({{req.time}}s) + </p> </div> <div class="message-body"> <h2 class="title is-6 my-2">Description</h2> @@ -98,18 +98,22 @@ </div> </article> {% endif %} - {% endif %} - <script> - const checkbox = document.querySelector("#show-sat-reqs") - const satReqs = document.querySelectorAll(".sat-req") - checkbox.addEventListener("click", () => { - satReqs.forEach(el => el.classList.toggle('is-hidden')) - }) - </script> + {% if net_validation %} + {% include "net.html" %} + {% else %} + <h3 class="title is-5">Network Validation</h3> + No issue detected within the model network configuration. + {% endif %} </div> +<script> + const checkbox = document.querySelector("#show-sat-reqs") + const satReqs = document.querySelectorAll(".sat-req") - + checkbox.addEventListener("click", () => { + satReqs.forEach(el => el.classList.toggle('is-hidden')) + }) +</script> {% if csp %} {% include "csp_content.html" %} {% endif %} diff --git a/mc_openapi/assets/templates/net.html b/mc_openapi/assets/templates/net.html new file mode 100644 index 0000000000000000000000000000000000000000..ec8371c861bbd7baae79b25d5d6b707c50e18ab8 --- /dev/null +++ b/mc_openapi/assets/templates/net.html @@ -0,0 +1,10 @@ +<h3 class="title is-5">Network Validation</h3> +<ul> + {% for warn in net_validation %} + <li class="message"> + <div class="message-body"> + {{warn}} + </div> + </li> + {% endfor %} +</ul> \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/__init__.py b/mc_openapi/doml_mc/builtin_requirements/__init__.py index edac2d1505124d44dca3f55bf71460d30d5a4aec..3f67bf2dc0630730dc6f61f2c9b6f0698f7025ef 100644 --- a/mc_openapi/doml_mc/builtin_requirements/__init__.py +++ b/mc_openapi/doml_mc/builtin_requirements/__init__.py @@ -7,15 +7,20 @@ CELEMS_V2_0 = [ ("infrastructure_ComputingGroup", "concrete_RuntimeProvider::group","concrete_ComputingGroup::maps"), ] +CELEMS_V3_1 = [ + *CELEMS_V2_0[0:5], + ("infrastructure_ComputingGroup", "concrete_RuntimeProvider::autoScalingGroups","concrete_AutoScalingGroup::maps") +] + from .vm_has_iface import VM_HAS_IFACE, VM_HAS_IFACE_V2_3 -from .software_package_iface_net import SOFTWARE_PACKAGE_IFACE_NET, SOFTWARE_PACKAGE_IFACE_NET_V2_1, SOFTWARE_PACKAGE_IFACE_NET_V2_3 +from .software_package_iface_net import SOFTWARE_PACKAGE_IFACE_NET, SOFTWARE_PACKAGE_IFACE_NET_V2_1, SOFTWARE_PACKAGE_IFACE_NET_V2_3, SOFTWARE_PACKAGE_IFACE_NET_V3_1 from .iface_uniq import IFACE_UNIQ from .all_software_components_deployed import ALL_SOFTWARE_COMPONENTS_DEPLOYED -from .all_infrastructure_elements_deployed import ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED -from .all_concrete_maps_something import ALL_CONCRETE_MAP_SOMETHING -from .security_group_must_have_iface import SECURITY_GROUP_MUST_HAVE_IFACE +from .all_infrastructure_elements_deployed import ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED, ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED_V3_1 +from .all_concrete_maps_something import ALL_CONCRETE_MAP_SOMETHING, ALL_CONCRETE_MAP_SOMETHING_V3_1 +from .security_group_must_have_iface import SECURITY_GROUP_MUST_HAVE_IFACE, SECURITY_GROUP_MUST_HAVE_IFACE_V3_1 from .concrete_asg_no_vm import CONCRETE_ASG_NO_VM -from .vm_os_required import VM_OS_REQUIRED +from .vm_os_required import VM_OS_REQUIRED, VM_OS_REQUIRED_V3_1 __ALL__ = [ VM_HAS_IFACE, @@ -23,11 +28,16 @@ __ALL__ = [ SOFTWARE_PACKAGE_IFACE_NET, SOFTWARE_PACKAGE_IFACE_NET_V2_1, SOFTWARE_PACKAGE_IFACE_NET_V2_3, + SOFTWARE_PACKAGE_IFACE_NET_V3_1, IFACE_UNIQ, ALL_SOFTWARE_COMPONENTS_DEPLOYED, ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED, + ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED_V3_1, ALL_CONCRETE_MAP_SOMETHING, + ALL_CONCRETE_MAP_SOMETHING_V3_1, SECURITY_GROUP_MUST_HAVE_IFACE, + SECURITY_GROUP_MUST_HAVE_IFACE_V3_1, CONCRETE_ASG_NO_VM, - VM_OS_REQUIRED + VM_OS_REQUIRED, + VM_OS_REQUIRED_V3_1 ] \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/all_concrete_maps_something.py b/mc_openapi/doml_mc/builtin_requirements/all_concrete_maps_something.py index 18a571973dad731f86236deca6c5f2048083be70..01e2f1e7ce243a895b3ef48369ccfc4975c5ce8b 100644 --- a/mc_openapi/doml_mc/builtin_requirements/all_concrete_maps_something.py +++ b/mc_openapi/doml_mc/builtin_requirements/all_concrete_maps_something.py @@ -2,7 +2,7 @@ from z3 import And, Const, Consts, Exists, ExprRef, Not, Or, Solver, Implies from mc_openapi.doml_mc.imc import Requirement, SMTEncoding, SMTSorts from mc_openapi.doml_mc.intermediate_model import DOMLVersion, IntermediateModel from mc_openapi.doml_mc.error_desc_helper import get_user_friendly_name -from . import CELEMS_V2_0 +from . import CELEMS_V2_0, CELEMS_V3_1 # All elements in the active concretization are mapped to some abstract infrastructure element. @@ -38,6 +38,38 @@ def all_concrete_map_something(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprR ) ) +def all_concrete_map_something_v3_1(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + def checkOneClass(ielem, provider, celem, providerAssoc, celemAssoc): + return And( + smtenc.association_rel( + provider, smtenc.associations[providerAssoc], celem), + Not( + Exists( + [ielem], + smtenc.association_rel( + celem, smtenc.associations[celemAssoc], ielem) + ) + ) + ) + + ielem, concr, provider, celem = Consts( + "ielem concr provider celem", smtsorts.element_sort) + return And( + smtenc.element_class_fun( + concr) == smtenc.classes["concrete_ConcreteInfrastructure"], + smtenc.association_rel( + concr, smtenc.associations["concrete_ConcreteInfrastructure::providers"], provider), + Or( + *( + checkOneClass( + ielem, provider, celem, + providerAssoc, celemAssoc + ) + for _, providerAssoc, celemAssoc in CELEMS_V3_1 + ) + ) + ) + def ed_all_concrete_map_something(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: try: @@ -56,4 +88,11 @@ ALL_CONCRETE_MAP_SOMETHING = ( "all_concrete_map_something", MSG, ed_all_concrete_map_something +) + +ALL_CONCRETE_MAP_SOMETHING_V3_1 = ( + all_concrete_map_something_v3_1, + "all_concrete_map_something", + MSG, + ed_all_concrete_map_something ) \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/all_infrastructure_elements_deployed.py b/mc_openapi/doml_mc/builtin_requirements/all_infrastructure_elements_deployed.py index 0d0f366cf1b018a0f0534642a1e65568115254d1..7e4b4e300caa546a06f9f110de3f34af7d0e8a27 100644 --- a/mc_openapi/doml_mc/builtin_requirements/all_infrastructure_elements_deployed.py +++ b/mc_openapi/doml_mc/builtin_requirements/all_infrastructure_elements_deployed.py @@ -2,7 +2,7 @@ from z3 import And, Const, Consts, Exists, ExprRef, Not, Or, Solver, Implies from mc_openapi.doml_mc.imc import Requirement, SMTEncoding, SMTSorts from mc_openapi.doml_mc.intermediate_model import DOMLVersion, IntermediateModel from mc_openapi.doml_mc.error_desc_helper import get_user_friendly_name -from . import CELEMS_V2_0 +from . import CELEMS_V2_0, CELEMS_V3_1 # Provider > elements generated by IOP only have "commons_DOMLElement::annotations" as an association # and do not have maps. Also networks are not generated by the IOP. But they are the same class @@ -70,6 +70,75 @@ def all_infrastructure_elements_deployed(smtenc: SMTEncoding, smtsorts: SMTSorts ) ) +def all_infrastructure_elements_deployed_v3_1(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + def checkOneClass(ielem, cinfr, provider, celem, ielemClass, providerAssoc, celemAssoc): + return And( + smtenc.element_class_fun(ielem) == smtenc.classes[ielemClass], + Not( + Exists( + [provider, celem], + And( + smtenc.association_rel( + cinfr, smtenc.associations["concrete_ConcreteInfrastructure::providers"], provider), + smtenc.association_rel( + provider, smtenc.associations[providerAssoc], celem), + smtenc.association_rel( + celem, smtenc.associations[celemAssoc], ielem) + ) + ) + ) + ) + + ielem, concr, provider, celem, net, asg = Consts("ielem concr provider celem net asg", smtsorts.element_sort) + return And( + smtenc.element_class_fun( + concr) == smtenc.classes["concrete_ConcreteInfrastructure"], + Or( + *( + checkOneClass( + ielem, concr, provider, celem, + ielemClass, providerAssoc, celemAssoc + ) + for ielemClass, providerAssoc, celemAssoc in CELEMS_V3_1 + if ielemClass != 'infrastructure_VirtualMachine' # handle special case separately in concrete_asg_no_vm and below + ), + And( + smtenc.element_class_fun(ielem) == smtenc.classes["infrastructure_VirtualMachine"], + Not(Exists([asg], + Or( + smtenc.association_rel( + asg, smtenc.associations["infrastructure_AutoScalingGroup::machineDefinition"], ielem), + Exists( + [provider, celem], + And( + smtenc.association_rel( + concr, smtenc.associations["concrete_ConcreteInfrastructure::providers"], provider), + smtenc.association_rel( + provider, smtenc.associations["concrete_RuntimeProvider::vms"], celem), + smtenc.association_rel( + celem, smtenc.associations["concrete_VirtualMachine::maps"], ielem) + ) + ) + ) + )) + ), + And( + smtenc.element_class_fun(ielem) == smtenc.classes["infrastructure_Subnet"], + Not(Exists([provider, net, celem], + And( + smtenc.association_rel( + concr, smtenc.associations["concrete_ConcreteInfrastructure::providers"], provider), + smtenc.association_rel( + provider, smtenc.associations["concrete_RuntimeProvider::networks"], net), + smtenc.association_rel( + net, smtenc.associations["concrete_Network::subnets"], celem), + smtenc.association_rel( + celem, smtenc.associations["concrete_Network::maps"], ielem) + ) + )) + ) + ) + ) def ed_all_infrastructure_elements_deployed(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: try: @@ -88,4 +157,11 @@ ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED = ( "all_infrastructure_elements_deployed", MSG, ed_all_infrastructure_elements_deployed +) + +ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED_V3_1 = ( + all_infrastructure_elements_deployed_v3_1, + "all_infrastructure_elements_deployed", + MSG, + ed_all_infrastructure_elements_deployed ) \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/security_group_must_have_iface.py b/mc_openapi/doml_mc/builtin_requirements/security_group_must_have_iface.py index e18ec59597bfac1797e261793f3d6f2d26283e07..6e9cbabf07ee335e565146c45d66e5145239f61c 100644 --- a/mc_openapi/doml_mc/builtin_requirements/security_group_must_have_iface.py +++ b/mc_openapi/doml_mc/builtin_requirements/security_group_must_have_iface.py @@ -18,21 +18,44 @@ def security_group_must_have_iface(smtenc: SMTEncoding, smtsorts: SMTSorts) -> E )) ) +def security_group_must_have_iface_v3_1(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + sg, elem = Consts("sg elem", smtsorts.element_sort) + return And( + smtenc.element_class_fun( + sg) == smtenc.classes["infrastructure_SecurityGroup"], + Not(Exists([elem], + Or( + smtenc.association_rel( + elem, smtenc.associations["infrastructure_NetworkInterface::associated"], sg), + smtenc.association_rel( + elem, smtenc.associations["infrastructure_ExecutionEnvironment::securityGroups"], sg) + ) + )) + ) + + def ed_security_group_must_have_iface(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: try: sg = Const("sg", smtsorts.element_sort) sg_name = get_user_friendly_name( intermediate_model, solver.model(), sg) if sg_name: - return f"Security group '{sg_name}' is not associated with any network interface." + return f"Security group '{sg_name}' is not associated with any network interface. You should probably remove it." except: - return "A network interface doesn't belong to any security group, or a security group is not associated with any network interface." + return "A security group is not associated with any element. You should probably remove it." -MSG = "All security group should be a associated to a network interface." +MSG = "All security group should be a associated to an element." SECURITY_GROUP_MUST_HAVE_IFACE = ( security_group_must_have_iface, "security_group_must_have_iface", MSG, ed_security_group_must_have_iface +) + +SECURITY_GROUP_MUST_HAVE_IFACE_V3_1 = ( + security_group_must_have_iface_v3_1, + "security_group_must_have_iface", + MSG, + ed_security_group_must_have_iface ) \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/software_package_iface_net.py b/mc_openapi/doml_mc/builtin_requirements/software_package_iface_net.py index e4ab9d07d93656b1da46fe4ad31d03656003a972..e570717bb4833641014f7076d0ae94f2c625ad3b 100644 --- a/mc_openapi/doml_mc/builtin_requirements/software_package_iface_net.py +++ b/mc_openapi/doml_mc/builtin_requirements/software_package_iface_net.py @@ -495,6 +495,169 @@ def software_package_iface_net_v2_3(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ) ) +def software_package_iface_net_v3_1(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + asc_consumer, asc_exposer, siface, net, net_iface, cnode, cdeployment, enode, edeployment, vm, cconf, csubnet, esubnet = Consts( + "asc_consumer asc_exposer siface net net_iface cnode cdeployment enode edeployment vm cconf csubnet esubnet", smtsorts.element_sort + ) + return And( + smtenc.association_rel( + asc_consumer, smtenc.associations["application_SoftwareComponent::exposedInterfaces"], siface), + smtenc.association_rel( + asc_exposer, smtenc.associations["application_SoftwareComponent::consumedInterfaces"], siface), + Not( + Or( + Exists( + [cdeployment, cnode, edeployment, enode, net], + And( + smtenc.association_rel( + cdeployment, smtenc.associations["commons_Deployment::component"], asc_consumer), + smtenc.association_rel( + cdeployment, smtenc.associations["commons_Deployment::node"], cnode), + Exists( + [vm, net_iface, cconf], + Or( + And( # asc_consumer is deployed on a component with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + And( # asc_consumer is deployed on a container hosted in a VM with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_Container::hostConfigs"], cconf), + smtenc.association_rel( + cconf, smtenc.associations["infrastructure_ContainerHostConfig::host"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + And( # asc_consumer is deployed on a VM in an AutoScalingGroup with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_AutoScalingGroup::machineDefinition"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + ) + ), + smtenc.association_rel( + edeployment, smtenc.associations["commons_Deployment::component"], asc_exposer), + smtenc.association_rel( + edeployment, smtenc.associations["commons_Deployment::node"], enode), + Exists( + [vm, net_iface, cconf], + Or( + And( # asc_exposer is deployed on a component with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + And( # asc_exposer is deployed on a container hosted on a VM with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_Container::hostConfigs"], cconf), + smtenc.association_rel( + cconf, smtenc.associations["infrastructure_ContainerHostConfig::host"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + And( # asc_exposer is deployed on a VM in an AutoScalingGroup with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_AutoScalingGroup::machineDefinition"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], net), + ), + ) + ) + ) + ), # OR + Exists( + [cdeployment, cnode, edeployment, enode, csubnet, esubnet], + And( + smtenc.association_rel( + cdeployment, smtenc.associations["commons_Deployment::component"], asc_consumer), + smtenc.association_rel( + cdeployment, smtenc.associations["commons_Deployment::node"], cnode), + Or( + smtenc.association_rel( + csubnet, smtenc.associations["infrastructure_Subnet::connectedTo"], esubnet), + smtenc.association_rel( + esubnet, smtenc.associations["infrastructure_Subnet::connectedTo"], csubnet), + ), + Exists( + [vm, net_iface, cconf], + Or( + And( # asc_consumer is deployed on a component with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], csubnet), + ), + And( # asc_consumer is deployed on a container hosted in a VM with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_Container::hostConfigs"], cconf), + smtenc.association_rel( + cconf, smtenc.associations["infrastructure_ContainerHostConfig::host"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], csubnet), + ), + And( # asc_consumer is deployed on a VM in an AutoScalingGroup with an interface in network n + smtenc.association_rel( + cnode, smtenc.associations["infrastructure_AutoScalingGroup::machineDefinition"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], csubnet), + ), + ) + ), + smtenc.association_rel( + edeployment, smtenc.associations["commons_Deployment::component"], asc_exposer), + smtenc.association_rel( + edeployment, smtenc.associations["commons_Deployment::node"], enode), + Exists( + [vm, net_iface, cconf], + Or( + And( # asc_exposer is deployed on a component with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], esubnet), + ), + And( # asc_exposer is deployed on a container hosted on a VM with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_Container::hostConfigs"], cconf), + smtenc.association_rel( + cconf, smtenc.associations["infrastructure_ContainerHostConfig::host"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], esubnet), + ), + And( # asc_exposer is deployed on a VM in an AutoScalingGroup with an interface in network n + smtenc.association_rel( + enode, smtenc.associations["infrastructure_AutoScalingGroup::machineDefinition"], vm), + smtenc.association_rel( + vm, smtenc.associations["infrastructure_Node::ifaces"], net_iface), + smtenc.association_rel( + net_iface, smtenc.associations["infrastructure_NetworkInterface::belongsTo"], esubnet), + ) + ) + ) + ) + ) + ) + ) + ) + def ed_software_package_iface_net(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: try: @@ -537,4 +700,11 @@ SOFTWARE_PACKAGE_IFACE_NET_V2_3 = ( "software_package_iface_net", MSG, ed_software_package_iface_net +) + +SOFTWARE_PACKAGE_IFACE_NET_V3_1 = ( + software_package_iface_net_v3_1, + "software_package_iface_net", + MSG, + ed_software_package_iface_net ) \ No newline at end of file diff --git a/mc_openapi/doml_mc/builtin_requirements/vm_os_required.py b/mc_openapi/doml_mc/builtin_requirements/vm_os_required.py index 2209c8892378224ce74cd6605c85e7a13c6f2df4..73a6ce4d5ade7a56c48c4319720989ef4b7a4e20 100644 --- a/mc_openapi/doml_mc/builtin_requirements/vm_os_required.py +++ b/mc_openapi/doml_mc/builtin_requirements/vm_os_required.py @@ -5,25 +5,6 @@ from mc_openapi.doml_mc.error_desc_helper import get_user_friendly_name def vm_os_required(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: - # cont, contcfg, vm = Consts("cont contcfg vm", smtsorts.element_sort) - # os = Const("os", smtsorts.attr_data_sort) - # return And( - # smtenc.element_class_fun(cont) == smtenc.classes["infrastructure_Container"], - # Not( - # Exists( - # [contcfg, os], - # And( - # smtenc.association_rel( - # cont, smtenc.associations["infrastructure_Container::configs"], contcfg), - # smtenc.association_rel( - # contcfg, smtenc.associations["infrastructure_ContainerConfig::host"], vm), - # smtenc.attribute_rel( - # vm, smtenc.attributes["infrastructure_ComputingNode::os"], os - # ) - # ) - # ) - # ) - # ) vm, cont, ccfg = Consts("vm cont ccfg", smtsorts.element_sort) os = Const("os", smtsorts.attr_data_sort) return And( @@ -46,6 +27,28 @@ def vm_os_required(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: ) ) +def vm_os_required_v3_1(smtenc: SMTEncoding, smtsorts: SMTSorts) -> ExprRef: + vm, cont, ccfg = Consts("vm cont ccfg", smtsorts.element_sort) + os = Const("os", smtsorts.attr_data_sort) + return And( + smtenc.element_class_fun( + vm) == smtenc.classes["infrastructure_VirtualMachine"], + smtenc.element_class_fun( + cont) == smtenc.classes["infrastructure_Container"], + Not( + Exists( + [vm, os, ccfg], + And( + smtenc.association_rel( + cont, smtenc.associations["infrastructure_Container::hostConfigs"], ccfg), + smtenc.association_rel( + ccfg, smtenc.associations["infrastructure_ContainerHostConfig::host"], vm), + smtenc.attribute_rel( + vm, smtenc.attributes["infrastructure_ComputingNode::os"], os) + ) + ) + ) + ) def ed_vm_os_required(solver: Solver, smtsorts: SMTSorts, intermediate_model: IntermediateModel) -> str: try: @@ -70,3 +73,9 @@ VM_OS_REQUIRED = ( ed_vm_os_required ) +VM_OS_REQUIRED_V3_1 = ( + vm_os_required_v3_1, + "vm_os_required", + MSG, + ed_vm_os_required +) \ No newline at end of file diff --git a/mc_openapi/doml_mc/common_reqs.py b/mc_openapi/doml_mc/common_reqs.py index 6f989d94ea44781eeb4737ddba0c7aa88ddd7b84..74edd900f6dea5d2695f8be48488e851b3b27d56 100644 --- a/mc_openapi/doml_mc/common_reqs.py +++ b/mc_openapi/doml_mc/common_reqs.py @@ -54,6 +54,17 @@ REQUIREMENTS = { SECURITY_GROUP_MUST_HAVE_IFACE, CONCRETE_ASG_NO_VM, VM_OS_REQUIRED + ], + DOMLVersion.V3_1: [ + VM_HAS_IFACE_V2_3, + SOFTWARE_PACKAGE_IFACE_NET_V3_1, + IFACE_UNIQ, + ALL_SOFTWARE_COMPONENTS_DEPLOYED, + ALL_INFRASTRUCTURE_ELEMENTS_DEPLOYED_V3_1, + ALL_CONCRETE_MAP_SOMETHING_V3_1, + SECURITY_GROUP_MUST_HAVE_IFACE_V3_1, + CONCRETE_ASG_NO_VM, + VM_OS_REQUIRED_V3_1 ] } diff --git a/mc_openapi/doml_mc/exceptions.py b/mc_openapi/doml_mc/exceptions.py index a94ab25111da89185f6c5eecca42906c255af76d..a3284438af998cd6cc9a64f15561918db5694f44 100644 --- a/mc_openapi/doml_mc/exceptions.py +++ b/mc_openapi/doml_mc/exceptions.py @@ -1,6 +1,3 @@ -from mc_openapi.doml_mc.intermediate_model.metamodel import DOMLVersion - - class BadDOMLException(Exception): def __init__(self, message: str = None, *args: object) -> None: super().__init__(*args) @@ -21,3 +18,7 @@ class NoActiveConcreteLayerException(Exception): super().__init__(*args) self.message = message or "No active concrete infrastructure layer has been specified in DOML." +class CommonRequirementException(Exception): + def __init__(self, message: str = None, *args: object) -> None: + super().__init__(*args) + self.message = message or "Couldn't get built-in requirements for this DOML version." \ No newline at end of file diff --git a/mc_openapi/doml_mc/intermediate_model/metamodel.py b/mc_openapi/doml_mc/intermediate_model/metamodel.py index fe0fdf1c8f277928931e25555f71890de686d0ec..f1ab8f48b11e4514f7c7c0dca8ebd3d109c9fc33 100644 --- a/mc_openapi/doml_mc/intermediate_model/metamodel.py +++ b/mc_openapi/doml_mc/intermediate_model/metamodel.py @@ -17,6 +17,7 @@ class DOMLVersion(Enum): V2_2_1 = "v2.2.1" V2_3 = "v2.3" V3_0 = "v3.0" + V3_1 = "v3.1" def get(v: str): """Retrieve DOML version from string. diff --git a/mc_openapi/doml_mc/main.py b/mc_openapi/doml_mc/main.py index 555cf4304eb2b9b14aa527d236ad29a5773dbe63..1d8c8934081bf4e78a17361fb74ac781334051a5 100644 --- a/mc_openapi/doml_mc/main.py +++ b/mc_openapi/doml_mc/main.py @@ -11,9 +11,11 @@ from mc_openapi.doml_mc.csp_compatibility import \ CSPCompatibilityValidator as CSPCompatibility from mc_openapi.doml_mc.domlr_parser import (DOMLRTransformer, Parser, SynthesisDOMLRTransformer) +from mc_openapi.doml_mc.exceptions import CommonRequirementException from mc_openapi.doml_mc.imc import RequirementStore from mc_openapi.doml_mc.intermediate_model.metamodel import (DOMLVersion, MetaModelDocs) +from mc_openapi.doml_mc.network_address_validator.validate import validate_network_address def init_model(domlx:bytes, doml_ver: DOMLVersion): @@ -42,7 +44,7 @@ def verify_model( # Parse external DOMLR file if external_domlr: - user_req_store, user_req_str_consts = domlr_parser.parse(external_domlr) + user_req_store, user_req_str_consts, flags = domlr_parser.parse(external_domlr) # Parse internal DOMLR requirements if DOMLVersion.has_DOMLR_support(dmc.doml_version): @@ -58,9 +60,13 @@ def verify_model( # Built-in requirements if not (flags.get('_ignore_builtin', False) or skip_builtin_checks): - req_store += CommonRequirements[dmc.doml_version] - # Skip selected requirements - req_store.skip_requirements_by_id([k for k,v in flags.items() if not k.startswith("_") and v is False]) + try: + req_store += CommonRequirements[dmc.doml_version] + # Skip selected requirements + req_store.skip_requirements_by_id([k for k,v in flags.items() if not k.startswith("_") and v is False]) + except: + logging.error('Failed to get Common Requirements. DOML Version is wrong?') + raise CommonRequirementException() # Consistency requirements (disabled by default) if flags.get('_check_consistency', False) or consistency_checks: @@ -77,6 +83,7 @@ def verify_model( # Log all requirements to check logging.debug("Checking following requirements: " + ", ".join([k.assert_name for k in req_store.get_all_requirements()])) + logging.debug("Flags: { " + ", ".join([f"{k}={v}" for k, v in flags.items()]) + " }") # Check satisfiability results = dmc.check_requirements( @@ -98,6 +105,9 @@ def verify_model( if flags.get('_csp', False): res['csp'] = verify_csp_compatibility(dmc) + # Validate network + res['net_validation'] = validate_network_address(dmc) + return res def synthesize_model(dmc: ModelChecker, external_domlr: str, max_tries: int): diff --git a/mc_openapi/doml_mc/mc_result.py b/mc_openapi/doml_mc/mc_result.py index fba8aaa505b8ece2fb0ce3b1bfa2e2feae310282..8693a421cd1377d942896f59265560382e230532 100644 --- a/mc_openapi/doml_mc/mc_result.py +++ b/mc_openapi/doml_mc/mc_result.py @@ -42,6 +42,19 @@ class MCResults: some_unsat = any(res == MCResult.unsat for res, _, _, _, _, _ in self.results) some_dontknow = any(res == MCResult.dontknow for res, _, _, _, _, _ in self.results) + all_reqs = [ + { + "id": id, + "type": type, + "message": msg, + "result": res.name, + "description": desc, + "time": time + } + for res, type, msg, id, desc, time in self.results + ] + + if some_unsat: builtin_err_msgs = [ (id, msg, time) for res, type, msg, id, _, time in self.results if res == MCResult.unsat and type == "BUILTIN"] @@ -60,18 +73,6 @@ class MCResults: if some_dontknow: err_msg += '\n' + MCResults.DONTKNOW_MSG - all_reqs = [ - { - "id": id, - "type": type, - "message": msg, - "result": res.name, - "description": desc, - "time": time - } - for res, type, msg, id, desc, time in self.results - ] - return { 'result': MCResult.unsat, 'builtin': builtin_err_msgs, @@ -83,7 +84,7 @@ class MCResults: elif some_dontknow: return {'result': MCResult.dontknow, 'description': MCResults.DONTKNOW_MSG } else: - return {'result': MCResult.sat, 'description': MCResults.SATISFIED_MSG } + return {'result': MCResult.sat, 'description': MCResults.SATISFIED_MSG, 'all_reqs': all_reqs } def add_results(self, results: "MCResults"): self.results.extend(results.results) diff --git a/mc_openapi/doml_mc/network_address_validator/__init__.py b/mc_openapi/doml_mc/network_address_validator/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b64d68b57bb369f04c53eba9a9e436a6fdb7cd1d --- /dev/null +++ b/mc_openapi/doml_mc/network_address_validator/__init__.py @@ -0,0 +1 @@ +from .validate import validate_network_address \ No newline at end of file diff --git a/mc_openapi/doml_mc/network_address_validator/validate.py b/mc_openapi/doml_mc/network_address_validator/validate.py new file mode 100644 index 0000000000000000000000000000000000000000..5cbcdc6dd54a482a895db72e1f57a790b3e58755 --- /dev/null +++ b/mc_openapi/doml_mc/network_address_validator/validate.py @@ -0,0 +1,275 @@ +import logging +from mc_openapi.doml_mc.intermediate_model import DOMLElement +from mc_openapi.doml_mc.mc import ModelChecker +from ipaddress import IPv4Address, IPv4Network + + +BASE_ADDR = '0.0.0.0' + + +CONCRETE_NETWORK = 'concrete_Network' +# associations +ASSOC_SUBNETS = 'infrastructure_Network::subnets' +ASSOC_CONCRETE_SUBNETS = 'concrete_Network::subnets' +ASSOC_CONCRETE_MAPS = 'concrete_Network::maps' +ASSOC_GATEWAYS = 'infrastructure_Network::gateways' +ASSOC_NETIFACE = 'infrastructure_Network::connectedIfaces' + +# attributes +ATTR_NET_CIDR = 'infrastructure_Network::cidr' +ATTR_GATEWAY_ADDRESS = 'infrastructure_InternetGateway::address' +ATTR_NETIFACE_ADDRESS = 'infrastructure_NetworkInterface::endPoint' +ATTR_PROTOCOL = 'infrastructure_Network::protocol' +ATTR_CONCRETE_PROTOCOL = 'concrete_Network::protocol' +ATTR_CONCRETE_ADDRESS_RANGE = 'concrete_Network::addressRange' + +def validate_network_address(imc: ModelChecker): + """ + HOW IT WORKS: + + * Infrastructure Layer + - [n] Network.protocol + - [e] InternetGateway.address + - [e] NetworkInterface.endPoint + * Concrete Layer + - [n] Network.protocol + - [n] Network.addressRange + - [n] Subnet.addressRange + + before MC + validate network + generate report + attach report to HTML output + """ + im = imc.intermediate_model + + # warnings: list[str] = [] + warnings: list[str] = [] + + ## Helpers ## + def get_attr(elem: DOMLElement, attr_id: str): + if elem := elem.attributes.get(attr_id): + return elem[0] + return None + + def get_assocs(elem: DOMLElement, assoc_id: str): + return elem.associations.get(assoc_id, []) + + def get_elem(elem: DOMLElement, assoc_id: str): + assocs = list(get_assocs(elem, assoc_id)) + if len(assocs) >= 1: + return im.get(assocs[0]) + return None + + def validate_net(cnet: DOMLElement, parent_net: DOMLElement | None = None): + + if (parent_net): + check_proper_subnet(cnet, parent_net) + + if inet := get_elem(cnet, ASSOC_CONCRETE_MAPS): + check_infr_and_conc_protocol_match(inet, cnet) + check_cidr_and_address_range(inet, cnet) + check_gateway_belongs_to_network(inet, cnet) + check_iface_belongs_to_network(inet, cnet) + + debug = f"{cnet.user_friendly_name} [concrete]\n" + debug += f"\tprotocol={get_attr(cnet, ATTR_CONCRETE_PROTOCOL)}\n" + debug += f"\taddress_range={get_attr(cnet, ATTR_CONCRETE_ADDRESS_RANGE)}\n" + debug += f"\tsubnets=\t{get_assocs(cnet, ASSOC_CONCRETE_SUBNETS)}\n" + if inet: + debug += f"{inet.user_friendly_name} [infrastructure]\n" + debug += f"\tprotocol={get_attr(inet, ATTR_PROTOCOL)}\n" + debug += f"\tcidr={get_attr(inet, ATTR_NET_CIDR)}\n" + debug += f"\tsubnets=\t{get_assocs(inet, ASSOC_SUBNETS)}\n" + debug += f"\tifaces=\t{get_assocs(inet, ASSOC_NETIFACE)}\n" + debug += f"\tgateways=\t{get_assocs(inet, ASSOC_GATEWAYS)}\n" + debug += "\n" + # print(debug) + + csubnet_ids = get_assocs(cnet, ASSOC_CONCRETE_SUBNETS) + for csubnet_id in csubnet_ids: + if csubnet := im.get(csubnet_id): + + validate_net(csubnet, cnet) + + ## Checks ## + def check_infr_and_conc_protocol_match(inet: DOMLElement, cnet: DOMLElement): + """Checks if the protocol of an infrastructure network matches the respective protocol of its concrete counterpart.""" + iprot = get_attr(inet, ATTR_PROTOCOL) + cprot = get_attr(cnet, ATTR_CONCRETE_PROTOCOL) + if iprot and cprot and iprot != cprot: + warnings.append(f"Protocol of infrastructure network '{inet.user_friendly_name}' must match protocol of concrete network '{cnet.user_friendly_name}'.") + + def check_cidr_and_address_range(inet: DOMLElement, cnet: DOMLElement, warnings=warnings): + """Checks if the addressRange of a concrete network respects the CIDR specified in the infrastructure layer.""" + cidr = get_attr(inet, ATTR_NET_CIDR) + addr_range = get_attr(cnet, ATTR_CONCRETE_ADDRESS_RANGE) + if cidr and addr_range: + try: + addr_range = IPv4Network(addr_range) + if addr_range.prefixlen != cidr: + warnings.append(f"CIDR ({cidr}) of infrastructure network '{inet.user_friendly_name}' does not match the address range of concrete network '{cnet.user_friendly_name}'.") + except: + warnings.append(f"Failed to parse concrete network '{cnet.user_friendly_name}' address range as an IPv4Network.") + + def check_proper_subnet(cnet: DOMLElement, parent_net: DOMLElement): + """Checks if a subnet address range respects the parent net.""" + addr_range = get_attr(cnet, ATTR_CONCRETE_ADDRESS_RANGE) + parent_addr_range = get_attr(parent_net, ATTR_CONCRETE_ADDRESS_RANGE) + if addr_range and parent_addr_range: + try: + addr_range = IPv4Network(addr_range) + parent_addr_range = IPv4Network(parent_addr_range) + + if not addr_range.subnet_of(parent_addr_range): + warnings.append(f"Subnet '{cnet.user_friendly_name}' is not a proper subnet of '{parent_net.user_friendly_name}'.") + except: + warnings.append(f"Failed to parse concrete network '{cnet.user_friendly_name}' or '{parent_net.user_friendly_name}' address range as an IPv4Network.") + + def check_gateway_belongs_to_network(inet: DOMLElement, cnet: DOMLElement): + """Checks if the address of the gateways of a network belongs to that network address range.""" + addr_range = get_attr(cnet, ATTR_CONCRETE_ADDRESS_RANGE) + gateway_ids = get_assocs(inet, ASSOC_GATEWAYS) + + if addr_range and gateway_ids: + for gateway_id in gateway_ids: + if gateway := im.get(gateway_id): + addr_gateway = get_attr(gateway, ATTR_GATEWAY_ADDRESS) + if addr_gateway: + try: + addr_range = IPv4Network(addr_range) + addr_gateway = IPv4Address(addr_gateway) + if addr_gateway not in addr_range: + warnings.append(f"Gateway '{gateway.user_friendly_name}' does not belong to network '{cnet.user_friendly_name}'.") + except: + warnings.append(f"Failed to parse concrete network {cnet.user_friendly_name} address range or its gateway address.") + + def check_iface_belongs_to_network(inet: DOMLElement, cnet: DOMLElement): + """Checks if the address of the network interfaces of a network belongs to that network address range.""" + addr_range = get_attr(cnet, ATTR_CONCRETE_ADDRESS_RANGE) + iface_ids = get_assocs(inet, ASSOC_NETIFACE) + + if addr_range and iface_ids: + for iface_id in iface_ids: + if iface := im.get(iface_id): + addr_iface = get_attr(iface, ATTR_NETIFACE_ADDRESS) + if addr_iface: + try: + addr_range = IPv4Network(addr_range) + addr_iface = IPv4Address(addr_iface) + if addr_iface not in addr_range: + warnings.append(f"Network Interface '{addr_iface.user_friendly_name}' does not belong to network '{cnet.user_friendly_name}'.") + except Exception as e: + print(e) + warnings.append(f"Failed to parse concrete network {cnet.user_friendly_name} address range or its associated network interface '{iface.user_friendly_name}' address.") + + + + + concrete_networks = [e for e in im.values() if e.class_ == CONCRETE_NETWORK] + + # print('-'*20) + # print('[DEBUG] Network Validation') + + for cnet in concrete_networks: + validate_net(cnet) + + # print('-'*20) + # print(warnings) + # print('-'*20) + + # networks = [e for e in im.values() if e.class_ == 'concrete_Network'] + # subnets = [e for e in im.values() if e.class_ == 'infrastructure_Subnet'] + # ifaces = [e for e in im.values() if e.class_ == 'infrastructure_NetworkInterface'] + + + # def visit_subnet(net: DOMLElement, acc: list): + # """Recursively navigate subnets to populate the `acc` list with all the subnet in a network.""" + # for subnet in get_assocs(net, ASSOC_SUBNETS): + # subnet = im[subnet] + # subnet_addr = fix_invalid_address(get_attr(subnet, ATTR_NET_ADDRESS), net, warnings) + # acc.append((subnet, IPv4Network(subnet_addr))) + # visit_subnet(subnet, acc) + + # def fix_invalid_address(address: any, net: DOMLElement, warning: list): + # # TODO: Use a match statement or use regexps once syntax for CIDR/Address is clear + # if isinstance(address, str) and address.startswith('/'): + # warning.append(("Network", f"Net '{net.user_friendly_name}' has an incomplete address: '{address}'. '0.0.0.0' has been temporarily assigned.")) + # return f"{BASE_ADDR}{address}" + + # return address + + + # for network in networks: + + # warning = [] + + # # Tuple(elem, cidr) + # subnets: list[tuple[DOMLElement, IPv4Network]] = [] + # # Tuple(elem, address) + # addresses: list[tuple[DOMLElement, IPv4Address]] = [] + + # # Add subnets (Networks) + # visit_subnet(network, subnets) + + # # pprint("SUBNETS:") + # # pprint(subnets) + + # # Add addresses (gateways, ifaces) + # for gateway in get_assocs(network, ASSOC_GATEWAYS): + # gateway = im[gateway] + # if gateway_address := get_attr(gateway, ATTR_GATEWAY_ADDRESS): + # addresses.append((gateway, IPv4Address(gateway_address))) + + # for iface in ifaces: + # if owner_id := get_assocs(iface, ASSOC_IFACE_NET): + # owner = im[list(owner_id)[0]] + # if owner.id_ in [s.id_ for (s, _) in subnets] + [network.id_]: + # if ((iface_address := get_attr(iface, ATTR_NETIFACE_ADDRESS)) + # and (owner_address := get_attr(owner, ATTR_NET_ADDRESS))): + # owner_address = fix_invalid_address(owner_address, owner, warning) + # iface_address = IPv4Address(iface_address) + # owner_address = IPv4Network(owner_address) + # # TODO: Remove? + # logging.info(f"{iface.user_friendly_name} ({iface_address}) belongs to {owner.user_friendly_name} ({owner_address})? {iface_address in owner_address.hosts()}") + + # addresses.append((iface, iface_address)) + # else: + # logging.info(f"NetworkInterface '{iface.user_friendly_name}' does not belong to net '{owner.user_friendly_name}'.") + # warning.append(( + # "Address", f"NetworkInterface '{iface.user_friendly_name}' does not belong to net '{owner.user_friendly_name}'." + # )) + + # # Validate Network and Subnets + # net_addr = fix_invalid_address(get_attr(network, ATTR_NET_ADDRESS), network, warning) + # # prepend 0.0.0.0 if starts with / i guess, print a warning + # print(f"{net_addr}\t{network.user_friendly_name}") + + # net = IPv4Network(net_addr) + + # if len(subnets) > 0: + # for (obj, sn) in subnets: + # logging.info(f"{sn}\t{obj.user_friendly_name} belongs? {sn.subnet_of(net)}") + # if not sn.subnet_of(net): + # warning.append(( + # "Subnet", f"Subnet {obj.user_friendly_name} ({sn}) does not belong to net '{network.user_friendly_name}' ({net_addr})." + # )) + # else: + # print("No subnets found!") + + # # Validate addresses (again) + # for (obj, addr) in addresses: + # if addr not in net.hosts(): + # warning.append(( + # "Address", f"'{obj.user_friendly_name}' [{obj.class_}] ({addr}) does not belong to net '{network.user_friendly_name}' ({net_addr})." + # )) + # logging.info(f"NetworkInterface '{obj.user_friendly_name}' ({addr}) belong to net '{network.user_friendly_name}' ({net_addr})? {addr in net.hosts()}") + + # warnings.append((network.user_friendly_name, list(set(warning)))) + + return warnings + + + + + diff --git a/mc_openapi/doml_mc/xmi_parser/special_parsers.py b/mc_openapi/doml_mc/xmi_parser/special_parsers.py index 66e9b88b96b9870a930d7096845ed5046578cd32..6509d13e4f6c9a4c6410a60e13072029fbd14820 100644 --- a/mc_openapi/doml_mc/xmi_parser/special_parsers.py +++ b/mc_openapi/doml_mc/xmi_parser/special_parsers.py @@ -86,6 +86,12 @@ def init_special_parsers(): ("infrastructure_ComputingNode", "memory_mb"): parse_memory_mb, ("commons_FProperty", "value"): parse_fproperty, }, + DOMLVersion.V3_1: { + ("infrastructure_Network", "addressRange"): parse_cidr, + ("infrastructure_NetworkInterface", "endPoint"): parse_iface_address, + ("infrastructure_ComputingNode", "memory_mb"): parse_memory_mb, + ("commons_FProperty", "value"): parse_fproperty, + } } for ver in DOMLVersion: SpecialParsers[ver] = SpecialParser(MetaModels[ver], attribute_parsers[ver]) diff --git a/mc_openapi/notebooks/net_diagram.ipynb b/mc_openapi/notebooks/net_diagram.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..3f4ba4c94b2f72020349941dcaf747a0a703202c --- /dev/null +++ b/mc_openapi/notebooks/net_diagram.ipynb @@ -0,0 +1,239 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/andrea/Projects/piacere-model-checker\n" + ] + } + ], + "source": [ + "%cd ../.." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting diagrams\n", + " Downloading diagrams-0.23.3-py3-none-any.whl (24.4 MB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m24.4/24.4 MB\u001b[0m \u001b[31m14.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mm eta \u001b[36m0:00:01\u001b[0m[36m0:00:01\u001b[0m\n", + "\u001b[?25hCollecting graphviz<0.21.0,>=0.13.2 (from diagrams)\n", + " Downloading graphviz-0.20.1-py3-none-any.whl (47 kB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m47.0/47.0 kB\u001b[0m \u001b[31m16.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: jinja2<4.0,>=2.10 in ./.venv/lib64/python3.11/site-packages (from diagrams) (3.1.2)\n", + "Collecting typed-ast<2.0.0,>=1.5.4 (from diagrams)\n", + " Downloading typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (860 kB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m860.3/860.3 kB\u001b[0m \u001b[31m14.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m31m15.1 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: MarkupSafe>=2.0 in ./.venv/lib64/python3.11/site-packages (from jinja2<4.0,>=2.10->diagrams) (2.1.2)\n", + "Installing collected packages: typed-ast, graphviz, diagrams\n", + "Successfully installed diagrams-0.23.3 graphviz-0.20.1 typed-ast-1.5.5\n", + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.1.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.2.1\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install diagrams" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [], + "source": [ + "# XMI_PATH = \"./tests/doml/CaseStudies/posidonia.domlx\"\n", + "XMI_PATH = \"./tests/doml/CaseStudies/nio3_test_exec_env.domlx\"\n", + "\n", + "with open(XMI_PATH, 'rb') as f:\n", + " doml_xmi = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from mc_openapi.doml_mc.intermediate_model.metamodel import DOMLVersion\n", + "from mc_openapi.doml_mc.main import init_model\n", + "\n", + "dmc = init_model(doml_xmi, doml_ver=None)\n", + "\n", + "[x for x in dmc.intermediate_model.values() if x.user_friendly_name and x.user_friendly_name.startswith(\"co1\")]" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [], + "source": [ + "from diagrams import Diagram, Cluster, Node, Edge\n", + "from diagrams.aws.compute import EC2, ECS, AutoScaling, AMI, Compute, EC2Instance, AppRunner\n", + "from diagrams.aws.network import CloudFront, APIGateway, TransitGateway\n", + "from diagrams.aws.storage import S3\n", + "from diagrams.aws.security import Shield, IAMPermissions, IdentityAndAccessManagementIamAddOn as KeyPair\n", + "from diagrams.aws.general import General\n", + "from diagrams.aws.database import DB\n", + "from diagrams.aws.mobile import APIGateway\n", + "\n", + "from mc_openapi.doml_mc.intermediate_model.doml_element import DOMLElement\n", + "\n", + "elems = [elem for elem in dmc.intermediate_model.values()]\n", + "\n", + "common_elems = [e for e in elems if e.class_.startswith(\"commons_\") if e.class_ not in [\"commons_Deployment\", \"commons_Configuration\", \"commons_SProperty\", \"commons_FProperty\", \"commons_BProperty\"]] \n", + "deployments = [e for e in elems if e.class_ == \"commons_Deployment\"] \n", + "app_elems = [e for e in elems if e.class_.startswith(\"application_\") and e.class_ != \"application_ApplicationLayer\"] \n", + "infr_elems = [e for e in elems if e.class_.startswith(\"infrastructure_\") and e.class_ != \"infrastructure_InfrastructureLayer\"] \n", + "concr_elems = [e for e in elems if e.class_.startswith(\"concrete_\") and e.class_ != \"concrete_ConcreteInfrastructure\"] \n", + "\n", + "group_elems = {\"Application\": app_elems, \"Infrastructure\": infr_elems, \"Concretization\": concr_elems}\n", + "\n", + "def prettify_class_name(name: str):\n", + " _, name = name.split('_', 1)\n", + " return name\n", + "\n", + "def prettify_assoc_name(assoc: str):\n", + " _, assoc = assoc.split('::', 1)\n", + " return assoc\n", + "\n", + "def get_component(elem: DOMLElement):\n", + " \n", + " class_name = prettify_class_name(elem.class_)\n", + "\n", + " name = f\"{elem.user_friendly_name or ''}\\n({class_name})\"\n", + "\n", + " match class_name:\n", + " case \"SoftwareComponent\":\n", + " return Compute(name)\n", + " case \"SoftwareInterface\":\n", + " return APIGateway(name)\n", + " case \"DBMS\":\n", + " return DB(name)\n", + " case \"Network\":\n", + " if address := elem.attributes.get('infrastructure_Network::cidr'):\n", + " name += f'\\nCIDR: {address[0]}'\n", + " return CloudFront(name)\n", + " case \"Subnet\":\n", + " if address := elem.attributes.get('infrastructure_Network::cidr'):\n", + " name += f'\\nCIDR: {address[0]}'\n", + " return CloudFront(name)\n", + " case \"InternetGateway\":\n", + " if address := elem.attributes.get('infrastructure_InternetGateway::address'):\n", + " name += f'\\nIP: {address[0]}'\n", + " return TransitGateway(name)\n", + " case \"NetworkInterface\":\n", + " if address := elem.attributes.get('infrastructure_NetworkInterface::endPoint'):\n", + " name += f'\\nIP: {address[0]}'\n", + " return APIGateway(name)\n", + " case \"Storage\":\n", + " return S3(name)\n", + " case \"VirtualMachine\":\n", + " return EC2(name)\n", + " case \"Container\":\n", + " return ECS(name)\n", + " case \"VMImage\":\n", + " return AMI(name)\n", + " case \"AutoScalingGroup\":\n", + " return AutoScaling(name)\n", + " case \"ComputingGroup\":\n", + " return EC2Instance(name)\n", + " case \"RuntimeProvider\":\n", + " return AppRunner(name)\n", + " case \"KeyPair\":\n", + " return KeyPair(name)\n", + " case \"UserPass\":\n", + " return KeyPair(name)\n", + " case \"SecurityGroup\":\n", + " return Shield(name)\n", + " case \"Rule\":\n", + " return IAMPermissions(name)\n", + " case _:\n", + " return General(name)\n", + " \n", + "graph_attr = {\n", + " \"pad\": \"1pt\"\n", + "}\n", + "\n", + "HIGHLIGHT_CONNECTIONS = [\n", + " 'infrastructure_NetworkInterface::belongsTo'\n", + "]\n", + "\n", + "with Diagram(\"DOML Model\", show=True, outformat=\"svg\", direction=\"TB\", graph_attr=graph_attr) as diagram:\n", + " cached_nodes: dict[str, Node] = {}\n", + " for gk, gv in group_elems.items():\n", + " with Cluster(gk):\n", + " cached_nodes |= {e.id_: get_component(e) for e in gv}\n", + " \n", + " # Dont group common elements\n", + " cached_nodes |= {e.id_: get_component(e) for e in common_elems}\n", + "\n", + " for groups in group_elems.values():\n", + " for elem in groups:\n", + " for assoc_k, assocs_v in elem.associations.items():\n", + " for assoc in assocs_v:\n", + " if (start := cached_nodes.get(elem.id_)) and (end := cached_nodes.get(assoc)):\n", + " if assoc_k in HIGHLIGHT_CONNECTIONS:\n", + " start >> Edge(label=prettify_assoc_name(assoc_k), color='green', style=\"bold\") >> end\n", + " elif 'maps' in assoc_k:\n", + " start >> Edge(label=prettify_assoc_name(assoc_k), style=\"bold\") >> end\n", + " else:\n", + " start >> end\n", + "\n", + " for dep in deployments:\n", + " for _component in dep.associations.get('commons_Deployment::component'):\n", + " for _node in dep.associations.get('commons_Deployment::node'):\n", + " if (start := cached_nodes.get(_component)) and (end := cached_nodes.get(_node)):\n", + " start >> Edge(style=\"bold\") >> end\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/mc_openapi/notebooks/net_validation.ipynb b/mc_openapi/notebooks/net_validation.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..7e432991179e0387f072f7ae99e568493c701e39 --- /dev/null +++ b/mc_openapi/notebooks/net_validation.ipynb @@ -0,0 +1,201 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/andrea/Projects/piacere-model-checker\n" + ] + } + ], + "source": [ + "%cd ../.." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# XMI_PATH = \"./tests/doml/CaseStudies/posidonia.domlx\"\n", + "# XMI_PATH = \"../piacere-workspace/Playground/NetValidation/test1.domlx\" # Subnets, Ifaces, Gateway\n", + "# XMI_PATH = \"./tests/doml/CaseStudies/posidonia_IOP.domlx\" # Subnets, no Gateway\n", + "# XMI_PATH = \"../piacere-workspace/Playground/CaseStudies/nio3_test_exec_env.domlx\" # No subnets, Gateway\n", + "# XMI_PATH = \"../piacere-workspace/Playground/CaseStudies/posidonia.domlx\"\n", + "XMI_PATH = \"../piacere-workspace/Playground/3.1/Ericsson_DOML.domlx\"\n", + "\n", + "with open(XMI_PATH, 'rb') as f:\n", + " doml_xmi = f.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from mc_openapi.doml_mc.main import init_model\n", + "\n", + "dmc = init_model(doml_xmi, doml_ver=None)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "AddressValueError", + "evalue": "Expected 4 octets in 'None'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAddressValueError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb Cell 4\u001b[0m line \u001b[0;36m1\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=99'>100</a>\u001b[0m \u001b[39mfor\u001b[39;00m (obj, addr) \u001b[39min\u001b[39;00m addresses:\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=100'>101</a>\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mNetworkInterface \u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00mobj\u001b[39m.\u001b[39muser_friendly_name\u001b[39m}\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m (\u001b[39m\u001b[39m{\u001b[39;00maddr\u001b[39m}\u001b[39;00m\u001b[39m) belong to net \u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00mnetwork\u001b[39m.\u001b[39muser_friendly_name\u001b[39m}\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m (\u001b[39m\u001b[39m{\u001b[39;00mnet_addr\u001b[39m}\u001b[39;00m\u001b[39m)? \u001b[39m\u001b[39m{\u001b[39;00maddr\u001b[39m \u001b[39m\u001b[39min\u001b[39;00m\u001b[39m \u001b[39mnet\u001b[39m.\u001b[39mhosts()\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m)\n\u001b[0;32m--> <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=104'>105</a>\u001b[0m validate_network_address(dmc)\n", + "\u001b[1;32m/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb Cell 4\u001b[0m line \u001b[0;36m6\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=56'>57</a>\u001b[0m addresses: \u001b[39mlist\u001b[39m[\u001b[39mtuple\u001b[39m[DOMLElement, IPv4Address]] \u001b[39m=\u001b[39m []\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=58'>59</a>\u001b[0m \u001b[39m# Add subnets (Networks)\u001b[39;00m\n\u001b[0;32m---> <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=59'>60</a>\u001b[0m visit_subnet(network, subnets)\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=61'>62</a>\u001b[0m \u001b[39m# pprint(\"SUBNETS:\")\u001b[39;00m\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=62'>63</a>\u001b[0m \u001b[39m# pprint(subnets)\u001b[39;00m\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=63'>64</a>\u001b[0m \n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=64'>65</a>\u001b[0m \u001b[39m# Add addresses (gateways, ifaces)\u001b[39;00m\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=65'>66</a>\u001b[0m \u001b[39mfor\u001b[39;00m gateway \u001b[39min\u001b[39;00m get_assocs(network, ASSOC_GATEWAYS):\n", + "\u001b[1;32m/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb Cell 4\u001b[0m line \u001b[0;36m4\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=40'>41</a>\u001b[0m subnet \u001b[39m=\u001b[39m im[subnet]\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=41'>42</a>\u001b[0m subnet_addr \u001b[39m=\u001b[39m fix_invalid_address( get_attr(subnet, ATTR_NET_ADDRESS) )\n\u001b[0;32m---> <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=42'>43</a>\u001b[0m acc\u001b[39m.\u001b[39mappend((subnet, IPv4Network(subnet_addr)))\n\u001b[1;32m <a href='vscode-notebook-cell:/home/andrea/Projects/piacere-model-checker/mc_openapi/notebooks/net_validation.ipynb#W3sZmlsZQ%3D%3D?line=43'>44</a>\u001b[0m visit_subnet(subnet, acc)\n", + "File \u001b[0;32m/usr/lib64/python3.11/ipaddress.py:1512\u001b[0m, in \u001b[0;36mIPv4Network.__init__\u001b[0;34m(self, address, strict)\u001b[0m\n\u001b[1;32m 1476\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\"Instantiate a new IPv4 network object.\u001b[39;00m\n\u001b[1;32m 1477\u001b[0m \n\u001b[1;32m 1478\u001b[0m \u001b[39mArgs:\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1508\u001b[0m \u001b[39m supplied.\u001b[39;00m\n\u001b[1;32m 1509\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 1510\u001b[0m addr, mask \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_split_addr_prefix(address)\n\u001b[0;32m-> 1512\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnetwork_address \u001b[39m=\u001b[39m IPv4Address(addr)\n\u001b[1;32m 1513\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnetmask, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_prefixlen \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_make_netmask(mask)\n\u001b[1;32m 1514\u001b[0m packed \u001b[39m=\u001b[39m \u001b[39mint\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnetwork_address)\n", + "File \u001b[0;32m/usr/lib64/python3.11/ipaddress.py:1315\u001b[0m, in \u001b[0;36mIPv4Address.__init__\u001b[0;34m(self, address)\u001b[0m\n\u001b[1;32m 1313\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39m'\u001b[39m\u001b[39m/\u001b[39m\u001b[39m'\u001b[39m \u001b[39min\u001b[39;00m addr_str:\n\u001b[1;32m 1314\u001b[0m \u001b[39mraise\u001b[39;00m AddressValueError(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mUnexpected \u001b[39m\u001b[39m'\u001b[39m\u001b[39m/\u001b[39m\u001b[39m'\u001b[39m\u001b[39m in \u001b[39m\u001b[39m{\u001b[39;00maddress\u001b[39m!r}\u001b[39;00m\u001b[39m\"\u001b[39m)\n\u001b[0;32m-> 1315\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_ip \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_ip_int_from_string(addr_str)\n", + "File \u001b[0;32m/usr/lib64/python3.11/ipaddress.py:1202\u001b[0m, in \u001b[0;36m_BaseV4._ip_int_from_string\u001b[0;34m(cls, ip_str)\u001b[0m\n\u001b[1;32m 1200\u001b[0m octets \u001b[39m=\u001b[39m ip_str\u001b[39m.\u001b[39msplit(\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[1;32m 1201\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(octets) \u001b[39m!=\u001b[39m \u001b[39m4\u001b[39m:\n\u001b[0;32m-> 1202\u001b[0m \u001b[39mraise\u001b[39;00m AddressValueError(\u001b[39m\"\u001b[39m\u001b[39mExpected 4 octets in \u001b[39m\u001b[39m%r\u001b[39;00m\u001b[39m\"\u001b[39m \u001b[39m%\u001b[39m ip_str)\n\u001b[1;32m 1204\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m 1205\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mint\u001b[39m\u001b[39m.\u001b[39mfrom_bytes(\u001b[39mmap\u001b[39m(\u001b[39mcls\u001b[39m\u001b[39m.\u001b[39m_parse_octet, octets), \u001b[39m'\u001b[39m\u001b[39mbig\u001b[39m\u001b[39m'\u001b[39m)\n", + "\u001b[0;31mAddressValueError\u001b[0m: Expected 4 octets in 'None'" + ] + } + ], + "source": [ + "from pprint import pprint\n", + "from mc_openapi.doml_mc.intermediate_model import DOMLElement\n", + "from mc_openapi.doml_mc.mc import ModelChecker\n", + "\n", + "from ipaddress import IPv4Address, IPv4Network\n", + "\n", + "BASE_ADDR = '0.0.0.0'\n", + "\n", + "ASSOC_SUBNETS = 'infrastructure_Network::subnets'\n", + "ASSOC_GATEWAYS = 'infrastructure_Network::gateways'\n", + "ASSOC_IFACE_NET = 'infrastructure_NetworkInterface::belongsTo'\n", + "\n", + "ATTR_NET_ADDRESS = 'infrastructure_Network::cidr' # not here anymore\n", + "ATTR_GATEWAY_ADDRESS = 'infrastructure_InternetGateway::address'\n", + "ATTR_IFACE_ADDRESS = 'infrastructure_NetworkInterface::endPoint'\n", + "\n", + "def get_attr(elem: DOMLElement, attr_id: str):\n", + " if elem := elem.attributes.get(attr_id):\n", + " return elem[0]\n", + " return None\n", + " \n", + "def get_assocs(elem: DOMLElement, assoc_id: str):\n", + " return elem.associations.get(assoc_id, [])\n", + "\n", + "def validate_network_address(dmc: ModelChecker):\n", + " im = dmc.intermediate_model\n", + "\n", + " networks = [e for e in im.values() if e.class_ == 'infrastructure_Network']\n", + " ifaces = [e for e in im.values() if e.class_ == 'infrastructure_NetworkInterface']\n", + " subnets = [e for e in im.values() if e.class_ == 'infrastructure_Subnet']\n", + "\n", + "# Network/24\n", + "# Subnet/28\n", + "# Subnet/30\n", + "# Address\n", + "# Address\n", + "\n", + " def visit_subnet(net: DOMLElement, acc: list):\n", + " \"\"\"Recursively navigate subnets to populate the `acc` list with all the subnet in a network.\"\"\"\n", + " for subnet in get_assocs(net, ASSOC_SUBNETS):\n", + " subnet = im[subnet]\n", + " subnet_addr = fix_invalid_address( get_attr(subnet, ATTR_NET_ADDRESS) )\n", + " acc.append((subnet, IPv4Network(subnet_addr)))\n", + " visit_subnet(subnet, acc)\n", + "\n", + " def fix_invalid_address(address: any):\n", + " if isinstance(address, str) and address.startswith('/'):\n", + " return f\"{BASE_ADDR}{address}\"\n", + "\n", + " return address\n", + "\n", + "\n", + " for network in networks:\n", + " # Tuple(elem, cidr)\n", + " subnets: list[tuple[DOMLElement, IPv4Network]] = []\n", + " # Tuple(elem, address)\n", + " addresses: list[tuple[DOMLElement, IPv4Address]] = []\n", + "\n", + " # Add subnets (Networks)\n", + " visit_subnet(network, subnets)\n", + "\n", + " # pprint(\"SUBNETS:\")\n", + " # pprint(subnets)\n", + "\n", + " # Add addresses (gateways, ifaces)\n", + " for gateway in get_assocs(network, ASSOC_GATEWAYS):\n", + " gateway = im[gateway]\n", + " if gateway_address := get_attr(gateway, ATTR_GATEWAY_ADDRESS):\n", + " addresses.append((gateway, IPv4Address(gateway_address)))\n", + "\n", + " for iface in ifaces:\n", + " if owner_id := get_assocs(iface, ASSOC_IFACE_NET):\n", + " owner = im[list(owner_id)[0]]\n", + " if owner.id_ in [s.id_ for (s, _) in subnets] + [network.id_]:\n", + " if ((iface_address := get_attr(iface, ATTR_IFACE_ADDRESS))\n", + " and (owner_address := get_attr(owner, ATTR_NET_ADDRESS))):\n", + " owner_address = fix_invalid_address(owner_address)\n", + " iface_address = IPv4Address(iface_address)\n", + " owner_address = IPv4Network(owner_address)\n", + " print(f\"{iface.user_friendly_name} ({iface_address}) belongs to {owner.user_friendly_name} ({owner_address})? {iface_address in owner_address.hosts()}\")\n", + "\n", + " addresses.append((iface, iface_address))\n", + " else:\n", + " print(f\"NetworkInterface '{iface.user_friendly_name}' does not belong to net '{owner.user_friendly_name}'.\")\n", + "\n", + " # Validate Network and Subnets\n", + " net_addr = fix_invalid_address( get_attr(network, ATTR_NET_ADDRESS) )\n", + " # prepend 0.0.0.0 if starts with / i guess, print a warning\n", + " print(f\"{net_addr}\\t{network.user_friendly_name}\")\n", + "\n", + " net = IPv4Network(net_addr)\n", + "\n", + " if len(subnets) > 0:\n", + " for (obj, sn) in subnets:\n", + " print(f\"{sn}\\t{obj.user_friendly_name} belongs? {sn.subnet_of(net)}\")\n", + " else:\n", + " print(\"No subnets!\")\n", + "\n", + " # Validate addresses (again)\n", + " for (obj, addr) in addresses:\n", + " print(f\"NetworkInterface '{obj.user_friendly_name}' ({addr}) belong to net '{network.user_friendly_name}' ({net_addr})? {addr in net.hosts()}\")\n", + "\n", + " \n", + "\n", + "validate_network_address(dmc)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tests/domlr/example_single_req_v3.0.domlr b/tests/domlr/example_single_req_v3.0.domlr new file mode 100644 index 0000000000000000000000000000000000000000..8adb15392a464475797d6f33a5b05781b3c7f044 --- /dev/null +++ b/tests/domlr/example_single_req_v3.0.domlr @@ -0,0 +1,18 @@ +# vm, iface = get_consts(smtsorts, ["vm", "iface"]) +# return And( +# smtenc.element_class_fun(vm) == smtenc.classes["infrastructure_VirtualMachine"], +# Not( +# Exists( +# [iface], +# ENCODINGS.association_rel(vm, smtenc.associations["infrastructure_ComputingNode::ifaces"], iface) +# ) +# ) +# ) + +- "All VMs have at least one interface 1" + vm is class infrastructure.VirtualMachine + and + not exists iface ( + vm has abstract.Node.ifaces iface + ) + error: "VM {vm} has no associated interface."