1 https://www.redhat.com/archives/libvir-list/2008-January/msg00097.html
3 From: "Daniel Hokka Zakrisson" <daniel hozac com>
4 To: libvir-list redhat com
5 Subject: [Libvir] [PATCH] Linux-VServer support
6 Date: Wed, 9 Jan 2008 22:51:20 +0100 (CET)
8 This patch implements support for Linux-VServer guests. It is currently
9 missing vcpu and console support, and the necessary virsh code to support
10 it, but is otherwise pretty feature complete.
12 This is an XML dump from one of my guests:
13 <domain type='vserver' id='40010'>
15 <uuid>19e12957-261a-5a06-d6d0-89917d6d439f</uuid>
16 <memory>2048000</memory>
18 <hostname>lenny.test</hostname>
19 <type arch='i686'>vserver</type>
22 <interface type='ethernet'>
23 <ip prefix='24' interface='dummy0' address='192.168.20.4' />
25 <interface type='ethernet'>
26 <ip prefix='24' interface='dummy0' type='range' address='192.168.32.100' address2='192.168.32.200'/>
28 <disk type='directory' device='directory'>
29 <source directory='/vservers/lenny' type='auto' options='defaults'/>
30 <target directory='/'/>
32 <disk type='directory' device='directory'>
33 <source directory='/srv' type='ext3' options='bind,ro'/>
34 <target directory='/srv'/>
36 <disk type='block' device='directory'>
37 <source dev='/dev/mapper/test' type='ext3' options='defaults'/>
38 <target directory='/mnt'/>
44 Daniel Hokka Zakrisson
45 --- libvirt-1.2.3/configure.ac~ 2014-04-06 12:21:22.000000000 +0300
46 +++ libvirt-1.2.3/configure.ac 2014-04-06 12:22:55.249258975 +0300
48 [AS_HELP_STRING([--with-parallels],
49 [add Parallels Cloud Server support @<:@default=check@:>@])])
50 m4_divert_text([DEFAULTS], [with_parallels=check])
51 +AC_ARG_WITH([vserver],
52 + [AS_HELP_STRING([--with-vserver],
53 + [add Linux-VServer support @<:@default=check@:>@])])
54 +m4_divert_text([DEFAULTS], [with_vserver=check])
56 [AS_HELP_STRING([--with-test],
57 [add test driver support @<:@default=yes@:>@])])
62 +if test "$with_vserver" = "yes" ; then
63 + AC_CHECK_LIB(vserver, [vc_rlimit_stat],, [with_vserver=no])
64 + AC_CHECK_TYPES([xid_t, nid_t, tag_t])
65 + AC_CHECK_HEADER(vserver.h,, [with_vserver=no], [AC_INCLUDES_DEFAULT()
67 +typedef unsigned int xid_t;
70 +typedef unsigned int nid_t;
73 +typedef unsigned int tag_t;
76 + AC_MSG_CHECKING([for vserver configuration directory])
77 + VSERVER_CONF_DIR=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \
78 + vserver-info - SYSINFO | sed -n 's/^.*cfg-Directory:.//p'`
79 + AC_MSG_RESULT([$VSERVER_CONF_DIR])
80 + AC_DEFINE_UNQUOTED([VSERVER_CONF_DIR], ["$VSERVER_CONF_DIR"],
81 + [The default path to the Linux-VServer configuration files])
83 + AC_MSG_CHECKING([for the vserver program])
84 + PROG_VSERVER=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \
85 + which vserver 2> /dev/null` || with_vserver=no
86 + AC_MSG_RESULT([$PROG_VSERVER])
87 + AC_DEFINE_UNQUOTED([PROG_VSERVER], ["$PROG_VSERVER"],
88 + [The path to the vserver program])
90 + if test "$with_vserver" = "yes" ; then
91 + LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_VSERVER"
97 dnl check for kernel headers required by src/bridge.c
99 AC_MSG_NOTICE([ ESX: $with_esx])
100 AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
101 AC_MSG_NOTICE([Parallels: $with_parallels])
102 +AC_MSG_NOTICE([ VServer: $with_vserver])
103 LIBVIRT_DRIVER_RESULT_BHYVE
104 AC_MSG_NOTICE([ Test: $with_test])
105 AC_MSG_NOTICE([ Remote: $with_remote])
106 --- libvirt-1.1.1/include/libvirt/virterror.h~ 2013-07-24 03:23:07.000000000 +0300
107 +++ libvirt-1.1.1/include/libvirt/virterror.h 2013-09-01 00:07:44.097192613 +0300
109 VIR_FROM_ACCESS = 55, /* Error from access control manager */
110 VIR_FROM_SYSTEMD = 56, /* Error from systemd code */
112 + VIR_FROM_VSERVER = 57, /* Error from Linux-VServer driver */
114 # ifdef VIR_ENUM_SENTINELS
117 --- libvirt-1.2.3/src/driver.h~ 2014-03-27 12:35:00.000000000 +0200
118 +++ libvirt-1.2.3/src/driver.h 2014-04-06 12:25:03.124800629 +0300
121 VIR_DRV_PARALLELS = 16,
123 + VIR_DRV_VSERVER = 18,
127 --- libvirt-1.1.1/src/libvirt.c~ 2013-09-01 00:20:50.000000000 +0300
128 +++ libvirt-1.1.1/src/libvirt.c 2013-09-01 00:21:02.812830784 +0300
130 #ifdef WITH_PARALLELS
131 # include "parallels/parallels_driver.h"
134 +# include "server/vserver_driver.h"
137 #define VIR_FROM_THIS VIR_FROM_NONE
140 if (parallelsRegister() == -1)
144 + if (verversRegister() == -1)
148 if (remoteRegister() == -1)
150 --- libvirt-1.1.1/src/Makefile.am~ 2013-07-30 10:21:31.000000000 +0300
151 +++ libvirt-1.1.1/src/Makefile.am 2013-09-01 00:11:19.080124997 +0300
153 $(NWFILTER_DRIVER_SOURCES) \
154 $(OPENVZ_DRIVER_SOURCES) \
155 $(PARALLELS_DRIVER_SOURCES) \
156 + $(VSERVER_DRIVER_SOURCES) \
157 $(PHYP_DRIVER_SOURCES) \
158 $(QEMU_DRIVER_SOURCES) \
159 $(REMOTE_DRIVER_SOURCES) \
161 parallels/parallels_storage.c \
162 parallels/parallels_network.c
164 +VSERVER_DRIVER_SOURCES = \
165 + vserver/vserver_driver.h \
166 + vserver/vserver_driver.c \
167 + vserver/vserver_conf.h \
168 + vserver/vserver_conf.c
170 NETWORK_DRIVER_SOURCES = \
171 network/bridge_driver.h network/bridge_driver.c
173 --- libvirt-1.2.3/src/util/virerror.c~ 2014-03-27 12:35:01.000000000 +0200
174 +++ libvirt-1.2.3/src/util/virerror.c 2014-04-06 12:25:58.523869047 +0300
177 "Access Manager", /* 55 */
183 --- libvirt-0.4.0.orig/src/vserver/vserver_conf.c 1970-01-01 01:00:00.000000000 +0100
184 +++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.c 2008-01-09 08:52:11.000000000 +0100
187 + * Configuration handling for Linux-VServer guests
189 + * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
191 + * This library is free software; you can redistribute it and/or
192 + * modify it under the terms of the GNU Lesser General Public
193 + * License as published by the Free Software Foundation; either
194 + * version 2.1 of the License, or (at your option) any later version.
196 + * This library is distributed in the hope that it will be useful,
197 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
198 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
199 + * Lesser General Public License for more details.
201 + * You should have received a copy of the GNU Lesser General Public
202 + * License along with this library; if not, write to the Free Software
203 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
205 + * Author: Daniel Hokka Zakrisson <daniel hozac com>
212 +#ifdef HAVE_CONFIG_H
213 +# include <config.h>
222 +#include <sys/types.h>
223 +#include <sys/socket.h>
224 +#include <arpa/inet.h>
226 +#include <sys/stat.h>
229 +#include <libvirt/virterror.h>
231 +#define IN_VSERVER 1
232 +#include "internal.h"
233 +#include "vserver_driver.h"
234 +#include "vserver_conf.h"
238 +readStr(char *dst, size_t len, const char *name, const char *setting)
240 + char file[strlen(name) + strlen(setting) + 2];
245 + sprintf(file, "%s/%s", name, setting);
247 + /* a non-existant file is not a failure */
249 + if ((fd = open(file, O_RDONLY)) == -1)
252 + if ((bytes = read(fd, dst, len - 1)) == -1) {
260 + if ((p = strchr(dst, '\n')) != NULL)
267 +readLong(void *v_dst, const char *name, const char *setting)
269 + char buf[128], *endptr;
273 + ret = readStr(buf, sizeof(buf), name, setting);
277 + *dst = strtol(buf, &endptr, 0);
278 + if (endptr && *endptr != '\0')
285 +readInt(void *v_dst, const char *name, const char *setting)
291 + ret = readLong(&val, name, setting);
301 +readBool(char *dst, const char *name, const char *setting)
303 + char file[strlen(name) + strlen(setting) + 2];
305 + sprintf(file, "%s/%s", name, setting);
307 + *dst = access(file, F_OK) != -1;
313 +vserverWriteToConfig(struct vserver_guest *guest, const char *filename,
314 + const char *format, ...)
316 + char path[strlen(guest->path) + 1 + strlen(filename) + 1];
320 + ssize_t len, off, ret;
323 + sprintf(path, "%s/%s", guest->path, filename);
325 + /* ensure the directory exists */
326 + dir = strrchr(path, '/');
328 + if (mkdir(path, 0755) && errno != EEXIST)
332 + va_start(va, format);
333 + if (strcmp(format, "%b") == 0) {
334 + /* bool, this is a special case */
335 + if (va_arg(va, int)) {
340 + if (unlink(path) == -1 && errno != ENOENT)
347 + len = vsnprintf(value, sizeof(value), format, va);
350 + fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0644);
354 + for (off = 0; off < len; off += ret) {
355 + ret = write(fd, value + off, len - off);
362 + if (close(fd) == -1)
367 +#define WRITE(...) if (vserverWriteToConfig(guest, __VA_ARGS__) == -1) \
369 +#define WRITE_SCHED_VAL(sched, file, mask, format, value) \
370 + if ((sched)->set_mask & mask) { \
371 + WRITE(file, format, value); \
373 +#define WRITE_SCHED(dir, sched) \
375 + WRITE_SCHED_VAL(sched, dir "/fill-rate", \
376 + VC_VXSM_FILL_RATE, "%u\n", \
377 + (sched)->fill_rate); \
378 + WRITE_SCHED_VAL(sched, dir "/interval", \
379 + VC_VXSM_INTERVAL, "%u\n", \
380 + (sched)->interval); \
381 + WRITE_SCHED_VAL(sched, dir "/fill-rate2", \
382 + VC_VXSM_FILL_RATE2, "%u\n", \
383 + (sched)->fill_rate2); \
384 + WRITE_SCHED_VAL(sched, dir "/interval2", \
385 + VC_VXSM_INTERVAL2, "%u\n", \
386 + (sched)->interval2); \
387 + WRITE_SCHED_VAL(sched, dir "/tokens-min", \
388 + VC_VXSM_TOKENS_MIN, "%u\n", \
389 + (sched)->tokens_min); \
390 + WRITE_SCHED_VAL(sched, dir "/tokens-max", \
391 + VC_VXSM_TOKENS_MAX, "%u\n", \
392 + (sched)->tokens_max); \
393 + WRITE_SCHED_VAL(sched, dir "/priority-bias", \
394 + VC_VXSM_PRIO_BIAS, "%u\n", \
395 + (sched)->priority_bias); \
396 + WRITE(dir "/idle-time", "%b", \
397 + (sched)->set_mask & VC_VXSM_IDLE_TIME); \
399 +#define WRITE_IP(filename, v4var, v6var) \
400 + strcpy(file, filename); \
402 + case VC_NXA_TYPE_IPV4: \
403 + inet_ntop(AF_INET, (v4var), buf, sizeof(buf)); \
405 + case VC_NXA_TYPE_IPV6: \
406 + inet_ntop(AF_INET6, (v6var), buf, sizeof(buf)); \
409 + WRITE(dir, "%s\n", buf);
412 +writeInterfaces(struct vserver_guest *guest)
414 + char name[strlen(guest->path) + sizeof("/interfaces/XXXXXX/prefix")],
417 + struct vserver_ip *ip;
420 + snprintf(name, sizeof(name), "%s/interfaces", guest->path);
421 + if (vserverRunCommand(0, "rm", "-fr", name, NULL) != 0)
423 + if (mkdir(name, 0755) == -1)
426 + dir = name + strlen(guest->path) + 1;
427 + for (ip = guest->ips, i = 0; ip; ip = ip->next, i++) {
430 + /* Yeah right... */
437 + file += snprintf(dir, sizeof(name) - (dir - name), "interfaces/%u", i);
438 + if (mkdir(name, 0755) == -1)
441 + type = ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6);
443 + strcpy(file, "/prefix");
444 + WRITE(dir, "%u\n", ip->addr.vna_prefix);
446 + if (*ip->interface) {
447 + strcpy(file, "/dev");
448 + WRITE(dir, "%s\n", ip->interface);
451 + strcpy(file, "/nodev");
452 + WRITE(dir, "%b", 1);
455 + WRITE_IP("/ip", &ip->addr.vna_v4_ip, &ip->addr.vna_v6_ip);
456 + if (ip->addr.vna_type & VC_NXA_TYPE_RANGE) {
457 + WRITE_IP("/ip2", &ip->addr.vna_v4_ip2, &ip->addr.vna_v6_ip2);
459 + if (ip->addr.vna_type & (VC_NXA_TYPE_RANGE|VC_NXA_TYPE_MASK)) {
460 + WRITE_IP("/mask", &ip->addr.vna_v4_mask, &ip->addr.vna_v6_mask);
467 +writeFstab(struct vserver_guest *guest)
470 + struct vserver_fstab *ent;
471 + char file[strlen(guest->path) + sizeof("/fstab")];
473 + sprintf(file, "%s/fstab", guest->path);
474 + fp = fopen(file, "w");
478 + for (ent = guest->fstab; ent; ent = ent->next) {
479 + if (!(ent->flags & VSERVER_FSTAB_OUTPUT))
481 + fprintf(fp, "%s\t%s\t%s\t%s\t%s\n", ent->source, ent->target,
482 + ent->fstype, ent->options, (ent->rest ? ent->rest : ""));
485 + if (fclose(fp) == -1)
492 +vserverWriteGuestToConfig(struct vserver_guest *guest)
496 + WRITE("context", "%u\n", guest->xid);
497 + WRITE("name", "%s\n", guest->name);
498 + virUUIDFormat(guest->uuid, buf);
499 + WRITE("uuid", "%s\n", buf);
500 + if (*guest->uts.hostname)
501 + WRITE("uts/nodename", "%s\n", guest->uts.hostname);
502 + if (*guest->uts.machine)
503 + WRITE("uts/machine", "%s\n", guest->uts.machine);
504 + if (*guest->uts.release)
505 + WRITE("uts/release", "%s\n", guest->uts.release);
506 + if (*guest->uts.version)
507 + WRITE("uts/version", "%s\n", guest->uts.version);
508 + if (guest->rss_hard > 0)
509 + WRITE("rlimits/rss.hard", "%lu\n", guest->rss_hard);
510 + WRITE("apps/init/mark", (guest->autostart ? "default\n" : "\n"));
511 + WRITE_SCHED("sched", &guest->sched);
513 + if (writeInterfaces(guest) == -1)
516 + if (writeFstab(guest) == -1)
523 +#undef WRITE_SCHED_VAL
527 +parseInterfaces(struct vserver_guest *guest, const char *directory)
530 + struct dirent *interface;
531 + struct vserver_ip *ip = NULL;
532 + char ipath[256], *subdir;
534 + char s_ip[48], s_prefix[4], s_mask[48], s_dev[32], s_ip2[48];
537 + subdir += snprintf(ipath, sizeof(ipath), "%s/%s", guest->name, directory);
538 + spare = sizeof(ipath) - (subdir - ipath);
540 + interfaces = opendir(ipath);
544 + while ((interface = readdir(interfaces)) != NULL) {
545 + if (*interface->d_name == '.')
547 + /* would overflow */
548 + if (strlen(interface->d_name) + sizeof("//disabled") > spare)
551 + snprintf(subdir, spare, "/%s/disabled", interface->d_name);
552 + if (access(ipath, F_OK) != -1)
555 + snprintf(subdir, spare, "/%s", interface->d_name);
558 + if (readStr(s_ip, sizeof(s_ip), ipath, "ip") == 0 &&
559 + (readStr(s_prefix, sizeof(s_prefix), ipath, "prefix") == 0 ||
560 + readStr(s_mask, sizeof(s_mask), ipath, "mask") == 0)) {
561 + if (readStr(s_dev, sizeof(s_dev), ipath, "dev") != 0)
563 + if (readStr(s_ip2, sizeof(s_ip2), ipath, "ip2") != 0)
570 + guest->ips = ip = calloc(1, sizeof(*ip));
572 + ip->next = calloc(1, sizeof(*ip));
578 + strcpy(ip->interface, s_dev);
580 + if (inet_pton(AF_INET6, s_ip, &ip->addr.vna_v6_ip) > 0)
581 + ip->addr.vna_type = VC_NXA_TYPE_IPV6;
582 + else if (inet_pton(AF_INET, s_ip, &ip->addr.vna_v4_ip) > 0)
583 + ip->addr.vna_type = VC_NXA_TYPE_IPV4;
587 + if (ip->addr.vna_type == VC_NXA_TYPE_IPV6) {
589 + if (inet_pton(AF_INET6, s_mask, &ip->addr.vna_v6_mask) <= 0)
593 + if (inet_pton(AF_INET6, s_ip2, &ip->addr.vna_v6_ip2) <= 0)
595 + ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
598 + ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
600 + else if (ip->addr.vna_type == VC_NXA_TYPE_IPV4) {
602 + if (inet_pton(AF_INET, s_mask, &ip->addr.vna_v4_mask) <= 0)
606 + if (inet_pton(AF_INET, s_ip2, &ip->addr.vna_v4_ip2) <= 0)
608 + ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
611 + ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
616 + ip->addr.vna_prefix = strtoul(s_prefix, &endptr, 0);
617 + if (*endptr != '\n' && *endptr)
622 + closedir(interfaces);
626 + closedir(interfaces);
630 +static inline char *
631 +endOfField(char *start)
634 + for (end = start; *(end - 1) != '\\' &&
636 + *end != '\0'; end++)
641 +static inline char *
642 +startOfField(char *end)
645 + for (start = end + 1; isspace(*start) &&
646 + *start != '\0'; start++)
651 +static const struct {
654 +} source_types[] = {
655 + { S_IFBLK, "block" },
656 + { S_IFREG, "file" },
657 + { S_IFDIR, "directory" },
661 +vserverFindSourceType(const char *source)
665 + if (stat(source, &st) == -1)
668 + mode = st.st_mode & S_IFMT;
669 + for (i = 0; i < (sizeof(source_types) / sizeof(*source_types)); i++) {
670 + if (mode == source_types[i].mode)
671 + return source_types[i].type;
677 +parseFstab(struct vserver_guest *guest, const char *filename)
680 + char buf[256], *start, *end;
681 + struct vserver_fstab *ent = NULL;
682 + char path[strlen(guest->name) + 2 + strlen(filename)];
684 + sprintf(path, "%s/%s", guest->name, filename);
685 + if ((fp = fopen(path, "r")) == NULL)
688 + while (fgets(buf, sizeof(buf), fp) != NULL) {
690 + guest->fstab = ent = calloc(1, sizeof(*ent));
692 + ent->next = calloc(1, sizeof(*ent));
699 + end = endOfField(start);
701 + ent->source = strdup(start);
702 + ent->source_type = vserverFindSourceType(start);
704 + ent->flags |= VSERVER_FSTAB_OUTPUT;
705 + if (ent->source_type)
706 + ent->flags |= VSERVER_FSTAB_SHOW;
708 + start = startOfField(end);
709 + end = endOfField(start);
711 + ent->target = strdup(start);
713 + start = startOfField(end);
714 + end = endOfField(start);
716 + ent->fstype = strdup(start);
718 + start = startOfField(end);
719 + end = endOfField(start);
720 + if (*end != '\0') {
722 + ent->rest = strdup(end + 1);
723 + ptr = strchr(ent->rest, '\n');
730 + ent->options = strdup(start);
732 + if (!ent->source || !ent->target || !ent->fstype || !ent->options)
745 +vserverInitializeDriver(virConnectPtr conn, struct vserver_driver *driver,
748 + struct vserver_guest *guest = NULL;
752 + const char *conf_dir = (*path ? path : VSERVER_CONF_DIR);
754 + if (driver->initialized == 1)
755 + return VIR_DRV_OPEN_SUCCESS;
757 + driver->guests = NULL;
758 + driver->inactive_guests = driver->active_guests = 0;
760 + cwd = open(".", O_RDONLY);
762 + chdir(conf_dir) == -1 ||
763 + (dp = opendir(".")) == NULL) {
764 + vserverError(conn, NULL, NULL, VIR_ERR_OPEN_FAILED, conf_dir);
768 + while ((de = readdir(dp)) != NULL) {
769 + char uuidstr[VIR_UUID_STRING_BUFLEN + 1];
773 + if (*de->d_name == '.')
776 + if (driver->guests == NULL)
777 + driver->guests = guest = calloc(1, sizeof(struct vserver_guest));
779 + guest->next = calloc(1, sizeof(struct vserver_guest));
780 + guest = guest->next;
784 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
789 + guest->path = calloc(strlen(conf_dir) + 1 + strlen(de->d_name) + 1, sizeof(char));
792 + sprintf(guest->path, "%s/%s", conf_dir, de->d_name);
798 +#define DO_SCHED(type, var, file, bit) \
801 + CHECK(ret = read ## type((var), de->d_name, (file))); \
803 + guest->sched.set_mask |= (bit); \
806 + /* Parse simple values */
807 + CHECK(readInt(&guest->xid, de->d_name, "context"));
808 + CHECK(readStr(guest->name, sizeof(guest->name), de->d_name, "name"));
809 + CHECK(readStr(guest->uts.hostname, sizeof(guest->uts.hostname), de->d_name,
811 + CHECK(readStr(guest->uts.machine, sizeof(guest->uts.machine), de->d_name,
813 + CHECK(readStr(guest->uts.release, sizeof(guest->uts.release), de->d_name,
815 + CHECK(readStr(guest->uts.version, sizeof(guest->uts.version), de->d_name,
817 + CHECK(readStr(mark, sizeof(mark), de->d_name, "apps/init/mark"));
819 + DO_SCHED(Int, &guest->sched.fill_rate, "sched/fill-rate",
820 + VC_VXSM_FILL_RATE);
821 + DO_SCHED(Int, &guest->sched.interval, "sched/interval",
823 + DO_SCHED(Int, &guest->sched.fill_rate2, "sched/fill-rate2",
824 + VC_VXSM_FILL_RATE2);
825 + DO_SCHED(Int, &guest->sched.interval2, "sched/interval2",
826 + VC_VXSM_INTERVAL2);
827 + DO_SCHED(Int, &guest->sched.tokens_min, "sched/tokens-min",
828 + VC_VXSM_TOKENS_MIN);
829 + DO_SCHED(Int, &guest->sched.tokens_max, "sched/tokens-max",
830 + VC_VXSM_TOKENS_MAX);
831 + DO_SCHED(Int, &guest->sched.priority_bias, "sched/priority-bias",
832 + VC_VXSM_PRIO_BIAS);
833 + if (readBool(&tmp, de->d_name, "sched/idle-time") == 0) {
835 + guest->sched.set_mask |= VC_VXSM_IDLE_TIME;
838 + CHECK(readLong(&guest->rss_hard, de->d_name, "rlimits/rss.hard"));
840 + /* Generate a UUID if one doesn't already exist */
841 + switch (readStr(uuidstr, sizeof(uuidstr), de->d_name, "uuid")) {
843 + CHECK(virUUIDGenerate(guest->uuid));
844 + virUUIDFormat(guest->uuid, uuidstr);
845 + CHECK(vserverWriteToConfig(guest, "uuid", "%s\n", uuidstr));
848 + CHECK(virUUIDParse(uuidstr, guest->uuid));
854 + /* Parse interfaces */
855 + if (parseInterfaces(guest, "interfaces") == -1)
859 + if (parseFstab(guest, "fstab") == -1)
862 + /* Make sure the guest has the / directory in the disk output */
864 + struct vserver_fstab *ent;
866 + for (ent = guest->fstab; ent; ent = ent->next) {
867 + if (strcmp(ent->target, "/") == 0) {
873 + char vdir[strlen(de->d_name) + sizeof("/vdir")];
875 + ent = calloc(1, sizeof(*ent));
879 + sprintf(vdir, "%s/vdir", de->d_name);
880 + ent->source = realpath(vdir, NULL);
882 + ent->flags = VSERVER_FSTAB_SHOW;
883 + ent->source_type = vserverFindSourceType("/");
884 + ent->target = strdup("/");
885 + ent->fstype = strdup("auto");
886 + ent->options = strdup("defaults");
887 + if (!ent->source || !ent->target || !ent->fstype || !ent->options)
889 + ent->next = guest->fstab;
890 + guest->fstab = ent;
896 + if (STREQ(mark, "default"))
897 + guest->autostart = 1;
898 + if (vserverContextIsRunning(guest->path)) {
899 + struct vc_ctx_flags flags;
900 + if (vc_get_cflags(guest->xid, &flags) == 0 &&
901 + (flags.flagword & VC_VXF_SCHED_PAUSE))
902 + guest->status = VIR_DOMAIN_PAUSED;
904 + guest->status = VIR_DOMAIN_RUNNING;
905 + driver->active_guests++;
908 + guest->status = VIR_DOMAIN_SHUTOFF;
909 + driver->inactive_guests++;
914 + if (fchdir(cwd) == -1 || close(cwd) == -1) {
915 + /* do nothing, we succeeded with everything else... */
917 + driver->initialized = 1;
919 + return VIR_DRV_OPEN_SUCCESS;
922 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
925 + vserverError(conn, NULL, NULL, VIR_ERR_PARSE_FAILED, de->d_name);
930 + if (fchdir(cwd) == -1 || close(cwd) == -1) {
931 + /* we're already failing, nothing to do */
933 + return VIR_DRV_OPEN_ERROR;
937 --- libvirt-0.4.0.orig/src/vserver/vserver_conf.h 1970-01-01 01:00:00.000000000 +0100
938 +++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.h 2008-01-05 02:10:20.000000000 +0100
941 + * Configuration handling for Linux-VServer guests
943 + * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
945 + * This library is free software; you can redistribute it and/or
946 + * modify it under the terms of the GNU Lesser General Public
947 + * License as published by the Free Software Foundation; either
948 + * version 2.1 of the License, or (at your option) any later version.
950 + * This library is distributed in the hope that it will be useful,
951 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
952 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
953 + * Lesser General Public License for more details.
955 + * You should have received a copy of the GNU Lesser General Public
956 + * License along with this library; if not, write to the Free Software
957 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
959 + * Author: Daniel Hokka Zakrisson <daniel hozac com>
964 +/* Kind of a hack */
966 +int vserverWriteToConfig(struct vserver_guest *guest, const char *filename,
967 + const char *format, ...);
968 +int vserverWriteGuestToConfig(struct vserver_guest *guest);
969 +virDrvOpenStatus vserverInitializeDriver(virConnectPtr conn,
970 + struct vserver_driver *driver,
972 +const char *vserverFindSourceType(const char *source);
976 diff -Nurp libvirt-0.4.0.orig/src/vserver_driver.c libvirt-0.4.0.vserver/src/vserver_driver.c
977 --- libvirt-0.4.0.orig/src/vserver_driver.c 1970-01-01 01:00:00.000000000 +0100
978 +++ libvirt-0.4.0.vserver/src/vserver_driver.c 2008-01-09 22:43:23.000000000 +0100
981 + * Core driver for managing Linux-VServer guests
983 + * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
985 + * This library is free software; you can redistribute it and/or
986 + * modify it under the terms of the GNU Lesser General Public
987 + * License as published by the Free Software Foundation; either
988 + * version 2.1 of the License, or (at your option) any later version.
990 + * This library is distributed in the hope that it will be useful,
991 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
992 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
993 + * Lesser General Public License for more details.
995 + * You should have received a copy of the GNU Lesser General Public
996 + * License along with this library; if not, write to the Free Software
997 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
999 + * Author: Daniel Hokka Zakrisson <daniel hozac com>
1002 +#ifdef WITH_VSERVER
1004 +#define _GNU_SOURCE
1006 +#ifdef HAVE_CONFIG_H
1007 +# include <config.h>
1011 +#include <unistd.h>
1012 +#include <stdlib.h>
1013 +#include <string.h>
1015 +#include <dirent.h>
1016 +#include <sys/wait.h>
1018 +#include <sys/types.h>
1019 +#include <sys/socket.h>
1020 +#include <arpa/inet.h>
1021 +#include <net/if.h>
1022 +#include <sys/syscall.h>
1024 +#include <libxml/uri.h>
1025 +#include <libxml/xpath.h>
1026 +#include <libxml/tree.h>
1028 +#include <libvirt/virterror.h>
1030 +#define IN_VSERVER 1
1031 +#include "internal.h"
1032 +#include "vserver_driver.h"
1033 +#include "vserver_conf.h"
1037 +#include "nodeinfo.h"
1039 +#define GET_DOMAIN(dom, ret) \
1040 + struct vserver_driver *driver = (struct vserver_driver *) \
1041 + (dom)->conn->privateData; \
1042 + struct vserver_guest *guest = getGuestByUUID(driver, (dom)->uuid); \
1045 + vserverError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \
1051 +# define MNT_DETACH 0x00000002
1054 +static int PAGE_SHIFT_TO_KIBI = 2;
1056 +static inline int sys_umount(const char *path, int flags)
1058 + return syscall(__NR_umount2, path, flags);
1061 +static inline struct vserver_guest *
1062 +getGuestByID(struct vserver_driver *driver,
1065 + struct vserver_guest *res;
1066 + for (res = driver->guests; res; res = res->next) {
1067 + if (res->xid == id)
1073 +static inline struct vserver_guest *
1074 +getGuestByUUID(struct vserver_driver *driver,
1075 + const unsigned char *uuid)
1077 + struct vserver_guest *res;
1078 + for (res = driver->guests; res; res = res->next) {
1079 + if (memcmp(res->uuid, uuid, VIR_UUID_BUFLEN) == 0)
1085 +static inline struct vserver_guest *
1086 +getGuestByName(struct vserver_driver *driver,
1089 + struct vserver_guest *res;
1090 + for (res = driver->guests; res; res = res->next) {
1091 + if (STREQ(res->name, name))
1098 +vserverError(virConnectPtr con,
1100 + virNetworkPtr net,
1101 + virErrorNumber error,
1104 + const char *errmsg;
1106 + if (error == VIR_ERR_OK)
1109 + errmsg = __virErrorMsg(error, info);
1110 + __virRaiseError(con, dom, net, VIR_FROM_VSERVER, error, VIR_ERR_ERROR,
1111 + errmsg, info, NULL, 0, 0, errmsg, info, 0);
1114 +/* like execl, but uses /dev/null and handles forking/waiting/etc. */
1116 +vserverRunCommand(int do_daemon, const char *cmd, ...)
1122 + sighandler_t sigchld;
1125 + va_start(va, cmd);
1127 + argv = calloc(argc, sizeof(*argv));
1128 + argv[0] = (char *) cmd;
1129 + for (i = 1; (argv[i] = va_arg(va, char *)) != NULL; i++) {
1130 + if (i == argc-1) {
1132 + argv = realloc(argv, sizeof(*argv) * argc);
1138 + /* XXX: This is bad, since another child could die
1139 + * between here and where we restore it */
1140 + sigchld = signal(SIGCHLD, SIG_DFL);
1141 + if ((pid = fork()) == 0) {
1144 + pid_t not_a_zombie;
1146 + if (setsid() == -1)
1149 + not_a_zombie = fork();
1150 + if (not_a_zombie == -1)
1152 + else if (not_a_zombie > 0)
1155 + if ((fd = open("/dev/null", O_RDWR)) == -1)
1157 + if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1)
1159 + if (fd > 2 && close(fd) == -1)
1161 + execvp(cmd, argv);
1165 + else if (pid == -1) {
1170 + if (waitpid(pid, &status, 0) == -1)
1172 + else if (WEXITSTATUS(status) != 0)
1178 + signal(SIGCHLD, sigchld);
1183 +vserverContextIsRunning(const char *path)
1185 + return vc_getVserverCtx(path, vcCFG_AUTO, false, 0, vcCTX_XID) != VC_NOCTX;
1189 +vserverSetPagesize(void)
1191 + long page_size = sysconf(_SC_PAGESIZE);
1192 + PAGE_SHIFT_TO_KIBI = page_size / 1024;
1195 +static virDrvOpenStatus
1196 +vserverOpen(virConnectPtr conn, xmlURIPtr uri,
1197 + virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1198 + int flags ATTRIBUTE_UNUSED)
1200 + virDrvOpenStatus ret;
1201 + struct vserver_driver *driver;
1204 + return VIR_DRV_OPEN_DECLINED;
1206 + if (getuid() != 0)
1207 + return VIR_DRV_OPEN_DECLINED;
1209 + if (!uri->scheme || STRNEQ(uri->scheme, "vserver"))
1210 + return VIR_DRV_OPEN_DECLINED;
1213 + return VIR_DRV_OPEN_DECLINED;
1215 + /* nothing else supported right now */
1216 + if (strncmp(uri->path, "/system", 7) != 0)
1217 + return VIR_DRV_OPEN_DECLINED;
1219 + /* make sure it's a Linux-VServer kernel */
1220 + if (vc_get_version() == -1)
1221 + return VIR_DRV_OPEN_DECLINED;
1223 + if (!conn->privateData)
1224 + conn->privateData = calloc(1, sizeof(struct vserver_driver));
1226 + ret = vserverInitializeDriver(conn, conn->privateData, uri->path + 7);
1227 + if (ret == VIR_DRV_OPEN_SUCCESS) {
1228 + driver = conn->privateData;
1229 + driver->uri = xmlSaveUri(uri);
1232 + free(conn->privateData);
1235 + vserverSetPagesize();
1241 +freeFstab(struct vserver_fstab *ent)
1243 + free(ent->source);
1244 + free(ent->target);
1245 + free(ent->fstype);
1246 + free(ent->options);
1251 +freeGuest(struct vserver_guest *guest)
1253 + struct vserver_ip *ip, *pip = NULL;
1254 + struct vserver_fstab *ent, *pent = NULL;
1255 + for (ip = guest->ips; ip; ip = ip->next) {
1262 + for (ent = guest->fstab; ent; ent = ent->next) {
1269 + free(guest->path);
1274 +vserverClose(virConnectPtr conn)
1276 + struct vserver_driver *driver = conn->privateData;
1277 + struct vserver_guest *guest, *pguest;
1279 + if (!driver || !driver->initialized)
1282 + for (guest = driver->guests, pguest = NULL; guest; guest = guest->next) {
1284 + freeGuest(pguest);
1288 + freeGuest(pguest);
1290 + xmlFree(driver->uri);
1292 + conn->privateData = NULL;
1297 +static const char *
1298 +vserverGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
1300 + return "Linux-VServer";
1304 +vserverGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
1311 +vserverGetHostname(virConnectPtr conn)
1315 + ret = calloc(VSERVER_UTS_MAX + 1, sizeof(char));
1317 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "gethostname");
1321 + if (gethostname(ret, VSERVER_UTS_MAX) == -1) {
1323 + vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno));
1331 +vserverGetURI(virConnectPtr conn)
1333 + struct vserver_driver *driver = conn->privateData;
1334 + return (char *) xmlStrdup(driver->uri);
1338 +vserverNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
1340 + return virNodeInfoPopulate(conn, nodeinfo);
1344 +vserverListDomains(virConnectPtr conn, int *ids, int nids)
1346 + struct vserver_driver *driver = conn->privateData;
1347 + struct vserver_guest *guest;
1350 + for (guest = driver->guests, i = 0; guest && i < nids;
1351 + guest = guest->next) {
1352 + if (guest->status != VIR_DOMAIN_SHUTOFF)
1353 + ids[i++] = guest->xid;
1360 +vserverNumOfDomains(virConnectPtr conn)
1362 + struct vserver_driver *driver = conn->privateData;
1364 + return driver->active_guests;
1367 +static virDomainPtr
1368 +vserverDomainLookupByID(virConnectPtr conn, int id)
1370 + struct vserver_driver *driver = conn->privateData;
1371 + struct vserver_guest *guest;
1372 + virDomainPtr domain;
1374 + if ((guest = getGuestByID(driver, id)) == NULL) {
1375 + vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1376 + _("No domain by that ID found"));
1380 + domain = virGetDomain(conn, guest->name, guest->uuid);
1382 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1386 + if (vserverIsRunning(guest))
1387 + domain->id = guest->xid;
1392 +static virDomainPtr
1393 +vserverDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
1395 + struct vserver_driver *driver = conn->privateData;
1396 + struct vserver_guest *guest;
1397 + virDomainPtr domain;
1399 + if ((guest = getGuestByUUID(driver, uuid)) == NULL) {
1400 + vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1401 + _("No domain by that UUID found"));
1405 + domain = virGetDomain(conn, guest->name, guest->uuid);
1407 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1411 + if (vserverIsRunning(guest))
1412 + domain->id = guest->xid;
1417 +static virDomainPtr
1418 +vserverDomainLookupByName(virConnectPtr conn, const char *name)
1420 + struct vserver_driver *driver = conn->privateData;
1421 + struct vserver_guest *guest;
1422 + virDomainPtr domain;
1424 + if ((guest = getGuestByName(driver, name)) == NULL) {
1425 + vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1426 + _("No domain by that name found"));
1430 + domain = virGetDomain(conn, guest->name, guest->uuid);
1432 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1436 + if (vserverIsRunning(guest))
1437 + domain->id = guest->xid;
1443 +vserverDomainSuspend(virDomainPtr domain)
1445 + struct vc_ctx_flags flags = {
1446 + .flagword = VC_VXF_SCHED_PAUSE,
1447 + .mask = VC_VXF_SCHED_PAUSE,
1449 + GET_DOMAIN(domain, -1);
1451 + if (guest->status == VIR_DOMAIN_PAUSED)
1453 + if (guest->status != VIR_DOMAIN_RUNNING) {
1454 + vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED,
1455 + _("domain is not running"));
1459 + if (vc_set_cflags(guest->xid, &flags) == -1) {
1460 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1464 + guest->status = VIR_DOMAIN_PAUSED;
1470 +vserverDomainResume(virDomainPtr domain)
1472 + struct vc_ctx_flags flags = {
1474 + .mask = VC_VXF_SCHED_PAUSE,
1476 + GET_DOMAIN(domain, -1);
1478 + if (guest->status == VIR_DOMAIN_RUNNING)
1480 + if (guest->status != VIR_DOMAIN_PAUSED) {
1481 + vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED,
1482 + _("domain is not running"));
1486 + if (vc_set_cflags(guest->xid, &flags) == -1) {
1487 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1491 + guest->status = VIR_DOMAIN_RUNNING;
1497 +vserverDomainShutdown(virDomainPtr domain)
1499 + GET_DOMAIN(domain, -1);
1501 + if (vserverRunCommand(1, PROG_VSERVER, guest->path, "stop", NULL) != 0) {
1502 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1507 + driver->active_guests--;
1508 + guest->status = VIR_DOMAIN_SHUTOFF;
1509 + driver->inactive_guests++;
1514 +vserverDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
1516 + GET_DOMAIN(domain, -1);
1518 + if (vserverRunCommand(1, PROG_VSERVER, guest->path, "restart", NULL) != 0) {
1519 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1520 + "vserver restart");
1524 + guest->status = VIR_DOMAIN_RUNNING;
1529 +vserverDomainDestroy(virDomainPtr domain)
1531 + GET_DOMAIN(domain, -1);
1533 + if (vserverDomainShutdown(domain) == -1)
1536 + virFreeDomain(domain->conn, domain);
1542 +vserverDomainGetOSType(virDomainPtr domain ATTRIBUTE_UNUSED)
1544 + return strdup("Linux");
1547 +static unsigned long
1548 +vserverDomainGetMaxMemory(virDomainPtr domain)
1550 + GET_DOMAIN(domain, (unsigned long) -1);
1552 + return guest->rss_hard << PAGE_SHIFT_TO_KIBI;
1556 +vserverDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
1558 + struct vc_rlimit limit = {
1561 + GET_DOMAIN(domain, -1);
1563 + guest->rss_hard = memory >> PAGE_SHIFT_TO_KIBI;
1564 + limit.soft = limit.hard = guest->rss_hard;
1565 + if (vserverIsRunning(guest) &&
1566 + vc_set_rlimit(guest->xid, RLIMIT_RSS, &limit) == -1) {
1567 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno));
1571 + if (vserverWriteToConfig(guest, "rlimits/rss.hard", "%lu\n", guest->rss_hard) == -1) {
1572 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1581 +vserverDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
1583 + struct vc_sched_info sinfo = { .user_msec = 0, .sys_msec = 0 };
1584 + struct vc_rlimit_stat rss_stat = { .value = 0 };
1585 + GET_DOMAIN(domain, -1);
1587 + if (vserverIsRunning(guest)) {
1588 + if (vc_sched_info(guest->xid, &sinfo) == -1) {
1589 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1593 + if (vc_rlimit_stat(guest->xid, RLIMIT_RSS, &rss_stat) == -1) {
1594 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1600 + info->state = guest->status;
1601 + info->maxMem = guest->rss_hard << PAGE_SHIFT_TO_KIBI;
1602 + info->nrVirtCpu = -1;
1603 + info->memory = rss_stat.value;
1604 + info->cpuTime = (sinfo.user_msec + sinfo.sys_msec) * 1000000ULL;
1610 +vserverDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
1613 + char uuid[VIR_UUID_STRING_BUFLEN + 1];
1614 + struct vserver_ip *ip;
1615 + GET_DOMAIN(domain, NULL);
1617 + buf = virBufferNew(4096);
1621 + virUUIDFormat(guest->uuid, uuid);
1622 + if (virBufferVSprintf(buf,
1623 +"<domain type='vserver' id='%d'>\n"
1624 +" <name>%s</name>\n"
1625 +" <uuid>%s</uuid>\n"
1626 + , guest->xid, guest->name, uuid
1629 + if (guest->rss_hard > 0)
1630 + if (virBufferVSprintf(buf, " <memory>%lu</memory>\n",
1631 + guest->rss_hard << PAGE_SHIFT_TO_KIBI) < 0)
1634 + if (virBufferVSprintf(buf, " <os>\n"
1635 + " <hostname>%s</hostname>\n"
1636 + , guest->uts.hostname) < 0)
1638 + if (virBufferVSprintf(buf, " <type") < 0)
1640 + if (*guest->uts.machine)
1641 + if (virBufferVSprintf(buf, " arch='%s'", guest->uts.machine) < 0)
1643 + if (virBufferVSprintf(buf, ">vserver</type>\n") < 0)
1645 + if (*guest->uts.release)
1646 + if (virBufferVSprintf(buf, " <release>%s</release>\n",
1647 + guest->uts.release) < 0)
1649 + if (*guest->uts.version)
1650 + if (virBufferVSprintf(buf, " <version>%s</version>\n",
1651 + guest->uts.version) < 0)
1653 + if (virBufferVSprintf(buf, " </os>\n"
1654 + " <devices>\n") < 0)
1657 + for (ip = guest->ips; ip; ip = ip->next) {
1658 + char addrbuf[128];
1659 + if (virBufferVSprintf(buf, " <interface type='ethernet'>\n"
1660 + " <ip prefix='%d'", ip->addr.vna_prefix) < 0)
1662 + if (*ip->interface)
1663 + if (virBufferVSprintf(buf, " interface='%s'", ip->interface) < 0)
1666 + switch (ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6)) {
1667 + case VC_NXA_TYPE_IPV4:
1668 + inet_ntop(AF_INET, &ip->addr.vna_v4_ip, addrbuf, sizeof(addrbuf));
1669 + if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0)
1671 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE)) {
1672 + inet_ntop(AF_INET, &ip->addr.vna_v4_ip2, addrbuf, sizeof(addrbuf));
1673 + if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0)
1676 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) {
1677 + if (virBufferVSprintf(buf, " type='mask'") < 0)
1680 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE) ||
1681 + ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) {
1682 + inet_ntop(AF_INET, &ip->addr.vna_v4_mask, addrbuf, sizeof(addrbuf));
1683 + if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0)
1688 + case VC_NXA_TYPE_IPV6:
1689 + inet_ntop(AF_INET6, &ip->addr.vna_v6_ip, addrbuf, sizeof(addrbuf));
1690 + if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0)
1692 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE)) {
1693 + inet_ntop(AF_INET6, &ip->addr.vna_v6_ip2, addrbuf, sizeof(addrbuf));
1694 + if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0)
1697 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) {
1698 + if (virBufferVSprintf(buf, " type='mask'") < 0)
1701 + if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE) ||
1702 + ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) {
1703 + inet_ntop(AF_INET6, &ip->addr.vna_v6_mask, addrbuf, sizeof(addrbuf));
1704 + if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0)
1710 + if (virBufferVSprintf(buf, " />\n"
1711 + " </interface>\n") < 0)
1715 + if (guest->fstab) {
1716 + struct vserver_fstab *ent;
1717 + for (ent = guest->fstab; ent; ent = ent->next) {
1718 + /* Skip things like proc */
1719 + if (!(ent->flags & VSERVER_FSTAB_SHOW))
1721 + if (virBufferVSprintf(buf, " <disk type='%s' device='directory'>\n"
1722 + " <source %s='%s' type='%s' options='%s'/>\n"
1723 + " <target directory='%s'/>\n"
1726 + (strcmp(ent->source_type, "block") == 0 ?
1727 + "dev" : ent->source_type),
1736 + if (virBufferVSprintf(buf, " </devices>\n"
1737 + "</domain>\n") < 0)
1740 + return virBufferContentAndFree(buf);
1744 + virBufferFree(buf);
1745 + vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY,
1751 +vserverParseIP(struct vserver_ip *ip, xmlNodePtr node)
1756 + value = xmlGetProp(node, BAD_CAST "address");
1759 + if (inet_pton(AF_INET6, (char *) value, &ip->addr.vna_v6_ip) > 0)
1760 + ip->addr.vna_type = VC_NXA_TYPE_IPV6;
1761 + else if (inet_pton(AF_INET, (char *) value, &ip->addr.vna_v4_ip) > 0)
1762 + ip->addr.vna_type = VC_NXA_TYPE_IPV4;
1766 + value = xmlGetProp(node, BAD_CAST "prefix");
1769 + ip->addr.vna_prefix = strtol((char *) value, &endptr, 0);
1774 + value = xmlGetProp(node, BAD_CAST "type");
1776 + ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
1778 + if (xmlStrcasecmp(value, BAD_CAST "address") == 0)
1779 + ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
1780 + else if (xmlStrcasecmp(value, BAD_CAST "mask") == 0)
1781 + ip->addr.vna_type |= VC_NXA_TYPE_MASK;
1782 + else if (xmlStrcasecmp(value, BAD_CAST "range") == 0)
1783 + ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
1789 + value = xmlGetProp(node, BAD_CAST "interface");
1791 + strncpy(ip->interface, (char *) value, IFNAMSIZ);
1803 +static const char *
1804 +diskTypeToAttr(const char *type)
1806 + return (strcmp(type, "block") == 0 ? "dev" : type);
1810 +vserverParseDisk(struct vserver_fstab *ent, xmlNodePtr node)
1812 + xmlChar *type = NULL, *value = NULL;
1813 + xmlNodePtr iter, source = NULL, target = NULL;
1815 + for (iter = node->children; iter && (!source || !target); iter = iter->next) {
1816 + if (iter->type != XML_ELEMENT_NODE)
1818 + if (xmlStrEqual(iter->name, BAD_CAST "source"))
1820 + else if (xmlStrEqual(iter->name, BAD_CAST "target"))
1823 + if (!target || !source)
1826 + value = xmlGetProp(node, BAD_CAST "device");
1827 + if (!value || !xmlStrEqual(value, BAD_CAST "directory"))
1831 + ent->target = (char *) xmlGetProp(target, BAD_CAST "directory");
1835 + type = xmlGetProp(node, BAD_CAST "type");
1838 + ent->source = (char *) xmlGetProp(source, BAD_CAST diskTypeToAttr((char *) type));
1843 + ent->source_type = vserverFindSourceType(ent->source);
1844 + if (!ent->source_type)
1847 + ent->fstype = (char *) xmlGetProp(source, BAD_CAST "type");
1849 + ent->fstype = strdup("auto");
1851 + ent->options = (char *) xmlGetProp(source, BAD_CAST "options");
1852 + if (!ent->options) {
1853 + if (strcmp(ent->source_type, "file") == 0)
1854 + ent->options = strdup("defaults,loop");
1856 + ent->options = strdup("defaults");
1859 + ent->flags = VSERVER_FSTAB_SHOW | VSERVER_FSTAB_OUTPUT;
1865 + xmlFree(ent->fstype);
1867 + xmlFree(ent->source);
1869 + xmlFree(ent->target);
1876 +vserverParseXML(struct vserver_guest *guest, xmlDocPtr doc)
1879 + xmlXPathContextPtr xpath = NULL;
1880 + xmlXPathObjectPtr obj;
1884 + /* FIXME: This could use some better error reporting... */
1885 + root = xmlDocGetRootElement(doc);
1886 + if (!root || !xmlStrEqual(root->name, BAD_CAST "domain"))
1889 + xpath = xmlXPathNewContext(doc);
1893 + if (virXPathLong("string(/domain[1]/@id)", xpath, &l_tmp) != 0)
1895 + guest->xid = (int) l_tmp;
1897 + str = virXPathString("string(/domain/name[1])", xpath);
1900 + strncpy(guest->name, str, VSERVER_NAME_MAX - 1);
1902 + str = virXPathString("string(/domain/uuid[1])", xpath);
1904 + if (virUUIDGenerate(guest->uuid) != 0)
1907 + else if (virUUIDParse(str, guest->uuid) < 0)
1910 + guest->rss_hard = 0;
1911 + if (virXPathLong("string(/domain/memory[1])", xpath, (long *) &guest->rss_hard) == -2)
1913 + guest->rss_hard >>= PAGE_SHIFT_TO_KIBI;
1915 + str = virXPathString("string(/domain/os[1]/hostname[1])", xpath);
1917 + strncpy(guest->uts.hostname, str, VSERVER_UTS_MAX - 1);
1919 + str = virXPathString("string(/domain/os[1]/type[1]/@arch)", xpath);
1921 + strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1923 + str = virXPathString("string(/domain/os[1]/release[1])", xpath);
1925 + strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1927 + str = virXPathString("string(/domain/os[1]/version[1])", xpath);
1929 + strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1931 + str = virXPathString("string(/domain/container/initstyle[1]/@type)", xpath);
1932 + guest->initstyle = VSERVER_INIT_SYSV;
1934 + if (strcmp(str, "plain") == 0)
1935 + guest->initstyle = VSERVER_INIT_PLAIN;
1936 + else if (strcmp(str, "gentoo") == 0)
1937 + guest->initstyle = VSERVER_INIT_GENTOO;
1938 + else if (strcmp(str, "minit") == 0)
1939 + guest->initstyle = VSERVER_INIT_MINIT;
1940 + else if (strcmp(str, "sysv") == 0)
1941 + guest->initstyle = VSERVER_INIT_SYSV;
1944 + obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/interface/ip", xpath);
1945 + if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL &&
1946 + obj->nodesetval->nodeNr > 0) {
1948 + struct vserver_ip *ip = NULL;
1950 + for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1952 + guest->ips = ip = calloc(1, sizeof(*ip));
1954 + ip->next = calloc(1, sizeof(*ip));
1958 + if (vserverParseIP(ip, obj->nodesetval->nodeTab[i]) == -1)
1963 + xmlXPathFreeObject(obj);
1965 + obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/disk", xpath);
1966 + if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL &&
1967 + obj->nodesetval->nodeNr > 0) {
1969 + struct vserver_fstab *ent = NULL;
1971 + for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1973 + guest->fstab = ent = calloc(1, sizeof(*ent));
1975 + ent->next = calloc(1, sizeof(*ent));
1979 + if (vserverParseDisk(ent, obj->nodesetval->nodeTab[i]) == -1)
1984 + xmlXPathFreeObject(obj);
1986 + xmlXPathFreeContext(xpath);
1992 + xmlXPathFreeObject(obj);
1995 + xmlXPathFreeContext(xpath);
1999 +static virDomainPtr
2000 +vserverDomainDefineXML(virConnectPtr conn, const char *xml)
2002 + struct vserver_driver *driver = conn->privateData;
2003 + struct vserver_guest *guest, *tail;
2004 + virDomainPtr domain;
2008 + if ((guest = calloc(1, sizeof(struct vserver_guest))) == NULL) {
2009 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "vserver_guest");
2013 + if ((doc = xmlReadDoc(BAD_CAST xml, "domain.xml", NULL,
2014 + XML_PARSE_NOENT | XML_PARSE_NONET |
2015 + XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) {
2016 + vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
2021 + if (vserverParseXML(guest, doc) == -1) {
2022 + vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
2030 + guest->path = calloc(sizeof(VSERVER_CONF_DIR "/") + strlen(guest->name), sizeof(char));
2031 + sprintf(guest->path, VSERVER_CONF_DIR "/%s", guest->name);
2032 + guest->status = VIR_DOMAIN_SHUTOFF;
2033 + if (vserverRunCommand(0, PROG_VSERVER, guest->name, "build", "-m",
2034 + "skeleton", "--confdir", guest->path, NULL) != 0) {
2035 + vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserver build");
2039 + virUUIDFormat(guest->uuid, buf);
2040 + if (vserverWriteGuestToConfig(guest) == -1) {
2041 + vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserverWriteToConfig");
2046 + /* add it to the list */
2047 + for (tail = driver->guests; tail && tail->next; tail = tail->next)
2050 + driver->guests = guest;
2052 + tail->next = guest;
2054 + driver->inactive_guests++;
2056 + domain = virGetDomain(conn, guest->name, guest->uuid);
2058 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
2064 +vserverListDefinedDomains(virConnectPtr conn, char **const names,
2067 + struct vserver_driver *driver = conn->privateData;
2068 + struct vserver_guest *guest;
2071 + for (guest = driver->guests; guest && i < maxnames; guest = guest->next) {
2072 + if (guest->status == VIR_DOMAIN_SHUTOFF) {
2073 + if ((names[i++] = strdup(guest->name)) == NULL) {
2074 + vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "names");
2084 +vserverNumOfDefinedDomains(virConnectPtr conn)
2086 + struct vserver_driver *driver = conn->privateData;
2088 + return driver->inactive_guests;
2092 +vserverDomainCreate(virDomainPtr domain)
2094 + GET_DOMAIN(domain, -1);
2096 + if (vserverRunCommand(1, PROG_VSERVER, guest->path, "start", NULL) != 0) {
2097 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2102 + driver->inactive_guests--;
2103 + guest->status = VIR_DOMAIN_RUNNING;
2104 + driver->active_guests++;
2108 +static virDomainPtr
2109 +vserverDomainCreateLinux(virConnectPtr conn, const char *xml,
2110 + unsigned int flags ATTRIBUTE_UNUSED)
2112 + virDomainPtr domain;
2114 + domain = vserverDomainDefineXML(conn, xml);
2118 + if (vserverDomainCreate(domain) == -1)
2125 +vserverDomainUndefine(virDomainPtr domain)
2127 + struct vserver_guest *prev;
2128 + GET_DOMAIN(domain, -1);
2130 + for (prev = driver->guests; prev; prev = prev->next) {
2131 + if (prev->next == guest)
2135 + vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
2136 + _("domain not found"));
2139 + if (vserverIsRunning(guest)) {
2140 + vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG,
2141 + _("domain is running"));
2145 + driver->inactive_guests--;
2146 + prev->next = guest->next;
2147 + /* XXX: deletes the domain's contents as well */
2148 + vserverRunCommand(0, PROG_VSERVER, "--silent", guest->path, "delete", NULL);
2155 +doMount(int do_umount, struct vserver_guest *guest, struct vserver_fstab *ent)
2160 + if ((child = fork()) == 0) {
2161 + if (vc_enter_namespace(guest->xid, CLONE_NEWNS|CLONE_FS) == -1)
2164 + if (sys_umount(ent->target, MNT_DETACH) == -1)
2168 + char target[strlen(guest->path) + sizeof("/vdir/") + strlen(ent->target)];
2169 + sprintf(target, "%s/vdir/%s", guest->path, ent->target);
2170 + if (vserverRunCommand(0, "mount", "-t", ent->fstype, "-n", "-o",
2171 + ent->options, ent->source, target, NULL))
2176 + else if (child == -1)
2179 + if (waitpid(child, &status, 0) == -1)
2181 + if (WEXITSTATUS(status) != 0) {
2182 + errno = WEXITSTATUS(status);
2191 +vserverDomainHandleDevice(virDomainPtr domain, const char *xml, int attach)
2195 + GET_DOMAIN(domain, -1);
2197 + if ((doc = xmlReadDoc(BAD_CAST xml, "device.xml", NULL,
2198 + XML_PARSE_NOENT | XML_PARSE_NONET |
2199 + XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) {
2200 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, _("device"));
2204 + node = xmlDocGetRootElement(doc);
2205 + if (node == NULL) {
2206 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2207 + _("missing root element"));
2211 + if (xmlStrEqual(node->name, BAD_CAST "interface")) {
2213 + struct vserver_ip *ip;
2215 + for (child = node->children; child; child = child->next) {
2216 + if (child->type != XML_ELEMENT_NODE)
2219 + /* This should be an only child, but who knows. */
2220 + if (xmlStrEqual(child->name, BAD_CAST "ip"))
2224 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2225 + _("no <ip> element found"));
2229 + ip = calloc(1, sizeof(*ip));
2230 + if (vserverParseIP(ip, child) == -1) {
2231 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2232 + _("parsing IP failed"));
2237 + list_add_tail(guest->ips, ip);
2238 + if (vserverIsRunning(guest)) {
2239 + if (vc_net_add(guest->xid, &ip->addr) == -1) {
2240 + vserverError(domain->conn, domain, NULL,
2241 + VIR_ERR_SYSTEM_ERROR, strerror(errno));
2247 + else /* detach */ {
2248 + struct vserver_ip *i, *p = NULL;
2249 + for (i = guest->ips; i; i = i->next) {
2250 + if (strcmp(ip->interface, i->interface) == 0 &&
2251 + memcmp(&ip->addr, &i->addr, sizeof(ip->addr)) == 0)
2257 + p->next = i->next;
2259 + guest->ips = i->next;
2260 + if (vserverIsRunning(guest)) {
2261 + /* Not a lot of kernels support this, so don't fail. */
2262 + vc_net_remove(guest->xid, &ip->addr);
2269 + else if (xmlStrEqual(node->name, BAD_CAST "disk")) {
2270 + struct vserver_fstab *ent = calloc(1, sizeof(*ent));
2272 + vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, NULL);
2276 + if (vserverParseDisk(ent, node) == -1) {
2277 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, "disk");
2282 + list_add_tail(guest->fstab, ent);
2283 + if (vserverIsRunning(guest)) {
2284 + if (doMount(0, guest, ent) == -1) {
2285 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2292 + else /* detach */ {
2293 + struct vserver_fstab *i, *p = NULL;
2294 + for (i = guest->fstab; i; i = i->next) {
2295 + /* These are the fields we care about */
2296 + if (strcmp(ent->source, i->source) == 0 &&
2297 + strcmp(ent->target, i->target) == 0 &&
2298 + strcmp(ent->source_type, i->source_type) == 0)
2304 + p->next = i->next;
2306 + guest->fstab = i->next;
2307 + if (vserverIsRunning(guest)) {
2308 + if (doMount(1, guest, ent) == -1) {
2309 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2320 + vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2321 + _("unknown device type"));
2325 + /* Both fstab and interfaces need a lot of writing, so write the whole thing */
2326 + if (vserverWriteGuestToConfig(guest) == -1) {
2327 + vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED, guest->name);
2337 +vserverDomainAttachDevice(virDomainPtr domain, const char *xml)
2339 + return vserverDomainHandleDevice(domain, xml, 1);
2343 +vserverDomainDetachDevice(virDomainPtr domain, const char *xml)
2345 + return vserverDomainHandleDevice(domain, xml, 0);
2349 +vserverDomainGetAutostart(virDomainPtr domain, int *autostart)
2351 + GET_DOMAIN(domain, -1);
2353 + *autostart = guest->autostart;
2358 +vserverDomainSetAutostart(virDomainPtr domain, int autostart)
2360 + GET_DOMAIN(domain, -1);
2362 + if (vserverWriteToConfig(guest, "apps/init/mark",
2363 + (autostart ? "default\n" : "\n")) == -1) {
2364 + vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED,
2365 + "apps/init/mark");
2368 + guest->autostart = autostart;
2372 +static const struct {
2374 + const char *field;
2376 +} sched_fields[] = {
2377 + { VC_VXSM_FILL_RATE, "fill_rate1", VIR_DOMAIN_SCHED_FIELD_UINT },
2378 + { VC_VXSM_INTERVAL, "interval1", VIR_DOMAIN_SCHED_FIELD_UINT },
2379 + { VC_VXSM_FILL_RATE2, "fill_rate2", VIR_DOMAIN_SCHED_FIELD_UINT },
2380 + { VC_VXSM_INTERVAL2, "interval2", VIR_DOMAIN_SCHED_FIELD_UINT },
2381 + { VC_VXSM_TOKENS_MIN, "tokens_min", VIR_DOMAIN_SCHED_FIELD_UINT },
2382 + { VC_VXSM_TOKENS_MAX, "tokens_max", VIR_DOMAIN_SCHED_FIELD_UINT },
2383 + { VC_VXSM_PRIO_BIAS, "prio_bias", VIR_DOMAIN_SCHED_FIELD_INT },
2384 + { VC_VXSM_IDLE_TIME, "idle_time", VIR_DOMAIN_SCHED_FIELD_BOOLEAN },
2389 +vserverDomainGetSchedulerType(virDomainPtr domain, int *nparams)
2393 + GET_DOMAIN(domain, NULL);
2395 + ret = strdup(guest->sched.set_mask & VC_VXSM_IDLE_TIME ? "fair" : "hard");
2397 + vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY,
2403 + for (i = 0; sched_fields[i].field != NULL; i++) {
2404 + /* only returns fields which are set */
2405 + if (guest->sched.set_mask & sched_fields[i].id)
2413 +vserverDomainGetSchedulerParams(virDomainPtr domain,
2414 + virSchedParameterPtr params,
2418 + GET_DOMAIN(domain, -1);
2420 + for (i = 0, j = 0; sched_fields[i].field != NULL && i < *nparams; i++) {
2421 + /* skip unset fields */
2422 + if (!(guest->sched.set_mask & sched_fields[i].id))
2425 + params[j].type = sched_fields[i].type;
2426 + strncpy(params[j].field, sched_fields[i].field, sizeof(params[j].field) - 1);
2427 + switch (sched_fields[i].id) {
2428 + case VC_VXSM_FILL_RATE:
2429 + params[j].value.ui = guest->sched.fill_rate;
2431 + case VC_VXSM_INTERVAL:
2432 + params[j].value.ui = guest->sched.interval;
2434 + case VC_VXSM_FILL_RATE2:
2435 + params[j].value.ui = guest->sched.fill_rate2;
2437 + case VC_VXSM_INTERVAL2:
2438 + params[j].value.ui = guest->sched.interval2;
2440 + case VC_VXSM_TOKENS_MIN:
2441 + params[j].value.ui = guest->sched.tokens_min;
2443 + case VC_VXSM_TOKENS_MAX:
2444 + params[j].value.ui = guest->sched.tokens_max;
2446 + case VC_VXSM_PRIO_BIAS:
2447 + params[j].value.i = guest->sched.priority_bias;
2449 + case VC_VXSM_IDLE_TIME:
2450 + params[j].value.b = guest->sched.set_mask & VC_VXSM_IDLE_TIME;
2461 +vserverDomainSetSchedulerParams(virDomainPtr domain,
2462 + virSchedParameterPtr params,
2466 + GET_DOMAIN(domain, -1);
2468 + for (i = 0; i < nparams; i++) {
2469 + for (j = 0; sched_fields[j].field != NULL; j++) {
2470 + if (STREQ(sched_fields[j].field, params[i].field))
2473 + if (sched_fields[j].field == NULL) {
2474 + vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "field");
2477 + if (sched_fields[j].type != params[i].type) {
2478 + vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "type");
2481 + switch (sched_fields[j].id) {
2482 + case VC_VXSM_FILL_RATE:
2483 + guest->sched.fill_rate = params[i].value.ui;
2484 + cret = vserverWriteToConfig(guest, "sched/fill-rate", "%u\n",
2485 + params[i].value.ui);
2487 + case VC_VXSM_INTERVAL:
2488 + guest->sched.interval = params[i].value.ui;
2489 + cret = vserverWriteToConfig(guest, "sched/interval", "%u\n",
2490 + params[i].value.ui);
2492 + case VC_VXSM_FILL_RATE2:
2493 + guest->sched.fill_rate2 = params[i].value.ui;
2494 + cret = vserverWriteToConfig(guest, "sched/fill-rate2", "%u\n",
2495 + params[i].value.ui);
2497 + case VC_VXSM_INTERVAL2:
2498 + guest->sched.interval2 = params[i].value.ui;
2499 + cret = vserverWriteToConfig(guest, "sched/interval2", "%u\n",
2500 + params[i].value.ui);
2502 + case VC_VXSM_TOKENS_MIN:
2503 + guest->sched.tokens_min = params[i].value.ui;
2504 + cret = vserverWriteToConfig(guest, "sched/tokens-min", "%u\n",
2505 + params[i].value.ui);
2507 + case VC_VXSM_TOKENS_MAX:
2508 + guest->sched.tokens_max = params[i].value.ui;
2509 + cret = vserverWriteToConfig(guest, "sched/tokens-max", "%u\n",
2510 + params[i].value.ui);
2512 + case VC_VXSM_PRIO_BIAS:
2513 + guest->sched.priority_bias = params[i].value.i;
2514 + cret = vserverWriteToConfig(guest, "sched/prio-bias", "%d\n",
2515 + params[i].value.i);
2517 + case VC_VXSM_IDLE_TIME:
2518 + cret = vserverWriteToConfig(guest, "sched/idle-time", "%b",
2519 + params[i].value.b);
2522 + vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
2523 + "Unknown scheduler parameter");
2527 + vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2528 + "vserverWriteToConfig");
2531 + guest->sched.set_mask |= sched_fields[j].id;
2538 +virDriver vserverDriver = {
2541 + LIBVIR_VERSION_NUMBER,
2544 + NULL, /* supports_feature */
2546 + vserverGetVersion,
2547 + vserverGetHostname,
2549 + NULL, /* getMaxVcpus */
2550 + vserverNodeGetInfo,
2551 + NULL, /* getCapabilties */
2552 + vserverListDomains,
2553 + vserverNumOfDomains,
2554 + vserverDomainCreateLinux,
2555 + vserverDomainLookupByID,
2556 + vserverDomainLookupByUUID,
2557 + vserverDomainLookupByName,
2558 + vserverDomainSuspend,
2559 + vserverDomainResume,
2560 + vserverDomainShutdown,
2561 + vserverDomainReboot,
2562 + vserverDomainDestroy,
2563 + vserverDomainGetOSType,
2564 + vserverDomainGetMaxMemory,
2565 + vserverDomainSetMaxMemory,
2566 + NULL, /* domainSetMemory */
2567 + vserverDomainGetInfo,
2568 + NULL, /* domainSave */
2569 + NULL, /* domainRestore */
2570 + NULL, /* domainCoreDump */
2571 + NULL, /* domainSetVcpus */
2572 + NULL, /* domainPinVcpu */
2573 + NULL, /* domainGetVcpus */
2574 + NULL, /* domainGetMaxVcpus */
2575 + vserverDomainDumpXML,
2576 + vserverListDefinedDomains,
2577 + vserverNumOfDefinedDomains,
2578 + vserverDomainCreate,
2579 + vserverDomainDefineXML,
2580 + vserverDomainUndefine,
2581 + vserverDomainAttachDevice,
2582 + vserverDomainDetachDevice,
2583 + vserverDomainGetAutostart,
2584 + vserverDomainSetAutostart,
2585 + vserverDomainGetSchedulerType,
2586 + vserverDomainGetSchedulerParams,
2587 + vserverDomainSetSchedulerParams,
2588 + NULL, /* domainMigratePrepare */
2589 + NULL, /* domainMigratePerform */
2590 + NULL, /* domainMigrateFinish */
2591 + NULL, /* domainBlockStats */
2592 + NULL, /* domainInterfaceStats */
2593 + NULL, /* nodeGetCellsFreeMemory */
2594 + NULL, /* getFreeMemory */
2597 +int vserverRegister(void)
2599 + if (virRegisterDriver(&vserverDriver) < 0)
2605 --- libvirt-0.4.0.orig/src/vserver/vserver_driver.h 1970-01-01 01:00:00.000000000 +0100
2606 +++ libvirt-0.4.0.vserver/src/vserver/vserver_driver.h 2008-01-09 19:14:08.000000000 +0100
2609 + * Core driver for managing Linux-VServer guests
2611 + * Copyright (C) 2007 Daniel Hokka Zakrisson
2613 + * This library is free software; you can redistribute it and/or
2614 + * modify it under the terms of the GNU Lesser General Public
2615 + * License as published by the Free Software Foundation; either
2616 + * version 2.1 of the License, or (at your option) any later version.
2618 + * This library is distributed in the hope that it will be useful,
2619 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2620 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2621 + * Lesser General Public License for more details.
2623 + * You should have received a copy of the GNU Lesser General Public
2624 + * License along with this library; if not, write to the Free Software
2625 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2627 + * Author: Daniel Hokka Zakrisson <daniel hozac com>
2630 +#ifdef WITH_VSERVER
2632 +/* Kind of a hack */
2635 +typedef unsigned int xid_t;
2638 +typedef unsigned int nid_t;
2641 +typedef unsigned int tag_t;
2643 +#include <vserver.h>
2645 +#define VSERVER_NAME_MAX 64
2646 +#define VSERVER_UTS_MAX 255
2648 +enum vserver_initstyle {
2649 + VSERVER_INIT_NONE,
2650 + VSERVER_INIT_SYSV,
2651 + VSERVER_INIT_PLAIN,
2652 + VSERVER_INIT_GENTOO,
2653 + VSERVER_INIT_MINIT,
2656 +struct vserver_ip {
2657 + char interface[IFNAMSIZ+1];
2658 + struct vc_net_addr addr;
2659 + struct vserver_ip *next;
2663 + VSERVER_FSTAB_SHOW=1,
2664 + VSERVER_FSTAB_OUTPUT=2,
2666 +struct vserver_fstab {
2668 + const char *source_type;
2674 + struct vserver_fstab *next;
2677 +struct vserver_guest {
2679 + char name[VSERVER_NAME_MAX];
2680 + unsigned char uuid[VIR_UUID_BUFLEN];
2684 + char hostname[VSERVER_UTS_MAX];
2685 + char machine[VSERVER_UTS_MAX];
2686 + char release[VSERVER_UTS_MAX];
2687 + char version[VSERVER_UTS_MAX];
2690 + struct vserver_ip *ips;
2692 + struct vc_set_sched sched;
2693 + unsigned long rss_hard;
2696 + enum vserver_initstyle initstyle;
2700 + struct vserver_fstab *fstab;
2702 + struct vserver_guest *next;
2705 +struct vserver_driver {
2706 + struct vserver_guest *guests;
2708 + unsigned int active_guests;
2709 + unsigned int inactive_guests;
2710 + unsigned int initialized : 1;
2714 +#define list_add_tail(list, elem) \
2716 + __typeof__(list) iter; \
2718 + for (iter = list; iter->next; iter = iter->next) \
2720 + iter->next = elem; \
2727 +vserverIsRunning(struct vserver_guest *guest) {
2728 + if (guest->status == VIR_DOMAIN_RUNNING || guest->status == VIR_DOMAIN_PAUSED)
2735 +int vserverContextIsRunning(const char *path);
2736 +int vserverRunCommand(int do_daemon, const char *cmd, ...);
2737 +void vserverError(virConnectPtr con, virDomainPtr dom, virNetworkPtr net,
2738 + virErrorNumber error, const char *info);
2742 +extern int vserverRegister(void);