Add "-r rootdisk" growdisk support

This commit is contained in:
reykfloeter 2019-06-01 23:41:32 +02:00
parent a8490a757f
commit 8dfa3c843a
5 changed files with 193 additions and 21 deletions

View File

@ -1,6 +1,7 @@
PROG= cloud-agent PROG= cloud-agent
SRCS= http.c json.c jsmn.c log.c main.c xml.c SRCS= http.c json.c jsmn.c log.c main.c xml.c
SRCS+= azure.c cloudinit.c opennebula.c openstack.c SRCS+= azure.c cloudinit.c opennebula.c openstack.c
SRCS+= growdisk.c
BINDIR= /usr/local/libexec BINDIR= /usr/local/libexec
MANDIR= /usr/local/man/man MANDIR= /usr/local/man/man

View File

@ -23,6 +23,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm cloud-agent .Nm cloud-agent
.Op Fl nuv .Op Fl nuv
.Op Fl r Ar rootdisk
.Op Fl t Ar timeout .Op Fl t Ar timeout
.Op Fl U Ar username .Op Fl U Ar username
.Ar interface .Ar interface
@ -53,6 +54,10 @@ configuration.
Using Using
.Dq root .Dq root
is supported, but not recommended. is supported, but not recommended.
.It Fl r Ar rootdisk
Automatically grow the last
.Ox
FFS partition of the root disk to use all the available space.
.It Fl u .It Fl u
Deprovision and unconfigure the system. Deprovision and unconfigure the system.
This deletes keys, passwords, and logs files without asking for permission. This deletes keys, passwords, and logs files without asking for permission.
@ -64,11 +69,12 @@ Enable
.Nm .Nm
in the in the
.Xr hostname.if 5 .Xr hostname.if 5
of the VM's primary networking interface: of the VM's primary networking interface and automatically the last
partition of the root disk:
.Bd -literal -offset indent .Bd -literal -offset indent
# cat /etc/hostname.hvn0 # cat /etc/hostname.hvn0
dhcp dhcp
!/usr/local/libexec/cloud-agent "\e$if" !/usr/local/libexec/cloud-agent -r sd0 "\e$if"
.Ed .Ed
.Sh FILES .Sh FILES
.Bl -tag -width "/usr/local/libexec/cloud-agentX" -compact .Bl -tag -width "/usr/local/libexec/cloud-agentX" -compact

149
agent/growdisk.c Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2019 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h> /* DEV_BSIZE */
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/dkio.h>
#define DKTYPENAMES
#include <sys/disklabel.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <util.h>
#include <err.h>
#include "main.h"
static uint16_t dkcksum(struct disklabel *);
static uint16_t
dkcksum(struct disklabel *lp)
{
uint16_t *start, *end, sum;
start = (uint16_t *)lp;
end = (uint16_t *)&lp->d_partitions[lp->d_npartitions];
for (sum = 0; start < end;)
sum ^= *start++;
return (sum);
}
int
growdisk(struct system_config *sc)
{
char c, last_part = 0, *out, *path = NULL;
int ret = -1, i, errfd, outfd;
struct partition *pp, *p = NULL;
struct disklabel lp;
int fd;
uint16_t cksum;
/*
* Grow the OpenBSD MBR partition
*/
/* XXX this is a bit ugly but easier to do */
if (shellout("e 3\n\n\n\n*\nw\nq\n", &out,
"fdisk", "-e", sc->sc_rootdisk, NULL) != 0) {
log_warnx("failed to grow OpenBSD partition");
return (-1);
}
free(out);
/*
* Grow the last partition in the disklabel
*/
if ((fd = opendev(sc->sc_rootdisk,
O_RDWR, OPENDEV_PART, NULL)) == -1) {
log_warn("failed to open %s", sc->sc_rootdisk);
return (-1);
}
if (ioctl(fd, DIOCGDINFO, &lp) == -1) {
log_warn("failed to get disklabel");
goto done;
}
if (lp.d_magic != DISKMAGIC || lp.d_magic2 != DISKMAGIC) {
log_warnx("invalid disklabel magic bytes");
goto done;
}
cksum = lp.d_checksum;
lp.d_checksum = 0;
if (dkcksum(&lp) != cksum) {
log_warnx("invalid disklabel checksum");
goto done;
}
pp = lp.d_partitions;
for (i = 0, pp = lp.d_partitions; i < lp.d_npartitions; i++, pp++) {
if (!DL_GETPSIZE(pp))
continue;
c = 'a' + i;
if (pp->p_fstype == FS_BSDFFS) {
last_part = c;
p = pp;
}
}
if (last_part == 0) {
log_warnx("last BSD partition not found");
goto done;
}
/* Update OpenBSD boundaries */
DL_SETBEND(&lp, DL_GETDSIZE(&lp) - DL_GETBSTART(&lp));
/* Update the size of the last partition */
DL_SETPSIZE(p, DL_GETBEND(&lp) - DL_GETPOFFSET(p));
lp.d_checksum = dkcksum(&lp);
if (ioctl(fd, DIOCWDINFO, &lp) == -1) {
log_warn("failed to write disklabel");
goto done;
}
/*
* Grow the filesystem
*/
if (asprintf(&path, "/dev/%s%c", sc->sc_rootdisk, last_part) == -1)
goto done;
errfd = disable_output(sc, STDERR_FILENO);
outfd = disable_output(sc, STDOUT_FILENO);
(void)shell("umount", "-f", path, NULL);
(void)shell("growfs", "-yq", path, NULL);
if ((ret = shell("fsck", "-y", path, NULL)) != 0)
ret = -1;
enable_output(sc, STDERR_FILENO, errfd);
enable_output(sc, STDOUT_FILENO, outfd);
ret = 0;
done:
free(path);
close(fd);
return (ret);
}

View File

@ -42,17 +42,18 @@
#include "main.h" #include "main.h"
#include "xml.h" #include "xml.h"
__dead void usage(void); __dead void usage(void);
static struct system_config *agent_init(const char *, int, int); static struct system_config
static int agent_configure(struct system_config *); *agent_init(const char *, const char *, int, int);
static int agent_network(struct system_config *); static int agent_configure(struct system_config *);
static void agent_free(struct system_config *); static int agent_network(struct system_config *);
static int agent_pf(struct system_config *, int); static void agent_free(struct system_config *);
static int agent_userdata(const unsigned char *, size_t); static int agent_pf(struct system_config *, int);
static void agent_unconfigure(void); static int agent_userdata(const unsigned char *, size_t);
static char *metadata_parse(char *, size_t, enum strtype); static void agent_unconfigure(void);
static char *metadata_parse(char *, size_t, enum strtype);
static int agent_timeout; static int agent_timeout;
int int
shell(const char *arg, ...) shell(const char *arg, ...)
@ -306,7 +307,7 @@ get_word(const unsigned char *ptr, size_t len)
} }
static struct system_config * static struct system_config *
agent_init(const char *ifname, int dryrun, int timeout) agent_init(const char *ifname, const char *rootdisk, int dryrun, int timeout)
{ {
struct system_config *sc; struct system_config *sc;
int fd, ret; int fd, ret;
@ -318,6 +319,7 @@ agent_init(const char *ifname, int dryrun, int timeout)
sc->sc_cdrom = "/dev/cd0c"; sc->sc_cdrom = "/dev/cd0c";
sc->sc_dryrun = dryrun ? 1 : 0; sc->sc_dryrun = dryrun ? 1 : 0;
sc->sc_timeout = agent_timeout = timeout < 1 ? -1 : timeout * 1000; sc->sc_timeout = agent_timeout = timeout < 1 ? -1 : timeout * 1000;
sc->sc_rootdisk = rootdisk;
TAILQ_INIT(&sc->sc_pubkeys); TAILQ_INIT(&sc->sc_pubkeys);
TAILQ_INIT(&sc->sc_netaddrs); TAILQ_INIT(&sc->sc_netaddrs);
@ -1089,8 +1091,8 @@ usage(void)
{ {
extern char *__progname; extern char *__progname;
fprintf(stderr, "usage: %s [-nuv] [-t 3] [-U puffy] interface\n", fprintf(stderr, "usage: %s [-nuv] [-r rootdisk] [-t 3] [-U puffy] "
__progname); "interface\n", __progname);
exit(1); exit(1);
} }
@ -1130,19 +1132,19 @@ main(int argc, char *const *argv)
struct system_config *sc; struct system_config *sc;
int verbose = 0, dryrun = 0, unconfigure = 0; int verbose = 0, dryrun = 0, unconfigure = 0;
int ch, ret, timeout = CONNECT_TIMEOUT; int ch, ret, timeout = CONNECT_TIMEOUT;
const char *error = NULL; const char *error = NULL, *rootdisk = NULL;
char *args, *username = NULL; char *args, *username = NULL;
if ((args = get_args(argc, argv)) == NULL) if ((args = get_args(argc, argv)) == NULL)
fatalx("failed to save args"); fatalx("failed to save args");
while ((ch = getopt(argc, argv, "nvt:U:u")) != -1) { while ((ch = getopt(argc, argv, "nr:t:U:uv")) != -1) {
switch (ch) { switch (ch) {
case 'n': case 'n':
dryrun = 1; dryrun = 1;
break; break;
case 'v': case 'r':
verbose += 2; rootdisk = optarg;
break; break;
case 't': case 't':
timeout = strtonum(optarg, -1, 86400, &error); timeout = strtonum(optarg, -1, 86400, &error);
@ -1156,6 +1158,9 @@ main(int argc, char *const *argv)
case 'u': case 'u':
unconfigure = 1; unconfigure = 1;
break; break;
case 'v':
verbose += 2;
break;
default: default:
usage(); usage();
} }
@ -1176,11 +1181,18 @@ main(int argc, char *const *argv)
if (argc != 1) if (argc != 1)
usage(); usage();
if (pledge("stdio cpath rpath wpath exec proc dns inet", NULL) == -1) if (pledge(rootdisk == NULL ?
"stdio cpath rpath wpath exec proc dns inet" :
"stdio cpath rpath wpath exec proc dns inet disklabel",
NULL) == -1)
fatal("pledge"); fatal("pledge");
if ((sc = agent_init(argv[0], dryrun, timeout)) == NULL) if ((sc = agent_init(argv[0], rootdisk, dryrun, timeout)) == NULL)
fatalx("agent"); fatalx("agent");
if (rootdisk != NULL && growdisk(sc) == -1)
fatalx("failed to grow %s", rootdisk);
sc->sc_args = args; sc->sc_args = args;
if (username != NULL) { if (username != NULL) {
free(sc->sc_username); free(sc->sc_username);

View File

@ -82,6 +82,7 @@ struct system_config {
const char *sc_ovfenv; const char *sc_ovfenv;
const char *sc_interface; const char *sc_interface;
const char *sc_cdrom; const char *sc_cdrom;
const char *sc_rootdisk;
int sc_mount; int sc_mount;
struct source sc_addr; struct source sc_addr;
@ -129,6 +130,9 @@ int opennebula(struct system_config *);
/* openstack.c */ /* openstack.c */
int openstack(struct system_config *); int openstack(struct system_config *);
/* growdisk.c */
int growdisk(struct system_config *);
/* main.c */ /* main.c */
int shell(const char *, ...); int shell(const char *, ...);
int shellout(const char *, char **, const char *, ...); int shellout(const char *, char **, const char *, ...);