Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

OS-986 modify KVM zone startup to not need fork and to dump zone priv…

…ileges to the log.
  • Loading branch information...
commit dd510fe78ed5a26f5d409d987c48dc3e43a83056 1 parent b76ebeb
@joshwilsdon joshwilsdon authored
View
1  .gitignore
@@ -8,6 +8,7 @@
/src/disk_size
/src/removable_disk
/src/disklist
+/src/qemu-exec
/src/zoneevent
/src/vm/tests.tar.gz
/src/node-kstat/.lock-wscript
View
9 src/Makefile
@@ -1,5 +1,5 @@
CC=gcc
-CFLAGS=-Wall
+CFLAGS=-Wall -Wextra
TARGETS=bootparams diskinfo disklist removable_disk disk_size \
node-kstat/build/Release/kstat.node zoneevent \
node-expat/build/Release/node-expat.node \
@@ -7,7 +7,7 @@ TARGETS=bootparams diskinfo disklist removable_disk disk_size \
node-zsock/build/Release/zsock_bindings.node \
node-zutil/build/Release/zutil_bindings.node \
-SMARTDC_TARGETS=has_hvx
+SMARTDC_TARGETS=has_hvx qemu-exec
DESTDIR=../proto
NODE_WAF=$(PWD)/../proto/usr/bin/node-waf
@@ -66,6 +66,9 @@ disk_size: disk_size.c
has_hvx: has_hvx.c
$(CC) $(CFLAGS) -o $@ $^
+qemu-exec: qemu-exec.c
+ $(CC) $(CFLAGS) -o $@ $^
+
node-kstat/build/Release/kstat.node: node-kstat/kstat.cc $(NODE_WAF)
(cd node-kstat && $(NODE_WAF) configure && $(NODE_WAF) build)
@@ -92,7 +95,7 @@ zoneevent: zoneevent.c
gcc -Wall -W -o zoneevent zoneevent.c -lnvpair -lsysevent
clean:
- @rm -f $(TARGETS)
+ @rm -f $(TARGETS) $(SMARTDC_TARGETS)
(cd node-kstat && $(NODE_WAF) clean)
(cd node-expat && $(NODE_WAF) clean)
(cd node-syslog && $(NODE_WAF) clean)
View
1  src/manifest
@@ -76,6 +76,7 @@ f usr/lib/amd64/libiostream.so.1 0755 root bin
d smartdc 0555 root bin
d smartdc/bin 0555 root bin
f smartdc/bin/has_hvx 0555 root bin
+f smartdc/bin/qemu-exec 0555 root bin
f usr/bin/sysinfo 0555 root bin
f usr/bin/bootparams 0555 root bin
f usr/bin/diskinfo 0555 root bin
View
164 src/qemu-exec.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ *
+ * This tool exists to exec qemu after rotating the /tmp/vm.log.* files and
+ * sending all output to /tmp/vm.log. It also dumps the zone's privileges to
+ * the log for verification.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <priv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define LOG_FILE "/tmp/vm.log"
+#define LOG_FILE_PATTERN "/tmp/vm.log.%u"
+
+void dump_args(int argc, char **argv);
+void dump_privs(void);
+void exec_next(int argc, char **argv);
+void redirect_output(void);
+void rotate_logs(void);
+
+int
+main(int argc, char **argv)
+{
+ if (argc < 2) {
+ (void) fprintf(stderr, "Usage: %s <command> ...\n", argv[0]);
+ exit(1);
+ }
+
+ rotate_logs();
+ redirect_output();
+ dump_privs();
+ dump_args(argc, argv);
+
+ /* print the header for the output from the program we exec (pre-flush) */
+ (void) puts("=== OUTPUT ===");
+
+ /* flush before next cmd takes over */
+ (void) fflush(stdout);
+ (void) fflush(stderr);
+
+ exec_next(argc, argv);
+
+ /* if we got here, we failed */
+ (void) fprintf(stderr, "FATAL: execvp() failed.\n");
+ exit(1);
+}
+
+void
+rotate_logs(void)
+{
+ unsigned int i;
+ char old_filename[] = LOG_FILE_PATTERN;
+ char new_filename[] = LOG_FILE_PATTERN;
+
+ /* rename:
+ *
+ * log.8 -> log.9
+ * ...
+ * log.0 -> log.1
+ *
+ */
+ for (i=9; i>0; i--) {
+ if (snprintf((char *)&old_filename, strlen(LOG_FILE_PATTERN),
+ LOG_FILE_PATTERN, i - 1) < 0) {
+
+ perror("Warning, failed to build old filename string");
+ continue;
+ }
+ if (snprintf((char *)&new_filename, strlen(LOG_FILE_PATTERN),
+ LOG_FILE_PATTERN, i) < 0) {
+
+ perror("Warning, failed to build new filename string");
+ continue;
+ }
+ if (rename(old_filename, new_filename)) {
+ perror(old_filename);
+ }
+ }
+
+ /* rename: log -> log.0 */
+ if (snprintf((char *)&new_filename, strlen(LOG_FILE_PATTERN),
+ LOG_FILE_PATTERN, 0) < 0) {
+
+ perror("Warning, failed to build new filename string");
+ return;
+ }
+ if (rename(LOG_FILE, new_filename)) {
+ perror(LOG_FILE);
+ }
+
+ return;
+}
+
+void
+redirect_output(void)
+{
+ int fd;
+
+ fd = open(LOG_FILE, O_WRONLY | O_CREAT, 0644);
+ if (fd >= 0) {
+ if (dup2(fd, 1) < 0) {
+ perror("Warning, dup2(stdout) failed");
+ }
+ if (dup2(fd, 2) < 0) {
+ perror("Warning, dup2(stderr) failed");
+ }
+ }
+
+ return;
+}
+
+void
+dump_privs(void)
+{
+ const char *pname;
+ int i;
+
+ priv_set_t *pset = priv_str_to_set("zone", ",", NULL);
+ if (pset == NULL) {
+ (void) fprintf(stderr, "unable to create priv_set for 'zone'\n");
+ return;
+ }
+ (void) puts("== Zone privileges ==");
+ for (i = 0; ((pname = priv_getbynum(i++)) != NULL); ) {
+ if (priv_ismember(pset, pname)) {
+ (void) puts(pname);
+ }
+ }
+
+ return;
+}
+
+void
+dump_args(int argc, char **argv)
+{
+ int i;
+
+ (void) puts("=== ARGV ===");
+ for (i = 0; i < argc; i++) {
+ (void) puts(argv[i]);
+ }
+
+ return;
+}
+
+void
+exec_next(int argc, char **argv)
+{
+ argv++;
+ argc--;
+
+ execvp(*argv, argv);
+
+ /* if we got here we failed. */
+ return;
+}
View
12 src/vm/node_modules/VM.js
@@ -3614,17 +3614,15 @@ function startVM(vmobj, extra, callback)
// This actually creates the qemu process
script = '#!/usr/bin/bash\n\n'
- + 'for i in {9..1}; do mv -f /tmp/vm.log.$((${i} - 1)) '
- + '/tmp/vm.log.${i};'
- + ' done\n'
- + 'mv -f /tmp/vm.log /tmp/vm.log.0\n\n'
- + 'exec >/tmp/vm.log 2>&1\n\n'
+ + 'exec >/tmp/vm.startvm.log 2>&1\n\n'
+ 'set -o xtrace\n\n'
+ 'if [[ -x /startvm.zone ]]; then\n'
- + ' exec /startvm.zone "' + cmdargs.join('" "')
+ + ' exec /smartdc/bin/qemu-exec /startvm.zone "'
+ + cmdargs.join('" "')
+ '" ' + qemu_opts + '\n'
+ 'else\n'
- + ' exec /smartdc/bin/qemu-system-x86_64 "' + cmdargs.join('" "')
+ + ' exec /smartdc/bin/qemu-exec /smartdc/bin/qemu-system-x86_64 "'
+ + cmdargs.join('" "')
+ '" ' + qemu_opts + '\n'
+ 'fi\n\n'
+ 'exit 1\n';
Please sign in to comment.
Something went wrong with that request. Please try again.