Add initial support for OpenNebula contextualization.
Thanks to datacenterlight.ch by ungleich glarus AG for providing access to their OpenNebula-based cloud.
This commit is contained in:
parent
ec87db177d
commit
d9899d488a
8 changed files with 449 additions and 25 deletions
209
agent/opennebula.c
Normal file
209
agent/opennebula.c
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fnmatch.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sha2.h>
|
||||
#include <err.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
int
|
||||
opennebula(struct system_config *sc)
|
||||
{
|
||||
FILE *fp;
|
||||
const char *delim = "\\\\\0", *errstr;
|
||||
char *line = NULL, *k, *v, *p, q;
|
||||
char *hname = NULL;
|
||||
size_t len, lineno = 0, i;
|
||||
int ret = -1;
|
||||
unsigned int unit;
|
||||
|
||||
/* Return silently without error */
|
||||
if ((fp = fopen("/mnt/context.sh", "r")) == NULL)
|
||||
goto done;
|
||||
|
||||
sc->sc_stack = "opennebula";
|
||||
|
||||
while ((line = fparseln(fp, &len, &lineno,
|
||||
delim, FPARSELN_UNESCALL)) != NULL) {
|
||||
/* key */
|
||||
k = line;
|
||||
|
||||
/* a context always starts with this header */
|
||||
if (lineno == 1) {
|
||||
ret = strcmp(line,
|
||||
"# Context variables generated by OpenNebula");
|
||||
if (ret != 0) {
|
||||
log_debug("%s: unsupported context", __func__);
|
||||
goto done;
|
||||
}
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
line[strcspn(line, "#")] = '\0';
|
||||
|
||||
/* value */
|
||||
if ((v = strchr(line, '=')) == NULL || *(v + 1) == '\0') {
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
*v++ = '\0';
|
||||
|
||||
/* value is quoted */
|
||||
q = *v;
|
||||
if (strspn(v, "\"'") == 0 || (p = strrchr(v, q)) == v) {
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
*v++ = '\0';
|
||||
*p = '\0';
|
||||
|
||||
/* continue if value is empty */
|
||||
if (*v == '\0') {
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug("%s: %s = %s", __func__, k, v);
|
||||
|
||||
if (strcasecmp("NETWORK", k) == 0) {
|
||||
if (strcasecmp("YES", v) == 0)
|
||||
sc->sc_network = 1;
|
||||
else if (strcasecmp("YES", v) == 0)
|
||||
sc->sc_network = 0;
|
||||
} else if (fnmatch("ETH*_*", k, 0) != FNM_NOMATCH) {
|
||||
/* Extract interface unit */
|
||||
if ((p = strdup(k + 3)) == NULL) {
|
||||
log_debug("%s: %s", __func__, k);
|
||||
goto done;
|
||||
}
|
||||
p[strcspn(p, "_")] = '\0';
|
||||
unit = strtonum(p, 0, UINT32_MAX, &errstr);
|
||||
free(p);
|
||||
if (errstr != NULL) {
|
||||
log_debug("%s: %s", __func__, k);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Get subkey */
|
||||
k += strcspn(k, "_") + 1;
|
||||
|
||||
if (strcasecmp("DNS", k) == 0) {
|
||||
/* We don't support per-interface DNS */
|
||||
for (p = v; *p != '\0'; v = p) {
|
||||
p = v + strcspn(v, " \t");
|
||||
*p++ = '\0';
|
||||
if ((ret = agent_addnetaddr(sc, 0,
|
||||
v, AF_UNSPEC, NET_DNS)) != 0)
|
||||
break;
|
||||
}
|
||||
} else if (strcasecmp("IP", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET, NET_IP);
|
||||
} else if (strcasecmp("MASK", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET, NET_MASK);
|
||||
} else if (strcasecmp("GATEWAY", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET, NET_GATEWAY);
|
||||
} else if (strcasecmp("IP6", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET6, NET_IP);
|
||||
} else if (strcasecmp("GATEWAY6", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET6, NET_GATEWAY);
|
||||
} else if (strcasecmp("PREFIX_LENGTH", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_INET6, NET_PREFIX);
|
||||
} else if (strcasecmp("MAC", k) == 0) {
|
||||
if (unit == 0 && hname == NULL) {
|
||||
/* Fake a hostname using the mac */
|
||||
if ((hname = p = calloc(1,
|
||||
strlen(v) + 3)) == NULL) {
|
||||
log_debug("%s: calloc",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
*p++ = 'v';
|
||||
*p++ = 'm';
|
||||
for (i = 0; i < strlen(v); i++) {
|
||||
if (!isalnum(v[i]))
|
||||
continue;
|
||||
*p++ = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_UNSPEC, NET_MAC);
|
||||
} else if (strcasecmp("MTU", k) == 0) {
|
||||
ret = agent_addnetaddr(sc, unit,
|
||||
v, AF_UNSPEC, NET_MTU);
|
||||
} else
|
||||
ret = 0;
|
||||
if (ret != 0) {
|
||||
log_debug("%s: failed to parse %s",
|
||||
__func__, k);
|
||||
goto done;
|
||||
}
|
||||
} else if (strcasecmp("SSH_PUBLIC_KEY", k) == 0) {
|
||||
if (agent_addpubkey(sc, v, NULL) != 0)
|
||||
log_warnx("failed to ssh pubkey");
|
||||
}
|
||||
|
||||
free(line);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
||||
/*
|
||||
* OpenNebula doesn't provide an instance id so we
|
||||
* calculate one using the hash of the context file.
|
||||
* This might break if the context is not consistent.
|
||||
*/
|
||||
if ((sc->sc_instance =
|
||||
calloc(1, SHA256_DIGEST_STRING_LENGTH)) == NULL ||
|
||||
SHA256File("/mnt/context.sh", sc->sc_instance) == NULL) {
|
||||
log_debug("%s: failed to calculate instance hash",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
log_debug("%s: context instance %s", __func__, sc->sc_instance);
|
||||
|
||||
/* Even the hostname is optional */
|
||||
if (hname != NULL) {
|
||||
free(sc->sc_hostname);
|
||||
sc->sc_hostname = hname;
|
||||
log_debug("%s: hostname %s", __func__, hname);
|
||||
}
|
||||
|
||||
line = NULL;
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
free(line);
|
||||
return (ret);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue