diff options
Diffstat (limited to 'app-emulation')
-rw-r--r-- | app-emulation/cloud-init/ChangeLog | 6 | ||||
-rw-r--r-- | app-emulation/cloud-init/Manifest | 33 | ||||
-rw-r--r-- | app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild | 5 | ||||
-rw-r--r-- | app-emulation/cloud-init/files/cloud.cfg | 37 | ||||
-rwxr-xr-x | app-emulation/cloud-init/files/growpart | 778 |
5 files changed, 814 insertions, 45 deletions
diff --git a/app-emulation/cloud-init/ChangeLog b/app-emulation/cloud-init/ChangeLog index 43720939287d..e518ff4fe9bc 100644 --- a/app-emulation/cloud-init/ChangeLog +++ b/app-emulation/cloud-init/ChangeLog @@ -1,6 +1,10 @@ # ChangeLog for app-emulation/cloud-init # Copyright 1999-2015 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/app-emulation/cloud-init/ChangeLog,v 1.17 2015/07/20 07:42:31 prometheanfire Exp $ +# $Header: /var/cvsroot/gentoo-x86/app-emulation/cloud-init/ChangeLog,v 1.18 2015/07/20 22:42:41 prometheanfire Exp $ + + 20 Jul 2015; Matthew Thode <prometheanfire@gentoo.org> +files/growpart, + cloud-init-0.7.6-r1.ebuild, files/cloud.cfg: + updating cloud.cfg and adding growparts *cloud-init-0.7.6-r1 (20 Jul 2015) diff --git a/app-emulation/cloud-init/Manifest b/app-emulation/cloud-init/Manifest index 1aa405c33b31..4e247ecd02be 100644 --- a/app-emulation/cloud-init/Manifest +++ b/app-emulation/cloud-init/Manifest @@ -2,30 +2,31 @@ Hash: SHA256 AUX cloud-init-0.7.5-tests-exclude.patch 534 SHA256 9d2a13365551334bdbdbd9c243ba3413b66f47dd36ae94727c5336fb013113bb SHA512 b59bdcb5a5c6c7891a62c67c7bea83c42f00b2458959341fde33520dc02d65fe4a29a344f84c4f94c166a37bd98c19b596ef92eb51760228a2945b67f919087a WHIRLPOOL a8126ba0641ccd700ab7d58f81815c1a15e5c4289536aa9db6504b47a218d18c232062c6e0a4f149a87b70f2cfea9599876dc1d05693b26079c199107f496fa7 -AUX cloud.cfg 2288 SHA256 440c69879e875da844db0d0c01b93f7ae4b85c2d98b15c87321ff0699e1a5c44 SHA512 454ae0e473dcb0c30be65c11f63328d8b9b62b4653efe5d29bcfcdcb84fd66bdff5f5f33aa6e706a9eb35131b91f322b110c10328a537f0c2db202817eeb6653 WHIRLPOOL 4a42dca664229f041d0ff8cf9e377965eb4951b5f50647b2476a33a2d2292e7f54dc86f4dc39551f0d6731814231e9b78dd5ec5c494f87e4493480497dd411df +AUX cloud.cfg 1815 SHA256 e2eecea357864a080ff8c757f4282b9ae6373acef4e6ed604b071f9c622cd7bd SHA512 ff9a978befebdc177000ce50252a89d2b9adf4e2ab92c7c87300c54cebe5ff160fd6619dd56f0432a6ec8a819a4f948aa3e99c06e37dc6650ed41fdce16daeb3 WHIRLPOOL 97a2dcfd07860920cad70e28641853272e3ff927ed7cdc6075a26065bbb2a017d94f2b39795ecdfa5c1ec70587fc6a7b88fd281b2f702cc3ddbf7d1475a1bba0 +AUX growpart 21323 SHA256 f3e1482ce64074c2f43bb8efd8a5589542f6ce913e28f8eaa9d46c61357b5577 SHA512 462d01202393ef94346d8ec819aa327ebfa0f7f5d95cb26107ac8a6b11a8b016d58e96fc07f388460a486d7d60a5cff622d54a920c11cedf007f280a74725aa4 WHIRLPOOL 90120f9bd06f0bb21b3761709355eb21105cc2e132ef0394bf5a4065415eb589aa98b044a88f9a126dcc1117c524debe4059c5f59a7c96c689455ff8d7a73084 AUX hosts.gentoo.tmpl 920 SHA256 a7d1a6e160bb05928bbb9f2b8cfcbc1fa60c3a33cd034b06f3f92ffe1126df37 SHA512 39e6bcdf40bd842a1d2e4ccd1c993b432016f7b3c4d5455b71896a16ee87a5d698e214919172f0a7e2f647156f5efe0964fed999dd193e4f16c944efdcc0f9c5 WHIRLPOOL 89ad898aa4479b9bc3dc3efc9a10d7be81c302e490e8548f3752af9d50cd688ef0f3202d2efeadf2e034fcf5ef39ef3a5e78f9ebfa308f79684dd0342686e94d DIST cloud-init-0.7.5.tar.gz 503717 SHA256 a92bb83809c139a7db378916414c18b0819e306852d6c60dd89388868857ed33 SHA512 79e1e4a9e1130a3a9deb0482278215baf5ed41e02beebed0a2c6fac4e215340a9537158bd259758a2e074f334c0c0b9e7b936c23eeb9c848c67f7e7835cf0f5d WHIRLPOOL 7d92a0e1b6a3faf550bc442b02c117280c47d160e7e318d9fb859d6d8b59a0ef947d057dfb615bd925420a25ca28852742ee87ffd6066664faf640ca53a13073 DIST cloud-init-0.7.6.tar.gz 515670 SHA256 9e8fd22eb7f6e40ae6a5f66173ddc3cc18f65ee406c460a728092b37db2f3ed7 SHA512 aa2397328afda8e77ed6d642e7642f41a4b4b5bcd3d0e87056aa8c88b56624ec65c57cfc66b0d13ccc235f1840baf1d577316974902a0439cf2f2eb0f8eef36d WHIRLPOOL 639a556e51b4b4b180951f9e481f9a0dcd45067d1d5760ce7e871ceea8bbb4e195258d96273d3ef88c7e2f2520318e9172c3ad0cb23d6ad0ae1835e17087e3a5 EBUILD cloud-init-0.7.5-r1.ebuild 1659 SHA256 b1b78f80550051f716b6b48fdf4855a251016d536dcc470041f39f15516269bd SHA512 33300619cd99e488f9255ef08ecb73d7b29b76271e28c541926208436ffaeddac7671f3082897ff84382a9fb9d524fc4cc78a32403292f4b5a1fa8d81419acc7 WHIRLPOOL f6da626c00c23c53a3607dd9c9a150f8c5bc28ed21ec44631e8f57503c0a6f114215b570b11b9b181a9081de6e3e06f05bedcb88abb1673ed2b000ff6191fcf0 EBUILD cloud-init-0.7.5-r2.ebuild 2411 SHA256 e4a58be7d11d57a75c8068169801c6f4fa0d6b65491e6f5012846c68ca5101c4 SHA512 5de768692d13c365b23570a3fb53ac594b62954965cad2f72efebc30d74be6905cf620ed06339ce6c97ed9e858c9201cab36be9feb91fc7df320d475e89cedfe WHIRLPOOL 7ae0e57a4617473ab781536b105e38b3f66dbe00f9865a061f41526a1cd524b36dba9875494bb6e5360340509c0617d2076a5e5e0bceec9bd023df93e3cd96a5 EBUILD cloud-init-0.7.5-r3.ebuild 2494 SHA256 4df093d1ce9383a1c2d7247a41fed2b774088d0a38ec226b151a55da2a4022ba SHA512 9f6392eb759e857d8656a8aecd475e2b05f77717a48ae8a687e5faea11f4fe6dd7b68cdb07072fb9760d7e30a192b54e41f4ec2d8572e89796af30345e658a60 WHIRLPOOL 18ffe9720d384c7b6f591b43f90bb65a4d33b31d6e960005e2441501784b351e02a31db9db49cace162be5a4ebcd24df10785cb42561b3405d5353b77e698ebd -EBUILD cloud-init-0.7.6-r1.ebuild 2651 SHA256 cb666f96fefb240da4a805b0d8892a5e5d620fc17099732b976de7bb49b50cbf SHA512 c6ef4436fc68efe0256d5bd43ea9c9f4e5314537bb7287e533107078f1d20c7d5de178c265ca577fbe2cffa81ba50809cfcc55d94f6219eb893b0c65743841be WHIRLPOOL e0429ce0d2aa6a5e8d3c1ec9b1121aeb446459a162fe8f430723bb4a00f9f40e887d9ace84705a1eb15a85a19b705544a8dacfcb28ced5ec4172743cec4c7944 +EBUILD cloud-init-0.7.6-r1.ebuild 2718 SHA256 45c7af3aaebab053ad1a13a0862c25c9e49beb8237563123c88bc54d48ebc952 SHA512 f8eac928f448b7412deb8dc46530874ac8812b5a8c3a11f7b41ebfc555742212bb21a3c4f857d67f52f8d335693c4d896496af157ded11c7796ca8a313d081ee WHIRLPOOL b8fa1221dc029818284ed8fe88af855c58795196420b230c52f1d677f0d66c7276bec20f333ef0aab06a270a4250c6dce0af28abf4dfd0bb5e068c0f4d41a478 EBUILD cloud-init-0.7.6.ebuild 2568 SHA256 00b1e414bd07ad55d6b5aa94bf17448f6627510de2ce869f3914dc0942962057 SHA512 643cd51cefafd4ebf81390edb37ce5e4b1ce8a1d15ed2cb655c4101e342348148957f4d4563fab1faa57c27d433832898f06652b59e00319d017f1164d27043e WHIRLPOOL e731eb613b42fafd2f3f5151d89ce3b30172d40d88df33a83547e9ca268be88babf56fbe0eccbe7140c77ffc4deecd3779011f05598e3bb0ab5ff2688c5b555a -MISC ChangeLog 3077 SHA256 548a45fb8a511a1dd6127e13c16bc7c722f13bd3c6d45e15a92528342bff9af5 SHA512 45b8d38cc4655e30e741dd2665a457bcb7b27a03be88852e5ecf1720fb3ca6d95af8f9da4bfcb0aedf144f8e2d77bf3604fbb467441a207b52759d24f795d4c4 WHIRLPOOL 8e43041cd7ba844afbfac316cb453bc3284531f9bba46c9b2fb70cc3c1c8c4e7f0ac2540ea2dcb23c308205a988d9b89d542c8c5fd8e197c26262ed5c9907812 +MISC ChangeLog 3241 SHA256 86bae93ac103fadecd0086bda4360bcc64e3150f9caec271deb2da677179b7eb SHA512 46ad6a804b3e957473adc4bf2c7aa78790aa7ed00e8eb7f7a2d05794f1a9991535ab1c483b49ba3d0db84ce64ac9abaae8e99773e46f79f55e376e63f1a359cf WHIRLPOOL e58bc36241928f5be57140c89c2a618f5ab7823b45f3ccf31ab31d482df527db875ede8a48ae0e8713c336e8f80650a1cb1ed9c4a0807bcba035d3dadf63d3e5 MISC metadata.xml 554 SHA256 144e77da975a51af29efdc0926a004294b47fd66e63ad6049da27b54fdecff04 SHA512 a49892c6f440a9eeb6c7461d71d47530d7b4fa69bfbe000259164857e82fd34eed30adb18e4a62063bbd12b8fc964c2ed5523e07f13f375ddb9519ff57674911 WHIRLPOOL c33e15cf8b5ab5bd834ee5f7987b6e460be4db20b442d2715db65eb6691397e4b633be9f876866ecc9d0b6bf8cb46b5342fb897835e31f90df466868f2599dca -----BEGIN PGP SIGNATURE----- -iQIcBAEBCAAGBQJVrKaoAAoJEGSje+quGaTo9mMQALqmAs3xbPml4NpZgDOMICWH -01U/mElvAc8UScXtbwQEM5n58sJ/NLFq1yZ2fwm/FArDPaEfGycPzocpRLqM2rEV -uCMtKARO4CuktDrUmscdf8ahNxBADcYib60xnjOUgqpm1wXOKjF+MPSaRfBziVFu -hoMrAfC1t/r3xGC4zV7itqsPOkr1hswQaaX3rCL2RqLEocrOg1FyuBDPSBN5r9vg -ZN+V4dfPRYw3SyfZ0d4WQtWLeojmLf1pQerS5Yvn+3A+QSO83ixXEnBTWZjdoMkE -JGyU+194nzj0VBJOt6ZV1oOIVdR8u16miU7XVhZzmw2mi6Y8+k8Zxt6LmEL6xKjJ -hssFMN2BcjGzp93v2OTwK3tKKMgkbQh1nRllqTWdVLy2HwTdFDFLmwyExwSqu//7 -xQdW+QVKf2MGNzDVx48N50A0SI70tbQhKcc0dWmpA3fkvg85xOItxufC/9xV7Z+z -mjppUQSMewASfDG2uRmegXaAX9lSrG71c75aNv5o/Ss5Qa+WNVyO2Ioh+my1j806 -/awv/HoWhgAx7GznrIukhjaNCRJjocHF45VflIiA87eWy7HOyIgDaykljZyx4t8w -d/4kU8SEaALtR42S8eMsYn012MaGHWq6Cx13Ekmx+QTdPYJ0d4TaCbsodNugAIS6 -aJLo1QBaPpr3APmvaJjf -=ZiFh +iQIcBAEBCAAGBQJVrXmjAAoJEGSje+quGaToW84P/292sz87YPu8D199fOVrsq1O +/1U/Zlx4lxAxnHVjXR8kx0ETzhJLAlD+eJXx7Vs7GB3KExI0k3gvzmZkOt8ZkFDQ +mOAQ3IodPa4BY8LxcfBoPBk60ZDKue/2VbpQ/l1r6jQGUIj7jl1Gcc5IAHPLq2Qt +m+ZrgWFOCymoOh8WZDelYcnCJWlMevFGTy3Ep9AulDsdzXIeKUbCfCXU14XsAURN +RvIT2GL8ld5rXp+2NmoIkrZ11N2wXS0CESBq2Krm63ORrMShyExGxnHMRHbWAIHn +eUK06/QR2S4Uw9gEfLTXrJ65rcoPKH31gd9UKg+ODo3PrC5DV5dCg3xzBOpC42Ec +GCdyTGOADPCMcF4isihWz4dZRaUUyvopBkd2fsZrUDPMq9uXH60ChPfBJcB8TJjM +6vc3QyQrgGLjf5YktRNQLdBMW84NVv/l2XINvOP3Hiq888RUxB8m2x0Pzru6h62M +XKqQDw5FE9i+O6I/xjpflO9BI58/VK7RB7KA2EgETQlustc9lruUey4HMtSUII2H +Jtnxu7VIuOfzyy4Uoh3NYk8+KxafYJlg6c0HKKpWlXtyB/eCHav1re24fcXqRTsh +D6jRb17ZsvErbrHr9NnWCfn2AHdzBslJWxEnlxVJ+Ur6icNcxeU6+i1YwyUXMe3W +hDg6lObidx4t/O4jT633 +=thHD -----END PGP SIGNATURE----- diff --git a/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild b/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild index 463aadf4407b..7fc94d860840 100644 --- a/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild +++ b/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild @@ -1,6 +1,6 @@ # Copyright 1999-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild,v 1.1 2015/07/20 07:42:31 prometheanfire Exp $ +# $Header: /var/cvsroot/gentoo-x86/app-emulation/cloud-init/cloud-init-0.7.6-r1.ebuild,v 1.2 2015/07/20 22:42:41 prometheanfire Exp $ EAPI=5 PYTHON_COMPAT=( python2_7 ) @@ -41,6 +41,7 @@ DEPEND=" " RDEPEND=" ${CDEPEND} + sys-apps/gptfdisk virtual/logger " @@ -91,6 +92,8 @@ python_install_all() { doinitd "${S}"/sysvinit/gentoo/cloud-init-local insinto /etc/cloud/templates doins "${FILESDIR}/hosts.gentoo.tmpl" + exeinto /usr/bin + doexe "${FILESDIR}/growpart" systemd_dounit "${S}"/systemd/cloud-config.service systemd_dounit "${S}"/systemd/cloud-config.target diff --git a/app-emulation/cloud-init/files/cloud.cfg b/app-emulation/cloud-init/files/cloud.cfg index f20ab5a1544f..d62e3a22241b 100644 --- a/app-emulation/cloud-init/files/cloud.cfg +++ b/app-emulation/cloud-init/files/cloud.cfg @@ -10,21 +10,17 @@ users: # If this is set, 'root' will not be able to ssh in and they # will get a message to login instead as the above $user (ubuntu) disable_root: true +ssh_pwauth: false # This will cause the set+update hostname module to not operate (if true) -preserve_hostname: false +# preserve_hostname: false -# Example datasource config -# datasource: -# Ec2: -# metadata_urls: [ 'blah.com' ] -# timeout: 5 # (defaults to 50 seconds) -# max_wait: 10 # (defaults to 120 seconds) +syslog_fix_perms: root:root + +ssh_deletekeys: false +ssh_genkeytypes: [rsa, dsa] -# The modules that run in the 'init' stage cloud_init_modules: - - migrator - - ubuntu-init-switch - seed_random - bootcmd - write-files @@ -34,25 +30,14 @@ cloud_init_modules: - update_hostname - update_etc_hosts - ca-certs - - rsyslog - users-groups - ssh -# The modules that run in the 'config' stage cloud_config_modules: -# Emit the cloud config ready event -# this can be used by upstart jobs for 'start on cloud-config'. - - emit_upstart - disk_setup - mounts - ssh-import-id - - locale - set-passwords - - grub-dpkg - - apt-pipelining - - apt-configure - - package-update-upgrade-install - - landscape - timezone - puppet - chef @@ -60,11 +45,8 @@ cloud_config_modules: - mcollective - disable-ec2-metadata - runcmd - - byobu -# The modules that run in the 'final' stage cloud_final_modules: - - rightscale_userdata - scripts-vendor - scripts-per-once - scripts-per-boot @@ -85,12 +67,13 @@ system_info: default_user: name: gentoo lock_passwd: True - gecos: gentoo - groups: [adm] + gecos: Gentoo + groups: [users, wheel] + primary_group: users + no-user-group: true sudo: ["ALL=(ALL) NOPASSWD:ALL"] shell: /bin/bash # Other config here will be given to the distro class and/or path classes paths: cloud_dir: /var/lib/cloud/ templates_dir: /etc/cloud/templates/ - ssh_svcname: sshd diff --git a/app-emulation/cloud-init/files/growpart b/app-emulation/cloud-init/files/growpart new file mode 100755 index 000000000000..4b67d8b90822 --- /dev/null +++ b/app-emulation/cloud-init/files/growpart @@ -0,0 +1,778 @@ +#!/bin/sh +# Copyright (C) 2011 Canonical Ltd. +# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. +# +# Authors: Scott Moser <smoser@canonical.com> +# Juerg Haefliger <juerg.haefliger@hp.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# the fudge factor. if within this many bytes dont bother +FUDGE=${GROWPART_FUDGE:-$((1024*1024))} +TEMP_D="" +RESTORE_FUNC="" +RESTORE_HUMAN="" +VERBOSITY=0 +DISK="" +PART="" +PT_UPDATE=false +DRY_RUN=0 + +SFDISK_VERSION="" +SFDISK_2_26="22600" +MBR_BACKUP="" +GPT_BACKUP="" +_capture="" + +error() { + echo "$@" 1>&2 +} + +fail() { + [ $# -eq 0 ] || echo "FAILED:" "$@" + exit 2 +} + +nochange() { + echo "NOCHANGE:" "$@" + exit 1 +} + +changed() { + echo "CHANGED:" "$@" + exit 0 +} + +change() { + echo "CHANGE:" "$@" + exit 0 +} + +cleanup() { + if [ -n "${RESTORE_FUNC}" ]; then + error "***** WARNING: Resize failed, attempting to revert ******" + if ${RESTORE_FUNC} ; then + error "***** Appears to have gone OK ****" + else + error "***** FAILED! ******" + if [ -n "${RESTORE_HUMAN}" -a -f "${RESTORE_HUMAN}" ]; then + error "**** original table looked like: ****" + cat "${RESTORE_HUMAN}" 1>&2 + else + error "We seem to have not saved the partition table!" + fi + fi + fi + [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" +} + +debug() { + local level=${1} + shift + [ "${level}" -gt "${VERBOSITY}" ] && return + if [ "${DEBUG_LOG}" ]; then + echo "$@" >>"${DEBUG_LOG}" + else + error "$@" + fi +} + +debugcat() { + local level="$1" + shift; + [ "${level}" -gt "$VERBOSITY" ] && return + if [ "${DEBUG_LOG}" ]; then + cat "$@" >>"${DEBUG_LOG}" + else + cat "$@" 1>&2 + fi +} + +mktemp_d() { + # just a mktemp -d that doens't need mktemp if its not there. + _RET=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX" 2>/dev/null) && + return + _RET=$(umask 077 && t="${TMPDIR:-/tmp}/${0##*/}.$$" && + mkdir "${t}" && echo "${t}") + return +} + +Usage() { + cat <<EOF +${0##*/} disk partition + rewrite partition table so that partition takes up all the space it can + options: + -h | --help print Usage and exit + --fudge F if part could be resized, but change would be + less than 'F' bytes, do not resize (default: ${FUDGE}) + -N | --dry-run only report what would be done, show new 'sfdisk -d' + -v | --verbose increase verbosity / debug + -u | --update R update the the kernel partition table info after growing + this requires kernel support and 'partx --update' + R is one of: + - 'auto' : [default] update partition if possible + - 'force' : try despite sanity checks (fail on failure) + - 'off' : do not attempt + - 'on' : fail if sanity checks indicate no support + + Example: + - ${0##*/} /dev/sda 1 + Resize partition 1 on /dev/sda +EOF +} + +bad_Usage() { + Usage 1>&2 + error "$@" + exit 2 +} + +sfdisk_restore_legacy() { + sfdisk --no-reread "${DISK}" -I "${MBR_BACKUP}" +} + +sfdisk_restore() { + # files are named: sfdisk-<device>-<offset>.bak + local f="" offset="" fails=0 + for f in "${MBR_BACKUP}"*.bak; do + [ -f "$f" ] || continue + offset=${f##*-} + offset=${offset%.bak} + [ "$offset" = "$f" ] && { + error "WARN: confused by file $f"; + continue; + } + dd "if=$f" "of=${DISK}" seek=$(($offset)) bs=1 conv=notrunc || + { error "WARN: failed restore from $f"; fails=$(($fails+1)); } + done + return $fails +} + +sfdisk_worked_but_blkrrpart_failed() { + local ret="$1" output="$2" + # exit code found was just 1, but dont insist on that + #[ $ret -eq 1 ] || return 1 + # Successfully wrote the new partition table + grep -qi "Success.* wrote.* new.* partition" "$output" && + grep -qi "BLKRRPART: Device or resource busy" "$output" + return +} + +get_sfdisk_version() { + # set SFDISK_VERSION to MAJOR*10000+MINOR*100+MICRO + local out oifs="$IFS" ver="" + [ -n "$SFDISK_VERSION" ] && return 0 + # expected output: sfdisk from util-linux 2.25.2 + out=$(sfdisk --version) || + { error "failed to get sfdisk version"; return 1; } + set -- $out + ver=$4 + case "$ver" in + [0-9]*.[0-9]*.[0-9]|[0-9].[0-9]*) + IFS="."; set -- $ver; IFS="$oifs" + SFDISK_VERSION=$(($1*10000+$2*100+${3:-0})) + return 0;; + *) error "unexpected output in sfdisk --version [$out]" + return 1;; + esac +} + +resize_sfdisk() { + local humanpt="${TEMP_D}/recovery" + local mbr_backup="${TEMP_D}/orig.save" + local restore_func="" + local format="$1" + + local change_out=${TEMP_D}/change.out + local dump_out=${TEMP_D}/dump.out + local new_out=${TEMP_D}/new.out + local dump_mod=${TEMP_D}/dump.mod + local tmp="${TEMP_D}/tmp.out" + local err="${TEMP_D}/err.out" + local mbr_max_512="4294967296" + + local pt_start pt_size pt_end max_end new_size change_info dpart + local sector_num sector_size disk_size tot out + + rqe sfd_list sfdisk --list --unit=S "$DISK" >"$tmp" || + fail "failed: sfdisk --list $DISK" + if [ "${SFDISK_VERSION}" -lt ${SFDISK_2_26} ]; then + # exected output contains: Units: sectors of 512 bytes, ... + out=$(awk '$1 == "Units:" && $5 ~ /bytes/ { print $4 }' "$tmp") || + fail "failed to read sfdisk output" + if [ -z "$out" ]; then + error "WARN: sector size not found in sfdisk output, assuming 512" + sector_size=512 + else + sector_size="$out" + fi + local _w _cyl _w1 _heads _w2 sectors _w3 t s + # show-size is in units of 1024 bytes (same as /proc/partitions) + t=$(sfdisk --show-size "${DISK}") || + fail "failed: sfdisk --show-size $DISK" + disk_size=$((t*1024)) + sector_num=$(($disk_size/$sector_size)) + msg="disk size '$disk_size' not evenly div by sector size '$sector_size'" + [ "$((${disk_size}%${sector_size}))" -eq 0 ] || + error "WARN: $msg" + restore_func=sfdisk_restore_legacy + else + # --list first line output: + # Disk /dev/vda: 20 GiB, 21474836480 bytes, 41943040 sectors + local _x + read _x _x _x _x disk_size _x sector_num _x < "$tmp" + sector_size=$((disk_size/$sector_num)) + restore_func=sfdisk_restore + fi + + debug 1 "$sector_num sectors of $sector_size. total size=${disk_size} bytes" + [ $(($disk_size/512)) -gt $mbr_max_512 ] && + debug 1 "WARN: disk is larger than 2TB. additional space will go unused." + + rqe sfd_dump sfdisk --unit=S --dump "${DISK}" >"${dump_out}" || + fail "failed to dump sfdisk info for ${DISK}" + RESTORE_HUMAN="$dump_out" + + { + echo "## sfdisk --unit=S --dump ${DISK}" + cat "${dump_out}" + } >"$humanpt" + + [ $? -eq 0 ] || fail "failed to save sfdisk -d output" + RESTORE_HUMAN="$humanpt" + + debugcat 1 "$humanpt" + + sed -e 's/,//g; s/start=/start /; s/size=/size /' "${dump_out}" \ + >"${dump_mod}" || + fail "sed failed on dump output" + + dpart="${DISK}${PART}" # disk and partition number + if [ -b "${DISK}p${PART}" -a "${DISK%[0-9]}" != "${DISK}" ]; then + # for block devices that end in a number (/dev/nbd0) + # the partition is "<name>p<partition_number>" (/dev/nbd0p1) + dpart="${DISK}p${PART}" + elif [ "${DISK#/dev/loop[0-9]}" != "${DISK}" ]; then + # for /dev/loop devices, sfdisk output will be <name>p<number> + # format also, even though there is not a device there. + dpart="${DISK}p${PART}" + fi + + pt_start=$(awk '$1 == pt { print $4 }' "pt=${dpart}" <"${dump_mod}") && + pt_size=$(awk '$1 == pt { print $6 }' "pt=${dpart}" <"${dump_mod}") && + [ -n "${pt_start}" -a -n "${pt_size}" ] && + pt_end=$((${pt_size}+${pt_start})) || + fail "failed to get start and end for ${dpart} in ${DISK}" + + # find the minimal starting location that is >= pt_end + max_end=$(awk '$3 == "start" { if($4 >= pt_end && $4 < min) + { min = $4 } } END { printf("%s\n",min); }' \ + min=${sector_num} pt_end=${pt_end} "${dump_mod}") && + [ -n "${max_end}" ] || + fail "failed to get max_end for partition ${PART}" + + mbr_max_sectors=$((mbr_max_512*$((sector_size/512)))) + if [ "$max_end" -gt "$mbr_max_sectors" ]; then + max_end=$mbr_max_sectors + fi + + if [ "$format" = "gpt" ]; then + # sfdisk respects 'last-lba' in input, and complains about + # partitions that go past that. without it, it does the right thing. + sed -i '/^last-lba:/d' "$dump_out" || + fail "failed to remove last-lba from output" + fi + + local gpt_second_size="33" + if [ "${max_end}" -gt "$((${sector_num}-${gpt_second_size}))" ]; then + # if mbr allow subsequent conversion to gpt without shrinking the + # partition. safety net at cost of 33 sectors, seems reasonable. + # if gpt, we can't write there anyway. + debug 1 "padding ${gpt_second_size} sectors for gpt secondary header" + max_end=$((${sector_num}-${gpt_second_size})) + fi + + debug 1 "max_end=${max_end} tot=${sector_num} pt_end=${pt_end}" \ + "pt_start=${pt_start} pt_size=${pt_size}" + [ $((${pt_end})) -eq ${max_end} ] && + nochange "partition ${PART} is size ${pt_size}. it cannot be grown" + [ $((${pt_end}+(${FUDGE}/$sector_size))) -gt ${max_end} ] && + nochange "partition ${PART} could only be grown by" \ + "$((${max_end}-${pt_end})) [fudge=$((${FUDGE}/$sector_size))]" + + # now, change the size for this partition in ${dump_out} to be the + # new size + new_size=$((${max_end}-${pt_start})) + sed "\|^\s*${dpart} |s/${pt_size},/${new_size},/" "${dump_out}" \ + >"${new_out}" || + fail "failed to change size in output" + + change_info="partition=${PART} start=${pt_start} old: size=${pt_size} end=${pt_end} new: size=${new_size},end=${max_end}" + if [ ${DRY_RUN} -ne 0 ]; then + echo "CHANGE: ${change_info}" + { + echo "# === old sfdisk -d ===" + cat "${dump_out}" + echo "# === new sfdisk -d ===" + cat "${new_out}" + } 1>&2 + exit 0 + fi + + MBR_BACKUP="${mbr_backup}" + LANG=C sfdisk --no-reread "${DISK}" --force \ + -O "${mbr_backup}" <"${new_out}" >"${change_out}" 2>&1 + ret=$? + [ $ret -eq 0 ] || RESTORE_FUNC="${restore_func}" + + if [ $ret -eq 0 ]; then + : + elif $PT_UPDATE && + sfdisk_worked_but_blkrrpart_failed "$ret" "${change_out}"; then + # if the command failed, but it looks like only because + # the device was busy and we have pt_update, then go on + debug 1 "sfdisk failed, but likely only because of blkrrpart" + else + error "attempt to resize ${DISK} failed. sfdisk output below:" + sed 's,^,| ,' "${change_out}" 1>&2 + fail "failed to resize" + fi + + rq pt_update pt_update "$DISK" "$PART" || + fail "pt_resize failed" + + RESTORE_FUNC="" + + changed "${change_info}" + + # dump_out looks something like: + ## partition table of /tmp/out.img + #unit: sectors + # + #/tmp/out.img1 : start= 1, size= 48194, Id=83 + #/tmp/out.img2 : start= 48195, size= 963900, Id=83 + #/tmp/out.img3 : start= 1012095, size= 305235, Id=82 + #/tmp/out.img4 : start= 1317330, size= 771120, Id= 5 + #/tmp/out.img5 : start= 1317331, size= 642599, Id=83 + #/tmp/out.img6 : start= 1959931, size= 48194, Id=83 + #/tmp/out.img7 : start= 2008126, size= 80324, Id=83 +} + +gpt_restore() { + sgdisk -l "${GPT_BACKUP}" "${DISK}" +} + +resize_sgdisk() { + GPT_BACKUP="${TEMP_D}/pt.backup" + + local pt_info="${TEMP_D}/pt.info" + local pt_pretend="${TEMP_D}/pt.pretend" + local pt_data="${TEMP_D}/pt.data" + local out="${TEMP_D}/out" + + local dev="disk=${DISK} partition=${PART}" + + local pt_start pt_end pt_size last pt_max code guid name new_size + local old new change_info sector_size + + # Dump the original partition information and details to disk. This is + # used in case something goes wrong and human interaction is required + # to revert any changes. + rqe sgd_info sgdisk "--info=${PART}" --print "${DISK}" >"${pt_info}" || + fail "${dev}: failed to dump original sgdisk info" + RESTORE_HUMAN="${pt_info}" + + sector_size=$(awk '$0 ~ /^Logical sector size:.*bytes/ { print $4 }' \ + "$pt_info") && [ -n "$sector_size" ] || { + sector_size=512 + error "WARN: did not find sector size, assuming 512" + } + + debug 1 "$dev: original sgdisk info:" + debugcat 1 "${pt_info}" + + # Pretend to move the backup GPT header to the end of the disk and dump + # the resulting partition information. We use this info to determine if + # we have to resize the partition. + rqe sgd_pretend sgdisk --pretend --move-second-header \ + --print "${DISK}" >"${pt_pretend}" || + fail "${dev}: failed to dump pretend sgdisk info" + + debug 1 "$dev: pretend sgdisk info" + debugcat 1 "${pt_pretend}" + + # Extract the partition data from the pretend dump + awk 'found { print } ; $1 == "Number" { found = 1 }' \ + "${pt_pretend}" >"${pt_data}" || + fail "${dev}: failed to parse pretend sgdisk info" + + # Get the start and end sectors of the partition to be grown + pt_start=$(awk '$1 == '"${PART}"' { print $2 }' "${pt_data}") && + [ -n "${pt_start}" ] || + fail "${dev}: failed to get start sector" + pt_end=$(awk '$1 == '"${PART}"' { print $3 }' "${pt_data}") && + [ -n "${pt_end}" ] || + fail "${dev}: failed to get end sector" + pt_size="$((${pt_end} - ${pt_start}))" + + # Get the last usable sector + last=$(awk '/last usable sector is/ { print $NF }' \ + "${pt_pretend}") && [ -n "${last}" ] || + fail "${dev}: failed to get last usable sector" + + # Find the minimal start sector that is >= pt_end + pt_max=$(awk '{ if ($2 >= pt_end && $2 < min) { min = $2 } } END \ + { print min }' min="${last}" pt_end="${pt_end}" \ + "${pt_data}") && [ -n "${pt_max}" ] || + fail "${dev}: failed to find max end sector" + + debug 1 "${dev}: pt_start=${pt_start} pt_end=${pt_end}" \ + "pt_size=${pt_size} pt_max=${pt_max} last=${last}" + + # Check if the partition can be grown + [ "${pt_end}" -eq "${pt_max}" ] && + nochange "${dev}: size=${pt_size}, it cannot be grown" + [ "$((${pt_end} + ${FUDGE}/${sector_size}))" -gt "${pt_max}" ] && + nochange "${dev}: could only be grown by" \ + "$((${pt_max} - ${pt_end})) [fudge=$((${FUDGE}/$sector_size))]" + + # The partition can be grown if we made it here. Get some more info + # about it so we can do it properly. + # FIXME: Do we care about the attribute flags? + code=$(awk '/^Partition GUID code:/ { print $4 }' "${pt_info}") + guid=$(awk '/^Partition unique GUID:/ { print $4 }' "${pt_info}") + name=$(awk '/^Partition name:/ { gsub(/'"'"'/, "") ; \ + if (NF >= 3) print substr($0, index($0, $3)) }' "${pt_info}") + [ -n "${code}" -a -n "${guid}" ] || + fail "${dev}: failed to parse sgdisk details" + + debug 1 "${dev}: code=${code} guid=${guid} name='${name}'" + local wouldrun="" + [ "$DRY_RUN" -ne 0 ] && wouldrun="would-run" + + # Calculate the new size of the partition + new_size=$((${pt_max} - ${pt_start})) + old="old: size=${pt_size},end=${pt_end}" + new="new: size=${new_size},end=${pt_max}" + change_info="${dev}: start=${pt_start} ${old} ${new}" + + # Backup the current partition table, we're about to modify it + rq sgd_backup $wouldrun sgdisk "--backup=${GPT_BACKUP}" "${DISK}" || + fail "${dev}: failed to backup the partition table" + + # Modify the partition table. We do it all in one go (the order is + # important!): + # - move the GPT backup header to the end of the disk + # - delete the partition + # - recreate the partition with the new size + # - set the partition code + # - set the partition GUID + # - set the partition name + rq sgdisk_mod $wouldrun sgdisk --move-second-header "--delete=${PART}" \ + "--new=${PART}:${pt_start}:${pt_max}" \ + "--typecode=${PART}:${code}" \ + "--partition-guid=${PART}:${guid}" \ + "--change-name=${PART}:${name}" "${DISK}" && + rq pt_update $wouldrun pt_update "$DISK" "$PART" || { + RESTORE_FUNC=gpt_restore + fail "${dev}: failed to repartition" + } + + # Dry run + [ "${DRY_RUN}" -ne 0 ] && change "${change_info}" + + changed "${change_info}" +} + +kver_to_num() { + local kver="$1" maj="" min="" mic="0" + kver=${kver%%-*} + maj=${kver%%.*} + min=${kver#${maj}.} + min=${min%%.*} + mic=${kver#${maj}.${min}.} + [ "$kver" = "$mic" ] && mic=0 + _RET=$(($maj*1000*1000+$min*1000+$mic)) +} + +kver_cmp() { + local op="$2" n1="" n2="" + kver_to_num "$1" + n1="$_RET" + kver_to_num "$3" + n2="$_RET" + [ $n1 $op $n2 ] +} + +rq() { + # runquieterror(label, command) + # gobble stderr of a command unless it errors + local label="$1" ret="" efile="" + efile="$TEMP_D/$label.err" + shift; + + local rlabel="running" + [ "$1" = "would-run" ] && rlabel="would-run" && shift + + local cmd="" x="" + for x in "$@"; do + [ "${x#* }" != "$x" -o "${x#* \"}" != "$x" ] && x="'$x'" + cmd="$cmd $x" + done + cmd=${cmd# } + + debug 2 "$rlabel[$label][$_capture]" "$cmd" + [ "$rlabel" = "would-run" ] && return 0 + + if [ "${_capture}" = "erronly" ]; then + "$@" 2>"$TEMP_D/$label.err" + ret=$? + else + "$@" >"$TEMP_D/$label.err" 2>&1 + ret=$? + fi + if [ $ret -ne 0 ]; then + error "failed [$label:$ret]" "$@" + cat "$efile" 1>&2 + fi + return $ret +} + +rqe() { + local _capture="erronly" + rq "$@" +} + +verify_ptupdate() { + local input="$1" found="" reason="" kver="" + + # we can always satisfy 'off' + if [ "$input" = "off" ]; then + _RET="false"; + return 0; + fi + + if command -v partx >/dev/null 2>&1; then + local out="" ret=0 + out=$(partx --help 2>&1) + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" | grep -q -- --update || { + reason="partx has no '--update' flag in usage." + found="off" + } + else + reason="'partx --help' returned $ret. assuming it is old." + found="off" + fi + else + reason="no 'partx' command" + found="off" + fi + + if [ -z "$found" ]; then + if [ "$(uname)" != "Linux" ]; then + reason="Kernel is not Linux per uname." + found="off" + fi + fi + + if [ -z "$found" ]; then + kver=$(uname -r) || debug 1 "uname -r failed!" + + if ! kver_cmp "${kver-0.0.0}" -ge 3.8.0; then + reason="Kernel '$kver' < 3.8.0." + found="off" + fi + fi + + if [ -z "$found" ]; then + _RET="true" + return 0 + fi + + case "$input" in + on) error "$reason"; return 1;; + auto) + _RET="false"; + debug 1 "partition update disabled: $reason" + return 0;; + force) + _RET="true" + error "WARNING: ptupdate forced on even though: $reason" + return 0;; + esac + error "unknown input '$input'"; + return 1; +} + +pt_update() { + local dev="$1" part="$2" update="${3:-$PT_UPDATE}" + if ! $update; then + return 0 + fi + # partx only works on block devices (do not run on file) + [ -b "$dev" ] || return 0 + partx --update "$part" "$dev" +} + +has_cmd() { + command -v "${1}" >/dev/null 2>&1 +} + +resize_sgdisk_gpt() { + resize_sgdisk gpt +} + +resize_sgdisk_dos() { + fail "unable to resize dos label with sgdisk" +} + +resize_sfdisk_gpt() { + resize_sfdisk gpt +} + +resize_sfdisk_dos() { + resize_sfdisk dos +} + +get_table_format() { + local out="" disk="$1" + if has_cmd blkid && out=$(blkid -o value -s PTTYPE "$disk") && + [ "$out" = "dos" -o "$out" = "gpt" ]; then + _RET="$out" + return + fi + _RET="dos" + if [ ${SFDISK_VERSION} -lt ${SFDISK_2_26} ] && + out=$(sfdisk --id --force "$disk" 1 2>/dev/null); then + if [ "$out" = "ee" ]; then + _RET="gpt" + else + _RET="dos" + fi + return + elif out=$(LANG=C sfdisk --list "$disk"); then + out=$(echo "$out" | sed -e '/Disklabel type/!d' -e 's/.*: //') + case "$out" in + gpt|dos) _RET="$out";; + *) error "WARN: unknown label $out";; + esac + fi +} + +get_resizer() { + local format="$1" user=${2:-"auto"} + + case "$user" in + sgdisk) _RET="resize_sgdisk_$format"; return;; + sfdisk) _RET="resize_sfdisk_$format"; return;; + auto) :;; + *) error "unexpected input: '$user'";; + esac + + if [ "$format" = "dos" ]; then + _RET="resize_sfdisk_dos" + return 0 + fi + + if [ "${SFDISK_VERSION}" -ge ${SFDISK_2_26} ]; then + _RET="resize_sfdisk_gpt" + elif has_cmd sgdisk; then + _RET="resize_sgdisk_$format" + else + error "no tools available to resize disk with '$format'" + return 1 + fi + return 0 +} + +pt_update="auto" +resizer=${GROWPART_RESIZER:-"auto"} +while [ $# -ne 0 ]; do + cur=${1} + next=${2} + case "$cur" in + -h|--help) + Usage + exit 0 + ;; + --fudge) + FUDGE=${next} + shift + ;; + -N|--dry-run) + DRY_RUN=1 + ;; + -u|--update|--update=*) + if [ "${cur#--update=}" != "$cur" ]; then + next="${cur#--update=}" + else + shift + fi + case "$next" in + off|auto|force|on) pt_update=$next;; + *) fail "unknown --update option: $next";; + esac + ;; + -v|--verbose) + VERBOSITY=$(($VERBOSITY+1)) + ;; + --) + shift + break + ;; + -*) + fail "unknown option ${cur}" + ;; + *) + if [ -z "${DISK}" ]; then + DISK=${cur} + else + [ -z "${PART}" ] || fail "confused by arg ${cur}" + PART=${cur} + fi + ;; + esac + shift +done + +[ -n "${DISK}" ] || bad_Usage "must supply disk and partition-number" +[ -n "${PART}" ] || bad_Usage "must supply partition-number" + +has_cmd "sfdisk" || fail "sfdisk not found" +get_sfdisk_version || fail + +[ -e "${DISK}" ] || fail "${DISK}: does not exist" + +[ "${PART#*[!0-9]}" = "${PART}" ] || fail "partition-number must be a number" + +verify_ptupdate "$pt_update" || fail +PT_UPDATE=$_RET + +debug 1 "update-partition set to $PT_UPDATE" + +mktemp_d && TEMP_D="${_RET}" || fail "failed to make temp dir" +trap cleanup 0 # EXIT - some shells may not like 'EXIT' but are ok with 0 + +# get the ID of the first partition to determine if it's MBR or GPT +get_table_format "$DISK" || fail +format=$_RET +get_resizer "$format" "$resizer" || + fail "failed to get a resizer for id '$id'" +resizer=$_RET + +debug 1 "resizing $PART on $DISK using $resizer" +"$resizer" + +# vi: ts=4 noexpandtab |