Use Heat to create and manage Tungsten Fabric objects

Utilizing OpenStack Heat templates is a common practice to orchestrate Tungsten Fabric resources. Heat allows for the definition of templates, which can depict the relationships between resources such as networks, and enforce policies accordingly. Through these templates, OpenStack REST APIs are invoked to create the necessary infrastructure in the correct order required to launch applications.

Managing Tungsten Fabric resources through OpenStack Heat represents a structured and automated approach as compared to using of Tungsten Fabric UI or API directly. The Heat templates provide a declarative mechanism to define and manage infrastructure, ensuring repeatability and consistency across deployments. This contrasts with the manual and potentially error-prone process of managing resources through the Tungsten Fabric UI and API.

To orchestrate Tungsten Fabric objects through a Heat template:

  1. Define the template with the Tungsten Fabric objects as required.

    Note

    You can view the full list of Heat resources available in your environment from either OpenStack Horizon dashboard, the Project > Orchestration > Resource Types page, or the OpenStack CLI:

    openstack orchestration resource type list
    

    Also, you can obtain the specification of the Tungsten Fabric configuration API by accessing http://TF_API_ADDRESS:8082/documentation/contrail_openapi.html on your environment.

    Below is an example template showcasing a Heat topology that illustrates the creation sequence of the following Tungsten Fabric resources: instance, port, network, router, and external network.

    Example Heat topology with Tungsten Fabric resources
    heat_template_version: 2015-04-30
    description: HOT template to create a Instance connected to external network
    parameters:
      stack_prefix:
        type: string
        description: Prefix name for stack resources.
        default: "net-logical-router"
      project:
        type: string
        description: project for the Server
      public_network_id:
        type: string
      floating_ip_pool:
        type: string
      subnet_ip_prefix:
        type: string
        default: '192.168.96.0'
      subnet_ip_prefix_len:
        type: string
        default: '24'
      server_image:
        type: string
        description: Name of image to use for server.
        default: 'Cirros-6.0'
      availability_zone:
        type: string
        default: 'nova'
    resources:
      ipam:
        type: OS::ContrailV2::NetworkIpam
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "ipam" ] ] }
          project: { get_param: project }
      private_network:
        type: OS::ContrailV2::VirtualNetwork
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "network" ] ] }
          project: { get_param: project }
          network_ipam_refs: [{ get_resource: ipam }]
          network_ipam_refs_data: [
            {
              network_ipam_refs_data_ipam_subnets: [
                {
                  network_ipam_refs_data_ipam_subnets_subnet_name: { list_join: [ '_', [ get_param: stack_prefix, "subnet" ] ] },
                  network_ipam_refs_data_ipam_subnets_subnet:
                    {
                      network_ipam_refs_data_ipam_subnets_subnet_ip_prefix: '192.168.96.0',
                      network_ipam_refs_data_ipam_subnets_subnet_ip_prefix_len: '24',
                    },
                  network_ipam_refs_data_ipam_subnets_allocation_pools: [
                    {
                      network_ipam_refs_data_ipam_subnets_allocation_pools_start: '192.168.96.10',
                      network_ipam_refs_data_ipam_subnets_allocation_pools_end: '192.168.96.100'
                    }
                  ],
                  network_ipam_refs_data_ipam_subnets_default_gateway: '192.168.96.1',
                  network_ipam_refs_data_ipam_subnets_enable_dhcp: 'true',
                }
              ]
            }
          ]
      private_network_interface:
        type: OS::ContrailV2::VirtualMachineInterface
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "interface" ] ] }
          project: { get_param: project }
          virtual_machine_interface_device_owner: 'network:router_interface'
          virtual_machine_interface_bindings: {
            virtual_machine_interface_bindings_key_value_pair: [
              {
                virtual_machine_interface_bindings_key_value_pair_key: 'vnic_type',
                virtual_machine_interface_bindings_key_value_pair_value: 'normal'
              }
            ]
          }
          virtual_network_refs: [{ get_resource: private_network }]
      instance_ip:
        type: OS::ContrailV2::InstanceIp
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "instance_ip" ] ] }
          fq_name: { list_join: [ '_', [ "fq_name", get_param: stack_prefix ] ] }
          virtual_network_refs: [{ get_resource: private_network }]
          virtual_machine_interface_refs: [{ get_resource: private_network_interface }]
      router:
        type: OS::ContrailV2::LogicalRouter
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "router" ] ] }
          project: { get_param: project }
          virtual_machine_interface_refs: [{ get_resource: private_network_interface }]
          virtual_network_refs: [{ get_param: public_network_id }]
          virtual_network_refs_data: [
            {
              virtual_network_refs_data_logical_router_virtual_network_type: 'ExternalGateway'
            },
          ]
      security_group:
        type: OS::ContrailV2::SecurityGroup
        properties:
          # description: SG with allowed ssh/icmp traffic
          name: { list_join: [ '_', [ get_param: stack_prefix, "sg" ] ] }
          project: { get_param: project }
          security_group_entries: {
            security_group_entries_policy_rule: [
              {
                security_group_entries_policy_rule_direction: '>',
                security_group_entries_policy_rule_protocol: 'any',
                security_group_entries_policy_rule_ethertype: 'IPv4',
                security_group_entries_policy_rule_src_addresses: [
                  {
                    security_group_entries_policy_rule_src_addresses_security_group: 'local',
                  }
                ],
                security_group_entries_policy_rule_dst_addresses: [
                  {
                    security_group_entries_policy_rule_dst_addresses_subnet:
                      {
                        security_group_entries_policy_rule_dst_addresses_subnet_ip_prefix: '0.0.0.0',
                        security_group_entries_policy_rule_dst_addresses_subnet_ip_prefix_len: '0',
                      },
                  }
                ]
              },
              {
                security_group_entries_policy_rule_direction: '>',
                security_group_entries_policy_rule_protocol: 'any',
                security_group_entries_policy_rule_ethertype: 'IPv6',
                security_group_entries_policy_rule_src_addresses: [
                  {
                    security_group_entries_policy_rule_src_addresses_security_group: 'local',
                  }
                ],
                security_group_entries_policy_rule_dst_addresses: [
                  {
                    security_group_entries_policy_rule_dst_addresses_subnet:
                      {
                        security_group_entries_policy_rule_dst_addresses_subnet_ip_prefix: '::',
                        security_group_entries_policy_rule_dst_addresses_subnet_ip_prefix_len: '0',
                      },
                  }
                ]
              },
              {
                security_group_entries_policy_rule_direction: '>',
                security_group_entries_policy_rule_protocol: 'icmp',
                security_group_entries_policy_rule_ethertype: 'IPv4',
                security_group_entries_policy_rule_src_addresses: [
                  {
                    security_group_entries_policy_rule_src_addresses_subnet:
                      {
                        security_group_entries_policy_rule_src_addresses_subnet_ip_prefix: '0.0.0.0',
                        security_group_entries_policy_rule_src_addresses_subnet_ip_prefix_len: '0',
                      },
                  }
                ],
                security_group_entries_policy_rule_dst_addresses: [
                  {
                    security_group_entries_policy_rule_dst_addresses_security_group: 'local',
                  }
                ]
              },
              {
                security_group_entries_policy_rule_direction: '>',
                security_group_entries_policy_rule_protocol: 'tcp',
                security_group_entries_policy_rule_ethertype: 'IPv4',
                security_group_entries_policy_rule_src_addresses: [
                  {
                    security_group_entries_policy_rule_src_addresses_subnet:
                      {
                        security_group_entries_policy_rule_src_addresses_subnet_ip_prefix: '0.0.0.0',
                        security_group_entries_policy_rule_src_addresses_subnet_ip_prefix_len: '0',
                      }
                  }
                ],
                security_group_entries_policy_rule_dst_addresses: [
                  {
                    security_group_entries_policy_rule_dst_addresses_security_group: 'local',
                  }
                ],
                security_group_entries_policy_rule_dst_ports: [
                  {
                    security_group_entries_policy_rule_dst_ports_start_port: '22',
                    security_group_entries_policy_rule_dst_ports_end_port: '22',
                  }
                ]
              }
            ]
          }
      flavor:
        type: OS::Nova::Flavor
        properties:
          disk: 3
          name: { list_join: [ '_', [ get_param: stack_prefix, "flavor" ] ] }
          ram: 1024
          vcpus: 2
      server_port:
        type: OS::Neutron::Port
        properties:
          network_id: { get_resource: private_network }
          binding:vnic_type: 'normal'
          security_groups: [ { get_resource: security_group } ]
      server:
        type: OS::Nova::Server
        properties:
          name: { list_join: [ '_', [ get_param: stack_prefix, "server" ] ] }
          image: { get_param: server_image }
          flavor: { get_resource: flavor }
          availability_zone: { get_param: availability_zone }
          networks:
            - port: { get_resource: server_port }
      server_fip:
        type: OS::ContrailV2::FloatingIp
        properties:
          floating_ip_pool: { get_param: floating_ip_pool }
          virtual_machine_interface_refs: [{ get_resource: server_port }]
    outputs:
      server_fip:
        description: Floating IP address of server in public network
        value: { get_attr: [ server_fip, floating_ip_address ] }
    
  2. Create an environment file to define values to put in the variables in the template file:

    parameters:
      stack_prefix: <STACK_NAME>
      project: <PROJECT>
      public_network_id: <PUBLIC_NETWORK_ID>
      floating_ip_pool: <FLOATING_IP_POOL_UUID>
      server_image: <SERVER_IMAGE>
    
  3. Use the OpenStack CLI or other client libraries to deploy the defined template:

    openstack stack create -e <ENV_FILE_NAME> -t <TEMPLATE_FILE_NAME> <STACK_NAME>
    

As a result of this procedure, you create and configure the Tungsten Fabric resources as specified in the template.