Tag Archives: cloud

What is Terraform and how to use it ?

Terraform it a tool to configure and provision cloud infrastructure, it provides similar functionality as heat. Major difference is, terrform is cloud agnostic, it can be use for openstack, amazon or other cloud providers, but heat functionality is limited only to openstack. In this article, I am going to show you the usage of terraform with openstack.

As more and more companies are moving towards hybrid cloud architectures hence tool like terraform provides great benefits.

Terraform configurations can be in terraformat or json. I have used json in this article.

Step 1 : Download the terraform according to your OS. I have downloaded terraform for linux 64 bit from official download page.

Step 2 : Unzip the downloaded zip file and copy the binary in /usr/bin so that it can be used as a command.

[root@allinone9 ~(keystone_admin)]# unzip terraform_0.7.4_linux_amd64.zip
Archive:  terraform_0.7.4_linux_amd64.zip
inflating: terraform

[root@allinone9 ~(keystone_admin)]# cp -p terraform /usr/bin/
[root@allinone9 ~(keystone_admin)]# terraform

Step 3 : Also, install the graphviz tool which we will be using later in this article.

[root@allinone9 ~(keystone_admin)]# yum install -y graphviz

Step 4 : To use terraform, we need to create four files in a directory, main logic lies in main.tf.json file. Basically main.tf.json and vars.tf.json are two mandatory files.

[root@allinone9 terrformexample1(keystone_admin)]# ll
total 32
-rw-r–r– 1 root root  419 Sep 29 08:16 main.tf.json
-rw-r–r– 1 root root  138 Sep 29 08:46 output.tf.json
-rw-r–r– 1 root root  233 Sep 29 08:11 provider.tf.json
-rw-r–r– 1 root root  177 Sep 29 08:12 vars.tf.json

Let’s check the content of these files.

a) In provider.tf.json file I am specifying the provider which I am going to use along with credentails of that provider. In this case, I am using openstack.

