OpenStack: Heat Python Tutorial

In this tutorial, we’ll focus on how to interact with OpenStack Heat using Python.  Before deep diving into Heat Python examples, I suggest being familiar with Heat itself and more specifically:

  • Templates
  • Basic operations: create/delete/update stack

Still here? let’s go 🙂

Set up Heat client

In order to work with Heat, we need first to create a heat client.

from heatclient import client as heat_client
from keystoneauth1 import loading
from keystoneauth1 import session

kwargs = {
'auth_url': ,
'username':,
'password': ,
'project_name': ,
'user_domain_name': ,
'project_domain_name': 
}

loader = loading.get_plugin_loader('password')
auth = loader.load_from_options(**kwargs)
sess = session.Session(auth=auth, verify=False)

client = heat_client.Client('1', session=sess, endpoint_type='public', service_type='orchestration')

Note: if for some reason you are using auth v2 and not v3, you can drop user_domain_name and project_domain_name.

You should be able to use your heat client now. Let’s test it.

List Stacks

for stack in client.stacks.list():
    print(stack)

Stack 
u'description':u'',
u'parent':None,
u'deletion_time':None,
u'stack_name':u'default',
u'stack_user_project_id':u'48babe632349f9b87ac3513',
u'stack_status_reason':u'Stack CREATE completed successfully',
u'creation_time':   u'2018-10-25T17:02:52   Z',
u'links': 
 
u'href':         u'https://my-server',
u'rel':u'self'
}
],
u'updated_time':None,
u'stack_owner':None,
u'stack_status':u'CREATE_COMPLETE',
u'id':u'b90d0e57-05a8-4700-b2f9-905497abe673',
u'tags':None
}>

The list method provides us with a generator that returns Stack objects. Each Stack object contains plenty of information. Information like the name of the stack, if it’s a nested stack you’ll get details on the parent stack, creation time and probably the most useful one – stack status which allows us to check if the stack is ready to use.

Create a Stack

In order to create a stack, we first need a template that will define how our stack would look like. I’m going to assume here that you read the template guide and you have a basic (or complex) template ready for use.

To load a template, heat developers have provided us with the get_template_content method

from heatclient.common import template_utils
import yaml

template_path = '/home/mario/my_template'

# Load the template
_files, template = template_utils.get_template_contents(template_path)

# Searlize it into a stream
s_template = yaml.safe_dump(template)

client.stacks.create(stack_name='my_stack', template = s_template)

Stack with parameters

In reality, there is a good chance your template includes several parameters that you have to pass when creating the stack. For example, take a look at this template

heat_template_version: 2013-05-23
description: My Awesome Stack

parameters:
  flavor:
    type: string
  image:
    type: string

In order for the stack creation to be completed successfully, we need to provide the parameters flavor and image. This will require a slight change in our code

parameters = {'flavor': 'm1.large', 'image': 'Fedora-30'}

client.stacks.create(stack_name='my_stack', template = s_template, parameters=parameters)

We created a dictionary with the required parameters and passed it to the stack create method. When more parameters added to your template, all you need to do is to extend the ‘parameters’ dictionary, without modifying the create call.

Inspect stack resources

Inspecting the stack as we previously did, might not be enough in certain scenarios. Imagine you want to use some resources as soon as they ready, regardless of overall stack readiness. In that case, you’ll want to check what is the status of a single resource. The following code will allow you to achieve that

stack = client.stacks.get("my_stack")
res = client.resources.get(stack.id, 'fip')
if res.resource_status == 'CREATE_COMPLETE':
    print("You may proceed :)")

So what did just happened? first, we need to obtain the ID of our stack. In order to do that we use the stacks get method by passing our stack’s name.

Now that we have the stack ID we can use it and the resource name we are interested in (‘fip’) to get the resource object.

Once we get the resource object, we can use ‘resource_status’ to check the if the stack creation has been completed and proceed accordingly.

Stack outputs

A better way to get quickly the output we interested in is the outputs section in Heat templates.

outputs:
server_ip:
  value: {get_attr: [floating_ip, floating_ip_address]}
server_ip2:
  value: {get_attr: [floating_ip2, floating_ip_address]}

In the above example, we are providing the user the information about two floating IPs of two different servers. We can then access this information with Python this way

print(my_stack.outputs)

[{u'output_value': u'10.2.224.22', u'output_key': u'server_ip2', u'description': u'No description given'}, {u'output_value': u'10.2.230.22', u'output_key': u'server_ip', u'description': u'No description given'}]

IP = stack.output[0]['output_value']
print(IP)

10.2.224.22

As you can see, each output represented by its own item in the ‘outputs’ list and is a better method (in my opinion at least) to access information quickly than inspecting the resources.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s