Use Heat to create and manage OpenSDN objects¶
Utilizing OpenStack Heat templates is a common practice to orchestrate OpenSDN 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 OpenSDN resources through OpenStack Heat represents a structured and automated approach as compared to using of OpenSDN 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 OpenSDN UI and API.
To orchestrate OpenSDN objects through a Heat template:
Define the template with the OpenSDN 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 OpenSDN configuration API by accessing
http://TF_API_ADDRESS:8082/documentation/contrail_openapi.htmlon your environment.Below is an example template showcasing a Heat topology that illustrates the creation sequence of the following OpenSDN resources: instance, port, network, router, and external network.
Example Heat topology with OpenSDN 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 ] }
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>
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 OpenSDN resources as specified in the template.