One of the more interesting and helpful features of software config is the ability to
run deployments only during certain lifecycle events. This allows the template author
to run scripts and other configurations only during specific actions like DELETE or
UPDATE. In this example, we will use the the actions
property of
OS::Heat::SoftwareDeployment
to apply specific configurations only during the listed
stack lifecycle actions.
One of the trickier things about using servers with attached Cloud Block Storage volumes is that in order to detatch the volume from the server, the volume must be unmounted. Usually, this means having to manually unmount the volume before detatching and deleting the other resources. Using software config during specific stack actions allows us to easily automate this process.
You can find the full template for this example at this repository's templates directory.
The following introductory material should give you enough background to proceed with this tutorial.
- Application software configuration using Heat
- HOT guide - Software configuration
- Software Config example templates
Start by adding the top-level template sections:
heat_template_version: 2014-10-16
description: |
Mounting/unmounting volumes with software config
1. Create a server and a volume and attach the volume to the server
2. Once the volume is attached, configure and mount the volume
3. On delete, unmount the volume so that it can be detatched without
error
resources:
outputs:
Add the server that we'll manage Cloud Block Storage volumes on:
# server to attach a volume to
server:
type: OS::Nova::Server
properties:
name:
str_replace:
template: stack-volume-server
params:
stack: { get_param: "OS::stack_name" }
metadata:
rax-heat: { get_param: "OS::stack_id" }
# use a public image that already has all the agents set up for software
# deployments; could also use a custom image or bootstrap a "clean" one
image: f4bbbce2-50b0-4b07-bf09-96c175a45f4b # Ubuntu 14.04 with agents
flavor: 2 GB Performance
config_drive: true
software_config_transport: POLL_TEMP_URL
user_data_format: SOFTWARE_CONFIG
Here, we've used a public image that already has all of the required software config
agents installed, but you can use a custom image (such as the one you may have created
in the Bootstrapping Software Config tutorial), or bootstrap a "clean" image from
the catalog. Also note that we've set up config_drive
, software_config_transport
and user_data_format
as required.
Now, we'll add a volume and attach it to the server:
# volume to attach to the server
volume:
type: OS::Cinder::Volume
properties:
name:
str_replace:
template: stack-test-volume
params:
stack: { get_param: "OS::stack_name" }
metadata:
rax-heat: { get_param: "OS::stack_id" }
size: 100
description: Volume for testing management via software config
# attach the volume to the server
attach_vol:
type: OS::Cinder::VolumeAttachment
properties:
instance_uuid: { get_resource: server }
volume_id: { get_resource: volume }
mountpoint: "/dev/xvdb"
Notice the mountpoint
property; we'll use this in a bit in our configuration.
Next, we'll add the software configurations to run on the server to manage the volume:
# script to configure and mount the volume
config_volume:
type: OS::Heat::SoftwareConfig
properties:
group: script
config: |
#!/bin/bash
(echo n; echo p; echo 1; echo; echo; echo w;) | fdisk /dev/xvdb
mkfs -t ext4 /dev/xvdb1
mkdir -p /myvol
mount /dev/xvdb1 /myvol
echo "/dev/xvdb1 /myvol ext4 defaults,noatime,_netdev,nofail 0 2" >> /etc/fstab
# script to unmount the volume
unmount_vol:
type: OS::Heat::SoftwareConfig
properties:
group: script
config: |
#!/bin/bash
umount -l /myvol
The config_volume
configuration is designed to run after the server is created to
format and mount the volume. Notice that it uses the mountpoint
we defined in the
attach_vol
resource previously.
The unmount_vol
is designed to run before the volume is detached and deleted. This is
important because if we did not unmount the volume prior to detaching it, the stack would
fail to delete.
Now, lets add a deployment resources that will execute these configurations at the
appropriate times in the stack's lifecycle. First, we'll deploy config_volume
to
the server during the CREATE
phase:
# run the script to setup and mount the volume once the server is up and the volume
# is attached
prep_volume:
type: OS::Heat::SoftwareDeployment
depends_on: attach_vol # make sure this runs after attach
properties:
signal_transport: TEMP_URL_SIGNAL
config: { get_resource: config_volume }
server: { get_resource: server }
actions:
- CREATE # only run on stack-create
Notice that we explicitly depend on the attach_vol
resource so that we are sure
the volume is attached and available before we try to configure it. Also notice that we
use the actions
property to tell the orchestration engine to only consider this
resource during the CREATE
phase. This deployment will therefor be ignored during
stack UPDATE
, DELETE
or any other lifecycle operation that isn't CREATE
.
Lastly, we'll deploy the unmount_vol
configuration to the server during stack
DELETE
:
# before detaching the volume, run the script that unmounts it
pre_delete:
type: OS::Heat::SoftwareDeployment
depends_on: attach_vol # make sure this runs before detach
properties:
signal_transport: TEMP_URL_SIGNAL
config: { get_resource: unmount_vol }
server: { get_resource: server }
actions:
- DELETE # only run on stack-delete
Note that this resource also depends on the attach_vol
resource. This is because we
want to execute the configuration before the volume is detached. This works because
during DELETE
operations, Orchestration works through the dependency tree in reverse.
This allows us to unmount our volume prior to detaching it and deleting the other
resources.
You can find the full template for this example at this repository's templates directory.