TOSCA
The Infrastructure Manager supports the definition of Cloud topologies using OASIS TOSCA Simple Profile in YAML Version 1.0.
The TOSCA support was developed under the framework of the INDIGO DataCloud EU project. You can see some input examples at https://github.com/grycap/tosca/tree/main/templates.
Basic example
This TOSCA file describes a cloud topology with 2 VM with at least 2 CPUs and 2 GB of RAM and 40 GB of root disk, connected with a public IP, using an Ubuntu 20.04 image. As outputs, the TOSCA file will return the public IP of the VM and the SSH credentials to access it.
tosca_definitions_version: tosca_simple_yaml_1_0
imports:
- indigo_custom_types: https://raw.githubusercontent.com/indigo-dc/tosca-types/master/custom_types.yaml
topology_template:
node_templates:
simple_node:
type: tosca.nodes.Compute
scalable:
properties:
count: 2
capabilities:
endpoint:
properties:
network_name: PUBLIC
host:
properties:
num_cpus: 2
mem_size: 2 GB
disk_size: 40 GB
os:
properties:
type: linux
distribution: ubuntu
version: 22.04
outputs:
node_ip:
value: { get_attribute: [ simple_node, public_address, 0 ] }
node_creds:
value: { get_attribute: [ simple_node, endpoint, credential, 0 ] }
Setting VMI URI
As in RADL, you can set a specific URI identifying the VMI to use in the VM.
The URI format is the same used in RADL (System Features). In this case
the type must be changed to tosca.nodes.indigo.Compute (the Compute normative
type does not support the os image property), and the image property must
be added in the os capability.
...
simple_node:
type: tosca.nodes.indigo.Compute
capabilities:
endpoint:
properties:
network_name: PUBLIC
host:
properties:
num_cpus: 2
mem_size: 2 GB
os:
properties:
image: one://someserver.com/123
...
Advanced Compute host properties
The tosca.nodes.indigo.Compute custom type adds a new set of advanced features to the
host properties, enabling the request of GPUs and
Intel SGX CPU support
in the compute node.
...
simple_node:
type: tosca.nodes.indigo.Compute
capabilities:
host:
properties:
num_cpus: 2
mem_size: 2 GB
num_gpus: 1
gpu_vendor: nvidia
gpu_model: Tesla V100
sgx: false
...
Network properties
Basic properties
The easiest way to specify network requirements of the Compute node is using the endpoint capability properties. For example, the following example the compute node requests for a public IP.
...
simple_node:
type: tosca.nodes.Compute
capabilities:
endpoint:
properties:
network_name: PUBLIC
...
Possible values of the network_name endpoint property:
PRIVATE: The Compute node does not require a public IP. This is the default behaviour if no endpoint capability is defined.
PUBLIC: The Compute node requires a public IP.
Network provider ID: As the provider_id network property in RADL It defines the name of the network in a specific Cloud provider (see Network Features):
Furthermore, the endpoint capability has a set of additional properties to set the DNS name of the node or the set of ports to be externally accessible.
Advanced properties
In case you need a more detailed definition of the networks, you can use the
tosca.nodes.network.Network and tosca.nodes.network.Port TOSCA normative types.
In this way you can define the set of networks needed in your topology using the ports to
link the networks with the Compute nodes.
...
pub_network:
type: tosca.nodes.network.Network
properties:
network_type: public
server_pub_port:
type: tosca.nodes.network.Port
properties:
order: 1
ip_address: X.X.X.X # optional to request specific IP
requirements:
- binding: simple_node
- link: pub_network
priv_network:
type: tosca.nodes.network.Network
properties:
network_type: private
server_port:
type: tosca.nodes.network.Port
properties:
order: 0
requirements:
- binding: simple_node
- link: priv_network
...
Custom defined Port type tosca.nodes.indigo.network.Port has a set of additional properties:
dns_name: DNS name to assing to the network interface.
additional_ip: (OpenStack specific) Additional IP to be allowed to the network interface.
additional_dns_names: Additional DNS names.
Software Components
IM enable the use of Ansible playbooks as implementation scripts. Furthermore, it enables to specify
Ansible roles (tosca.artifacts.AnsibleGalaxy.role) and collections (tosca.artifacts.AnsibleGalaxy.collections)
to be installed and used in the playbooks.
Storage
IM enables the definition of BlockStorage volumes to be attached to the compute nodes. In this example we can see how to define a volume of 10GB to be attached to the compute node and mounted in the path /mnt/disk. The device parameter is optional and it is only needed in some cloud providers, in general is better not to add it.
...
simple_node:
type: tosca.nodes.Compute
...
requirements:
- local_storage:
node: my_storage
relationship:
type: AttachesTo
properties:
location: /mnt/disk
device: hdb # optional
my_storage:
type: tosca.nodes.BlockStorage
properties:
size: 10GB
...
Policies & groups
IM enables the definition of the specific cloud provider where the Compute nodes will be deployed in a hybrid deployment. For example, in the following code we assume that we have defined three compute nodes (compute_one, compute_two and compute_three). We can create a placement group with two of them (compute_one and compute_two) and then set a placement policy with a cloud_id (that must be defined in the Authorization File), and create a second placement policy where we can set a different cloud provider and, optionally, an availability zone.
...
groups:
my_placement_group:
type: tosca.groups.Root
members: [ compute_one, compute_two ]
policies:
- deploy_group_on_cloudid:
type: tosca.policies.indigo.Placement
properties: { cloud_id: cloudid1 }
targets: [ my_placement_group ]
- deploy_on_cloudid:
type: tosca.policies.indigo.Placement
properties: { cloud_id: cloudid2, availability_zone: some_zone }
targets: [ compute_three ]
...
Container Applications (Kubernetes connector)
IM also enables the definition of container applications to be deployed in a Kubernetes cluster.
In the following example, we can see how to define a container application (IM) that uses a
ConfigMap for a configuration file. The IM application is connected with a MySQL backend
using the IM_DATA_DB environment variable. The MySQL container is defined with a Persistent
Volume Claim (PVC) of 10GB. The IM assumes the Kuberentes cluster ha some Dynamic volume
provisioning enabled.
Furthermore, the IM application specifies an endpoint to be published that will result in the
creation of a Kubernetes Ingress.
...
node_templates:
im_container:
type: tosca.nodes.Container.Application.Docker
properties:
environment:
IM_DATA_DB:
concat:
- "mysql://root:"
- { get_input: mysql_root_password }
- "@"
- { get_attribute: [ mysql_container, endpoints, 0 ] }
- "/im-db"
requirements:
- host: im_runtime
artifacts:
my_image:
file: grycap/im
type: tosca.artifacts.Deployment.Image.Container.Docker
my_config_map:
deploy_path: /etc/im/im.cfg
file: https://raw.githubusercontent.com/grycap/im/master/etc/im.cfg
type: tosca.artifacts.File
properties:
# when the content is not provided, the file is downloaded from the URL
# otherwise, the file is ignored
# If the content is base64 encoded, it is assumed to be a K8s Secret
content: |
[im]
REST_API = True
# The properties of the runtime to host the container
im_runtime:
type: tosca.nodes.Container.Runtime.Docker
capabilities:
host:
properties:
num_cpus: 0.5
mem_size: 1 GB
publish_ports:
- protocol: tcp
target: 8800
source: 30880
endpoint: https://im.domain.com/im
# The MYSQL container based on official MySQL image in Docker hub
mysql_container:
type: tosca.nodes.Container.Application.Docker
properties:
environment:
MYSQL_ROOT_PASSWORD: { get_input: mysql_root_password }
MYSQL_DATABASE: "im-db"
requirements:
- host: mysql_runtime
artifacts:
my_image:
file: mysql:8
type: tosca.artifacts.Deployment.Image.Container.Docker
# The properties of the runtime to host the container
mysql_runtime:
type: tosca.nodes.Container.Runtime.Docker
capabilities:
host:
properties:
num_cpus: 0.5
mem_size: 1 GB
expose_ports:
- protocol: tcp
target: 3306
volumes:
- "some_vol:/var/lib/mysql"
some_vol:
type: tosca.nodes.BlockStorage
properties:
size: 10 GB
# Set the PV name in this field
# volume_id: "PV name"
outputs:
im_service_endpoint:
value: { get_attribute: [ im_container, endpoints, 0 ] }
Advanced Output values
The tosca.nodes.indigo.Compute node type adds a new
attribute named: ansible_output. It is a map that has one element per each IM
configuration step, so you can access it by name. The steps have the keyword
tasks, that is also a map that has one element per ansible task. In this case
it can be accessed using the task name as defined in the playbook. Finally
there is an output keyword that returns the output of the task.
In most of the cases the task is a debug ansible task that shows anything you
want to return.
In the following example, the specified task was a debug ansible task that shows the value of a internally defined value.
...
outputs:
node_ip:
value:
get_attribute:
- front
- ansible_output
- lrms_front_end_front_conf_front
- tasks
- 'grycap.nomad : nomad_secret_id'
- output
Special Input values
The IM TOSCA parser supports the generation of some special values for string inputs.
Random values
The special string random(N) generates a random string of length N with
alphanumeric characters. It can be used to define passwords or any other random
string input value (from version 1.19.2).
...
inputs:
app_password:
type: string
description: Password for the App
default: 'random(12)'
Access Token
The special string access_token() substitutes the function with the OIDC
user access token sent in the authorization header sent in the IM call,
in the InfrastructureManager type element. If user/password has sent to
authenticate with the IM, the string will be left unchanged.
...
inputs:
user_access_token:
type: string
description: User OIDC Access Token
default: 'access_token()'