[root@allinone9 terrformexample1(keystone_admin)]# cat provider.tf.json
“provider”: {
“openstack”: {
“user_name”: “admin”,
“tenant_name”: “admin”,
“password”: “ed5432114db34e29”,
“auth_url”: “”

b) I have defined image and flavor as variables in separate file, to make the main logic more modular. Basically this acts like a heat environment file.

[root@allinone9 terrformexample1(keystone_admin)]# cat vars.tf.json
“variable”: {
“image”: {
“default”: “cirros”
“variable”: {
“flavor”: {
“default”: “m1.tiny”

c) main.tf.json file contains the main resource definition. I am using the various defined in vars.tf.json file in this file to spawn an instance. This file plays the same role as heat resource definition file.

[root@allinone9 terrformexample1(keystone_admin)]# cat main.tf.json
“resource”: {
“openstack_compute_instance_v2”: {
“tf-instance”: {
“name”: “tf-instance”,
“image_name”: “${var.image}”,
“flavor_name”: “${var.flavor}”,
“security_groups”: [“default”],
“network”: {
“uuid”: “1e149f28-66b3-4254-a88c-f1b42e7bc200”

Note : Security group should be in list format, despite of being a single value. This is hard coded.

d) Output to print when the operation is completed successfully. I am printing the instance IP.  In case of heat it’s display in resource definition file.

[root@allinone9 terrformexample1(keystone_admin)]# cat output.tf.json
“output”: {
“address”: {
“value”: “${openstack_compute_instance_v2.tf-instance.access_ip_v4}”

Step 5 : All the required files are in place, now issue the deployment command to create the instance.

[root@allinone9 terrformexample1(keystone_admin)]# terraform apply
openstack_compute_instance_v2.tf-instance: Creating…
access_ip_v4:               “” => “<computed>”
access_ip_v6:               “” => “<computed>”
flavor_id:                  “” => “<computed>”
flavor_name:                “” => “m1.tiny”
image_id:                   “” => “<computed>”
image_name:                 “” => “cirros”
name:                       “” => “tf-instance”
network.#:                  “” => “1”
network.0.access_network:   “” => “false”
network.0.fixed_ip_v4:      “” => “<computed>”
network.0.fixed_ip_v6:      “” => “<computed>”
network.0.floating_ip:      “” => “<computed>”
network.0.mac:              “” => “<computed>”
network.0.name:             “” => “<computed>”
network.0.port:             “” => “<computed>”
network.0.uuid:             “” => “1e149f28-66b3-4254-a88c-f1b42e7bc200”
region:                     “” => “RegionOne”
security_groups.#:          “” => “1”
security_groups.3814588639: “” => “default”
stop_before_destroy:        “” => “false”
openstack_compute_instance_v2.tf-instance: Still creating… (10s elapsed)
openstack_compute_instance_v2.tf-instance: Creation complete

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate


address =

Above output shows the instance information and IP address of instance because we have specified it to print the IP address.

Step 6 : Verify the instance is spawned successfully.

[root@allinone9 terrformexample1(keystone_admin)]# nova list | grep tf-instance
| 10f635b3-a7bb-40ef-a3e7-9c7fef0a712f | tf-instance   | ACTIVE  | –          | Running     | internal1= |

Step 7 : If later on we want to check the information about our deployment, we can use below commands.

[root@allinone9 terrformexample1(keystone_admin)]# terraform output
address =

[root@allinone9 terrformexample1(keystone_admin)]# terraform show
id = 10f635b3-a7bb-40ef-a3e7-9c7fef0a712f
access_ip_v4 =
access_ip_v6 =
flavor_id = eb45fb1b-1470-4315-81e5-ac5be702dbd2
flavor_name = m1.tiny
image_id = b74c6a4e-ccd4-4b47-9bca-8019d3ce44d9
image_name = cirros
metadata.% = 0
name = tf-instance
network.# = 1
network.0.access_network = false
network.0.fixed_ip_v4 =
network.0.fixed_ip_v6 =
network.0.floating_ip =
network.0.mac = fa:16:3e:ad:cb:6c
network.0.name = internal1
network.0.port =
network.0.uuid = 1e149f28-66b3-4254-a88c-f1b42e7bc200
region = RegionOne
security_groups.# = 1
security_groups.3814588639 = default
stop_before_destroy = false
volume.# = 0


address =

Step 8 : Deployment stack can be dumped into an image. I found this feature quite useful, as it’s easy to visualize.

[root@allinone9 terrformexample1(keystone_admin)]# terraform graph | dot -Tpng > graph.png

Step 9 : If you are missing the heat commands like “resource-list” don’t worry those are also available in terraforms.

[root@allinone9 terrformexample1(keystone_admin)]# terraform state list
[root@allinone9 terrformexample1(keystone_admin)]# terraform state show
id                         = 10f635b3-a7bb-40ef-a3e7-9c7fef0a712f
access_ip_v4               =
access_ip_v6               =
flavor_id                  = eb45fb1b-1470-4315-81e5-ac5be702dbd2
flavor_name                = m1.tiny
image_id                   = b74c6a4e-ccd4-4b47-9bca-8019d3ce44d9
image_name                 = cirros
metadata.%                 = 0
name                       = tf-instance
network.#                  = 1
network.0.access_network   = false
network.0.fixed_ip_v4      =
network.0.fixed_ip_v6      =
network.0.floating_ip      =
network.0.mac              = fa:16:3e:ad:cb:6c
network.0.name             = internal1
network.0.port             =
network.0.uuid             = 1e149f28-66b3-4254-a88c-f1b42e7bc200
region                     = RegionOne
security_groups.#          = 1
security_groups.3814588639 = default
stop_before_destroy        = false
volume.#                   = 0

Step 10 : Finally we can destroy the deployment.

[root@allinone9 terrformexample1(keystone_admin)]# terraform destroy
Do you really want to destroy?
Terraform will delete all your managed infrastructure.
There is no undo. Only ‘yes’ will be accepted to confirm.

Enter a value: yes

openstack_compute_instance_v2.tf-instance: Refreshing state… (ID: 10f635b3-a7bb-40ef-a3e7-9c7fef0a712f)
openstack_compute_instance_v2.tf-instance: Destroying…
openstack_compute_instance_v2.tf-instance: Still destroying… (10s elapsed)
openstack_compute_instance_v2.tf-instance: Destruction complete

Destroy complete! Resources: 1 destroyed.


In this article, I have just covered the basic working functionality of terrforms,  there are lot of other features available in this tool. You can refer the official hashicorp site to know more about terraform features.



How to modify the size of cloud image ?

Recently while working in cloud environment, I encountered a need of expanding an existing cloud image.  I was having rhel 7 qcow2 image with me hence the task was to resize that image to meet some requirements.

Thanks to ample amount of utilities provided by “libguestfs-tools” package which make my task possible.

Step 1 : Checking the size of rhel 7 qcow2 image.

# qemu-img info rhel-guest-image-7.0-20140930.0.x86_64.qcow2
image: rhel-guest-image-7.0-20140930.0.x86_64.qcow2
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 417M
cluster_size: 65536
Format specific information:
compat: 0.10

We can see that virtual disk size is 10GB.

Step 2 : Filesystems inside that image are taking 6GB only.

# virt-filesystems –long -h –all -a rhel-guest-image-7.0-20140930.0.x86_64.qcow2
Name       Type        VFS  Label  MBR  Size  Parent
/dev/sda1  filesystem  xfs  –      –    6.0G  –
/dev/sda1  partition   –    –      83   6.0G  /dev/sda
/dev/sda   device      –    –      –    10G   –

Step 3 : My requirement is to have the filesystem of 15 GB. I created one more image of 15GB.

# qemu-img create -f qcow2 rhel7-guest.qcow2 15G
Formatting ‘rhel7-guest.qcow2’, fmt=qcow2 size=16106127360 encryption=off cluster_size=65536 lazy_refcounts=off

Step 4 : Install the “libguestfs-xfs” package to expand the xfs filesystem.

# yum -y install libguestfs-xfs

Step 5 : Issued the below command to perform the expansion. Make sure that this operation ends with “no error”. Also as suggested at the end of below command try to launch the instance using new image before deleting the old image.

# virt-resize –expand /dev/sda1 rhel-guest-image-7.0-20140930.0.x86_64.qcow2 rhel7-guest.qcow2
Examining rhel-guest-image-7.0-20140930.0.x86_64.qcow2 …

Summary of changes:

/dev/sda1: This partition will be resized from 6.0G to 15.0G.  The
filesystem xfs on /dev/sda1 will be expanded using the ‘xfs_growfs’

Setting up initial partition table on rhel7-guest.qcow2 …
Copying /dev/sda1 …
100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
Expanding /dev/sda1 using the ‘xfs_growfs’ method …

Resize operation completed with no errors.  Before deleting the old disk,
carefully check that the resized disk boots and works correctly.

Step 6 : Let’s check the size information about new image.

# qemu-img info rhel7-guest.qcow2
image: rhel7-guest.qcow2
file format: qcow2
virtual size: 15G (16106127360 bytes)
disk size: 976M
cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false

Step 7 : I can see the increased size of filesystem in new image to 15 GB from 6GB of previous image.

# virt-filesystems –long -h –all -a rhel7-guest.qcow2
Name       Type        VFS  Label  MBR  Size  Parent
/dev/sda1  filesystem  xfs  –      –    15G   –
/dev/sda1  partition   –    –      83   15G   /dev/sda
/dev/sda   device      –    –      –    15G   –