An Introduction to OpenStack Automation with HEAT

The OpenStack dashboard provides an easy interface to create the infrastructure that your project requires. However, there is often a requirement to spin up and shut down discreet configurations of instances and networks that would be tedious to do again every time they are needed. For this reason, OpenStack provides the means to automate the process of creating resources via small, human-editable scripts. These are known as HEAT orchestration templates and are uploaded or copied and pasted into the dashboard and run from there.

This guide will describe the process involved in starting a pair of instances attached to their own network, which is in turn attached to to an internet-connected router.

HEAT templates are written in YAML which is extremely particular in regards to tabs and spaces. It is much more simple to ensure that you stick to spaces (and use them consistently) in all templates and use an editor with YAML syntax highlighting such as gedit.

Template Header

The first part of a HEAT template is the version (which is mandatory) of the style of template file and label (all labels are optional but recommended) and should look like this:

heat_template_version: 2013-05-23
description: A simple HEAT template

A single resource

The most basic task that a template can achieve is to start a single resource, in this case, an instance, with all parameters hard-coded into the script. The following script is complete and will start a virtual machine attached to a network called "Second Network":

heat_template_version: 2013-05-23
description: A simple HEAT template

resources:
  web_instance:
    properties:
      flavor: OS100
      image: b8671602-b2c1-4112-b032-84384d237dd2
      key_name: Cloud Key
      networks:
      - {network: Second Network}
    type: OS::Nova::Server

The resources section is where the instance that will be started is defined and the options used should fairly self explanatory. This uses the ID of an image which in this case is the Memset public Ubuntu 15.10 (Wily) image, available in all OpenStack accounts.

Adding a second server

A simple extension to this template is to create a second instance on the same network using the same parameters as the first (except for the name):

heat_template_version: 2013-05-23
description: A simple HEAT template

resources:
  web1_instance:
    properties:
      flavor: OS100
      image: b8671602-b2c1-4112-b032-84384d237dd2
      key_name: Cloud Key
      networks:
      - {network: Second Network}
    type: OS::Nova::Server


  web2_instance:
    properties:
      flavor: OS100
      image: b8671602-b2c1-4112-b032-84384d237dd2
      key_name: Cloud Key
      networks:
      - {network: Second Network}
    type: OS::Nova::Server

Defining Parameters

Now that the template is starting to become more complex, it is important to define parameters which will make it more manageable and more reusable in the future.

When attributes are configured as parameters the user that runs the template will be given the option to select the resource type from a dialogue with all other available options listed. So for example, if the SSH key is configured as a parameter when the template is run a dialogue will open that contains a dropdown of all available SSH keys, with the default being pre-selected.

A single parameter section for the SSH key looks like this:

parameters:
  key_name:
    type: string
    label: Key Name
    description: Name of key-pair to be used for compute instance
    default: Cloud Key

The lines mean:

  • type - This defines the format of the values provided, we will use text.
  • label - This is a short human-readable label for the parameter.
  • description - A longer human readable description of what is being defined.
  • default - This is the option that will be pre-filled, in this case, it is an existing SSH key.

Putting this all together give us the template:

heat_template_version: 2013-05-23
description: A simple HEAT template

parameters:
  key_name:
    type: string
    label: Key Name
    description: Name of key-pair to be used for compute instance
    default: Cloud Key

  image_id:
    type: string
    label: Image ID
    description: Image to be used for compute instance
    default: b8671602-b2c1-4112-b032-84384d237dd2

  instance_type:
    type: string
    label: Instance type
    description: Type of instance (flavour) to be used
    default: OS100


resources:
  web1_instance:
    type: OS::Nova::Server
    properties:
      flavor:   { get_param: instance_type }
      image:    { get_param: image_id }
      key_name: { get_param: key_name }
      networks:
      - {network: Second Network}

  web2_instance:
    type: OS::Nova::Server
    properties:
      flavor:   { get_param: instance_type }
      image:    { get_param: image_id }
      key_name: { get_param: key_name }
      networks:
      - {network: Second Network}

This template will now bring up several instances on an existing network. The next section will cover creating and using a new network.

Building a network

An OpenStack network is a collection of several resources which must be individually created. The first is the network itself:

resources:
  private_network:
    type: OS::Neutron::Net

This creates the network private_network. Next, it must be allocated an IP subnet:

resources:
  private_network:
    type: OS::Neutron::Net

  private_subnet:
    type: OS::Neutron::Subnet
    properties:
      network_id: { get_resource: private_network }
      cidr: 10.10.50.0/24

Note that the network_id line references the previously created network.

Now the router needs creating that the network will attach to:

resources:
  private_network:
    type: OS::Neutron::Net

  private_subnet:
    type: OS::Neutron::Subnet
    properties:
      network_id: { get_resource: private_network }
      cidr: 10.10.10.0/24

  router:
    type: OS::Neutron::Router
    properties:
      name: Internet
      external_gateway_info:
        network: ext-net

  router-interface:
    type: OS::Neutron::RouterInterface
    properties:
      router_id: { get_resource: router }
      subnet:    { get_resource: private_subnet }

Finally, the above network configuration needs adding to the template in the resources section. In addition, the instance needs to be updated so that they attach to the new network. The completed template is as follows:

heat_template_version: 2013-05-23
description: A simple HEAT template

parameters:
  key_name:
    type: string
    label: Key Name
    description: Name of key-pair to be used for compute instance
    default: Cloud Key

  image_id:
    type: string
    label: Image ID
    description: Image to be used for compute instance
    default: b8671602-b2c1-4112-b032-84384d237dd2

  instance_type:
    type: string
    label: Instance type
    description: Type of instance (flavour) to be used
    default: OS100


resources:
  private_network:
    type: OS::Neutron::Net

  private_subnet:
    type: OS::Neutron::Subnet
    properties:
      network_id: { get_resource: private_network }
      cidr: 10.10.10.0/24

  router:
    type: OS::Neutron::Router
    properties:
      name: Internet
      external_gateway_info:
        network: ext-net

  router-interface:
    type: OS::Neutron::RouterInterface
    properties:
      router_id: { get_resource: router }
      subnet:    { get_resource: private_subnet }

  web1_instance:
    type: OS::Nova::Server
    properties:
      flavor:   { get_param: instance_type }
      image:    { get_param: image_id }
      key_name: { get_param: key_name }
      networks:
      - network: { get_resource: private_network }

  web2_instance:
    type: OS::Nova::Server
    properties:
      flavor:   { get_param: instance_type }
      image:    { get_param: image_id }
      key_name: { get_param: key_name }
      networks:
      - network: { get_resource: private_network }

Running the template

Now the template is ready to run in the OpenStack dashboard. This is achieved in the Orchestration -> Stacks page. From there click the Launch Stack button. This will bring up the following dialogue where you need to:

  1. Select Direct Input as the Template Source.
  2. Copy/paste the template you have written into the box.

You will then be prompted to give the stack a name and to enter your password. The stack will then first be checked for errors and then run. All of the resources in the script will be created when the script is run.

Once the 'stack' has been created you will be able to review all of its components by clicking on its name under the Stack Name column.

Suspending the stack will suspend (but not remove) all of the resources that it created.

Deleting the stack will terminate all the resources that it created.

Last updated 13 June 2016, 10:54 GMT