Showing posts with label Template. Show all posts
Showing posts with label Template. Show all posts

Thursday, January 25, 2018

Ansible and Jinja2 template rendering


In this example an ansible playbook has some variables defined. These variables are then rendered by Jinja. 

The jinja template file here is jinjafile.j2  that gets saved after the rendering to the text file /tmp/ansible.all

The Jinja2 template file here looks clumsy. but please note that the multiline comment in Jinja2 is as {# .... #}. These are used in order as here in this template to inline explain the Jinja syntax. 

Once the playbook is in place and the jinja template file with the name of  jinjafile.j2 with the contents as in the mention, you can run the playbook and then see the contents of the rendered file /tnp/ansible.all

The Ansible playbook looks like 


---
- name: JinjAs
  hosts: localhost

  vars:

    foo: { "bar": 200, "abc": 1000, "sujit": 20000 }
    list1: [ 1, 2, 3 ]
    list2: [ 3, 4, 5 ]
    list3: { "x": "a", "y": "b" }

    production:
      - { name: "server1", ip: "1.1.1.1" }
      - { name: "server2", ip: "2.2.2.2" }

  tasks:
    - name: jinja render save to a file
      template: src=jinjafile.j2 dest=/tmp/ansible.all force=true


Please note that the actual JINJA syntax is highlighted in Blue and the remaining are the explanations of the syntax exampe.

The corresponding Jinja2 template file looks like

{#
## Select a random output from the list
## for selection of a random value from the list ["a", "b", "c"]
## the jinja syntax for the same is
##{{[ "a", "b", "c" ] | random }}
##
## The result is "b"
##

{{[ "a", "b", "c" ] | random }}

{#
## print the entire list here list1 is a list variable as list1 = [ 1, 2, 3 ]
## ## the jinja syntax for the same is
##
##{{ list1 }}
##
## The result is [1, 2, 3]
##
#}
{{ list1 }}


{#
## print each of the elements in a simple list
## here the list given is as list1 = [ 1, 2, 3 ]
## ## the jinja syntax for the same is
##
#}

{#
##{% for item in list1 %}
##{{ item }}
##{% endfor %}
##
## The result is
1
2
3
##
#}

{% for item in list1 %}
{{ item }}
{% endfor %}

{#
## printing of each of the element of a simple list variable where list1 is a variable like list1 = [ 1, 2, 3 ]
## This will union the 2 lists
## to union 2 lists where list1 = [ 1, 2, 3] and list2 = [ 3, 4, 5 ]
## the jinja syntax for the same is
##
##
##{{ list1 | union(list2) }}
## The result is [1, 2, 3, 4, 5]
##
#}

{{ list1 | union(list2) }}



{#
## This will show the length of the list
## This shows the length of the list list1 where list1 = [ 1, 2, 3 ]
## the jinja syntax for the same is
##
##
##{{ list1 | length }}
## The result is 3
##
#}
{{ list1 | length }}

{#
## This is to extract the elements at the list indexes of 0 and 1 from the list list11 where list1 = [ 1, 2, 3 ]
## extraction of the list index elements at the index of 0 and 1 from list list1 = [ 1, 2, 3 ]
## the jinja syntax for the same is
##
##
##{{ [0,2]  | map('extract',list1)| list }}
## The result is [1, 3]
##
#}
{{ [0,2]  | map('extract',list1)| list }}

{#
## This is to extract the values of the keys 'x' and 'y' from the dictionary { "x": 22 , "y" 44 }
## the jinja syntax for the same is
##
##{{ ['x', 'y'] | map('extract', { 'x': 22, 'y': 44 }) | list }}
##
## The result is [22, 44]
##
#}
{{ ['x', 'y'] | map('extract', { 'x': 22, 'y': 44 }) | list }}

{#
## This is again an example to know the number of elements but this time the object is a dict where
## the dict foo is as foo: { "bar": 200, "abc": 1000, "sujit": 20000 }
##
## ## the jinja syntax for the same is
##
##The lengh of the variable or the number of elements in the variable foo is
##{{ foo | length }}
##
##
## The result is 3
##
#}
{{ foo | length }}

{#
## for the dict variable foo where foo is foo: { "bar": 200, "abc": 1000, "sujit": 20000 }
## this prints each of the key and the value pairs iterating over all the elements of the dict
## notice the use of 'iteritems' here
##
## ## the jinja syntax for the same is
##
##
##
##{% for key, value  in foo.iteritems() %}
##{{ key }} : "{{ value }}"
##{% endfor %}
##
##
## The result is
##
sujit : "20000"
abc : "1000"
bar : "200"
#}
{% for key, value  in foo.iteritems() %}
{{ key }} : "{{ value }}"
{% endfor %}

{#
## for the variable foo which is a dict as foo: { "bar": 200, "abc": 1000, "sujit": 20000 }
## with the multiple elements
## this prints the value of the element having key as "bar"
## ## the jinja syntax for the same is
##
##
##{{ foo.bar }}
##
## The result is 200
##
##
##
#}
{{ foo.bar }}

{#
## this is the same as the example previous
##
##
## the jinja syntax for the same is
##
##{{ foo['bar'] }}
##
##
## The result is 200
##
#}
{{ foo['bar'] }}


{#
## This is for the example of evaluating the value of foo.bar is equal to 100 or not where foo is a dict as foo: { "bar": 200, "abc": 1000, "sujit": 20000 }
## the jinja syntax for the same is
##
##{% if foo.bar == 100 %}
##value is 100
##{% else %}
##value is not 100
##{% endif %}
##
## The result is "value is not 100"
##
#}
{% if foo.bar == 100 %}
value is 100
{% else %}
value is not 100
{% endif %}

{#
## See the length of or the list variable production where each of the entity in the variable production is a dict in itself
## Here the production variable looks like below.
## the same "production" variable has also been used in the subsequent examples
##    production:
##      - { name: "server1", ip: "1.1.1.1" }
##      - { name: "server2", ip: "2.2.2.2" }
## the jinja syntax for the same is
##
##
##{{ production | length }}
##
##
## The result is 2
##
#}
{{ production | length }}

{#
## for the production variable above that is a list of dictionaries, the list shows the items of the list
## The result will be a list of dictionaries
##
##
## the jinja syntax for the same is
##
##
##{{ production | list }}
##
## The result is [{u'ip': u'1.1.1.1', u'name': u'server1'}, {u'ip': u'2.2.2.2', u'name': u'server2'}]
##
#}
{{ production | list }}

{#
## also the way to iterate through the elements of the variable production as production is a list of dicts
##
## the jinja syntax for the same is
##
##{% for item in production %}
##      {{ item }}
##{% endfor %}
##
## The result is 
        {u'ip': u'1.1.1.1', u'name': u'server1'}
        {u'ip': u'2.2.2.2', u'name': u'server2'}

##
#}
{% for item in production %}
        {{ item }}
{% endfor %}

{#
## for the list of dictionaries values variable production this iterates to each dict element
## then this iterates through each of the elements in the dict and prints the key value pairs.
##
##
## the jinja syntax for the same is
##
##{% for item in production|list %}
##{% for key, value in item.iteritems() %}
##{{key}}: "{{value}}"
##{% endfor %}
##{% endfor %}
##
## The result is
ip: "1.1.1.1"
name: "server1"
ip: "2.2.2.2"
name: "server2"

##
#}

{% for item in production|list %}
{% for key, value in item.iteritems() %}
{{key}}: "{{value}}"
{% endfor %}
{% endfor %}

Monday, December 12, 2016

Deploying an very basic instance on OpenStack Mitaka using a simple heat orchestration template and associate a Floating IP to the simple stack

Deploying an very basic instance on OpenStack using a simple heat template


The below is a simple sample template which we will use
=========================================================
heat_template_version: 2013-05-23

description: Simple template to deploy a single compute instance

parameters:
  image:
    type: string
    label: Image name or ID
    description: Image to be used for compute instance
    default: cirros-0.3.3-x86_64
  flavor:
    type: string
    label: Flavor
    description: Type of instance (flavor) to be used
    default: m1.small
  key:
    type: string
    label: Key name
    description: Name of key-pair to be used for compute instance
    default: my_key
  private_network:
    type: string
    label: Private network name or ID
    description: Network to attach instance to.
    default: private-net

resources:
  my_instance:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }
      key_name: { get_param: key }
      networks:
        - network: { get_param: private_network }
      user_data: |
        #!/bin/sh
        echo "Hello, World!"
      user_data_format: RAW

outputs:
  instance_name:
    description: Name of the instance
    value: { get_attr: [my_instance, name] }
  instance_ip:
    description: IP address of the instance
    value: { get_attr: [my_instance, first_address] }



The above file has to be copied in the form of an YAML file


We will Need to specify the above in the heat template YAML file: network, instance, flavor, security keys also the instance name

Lets get the information on the resources from the existing OpenStack Setup


Source the required credentials


[root@controller ~]# . keystonerc_admin

See the available flavors
==========================
[root@controller ~(keystone_admin)]# openstack flavor list
+----+-----------+-------+------+-----------+-------+-----------+
| ID | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |
+----+-----------+-------+------+-----------+-------+-----------+
| 1  | m1.tiny   |   512 |    1 |         0 |     1 | True      |
| 2  | m1.small  |  2048 |   20 |         0 |     1 | True      |
| 3  | m1.medium |  4096 |   40 |         0 |     2 | True      |
| 4  | m1.large  |  8192 |   80 |         0 |     4 | True      |
| 5  | m1.xlarge | 16384 |  160 |         0 |     8 | True      |
+----+-----------+-------+------+-----------+-------+-----------+


See the available images
========================
[root@controller ~(keystone_admin)]# openstack image list
+--------------------------------------+--------+--------+
| ID                                   | Name   | Status |
+--------------------------------------+--------+--------+
| 44bb15d9-a970-40c4-8b77-a7e71b170659 | Cirros | active |
+--------------------------------------+--------+--------+
[root@controller ~(keystone_admin)]#


See the available networks in neutron
=====================================
[root@controller ~(keystone_admin)]# neutron net-list
+--------------------------------------+-----------+-------------------------------------------------------+
| id                                   | name      | subnets                                               |
+--------------------------------------+-----------+-------------------------------------------------------+
| 60ca0e7b-3c40-482c-92d1-3b4da4126e9d | testnet1  | 8fd08288-a83b-44ee-ac04-f8b88fc69628 172.16.15.0/24   |
| 8649a5a8-c137-444d-950d-e0c0569e3ee4 | internal1 | bd5b5a96-eaf5-45a8-93e5-6be837e61414 172.16.16.0/24   |
| 001ac29b-1f5f-4498-a44b-de0f809d2322 | external  | cf1da694-4a75-4768-b758-859dc750a02d 192.168.205.0/24 |
+--------------------------------------+-----------+-------------------------------------------------------+


See the available subnets in the neutron
========================================
[root@controller ~(keystone_admin)]# neutron subnet-list
+--------------------------------------+--------------+------------------+--------------------------------------------------------+
| id                                   | name         | cidr             | allocation_pools                                       |
+--------------------------------------+--------------+------------------+--------------------------------------------------------+
| 8fd08288-a83b-44ee-ac04-f8b88fc69628 | testsub      | 172.16.15.0/24   | {"start": "172.16.15.2", "end": "172.16.15.254"}       |
| bd5b5a96-eaf5-45a8-93e5-6be837e61414 | internal1sub | 172.16.16.0/24   | {"start": "172.16.16.2", "end": "172.16.16.254"}       |
| cf1da694-4a75-4768-b758-859dc750a02d | extsub       | 192.168.205.0/24 | {"start": "192.168.205.101", "end": "192.168.205.254"} |
+--------------------------------------+--------------+------------------+--------------------------------------------------------+

See the available keypairs for the project
==========================================
[root@controller ~(keystone_admin)]# openstack keypair list
+------+-------------------------------------------------+
| Name | Fingerprint                                     |
+------+-------------------------------------------------+
| key1 | 2f:40:44:36:1d:b9:ab:cd:b6:57:24:c7:70:dc:8c:f7 |
+------+-------------------------------------------------+
[root@controller ~(keystone_admin)]#


Lets edit the YAML file which will look like below now

heat_template_version: 2013-05-23

description: Simple template to deploy a single compute instance

parameters:
  image:
    type: string
    label: Image name or ID
    description: Image to be used for compute instance
    default: Cirros
  flavor:
    type: string
    label: Flavor
    description: Type of instance (flavor) to be used
    default: m1.tiny
  key:
    type: string
    label: Key name
    description: Name of key-pair to be used for compute instance
    default: key1
  private_network:
    type: string
    label: Private network name or ID
    description: Network to attach instance to.
    default: internal1

resources:
  my_instance:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }
      key_name: { get_param: key }
      networks:
        - network: { get_param: private_network }
      user_data: |
        #!/bin/sh
        echo "Hello, World!"
      user_data_format: RAW

outputs:
  instance_name:
    description: Name of the instance
    value: { get_attr: [my_instance, name] }
  instance_ip:
    description: IP address of the instance
    value: { get_attr: [my_instance, first_address] }




Lets copy this YAML file in the OpenStack server as the file heatstack1.yaml


Create the stack syntax:

heat stack-create <Name of the Stack> -f <file containing YAML information of the stack>

heat stack-create stack1 -f heatstack1.yaml


Create the stack using the YAML file
====================================

[root@controller ~(keystone_admin)]# heat stack-create stack1 -f heatstack1.yaml
+--------------------------------------+------------+--------------------+---------------------+--------------+
| id                                   | stack_name | stack_status       | creation_time       | updated_time |
+--------------------------------------+------------+--------------------+---------------------+--------------+
| 5ab8fe95-7ea3-4530-86de-facae9f52c71 | stack1     | CREATE_IN_PROGRESS | 2016-12-07T06:31:07 | None         |
+--------------------------------------+------------+--------------------+---------------------+--------------+
[root@controller ~(keystone_admin)]#


See the list of the stacks
==========================
[root@controller ~(keystone_admin)]# heat stack-list
+--------------------------------------+------------+-----------------+---------------------+--------------+
| id                                   | stack_name | stack_status    | creation_time       | updated_time |
+--------------------------------------+------------+-----------------+---------------------+--------------+
| 5ab8fe95-7ea3-4530-86de-facae9f52c71 | stack1     | CREATE_COMPLETE | 2016-12-07T06:31:07 | None         |
+--------------------------------------+------------+-----------------+---------------------+--------------+
[root@controller ~(keystone_admin)]#
[root@controller ~(keystone_admin)]#


See more information on the Stack which is created
===================================================
[root@controller ~(keystone_admin)]# heat stack-show stack1
+-----------------------+----------------------------------------------------------------------------------------------------------------------------------+
| Property              | Value                                                                                                                            |
+-----------------------+----------------------------------------------------------------------------------------------------------------------------------+
| capabilities          | []                                                                                                                               |
| creation_time         | 2016-12-07T06:31:07                                                                                                              |
| description           | Simple template to deploy a single compute instance                                                                              |
| disable_rollback      | True                                                                                                                             |
| id                    | 5ab8fe95-7ea3-4530-86de-facae9f52c71                                                                                             |
| links                 | http://controller.example.com:8004/v1/f84cfac47c10472fb36c56dc149d3caa/stacks/stack1/5ab8fe95-7ea3-4530-86de-facae9f52c71 (self) |
| notification_topics   | []                                                                                                                               |
| outputs               | [                                                                                                                                |
|                       |   {                                                                                                                              |
|                       |     "output_value": "stack1-my_instance-rrmsgn57cvxy",                                                                           |
|                       |     "output_key": "instance_name",                                                                                               |
|                       |     "description": "Name of the instance"                                                                                        |
|                       |   },                                                                                                                             |
|                       |   {                                                                                                                              |
|                       |     "output_value": "172.16.16.5",                                                                                               |
|                       |     "output_key": "instance_ip",                                                                                                 |
|                       |     "description": "IP address of the instance"                                                                                  |
|                       |   }                                                                                                                              |
|                       | ]                                                                                                                                |
| parameters            | {                                                                                                                                |
|                       |   "OS::project_id": "f84cfac47c10472fb36c56dc149d3caa",                                                                          |
|                       |   "OS::stack_id": "5ab8fe95-7ea3-4530-86de-facae9f52c71",                                                                        |
|                       |   "OS::stack_name": "stack1",                                                                                                    |
|                       |   "image": "Cirros",                                                                                                             |
|                       |   "key": "key1",                                                                                                                 |
|                       |   "private_network": "internal1",                                                                                                |
|                       |   "flavor": "m1.tiny"                                                                                                            |
|                       | }                                                                                                                                |
| parent                | None                                                                                                                             |
| stack_name            | stack1                                                                                                                           |
| stack_owner           | None                                                                                                                             |
| stack_status          | CREATE_COMPLETE                                                                                                                  |
| stack_status_reason   | Stack CREATE completed successfully                                                                                              |
| stack_user_project_id | f7e5c9e4b80f4f1faf411c95880c1309                                                                                                 |
| tags                  | null                                                                                                                             |
| template_description  | Simple template to deploy a single compute instance                                                                              |
| timeout_mins          | None                                                                                                                             |
| updated_time          | None                                                                                                                             |
+-----------------------+----------------------------------------------------------------------------------------------------------------------------------+
[root@controller ~(keystone_admin)]#


Association of the floating IP to the instance
================================================
Asscoiate a floating IP to the instance. Create a floating IP if there are no free floating IPs available.

Get the information on all the networks, here the external is the external network in which the floating IP will get created.

[root@controller ~(keystone_admin)]# neutron net-list
+--------------------------------------+-----------+-------------------------------------------------------+
| id                                   | name      | subnets                                               |
+--------------------------------------+-----------+-------------------------------------------------------+
| 60ca0e7b-3c40-482c-92d1-3b4da4126e9d | testnet1  | 8fd08288-a83b-44ee-ac04-f8b88fc69628 172.16.15.0/24   |
| 8649a5a8-c137-444d-950d-e0c0569e3ee4 | internal1 | bd5b5a96-eaf5-45a8-93e5-6be837e61414 172.16.16.0/24   |
| 001ac29b-1f5f-4498-a44b-de0f809d2322 | external  | cf1da694-4a75-4768-b758-859dc750a02d 192.168.205.0/24 |
+--------------------------------------+-----------+-------------------------------------------------------+
[root@controller ~(keystone_admin)]# neutron floatingip-create externla^C
[root@controller ~(keystone_admin)]#


Create a floating IP in the external network
=============================================

[root@controller ~(keystone_admin)]# neutron floatingip-create external
Created a new floatingip:
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| description         |                                      |
| fixed_ip_address    |                                      |
| floating_ip_address | 192.168.205.105                      |
| floating_network_id | 001ac29b-1f5f-4498-a44b-de0f809d2322 |
| id                  | ab40dcbd-1082-424a-b0fb-135b8756bc91 |
| port_id             |                                      |
| router_id           |                                      |
| status              | DOWN                                 |
| tenant_id           | f84cfac47c10472fb36c56dc149d3caa     |
+---------------------+--------------------------------------+
[root@controller ~(keystone_admin)]#


Ensure the floating IP is listed and that the UUID of floating IP appears as free floating IP
===============================================================

[root@controller ~(keystone_admin)]# neutron floatingip-list
+--------------------------------------+------------------+---------------------+--------------------------------------+
| id                                   | fixed_ip_address | floating_ip_address | port_id                              |
+--------------------------------------+------------------+---------------------+--------------------------------------+
| 816e8bf9-7dec-4011-9333-f761b8b95c15 | 172.16.15.3      | 192.168.205.104     | 69d9cde5-e06d-4ecf-9f87-0f91cb06a653 |
| ab40dcbd-1082-424a-b0fb-135b8756bc91 |                  | 192.168.205.105     |                                      |
| c1e1d2a7-7f5c-4b51-938e-eb064d5d1939 | 172.16.16.3      | 192.168.205.103     | 315b610f-54e1-404c-bac3-048feb37bc23 |
+--------------------------------------+------------------+---------------------+--------------------------------------+


See information of the new instance get the Private network IP of the same.
===============================================================

[root@controller ~(keystone_admin)]# nova list
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+
| ID                                   | Name                            | Status | Task State | Power State | Networks                               |
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+
| a2c265bb-242c-40ae-ae9c-98849e459bf7 | instance1                       | ACTIVE | -          | Running     | internal1=172.16.16.3, 192.168.205.103 |
| 5d767783-933e-423d-848f-37e816fa05b3 | stack1-my_instance-rrmsgn57cvxy | ACTIVE | -          | Running     | internal1=172.16.16.5                  |
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+

Find the neutron port for the instance this information is needed to associate the floating IP to the port of the instance
===============================================================
[root@controller ~(keystone_admin)]# neutron port-list | grep -i 172.16.16.5
| 42304108-f397-4de7-8936-5f011e4be5f3 |      | fa:16:3e:ff:52:0a | {"subnet_id": "bd5b5a96-eaf5-45a8-93e5-6be837e61414", "ip_address": "172.16.16.5"}     |
[root@controller ~(keystone_admin)]#
[root@controller ~(keystone_admin)]#


Associate the floating IP
=================
[root@controller ~(keystone_admin)]# neutron floatingip-associate ab40dcbd-1082-424a-b0fb-135b8756bc91 42304108-f397-4de7-8936-5f011e4be5f3
Associated floating IP ab40dcbd-1082-424a-b0fb-135b8756bc91
[root@controller ~(keystone_admin)]#

Ensure the floating IP is seen to be associated to the instance as in the nova list
========================================================================

[root@controller ~(keystone_admin)]# nova list
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+
| ID                                   | Name                            | Status | Task State | Power State | Networks                               |
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+
| a2c265bb-242c-40ae-ae9c-98849e459bf7 | instance1                       | ACTIVE | -          | Running     | internal1=172.16.16.3, 192.168.205.103 |
| 5d767783-933e-423d-848f-37e816fa05b3 | stack1-my_instance-rrmsgn57cvxy | ACTIVE | -          | Running     | internal1=172.16.16.5, 192.168.205.105 |
+--------------------------------------+---------------------------------+--------+------------+-------------+----------------------------------------+
[root@controller ~(keystone_admin)]#


you can now use the keys and SSH to the instance.

Please note that the security group for the instance has to have the ingress SSH allowed for a successful SSH to the instance