Last active
August 29, 2015 14:07
-
-
Save a13m/715bf631ba3732aee7ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#-- | |
# Copyright 2014 Red Hat, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
#++ | |
# Purpose: This script grows the root filesystem and sets up LVM volumes | |
# for docker metadata and data. | |
# Author: Andy Grimm <agrimm@redhat.com> | |
set -e | |
# Read the config. Currently supported options: | |
# DEVS: A quoted, space-separated list of devices to be used. This currently | |
# expects the devices to be unpartitioned drives. If "VG" is not | |
# specified, then use of the root disk's extra space is implied. | |
# | |
# VG: The volume group to use for docker storage. Defaults to the volume | |
# group where the root filesystem resides. If VG is specified and the | |
# volume group does not exist, it will be created (which requires that | |
# "DEVS" be nonempty, since we don't currently support putting a second | |
# partition on the root disk). | |
# | |
# The options below should be specified as values acceptable to 'lvextend -L': | |
# | |
# ROOT_SIZE: The size to which the root filesystem should be grown. | |
# | |
# DATA_SIZE: The desired size for the docker data LV. Defaults to using all | |
# free space in the VG after the root LV and docker metadata LV | |
# have been allocated/grown. | |
# | |
# Other possibilities: | |
# * Support lvm raid setups for docker data? This would not be very difficult | |
# if given multiple PVs and another variable; options could be just a simple | |
# "mirror" or "stripe", or something more detailed. | |
source /etc/sysconfig/docker-storage-setup | |
# Read mounts | |
ROOT_DEV=$( awk '$2 ~ /^\/$/ && $1 !~ /rootfs/ { print $1 }' /proc/mounts ) | |
ROOT_VG=$( lvs --noheadings -o vg_name $ROOT_DEV ) | |
ROOT_PVS=$( pvs --noheadings -o pv_name,vg_name | awk "\$2 ~ /^$ROOT_VG\$/ { print \$1 }" ) | |
VG_EXISTS= | |
if [ -z "$VG" ]; then | |
VG=$ROOT_VG | |
VG_EXISTS=1 | |
else | |
for vg_name in $( vgs --noheadings -o vg_name ); do | |
if [ "$vg_name" == "$VG" ]; then | |
VG_EXISTS=1 | |
break | |
fi | |
done | |
fi | |
if [ -z "$DEVS" ] && [ -z "$VG_EXISTS" ]; then | |
echo "Specified volume group $VG does not exists, and no devices were specified" >&2 | |
exit 1 | |
fi | |
PVS= | |
GROWPART= | |
if [ -n "$DEVS" ] ; then | |
for dev in $DEVS; do | |
if expr match $dev ".*[0-9]"; then | |
echo "Partition specification unsupported at this time." >&2 | |
exit 1 | |
fi | |
# Use a single partition of a whole device | |
# TODO: | |
# * Consider gpt, or unpartitioned volumes | |
# * Error handling when partition(s) already exist | |
# * Deal with loop/nbd device names. See growpart code | |
PARTS=$( awk "\$4 ~ /"$( basename $dev )"[0-9]/ { print \$4 }" /proc/partitions ) | |
if [ -n "$PARTS" ]; then | |
echo "$dev has partitions: $PARTS" | |
exit 1 | |
fi | |
size=$(( $( awk "\$4 ~ /"$( basename $dev )"/ { print \$3 }" /proc/partitions ) * 2 - 2048 )) | |
cat <<EOF | sfdisk $dev | |
unit: sectors | |
${dev}1 : start= 2048, size= ${size}, Id=8e | |
EOF | |
pvcreate ${dev}1 | |
PVS="$PVS ${dev}1" | |
done | |
if [ -z "$VG_EXISTS" ]; then | |
vgcreate $VG $PVS | |
else | |
# TODO: | |
# * Error handling when PV is already part of a VG | |
vgextend $VG $PVS | |
fi | |
GROWPART=1 | |
elif [ "$ROOT_VG" == "$VG" ]; then | |
GROWPART=1 | |
fi | |
# Note that growpart is only variable here because we may someday support | |
# using separate partitions on the same disk. Today we fail early in that | |
# case. Also note that the way we are doing this, it should support LVM | |
# RAID for the root device. In the mirrored or striped case, we are growing | |
# partitions on all disks, so as long as they match, growing the LV should | |
# also work. | |
if [ -n "$GROWPART" ]; then | |
for pv in $ROOT_PVS; do | |
# Split device & partition. Ick. | |
echo growpart $( echo $pv | sed -r 's/([^0-9]*)([0-9]+)/\1 \2/' ) | |
echo pvresize $pv | |
done | |
fi | |
# NB: We are growing root here first, because when root and docker share a | |
# disk, we'll default to giving docker "everything else." This will be a | |
# problem if someone tries to assign root a value like"100%FREE". | |
if [ -n "$ROOT_SIZE" ]; then | |
# TODO: Error checking if specified size is <= current size | |
lvextend -L $ROOT_SIZE $ROOT_DEV || true | |
fi | |
# Reserve 0.1% of the free space in the VG for docker metadata. | |
# Calculating the based on actual data size might be better, but is | |
# more difficult do to the range of possible inputs. | |
VG_FREE_EXTS=$( vgs --noheadings --nosuffix --units s -o vg_free $VG ) | |
META_SIZE=$(( $VG_FREE_EXTS / 1000 + 1 )) | |
lvcreate -l ${META_SIZE}S -n docker-meta $VG | |
if [ -n "$DATA_SIZE" ]; then | |
# TODO: Error handling when DATA_SIZE > available space. | |
lvcreate -L $DATA_SIZE -n docker-data $VG | |
else | |
lvcreate -l "100%FREE" -n docker-data $VG | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment