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.