Adding new provider

Template of project files structure:

On client:

ansible_plugins/
|-- plugins
|   |-- module_utils
|   |   |-- cloud_infra_by_tosca.py

In provider tool:

provider_tool/
|-- providers
|   |-- <provider>
|   |   |-- provider.cfg
|   |   |-- tosca_elements_map_to_provider.json
|   |   |-- TOSCA_<provider>_definition_1_0.yaml

The <provider> means the provider’s unique nic. Adding new provider includes several steps.

Prestep: considering main components of cloud

There is set of common parameters to launch virtual machine. This parameters are manages in different ways by different providers and a unified by TOSCA.

  • private address - the primary private IP address assigned by the cloud provider that applications may use to access the Compute node.

  • public address - he primary public IP address assigned by the cloud provider that applications may use to access the Compute node.

  • networks/ports: network names or ids or port names or ids or addresses

  • host: number of CPUs, disk size, RAM size or CPU frequency

  • endpoint - network access endpoint capability

    • protocol - http, https, ftp, tcp, udp, etc

    • port of endpoint

    • url path of endpoint’s address if applicable for the protocol

    • port name which endpoint should be bound to

    • network name which endpoint should be bound to

    • initiator - one of: source, target, peer

    • IP address as propagated up by the associated node’s host (Compute) container

    • if secured connection

  • os - operating system parameters:

    • architecture - x86_32, x86_64, etc.

    • type - linux, aix, mac, windows, etc.

    • distribution - debian, fedora, rhel and ubuntu

    • version

  • scalable: min, default, max of instances to launch

  • volumes: local storages

Step 1: Defining main components of cloud provider

Prestep results in set of virtual cloud resources containing required parameters (instances, images, security groups, etc.)

Define main components definitions in language specified by TOSCA.

The template of definition file must be:

tosca_definitions_version: tosca_simple_yaml_1_0
capability_types:
    <provider>.capabilities.Root:
        derived_from: tosca.capabilities.Root
    <...>
node_types:
    <provider>.nodes.Root:
        derived_from: tosca.nodes.Root
        capabilities:
            feature:
                type: <provider>.capabilities.Node
                occurrences: [ 1, 1 ]
        requirements:
            - dependency:
                capability: <provider>.capabilities.Node
                node: <provider>.nodes.Root
                relationship: <provider>.relationships.DependsOn
                occurrences: [ 0, UNBOUNDED ]
    <...>
relationship_types:
    <provider>.relationships.DependsOn:
        description: This type results in ordering of initializing objects.
        derived_from: tosca.relationships.DependsOn
        valid_target_types: [ <provider>.capabilities.Node ]
    <...>

Examples can be found in toscatranslator/providers/<provider> directories.

Step 2: Defining mapping between tosca.nodes.Compute and main components of cloud provider

This step is the declarative defining of mapping considered in Prestep using definitions from Step 1.

This mapping represents in either JSON or YAML format. Further the rules to describe the mapping are provided.

The parameters of TOSCA normative node type are determined as keys, and the parameters of the provider node types are determined as values. All parameters name must include the node type and the parameter section and name, which called extended parameter name. For example, tosca.nodes.Compute.attributes.private_address.

The values are represented in format, called value format. The value format can be of type list, map and string. If the value is of type map, then it’s one of the following cases:

  • keys are parameter, value, keyname: parameter contains the name of the specialized type parameter, the value contains the value of this parameter, keyname specialises the name of the node topology in which to add this parameter, keyname can be used to create several nodes of the same type. Be attentive and sure you don’t set existing names. Example:

tosca.nodes.Compute.capabilities.host.properties.num_cpus:
  parameter: openstack.nodes.Server.requirements
             .flavor.node_filter.properties.vcpus
  value: {self[value]}
  • keys are error, reason: used if the parameter cannot be specified in TOSCA template for a certain reason.

  • keys are source, parameters, extra, value, executor: used to add operation implementation and hence create a relationship, source represents the name of ansible module or any other command or source of a specific executor or the file name to execute, parameters are the arguments of the source, extra is the extra info, if Ansible is used parameters are the arguments of module and extra are the extra parameters of the task, value represents variable name passing after script execution, it can be unnecessary but must be defined any way, executor represents the configuration tool or some another supported executor (ex. ansible, python). Example:

