Create a plugin for expand_root to replace the internal common task.

Switch GCE to use this plugin.
This commit is contained in:
Zach Marano 2017-01-24 16:48:46 -08:00
parent 29b61ca05a
commit 74a58c6829
10 changed files with 158 additions and 37 deletions

View file

@ -0,0 +1,11 @@
Expand Root
-----------
This plugin adds support to expand the root partition and filesystem dynamically on boot. It adds a shell script to call growpart and the proper filesystem expansion tool for a given device, partition, and filesystem. The growpart script is part of the cloud-guest-utils package in stretch and jessie-backports. The version of this script in jessie is broken in several ways and so this plugin installs the version from jessie-backports which works correctly. This plugin should not be used in conjunction with common.tasks.initd.AddExpandRoot and common.tasks.initd.AdjustExpandRootScript. It is meant to replace the existing internal common version of expand-root.
Settings
--------
- ``filesystem_type``: The type of filesystem to grow, one of ext2, ext3, ext4, of xfs.
- ``root_device``: The root device we are growing, /dev/sda as an example.
- ``root_partition``: The root partition ID we are growing, 1 (which becomes /dev/sda1). This is specified so you could grow a different partition on the root_device if you have a multi partition setup and because growpart takes the partition number as a separate argument.

View file

@ -0,0 +1,11 @@
import tasks
from bootstrapvz.common.tools import rel_path
def validate_manifest(data, validator, error):
validator(data, rel_path(__file__, 'manifest-schema.yml'))
def resolve_tasks(taskset, manifest):
taskset.add(tasks.InstallGrowpart)
taskset.add(tasks.InstallExpandRootScripts)

View file

@ -0,0 +1,11 @@
[Unit]
Description=Expand the root partition and filesystem on boot
After=local-fs.target
Wants=local-fs.target
[Service]
ExecStart=/usr/bin/expand-root.sh DEVICE PARTITION FILESYSTEM
Type=oneshot
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,33 @@
#!/bin/bash
# Expands a partition and filesystem using growpart and an appropriate
# filesystem tool for live filesystem expansion. Takes three arguments:
# DEVICE, such as "/dev/sda"
# PARTITION, such as "1"
# FILESYSTEM, such as "ext4"
DEVICE="${1}"
PARTITION="${2}"
FILESYSTEM="${3}"
if [[ -z "${DEVICE}" || -z "${PARTITION}" || -z "${FILESYSTEM}" ]]; then
echo "Requires: $0 DEVICE PARTITION FILESYSTEM"
exit 1
fi
# Grow partition using growpart
if [[ -x /usr/bin/growpart ]]; then
echo "Growing partition ${DEVICE}${PARTITION}"
/usr/bin/growpart "${DEVICE}" "${PARTITION}"
else
echo "/usr/bin/growpart was not found"
exit 1
fi
echo "Resizing ${FILESYSTEM} filesystem on ${DEVICE}${PARTITION}"
case "${FILESYSTEM}" in
xfs) xfs_growfs / ;;
ext2) resize2fs "${DEVICE}${PARTITION}" ;;
ext3) resize2fs "${DEVICE}${PARTITION}" ;;
ext4) resize2fs "${DEVICE}${PARTITION}" ;;
*) echo "Unsupported filesystem, unable to expand size." ;;
esac

View file

@ -0,0 +1,24 @@
---
$schema: http://json-schema.org/draft-04/schema#
title: Expand root plugin manifest
type: object
properties:
plugins:
type: object
properties:
expand_root:
type: object
properties:
filesystem_type:
enum:
- ext2
- ext3
- ext4
- xfs
root_device: {type: string}
root_partition: {type: integer}
required:
- filesystem_type
- root_device
- root_partition
additionalProperties: false

View file

@ -0,0 +1,58 @@
from bootstrapvz.base import Task
from bootstrapvz.common import phases
from bootstrapvz.common.tasks import initd
from bootstrapvz.common.tasks import packages
from bootstrapvz.common.tools import log_check_call
from bootstrapvz.common.tools import rel_path
from bootstrapvz.common.tools import sed_i
import os
import shutil
ASSETS_DIR = rel_path(__file__, 'assets')
class InstallGrowpart(Task):
description = 'Adding necessary packages for growpart.'
phase = phases.preparation
successors = [packages.AddManifestPackages]
@classmethod
def run(cls, info):
# Use the cloud-guest-utils package from jessie-backports which has
# several significant bug fixes from the mainline growpart script.
target = None
from bootstrapvz.common.releases import jessie
if info.manifest.release == jessie:
target = '{system.release}-backports'
info.packages.add('cloud-guest-utils', target)
class InstallExpandRootScripts(Task):
description = 'Installing scripts for expand-root.'
phase = phases.system_modification
successors = [initd.InstallInitScripts]
@classmethod
def run(cls, info):
expand_root_script = os.path.join(ASSETS_DIR, 'expand-root.sh')
expand_root_service = os.path.join(ASSETS_DIR, 'expand-root.service')
expand_root_script_dest = os.path.join(info.root, 'usr/bin/expand-root.sh')
expand_root_service_dest = os.path.join(info.root, 'lib/systemd/system/expand-root.service')
filesystem_type = info.manifest.plugins['expand_root'].get('filesystem_type')
root_device = info.manifest.plugins['expand_root'].get('root_device')
root_partition = info.manifest.plugins['expand_root'].get('root_partition')
# Copy files over
shutil.copy(expand_root_script, expand_root_script_dest)
os.chmod(expand_root_script_dest, 0750)
shutil.copy(expand_root_service, expand_root_service_dest)
# Expand out options into expand-root.sh script.
opts = '%s %s %s' % (root_device, root_partition, filesystem_type)
sed_i(expand_root_service_dest, r'^ExecStart=/usr/bin/expand-root.sh.*$',
'ExecStart=/usr/bin/expand-root.sh %s' % opts)
# Enable systemd service
log_check_call(['chroot', info.root, 'systemctl', 'enable', 'expand-root.service'])

