From: Marcin Krol Date: Fri, 18 Mar 2016 12:47:04 +0000 (+0000) Subject: - dropped, TLD doesn't support vserver X-Git-Url: https://git.tld-linux.org/?a=commitdiff_plain;h=66569754694fa4132d3718d08fdd22aa941a4966;p=packages%2Flibvirt.git - dropped, TLD doesn't support vserver --- diff --git a/vserver.patch b/vserver.patch deleted file mode 100644 index 42c4fe2..0000000 --- a/vserver.patch +++ /dev/null @@ -1,2744 +0,0 @@ -https://www.redhat.com/archives/libvir-list/2008-January/msg00097.html - -From: "Daniel Hokka Zakrisson" -To: libvir-list redhat com -Subject: [Libvir] [PATCH] Linux-VServer support -Date: Wed, 9 Jan 2008 22:51:20 +0100 (CET) - -This patch implements support for Linux-VServer guests. It is currently -missing vcpu and console support, and the necessary virsh code to support -it, but is otherwise pretty feature complete. - -This is an XML dump from one of my guests: - - lenny - 19e12957-261a-5a06-d6d0-89917d6d439f - 2048000 - - lenny.test - vserver - - - - - - - - - - - - - - - - - - - - - - - --- -Daniel Hokka Zakrisson ---- libvirt-1.2.3/configure.ac~ 2014-04-06 12:21:22.000000000 +0300 -+++ libvirt-1.2.3/configure.ac 2014-04-06 12:22:55.249258975 +0300 -@@ -546,6 +546,10 @@ - [AS_HELP_STRING([--with-parallels], - [add Parallels Cloud Server support @<:@default=check@:>@])]) - m4_divert_text([DEFAULTS], [with_parallels=check]) -+AC_ARG_WITH([vserver], -+ [AS_HELP_STRING([--with-vserver], -+ [add Linux-VServer support @<:@default=check@:>@])]) -+m4_divert_text([DEFAULTS], [with_vserver=check]) - AC_ARG_WITH([test], - [AS_HELP_STRING([--with-test], - [add test driver support @<:@default=yes@:>@])]) -@@ -991,6 +991,39 @@ - fi - fi - -+if test "$with_vserver" = "yes" ; then -+ AC_CHECK_LIB(vserver, [vc_rlimit_stat],, [with_vserver=no]) -+ AC_CHECK_TYPES([xid_t, nid_t, tag_t]) -+ AC_CHECK_HEADER(vserver.h,, [with_vserver=no], [AC_INCLUDES_DEFAULT() -+#ifndef HAVE_XID_T -+typedef unsigned int xid_t; -+#endif -+#ifndef HAVE_NID_T -+typedef unsigned int nid_t; -+#endif -+#ifndef HAVE_TAG_T -+typedef unsigned int tag_t; -+#endif]) -+ -+ AC_MSG_CHECKING([for vserver configuration directory]) -+ VSERVER_CONF_DIR=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \ -+ vserver-info - SYSINFO | sed -n 's/^.*cfg-Directory:.//p'` -+ AC_MSG_RESULT([$VSERVER_CONF_DIR]) -+ AC_DEFINE_UNQUOTED([VSERVER_CONF_DIR], ["$VSERVER_CONF_DIR"], -+ [The default path to the Linux-VServer configuration files]) -+ -+ AC_MSG_CHECKING([for the vserver program]) -+ PROG_VSERVER=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \ -+ which vserver 2> /dev/null` || with_vserver=no -+ AC_MSG_RESULT([$PROG_VSERVER]) -+ AC_DEFINE_UNQUOTED([PROG_VSERVER], ["$PROG_VSERVER"], -+ [The path to the vserver program]) -+ -+ if test "$with_vserver" = "yes" ; then -+ LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_VSERVER" -+ fi -+fi -+ - - dnl - dnl check for kernel headers required by src/bridge.c -@@ -2759,6 +2759,7 @@ - AC_MSG_NOTICE([ ESX: $with_esx]) - AC_MSG_NOTICE([ Hyper-V: $with_hyperv]) - AC_MSG_NOTICE([Parallels: $with_parallels]) -+AC_MSG_NOTICE([ VServer: $with_vserver]) - LIBVIRT_DRIVER_RESULT_BHYVE - AC_MSG_NOTICE([ Test: $with_test]) - AC_MSG_NOTICE([ Remote: $with_remote]) ---- libvirt-1.1.1/include/libvirt/virterror.h~ 2013-07-24 03:23:07.000000000 +0300 -+++ libvirt-1.1.1/include/libvirt/virterror.h 2013-09-01 00:07:44.097192613 +0300 -@@ -121,6 +121,8 @@ - VIR_FROM_ACCESS = 55, /* Error from access control manager */ - VIR_FROM_SYSTEMD = 56, /* Error from systemd code */ - -+ VIR_FROM_VSERVER = 57, /* Error from Linux-VServer driver */ -+ - # ifdef VIR_ENUM_SENTINELS - VIR_ERR_DOMAIN_LAST - # endif ---- libvirt-1.2.3/src/driver.h~ 2014-03-27 12:35:00.000000000 +0200 -+++ libvirt-1.2.3/src/driver.h 2014-04-06 12:25:03.124800629 +0300 -@@ -48,6 +48,7 @@ - VIR_DRV_HYPERV = 15, - VIR_DRV_PARALLELS = 16, - VIR_DRV_BHYVE = 17, -+ VIR_DRV_VSERVER = 18, - } virDrvNo; - - ---- libvirt-1.1.1/src/libvirt.c~ 2013-09-01 00:20:50.000000000 +0300 -+++ libvirt-1.1.1/src/libvirt.c 2013-09-01 00:21:02.812830784 +0300 -@@ -94,6 +94,9 @@ - #ifdef WITH_PARALLELS - # include "parallels/parallels_driver.h" - #endif -+#ifdef WITH_VSERVER -+# include "server/vserver_driver.h" -+#endif - - #define VIR_FROM_THIS VIR_FROM_NONE - -@@ -479,6 +482,10 @@ - if (parallelsRegister() == -1) - goto error; - #endif -+#ifdef WITH_VSERVER -+ if (verversRegister() == -1) -+ goto error; -+#endif - #ifdef WITH_REMOTE - if (remoteRegister() == -1) - goto error; ---- libvirt-1.1.1/src/Makefile.am~ 2013-07-30 10:21:31.000000000 +0300 -+++ libvirt-1.1.1/src/Makefile.am 2013-09-01 00:11:19.080124997 +0300 -@@ -467,6 +467,7 @@ - $(NWFILTER_DRIVER_SOURCES) \ - $(OPENVZ_DRIVER_SOURCES) \ - $(PARALLELS_DRIVER_SOURCES) \ -+ $(VSERVER_DRIVER_SOURCES) \ - $(PHYP_DRIVER_SOURCES) \ - $(QEMU_DRIVER_SOURCES) \ - $(REMOTE_DRIVER_SOURCES) \ -@@ -727,6 +728,12 @@ - parallels/parallels_storage.c \ - parallels/parallels_network.c - -+VSERVER_DRIVER_SOURCES = \ -+ vserver/vserver_driver.h \ -+ vserver/vserver_driver.c \ -+ vserver/vserver_conf.h \ -+ vserver/vserver_conf.c -+ - NETWORK_DRIVER_SOURCES = \ - network/bridge_driver.h network/bridge_driver.c - ---- libvirt-1.2.3/src/util/virerror.c~ 2014-03-27 12:35:01.000000000 +0200 -+++ libvirt-1.2.3/src/util/virerror.c 2014-04-06 12:25:58.523869047 +0300 -@@ -127,6 +127,7 @@ - - "Access Manager", /* 55 */ - "Systemd", -+ "Vserver", - "Bhyve", - "Crypto", - ) ---- libvirt-0.4.0.orig/src/vserver/vserver_conf.c 1970-01-01 01:00:00.000000000 +0100 -+++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.c 2008-01-09 08:52:11.000000000 +0100 -@@ -0,0 +1,751 @@ -+/* -+ * Configuration handling for Linux-VServer guests -+ * -+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Daniel Hokka Zakrisson -+ */ -+ -+#ifdef WITH_VSERVER -+ -+#define _GNU_SOURCE -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define IN_VSERVER 1 -+#include "internal.h" -+#include "vserver_driver.h" -+#include "vserver_conf.h" -+#include "uuid.h" -+ -+static int -+readStr(char *dst, size_t len, const char *name, const char *setting) -+{ -+ char file[strlen(name) + strlen(setting) + 2]; -+ int fd; -+ ssize_t bytes; -+ char *p; -+ -+ sprintf(file, "%s/%s", name, setting); -+ -+ /* a non-existant file is not a failure */ -+ *dst = '\0'; -+ if ((fd = open(file, O_RDONLY)) == -1) -+ return 1; -+ -+ if ((bytes = read(fd, dst, len - 1)) == -1) { -+ close(fd); -+ return -1; -+ } -+ close(fd); -+ -+ dst[bytes] = '\0'; -+ -+ if ((p = strchr(dst, '\n')) != NULL) -+ *p = '\0'; -+ -+ return 0; -+} -+ -+static int -+readLong(void *v_dst, const char *name, const char *setting) -+{ -+ char buf[128], *endptr; -+ int ret; -+ long *dst = v_dst; -+ -+ ret = readStr(buf, sizeof(buf), name, setting); -+ if (ret) -+ return ret; -+ -+ *dst = strtol(buf, &endptr, 0); -+ if (endptr && *endptr != '\0') -+ return -1; -+ -+ return 0; -+} -+ -+static int -+readInt(void *v_dst, const char *name, const char *setting) -+{ -+ long val; -+ int *dst = v_dst; -+ int ret; -+ -+ ret = readLong(&val, name, setting); -+ if (ret) -+ return ret; -+ -+ *dst = (int) val; -+ -+ return 0; -+} -+ -+static int -+readBool(char *dst, const char *name, const char *setting) -+{ -+ char file[strlen(name) + strlen(setting) + 2]; -+ -+ sprintf(file, "%s/%s", name, setting); -+ -+ *dst = access(file, F_OK) != -1; -+ -+ return 0; -+} -+ -+int -+vserverWriteToConfig(struct vserver_guest *guest, const char *filename, -+ const char *format, ...) -+{ -+ char path[strlen(guest->path) + 1 + strlen(filename) + 1]; -+ va_list va; -+ char value[1024]; -+ int fd; -+ ssize_t len, off, ret; -+ char *dir; -+ -+ sprintf(path, "%s/%s", guest->path, filename); -+ -+ /* ensure the directory exists */ -+ dir = strrchr(path, '/'); -+ *dir = '\0'; -+ if (mkdir(path, 0755) && errno != EEXIST) -+ return -1; -+ *dir = '/'; -+ -+ va_start(va, format); -+ if (strcmp(format, "%b") == 0) { -+ /* bool, this is a special case */ -+ if (va_arg(va, int)) { -+ *value = '\0'; -+ len = 0; -+ } -+ else { -+ if (unlink(path) == -1 && errno != ENOENT) -+ return -1; -+ else -+ return 0; -+ } -+ } -+ else -+ len = vsnprintf(value, sizeof(value), format, va); -+ va_end(va); -+ -+ fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0644); -+ if (fd == -1) -+ return -1; -+ -+ for (off = 0; off < len; off += ret) { -+ ret = write(fd, value + off, len - off); -+ if (ret == -1) { -+ close(fd); -+ return -1; -+ } -+ } -+ -+ if (close(fd) == -1) -+ return -1; -+ return 0; -+} -+ -+#define WRITE(...) if (vserverWriteToConfig(guest, __VA_ARGS__) == -1) \ -+ return -1 -+#define WRITE_SCHED_VAL(sched, file, mask, format, value) \ -+ if ((sched)->set_mask & mask) { \ -+ WRITE(file, format, value); \ -+ } -+#define WRITE_SCHED(dir, sched) \ -+ do { \ -+ WRITE_SCHED_VAL(sched, dir "/fill-rate", \ -+ VC_VXSM_FILL_RATE, "%u\n", \ -+ (sched)->fill_rate); \ -+ WRITE_SCHED_VAL(sched, dir "/interval", \ -+ VC_VXSM_INTERVAL, "%u\n", \ -+ (sched)->interval); \ -+ WRITE_SCHED_VAL(sched, dir "/fill-rate2", \ -+ VC_VXSM_FILL_RATE2, "%u\n", \ -+ (sched)->fill_rate2); \ -+ WRITE_SCHED_VAL(sched, dir "/interval2", \ -+ VC_VXSM_INTERVAL2, "%u\n", \ -+ (sched)->interval2); \ -+ WRITE_SCHED_VAL(sched, dir "/tokens-min", \ -+ VC_VXSM_TOKENS_MIN, "%u\n", \ -+ (sched)->tokens_min); \ -+ WRITE_SCHED_VAL(sched, dir "/tokens-max", \ -+ VC_VXSM_TOKENS_MAX, "%u\n", \ -+ (sched)->tokens_max); \ -+ WRITE_SCHED_VAL(sched, dir "/priority-bias", \ -+ VC_VXSM_PRIO_BIAS, "%u\n", \ -+ (sched)->priority_bias); \ -+ WRITE(dir "/idle-time", "%b", \ -+ (sched)->set_mask & VC_VXSM_IDLE_TIME); \ -+ } while (0) -+#define WRITE_IP(filename, v4var, v6var) \ -+ strcpy(file, filename); \ -+ switch (type) { \ -+ case VC_NXA_TYPE_IPV4: \ -+ inet_ntop(AF_INET, (v4var), buf, sizeof(buf)); \ -+ break; \ -+ case VC_NXA_TYPE_IPV6: \ -+ inet_ntop(AF_INET6, (v6var), buf, sizeof(buf)); \ -+ break; \ -+ } \ -+ WRITE(dir, "%s\n", buf); -+ -+static int -+writeInterfaces(struct vserver_guest *guest) -+{ -+ char name[strlen(guest->path) + sizeof("/interfaces/XXXXXX/prefix")], -+ *dir, *file; -+ char buf[128]; -+ struct vserver_ip *ip; -+ unsigned int i; -+ -+ snprintf(name, sizeof(name), "%s/interfaces", guest->path); -+ if (vserverRunCommand(0, "rm", "-fr", name, NULL) != 0) -+ return -1; -+ if (mkdir(name, 0755) == -1) -+ return -1; -+ -+ dir = name + strlen(guest->path) + 1; -+ for (ip = guest->ips, i = 0; ip; ip = ip->next, i++) { -+ uint16_t type; -+ -+ /* Yeah right... */ -+ if (i > 999999) { -+ errno = EOVERFLOW; -+ return -1; -+ } -+ -+ file = dir; -+ file += snprintf(dir, sizeof(name) - (dir - name), "interfaces/%u", i); -+ if (mkdir(name, 0755) == -1) -+ return -1; -+ -+ type = ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6); -+ -+ strcpy(file, "/prefix"); -+ WRITE(dir, "%u\n", ip->addr.vna_prefix); -+ -+ if (*ip->interface) { -+ strcpy(file, "/dev"); -+ WRITE(dir, "%s\n", ip->interface); -+ } -+ else { -+ strcpy(file, "/nodev"); -+ WRITE(dir, "%b", 1); -+ } -+ -+ WRITE_IP("/ip", &ip->addr.vna_v4_ip, &ip->addr.vna_v6_ip); -+ if (ip->addr.vna_type & VC_NXA_TYPE_RANGE) { -+ WRITE_IP("/ip2", &ip->addr.vna_v4_ip2, &ip->addr.vna_v6_ip2); -+ } -+ if (ip->addr.vna_type & (VC_NXA_TYPE_RANGE|VC_NXA_TYPE_MASK)) { -+ WRITE_IP("/mask", &ip->addr.vna_v4_mask, &ip->addr.vna_v6_mask); -+ } -+ } -+ return 0; -+} -+ -+static int -+writeFstab(struct vserver_guest *guest) -+{ -+ FILE *fp; -+ struct vserver_fstab *ent; -+ char file[strlen(guest->path) + sizeof("/fstab")]; -+ -+ sprintf(file, "%s/fstab", guest->path); -+ fp = fopen(file, "w"); -+ if (fp == NULL) -+ return -1; -+ -+ for (ent = guest->fstab; ent; ent = ent->next) { -+ if (!(ent->flags & VSERVER_FSTAB_OUTPUT)) -+ continue; -+ fprintf(fp, "%s\t%s\t%s\t%s\t%s\n", ent->source, ent->target, -+ ent->fstype, ent->options, (ent->rest ? ent->rest : "")); -+ } -+ -+ if (fclose(fp) == -1) -+ return -1; -+ -+ return 0; -+} -+ -+int -+vserverWriteGuestToConfig(struct vserver_guest *guest) -+{ -+ char buf[128]; -+ -+ WRITE("context", "%u\n", guest->xid); -+ WRITE("name", "%s\n", guest->name); -+ virUUIDFormat(guest->uuid, buf); -+ WRITE("uuid", "%s\n", buf); -+ if (*guest->uts.hostname) -+ WRITE("uts/nodename", "%s\n", guest->uts.hostname); -+ if (*guest->uts.machine) -+ WRITE("uts/machine", "%s\n", guest->uts.machine); -+ if (*guest->uts.release) -+ WRITE("uts/release", "%s\n", guest->uts.release); -+ if (*guest->uts.version) -+ WRITE("uts/version", "%s\n", guest->uts.version); -+ if (guest->rss_hard > 0) -+ WRITE("rlimits/rss.hard", "%lu\n", guest->rss_hard); -+ WRITE("apps/init/mark", (guest->autostart ? "default\n" : "\n")); -+ WRITE_SCHED("sched", &guest->sched); -+ -+ if (writeInterfaces(guest) == -1) -+ return -1; -+ -+ if (writeFstab(guest) == -1) -+ return -1; -+ -+ return 0; -+} -+#undef WRITE_IP -+#undef WRITE_SCHED -+#undef WRITE_SCHED_VAL -+#undef WRITE -+ -+static int -+parseInterfaces(struct vserver_guest *guest, const char *directory) -+{ -+ DIR *interfaces; -+ struct dirent *interface; -+ struct vserver_ip *ip = NULL; -+ char ipath[256], *subdir; -+ size_t spare; -+ char s_ip[48], s_prefix[4], s_mask[48], s_dev[32], s_ip2[48]; -+ -+ subdir = ipath; -+ subdir += snprintf(ipath, sizeof(ipath), "%s/%s", guest->name, directory); -+ spare = sizeof(ipath) - (subdir - ipath); -+ -+ interfaces = opendir(ipath); -+ if (!interfaces) -+ return 0; -+ -+ while ((interface = readdir(interfaces)) != NULL) { -+ if (*interface->d_name == '.') -+ continue; -+ /* would overflow */ -+ if (strlen(interface->d_name) + sizeof("//disabled") > spare) -+ continue; -+ -+ snprintf(subdir, spare, "/%s/disabled", interface->d_name); -+ if (access(ipath, F_OK) != -1) -+ continue; -+ -+ snprintf(subdir, spare, "/%s", interface->d_name); -+ *s_mask = '\0'; -+ *s_prefix = '\0'; -+ if (readStr(s_ip, sizeof(s_ip), ipath, "ip") == 0 && -+ (readStr(s_prefix, sizeof(s_prefix), ipath, "prefix") == 0 || -+ readStr(s_mask, sizeof(s_mask), ipath, "mask") == 0)) { -+ if (readStr(s_dev, sizeof(s_dev), ipath, "dev") != 0) -+ *s_dev = '\0'; -+ if (readStr(s_ip2, sizeof(s_ip2), ipath, "ip2") != 0) -+ *s_ip2 = '\0'; -+ } -+ else -+ continue; -+ -+ if (!ip) -+ guest->ips = ip = calloc(1, sizeof(*ip)); -+ else { -+ ip->next = calloc(1, sizeof(*ip)); -+ ip = ip->next; -+ } -+ if (!ip) -+ goto cleanup; -+ -+ strcpy(ip->interface, s_dev); -+ -+ if (inet_pton(AF_INET6, s_ip, &ip->addr.vna_v6_ip) > 0) -+ ip->addr.vna_type = VC_NXA_TYPE_IPV6; -+ else if (inet_pton(AF_INET, s_ip, &ip->addr.vna_v4_ip) > 0) -+ ip->addr.vna_type = VC_NXA_TYPE_IPV4; -+ else -+ goto cleanup; -+ -+ if (ip->addr.vna_type == VC_NXA_TYPE_IPV6) { -+ if (*s_mask) { -+ if (inet_pton(AF_INET6, s_mask, &ip->addr.vna_v6_mask) <= 0) -+ goto cleanup; -+ } -+ if (*s_ip2) { -+ if (inet_pton(AF_INET6, s_ip2, &ip->addr.vna_v6_ip2) <= 0) -+ goto cleanup; -+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE; -+ } -+ else -+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR; -+ } -+ else if (ip->addr.vna_type == VC_NXA_TYPE_IPV4) { -+ if (*s_mask) { -+ if (inet_pton(AF_INET, s_mask, &ip->addr.vna_v4_mask) <= 0) -+ goto cleanup; -+ } -+ if (*s_ip2) { -+ if (inet_pton(AF_INET, s_ip2, &ip->addr.vna_v4_ip2) <= 0) -+ goto cleanup; -+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE; -+ } -+ else -+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR; -+ } -+ -+ if (*s_prefix) { -+ char *endptr; -+ ip->addr.vna_prefix = strtoul(s_prefix, &endptr, 0); -+ if (*endptr != '\n' && *endptr) -+ goto cleanup; -+ } -+ } -+ -+ closedir(interfaces); -+ return 0; -+ -+cleanup: -+ closedir(interfaces); -+ return -1; -+} -+ -+static inline char * -+endOfField(char *start) -+{ -+ char *end; -+ for (end = start; *(end - 1) != '\\' && -+ !isspace(*end) && -+ *end != '\0'; end++) -+ ; -+ return end; -+} -+ -+static inline char * -+startOfField(char *end) -+{ -+ char *start; -+ for (start = end + 1; isspace(*start) && -+ *start != '\0'; start++) -+ ; -+ return start; -+} -+ -+static const struct { -+ int mode; -+ const char *type; -+} source_types[] = { -+ { S_IFBLK, "block" }, -+ { S_IFREG, "file" }, -+ { S_IFDIR, "directory" }, -+}; -+ -+const char * -+vserverFindSourceType(const char *source) -+{ -+ struct stat st; -+ int mode, i; -+ if (stat(source, &st) == -1) -+ mode = -1; -+ else -+ mode = st.st_mode & S_IFMT; -+ for (i = 0; i < (sizeof(source_types) / sizeof(*source_types)); i++) { -+ if (mode == source_types[i].mode) -+ return source_types[i].type; -+ } -+ return NULL; -+} -+ -+static int -+parseFstab(struct vserver_guest *guest, const char *filename) -+{ -+ FILE *fp; -+ char buf[256], *start, *end; -+ struct vserver_fstab *ent = NULL; -+ char path[strlen(guest->name) + 2 + strlen(filename)]; -+ -+ sprintf(path, "%s/%s", guest->name, filename); -+ if ((fp = fopen(path, "r")) == NULL) -+ return 0; -+ -+ while (fgets(buf, sizeof(buf), fp) != NULL) { -+ if (!ent) -+ guest->fstab = ent = calloc(1, sizeof(*ent)); -+ else { -+ ent->next = calloc(1, sizeof(*ent)); -+ ent = ent->next; -+ } -+ if (!ent) -+ goto err; -+ -+ start = buf; -+ end = endOfField(start); -+ *end = '\0'; -+ ent->source = strdup(start); -+ ent->source_type = vserverFindSourceType(start); -+ -+ ent->flags |= VSERVER_FSTAB_OUTPUT; -+ if (ent->source_type) -+ ent->flags |= VSERVER_FSTAB_SHOW; -+ -+ start = startOfField(end); -+ end = endOfField(start); -+ *end = '\0'; -+ ent->target = strdup(start); -+ -+ start = startOfField(end); -+ end = endOfField(start); -+ *end = '\0'; -+ ent->fstype = strdup(start); -+ -+ start = startOfField(end); -+ end = endOfField(start); -+ if (*end != '\0') { -+ char *ptr; -+ ent->rest = strdup(end + 1); -+ ptr = strchr(ent->rest, '\n'); -+ if (ptr) -+ *ptr = '\0'; -+ } -+ else -+ ent->rest = NULL; -+ *end = '\0'; -+ ent->options = strdup(start); -+ -+ if (!ent->source || !ent->target || !ent->fstype || !ent->options) -+ goto err; -+ } -+ -+ fclose(fp); -+ return 0; -+ -+err: -+ fclose(fp); -+ return -1; -+} -+ -+virDrvOpenStatus -+vserverInitializeDriver(virConnectPtr conn, struct vserver_driver *driver, -+ const char *path) -+{ -+ struct vserver_guest *guest = NULL; -+ DIR *dp = NULL; -+ struct dirent *de; -+ int cwd; -+ const char *conf_dir = (*path ? path : VSERVER_CONF_DIR); -+ -+ if (driver->initialized == 1) -+ return VIR_DRV_OPEN_SUCCESS; -+ -+ driver->guests = NULL; -+ driver->inactive_guests = driver->active_guests = 0; -+ -+ cwd = open(".", O_RDONLY); -+ if (cwd == -1 || -+ chdir(conf_dir) == -1 || -+ (dp = opendir(".")) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_OPEN_FAILED, conf_dir); -+ goto error; -+ } -+ -+ while ((de = readdir(dp)) != NULL) { -+ char uuidstr[VIR_UUID_STRING_BUFLEN + 1]; -+ char mark[32]; -+ char tmp; -+ -+ if (*de->d_name == '.') -+ continue; -+ -+ if (driver->guests == NULL) -+ driver->guests = guest = calloc(1, sizeof(struct vserver_guest)); -+ else { -+ guest->next = calloc(1, sizeof(struct vserver_guest)); -+ guest = guest->next; -+ } -+ -+ if (!guest) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, -+ "vserver_guest"); -+ goto error; -+ } -+ -+ guest->path = calloc(strlen(conf_dir) + 1 + strlen(de->d_name) + 1, sizeof(char)); -+ if (!guest->path) -+ goto nomem; -+ sprintf(guest->path, "%s/%s", conf_dir, de->d_name); -+ -+#define CHECK(x) \ -+ if ((x) == -1) { \ -+ goto parseerror; \ -+ } -+#define DO_SCHED(type, var, file, bit) \ -+ do { \ -+ int ret; \ -+ CHECK(ret = read ## type((var), de->d_name, (file))); \ -+ if (ret == 0) \ -+ guest->sched.set_mask |= (bit); \ -+ } while (0) -+ -+ /* Parse simple values */ -+ CHECK(readInt(&guest->xid, de->d_name, "context")); -+ CHECK(readStr(guest->name, sizeof(guest->name), de->d_name, "name")); -+ CHECK(readStr(guest->uts.hostname, sizeof(guest->uts.hostname), de->d_name, -+ "uts/nodename")); -+ CHECK(readStr(guest->uts.machine, sizeof(guest->uts.machine), de->d_name, -+ "uts/machine")); -+ CHECK(readStr(guest->uts.release, sizeof(guest->uts.release), de->d_name, -+ "uts/release")); -+ CHECK(readStr(guest->uts.version, sizeof(guest->uts.version), de->d_name, -+ "uts/version")); -+ CHECK(readStr(mark, sizeof(mark), de->d_name, "apps/init/mark")); -+ -+ DO_SCHED(Int, &guest->sched.fill_rate, "sched/fill-rate", -+ VC_VXSM_FILL_RATE); -+ DO_SCHED(Int, &guest->sched.interval, "sched/interval", -+ VC_VXSM_INTERVAL); -+ DO_SCHED(Int, &guest->sched.fill_rate2, "sched/fill-rate2", -+ VC_VXSM_FILL_RATE2); -+ DO_SCHED(Int, &guest->sched.interval2, "sched/interval2", -+ VC_VXSM_INTERVAL2); -+ DO_SCHED(Int, &guest->sched.tokens_min, "sched/tokens-min", -+ VC_VXSM_TOKENS_MIN); -+ DO_SCHED(Int, &guest->sched.tokens_max, "sched/tokens-max", -+ VC_VXSM_TOKENS_MAX); -+ DO_SCHED(Int, &guest->sched.priority_bias, "sched/priority-bias", -+ VC_VXSM_PRIO_BIAS); -+ if (readBool(&tmp, de->d_name, "sched/idle-time") == 0) { -+ if (tmp) -+ guest->sched.set_mask |= VC_VXSM_IDLE_TIME; -+ } -+ -+ CHECK(readLong(&guest->rss_hard, de->d_name, "rlimits/rss.hard")); -+ -+ /* Generate a UUID if one doesn't already exist */ -+ switch (readStr(uuidstr, sizeof(uuidstr), de->d_name, "uuid")) { -+ case 1: -+ CHECK(virUUIDGenerate(guest->uuid)); -+ virUUIDFormat(guest->uuid, uuidstr); -+ CHECK(vserverWriteToConfig(guest, "uuid", "%s\n", uuidstr)); -+ break; -+ case 0: -+ CHECK(virUUIDParse(uuidstr, guest->uuid)); -+ break; -+ case -1: -+ goto parseerror; -+ } -+ -+ /* Parse interfaces */ -+ if (parseInterfaces(guest, "interfaces") == -1) -+ goto parseerror; -+ -+ /* Parse fstab */ -+ if (parseFstab(guest, "fstab") == -1) -+ goto parseerror; -+ -+ /* Make sure the guest has the / directory in the disk output */ -+ do { -+ struct vserver_fstab *ent; -+ int has_root = 0; -+ for (ent = guest->fstab; ent; ent = ent->next) { -+ if (strcmp(ent->target, "/") == 0) { -+ has_root = 1; -+ break; -+ } -+ } -+ if (!has_root) { -+ char vdir[strlen(de->d_name) + sizeof("/vdir")]; -+ -+ ent = calloc(1, sizeof(*ent)); -+ if (!ent) -+ goto nomem; -+ -+ sprintf(vdir, "%s/vdir", de->d_name); -+ ent->source = realpath(vdir, NULL); -+ -+ ent->flags = VSERVER_FSTAB_SHOW; -+ ent->source_type = vserverFindSourceType("/"); -+ ent->target = strdup("/"); -+ ent->fstype = strdup("auto"); -+ ent->options = strdup("defaults"); -+ if (!ent->source || !ent->target || !ent->fstype || !ent->options) -+ goto nomem; -+ ent->next = guest->fstab; -+ guest->fstab = ent; -+ } -+ } while (0); -+#undef DO_SCHED -+#undef CHECK -+ -+ if (STREQ(mark, "default")) -+ guest->autostart = 1; -+ if (vserverContextIsRunning(guest->path)) { -+ struct vc_ctx_flags flags; -+ if (vc_get_cflags(guest->xid, &flags) == 0 && -+ (flags.flagword & VC_VXF_SCHED_PAUSE)) -+ guest->status = VIR_DOMAIN_PAUSED; -+ else -+ guest->status = VIR_DOMAIN_RUNNING; -+ driver->active_guests++; -+ } -+ else { -+ guest->status = VIR_DOMAIN_SHUTOFF; -+ driver->inactive_guests++; -+ } -+ } -+ -+ closedir(dp); -+ if (fchdir(cwd) == -1 || close(cwd) == -1) { -+ /* do nothing, we succeeded with everything else... */ -+ } -+ driver->initialized = 1; -+ -+ return VIR_DRV_OPEN_SUCCESS; -+ -+nomem: -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); -+ goto error; -+parseerror: -+ vserverError(conn, NULL, NULL, VIR_ERR_PARSE_FAILED, de->d_name); -+error: -+ if (dp) -+ closedir(dp); -+ -+ if (fchdir(cwd) == -1 || close(cwd) == -1) { -+ /* we're already failing, nothing to do */ -+ } -+ return VIR_DRV_OPEN_ERROR; -+} -+ -+#endif ---- libvirt-0.4.0.orig/src/vserver/vserver_conf.h 1970-01-01 01:00:00.000000000 +0100 -+++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.h 2008-01-05 02:10:20.000000000 +0100 -@@ -0,0 +1,36 @@ -+/* -+ * Configuration handling for Linux-VServer guests -+ * -+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Daniel Hokka Zakrisson -+ */ -+ -+#ifdef WITH_VSERVER -+ -+/* Kind of a hack */ -+#ifdef IN_VSERVER -+int vserverWriteToConfig(struct vserver_guest *guest, const char *filename, -+ const char *format, ...); -+int vserverWriteGuestToConfig(struct vserver_guest *guest); -+virDrvOpenStatus vserverInitializeDriver(virConnectPtr conn, -+ struct vserver_driver *driver, -+ const char *path); -+const char *vserverFindSourceType(const char *source); -+#endif -+ -+#endif -diff -Nurp libvirt-0.4.0.orig/src/vserver_driver.c libvirt-0.4.0.vserver/src/vserver_driver.c ---- libvirt-0.4.0.orig/src/vserver_driver.c 1970-01-01 01:00:00.000000000 +0100 -+++ libvirt-0.4.0.vserver/src/vserver_driver.c 2008-01-09 22:43:23.000000000 +0100 -@@ -0,0 +1,1625 @@ -+/* -+ * Core driver for managing Linux-VServer guests -+ * -+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Daniel Hokka Zakrisson -+ */ -+ -+#ifdef WITH_VSERVER -+ -+#define _GNU_SOURCE -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#define IN_VSERVER 1 -+#include "internal.h" -+#include "vserver_driver.h" -+#include "vserver_conf.h" -+#include "buf.h" -+#include "uuid.h" -+#include "xml.h" -+#include "nodeinfo.h" -+ -+#define GET_DOMAIN(dom, ret) \ -+ struct vserver_driver *driver = (struct vserver_driver *) \ -+ (dom)->conn->privateData; \ -+ struct vserver_guest *guest = getGuestByUUID(driver, (dom)->uuid); \ -+ \ -+ if (!guest) { \ -+ vserverError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \ -+ __FUNCTION__); \ -+ return (ret); \ -+ } -+ -+#ifndef MNT_DETACH -+# define MNT_DETACH 0x00000002 -+#endif -+ -+static int PAGE_SHIFT_TO_KIBI = 2; -+ -+static inline int sys_umount(const char *path, int flags) -+{ -+ return syscall(__NR_umount2, path, flags); -+} -+ -+static inline struct vserver_guest * -+getGuestByID(struct vserver_driver *driver, -+ int id) -+{ -+ struct vserver_guest *res; -+ for (res = driver->guests; res; res = res->next) { -+ if (res->xid == id) -+ break; -+ } -+ return res; -+} -+ -+static inline struct vserver_guest * -+getGuestByUUID(struct vserver_driver *driver, -+ const unsigned char *uuid) -+{ -+ struct vserver_guest *res; -+ for (res = driver->guests; res; res = res->next) { -+ if (memcmp(res->uuid, uuid, VIR_UUID_BUFLEN) == 0) -+ break; -+ } -+ return res; -+} -+ -+static inline struct vserver_guest * -+getGuestByName(struct vserver_driver *driver, -+ const char *name) -+{ -+ struct vserver_guest *res; -+ for (res = driver->guests; res; res = res->next) { -+ if (STREQ(res->name, name)) -+ break; -+ } -+ return res; -+} -+ -+void -+vserverError(virConnectPtr con, -+ virDomainPtr dom, -+ virNetworkPtr net, -+ virErrorNumber error, -+ const char *info) -+{ -+ const char *errmsg; -+ -+ if (error == VIR_ERR_OK) -+ return; -+ -+ errmsg = __virErrorMsg(error, info); -+ __virRaiseError(con, dom, net, VIR_FROM_VSERVER, error, VIR_ERR_ERROR, -+ errmsg, info, NULL, 0, 0, errmsg, info, 0); -+} -+ -+/* like execl, but uses /dev/null and handles forking/waiting/etc. */ -+int -+vserverRunCommand(int do_daemon, const char *cmd, ...) -+{ -+ pid_t pid; -+ va_list va; -+ char **argv; -+ int i, argc; -+ sighandler_t sigchld; -+ int ret; -+ -+ va_start(va, cmd); -+ argc = 15; -+ argv = calloc(argc, sizeof(*argv)); -+ argv[0] = (char *) cmd; -+ for (i = 1; (argv[i] = va_arg(va, char *)) != NULL; i++) { -+ if (i == argc-1) { -+ argc += 5; -+ argv = realloc(argv, sizeof(*argv) * argc); -+ } -+ } -+ -+ va_end(va); -+ -+ /* XXX: This is bad, since another child could die -+ * between here and where we restore it */ -+ sigchld = signal(SIGCHLD, SIG_DFL); -+ if ((pid = fork()) == 0) { -+ int fd; -+ if (do_daemon) { -+ pid_t not_a_zombie; -+ -+ if (setsid() == -1) -+ goto error; -+ -+ not_a_zombie = fork(); -+ if (not_a_zombie == -1) -+ goto error; -+ else if (not_a_zombie > 0) -+ _exit(0); -+ } -+ if ((fd = open("/dev/null", O_RDWR)) == -1) -+ goto error; -+ if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) -+ goto error; -+ if (fd > 2 && close(fd) == -1) -+ goto error; -+ execvp(cmd, argv); -+ error: -+ _exit(1); -+ } -+ else if (pid == -1) { -+ ret = -1; -+ } -+ else { -+ int status; -+ if (waitpid(pid, &status, 0) == -1) -+ ret = -1; -+ else if (WEXITSTATUS(status) != 0) -+ ret = 1; -+ else -+ ret = 0; -+ } -+ -+ signal(SIGCHLD, sigchld); -+ return ret; -+} -+ -+int -+vserverContextIsRunning(const char *path) -+{ -+ return vc_getVserverCtx(path, vcCFG_AUTO, false, 0, vcCTX_XID) != VC_NOCTX; -+} -+ -+static void -+vserverSetPagesize(void) -+{ -+ long page_size = sysconf(_SC_PAGESIZE); -+ PAGE_SHIFT_TO_KIBI = page_size / 1024; -+} -+ -+static virDrvOpenStatus -+vserverOpen(virConnectPtr conn, xmlURIPtr uri, -+ virConnectAuthPtr auth ATTRIBUTE_UNUSED, -+ int flags ATTRIBUTE_UNUSED) -+{ -+ virDrvOpenStatus ret; -+ struct vserver_driver *driver; -+ -+ if (!uri) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ if (getuid() != 0) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ if (!uri->scheme || STRNEQ(uri->scheme, "vserver")) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ if (uri->server) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ /* nothing else supported right now */ -+ if (strncmp(uri->path, "/system", 7) != 0) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ /* make sure it's a Linux-VServer kernel */ -+ if (vc_get_version() == -1) -+ return VIR_DRV_OPEN_DECLINED; -+ -+ if (!conn->privateData) -+ conn->privateData = calloc(1, sizeof(struct vserver_driver)); -+ -+ ret = vserverInitializeDriver(conn, conn->privateData, uri->path + 7); -+ if (ret == VIR_DRV_OPEN_SUCCESS) { -+ driver = conn->privateData; -+ driver->uri = xmlSaveUri(uri); -+ } -+ else { -+ free(conn->privateData); -+ } -+ -+ vserverSetPagesize(); -+ -+ return ret; -+} -+ -+static void -+freeFstab(struct vserver_fstab *ent) -+{ -+ free(ent->source); -+ free(ent->target); -+ free(ent->fstype); -+ free(ent->options); -+ free(ent); -+} -+ -+static void -+freeGuest(struct vserver_guest *guest) -+{ -+ struct vserver_ip *ip, *pip = NULL; -+ struct vserver_fstab *ent, *pent = NULL; -+ for (ip = guest->ips; ip; ip = ip->next) { -+ if (pip) -+ free(pip); -+ pip = ip; -+ } -+ if (pip) -+ free(pip); -+ for (ent = guest->fstab; ent; ent = ent->next) { -+ if (pent) -+ freeFstab(pent); -+ pent = ent; -+ } -+ if (pent) -+ freeFstab(pent); -+ free(guest->path); -+ free(guest); -+} -+ -+static int -+vserverClose(virConnectPtr conn) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest, *pguest; -+ -+ if (!driver || !driver->initialized) -+ return 0; -+ -+ for (guest = driver->guests, pguest = NULL; guest; guest = guest->next) { -+ if (pguest) -+ freeGuest(pguest); -+ pguest = guest; -+ } -+ if (pguest) -+ freeGuest(pguest); -+ -+ xmlFree(driver->uri); -+ free(driver); -+ conn->privateData = NULL; -+ -+ return 0; -+} -+ -+static const char * -+vserverGetType(virConnectPtr conn ATTRIBUTE_UNUSED) -+{ -+ return "Linux-VServer"; -+} -+ -+static int -+vserverGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version) -+{ -+ *version = 1; -+ return 0; -+} -+ -+static char * -+vserverGetHostname(virConnectPtr conn) -+{ -+ char *ret; -+ -+ ret = calloc(VSERVER_UTS_MAX + 1, sizeof(char)); -+ if (!ret) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "gethostname"); -+ return NULL; -+ } -+ -+ if (gethostname(ret, VSERVER_UTS_MAX) == -1) { -+ free(ret); -+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno)); -+ return NULL; -+ } -+ -+ return ret; -+} -+ -+static char * -+vserverGetURI(virConnectPtr conn) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ return (char *) xmlStrdup(driver->uri); -+} -+ -+static int -+vserverNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) -+{ -+ return virNodeInfoPopulate(conn, nodeinfo); -+} -+ -+static int -+vserverListDomains(virConnectPtr conn, int *ids, int nids) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest; -+ int i; -+ -+ for (guest = driver->guests, i = 0; guest && i < nids; -+ guest = guest->next) { -+ if (guest->status != VIR_DOMAIN_SHUTOFF) -+ ids[i++] = guest->xid; -+ } -+ -+ return i; -+} -+ -+static int -+vserverNumOfDomains(virConnectPtr conn) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ -+ return driver->active_guests; -+} -+ -+static virDomainPtr -+vserverDomainLookupByID(virConnectPtr conn, int id) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest; -+ virDomainPtr domain; -+ -+ if ((guest = getGuestByID(driver, id)) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, -+ _("No domain by that ID found")); -+ return NULL; -+ } -+ -+ domain = virGetDomain(conn, guest->name, guest->uuid); -+ if (!domain) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain"); -+ return NULL; -+ } -+ -+ if (vserverIsRunning(guest)) -+ domain->id = guest->xid; -+ -+ return domain; -+} -+ -+static virDomainPtr -+vserverDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest; -+ virDomainPtr domain; -+ -+ if ((guest = getGuestByUUID(driver, uuid)) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, -+ _("No domain by that UUID found")); -+ return NULL; -+ } -+ -+ domain = virGetDomain(conn, guest->name, guest->uuid); -+ if (!domain) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain"); -+ return NULL; -+ } -+ -+ if (vserverIsRunning(guest)) -+ domain->id = guest->xid; -+ -+ return domain; -+} -+ -+static virDomainPtr -+vserverDomainLookupByName(virConnectPtr conn, const char *name) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest; -+ virDomainPtr domain; -+ -+ if ((guest = getGuestByName(driver, name)) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, -+ _("No domain by that name found")); -+ return NULL; -+ } -+ -+ domain = virGetDomain(conn, guest->name, guest->uuid); -+ if (!domain) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain"); -+ return NULL; -+ } -+ -+ if (vserverIsRunning(guest)) -+ domain->id = guest->xid; -+ -+ return domain; -+} -+ -+static int -+vserverDomainSuspend(virDomainPtr domain) -+{ -+ struct vc_ctx_flags flags = { -+ .flagword = VC_VXF_SCHED_PAUSE, -+ .mask = VC_VXF_SCHED_PAUSE, -+ }; -+ GET_DOMAIN(domain, -1); -+ -+ if (guest->status == VIR_DOMAIN_PAUSED) -+ return 0; -+ if (guest->status != VIR_DOMAIN_RUNNING) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED, -+ _("domain is not running")); -+ return -1; -+ } -+ -+ if (vc_set_cflags(guest->xid, &flags) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ guest->status = VIR_DOMAIN_PAUSED; -+ -+ return 0; -+} -+ -+static int -+vserverDomainResume(virDomainPtr domain) -+{ -+ struct vc_ctx_flags flags = { -+ .flagword = 0, -+ .mask = VC_VXF_SCHED_PAUSE, -+ }; -+ GET_DOMAIN(domain, -1); -+ -+ if (guest->status == VIR_DOMAIN_RUNNING) -+ return 0; -+ if (guest->status != VIR_DOMAIN_PAUSED) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED, -+ _("domain is not running")); -+ return -1; -+ } -+ -+ if (vc_set_cflags(guest->xid, &flags) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ guest->status = VIR_DOMAIN_RUNNING; -+ -+ return 0; -+} -+ -+static int -+vserverDomainShutdown(virDomainPtr domain) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "stop", NULL) != 0) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ "vserver stop"); -+ return -1; -+ } -+ -+ driver->active_guests--; -+ guest->status = VIR_DOMAIN_SHUTOFF; -+ driver->inactive_guests++; -+ return 0; -+} -+ -+static int -+vserverDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "restart", NULL) != 0) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ "vserver restart"); -+ return -1; -+ } -+ -+ guest->status = VIR_DOMAIN_RUNNING; -+ return 0; -+} -+ -+static int -+vserverDomainDestroy(virDomainPtr domain) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverDomainShutdown(domain) == -1) -+ return -1; -+ -+ virFreeDomain(domain->conn, domain); -+ -+ return 0; -+} -+ -+static char * -+vserverDomainGetOSType(virDomainPtr domain ATTRIBUTE_UNUSED) -+{ -+ return strdup("Linux"); -+} -+ -+static unsigned long -+vserverDomainGetMaxMemory(virDomainPtr domain) -+{ -+ GET_DOMAIN(domain, (unsigned long) -1); -+ -+ return guest->rss_hard << PAGE_SHIFT_TO_KIBI; -+} -+ -+static int -+vserverDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) -+{ -+ struct vc_rlimit limit = { -+ .min = 0, -+ }; -+ GET_DOMAIN(domain, -1); -+ -+ guest->rss_hard = memory >> PAGE_SHIFT_TO_KIBI; -+ limit.soft = limit.hard = guest->rss_hard; -+ if (vserverIsRunning(guest) && -+ vc_set_rlimit(guest->xid, RLIMIT_RSS, &limit) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno)); -+ return -1; -+ } -+ -+ if (vserverWriteToConfig(guest, "rlimits/rss.hard", "%lu\n", guest->rss_hard) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+vserverDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) -+{ -+ struct vc_sched_info sinfo = { .user_msec = 0, .sys_msec = 0 }; -+ struct vc_rlimit_stat rss_stat = { .value = 0 }; -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverIsRunning(guest)) { -+ if (vc_sched_info(guest->xid, &sinfo) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ if (vc_rlimit_stat(guest->xid, RLIMIT_RSS, &rss_stat) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ } -+ -+ info->state = guest->status; -+ info->maxMem = guest->rss_hard << PAGE_SHIFT_TO_KIBI; -+ info->nrVirtCpu = -1; -+ info->memory = rss_stat.value; -+ info->cpuTime = (sinfo.user_msec + sinfo.sys_msec) * 1000000ULL; -+ -+ return 0; -+} -+ -+static char * -+vserverDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) -+{ -+ virBufferPtr buf; -+ char uuid[VIR_UUID_STRING_BUFLEN + 1]; -+ struct vserver_ip *ip; -+ GET_DOMAIN(domain, NULL); -+ -+ buf = virBufferNew(4096); -+ if (!buf) -+ goto no_memory; -+ -+ virUUIDFormat(guest->uuid, uuid); -+ if (virBufferVSprintf(buf, -+"\n" -+" %s\n" -+" %s\n" -+ , guest->xid, guest->name, uuid -+ ) < 0) -+ goto no_memory; -+ if (guest->rss_hard > 0) -+ if (virBufferVSprintf(buf, " %lu\n", -+ guest->rss_hard << PAGE_SHIFT_TO_KIBI) < 0) -+ goto no_memory; -+ -+ if (virBufferVSprintf(buf, " \n" -+ " %s\n" -+ , guest->uts.hostname) < 0) -+ goto no_memory; -+ if (virBufferVSprintf(buf, " uts.machine) -+ if (virBufferVSprintf(buf, " arch='%s'", guest->uts.machine) < 0) -+ goto no_memory; -+ if (virBufferVSprintf(buf, ">vserver\n") < 0) -+ goto no_memory; -+ if (*guest->uts.release) -+ if (virBufferVSprintf(buf, " %s\n", -+ guest->uts.release) < 0) -+ goto no_memory; -+ if (*guest->uts.version) -+ if (virBufferVSprintf(buf, " %s\n", -+ guest->uts.version) < 0) -+ goto no_memory; -+ if (virBufferVSprintf(buf, " \n" -+ " \n") < 0) -+ goto no_memory; -+ -+ for (ip = guest->ips; ip; ip = ip->next) { -+ char addrbuf[128]; -+ if (virBufferVSprintf(buf, " \n" -+ " addr.vna_prefix) < 0) -+ goto no_memory; -+ if (*ip->interface) -+ if (virBufferVSprintf(buf, " interface='%s'", ip->interface) < 0) -+ goto no_memory; -+ -+ switch (ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6)) { -+ case VC_NXA_TYPE_IPV4: -+ inet_ntop(AF_INET, &ip->addr.vna_v4_ip, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0) -+ goto no_memory; -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE)) { -+ inet_ntop(AF_INET, &ip->addr.vna_v4_ip2, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0) -+ goto no_memory; -+ } -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) { -+ if (virBufferVSprintf(buf, " type='mask'") < 0) -+ goto no_memory; -+ } -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE) || -+ ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) { -+ inet_ntop(AF_INET, &ip->addr.vna_v4_mask, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0) -+ goto no_memory; -+ } -+ break; -+ -+ case VC_NXA_TYPE_IPV6: -+ inet_ntop(AF_INET6, &ip->addr.vna_v6_ip, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0) -+ goto no_memory; -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE)) { -+ inet_ntop(AF_INET6, &ip->addr.vna_v6_ip2, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0) -+ goto no_memory; -+ } -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) { -+ if (virBufferVSprintf(buf, " type='mask'") < 0) -+ goto no_memory; -+ } -+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE) || -+ ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) { -+ inet_ntop(AF_INET6, &ip->addr.vna_v6_mask, addrbuf, sizeof(addrbuf)); -+ if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0) -+ goto no_memory; -+ } -+ break; -+ } -+ -+ if (virBufferVSprintf(buf, " />\n" -+ " \n") < 0) -+ goto no_memory; -+ } -+ -+ if (guest->fstab) { -+ struct vserver_fstab *ent; -+ for (ent = guest->fstab; ent; ent = ent->next) { -+ /* Skip things like proc */ -+ if (!(ent->flags & VSERVER_FSTAB_SHOW)) -+ continue; -+ if (virBufferVSprintf(buf, " \n" -+ " \n" -+ " \n" -+ " \n", -+ ent->source_type, -+ (strcmp(ent->source_type, "block") == 0 ? -+ "dev" : ent->source_type), -+ ent->source, -+ ent->fstype, -+ ent->options, -+ ent->target) < 0) -+ goto no_memory; -+ } -+ } -+ -+ if (virBufferVSprintf(buf, " \n" -+ "\n") < 0) -+ goto no_memory; -+ -+ return virBufferContentAndFree(buf); -+ -+no_memory: -+ if (buf) -+ virBufferFree(buf); -+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, -+ "xml"); -+ return NULL; -+} -+ -+static int -+vserverParseIP(struct vserver_ip *ip, xmlNodePtr node) -+{ -+ xmlChar *value; -+ char *endptr; -+ -+ value = xmlGetProp(node, BAD_CAST "address"); -+ if (!value) -+ goto err; -+ if (inet_pton(AF_INET6, (char *) value, &ip->addr.vna_v6_ip) > 0) -+ ip->addr.vna_type = VC_NXA_TYPE_IPV6; -+ else if (inet_pton(AF_INET, (char *) value, &ip->addr.vna_v4_ip) > 0) -+ ip->addr.vna_type = VC_NXA_TYPE_IPV4; -+ else -+ goto err; -+ -+ value = xmlGetProp(node, BAD_CAST "prefix"); -+ if (!value) -+ goto err; -+ ip->addr.vna_prefix = strtol((char *) value, &endptr, 0); -+ if (*endptr) -+ goto err; -+ xmlFree(value); -+ -+ value = xmlGetProp(node, BAD_CAST "type"); -+ if (!value) -+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR; -+ else { -+ if (xmlStrcasecmp(value, BAD_CAST "address") == 0) -+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR; -+ else if (xmlStrcasecmp(value, BAD_CAST "mask") == 0) -+ ip->addr.vna_type |= VC_NXA_TYPE_MASK; -+ else if (xmlStrcasecmp(value, BAD_CAST "range") == 0) -+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE; -+ else -+ goto err; -+ xmlFree(value); -+ } -+ -+ value = xmlGetProp(node, BAD_CAST "interface"); -+ if (value) { -+ strncpy(ip->interface, (char *) value, IFNAMSIZ); -+ xmlFree(value); -+ } -+ -+ return 0; -+ -+err: -+ if (value) -+ xmlFree(value); -+ return -1; -+} -+ -+static const char * -+diskTypeToAttr(const char *type) -+{ -+ return (strcmp(type, "block") == 0 ? "dev" : type); -+} -+ -+static int -+vserverParseDisk(struct vserver_fstab *ent, xmlNodePtr node) -+{ -+ xmlChar *type = NULL, *value = NULL; -+ xmlNodePtr iter, source = NULL, target = NULL; -+ -+ for (iter = node->children; iter && (!source || !target); iter = iter->next) { -+ if (iter->type != XML_ELEMENT_NODE) -+ continue; -+ if (xmlStrEqual(iter->name, BAD_CAST "source")) -+ source = iter; -+ else if (xmlStrEqual(iter->name, BAD_CAST "target")) -+ target = iter; -+ } -+ if (!target || !source) -+ goto err; -+ -+ value = xmlGetProp(node, BAD_CAST "device"); -+ if (!value || !xmlStrEqual(value, BAD_CAST "directory")) -+ goto err; -+ xmlFree(value); -+ -+ ent->target = (char *) xmlGetProp(target, BAD_CAST "directory"); -+ if (!value) -+ goto err; -+ -+ type = xmlGetProp(node, BAD_CAST "type"); -+ if (!type) -+ goto err; -+ ent->source = (char *) xmlGetProp(source, BAD_CAST diskTypeToAttr((char *) type)); -+ xmlFree(type); -+ if (!ent->source) -+ goto err; -+ -+ ent->source_type = vserverFindSourceType(ent->source); -+ if (!ent->source_type) -+ goto err; -+ -+ ent->fstype = (char *) xmlGetProp(source, BAD_CAST "type"); -+ if (!ent->fstype) -+ ent->fstype = strdup("auto"); -+ -+ ent->options = (char *) xmlGetProp(source, BAD_CAST "options"); -+ if (!ent->options) { -+ if (strcmp(ent->source_type, "file") == 0) -+ ent->options = strdup("defaults,loop"); -+ else -+ ent->options = strdup("defaults"); -+ } -+ -+ ent->flags = VSERVER_FSTAB_SHOW | VSERVER_FSTAB_OUTPUT; -+ -+ return 0; -+ -+err: -+ if (ent->fstype) -+ xmlFree(ent->fstype); -+ if (ent->source) -+ xmlFree(ent->source); -+ if (ent->target) -+ xmlFree(ent->target); -+ if (value) -+ xmlFree(value); -+ return -1; -+} -+ -+static int -+vserverParseXML(struct vserver_guest *guest, xmlDocPtr doc) -+{ -+ xmlNodePtr root; -+ xmlXPathContextPtr xpath = NULL; -+ xmlXPathObjectPtr obj; -+ char *str; -+ long l_tmp; -+ -+ /* FIXME: This could use some better error reporting... */ -+ root = xmlDocGetRootElement(doc); -+ if (!root || !xmlStrEqual(root->name, BAD_CAST "domain")) -+ goto err; -+ -+ xpath = xmlXPathNewContext(doc); -+ if (!xpath) -+ goto err; -+ -+ if (virXPathLong("string(/domain[1]/@id)", xpath, &l_tmp) != 0) -+ goto err; -+ guest->xid = (int) l_tmp; -+ -+ str = virXPathString("string(/domain/name[1])", xpath); -+ if (!str) -+ goto err; -+ strncpy(guest->name, str, VSERVER_NAME_MAX - 1); -+ -+ str = virXPathString("string(/domain/uuid[1])", xpath); -+ if (!str) { -+ if (virUUIDGenerate(guest->uuid) != 0) -+ goto err; -+ } -+ else if (virUUIDParse(str, guest->uuid) < 0) -+ goto err; -+ -+ guest->rss_hard = 0; -+ if (virXPathLong("string(/domain/memory[1])", xpath, (long *) &guest->rss_hard) == -2) -+ goto err; -+ guest->rss_hard >>= PAGE_SHIFT_TO_KIBI; -+ -+ str = virXPathString("string(/domain/os[1]/hostname[1])", xpath); -+ if (str) -+ strncpy(guest->uts.hostname, str, VSERVER_UTS_MAX - 1); -+ -+ str = virXPathString("string(/domain/os[1]/type[1]/@arch)", xpath); -+ if (str) -+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1); -+ -+ str = virXPathString("string(/domain/os[1]/release[1])", xpath); -+ if (str) -+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1); -+ -+ str = virXPathString("string(/domain/os[1]/version[1])", xpath); -+ if (str) -+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1); -+ -+ str = virXPathString("string(/domain/container/initstyle[1]/@type)", xpath); -+ guest->initstyle = VSERVER_INIT_SYSV; -+ if (str) { -+ if (strcmp(str, "plain") == 0) -+ guest->initstyle = VSERVER_INIT_PLAIN; -+ else if (strcmp(str, "gentoo") == 0) -+ guest->initstyle = VSERVER_INIT_GENTOO; -+ else if (strcmp(str, "minit") == 0) -+ guest->initstyle = VSERVER_INIT_MINIT; -+ else if (strcmp(str, "sysv") == 0) -+ guest->initstyle = VSERVER_INIT_SYSV; -+ } -+ -+ obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/interface/ip", xpath); -+ if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL && -+ obj->nodesetval->nodeNr > 0) { -+ int i; -+ struct vserver_ip *ip = NULL; -+ -+ for (i = 0; i < obj->nodesetval->nodeNr; i++) { -+ if (ip == NULL) -+ guest->ips = ip = calloc(1, sizeof(*ip)); -+ else { -+ ip->next = calloc(1, sizeof(*ip)); -+ ip = ip->next; -+ } -+ -+ if (vserverParseIP(ip, obj->nodesetval->nodeTab[i]) == -1) -+ goto nodeset_err; -+ } -+ } -+ if (obj) -+ xmlXPathFreeObject(obj); -+ -+ obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/disk", xpath); -+ if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL && -+ obj->nodesetval->nodeNr > 0) { -+ int i; -+ struct vserver_fstab *ent = NULL; -+ -+ for (i = 0; i < obj->nodesetval->nodeNr; i++) { -+ if (ent == NULL) -+ guest->fstab = ent = calloc(1, sizeof(*ent)); -+ else { -+ ent->next = calloc(1, sizeof(*ent)); -+ ent = ent->next; -+ } -+ -+ if (vserverParseDisk(ent, obj->nodesetval->nodeTab[i]) == -1) -+ goto nodeset_err; -+ } -+ } -+ if (obj) -+ xmlXPathFreeObject(obj); -+ -+ xmlXPathFreeContext(xpath); -+ xpath = NULL; -+ -+ return 0; -+ -+nodeset_err: -+ xmlXPathFreeObject(obj); -+err: -+ if (xpath) -+ xmlXPathFreeContext(xpath); -+ return -1; -+} -+ -+static virDomainPtr -+vserverDomainDefineXML(virConnectPtr conn, const char *xml) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest, *tail; -+ virDomainPtr domain; -+ xmlDocPtr doc; -+ char buf[128]; -+ -+ if ((guest = calloc(1, sizeof(struct vserver_guest))) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "vserver_guest"); -+ return NULL; -+ } -+ -+ if ((doc = xmlReadDoc(BAD_CAST xml, "domain.xml", NULL, -+ XML_PARSE_NOENT | XML_PARSE_NONET | -+ XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); -+ free(guest); -+ return NULL; -+ } -+ -+ if (vserverParseXML(guest, doc) == -1) { -+ vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain")); -+ xmlFreeDoc(doc); -+ free(guest); -+ return NULL; -+ } -+ -+ xmlFreeDoc(doc); -+ -+ guest->path = calloc(sizeof(VSERVER_CONF_DIR "/") + strlen(guest->name), sizeof(char)); -+ sprintf(guest->path, VSERVER_CONF_DIR "/%s", guest->name); -+ guest->status = VIR_DOMAIN_SHUTOFF; -+ if (vserverRunCommand(0, PROG_VSERVER, guest->name, "build", "-m", -+ "skeleton", "--confdir", guest->path, NULL) != 0) { -+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserver build"); -+ free(guest); -+ return NULL; -+ } -+ virUUIDFormat(guest->uuid, buf); -+ if (vserverWriteGuestToConfig(guest) == -1) { -+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserverWriteToConfig"); -+ free(guest); -+ return NULL; -+ } -+ -+ /* add it to the list */ -+ for (tail = driver->guests; tail && tail->next; tail = tail->next) -+ ; -+ if (!tail) -+ driver->guests = guest; -+ else -+ tail->next = guest; -+ -+ driver->inactive_guests++; -+ -+ domain = virGetDomain(conn, guest->name, guest->uuid); -+ if (!domain) -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain"); -+ -+ return domain; -+} -+ -+static int -+vserverListDefinedDomains(virConnectPtr conn, char **const names, -+ int maxnames) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ struct vserver_guest *guest; -+ int i = 0; -+ -+ for (guest = driver->guests; guest && i < maxnames; guest = guest->next) { -+ if (guest->status == VIR_DOMAIN_SHUTOFF) { -+ if ((names[i++] = strdup(guest->name)) == NULL) { -+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "names"); -+ return -1; -+ } -+ } -+ } -+ -+ return i; -+} -+ -+static int -+vserverNumOfDefinedDomains(virConnectPtr conn) -+{ -+ struct vserver_driver *driver = conn->privateData; -+ -+ return driver->inactive_guests; -+} -+ -+static int -+vserverDomainCreate(virDomainPtr domain) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "start", NULL) != 0) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ "vserver start"); -+ return -1; -+ } -+ -+ driver->inactive_guests--; -+ guest->status = VIR_DOMAIN_RUNNING; -+ driver->active_guests++; -+ return 0; -+} -+ -+static virDomainPtr -+vserverDomainCreateLinux(virConnectPtr conn, const char *xml, -+ unsigned int flags ATTRIBUTE_UNUSED) -+{ -+ virDomainPtr domain; -+ -+ domain = vserverDomainDefineXML(conn, xml); -+ if (!domain) -+ return NULL; -+ -+ if (vserverDomainCreate(domain) == -1) -+ return NULL; -+ -+ return domain; -+} -+ -+static int -+vserverDomainUndefine(virDomainPtr domain) -+{ -+ struct vserver_guest *prev; -+ GET_DOMAIN(domain, -1); -+ -+ for (prev = driver->guests; prev; prev = prev->next) { -+ if (prev->next == guest) -+ break; -+ } -+ if (!prev) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, -+ _("domain not found")); -+ return -1; -+ } -+ if (vserverIsRunning(guest)) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, -+ _("domain is running")); -+ return -1; -+ } -+ -+ driver->inactive_guests--; -+ prev->next = guest->next; -+ /* XXX: deletes the domain's contents as well */ -+ vserverRunCommand(0, PROG_VSERVER, "--silent", guest->path, "delete", NULL); -+ free(guest); -+ -+ return 0; -+} -+ -+static int -+doMount(int do_umount, struct vserver_guest *guest, struct vserver_fstab *ent) -+{ -+ pid_t child; -+ int status; -+ -+ if ((child = fork()) == 0) { -+ if (vc_enter_namespace(guest->xid, CLONE_NEWNS|CLONE_FS) == -1) -+ _exit(errno); -+ if (do_umount) { -+ if (sys_umount(ent->target, MNT_DETACH) == -1) -+ _exit(errno); -+ } -+ else { -+ char target[strlen(guest->path) + sizeof("/vdir/") + strlen(ent->target)]; -+ sprintf(target, "%s/vdir/%s", guest->path, ent->target); -+ if (vserverRunCommand(0, "mount", "-t", ent->fstype, "-n", "-o", -+ ent->options, ent->source, target, NULL)) -+ _exit(errno); -+ } -+ _exit(0); -+ } -+ else if (child == -1) -+ return -1; -+ else { -+ if (waitpid(child, &status, 0) == -1) -+ return -1; -+ if (WEXITSTATUS(status) != 0) { -+ errno = WEXITSTATUS(status); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+static int -+vserverDomainHandleDevice(virDomainPtr domain, const char *xml, int attach) -+{ -+ xmlDocPtr doc; -+ xmlNodePtr node; -+ GET_DOMAIN(domain, -1); -+ -+ if ((doc = xmlReadDoc(BAD_CAST xml, "device.xml", NULL, -+ XML_PARSE_NOENT | XML_PARSE_NONET | -+ XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, _("device")); -+ return -1; -+ } -+ -+ node = xmlDocGetRootElement(doc); -+ if (node == NULL) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, -+ _("missing root element")); -+ return -1; -+ } -+ -+ if (xmlStrEqual(node->name, BAD_CAST "interface")) { -+ xmlNodePtr child; -+ struct vserver_ip *ip; -+ -+ for (child = node->children; child; child = child->next) { -+ if (child->type != XML_ELEMENT_NODE) -+ continue; -+ -+ /* This should be an only child, but who knows. */ -+ if (xmlStrEqual(child->name, BAD_CAST "ip")) -+ break; -+ } -+ if (!child) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, -+ _("no element found")); -+ return -1; -+ } -+ -+ ip = calloc(1, sizeof(*ip)); -+ if (vserverParseIP(ip, child) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, -+ _("parsing IP failed")); -+ return -1; -+ } -+ -+ if (attach) { -+ list_add_tail(guest->ips, ip); -+ if (vserverIsRunning(guest)) { -+ if (vc_net_add(guest->xid, &ip->addr) == -1) { -+ vserverError(domain->conn, domain, NULL, -+ VIR_ERR_SYSTEM_ERROR, strerror(errno)); -+ return -1; -+ } -+ } -+ } -+ -+ else /* detach */ { -+ struct vserver_ip *i, *p = NULL; -+ for (i = guest->ips; i; i = i->next) { -+ if (strcmp(ip->interface, i->interface) == 0 && -+ memcmp(&ip->addr, &i->addr, sizeof(ip->addr)) == 0) -+ break; -+ p = i; -+ } -+ if (i) { -+ if (p) -+ p->next = i->next; -+ else -+ guest->ips = i->next; -+ if (vserverIsRunning(guest)) { -+ /* Not a lot of kernels support this, so don't fail. */ -+ vc_net_remove(guest->xid, &ip->addr); -+ } -+ free(i); -+ } -+ free(ip); -+ } -+ } -+ else if (xmlStrEqual(node->name, BAD_CAST "disk")) { -+ struct vserver_fstab *ent = calloc(1, sizeof(*ent)); -+ if (!ent) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, NULL); -+ return -1; -+ } -+ -+ if (vserverParseDisk(ent, node) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, "disk"); -+ return -1; -+ } -+ -+ if (attach) { -+ list_add_tail(guest->fstab, ent); -+ if (vserverIsRunning(guest)) { -+ if (doMount(0, guest, ent) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ } -+ } -+ -+ else /* detach */ { -+ struct vserver_fstab *i, *p = NULL; -+ for (i = guest->fstab; i; i = i->next) { -+ /* These are the fields we care about */ -+ if (strcmp(ent->source, i->source) == 0 && -+ strcmp(ent->target, i->target) == 0 && -+ strcmp(ent->source_type, i->source_type) == 0) -+ break; -+ p = i; -+ } -+ if (i) { -+ if (p) -+ p->next = i->next; -+ else -+ guest->fstab = i->next; -+ if (vserverIsRunning(guest)) { -+ if (doMount(1, guest, ent) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ strerror(errno)); -+ return -1; -+ } -+ } -+ freeFstab(i); -+ } -+ freeFstab(ent); -+ } -+ } -+ else { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, -+ _("unknown device type")); -+ return -1; -+ } -+ -+ /* Both fstab and interfaces need a lot of writing, so write the whole thing */ -+ if (vserverWriteGuestToConfig(guest) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED, guest->name); -+ return -1; -+ } -+ -+ xmlFreeDoc(doc); -+ -+ return 0; -+} -+ -+static int -+vserverDomainAttachDevice(virDomainPtr domain, const char *xml) -+{ -+ return vserverDomainHandleDevice(domain, xml, 1); -+} -+ -+static int -+vserverDomainDetachDevice(virDomainPtr domain, const char *xml) -+{ -+ return vserverDomainHandleDevice(domain, xml, 0); -+} -+ -+static int -+vserverDomainGetAutostart(virDomainPtr domain, int *autostart) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ *autostart = guest->autostart; -+ return 0; -+} -+ -+static int -+vserverDomainSetAutostart(virDomainPtr domain, int autostart) -+{ -+ GET_DOMAIN(domain, -1); -+ -+ if (vserverWriteToConfig(guest, "apps/init/mark", -+ (autostart ? "default\n" : "\n")) == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED, -+ "apps/init/mark"); -+ return -1; -+ } -+ guest->autostart = autostart; -+ return 0; -+} -+ -+static const struct { -+ unsigned int id; -+ const char *field; -+ int type; -+} sched_fields[] = { -+ { VC_VXSM_FILL_RATE, "fill_rate1", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_INTERVAL, "interval1", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_FILL_RATE2, "fill_rate2", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_INTERVAL2, "interval2", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_TOKENS_MIN, "tokens_min", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_TOKENS_MAX, "tokens_max", VIR_DOMAIN_SCHED_FIELD_UINT }, -+ { VC_VXSM_PRIO_BIAS, "prio_bias", VIR_DOMAIN_SCHED_FIELD_INT }, -+ { VC_VXSM_IDLE_TIME, "idle_time", VIR_DOMAIN_SCHED_FIELD_BOOLEAN }, -+ { 0, NULL, 0 } -+}; -+ -+static char * -+vserverDomainGetSchedulerType(virDomainPtr domain, int *nparams) -+{ -+ char *ret; -+ int i; -+ GET_DOMAIN(domain, NULL); -+ -+ ret = strdup(guest->sched.set_mask & VC_VXSM_IDLE_TIME ? "fair" : "hard"); -+ if (!ret) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, -+ _("scheduler")); -+ return NULL; -+ } -+ -+ *nparams = 0; -+ for (i = 0; sched_fields[i].field != NULL; i++) { -+ /* only returns fields which are set */ -+ if (guest->sched.set_mask & sched_fields[i].id) -+ (*nparams)++; -+ } -+ -+ return ret; -+} -+ -+static int -+vserverDomainGetSchedulerParams(virDomainPtr domain, -+ virSchedParameterPtr params, -+ int *nparams) -+{ -+ int i, j; -+ GET_DOMAIN(domain, -1); -+ -+ for (i = 0, j = 0; sched_fields[i].field != NULL && i < *nparams; i++) { -+ /* skip unset fields */ -+ if (!(guest->sched.set_mask & sched_fields[i].id)) -+ continue; -+ -+ params[j].type = sched_fields[i].type; -+ strncpy(params[j].field, sched_fields[i].field, sizeof(params[j].field) - 1); -+ switch (sched_fields[i].id) { -+ case VC_VXSM_FILL_RATE: -+ params[j].value.ui = guest->sched.fill_rate; -+ break; -+ case VC_VXSM_INTERVAL: -+ params[j].value.ui = guest->sched.interval; -+ break; -+ case VC_VXSM_FILL_RATE2: -+ params[j].value.ui = guest->sched.fill_rate2; -+ break; -+ case VC_VXSM_INTERVAL2: -+ params[j].value.ui = guest->sched.interval2; -+ break; -+ case VC_VXSM_TOKENS_MIN: -+ params[j].value.ui = guest->sched.tokens_min; -+ break; -+ case VC_VXSM_TOKENS_MAX: -+ params[j].value.ui = guest->sched.tokens_max; -+ break; -+ case VC_VXSM_PRIO_BIAS: -+ params[j].value.i = guest->sched.priority_bias; -+ break; -+ case VC_VXSM_IDLE_TIME: -+ params[j].value.b = guest->sched.set_mask & VC_VXSM_IDLE_TIME; -+ break; -+ } -+ j++; -+ } -+ *nparams = j; -+ -+ return 0; -+} -+ -+static int -+vserverDomainSetSchedulerParams(virDomainPtr domain, -+ virSchedParameterPtr params, -+ int nparams) -+{ -+ int i, j, cret; -+ GET_DOMAIN(domain, -1); -+ -+ for (i = 0; i < nparams; i++) { -+ for (j = 0; sched_fields[j].field != NULL; j++) { -+ if (STREQ(sched_fields[j].field, params[i].field)) -+ break; -+ } -+ if (sched_fields[j].field == NULL) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "field"); -+ return -1; -+ } -+ if (sched_fields[j].type != params[i].type) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "type"); -+ return -1; -+ } -+ switch (sched_fields[j].id) { -+ case VC_VXSM_FILL_RATE: -+ guest->sched.fill_rate = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/fill-rate", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_INTERVAL: -+ guest->sched.interval = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/interval", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_FILL_RATE2: -+ guest->sched.fill_rate2 = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/fill-rate2", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_INTERVAL2: -+ guest->sched.interval2 = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/interval2", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_TOKENS_MIN: -+ guest->sched.tokens_min = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/tokens-min", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_TOKENS_MAX: -+ guest->sched.tokens_max = params[i].value.ui; -+ cret = vserverWriteToConfig(guest, "sched/tokens-max", "%u\n", -+ params[i].value.ui); -+ break; -+ case VC_VXSM_PRIO_BIAS: -+ guest->sched.priority_bias = params[i].value.i; -+ cret = vserverWriteToConfig(guest, "sched/prio-bias", "%d\n", -+ params[i].value.i); -+ break; -+ case VC_VXSM_IDLE_TIME: -+ cret = vserverWriteToConfig(guest, "sched/idle-time", "%b", -+ params[i].value.b); -+ break; -+ default: -+ vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, -+ "Unknown scheduler parameter"); -+ return -1; -+ } -+ if (cret == -1) { -+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, -+ "vserverWriteToConfig"); -+ return -1; -+ } -+ guest->sched.set_mask |= sched_fields[j].id; -+ } -+ -+ return 0; -+} -+ -+ -+virDriver vserverDriver = { -+ VIR_DRV_VSERVER, -+ "Linux-VServer", -+ LIBVIR_VERSION_NUMBER, -+ vserverOpen, -+ vserverClose, -+ NULL, /* supports_feature */ -+ vserverGetType, -+ vserverGetVersion, -+ vserverGetHostname, -+ vserverGetURI, -+ NULL, /* getMaxVcpus */ -+ vserverNodeGetInfo, -+ NULL, /* getCapabilties */ -+ vserverListDomains, -+ vserverNumOfDomains, -+ vserverDomainCreateLinux, -+ vserverDomainLookupByID, -+ vserverDomainLookupByUUID, -+ vserverDomainLookupByName, -+ vserverDomainSuspend, -+ vserverDomainResume, -+ vserverDomainShutdown, -+ vserverDomainReboot, -+ vserverDomainDestroy, -+ vserverDomainGetOSType, -+ vserverDomainGetMaxMemory, -+ vserverDomainSetMaxMemory, -+ NULL, /* domainSetMemory */ -+ vserverDomainGetInfo, -+ NULL, /* domainSave */ -+ NULL, /* domainRestore */ -+ NULL, /* domainCoreDump */ -+ NULL, /* domainSetVcpus */ -+ NULL, /* domainPinVcpu */ -+ NULL, /* domainGetVcpus */ -+ NULL, /* domainGetMaxVcpus */ -+ vserverDomainDumpXML, -+ vserverListDefinedDomains, -+ vserverNumOfDefinedDomains, -+ vserverDomainCreate, -+ vserverDomainDefineXML, -+ vserverDomainUndefine, -+ vserverDomainAttachDevice, -+ vserverDomainDetachDevice, -+ vserverDomainGetAutostart, -+ vserverDomainSetAutostart, -+ vserverDomainGetSchedulerType, -+ vserverDomainGetSchedulerParams, -+ vserverDomainSetSchedulerParams, -+ NULL, /* domainMigratePrepare */ -+ NULL, /* domainMigratePerform */ -+ NULL, /* domainMigrateFinish */ -+ NULL, /* domainBlockStats */ -+ NULL, /* domainInterfaceStats */ -+ NULL, /* nodeGetCellsFreeMemory */ -+ NULL, /* getFreeMemory */ -+}; -+ -+int vserverRegister(void) -+{ -+ if (virRegisterDriver(&vserverDriver) < 0) -+ return -1; -+ return 0; -+} -+ -+#endif ---- libvirt-0.4.0.orig/src/vserver/vserver_driver.h 1970-01-01 01:00:00.000000000 +0100 -+++ libvirt-0.4.0.vserver/src/vserver/vserver_driver.h 2008-01-09 19:14:08.000000000 +0100 -@@ -0,0 +1,137 @@ -+/* -+ * Core driver for managing Linux-VServer guests -+ * -+ * Copyright (C) 2007 Daniel Hokka Zakrisson -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Daniel Hokka Zakrisson -+ */ -+ -+#ifdef WITH_VSERVER -+ -+/* Kind of a hack */ -+#ifdef IN_VSERVER -+#ifndef HAVE_XID_T -+typedef unsigned int xid_t; -+#endif -+#ifndef HAVE_NID_T -+typedef unsigned int nid_t; -+#endif -+#ifndef HAVE_TAG_T -+typedef unsigned int tag_t; -+#endif -+#include -+ -+#define VSERVER_NAME_MAX 64 -+#define VSERVER_UTS_MAX 255 -+ -+enum vserver_initstyle { -+ VSERVER_INIT_NONE, -+ VSERVER_INIT_SYSV, -+ VSERVER_INIT_PLAIN, -+ VSERVER_INIT_GENTOO, -+ VSERVER_INIT_MINIT, -+}; -+ -+struct vserver_ip { -+ char interface[IFNAMSIZ+1]; -+ struct vc_net_addr addr; -+ struct vserver_ip *next; -+}; -+ -+enum fstab_flags { -+ VSERVER_FSTAB_SHOW=1, -+ VSERVER_FSTAB_OUTPUT=2, -+}; -+struct vserver_fstab { -+ char *source; -+ const char *source_type; -+ char *target; -+ char *fstype; -+ char *options; -+ char *rest; -+ int flags; -+ struct vserver_fstab *next; -+}; -+ -+struct vserver_guest { -+ xid_t xid; -+ char name[VSERVER_NAME_MAX]; -+ unsigned char uuid[VIR_UUID_BUFLEN]; -+ char *path; -+ -+ struct { -+ char hostname[VSERVER_UTS_MAX]; -+ char machine[VSERVER_UTS_MAX]; -+ char release[VSERVER_UTS_MAX]; -+ char version[VSERVER_UTS_MAX]; -+ } uts; -+ -+ struct vserver_ip *ips; -+ -+ struct vc_set_sched sched; -+ unsigned long rss_hard; -+ -+ char autostart; -+ enum vserver_initstyle initstyle; -+ -+ int status; -+ -+ struct vserver_fstab *fstab; -+ -+ struct vserver_guest *next; -+}; -+ -+struct vserver_driver { -+ struct vserver_guest *guests; -+ xmlChar *uri; -+ unsigned int active_guests; -+ unsigned int inactive_guests; -+ unsigned int initialized : 1; -+}; -+ -+ -+#define list_add_tail(list, elem) \ -+ do { \ -+ __typeof__(list) iter; \ -+ if (list) { \ -+ for (iter = list; iter->next; iter = iter->next) \ -+ ; \ -+ iter->next = elem; \ -+ } \ -+ else \ -+ list = elem; \ -+ } while (0) -+ -+static inline int -+vserverIsRunning(struct vserver_guest *guest) { -+ if (guest->status == VIR_DOMAIN_RUNNING || guest->status == VIR_DOMAIN_PAUSED) -+ return 1; -+ else -+ return 0; -+} -+ -+ -+int vserverContextIsRunning(const char *path); -+int vserverRunCommand(int do_daemon, const char *cmd, ...); -+void vserverError(virConnectPtr con, virDomainPtr dom, virNetworkPtr net, -+ virErrorNumber error, const char *info); -+#endif -+ -+ -+extern int vserverRegister(void); -+ -+#endif