- source: set_fact
  executor: ansible
  parameters:
    new_var: 1
  value: tmp_value
# example with python script
- source: transform_units
  parameters:
    source_value: "{self[value]}"
    is_without_b: True
  executor: python
  value: default
  • keys are value, condition, facts, arguments, executor: used if the value must be first chosen from existing cloud resources, facts represents the source which is use to get list of cloud resources paramters, facts need to be filtered for some value satisfying some condition and its arguments. Three conditions are supported: equals, contains, ip_contains. Example:

tosca.nodes.Compute.attributes.networks.*
                .addresses:
parameter: openstack.nodes.Server.requirements
                .nics.node_filter.properties.id
value:
  - value: network_id
  condition: ip_contains
  facts: os_subnets_facts.ansible_facts.openstack_subnets
  executor: ansible
  arguments:
  - allocation_pool_start
  - allocation_pool_end
  - "{self[value]}"

ATTENTION. Please don’t use reserved keys in you mapping values, ex. replace ‘parameter’ key by ‘input_parameter’.

The interpreter also defines a variable self that can be used to store and read some values in a key-value format. For example:

tosca.nodes.Compute.endpoint.attributes.ip_address:
  parameter: {self[buffer][security_group_rule][cidr_ip]}
  value: {self[value]}
tosca.nodes.Compute.endpoint.properties.initiator.target:
  parameter: amazon.nodes.SecurityGroup.properties.rules
  value:
    - {self[buffer][security_group_rule]}

There are also predefined values:

  • parameter contains the extended name of TOSCA normative type parameter

  • value contains the value defined by the key parameter in TOSCA template

  • name contains the current node name

As a result, any updates of cloud API or new versions of TOSCA standard causes only minor changes in the interpreter cloud definitions, which simplifies the process of adding a new cloud provider support.

ATTENTION You shouldn’t use multiple type deriviation from each other except default deriviation from Root. As it’s unknown actions to resolve dependencies from parents.

Step 3: Provider configuration file

Every provider is configured with configuration file which can be one the following (sorted by priority):

  1. <provider>.cfg in the working directory where user executes Clouni

  2. toscatranslator/providers/<provider>/provider.cfg in $TOSCA_HOME

  3. toscatranslator/providers/<provider>/<provider>.cfg in $TOSCA_HOME

<provider> means provider’s nic in Clouni

It has required settings for Clouni execution:

[main]
tosca_elements_definition_file = TOSCA_openstack_definition_1_0.yaml
tosca_elements_map_file = tosca_elements_map_to_openstack.yaml
  • tosca_elements_definition_file points to the name of the file created in Step 1

  • tosca_elements_map_file points to the name of the file created in Step 2

Paths to the specified files must be absolute or from the directory where provider configuration file is located.

Configuration tools are configured for every provider in provider configuration file. Settings must be in section names with the configuration tool. For example:

[ansible]
module_prefix = os_
module_description = Create OpenStack component
  • module_prefix is added to the name of provider component type, for example if openstack.nodes.Server is created then os_server Ansible module will be used

  • module_description is added as a description to the Ansible module

Every configuration tool can have it’s own setting parameters

If the mapping from Step 2 uses TOSCA node_filter (example), then the following section must be specified for every supported configuration tool:

[ansible.node_filter]
node_filter_source_prefix = os_
node_filter_source_postfix = _facts
node_filter_exceptions =
    subnet = os_subnets_facts
node_filter_inner_variable =
    image = ansible_facts,openstack_image
    flavor = ansible_facts,openstack_flavors
  • node_filter_source_prefix, node_filter_source_postfix is added to the name of provider component type, for example if openstack.nodes.Server is need to be filtered then os_server_facts Ansible module will be used

  • node_filter_exceptions is of key = value format and is used if prefix and postfix is not enough, for example openstack.nodes.Subnet would be filtered by os_subnets_facts not os_subnet_facts

  • node_filter_inner_variable is used to specify JSON keys if facts were received not as list, for example facts for openstack.nodes.Image would be received by module os_image_facts and the return value would be image_facts = output_os_image_facts["ansible_facts"]["openstack_image"]