View file

@ -3,7 +3,6 @@ import tasks.apt
import tasks.boot import tasks.boot
import tasks.configuration import tasks.configuration
import tasks.image import tasks.image
import tasks.initd
import tasks.host import tasks.host
import tasks.packages import tasks.packages
from bootstrapvz.common.tasks import apt, boot, image, loopback, initd from bootstrapvz.common.tasks import apt, boot, image, loopback, initd
@ -16,7 +15,6 @@ def validate_manifest(data, validator, error):
def resolve_tasks(taskset, manifest): def resolve_tasks(taskset, manifest):
from bootstrapvz.common.releases import stretch
taskset.update(task_groups.get_standard_groups(manifest)) taskset.update(task_groups.get_standard_groups(manifest))
taskset.update([apt.AddBackports, taskset.update([apt.AddBackports,
apt.AddDefaultSources, apt.AddDefaultSources,
@ -27,9 +25,6 @@ def resolve_tasks(taskset, manifest):
tasks.host.DisableIPv6, tasks.host.DisableIPv6,
tasks.boot.ConfigureGrub, tasks.boot.ConfigureGrub,
initd.InstallInitScripts, initd.InstallInitScripts,
initd.AddExpandRoot,
initd.AdjustExpandRootScript,
tasks.initd.AdjustExpandRootDev,
boot.BlackListModules, boot.BlackListModules,
boot.UpdateInitramfs, boot.UpdateInitramfs,
ssh.AddSSHKeyGeneration, ssh.AddSSHKeyGeneration,
@ -42,13 +37,6 @@ def resolve_tasks(taskset, manifest):
]) ])
taskset.discard(grub.SetGrubConsolOutputDeviceToSerial) taskset.discard(grub.SetGrubConsolOutputDeviceToSerial)
# Temporary fix for Stretch
if manifest.release == stretch:
taskset.discard(initd.InstallInitScripts)
taskset.discard(initd.AddExpandRoot)
taskset.discard(initd.AdjustExpandRootScript)
taskset.discard(tasks.initd.AdjustExpandRootDev)
if 'gcs_destination' in manifest.provider: if 'gcs_destination' in manifest.provider:
taskset.add(tasks.image.UploadImage) taskset.add(tasks.image.UploadImage)
if 'gce_project' in manifest.provider: if 'gce_project' in manifest.provider:

View file

@ -1,16 +0,0 @@
from bootstrapvz.base import Task
from bootstrapvz.common import phases
from bootstrapvz.common.tasks import initd
import os.path
class AdjustExpandRootDev(Task):
description = 'Adjusting the expand-root device'
phase = phases.system_modification
predecessors = [initd.AddExpandRoot, initd.AdjustExpandRootScript]
@classmethod
def run(cls, info):
from bootstrapvz.common.tools import sed_i
script = os.path.join(info.root, 'etc/init.d/expand-root')
sed_i(script, '/dev/loop0', '/dev/sda')

View file

@ -26,8 +26,6 @@ packages:
- deb http://packages.cloud.google.com/apt cloud-sdk-{system.release} main - deb http://packages.cloud.google.com/apt cloud-sdk-{system.release} main
- deb http://packages.cloud.google.com/apt google-cloud-compute-{system.release} main - deb http://packages.cloud.google.com/apt google-cloud-compute-{system.release} main
install: install:
- cloud-initramfs-growroot
- cloud-utils
- google-cloud-sdk - google-cloud-sdk
- google-compute-engine-{system.release} - google-compute-engine-{system.release}
- google-compute-engine-init-{system.release} - google-compute-engine-init-{system.release}
@ -41,12 +39,11 @@ packages:
- package: python-crcmod - package: python-crcmod
pin: release n=jessie-backports pin: release n=jessie-backports
pin-priority: 500 pin-priority: 500
# cloud-utils in backports has a fixed version of growpart to allow root disk expansion on disks > 2TB.
backport-cloud-utils:
- package: cloud-utils
pin: release n=jessie-backports
pin-priority: 500
plugins: plugins:
expand_root:
filesystem_type: ext4
root_device: /dev/sda
root_partition: 1
google_cloud_repo: google_cloud_repo:
cleanup_bootstrap_key: true cleanup_bootstrap_key: true
enable_keyring_repo: true enable_keyring_repo: true

View file

@ -26,16 +26,20 @@ packages:
- deb http://packages.cloud.google.com/apt cloud-sdk-{system.release} main - deb http://packages.cloud.google.com/apt cloud-sdk-{system.release} main
- deb http://packages.cloud.google.com/apt google-cloud-compute-{system.release} main - deb http://packages.cloud.google.com/apt google-cloud-compute-{system.release} main
install: install:
- cloud-initramfs-growroot
- cloud-utils
- google-cloud-sdk - google-cloud-sdk
- google-compute-engine-{system.release} - google-compute-engine-{system.release}
- google-compute-engine-init-{system.release} - google-compute-engine-init-{system.release}
- google-config-{system.release} - google-config-{system.release}
- man
- net-tools
- python-crcmod - python-crcmod
- screen - screen
- vim - vim
plugins: plugins:
expand_root:
filesystem_type: ext4
root_device: /dev/sda
root_partition: 1
google_cloud_repo: google_cloud_repo:
cleanup_bootstrap_key: true cleanup_bootstrap_key: true
enable_keyring_repo: true enable_keyring_repo: true