Skip to content

Instantly share code, notes, and snippets.

@s3u
Created December 31, 2014 02:17
Show Gist options
  • Save s3u/5104f77b2b55900f243c to your computer and use it in GitHub Desktop.
Save s3u/5104f77b2b55900f243c to your computer and use it in GitHub Desktop.
vol-agent
import sys
import subprocess
import requests
import os
# The purpose of this script is to find look for unmounted volumes, and mount them. If a volume is unitialized, it
# will initialize as ext4.
#
# The simplest way to run this is via cron. Use the following crontab entry
#
# */1 * * * * python /somepath/agent.py >> /var/log/vol-agent.log
#
# This script will act based on the following stimuli:
#
# 1. A volume has been attached to the VM, e.g. via
# nova volume-attach <VM-UUID> <Volume-UUID>
# 2. The VM's metadata has been updated to include the list of volumes that must be auto-mounted.
# nova meta <VM-UUID> set volumes="space delimited volume-UUIDs"
#
# This script will then mount the specified volumes under
#
# /mnt/slaves/<volume-UUID>
#
# Feel free to modify to the default conventions.
#
# To unmount a volume, follow the same type of stimuli
#
# 1. Remove the volume's UUID from the metadata. Simply remove the volume's UUID from the value of the
# `volumes` parameter in the `nova meta` command.
# 2. Detach the volume via `nova volume-detach <VM-UUID> <Volume-UUID>`
#
# Parses `lsblk` output to determine uninitialized volumes.
def parse_lsblk(out):
blkDict = []
for l in out:
d = {}
for t in l.split():
k, v = t.split('=', 1)
d[k] = v[1:-1]
blkDict.append(d)
return blkDict
# Run `lsblk` to find uninitialized volumes. If found one, initialize as ext4 file system
cmd = ['lsblk', '--bytes', '--pairs', '--output', 'KNAME,FSTYPE,UUID']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.communicate()
out = out[0].splitlines()
parsed = parse_lsblk(out)
for volume in parsed:
if volume['FSTYPE'] == '':
# Initialize the volume
print "Initializing %s" % volume['KNAME']
cmd = ['mkfs', '-t', 'ext4', '/dev/%s' % volume['KNAME']]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.communicate()
#
# Find the list of volumes that must be mounted.
r = requests.get('http://169.254.169.254/openstack/latest/meta_data.json')
if r.status_code != 200:
sys.exit(0)
meta = r.json()["meta"]
volumes = meta["volumes"] or ''
volumes = [] or volumes.split(',')
# Unmount removed
try:
os.makedirs('/mnt/slaves')
except:
pass
mounted = os.listdir('/mnt/slaves')
for m in mounted:
if m not in volumes:
print "Unmounting /mnt/slaves/%s" % m
cmd = ['umount', '/mnt/slaves/' + m]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.communicate()
for volume in (volume for volume in volumes if len(volume) > 0):
disk = '/dev/disk/by-id/virtio-' + volume[:20]
if not os.path.exists(disk):
sys.exit(0)
device = os.path.realpath('/dev/disk/by-id/' + os.readlink(disk))
try:
os.makedirs('/mnt/slaves/' + volume)
except:
pass
try:
print ("Mounting %s at /mnt/slaves/%s" % (device, volume))
cmd = ['mount', device, '/mnt/slaves/' + volume]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.communicate()
except:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment