Add "-r rootdisk" growdisk support
This commit is contained in:
parent
a8490a757f
commit
8dfa3c843a
5 changed files with 193 additions and 21 deletions
|
@ -1,6 +1,7 @@
|
|||
PROG= cloud-agent
|
||||
SRCS= http.c json.c jsmn.c log.c main.c xml.c
|
||||
SRCS+= azure.c cloudinit.c opennebula.c openstack.c
|
||||
SRCS+= growdisk.c
|
||||
BINDIR= /usr/local/libexec
|
||||
MANDIR= /usr/local/man/man
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
.Sh SYNOPSIS
|
||||
.Nm cloud-agent
|
||||
.Op Fl nuv
|
||||
.Op Fl r Ar rootdisk
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl U Ar username
|
||||
.Ar interface
|
||||
|
@ -53,6 +54,10 @@ configuration.
|
|||
Using
|
||||
.Dq root
|
||||
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
|
||||
Deprovision and unconfigure the system.
|
||||
This deletes keys, passwords, and logs files without asking for permission.
|
||||
|
@ -64,11 +69,12 @@ Enable
|
|||
.Nm
|
||||
in the
|
||||
.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
|
||||
# cat /etc/hostname.hvn0
|
||||
dhcp
|
||||
!/usr/local/libexec/cloud-agent "\e$if"
|
||||
!/usr/local/libexec/cloud-agent -r sd0 "\e$if"
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/usr/local/libexec/cloud-agentX" -compact
|
||||
|
|
149
agent/growdisk.c
Normal file
149
agent/growdisk.c
Normal 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);
|
||||
}
|
32
agent/main.c
32
agent/main.c
|
@ -43,7 +43,8 @@
|
|||
#include "xml.h"
|
||||
|
||||
__dead void usage(void);
|
||||
static struct system_config *agent_init(const char *, int, int);
|
||||
static struct system_config
|
||||
*agent_init(const char *, const char *, int, int);
|
||||
static int agent_configure(struct system_config *);
|
||||
static int agent_network(struct system_config *);
|
||||
static void agent_free(struct system_config *);
|
||||
|
@ -306,7 +307,7 @@ get_word(const unsigned char *ptr, size_t len)
|
|||
}
|
||||
|
||||
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;
|
||||
int fd, ret;
|
||||
|
@ -318,6 +319,7 @@ agent_init(const char *ifname, int dryrun, int timeout)
|
|||
sc->sc_cdrom = "/dev/cd0c";
|
||||
sc->sc_dryrun = dryrun ? 1 : 0;
|
||||
sc->sc_timeout = agent_timeout = timeout < 1 ? -1 : timeout * 1000;
|
||||
sc->sc_rootdisk = rootdisk;
|
||||
TAILQ_INIT(&sc->sc_pubkeys);
|
||||
TAILQ_INIT(&sc->sc_netaddrs);
|
||||
|
||||
|
@ -1089,8 +1091,8 @@ usage(void)
|
|||
{
|
||||
extern char *__progname;
|
||||
|
||||
fprintf(stderr, "usage: %s [-nuv] [-t 3] [-U puffy] interface\n",
|
||||
__progname);
|
||||
fprintf(stderr, "usage: %s [-nuv] [-r rootdisk] [-t 3] [-U puffy] "
|
||||
"interface\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1130,19 +1132,19 @@ main(int argc, char *const *argv)
|
|||
struct system_config *sc;
|
||||
int verbose = 0, dryrun = 0, unconfigure = 0;
|
||||
int ch, ret, timeout = CONNECT_TIMEOUT;
|
||||
const char *error = NULL;
|
||||
const char *error = NULL, *rootdisk = NULL;
|
||||
char *args, *username = NULL;
|
||||
|
||||
if ((args = get_args(argc, argv)) == NULL)
|
||||
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) {
|
||||
case 'n':
|
||||
dryrun = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose += 2;
|
||||
case 'r':
|
||||
rootdisk = optarg;
|
||||
break;
|
||||
case 't':
|
||||
timeout = strtonum(optarg, -1, 86400, &error);
|
||||
|
@ -1156,6 +1158,9 @@ main(int argc, char *const *argv)
|
|||
case 'u':
|
||||
unconfigure = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose += 2;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
@ -1176,11 +1181,18 @@ main(int argc, char *const *argv)
|
|||
if (argc != 1)
|
||||
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");
|
||||
|
||||
if ((sc = agent_init(argv[0], dryrun, timeout)) == NULL)
|
||||
if ((sc = agent_init(argv[0], rootdisk, dryrun, timeout)) == NULL)
|
||||
fatalx("agent");
|
||||
|
||||
if (rootdisk != NULL && growdisk(sc) == -1)
|
||||
fatalx("failed to grow %s", rootdisk);
|
||||
|
||||
sc->sc_args = args;
|
||||
if (username != NULL) {
|
||||
free(sc->sc_username);
|
||||
|
|
|
@ -82,6 +82,7 @@ struct system_config {
|
|||
const char *sc_ovfenv;
|
||||
const char *sc_interface;
|
||||
const char *sc_cdrom;
|
||||
const char *sc_rootdisk;
|
||||
int sc_mount;
|
||||
|
||||
struct source sc_addr;
|
||||
|
@ -129,6 +130,9 @@ int opennebula(struct system_config *);
|
|||
/* openstack.c */
|
||||
int openstack(struct system_config *);
|
||||
|
||||
/* growdisk.c */
|
||||
int growdisk(struct system_config *);
|
||||
|
||||
/* main.c */
|
||||
int shell(const char *, ...);
|
||||
int shellout(const char *, char **, const char *, ...);
|
||||
|
|
Loading…
Reference in a new issue