This repository contains the API component of an implementation of the Simulation as a Service (SIMaaS)-concept based on the Functional Mock-up Interface (FMI) that uses dedicated worker-processes to execute simulation jobs distributed using a task queue. Find the worker implementation at https://github.com/UdSAES/simaas-worker.
From a functional perspective, the SIMaaS-implementation allows executing simulations of Functional Mock-up Units (FMUs) on a distributed, horizontally scalable set of computing resources via HTTP-requests. Moreover, the models and model instances registered with an API-instance can be downloaded and searched.
There are two variants of the API with different characteristics, depending on which format is chosen for resource representations:
-
a RESTful hypermedia API that transfers TriG- and JSON-LD-representations of resources using the RDF data model and supports HATEOAS; as well as
-
a REST-based HTTP-API that transfers JSON-representations of resources in an app-specific data model, documented according to the OpenAPI Specification (OAS).
The core intent of the hypermedia API-variant is to enable software agents to use the functionality exposed without (!) being explicitly programmed to do so and without having to “read” a manual like the OAS.
This is achieved by interlinking the resources exposed through machine-readable controls, just like links and forms interlink websites designed for humans. Additionally, RESTdesc descriptions explain triggers and consequences of possible state transitions to software agents. Thereby, the Hypermedia representations of resources become The Engine Of Application State (HATEOAS), as required by the Representational State Transfer (REST) constraints.
There is a Quad Pattern Fragments (QPF) interface exposed that enables querying the information held by an instance. SPARQL can be used to formulate these queries if a query engine that can decompose SPARQL queries into QPF requests, such as Comunica, is used.
A scientific paper describing motivation, concepts, system design and applications in detail, as well as the benefits of the design in terms of increased FAIRness and support for loose coupling, is currently under review.
The REST-based HTTP-API precedes the implementation of the hypermedia API.
Design concepts, software architecture and applications are discussed here:
Stüber, Moritz and Georg Frey (2021-09). "A Cloud-native Implementation of the Simulation as a Service-Concept Based on FMI". In: Proceedings of the 14th International Modelica Conference, Linköping, Sweden, September 20-24, 2021. Linköping University Electronic Press, pp. 393—402. DOI: 10.3384/ecp21181393
A demonstration of the capabilities by means of the examples described in the paper can be found at https://github.com/UdSAES/simaas-demo. The descriptions in the paper refer to v0.5.0 of the API and v0.1.0 of the worker-implementation.
Warning
|
Input validation for JSON request bodies was temporarily disabled in favour of simplifying the development of the hypermedia API-variant. Consider sticking to v0.5.0 for running the version presented at the Modelica conference. Moreover, JSON-representations and RDF-representations are not fully synchronized, so preferably use one variant only. |
The code can be executed directly on GNU/Linux host machines or containerized using Podman or Docker. In both cases, some environment variables (ENVVARs) must be set according to the table below.
There is an Ansible playbook that demonstrates a fully functional deployment of all necessary components using Docker. Because the playbook can be executed, this is likely the fastest way of arriving at a running instance! See scripts/deploy_using_ansible.yaml and documentation/deployment.adoc for details.
All environment variables without a default value MUST be set before starting the program. Otherwise, a fatal error will be raised and the program will terminate with a non-zero exit code.
Environment Variable | Description | Default Value |
---|---|---|
|
The size of the |
|
|
The path at which to store temporary files. Should be a |
— |
|
The path of the directory in which to store FMUs and other persistent data such as the internal list of model representations or the up-to-date OpenAPI-Specification. Should be on a volume if running containerized so the state survives container restarts. |
— |
|
The hostname of the RabbitMQ-instance |
— |
|
The username for the RabbitMQ-instance |
— |
|
The password for the RabbitMQ-instance |
— |
|
The hostname of the Redis-instance |
— |
|
The port on which to listen to incoming requests |
— |
|
The period in milliseconds at which to log heartbeat-messages |
|
|
The minimal included log level that shall be printed to |
|
|
The path to any static HTML file to be exposed; intended for rendered version of OAS |
|
|
The URL path at which to expose the static HTML file |
|
|
Whether ( |
|
|
The origin of a containerized Linked Data Fragments Server-instance to which requests are proxied |
— |
|
The container engine which runs the Linked Data Fragments Server-instance (only |
|
|
The name of the container in which the Linked Data Fragments Server-instance runs |
— |
|
The path at which to expose the QPF interface |
|
|
The configuration file for the Linked Data Fragments Server-instance |
|
-
Ensure that Node.js is installed
-
Install the dependencies by running
npm install
-
Apply a patch for an insufficient buffer size by running
node scripts/set_buffer_size_amqplib.js
-
Start at least one instance of the simaas-worker
-
Optionally, start an instance of the Linked Data Fragments Server
-
Set the required ENVVARs, for example by putting
export SIMAAS_*=…
-statements in a file named.env
and then loading the contents of this file viasource .env
-
Start the API by running
node index.js
-
Logs are serialized as JSON, so readability in a terminal increases greatly if the output is piped to jq
The steps outlined below are automated in scripts/deploy_using_ansible.yaml, look there for details!
-
Ensure that a container engine such as Docker or podman are installed and running.
-
Start instances of redis and RabbitMQ (both available on dockerhub)
-
Build the container image, e.g. using
podman build -t simaas-api:latest .
-
Start at least one instance of the simaas-worker
-
Set the required ENVVARs, for example by putting
export SIMAAS_*=…
-statements in a file named.env
and then loading the contents of this file viasource .env
-
Run the API as a container, e.g.:
podman run \ --name simaas-api \ --env SIMAAS_RABBITMQ_HOSTNAME=... \ --env SIMAAS_RABBITMQ_USERNAME=guest \ --env SIMAAS_RABBITMQ_PASSWORD=guest \ --env SIMAAS_REDIS_HOSTNAME=... \ -p 3000:3000 \ # (1) --rm -d \ simaas-api:latest
-
Within the container image,
SIMAAS_LISTEN_PORT
is set to 3000 and exposed, so port 3000 needs to be mapped to a port on the host.
-
-
Access the service instance in a browser using the URL
http://localhost:3000
-
Logs are serialized as JSON, so readability in a terminal increases greatly if the output is piped to jq
Request a supported serialization of RDF as the format for a resource representation using the "Accept"
-header and start browsing at /
. Supported serializations are:
'text/turtle', 'application/trig', 'application/n-triples', 'application/n-quads', 'application/ld+json' 'text/n3'
The RESTdesc-descriptions can be obtained through an OPTIONS
request to *
with the "Accept"
-header set to text/n3
.
See the repository https://github.com/UdSAES/pragmatic-proof-agent for an example of how the developed hypermedia API is used by a generic software agent.
Once all required components are running, you can access the API documentation at /ui
. It is rendered from the OpenAPI-Specification (OAS) using ReDoc.
Initially, the service instance does not know about any models. Therefore, you have to push a model to the service instance first. The model needs to be an FMU 2.0 for co-simulation that includes binaries for GNU/Linux. Two supported FMUs can be found in the simaas-demo-repository, alongside the implementation of two exemplary applications of the REST-based HTTP-API using these FMUs.
Optionally, the name(s) of one or more records[2] used for storing parameters can be supplied. These will then be used to filter the full list of parameters read from modelDescription.xml
in order to only expose those parameters that should actually be accessible through the API.
Once a model was successfully added, the OAS is updated and details on how to add model instances and simulate them become available.
Feedback is very welcome! Please open an issue for questions, remarks and bug reports; or open a pull request if you want to improve something. However, please note that further development will be dictated by what I need for my PhD thesis until that is finished.
The code in this repository uses Semantic Versioning (semver) and follows the semver specification.
JavaScript code and JSON documents are formatted automatically according to JavaScript Standard Style using prettier-standard
via npm run format
.
We will work on the following issues in the near future:
-
❏ provide more “rich” (meta)data, context and controls for all resources (revise)
-
❏ validate graphs supplied as request bodies against shape definition
-
❏ provide “Getting Started” including exemplary FMUs in documentation
-
❏ bring back API and unit tests (already exist but need updating)
-
❏ bring back input validation for JSON request bodies
-
❏ clarify additional restrictions posed on FMUs
-
❏ remove as many of these restrictions as possible
-
❏ investigate relation to and possible use of (parts of) the SSP-standard
-
❏ shorten README/make more concise by moving details to separate files?
-
❏ …
The source code is licensed under the MIT License. This is specified in the format suggested by the REUSE SOFTWARE-initiative — in short: SPDX IDs are included in every non-binary file and the license text can be found in ./LICENSES/.
From January 2017 to March 2021, this work was supported by the SINTEG-project “Designetz” funded by the German Federal Ministry of Economic Affairs and Energy (BMWi) under grant 03SIN224.