initial commit
This commit is contained in:
commit
ca6a4d45d1
113 changed files with 10501 additions and 0 deletions
|
@ -0,0 +1,134 @@
|
|||
---
|
||||
date: 2015-05-05
|
||||
title: Identify and mounting Cinder Volumes in Openstack Heat
|
||||
category: devops
|
||||
---
|
||||
|
||||
I\'m back playing with Openstack again. The day job once again Openstack
|
||||
based, and as of last week my lab is all Openstack too. While
|
||||
[oVirt](http://ovirt.org) is awesome, I felt like a change.
|
||||
|
||||
Anyway, the meat of today\'s problem comes from the day job. I have some
|
||||
instances deployed via heat that have multiple Cinder volumes attached
|
||||
to them, these then need to be mounted in a certain way. The syntax for
|
||||
attaching a cinder volume to an instance is:
|
||||
|
||||
instance_vol_att:
|
||||
type: OS::Cinder::VolumeAttachment
|
||||
properties:
|
||||
instance_uuid: { get_resource: instance }
|
||||
volume_id: { get_resource: instance_vol_data }
|
||||
mountpoint: /dev/vdb
|
||||
|
||||
See at the end there is `mountpoint`? Awesome, my device will always
|
||||
appear as /dev/vdb!
|
||||
|
||||
No! Unfortunately, there is no link between Cinder/Nova and *udev*
|
||||
within the instance. As a result, udev will simply assign it a device
|
||||
name in the same way your workstation does to a USB key: it could be
|
||||
anything.
|
||||
|
||||
So what is a poor Openstack admin to do?
|
||||
|
||||
Each volume has a UUID, which in the example above. Lets start with a
|
||||
simple HOT template to create a single instance and volume:
|
||||
|
||||
heat_template_version: 2014-10-16
|
||||
description: A simple server to run Jenkins
|
||||
|
||||
parameters:
|
||||
imageid:
|
||||
type: string
|
||||
default: Centos-7-x64
|
||||
description: Image use to boot a server
|
||||
|
||||
resources:
|
||||
jenkins:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
image: { get_param: ImageID }
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- network: { get_param: NetID }
|
||||
jenkins_data:
|
||||
type: OS::Cinder::Volume
|
||||
properties:
|
||||
size: 50G
|
||||
jenkins_data_att:
|
||||
type: OS::Cinder::VolumeAttachment
|
||||
properties:
|
||||
instance_uuid: { get_resource: jenkins }
|
||||
volume_id: { get_resource: jenkins_data}
|
||||
|
||||
That will create everything we need. The rest we need to pass though
|
||||
from Nova to the instance somehow. While Nova does not talk to udev, it
|
||||
does pass the `volume_id` though, albeit with a caveat. the ID is
|
||||
truncated to **20** characters and is available as
|
||||
`/dev/disk/by-id/virtio-volid20chars`. We can now access this using the
|
||||
userdata property and `cloud-init`.
|
||||
|
||||
I actually create a small bash script then run it later, so now my
|
||||
*Server* resource will look like:
|
||||
|
||||
jenkins:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
image: { get_param: ImageID }
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- network: { get_param: NetID }
|
||||
user_data_format: RAW
|
||||
user_data:
|
||||
str_replace:
|
||||
template: |
|
||||
#cloud-config
|
||||
write_files:
|
||||
- content: |
|
||||
#!/bin/bash
|
||||
voldata_id="%voldata_id%"
|
||||
voldata_dev="/dev/disk/by-id/virtio-$(echo ${voldata_id} | cut -c -20)"
|
||||
mkfs.ext4 ${voldata_dev}
|
||||
mkdir -pv /var/lib/jenkins
|
||||
echo "${voldata_dev} /var/lib/jenkins ext4 defaults 1 2" >> /etc/fstab
|
||||
mount /var/lib/jenkins
|
||||
path: /tmp/format-disks
|
||||
permissions: '0700'
|
||||
runcmd:
|
||||
- /tmp/format-disks
|
||||
params:
|
||||
"%voldata_id%": { get_resource: jenkins_data }
|
||||
jenkins_data:
|
||||
type: OS::Cinder::Volume
|
||||
properties:
|
||||
size: 50
|
||||
jenkins_data_att:
|
||||
type: OS::Cinder::VolumeAttachment
|
||||
properties:
|
||||
instance_uuid: { get_resource: jenkins }
|
||||
volume_id: { get_resource: jenkins_data}
|
||||
|
||||
What is happenning here? I create 3 resources:
|
||||
|
||||
- a server
|
||||
- a volume
|
||||
- a volume attachment
|
||||
|
||||
Within the server there is a *cloud-init* script passed in via
|
||||
*user*data\_. This cloud-init script is created using a template which
|
||||
has a single parameter. This parameter is `%voldata_id%` - I put `%`
|
||||
symbols around all my variables in this context, it makes false matches
|
||||
pretty much impossible. The `get_resource` command collects the ID of
|
||||
the Cinder volume I created.
|
||||
|
||||
Now we move into the *cloud-init* script created which does 2 things:
|
||||
|
||||
- creates a bash script, including the variable for the ID
|
||||
- launches that scripts
|
||||
|
||||
The Bash script calculates what the device will be (`$voldata_dev`),
|
||||
formats it and mounts it at the mountpoint it creates. It also adds this
|
||||
into `/etc/fstab` for the future.
|
||||
|
||||
This can easily be used for multiple volumes. All one does is add an
|
||||
extra parameter to collect the extra resources, then extend the Bash
|
||||
script to do them too.
|
Loading…
Add table
Add a link
Reference in a new issue