]> git.pld-linux.org Git - packages/libvirt.git/blame - vserver.patch
- updated to 1.1.2
[packages/libvirt.git] / vserver.patch
CommitLineData
bd1fcfb7
ER
1https://www.redhat.com/archives/libvir-list/2008-January/msg00097.html
2
3From: "Daniel Hokka Zakrisson" <daniel hozac com>
4To: libvir-list redhat com
5Subject: [Libvir] [PATCH] Linux-VServer support
6Date: Wed, 9 Jan 2008 22:51:20 +0100 (CET)
7
8This patch implements support for Linux-VServer guests. It is currently
9missing vcpu and console support, and the necessary virsh code to support
10it, but is otherwise pretty feature complete.
11
12This is an XML dump from one of my guests:
13<domain type='vserver' id='40010'>
14 <name>lenny</name>
15 <uuid>19e12957-261a-5a06-d6d0-89917d6d439f</uuid>
16 <memory>2048000</memory>
17 <os>
18 <hostname>lenny.test</hostname>
19 <type arch='i686'>vserver</type>
20 </os>
21 <devices>
22 <interface type='ethernet'>
23 <ip prefix='24' interface='dummy0' address='192.168.20.4' />
24 </interface>
25 <interface type='ethernet'>
26 <ip prefix='24' interface='dummy0' type='range' address='192.168.32.100' address2='192.168.32.200'/>
27 </interface>
28 <disk type='directory' device='directory'>
29 <source directory='/vservers/lenny' type='auto' options='defaults'/>
30 <target directory='/'/>
31 </disk>
32 <disk type='directory' device='directory'>
33 <source directory='/srv' type='ext3' options='bind,ro'/>
34 <target directory='/srv'/>
35 </disk>
36 <disk type='block' device='directory'>
37 <source dev='/dev/mapper/test' type='ext3' options='defaults'/>
38 <target directory='/mnt'/>
39 </disk>
40 </devices>
41</domain>
42
43--
44Daniel Hokka Zakrisson
eb319e62
ER
45--- libvirt-1.1.1/configure.ac~ 2013-08-31 23:44:52.000000000 +0300
46+++ libvirt-1.1.1/configure.ac 2013-08-31 23:46:02.245725043 +0300
47@@ -449,6 +449,8 @@
48 AC_HELP_STRING([--with-hyperv], [add Hyper-V support @<:@default=check@:>@]),[],[with_hyperv=check])
49 AC_ARG_WITH([parallels],
50 AC_HELP_STRING([--with-parallels], [add Parallels Cloud Server support @<:@default=check@:>@]),[],[with_parallels=check])
51+AC_ARG_WITH([vserver],
52+ AC_HELP_STRING([--with-vserver], [add VServer support @<:@default=check@:>@]),[],[with_vserver=check])
53 AC_ARG_WITH([test],
54 AC_HELP_STRING([--with-test], [add test driver support @<:@default=yes@:>@]),[],[with_test=yes])
55 AC_ARG_WITH([remote],
56@@ -991,6 +991,39 @@
57 fi
bd1fcfb7 58 fi
eb319e62 59
bd1fcfb7
ER
60+if test "$with_vserver" = "yes" ; then
61+ AC_CHECK_LIB(vserver, [vc_rlimit_stat],, [with_vserver=no])
62+ AC_CHECK_TYPES([xid_t, nid_t, tag_t])
63+ AC_CHECK_HEADER(vserver.h,, [with_vserver=no], [AC_INCLUDES_DEFAULT()
64+#ifndef HAVE_XID_T
65+typedef unsigned int xid_t;
66+#endif
67+#ifndef HAVE_NID_T
68+typedef unsigned int nid_t;
69+#endif
70+#ifndef HAVE_TAG_T
71+typedef unsigned int tag_t;
72+#endif])
73+
74+ AC_MSG_CHECKING([for vserver configuration directory])
75+ VSERVER_CONF_DIR=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \
76+ vserver-info - SYSINFO | sed -n 's/^.*cfg-Directory:.//p'`
77+ AC_MSG_RESULT([$VSERVER_CONF_DIR])
78+ AC_DEFINE_UNQUOTED([VSERVER_CONF_DIR], ["$VSERVER_CONF_DIR"],
79+ [The default path to the Linux-VServer configuration files])
80+
81+ AC_MSG_CHECKING([for the vserver program])
82+ PROG_VSERVER=`env PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" \
83+ which vserver 2> /dev/null` || with_vserver=no
84+ AC_MSG_RESULT([$PROG_VSERVER])
85+ AC_DEFINE_UNQUOTED([PROG_VSERVER], ["$PROG_VSERVER"],
86+ [The path to the vserver program])
87+
88+ if test "$with_vserver" = "yes" ; then
89+ LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_VSERVER"
90+ fi
91+fi
eb319e62 92+
bd1fcfb7 93
eb319e62
ER
94 dnl
95 dnl check for kernel headers required by src/bridge.c
96@@ -2506,6 +2506,7 @@
97 AC_MSG_NOTICE([ ESX: $with_esx])
98 AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
99 AC_MSG_NOTICE([Parallels: $with_parallels])
100+AC_MSG_NOTICE([ VServer: $with_vserver])
101 AC_MSG_NOTICE([ Test: $with_test])
102 AC_MSG_NOTICE([ Remote: $with_remote])
103 AC_MSG_NOTICE([ Network: $with_network])
104--- libvirt-1.1.1/include/libvirt/virterror.h~ 2013-07-24 03:23:07.000000000 +0300
105+++ libvirt-1.1.1/include/libvirt/virterror.h 2013-09-01 00:07:44.097192613 +0300
106@@ -121,6 +121,8 @@
107 VIR_FROM_ACCESS = 55, /* Error from access control manager */
108 VIR_FROM_SYSTEMD = 56, /* Error from systemd code */
bd1fcfb7 109
eb319e62
ER
110+ VIR_FROM_VSERVER = 57, /* Error from Linux-VServer driver */
111+
112 # ifdef VIR_ENUM_SENTINELS
113 VIR_ERR_DOMAIN_LAST
114 # endif
115--- libvirt-1.1.1/src/driver.h~ 2013-07-29 03:25:51.000000000 +0300
116+++ libvirt-1.1.1/src/driver.h 2013-09-01 00:08:21.575533465 +0300
117@@ -46,6 +46,7 @@
118 VIR_DRV_LIBXL = 14,
119 VIR_DRV_HYPERV = 15,
120 VIR_DRV_PARALLELS = 16,
121+ VIR_DRV_VSERVER = 17,
bd1fcfb7
ER
122 } virDrvNo;
123
124
eb319e62
ER
125--- libvirt-1.1.1/src/./libvirt.c~ 2013-09-01 00:20:50.000000000 +0300
126+++ libvirt-1.1.1/src/./libvirt.c 2013-09-01 00:21:02.812830784 +0300
127@@ -94,6 +94,9 @@
128 #ifdef WITH_PARALLELS
129 # include "parallels/parallels_driver.h"
bd1fcfb7 130 #endif
eb319e62
ER
131+#ifdef WITH_VSERVER
132+# include "server/vserver_driver.h"
133+#endif
134
135 #define VIR_FROM_THIS VIR_FROM_NONE
bd1fcfb7 136
eb319e62
ER
137@@ -479,6 +482,10 @@
138 if (parallelsRegister() == -1)
139 goto error;
bd1fcfb7
ER
140 #endif
141+#ifdef WITH_VSERVER
eb319e62
ER
142+ if (verversRegister() == -1)
143+ goto error;
bd1fcfb7
ER
144+#endif
145 #ifdef WITH_REMOTE
eb319e62
ER
146 if (remoteRegister() == -1)
147 goto error;
148--- libvirt-1.1.1/src/Makefile.am~ 2013-07-30 10:21:31.000000000 +0300
149+++ libvirt-1.1.1/src/Makefile.am 2013-09-01 00:11:19.080124997 +0300
150@@ -467,6 +467,7 @@
151 $(NWFILTER_DRIVER_SOURCES) \
152 $(OPENVZ_DRIVER_SOURCES) \
153 $(PARALLELS_DRIVER_SOURCES) \
154+ $(VSERVER_DRIVER_SOURCES) \
155 $(PHYP_DRIVER_SOURCES) \
156 $(QEMU_DRIVER_SOURCES) \
157 $(REMOTE_DRIVER_SOURCES) \
158@@ -727,6 +728,12 @@
159 parallels/parallels_storage.c \
160 parallels/parallels_network.c
161
162+VSERVER_DRIVER_SOURCES = \
163+ vserver/vserver_driver.h \
164+ vserver/vserver_driver.c \
165+ vserver/vserver_conf.h \
166+ vserver/vserver_conf.c
167+
168 NETWORK_DRIVER_SOURCES = \
169 network/bridge_driver.h network/bridge_driver.c
170
171--- libvirt-1.1.1/./src/util/virerror.c~ 2013-07-25 09:17:45.000000000 +0300
172+++ libvirt-1.1.1/./src/util/virerror.c 2013-09-01 00:14:15.371324604 +0300
173@@ -124,6 +124,7 @@
174
175 "Access Manager", /* 55 */
176 "Systemd",
177+ "Vserver",
178 )
bd1fcfb7 179
bd1fcfb7 180
eb319e62
ER
181--- libvirt-0.4.0.orig/src/vserver/vserver_conf.c 1970-01-01 01:00:00.000000000 +0100
182+++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.c 2008-01-09 08:52:11.000000000 +0100
bd1fcfb7
ER
183@@ -0,0 +1,751 @@
184+/*
185+ * Configuration handling for Linux-VServer guests
186+ *
187+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
188+ *
189+ * This library is free software; you can redistribute it and/or
190+ * modify it under the terms of the GNU Lesser General Public
191+ * License as published by the Free Software Foundation; either
192+ * version 2.1 of the License, or (at your option) any later version.
193+ *
194+ * This library is distributed in the hope that it will be useful,
195+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
196+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
197+ * Lesser General Public License for more details.
198+ *
199+ * You should have received a copy of the GNU Lesser General Public
200+ * License along with this library; if not, write to the Free Software
201+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
202+ *
203+ * Author: Daniel Hokka Zakrisson <daniel hozac com>
204+ */
205+
206+#ifdef WITH_VSERVER
207+
208+#define _GNU_SOURCE
209+
210+#ifdef HAVE_CONFIG_H
211+# include <config.h>
212+#endif
213+
214+#include <stdio.h>
215+#include <unistd.h>
216+#include <stdlib.h>
217+#include <fcntl.h>
218+#include <dirent.h>
219+#include <errno.h>
220+#include <sys/types.h>
221+#include <sys/socket.h>
222+#include <arpa/inet.h>
223+#include <net/if.h>
224+#include <sys/stat.h>
225+#include <ctype.h>
226+
227+#include <libvirt/virterror.h>
228+
229+#define IN_VSERVER 1
230+#include "internal.h"
231+#include "vserver_driver.h"
232+#include "vserver_conf.h"
233+#include "uuid.h"
234+
235+static int
236+readStr(char *dst, size_t len, const char *name, const char *setting)
237+{
238+ char file[strlen(name) + strlen(setting) + 2];
239+ int fd;
240+ ssize_t bytes;
241+ char *p;
242+
243+ sprintf(file, "%s/%s", name, setting);
244+
245+ /* a non-existant file is not a failure */
246+ *dst = '\0';
247+ if ((fd = open(file, O_RDONLY)) == -1)
248+ return 1;
249+
250+ if ((bytes = read(fd, dst, len - 1)) == -1) {
251+ close(fd);
252+ return -1;
253+ }
254+ close(fd);
255+
256+ dst[bytes] = '\0';
257+
258+ if ((p = strchr(dst, '\n')) != NULL)
259+ *p = '\0';
260+
261+ return 0;
262+}
263+
264+static int
265+readLong(void *v_dst, const char *name, const char *setting)
266+{
267+ char buf[128], *endptr;
268+ int ret;
269+ long *dst = v_dst;
270+
271+ ret = readStr(buf, sizeof(buf), name, setting);
272+ if (ret)
273+ return ret;
274+
275+ *dst = strtol(buf, &endptr, 0);
276+ if (endptr && *endptr != '\0')
277+ return -1;
278+
279+ return 0;
280+}
281+
282+static int
283+readInt(void *v_dst, const char *name, const char *setting)
284+{
285+ long val;
286+ int *dst = v_dst;
287+ int ret;
288+
289+ ret = readLong(&val, name, setting);
290+ if (ret)
291+ return ret;
292+
293+ *dst = (int) val;
294+
295+ return 0;
296+}
297+
298+static int
299+readBool(char *dst, const char *name, const char *setting)
300+{
301+ char file[strlen(name) + strlen(setting) + 2];
302+
303+ sprintf(file, "%s/%s", name, setting);
304+
305+ *dst = access(file, F_OK) != -1;
306+
307+ return 0;
308+}
309+
310+int
311+vserverWriteToConfig(struct vserver_guest *guest, const char *filename,
312+ const char *format, ...)
313+{
314+ char path[strlen(guest->path) + 1 + strlen(filename) + 1];
315+ va_list va;
316+ char value[1024];
317+ int fd;
318+ ssize_t len, off, ret;
319+ char *dir;
320+
321+ sprintf(path, "%s/%s", guest->path, filename);
322+
323+ /* ensure the directory exists */
324+ dir = strrchr(path, '/');
325+ *dir = '\0';
326+ if (mkdir(path, 0755) && errno != EEXIST)
327+ return -1;
328+ *dir = '/';
329+
330+ va_start(va, format);
331+ if (strcmp(format, "%b") == 0) {
332+ /* bool, this is a special case */
333+ if (va_arg(va, int)) {
334+ *value = '\0';
335+ len = 0;
336+ }
337+ else {
338+ if (unlink(path) == -1 && errno != ENOENT)
339+ return -1;
340+ else
341+ return 0;
342+ }
343+ }
344+ else
345+ len = vsnprintf(value, sizeof(value), format, va);
346+ va_end(va);
347+
348+ fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0644);
349+ if (fd == -1)
350+ return -1;
351+
352+ for (off = 0; off < len; off += ret) {
353+ ret = write(fd, value + off, len - off);
354+ if (ret == -1) {
355+ close(fd);
356+ return -1;
357+ }
358+ }
359+
360+ if (close(fd) == -1)
361+ return -1;
362+ return 0;
363+}
364+
365+#define WRITE(...) if (vserverWriteToConfig(guest, __VA_ARGS__) == -1) \
366+ return -1
367+#define WRITE_SCHED_VAL(sched, file, mask, format, value) \
368+ if ((sched)->set_mask & mask) { \
369+ WRITE(file, format, value); \
370+ }
371+#define WRITE_SCHED(dir, sched) \
372+ do { \
373+ WRITE_SCHED_VAL(sched, dir "/fill-rate", \
374+ VC_VXSM_FILL_RATE, "%u\n", \
375+ (sched)->fill_rate); \
376+ WRITE_SCHED_VAL(sched, dir "/interval", \
377+ VC_VXSM_INTERVAL, "%u\n", \
378+ (sched)->interval); \
379+ WRITE_SCHED_VAL(sched, dir "/fill-rate2", \
380+ VC_VXSM_FILL_RATE2, "%u\n", \
381+ (sched)->fill_rate2); \
382+ WRITE_SCHED_VAL(sched, dir "/interval2", \
383+ VC_VXSM_INTERVAL2, "%u\n", \
384+ (sched)->interval2); \
385+ WRITE_SCHED_VAL(sched, dir "/tokens-min", \
386+ VC_VXSM_TOKENS_MIN, "%u\n", \
387+ (sched)->tokens_min); \
388+ WRITE_SCHED_VAL(sched, dir "/tokens-max", \
389+ VC_VXSM_TOKENS_MAX, "%u\n", \
390+ (sched)->tokens_max); \
391+ WRITE_SCHED_VAL(sched, dir "/priority-bias", \
392+ VC_VXSM_PRIO_BIAS, "%u\n", \
393+ (sched)->priority_bias); \
394+ WRITE(dir "/idle-time", "%b", \
395+ (sched)->set_mask & VC_VXSM_IDLE_TIME); \
396+ } while (0)
397+#define WRITE_IP(filename, v4var, v6var) \
398+ strcpy(file, filename); \
399+ switch (type) { \
400+ case VC_NXA_TYPE_IPV4: \
401+ inet_ntop(AF_INET, (v4var), buf, sizeof(buf)); \
402+ break; \
403+ case VC_NXA_TYPE_IPV6: \
404+ inet_ntop(AF_INET6, (v6var), buf, sizeof(buf)); \
405+ break; \
406+ } \
407+ WRITE(dir, "%s\n", buf);
408+
409+static int
410+writeInterfaces(struct vserver_guest *guest)
411+{
412+ char name[strlen(guest->path) + sizeof("/interfaces/XXXXXX/prefix")],
413+ *dir, *file;
414+ char buf[128];
415+ struct vserver_ip *ip;
416+ unsigned int i;
417+
418+ snprintf(name, sizeof(name), "%s/interfaces", guest->path);
419+ if (vserverRunCommand(0, "rm", "-fr", name, NULL) != 0)
420+ return -1;
421+ if (mkdir(name, 0755) == -1)
422+ return -1;
423+
424+ dir = name + strlen(guest->path) + 1;
425+ for (ip = guest->ips, i = 0; ip; ip = ip->next, i++) {
426+ uint16_t type;
427+
428+ /* Yeah right... */
429+ if (i > 999999) {
430+ errno = EOVERFLOW;
431+ return -1;
432+ }
433+
434+ file = dir;
435+ file += snprintf(dir, sizeof(name) - (dir - name), "interfaces/%u", i);
436+ if (mkdir(name, 0755) == -1)
437+ return -1;
438+
439+ type = ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6);
440+
441+ strcpy(file, "/prefix");
442+ WRITE(dir, "%u\n", ip->addr.vna_prefix);
443+
444+ if (*ip->interface) {
445+ strcpy(file, "/dev");
446+ WRITE(dir, "%s\n", ip->interface);
447+ }
448+ else {
449+ strcpy(file, "/nodev");
450+ WRITE(dir, "%b", 1);
451+ }
452+
453+ WRITE_IP("/ip", &ip->addr.vna_v4_ip, &ip->addr.vna_v6_ip);
454+ if (ip->addr.vna_type & VC_NXA_TYPE_RANGE) {
455+ WRITE_IP("/ip2", &ip->addr.vna_v4_ip2, &ip->addr.vna_v6_ip2);
456+ }
457+ if (ip->addr.vna_type & (VC_NXA_TYPE_RANGE|VC_NXA_TYPE_MASK)) {
458+ WRITE_IP("/mask", &ip->addr.vna_v4_mask, &ip->addr.vna_v6_mask);
459+ }
460+ }
461+ return 0;
462+}
463+
464+static int
465+writeFstab(struct vserver_guest *guest)
466+{
467+ FILE *fp;
468+ struct vserver_fstab *ent;
469+ char file[strlen(guest->path) + sizeof("/fstab")];
470+
471+ sprintf(file, "%s/fstab", guest->path);
472+ fp = fopen(file, "w");
473+ if (fp == NULL)
474+ return -1;
475+
476+ for (ent = guest->fstab; ent; ent = ent->next) {
477+ if (!(ent->flags & VSERVER_FSTAB_OUTPUT))
478+ continue;
479+ fprintf(fp, "%s\t%s\t%s\t%s\t%s\n", ent->source, ent->target,
480+ ent->fstype, ent->options, (ent->rest ? ent->rest : ""));
481+ }
482+
483+ if (fclose(fp) == -1)
484+ return -1;
485+
486+ return 0;
487+}
488+
489+int
490+vserverWriteGuestToConfig(struct vserver_guest *guest)
491+{
492+ char buf[128];
493+
494+ WRITE("context", "%u\n", guest->xid);
495+ WRITE("name", "%s\n", guest->name);
496+ virUUIDFormat(guest->uuid, buf);
497+ WRITE("uuid", "%s\n", buf);
498+ if (*guest->uts.hostname)
499+ WRITE("uts/nodename", "%s\n", guest->uts.hostname);
500+ if (*guest->uts.machine)
501+ WRITE("uts/machine", "%s\n", guest->uts.machine);
502+ if (*guest->uts.release)
503+ WRITE("uts/release", "%s\n", guest->uts.release);
504+ if (*guest->uts.version)
505+ WRITE("uts/version", "%s\n", guest->uts.version);
506+ if (guest->rss_hard > 0)
507+ WRITE("rlimits/rss.hard", "%lu\n", guest->rss_hard);
508+ WRITE("apps/init/mark", (guest->autostart ? "default\n" : "\n"));
509+ WRITE_SCHED("sched", &guest->sched);
510+
511+ if (writeInterfaces(guest) == -1)
512+ return -1;
513+
514+ if (writeFstab(guest) == -1)
515+ return -1;
516+
517+ return 0;
518+}
519+#undef WRITE_IP
520+#undef WRITE_SCHED
521+#undef WRITE_SCHED_VAL
522+#undef WRITE
523+
524+static int
525+parseInterfaces(struct vserver_guest *guest, const char *directory)
526+{
527+ DIR *interfaces;
528+ struct dirent *interface;
529+ struct vserver_ip *ip = NULL;
530+ char ipath[256], *subdir;
531+ size_t spare;
532+ char s_ip[48], s_prefix[4], s_mask[48], s_dev[32], s_ip2[48];
533+
534+ subdir = ipath;
535+ subdir += snprintf(ipath, sizeof(ipath), "%s/%s", guest->name, directory);
536+ spare = sizeof(ipath) - (subdir - ipath);
537+
538+ interfaces = opendir(ipath);
539+ if (!interfaces)
540+ return 0;
541+
542+ while ((interface = readdir(interfaces)) != NULL) {
543+ if (*interface->d_name == '.')
544+ continue;
545+ /* would overflow */
546+ if (strlen(interface->d_name) + sizeof("//disabled") > spare)
547+ continue;
548+
549+ snprintf(subdir, spare, "/%s/disabled", interface->d_name);
550+ if (access(ipath, F_OK) != -1)
551+ continue;
552+
553+ snprintf(subdir, spare, "/%s", interface->d_name);
554+ *s_mask = '\0';
555+ *s_prefix = '\0';
556+ if (readStr(s_ip, sizeof(s_ip), ipath, "ip") == 0 &&
557+ (readStr(s_prefix, sizeof(s_prefix), ipath, "prefix") == 0 ||
558+ readStr(s_mask, sizeof(s_mask), ipath, "mask") == 0)) {
559+ if (readStr(s_dev, sizeof(s_dev), ipath, "dev") != 0)
560+ *s_dev = '\0';
561+ if (readStr(s_ip2, sizeof(s_ip2), ipath, "ip2") != 0)
562+ *s_ip2 = '\0';
563+ }
564+ else
565+ continue;
566+
567+ if (!ip)
568+ guest->ips = ip = calloc(1, sizeof(*ip));
569+ else {
570+ ip->next = calloc(1, sizeof(*ip));
571+ ip = ip->next;
572+ }
573+ if (!ip)
574+ goto cleanup;
575+
576+ strcpy(ip->interface, s_dev);
577+
578+ if (inet_pton(AF_INET6, s_ip, &ip->addr.vna_v6_ip) > 0)
579+ ip->addr.vna_type = VC_NXA_TYPE_IPV6;
580+ else if (inet_pton(AF_INET, s_ip, &ip->addr.vna_v4_ip) > 0)
581+ ip->addr.vna_type = VC_NXA_TYPE_IPV4;
582+ else
583+ goto cleanup;
584+
585+ if (ip->addr.vna_type == VC_NXA_TYPE_IPV6) {
586+ if (*s_mask) {
587+ if (inet_pton(AF_INET6, s_mask, &ip->addr.vna_v6_mask) <= 0)
588+ goto cleanup;
589+ }
590+ if (*s_ip2) {
591+ if (inet_pton(AF_INET6, s_ip2, &ip->addr.vna_v6_ip2) <= 0)
592+ goto cleanup;
593+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
594+ }
595+ else
596+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
597+ }
598+ else if (ip->addr.vna_type == VC_NXA_TYPE_IPV4) {
599+ if (*s_mask) {
600+ if (inet_pton(AF_INET, s_mask, &ip->addr.vna_v4_mask) <= 0)
601+ goto cleanup;
602+ }
603+ if (*s_ip2) {
604+ if (inet_pton(AF_INET, s_ip2, &ip->addr.vna_v4_ip2) <= 0)
605+ goto cleanup;
606+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
607+ }
608+ else
609+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
610+ }
611+
612+ if (*s_prefix) {
613+ char *endptr;
614+ ip->addr.vna_prefix = strtoul(s_prefix, &endptr, 0);
615+ if (*endptr != '\n' && *endptr)
616+ goto cleanup;
617+ }
618+ }
619+
620+ closedir(interfaces);
621+ return 0;
622+
623+cleanup:
624+ closedir(interfaces);
625+ return -1;
626+}
627+
628+static inline char *
629+endOfField(char *start)
630+{
631+ char *end;
632+ for (end = start; *(end - 1) != '\\' &&
633+ !isspace(*end) &&
634+ *end != '\0'; end++)
635+ ;
636+ return end;
637+}
638+
639+static inline char *
640+startOfField(char *end)
641+{
642+ char *start;
643+ for (start = end + 1; isspace(*start) &&
644+ *start != '\0'; start++)
645+ ;
646+ return start;
647+}
648+
649+static const struct {
650+ int mode;
651+ const char *type;
652+} source_types[] = {
653+ { S_IFBLK, "block" },
654+ { S_IFREG, "file" },
655+ { S_IFDIR, "directory" },
656+};
657+
658+const char *
659+vserverFindSourceType(const char *source)
660+{
661+ struct stat st;
662+ int mode, i;
663+ if (stat(source, &st) == -1)
664+ mode = -1;
665+ else
666+ mode = st.st_mode & S_IFMT;
667+ for (i = 0; i < (sizeof(source_types) / sizeof(*source_types)); i++) {
668+ if (mode == source_types[i].mode)
669+ return source_types[i].type;
670+ }
671+ return NULL;
672+}
673+
674+static int
675+parseFstab(struct vserver_guest *guest, const char *filename)
676+{
677+ FILE *fp;
678+ char buf[256], *start, *end;
679+ struct vserver_fstab *ent = NULL;
680+ char path[strlen(guest->name) + 2 + strlen(filename)];
681+
682+ sprintf(path, "%s/%s", guest->name, filename);
683+ if ((fp = fopen(path, "r")) == NULL)
684+ return 0;
685+
686+ while (fgets(buf, sizeof(buf), fp) != NULL) {
687+ if (!ent)
688+ guest->fstab = ent = calloc(1, sizeof(*ent));
689+ else {
690+ ent->next = calloc(1, sizeof(*ent));
691+ ent = ent->next;
692+ }
693+ if (!ent)
694+ goto err;
695+
696+ start = buf;
697+ end = endOfField(start);
698+ *end = '\0';
699+ ent->source = strdup(start);
700+ ent->source_type = vserverFindSourceType(start);
701+
702+ ent->flags |= VSERVER_FSTAB_OUTPUT;
703+ if (ent->source_type)
704+ ent->flags |= VSERVER_FSTAB_SHOW;
705+
706+ start = startOfField(end);
707+ end = endOfField(start);
708+ *end = '\0';
709+ ent->target = strdup(start);
710+
711+ start = startOfField(end);
712+ end = endOfField(start);
713+ *end = '\0';
714+ ent->fstype = strdup(start);
715+
716+ start = startOfField(end);
717+ end = endOfField(start);
718+ if (*end != '\0') {
719+ char *ptr;
720+ ent->rest = strdup(end + 1);
721+ ptr = strchr(ent->rest, '\n');
722+ if (ptr)
723+ *ptr = '\0';
724+ }
725+ else
726+ ent->rest = NULL;
727+ *end = '\0';
728+ ent->options = strdup(start);
729+
730+ if (!ent->source || !ent->target || !ent->fstype || !ent->options)
731+ goto err;
732+ }
733+
734+ fclose(fp);
735+ return 0;
736+
737+err:
738+ fclose(fp);
739+ return -1;
740+}
741+
742+virDrvOpenStatus
743+vserverInitializeDriver(virConnectPtr conn, struct vserver_driver *driver,
744+ const char *path)
745+{
746+ struct vserver_guest *guest = NULL;
747+ DIR *dp = NULL;
748+ struct dirent *de;
749+ int cwd;
750+ const char *conf_dir = (*path ? path : VSERVER_CONF_DIR);
751+
752+ if (driver->initialized == 1)
753+ return VIR_DRV_OPEN_SUCCESS;
754+
755+ driver->guests = NULL;
756+ driver->inactive_guests = driver->active_guests = 0;
757+
758+ cwd = open(".", O_RDONLY);
759+ if (cwd == -1 ||
760+ chdir(conf_dir) == -1 ||
761+ (dp = opendir(".")) == NULL) {
762+ vserverError(conn, NULL, NULL, VIR_ERR_OPEN_FAILED, conf_dir);
763+ goto error;
764+ }
765+
766+ while ((de = readdir(dp)) != NULL) {
767+ char uuidstr[VIR_UUID_STRING_BUFLEN + 1];
768+ char mark[32];
769+ char tmp;
770+
771+ if (*de->d_name == '.')
772+ continue;
773+
774+ if (driver->guests == NULL)
775+ driver->guests = guest = calloc(1, sizeof(struct vserver_guest));
776+ else {
777+ guest->next = calloc(1, sizeof(struct vserver_guest));
778+ guest = guest->next;
779+ }
780+
781+ if (!guest) {
782+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
783+ "vserver_guest");
784+ goto error;
785+ }
786+
787+ guest->path = calloc(strlen(conf_dir) + 1 + strlen(de->d_name) + 1, sizeof(char));
788+ if (!guest->path)
789+ goto nomem;
790+ sprintf(guest->path, "%s/%s", conf_dir, de->d_name);
791+
792+#define CHECK(x) \
793+ if ((x) == -1) { \
794+ goto parseerror; \
795+ }
796+#define DO_SCHED(type, var, file, bit) \
797+ do { \
798+ int ret; \
799+ CHECK(ret = read ## type((var), de->d_name, (file))); \
800+ if (ret == 0) \
801+ guest->sched.set_mask |= (bit); \
802+ } while (0)
803+
804+ /* Parse simple values */
805+ CHECK(readInt(&guest->xid, de->d_name, "context"));
806+ CHECK(readStr(guest->name, sizeof(guest->name), de->d_name, "name"));
807+ CHECK(readStr(guest->uts.hostname, sizeof(guest->uts.hostname), de->d_name,
808+ "uts/nodename"));
809+ CHECK(readStr(guest->uts.machine, sizeof(guest->uts.machine), de->d_name,
810+ "uts/machine"));
811+ CHECK(readStr(guest->uts.release, sizeof(guest->uts.release), de->d_name,
812+ "uts/release"));
813+ CHECK(readStr(guest->uts.version, sizeof(guest->uts.version), de->d_name,
814+ "uts/version"));
815+ CHECK(readStr(mark, sizeof(mark), de->d_name, "apps/init/mark"));
816+
817+ DO_SCHED(Int, &guest->sched.fill_rate, "sched/fill-rate",
818+ VC_VXSM_FILL_RATE);
819+ DO_SCHED(Int, &guest->sched.interval, "sched/interval",
820+ VC_VXSM_INTERVAL);
821+ DO_SCHED(Int, &guest->sched.fill_rate2, "sched/fill-rate2",
822+ VC_VXSM_FILL_RATE2);
823+ DO_SCHED(Int, &guest->sched.interval2, "sched/interval2",
824+ VC_VXSM_INTERVAL2);
825+ DO_SCHED(Int, &guest->sched.tokens_min, "sched/tokens-min",
826+ VC_VXSM_TOKENS_MIN);
827+ DO_SCHED(Int, &guest->sched.tokens_max, "sched/tokens-max",
828+ VC_VXSM_TOKENS_MAX);
829+ DO_SCHED(Int, &guest->sched.priority_bias, "sched/priority-bias",
830+ VC_VXSM_PRIO_BIAS);
831+ if (readBool(&tmp, de->d_name, "sched/idle-time") == 0) {
832+ if (tmp)
833+ guest->sched.set_mask |= VC_VXSM_IDLE_TIME;
834+ }
835+
836+ CHECK(readLong(&guest->rss_hard, de->d_name, "rlimits/rss.hard"));
837+
838+ /* Generate a UUID if one doesn't already exist */
839+ switch (readStr(uuidstr, sizeof(uuidstr), de->d_name, "uuid")) {
840+ case 1:
841+ CHECK(virUUIDGenerate(guest->uuid));
842+ virUUIDFormat(guest->uuid, uuidstr);
843+ CHECK(vserverWriteToConfig(guest, "uuid", "%s\n", uuidstr));
844+ break;
845+ case 0:
846+ CHECK(virUUIDParse(uuidstr, guest->uuid));
847+ break;
848+ case -1:
849+ goto parseerror;
850+ }
851+
852+ /* Parse interfaces */
853+ if (parseInterfaces(guest, "interfaces") == -1)
854+ goto parseerror;
855+
856+ /* Parse fstab */
857+ if (parseFstab(guest, "fstab") == -1)
858+ goto parseerror;
859+
860+ /* Make sure the guest has the / directory in the disk output */
861+ do {
862+ struct vserver_fstab *ent;
863+ int has_root = 0;
864+ for (ent = guest->fstab; ent; ent = ent->next) {
865+ if (strcmp(ent->target, "/") == 0) {
866+ has_root = 1;
867+ break;
868+ }
869+ }
870+ if (!has_root) {
871+ char vdir[strlen(de->d_name) + sizeof("/vdir")];
872+
873+ ent = calloc(1, sizeof(*ent));
874+ if (!ent)
875+ goto nomem;
876+
877+ sprintf(vdir, "%s/vdir", de->d_name);
878+ ent->source = realpath(vdir, NULL);
879+
880+ ent->flags = VSERVER_FSTAB_SHOW;
881+ ent->source_type = vserverFindSourceType("/");
882+ ent->target = strdup("/");
883+ ent->fstype = strdup("auto");
884+ ent->options = strdup("defaults");
885+ if (!ent->source || !ent->target || !ent->fstype || !ent->options)
886+ goto nomem;
887+ ent->next = guest->fstab;
888+ guest->fstab = ent;
889+ }
890+ } while (0);
891+#undef DO_SCHED
892+#undef CHECK
893+
894+ if (STREQ(mark, "default"))
895+ guest->autostart = 1;
896+ if (vserverContextIsRunning(guest->path)) {
897+ struct vc_ctx_flags flags;
898+ if (vc_get_cflags(guest->xid, &flags) == 0 &&
899+ (flags.flagword & VC_VXF_SCHED_PAUSE))
900+ guest->status = VIR_DOMAIN_PAUSED;
901+ else
902+ guest->status = VIR_DOMAIN_RUNNING;
903+ driver->active_guests++;
904+ }
905+ else {
906+ guest->status = VIR_DOMAIN_SHUTOFF;
907+ driver->inactive_guests++;
908+ }
909+ }
910+
911+ closedir(dp);
912+ if (fchdir(cwd) == -1 || close(cwd) == -1) {
913+ /* do nothing, we succeeded with everything else... */
914+ }
915+ driver->initialized = 1;
916+
917+ return VIR_DRV_OPEN_SUCCESS;
918+
919+nomem:
920+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
921+ goto error;
922+parseerror:
923+ vserverError(conn, NULL, NULL, VIR_ERR_PARSE_FAILED, de->d_name);
924+error:
925+ if (dp)
926+ closedir(dp);
927+
928+ if (fchdir(cwd) == -1 || close(cwd) == -1) {
929+ /* we're already failing, nothing to do */
930+ }
931+ return VIR_DRV_OPEN_ERROR;
932+}
933+
934+#endif
eb319e62
ER
935--- libvirt-0.4.0.orig/src/vserver/vserver_conf.h 1970-01-01 01:00:00.000000000 +0100
936+++ libvirt-0.4.0.vserver/src/vserver/vserver_conf.h 2008-01-05 02:10:20.000000000 +0100
bd1fcfb7
ER
937@@ -0,0 +1,36 @@
938+/*
939+ * Configuration handling for Linux-VServer guests
940+ *
941+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
942+ *
943+ * This library is free software; you can redistribute it and/or
944+ * modify it under the terms of the GNU Lesser General Public
945+ * License as published by the Free Software Foundation; either
946+ * version 2.1 of the License, or (at your option) any later version.
947+ *
948+ * This library is distributed in the hope that it will be useful,
949+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
950+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
951+ * Lesser General Public License for more details.
952+ *
953+ * You should have received a copy of the GNU Lesser General Public
954+ * License along with this library; if not, write to the Free Software
955+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
956+ *
957+ * Author: Daniel Hokka Zakrisson <daniel hozac com>
958+ */
959+
960+#ifdef WITH_VSERVER
961+
962+/* Kind of a hack */
963+#ifdef IN_VSERVER
964+int vserverWriteToConfig(struct vserver_guest *guest, const char *filename,
965+ const char *format, ...);
966+int vserverWriteGuestToConfig(struct vserver_guest *guest);
967+virDrvOpenStatus vserverInitializeDriver(virConnectPtr conn,
968+ struct vserver_driver *driver,
969+ const char *path);
970+const char *vserverFindSourceType(const char *source);
971+#endif
972+
973+#endif
974diff -Nurp libvirt-0.4.0.orig/src/vserver_driver.c libvirt-0.4.0.vserver/src/vserver_driver.c
975--- libvirt-0.4.0.orig/src/vserver_driver.c 1970-01-01 01:00:00.000000000 +0100
976+++ libvirt-0.4.0.vserver/src/vserver_driver.c 2008-01-09 22:43:23.000000000 +0100
977@@ -0,0 +1,1625 @@
978+/*
979+ * Core driver for managing Linux-VServer guests
980+ *
981+ * Copyright (C) 2007-2008 Daniel Hokka Zakrisson
982+ *
983+ * This library is free software; you can redistribute it and/or
984+ * modify it under the terms of the GNU Lesser General Public
985+ * License as published by the Free Software Foundation; either
986+ * version 2.1 of the License, or (at your option) any later version.
987+ *
988+ * This library is distributed in the hope that it will be useful,
989+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
990+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
991+ * Lesser General Public License for more details.
992+ *
993+ * You should have received a copy of the GNU Lesser General Public
994+ * License along with this library; if not, write to the Free Software
995+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
996+ *
997+ * Author: Daniel Hokka Zakrisson <daniel hozac com>
998+ */
999+
1000+#ifdef WITH_VSERVER
1001+
1002+#define _GNU_SOURCE
1003+
1004+#ifdef HAVE_CONFIG_H
1005+# include <config.h>
1006+#endif
1007+
1008+#include <stdio.h>
1009+#include <unistd.h>
1010+#include <stdlib.h>
1011+#include <string.h>
1012+#include <fcntl.h>
1013+#include <dirent.h>
1014+#include <sys/wait.h>
1015+#include <errno.h>
1016+#include <sys/types.h>
1017+#include <sys/socket.h>
1018+#include <arpa/inet.h>
1019+#include <net/if.h>
1020+#include <sys/syscall.h>
1021+
1022+#include <libxml/uri.h>
1023+#include <libxml/xpath.h>
1024+#include <libxml/tree.h>
1025+
1026+#include <libvirt/virterror.h>
1027+
1028+#define IN_VSERVER 1
1029+#include "internal.h"
1030+#include "vserver_driver.h"
1031+#include "vserver_conf.h"
1032+#include "buf.h"
1033+#include "uuid.h"
1034+#include "xml.h"
1035+#include "nodeinfo.h"
1036+
1037+#define GET_DOMAIN(dom, ret) \
1038+ struct vserver_driver *driver = (struct vserver_driver *) \
1039+ (dom)->conn->privateData; \
1040+ struct vserver_guest *guest = getGuestByUUID(driver, (dom)->uuid); \
1041+ \
1042+ if (!guest) { \
1043+ vserverError((dom)->conn, (dom), NULL, VIR_ERR_INVALID_ARG, \
1044+ __FUNCTION__); \
1045+ return (ret); \
1046+ }
1047+
1048+#ifndef MNT_DETACH
1049+# define MNT_DETACH 0x00000002
1050+#endif
1051+
1052+static int PAGE_SHIFT_TO_KIBI = 2;
1053+
1054+static inline int sys_umount(const char *path, int flags)
1055+{
1056+ return syscall(__NR_umount2, path, flags);
1057+}
1058+
1059+static inline struct vserver_guest *
1060+getGuestByID(struct vserver_driver *driver,
1061+ int id)
1062+{
1063+ struct vserver_guest *res;
1064+ for (res = driver->guests; res; res = res->next) {
1065+ if (res->xid == id)
1066+ break;
1067+ }
1068+ return res;
1069+}
1070+
1071+static inline struct vserver_guest *
1072+getGuestByUUID(struct vserver_driver *driver,
1073+ const unsigned char *uuid)
1074+{
1075+ struct vserver_guest *res;
1076+ for (res = driver->guests; res; res = res->next) {
1077+ if (memcmp(res->uuid, uuid, VIR_UUID_BUFLEN) == 0)
1078+ break;
1079+ }
1080+ return res;
1081+}
1082+
1083+static inline struct vserver_guest *
1084+getGuestByName(struct vserver_driver *driver,
1085+ const char *name)
1086+{
1087+ struct vserver_guest *res;
1088+ for (res = driver->guests; res; res = res->next) {
1089+ if (STREQ(res->name, name))
1090+ break;
1091+ }
1092+ return res;
1093+}
1094+
1095+void
1096+vserverError(virConnectPtr con,
1097+ virDomainPtr dom,
1098+ virNetworkPtr net,
1099+ virErrorNumber error,
1100+ const char *info)
1101+{
1102+ const char *errmsg;
1103+
1104+ if (error == VIR_ERR_OK)
1105+ return;
1106+
1107+ errmsg = __virErrorMsg(error, info);
1108+ __virRaiseError(con, dom, net, VIR_FROM_VSERVER, error, VIR_ERR_ERROR,
1109+ errmsg, info, NULL, 0, 0, errmsg, info, 0);
1110+}
1111+
1112+/* like execl, but uses /dev/null and handles forking/waiting/etc. */
1113+int
1114+vserverRunCommand(int do_daemon, const char *cmd, ...)
1115+{
1116+ pid_t pid;
1117+ va_list va;
1118+ char **argv;
1119+ int i, argc;
1120+ sighandler_t sigchld;
1121+ int ret;
1122+
1123+ va_start(va, cmd);
1124+ argc = 15;
1125+ argv = calloc(argc, sizeof(*argv));
1126+ argv[0] = (char *) cmd;
1127+ for (i = 1; (argv[i] = va_arg(va, char *)) != NULL; i++) {
1128+ if (i == argc-1) {
1129+ argc += 5;
1130+ argv = realloc(argv, sizeof(*argv) * argc);
1131+ }
1132+ }
1133+
1134+ va_end(va);
1135+
1136+ /* XXX: This is bad, since another child could die
1137+ * between here and where we restore it */
1138+ sigchld = signal(SIGCHLD, SIG_DFL);
1139+ if ((pid = fork()) == 0) {
1140+ int fd;
1141+ if (do_daemon) {
1142+ pid_t not_a_zombie;
1143+
1144+ if (setsid() == -1)
1145+ goto error;
1146+
1147+ not_a_zombie = fork();
1148+ if (not_a_zombie == -1)
1149+ goto error;
1150+ else if (not_a_zombie > 0)
1151+ _exit(0);
1152+ }
1153+ if ((fd = open("/dev/null", O_RDWR)) == -1)
1154+ goto error;
1155+ if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1)
1156+ goto error;
1157+ if (fd > 2 && close(fd) == -1)
1158+ goto error;
1159+ execvp(cmd, argv);
1160+ error:
1161+ _exit(1);
1162+ }
1163+ else if (pid == -1) {
1164+ ret = -1;
1165+ }
1166+ else {
1167+ int status;
1168+ if (waitpid(pid, &status, 0) == -1)
1169+ ret = -1;
1170+ else if (WEXITSTATUS(status) != 0)
1171+ ret = 1;
1172+ else
1173+ ret = 0;
1174+ }
1175+
1176+ signal(SIGCHLD, sigchld);
1177+ return ret;
1178+}
1179+
1180+int
1181+vserverContextIsRunning(const char *path)
1182+{
1183+ return vc_getVserverCtx(path, vcCFG_AUTO, false, 0, vcCTX_XID) != VC_NOCTX;
1184+}
1185+
1186+static void
1187+vserverSetPagesize(void)
1188+{
1189+ long page_size = sysconf(_SC_PAGESIZE);
1190+ PAGE_SHIFT_TO_KIBI = page_size / 1024;
1191+}
1192+
1193+static virDrvOpenStatus
1194+vserverOpen(virConnectPtr conn, xmlURIPtr uri,
1195+ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1196+ int flags ATTRIBUTE_UNUSED)
1197+{
1198+ virDrvOpenStatus ret;
1199+ struct vserver_driver *driver;
1200+
1201+ if (!uri)
1202+ return VIR_DRV_OPEN_DECLINED;
1203+
1204+ if (getuid() != 0)
1205+ return VIR_DRV_OPEN_DECLINED;
1206+
1207+ if (!uri->scheme || STRNEQ(uri->scheme, "vserver"))
1208+ return VIR_DRV_OPEN_DECLINED;
1209+
1210+ if (uri->server)
1211+ return VIR_DRV_OPEN_DECLINED;
1212+
1213+ /* nothing else supported right now */
1214+ if (strncmp(uri->path, "/system", 7) != 0)
1215+ return VIR_DRV_OPEN_DECLINED;
1216+
1217+ /* make sure it's a Linux-VServer kernel */
1218+ if (vc_get_version() == -1)
1219+ return VIR_DRV_OPEN_DECLINED;
1220+
1221+ if (!conn->privateData)
1222+ conn->privateData = calloc(1, sizeof(struct vserver_driver));
1223+
1224+ ret = vserverInitializeDriver(conn, conn->privateData, uri->path + 7);
1225+ if (ret == VIR_DRV_OPEN_SUCCESS) {
1226+ driver = conn->privateData;
1227+ driver->uri = xmlSaveUri(uri);
1228+ }
1229+ else {
1230+ free(conn->privateData);
1231+ }
1232+
1233+ vserverSetPagesize();
1234+
1235+ return ret;
1236+}
1237+
1238+static void
1239+freeFstab(struct vserver_fstab *ent)
1240+{
1241+ free(ent->source);
1242+ free(ent->target);
1243+ free(ent->fstype);
1244+ free(ent->options);
1245+ free(ent);
1246+}
1247+
1248+static void
1249+freeGuest(struct vserver_guest *guest)
1250+{
1251+ struct vserver_ip *ip, *pip = NULL;
1252+ struct vserver_fstab *ent, *pent = NULL;
1253+ for (ip = guest->ips; ip; ip = ip->next) {
1254+ if (pip)
1255+ free(pip);
1256+ pip = ip;
1257+ }
1258+ if (pip)
1259+ free(pip);
1260+ for (ent = guest->fstab; ent; ent = ent->next) {
1261+ if (pent)
1262+ freeFstab(pent);
1263+ pent = ent;
1264+ }
1265+ if (pent)
1266+ freeFstab(pent);
1267+ free(guest->path);
1268+ free(guest);
1269+}
1270+
1271+static int
1272+vserverClose(virConnectPtr conn)
1273+{
1274+ struct vserver_driver *driver = conn->privateData;
1275+ struct vserver_guest *guest, *pguest;
1276+
1277+ if (!driver || !driver->initialized)
1278+ return 0;
1279+
1280+ for (guest = driver->guests, pguest = NULL; guest; guest = guest->next) {
1281+ if (pguest)
1282+ freeGuest(pguest);
1283+ pguest = guest;
1284+ }
1285+ if (pguest)
1286+ freeGuest(pguest);
1287+
1288+ xmlFree(driver->uri);
1289+ free(driver);
1290+ conn->privateData = NULL;
1291+
1292+ return 0;
1293+}
1294+
1295+static const char *
1296+vserverGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
1297+{
1298+ return "Linux-VServer";
1299+}
1300+
1301+static int
1302+vserverGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
1303+{
1304+ *version = 1;
1305+ return 0;
1306+}
1307+
1308+static char *
1309+vserverGetHostname(virConnectPtr conn)
1310+{
1311+ char *ret;
1312+
1313+ ret = calloc(VSERVER_UTS_MAX + 1, sizeof(char));
1314+ if (!ret) {
1315+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "gethostname");
1316+ return NULL;
1317+ }
1318+
1319+ if (gethostname(ret, VSERVER_UTS_MAX) == -1) {
1320+ free(ret);
1321+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno));
1322+ return NULL;
1323+ }
1324+
1325+ return ret;
1326+}
1327+
1328+static char *
1329+vserverGetURI(virConnectPtr conn)
1330+{
1331+ struct vserver_driver *driver = conn->privateData;
1332+ return (char *) xmlStrdup(driver->uri);
1333+}
1334+
1335+static int
1336+vserverNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
1337+{
1338+ return virNodeInfoPopulate(conn, nodeinfo);
1339+}
1340+
1341+static int
1342+vserverListDomains(virConnectPtr conn, int *ids, int nids)
1343+{
1344+ struct vserver_driver *driver = conn->privateData;
1345+ struct vserver_guest *guest;
1346+ int i;
1347+
1348+ for (guest = driver->guests, i = 0; guest && i < nids;
1349+ guest = guest->next) {
1350+ if (guest->status != VIR_DOMAIN_SHUTOFF)
1351+ ids[i++] = guest->xid;
1352+ }
1353+
1354+ return i;
1355+}
1356+
1357+static int
1358+vserverNumOfDomains(virConnectPtr conn)
1359+{
1360+ struct vserver_driver *driver = conn->privateData;
1361+
1362+ return driver->active_guests;
1363+}
1364+
1365+static virDomainPtr
1366+vserverDomainLookupByID(virConnectPtr conn, int id)
1367+{
1368+ struct vserver_driver *driver = conn->privateData;
1369+ struct vserver_guest *guest;
1370+ virDomainPtr domain;
1371+
1372+ if ((guest = getGuestByID(driver, id)) == NULL) {
1373+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1374+ _("No domain by that ID found"));
1375+ return NULL;
1376+ }
1377+
1378+ domain = virGetDomain(conn, guest->name, guest->uuid);
1379+ if (!domain) {
1380+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1381+ return NULL;
1382+ }
1383+
1384+ if (vserverIsRunning(guest))
1385+ domain->id = guest->xid;
1386+
1387+ return domain;
1388+}
1389+
1390+static virDomainPtr
1391+vserverDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
1392+{
1393+ struct vserver_driver *driver = conn->privateData;
1394+ struct vserver_guest *guest;
1395+ virDomainPtr domain;
1396+
1397+ if ((guest = getGuestByUUID(driver, uuid)) == NULL) {
1398+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1399+ _("No domain by that UUID found"));
1400+ return NULL;
1401+ }
1402+
1403+ domain = virGetDomain(conn, guest->name, guest->uuid);
1404+ if (!domain) {
1405+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1406+ return NULL;
1407+ }
1408+
1409+ if (vserverIsRunning(guest))
1410+ domain->id = guest->xid;
1411+
1412+ return domain;
1413+}
1414+
1415+static virDomainPtr
1416+vserverDomainLookupByName(virConnectPtr conn, const char *name)
1417+{
1418+ struct vserver_driver *driver = conn->privateData;
1419+ struct vserver_guest *guest;
1420+ virDomainPtr domain;
1421+
1422+ if ((guest = getGuestByName(driver, name)) == NULL) {
1423+ vserverError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
1424+ _("No domain by that name found"));
1425+ return NULL;
1426+ }
1427+
1428+ domain = virGetDomain(conn, guest->name, guest->uuid);
1429+ if (!domain) {
1430+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
1431+ return NULL;
1432+ }
1433+
1434+ if (vserverIsRunning(guest))
1435+ domain->id = guest->xid;
1436+
1437+ return domain;
1438+}
1439+
1440+static int
1441+vserverDomainSuspend(virDomainPtr domain)
1442+{
1443+ struct vc_ctx_flags flags = {
1444+ .flagword = VC_VXF_SCHED_PAUSE,
1445+ .mask = VC_VXF_SCHED_PAUSE,
1446+ };
1447+ GET_DOMAIN(domain, -1);
1448+
1449+ if (guest->status == VIR_DOMAIN_PAUSED)
1450+ return 0;
1451+ if (guest->status != VIR_DOMAIN_RUNNING) {
1452+ vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED,
1453+ _("domain is not running"));
1454+ return -1;
1455+ }
1456+
1457+ if (vc_set_cflags(guest->xid, &flags) == -1) {
1458+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1459+ strerror(errno));
1460+ return -1;
1461+ }
1462+ guest->status = VIR_DOMAIN_PAUSED;
1463+
1464+ return 0;
1465+}
1466+
1467+static int
1468+vserverDomainResume(virDomainPtr domain)
1469+{
1470+ struct vc_ctx_flags flags = {
1471+ .flagword = 0,
1472+ .mask = VC_VXF_SCHED_PAUSE,
1473+ };
1474+ GET_DOMAIN(domain, -1);
1475+
1476+ if (guest->status == VIR_DOMAIN_RUNNING)
1477+ return 0;
1478+ if (guest->status != VIR_DOMAIN_PAUSED) {
1479+ vserverError(domain->conn, domain, NULL, VIR_ERR_OPERATION_FAILED,
1480+ _("domain is not running"));
1481+ return -1;
1482+ }
1483+
1484+ if (vc_set_cflags(guest->xid, &flags) == -1) {
1485+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1486+ strerror(errno));
1487+ return -1;
1488+ }
1489+ guest->status = VIR_DOMAIN_RUNNING;
1490+
1491+ return 0;
1492+}
1493+
1494+static int
1495+vserverDomainShutdown(virDomainPtr domain)
1496+{
1497+ GET_DOMAIN(domain, -1);
1498+
1499+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "stop", NULL) != 0) {
1500+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1501+ "vserver stop");
1502+ return -1;
1503+ }
1504+
1505+ driver->active_guests--;
1506+ guest->status = VIR_DOMAIN_SHUTOFF;
1507+ driver->inactive_guests++;
1508+ return 0;
1509+}
1510+
1511+static int
1512+vserverDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
1513+{
1514+ GET_DOMAIN(domain, -1);
1515+
1516+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "restart", NULL) != 0) {
1517+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1518+ "vserver restart");
1519+ return -1;
1520+ }
1521+
1522+ guest->status = VIR_DOMAIN_RUNNING;
1523+ return 0;
1524+}
1525+
1526+static int
1527+vserverDomainDestroy(virDomainPtr domain)
1528+{
1529+ GET_DOMAIN(domain, -1);
1530+
1531+ if (vserverDomainShutdown(domain) == -1)
1532+ return -1;
1533+
1534+ virFreeDomain(domain->conn, domain);
1535+
1536+ return 0;
1537+}
1538+
1539+static char *
1540+vserverDomainGetOSType(virDomainPtr domain ATTRIBUTE_UNUSED)
1541+{
1542+ return strdup("Linux");
1543+}
1544+
1545+static unsigned long
1546+vserverDomainGetMaxMemory(virDomainPtr domain)
1547+{
1548+ GET_DOMAIN(domain, (unsigned long) -1);
1549+
1550+ return guest->rss_hard << PAGE_SHIFT_TO_KIBI;
1551+}
1552+
1553+static int
1554+vserverDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
1555+{
1556+ struct vc_rlimit limit = {
1557+ .min = 0,
1558+ };
1559+ GET_DOMAIN(domain, -1);
1560+
1561+ guest->rss_hard = memory >> PAGE_SHIFT_TO_KIBI;
1562+ limit.soft = limit.hard = guest->rss_hard;
1563+ if (vserverIsRunning(guest) &&
1564+ vc_set_rlimit(guest->xid, RLIMIT_RSS, &limit) == -1) {
1565+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR, strerror(errno));
1566+ return -1;
1567+ }
1568+
1569+ if (vserverWriteToConfig(guest, "rlimits/rss.hard", "%lu\n", guest->rss_hard) == -1) {
1570+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1571+ strerror(errno));
1572+ return -1;
1573+ }
1574+
1575+ return 0;
1576+}
1577+
1578+static int
1579+vserverDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
1580+{
1581+ struct vc_sched_info sinfo = { .user_msec = 0, .sys_msec = 0 };
1582+ struct vc_rlimit_stat rss_stat = { .value = 0 };
1583+ GET_DOMAIN(domain, -1);
1584+
1585+ if (vserverIsRunning(guest)) {
1586+ if (vc_sched_info(guest->xid, &sinfo) == -1) {
1587+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1588+ strerror(errno));
1589+ return -1;
1590+ }
1591+ if (vc_rlimit_stat(guest->xid, RLIMIT_RSS, &rss_stat) == -1) {
1592+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
1593+ strerror(errno));
1594+ return -1;
1595+ }
1596+ }
1597+
1598+ info->state = guest->status;
1599+ info->maxMem = guest->rss_hard << PAGE_SHIFT_TO_KIBI;
1600+ info->nrVirtCpu = -1;
1601+ info->memory = rss_stat.value;
1602+ info->cpuTime = (sinfo.user_msec + sinfo.sys_msec) * 1000000ULL;
1603+
1604+ return 0;
1605+}
1606+
1607+static char *
1608+vserverDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
1609+{
1610+ virBufferPtr buf;
1611+ char uuid[VIR_UUID_STRING_BUFLEN + 1];
1612+ struct vserver_ip *ip;
1613+ GET_DOMAIN(domain, NULL);
1614+
1615+ buf = virBufferNew(4096);
1616+ if (!buf)
1617+ goto no_memory;
1618+
1619+ virUUIDFormat(guest->uuid, uuid);
1620+ if (virBufferVSprintf(buf,
1621+"<domain type='vserver' id='%d'>\n"
1622+" <name>%s</name>\n"
1623+" <uuid>%s</uuid>\n"
1624+ , guest->xid, guest->name, uuid
1625+ ) < 0)
1626+ goto no_memory;
1627+ if (guest->rss_hard > 0)
1628+ if (virBufferVSprintf(buf, " <memory>%lu</memory>\n",
1629+ guest->rss_hard << PAGE_SHIFT_TO_KIBI) < 0)
1630+ goto no_memory;
1631+
1632+ if (virBufferVSprintf(buf, " <os>\n"
1633+ " <hostname>%s</hostname>\n"
1634+ , guest->uts.hostname) < 0)
1635+ goto no_memory;
1636+ if (virBufferVSprintf(buf, " <type") < 0)
1637+ goto no_memory;
1638+ if (*guest->uts.machine)
1639+ if (virBufferVSprintf(buf, " arch='%s'", guest->uts.machine) < 0)
1640+ goto no_memory;
1641+ if (virBufferVSprintf(buf, ">vserver</type>\n") < 0)
1642+ goto no_memory;
1643+ if (*guest->uts.release)
1644+ if (virBufferVSprintf(buf, " <release>%s</release>\n",
1645+ guest->uts.release) < 0)
1646+ goto no_memory;
1647+ if (*guest->uts.version)
1648+ if (virBufferVSprintf(buf, " <version>%s</version>\n",
1649+ guest->uts.version) < 0)
1650+ goto no_memory;
1651+ if (virBufferVSprintf(buf, " </os>\n"
1652+ " <devices>\n") < 0)
1653+ goto no_memory;
1654+
1655+ for (ip = guest->ips; ip; ip = ip->next) {
1656+ char addrbuf[128];
1657+ if (virBufferVSprintf(buf, " <interface type='ethernet'>\n"
1658+ " <ip prefix='%d'", ip->addr.vna_prefix) < 0)
1659+ goto no_memory;
1660+ if (*ip->interface)
1661+ if (virBufferVSprintf(buf, " interface='%s'", ip->interface) < 0)
1662+ goto no_memory;
1663+
1664+ switch (ip->addr.vna_type & (VC_NXA_TYPE_IPV4|VC_NXA_TYPE_IPV6)) {
1665+ case VC_NXA_TYPE_IPV4:
1666+ inet_ntop(AF_INET, &ip->addr.vna_v4_ip, addrbuf, sizeof(addrbuf));
1667+ if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0)
1668+ goto no_memory;
1669+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE)) {
1670+ inet_ntop(AF_INET, &ip->addr.vna_v4_ip2, addrbuf, sizeof(addrbuf));
1671+ if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0)
1672+ goto no_memory;
1673+ }
1674+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) {
1675+ if (virBufferVSprintf(buf, " type='mask'") < 0)
1676+ goto no_memory;
1677+ }
1678+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_RANGE) ||
1679+ ip->addr.vna_type == (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_MASK)) {
1680+ inet_ntop(AF_INET, &ip->addr.vna_v4_mask, addrbuf, sizeof(addrbuf));
1681+ if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0)
1682+ goto no_memory;
1683+ }
1684+ break;
1685+
1686+ case VC_NXA_TYPE_IPV6:
1687+ inet_ntop(AF_INET6, &ip->addr.vna_v6_ip, addrbuf, sizeof(addrbuf));
1688+ if (virBufferVSprintf(buf, " address='%s'", addrbuf) < 0)
1689+ goto no_memory;
1690+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE)) {
1691+ inet_ntop(AF_INET6, &ip->addr.vna_v6_ip2, addrbuf, sizeof(addrbuf));
1692+ if (virBufferVSprintf(buf, " address2='%s' type='range'", addrbuf) < 0)
1693+ goto no_memory;
1694+ }
1695+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) {
1696+ if (virBufferVSprintf(buf, " type='mask'") < 0)
1697+ goto no_memory;
1698+ }
1699+ if (ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_RANGE) ||
1700+ ip->addr.vna_type == (VC_NXA_TYPE_IPV6 | VC_NXA_TYPE_MASK)) {
1701+ inet_ntop(AF_INET6, &ip->addr.vna_v6_mask, addrbuf, sizeof(addrbuf));
1702+ if (virBufferVSprintf(buf, " mask='%s'", addrbuf) < 0)
1703+ goto no_memory;
1704+ }
1705+ break;
1706+ }
1707+
1708+ if (virBufferVSprintf(buf, " />\n"
1709+ " </interface>\n") < 0)
1710+ goto no_memory;
1711+ }
1712+
1713+ if (guest->fstab) {
1714+ struct vserver_fstab *ent;
1715+ for (ent = guest->fstab; ent; ent = ent->next) {
1716+ /* Skip things like proc */
1717+ if (!(ent->flags & VSERVER_FSTAB_SHOW))
1718+ continue;
1719+ if (virBufferVSprintf(buf, " <disk type='%s' device='directory'>\n"
1720+ " <source %s='%s' type='%s' options='%s'/>\n"
1721+ " <target directory='%s'/>\n"
1722+ " </disk>\n",
1723+ ent->source_type,
1724+ (strcmp(ent->source_type, "block") == 0 ?
1725+ "dev" : ent->source_type),
1726+ ent->source,
1727+ ent->fstype,
1728+ ent->options,
1729+ ent->target) < 0)
1730+ goto no_memory;
1731+ }
1732+ }
1733+
1734+ if (virBufferVSprintf(buf, " </devices>\n"
1735+ "</domain>\n") < 0)
1736+ goto no_memory;
1737+
1738+ return virBufferContentAndFree(buf);
1739+
1740+no_memory:
1741+ if (buf)
1742+ virBufferFree(buf);
1743+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY,
1744+ "xml");
1745+ return NULL;
1746+}
1747+
1748+static int
1749+vserverParseIP(struct vserver_ip *ip, xmlNodePtr node)
1750+{
1751+ xmlChar *value;
1752+ char *endptr;
1753+
1754+ value = xmlGetProp(node, BAD_CAST "address");
1755+ if (!value)
1756+ goto err;
1757+ if (inet_pton(AF_INET6, (char *) value, &ip->addr.vna_v6_ip) > 0)
1758+ ip->addr.vna_type = VC_NXA_TYPE_IPV6;
1759+ else if (inet_pton(AF_INET, (char *) value, &ip->addr.vna_v4_ip) > 0)
1760+ ip->addr.vna_type = VC_NXA_TYPE_IPV4;
1761+ else
1762+ goto err;
1763+
1764+ value = xmlGetProp(node, BAD_CAST "prefix");
1765+ if (!value)
1766+ goto err;
1767+ ip->addr.vna_prefix = strtol((char *) value, &endptr, 0);
1768+ if (*endptr)
1769+ goto err;
1770+ xmlFree(value);
1771+
1772+ value = xmlGetProp(node, BAD_CAST "type");
1773+ if (!value)
1774+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
1775+ else {
1776+ if (xmlStrcasecmp(value, BAD_CAST "address") == 0)
1777+ ip->addr.vna_type |= VC_NXA_TYPE_ADDR;
1778+ else if (xmlStrcasecmp(value, BAD_CAST "mask") == 0)
1779+ ip->addr.vna_type |= VC_NXA_TYPE_MASK;
1780+ else if (xmlStrcasecmp(value, BAD_CAST "range") == 0)
1781+ ip->addr.vna_type |= VC_NXA_TYPE_RANGE;
1782+ else
1783+ goto err;
1784+ xmlFree(value);
1785+ }
1786+
1787+ value = xmlGetProp(node, BAD_CAST "interface");
1788+ if (value) {
1789+ strncpy(ip->interface, (char *) value, IFNAMSIZ);
1790+ xmlFree(value);
1791+ }
1792+
1793+ return 0;
1794+
1795+err:
1796+ if (value)
1797+ xmlFree(value);
1798+ return -1;
1799+}
1800+
1801+static const char *
1802+diskTypeToAttr(const char *type)
1803+{
1804+ return (strcmp(type, "block") == 0 ? "dev" : type);
1805+}
1806+
1807+static int
1808+vserverParseDisk(struct vserver_fstab *ent, xmlNodePtr node)
1809+{
1810+ xmlChar *type = NULL, *value = NULL;
1811+ xmlNodePtr iter, source = NULL, target = NULL;
1812+
1813+ for (iter = node->children; iter && (!source || !target); iter = iter->next) {
1814+ if (iter->type != XML_ELEMENT_NODE)
1815+ continue;
1816+ if (xmlStrEqual(iter->name, BAD_CAST "source"))
1817+ source = iter;
1818+ else if (xmlStrEqual(iter->name, BAD_CAST "target"))
1819+ target = iter;
1820+ }
1821+ if (!target || !source)
1822+ goto err;
1823+
1824+ value = xmlGetProp(node, BAD_CAST "device");
1825+ if (!value || !xmlStrEqual(value, BAD_CAST "directory"))
1826+ goto err;
1827+ xmlFree(value);
1828+
1829+ ent->target = (char *) xmlGetProp(target, BAD_CAST "directory");
1830+ if (!value)
1831+ goto err;
1832+
1833+ type = xmlGetProp(node, BAD_CAST "type");
1834+ if (!type)
1835+ goto err;
1836+ ent->source = (char *) xmlGetProp(source, BAD_CAST diskTypeToAttr((char *) type));
1837+ xmlFree(type);
1838+ if (!ent->source)
1839+ goto err;
1840+
1841+ ent->source_type = vserverFindSourceType(ent->source);
1842+ if (!ent->source_type)
1843+ goto err;
1844+
1845+ ent->fstype = (char *) xmlGetProp(source, BAD_CAST "type");
1846+ if (!ent->fstype)
1847+ ent->fstype = strdup("auto");
1848+
1849+ ent->options = (char *) xmlGetProp(source, BAD_CAST "options");
1850+ if (!ent->options) {
1851+ if (strcmp(ent->source_type, "file") == 0)
1852+ ent->options = strdup("defaults,loop");
1853+ else
1854+ ent->options = strdup("defaults");
1855+ }
1856+
1857+ ent->flags = VSERVER_FSTAB_SHOW | VSERVER_FSTAB_OUTPUT;
1858+
1859+ return 0;
1860+
1861+err:
1862+ if (ent->fstype)
1863+ xmlFree(ent->fstype);
1864+ if (ent->source)
1865+ xmlFree(ent->source);
1866+ if (ent->target)
1867+ xmlFree(ent->target);
1868+ if (value)
1869+ xmlFree(value);
1870+ return -1;
1871+}
1872+
1873+static int
1874+vserverParseXML(struct vserver_guest *guest, xmlDocPtr doc)
1875+{
1876+ xmlNodePtr root;
1877+ xmlXPathContextPtr xpath = NULL;
1878+ xmlXPathObjectPtr obj;
1879+ char *str;
1880+ long l_tmp;
1881+
1882+ /* FIXME: This could use some better error reporting... */
1883+ root = xmlDocGetRootElement(doc);
1884+ if (!root || !xmlStrEqual(root->name, BAD_CAST "domain"))
1885+ goto err;
1886+
1887+ xpath = xmlXPathNewContext(doc);
1888+ if (!xpath)
1889+ goto err;
1890+
1891+ if (virXPathLong("string(/domain[1]/@id)", xpath, &l_tmp) != 0)
1892+ goto err;
1893+ guest->xid = (int) l_tmp;
1894+
1895+ str = virXPathString("string(/domain/name[1])", xpath);
1896+ if (!str)
1897+ goto err;
1898+ strncpy(guest->name, str, VSERVER_NAME_MAX - 1);
1899+
1900+ str = virXPathString("string(/domain/uuid[1])", xpath);
1901+ if (!str) {
1902+ if (virUUIDGenerate(guest->uuid) != 0)
1903+ goto err;
1904+ }
1905+ else if (virUUIDParse(str, guest->uuid) < 0)
1906+ goto err;
1907+
1908+ guest->rss_hard = 0;
1909+ if (virXPathLong("string(/domain/memory[1])", xpath, (long *) &guest->rss_hard) == -2)
1910+ goto err;
1911+ guest->rss_hard >>= PAGE_SHIFT_TO_KIBI;
1912+
1913+ str = virXPathString("string(/domain/os[1]/hostname[1])", xpath);
1914+ if (str)
1915+ strncpy(guest->uts.hostname, str, VSERVER_UTS_MAX - 1);
1916+
1917+ str = virXPathString("string(/domain/os[1]/type[1]/@arch)", xpath);
1918+ if (str)
1919+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1920+
1921+ str = virXPathString("string(/domain/os[1]/release[1])", xpath);
1922+ if (str)
1923+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1924+
1925+ str = virXPathString("string(/domain/os[1]/version[1])", xpath);
1926+ if (str)
1927+ strncpy(guest->uts.machine, str, VSERVER_UTS_MAX - 1);
1928+
1929+ str = virXPathString("string(/domain/container/initstyle[1]/@type)", xpath);
1930+ guest->initstyle = VSERVER_INIT_SYSV;
1931+ if (str) {
1932+ if (strcmp(str, "plain") == 0)
1933+ guest->initstyle = VSERVER_INIT_PLAIN;
1934+ else if (strcmp(str, "gentoo") == 0)
1935+ guest->initstyle = VSERVER_INIT_GENTOO;
1936+ else if (strcmp(str, "minit") == 0)
1937+ guest->initstyle = VSERVER_INIT_MINIT;
1938+ else if (strcmp(str, "sysv") == 0)
1939+ guest->initstyle = VSERVER_INIT_SYSV;
1940+ }
1941+
1942+ obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/interface/ip", xpath);
1943+ if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL &&
1944+ obj->nodesetval->nodeNr > 0) {
1945+ int i;
1946+ struct vserver_ip *ip = NULL;
1947+
1948+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1949+ if (ip == NULL)
1950+ guest->ips = ip = calloc(1, sizeof(*ip));
1951+ else {
1952+ ip->next = calloc(1, sizeof(*ip));
1953+ ip = ip->next;
1954+ }
1955+
1956+ if (vserverParseIP(ip, obj->nodesetval->nodeTab[i]) == -1)
1957+ goto nodeset_err;
1958+ }
1959+ }
1960+ if (obj)
1961+ xmlXPathFreeObject(obj);
1962+
1963+ obj = xmlXPathEval(BAD_CAST "/domain/devices[1]/disk", xpath);
1964+ if (obj != NULL && obj->type == XPATH_NODESET && obj->nodesetval != NULL &&
1965+ obj->nodesetval->nodeNr > 0) {
1966+ int i;
1967+ struct vserver_fstab *ent = NULL;
1968+
1969+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1970+ if (ent == NULL)
1971+ guest->fstab = ent = calloc(1, sizeof(*ent));
1972+ else {
1973+ ent->next = calloc(1, sizeof(*ent));
1974+ ent = ent->next;
1975+ }
1976+
1977+ if (vserverParseDisk(ent, obj->nodesetval->nodeTab[i]) == -1)
1978+ goto nodeset_err;
1979+ }
1980+ }
1981+ if (obj)
1982+ xmlXPathFreeObject(obj);
1983+
1984+ xmlXPathFreeContext(xpath);
1985+ xpath = NULL;
1986+
1987+ return 0;
1988+
1989+nodeset_err:
1990+ xmlXPathFreeObject(obj);
1991+err:
1992+ if (xpath)
1993+ xmlXPathFreeContext(xpath);
1994+ return -1;
1995+}
1996+
1997+static virDomainPtr
1998+vserverDomainDefineXML(virConnectPtr conn, const char *xml)
1999+{
2000+ struct vserver_driver *driver = conn->privateData;
2001+ struct vserver_guest *guest, *tail;
2002+ virDomainPtr domain;
2003+ xmlDocPtr doc;
2004+ char buf[128];
2005+
2006+ if ((guest = calloc(1, sizeof(struct vserver_guest))) == NULL) {
2007+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "vserver_guest");
2008+ return NULL;
2009+ }
2010+
2011+ if ((doc = xmlReadDoc(BAD_CAST xml, "domain.xml", NULL,
2012+ XML_PARSE_NOENT | XML_PARSE_NONET |
2013+ XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) {
2014+ vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
2015+ free(guest);
2016+ return NULL;
2017+ }
2018+
2019+ if (vserverParseXML(guest, doc) == -1) {
2020+ vserverError(conn, NULL, NULL, VIR_ERR_XML_ERROR, _("domain"));
2021+ xmlFreeDoc(doc);
2022+ free(guest);
2023+ return NULL;
2024+ }
2025+
2026+ xmlFreeDoc(doc);
2027+
2028+ guest->path = calloc(sizeof(VSERVER_CONF_DIR "/") + strlen(guest->name), sizeof(char));
2029+ sprintf(guest->path, VSERVER_CONF_DIR "/%s", guest->name);
2030+ guest->status = VIR_DOMAIN_SHUTOFF;
2031+ if (vserverRunCommand(0, PROG_VSERVER, guest->name, "build", "-m",
2032+ "skeleton", "--confdir", guest->path, NULL) != 0) {
2033+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserver build");
2034+ free(guest);
2035+ return NULL;
2036+ }
2037+ virUUIDFormat(guest->uuid, buf);
2038+ if (vserverWriteGuestToConfig(guest) == -1) {
2039+ vserverError(conn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "vserverWriteToConfig");
2040+ free(guest);
2041+ return NULL;
2042+ }
2043+
2044+ /* add it to the list */
2045+ for (tail = driver->guests; tail && tail->next; tail = tail->next)
2046+ ;
2047+ if (!tail)
2048+ driver->guests = guest;
2049+ else
2050+ tail->next = guest;
2051+
2052+ driver->inactive_guests++;
2053+
2054+ domain = virGetDomain(conn, guest->name, guest->uuid);
2055+ if (!domain)
2056+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "virGetDomain");
2057+
2058+ return domain;
2059+}
2060+
2061+static int
2062+vserverListDefinedDomains(virConnectPtr conn, char **const names,
2063+ int maxnames)
2064+{
2065+ struct vserver_driver *driver = conn->privateData;
2066+ struct vserver_guest *guest;
2067+ int i = 0;
2068+
2069+ for (guest = driver->guests; guest && i < maxnames; guest = guest->next) {
2070+ if (guest->status == VIR_DOMAIN_SHUTOFF) {
2071+ if ((names[i++] = strdup(guest->name)) == NULL) {
2072+ vserverError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "names");
2073+ return -1;
2074+ }
2075+ }
2076+ }
2077+
2078+ return i;
2079+}
2080+
2081+static int
2082+vserverNumOfDefinedDomains(virConnectPtr conn)
2083+{
2084+ struct vserver_driver *driver = conn->privateData;
2085+
2086+ return driver->inactive_guests;
2087+}
2088+
2089+static int
2090+vserverDomainCreate(virDomainPtr domain)
2091+{
2092+ GET_DOMAIN(domain, -1);
2093+
2094+ if (vserverRunCommand(1, PROG_VSERVER, guest->path, "start", NULL) != 0) {
2095+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2096+ "vserver start");
2097+ return -1;
2098+ }
2099+
2100+ driver->inactive_guests--;
2101+ guest->status = VIR_DOMAIN_RUNNING;
2102+ driver->active_guests++;
2103+ return 0;
2104+}
2105+
2106+static virDomainPtr
2107+vserverDomainCreateLinux(virConnectPtr conn, const char *xml,
2108+ unsigned int flags ATTRIBUTE_UNUSED)
2109+{
2110+ virDomainPtr domain;
2111+
2112+ domain = vserverDomainDefineXML(conn, xml);
2113+ if (!domain)
2114+ return NULL;
2115+
2116+ if (vserverDomainCreate(domain) == -1)
2117+ return NULL;
2118+
2119+ return domain;
2120+}
2121+
2122+static int
2123+vserverDomainUndefine(virDomainPtr domain)
2124+{
2125+ struct vserver_guest *prev;
2126+ GET_DOMAIN(domain, -1);
2127+
2128+ for (prev = driver->guests; prev; prev = prev->next) {
2129+ if (prev->next == guest)
2130+ break;
2131+ }
2132+ if (!prev) {
2133+ vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
2134+ _("domain not found"));
2135+ return -1;
2136+ }
2137+ if (vserverIsRunning(guest)) {
2138+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG,
2139+ _("domain is running"));
2140+ return -1;
2141+ }
2142+
2143+ driver->inactive_guests--;
2144+ prev->next = guest->next;
2145+ /* XXX: deletes the domain's contents as well */
2146+ vserverRunCommand(0, PROG_VSERVER, "--silent", guest->path, "delete", NULL);
2147+ free(guest);
2148+
2149+ return 0;
2150+}
2151+
2152+static int
2153+doMount(int do_umount, struct vserver_guest *guest, struct vserver_fstab *ent)
2154+{
2155+ pid_t child;
2156+ int status;
2157+
2158+ if ((child = fork()) == 0) {
2159+ if (vc_enter_namespace(guest->xid, CLONE_NEWNS|CLONE_FS) == -1)
2160+ _exit(errno);
2161+ if (do_umount) {
2162+ if (sys_umount(ent->target, MNT_DETACH) == -1)
2163+ _exit(errno);
2164+ }
2165+ else {
2166+ char target[strlen(guest->path) + sizeof("/vdir/") + strlen(ent->target)];
2167+ sprintf(target, "%s/vdir/%s", guest->path, ent->target);
2168+ if (vserverRunCommand(0, "mount", "-t", ent->fstype, "-n", "-o",
2169+ ent->options, ent->source, target, NULL))
2170+ _exit(errno);
2171+ }
2172+ _exit(0);
2173+ }
2174+ else if (child == -1)
2175+ return -1;
2176+ else {
2177+ if (waitpid(child, &status, 0) == -1)
2178+ return -1;
2179+ if (WEXITSTATUS(status) != 0) {
2180+ errno = WEXITSTATUS(status);
2181+ return -1;
2182+ }
2183+ }
2184+
2185+ return 0;
2186+}
2187+
2188+static int
2189+vserverDomainHandleDevice(virDomainPtr domain, const char *xml, int attach)
2190+{
2191+ xmlDocPtr doc;
2192+ xmlNodePtr node;
2193+ GET_DOMAIN(domain, -1);
2194+
2195+ if ((doc = xmlReadDoc(BAD_CAST xml, "device.xml", NULL,
2196+ XML_PARSE_NOENT | XML_PARSE_NONET |
2197+ XML_PARSE_NOWARNING | XML_PARSE_NOERROR)) == NULL) {
2198+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, _("device"));
2199+ return -1;
2200+ }
2201+
2202+ node = xmlDocGetRootElement(doc);
2203+ if (node == NULL) {
2204+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2205+ _("missing root element"));
2206+ return -1;
2207+ }
2208+
2209+ if (xmlStrEqual(node->name, BAD_CAST "interface")) {
2210+ xmlNodePtr child;
2211+ struct vserver_ip *ip;
2212+
2213+ for (child = node->children; child; child = child->next) {
2214+ if (child->type != XML_ELEMENT_NODE)
2215+ continue;
2216+
2217+ /* This should be an only child, but who knows. */
2218+ if (xmlStrEqual(child->name, BAD_CAST "ip"))
2219+ break;
2220+ }
2221+ if (!child) {
2222+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2223+ _("no <ip> element found"));
2224+ return -1;
2225+ }
2226+
2227+ ip = calloc(1, sizeof(*ip));
2228+ if (vserverParseIP(ip, child) == -1) {
2229+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2230+ _("parsing IP failed"));
2231+ return -1;
2232+ }
2233+
2234+ if (attach) {
2235+ list_add_tail(guest->ips, ip);
2236+ if (vserverIsRunning(guest)) {
2237+ if (vc_net_add(guest->xid, &ip->addr) == -1) {
2238+ vserverError(domain->conn, domain, NULL,
2239+ VIR_ERR_SYSTEM_ERROR, strerror(errno));
2240+ return -1;
2241+ }
2242+ }
2243+ }
2244+
2245+ else /* detach */ {
2246+ struct vserver_ip *i, *p = NULL;
2247+ for (i = guest->ips; i; i = i->next) {
2248+ if (strcmp(ip->interface, i->interface) == 0 &&
2249+ memcmp(&ip->addr, &i->addr, sizeof(ip->addr)) == 0)
2250+ break;
2251+ p = i;
2252+ }
2253+ if (i) {
2254+ if (p)
2255+ p->next = i->next;
2256+ else
2257+ guest->ips = i->next;
2258+ if (vserverIsRunning(guest)) {
2259+ /* Not a lot of kernels support this, so don't fail. */
2260+ vc_net_remove(guest->xid, &ip->addr);
2261+ }
2262+ free(i);
2263+ }
2264+ free(ip);
2265+ }
2266+ }
2267+ else if (xmlStrEqual(node->name, BAD_CAST "disk")) {
2268+ struct vserver_fstab *ent = calloc(1, sizeof(*ent));
2269+ if (!ent) {
2270+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY, NULL);
2271+ return -1;
2272+ }
2273+
2274+ if (vserverParseDisk(ent, node) == -1) {
2275+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR, "disk");
2276+ return -1;
2277+ }
2278+
2279+ if (attach) {
2280+ list_add_tail(guest->fstab, ent);
2281+ if (vserverIsRunning(guest)) {
2282+ if (doMount(0, guest, ent) == -1) {
2283+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2284+ strerror(errno));
2285+ return -1;
2286+ }
2287+ }
2288+ }
2289+
2290+ else /* detach */ {
2291+ struct vserver_fstab *i, *p = NULL;
2292+ for (i = guest->fstab; i; i = i->next) {
2293+ /* These are the fields we care about */
2294+ if (strcmp(ent->source, i->source) == 0 &&
2295+ strcmp(ent->target, i->target) == 0 &&
2296+ strcmp(ent->source_type, i->source_type) == 0)
2297+ break;
2298+ p = i;
2299+ }
2300+ if (i) {
2301+ if (p)
2302+ p->next = i->next;
2303+ else
2304+ guest->fstab = i->next;
2305+ if (vserverIsRunning(guest)) {
2306+ if (doMount(1, guest, ent) == -1) {
2307+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2308+ strerror(errno));
2309+ return -1;
2310+ }
2311+ }
2312+ freeFstab(i);
2313+ }
2314+ freeFstab(ent);
2315+ }
2316+ }
2317+ else {
2318+ vserverError(domain->conn, domain, NULL, VIR_ERR_XML_ERROR,
2319+ _("unknown device type"));
2320+ return -1;
2321+ }
2322+
2323+ /* Both fstab and interfaces need a lot of writing, so write the whole thing */
2324+ if (vserverWriteGuestToConfig(guest) == -1) {
2325+ vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED, guest->name);
2326+ return -1;
2327+ }
2328+
2329+ xmlFreeDoc(doc);
2330+
2331+ return 0;
2332+}
2333+
2334+static int
2335+vserverDomainAttachDevice(virDomainPtr domain, const char *xml)
2336+{
2337+ return vserverDomainHandleDevice(domain, xml, 1);
2338+}
2339+
2340+static int
2341+vserverDomainDetachDevice(virDomainPtr domain, const char *xml)
2342+{
2343+ return vserverDomainHandleDevice(domain, xml, 0);
2344+}
2345+
2346+static int
2347+vserverDomainGetAutostart(virDomainPtr domain, int *autostart)
2348+{
2349+ GET_DOMAIN(domain, -1);
2350+
2351+ *autostart = guest->autostart;
2352+ return 0;
2353+}
2354+
2355+static int
2356+vserverDomainSetAutostart(virDomainPtr domain, int autostart)
2357+{
2358+ GET_DOMAIN(domain, -1);
2359+
2360+ if (vserverWriteToConfig(guest, "apps/init/mark",
2361+ (autostart ? "default\n" : "\n")) == -1) {
2362+ vserverError(domain->conn, domain, NULL, VIR_ERR_WRITE_FAILED,
2363+ "apps/init/mark");
2364+ return -1;
2365+ }
2366+ guest->autostart = autostart;
2367+ return 0;
2368+}
2369+
2370+static const struct {
2371+ unsigned int id;
2372+ const char *field;
2373+ int type;
2374+} sched_fields[] = {
2375+ { VC_VXSM_FILL_RATE, "fill_rate1", VIR_DOMAIN_SCHED_FIELD_UINT },
2376+ { VC_VXSM_INTERVAL, "interval1", VIR_DOMAIN_SCHED_FIELD_UINT },
2377+ { VC_VXSM_FILL_RATE2, "fill_rate2", VIR_DOMAIN_SCHED_FIELD_UINT },
2378+ { VC_VXSM_INTERVAL2, "interval2", VIR_DOMAIN_SCHED_FIELD_UINT },
2379+ { VC_VXSM_TOKENS_MIN, "tokens_min", VIR_DOMAIN_SCHED_FIELD_UINT },
2380+ { VC_VXSM_TOKENS_MAX, "tokens_max", VIR_DOMAIN_SCHED_FIELD_UINT },
2381+ { VC_VXSM_PRIO_BIAS, "prio_bias", VIR_DOMAIN_SCHED_FIELD_INT },
2382+ { VC_VXSM_IDLE_TIME, "idle_time", VIR_DOMAIN_SCHED_FIELD_BOOLEAN },
2383+ { 0, NULL, 0 }
2384+};
2385+
2386+static char *
2387+vserverDomainGetSchedulerType(virDomainPtr domain, int *nparams)
2388+{
2389+ char *ret;
2390+ int i;
2391+ GET_DOMAIN(domain, NULL);
2392+
2393+ ret = strdup(guest->sched.set_mask & VC_VXSM_IDLE_TIME ? "fair" : "hard");
2394+ if (!ret) {
2395+ vserverError(domain->conn, domain, NULL, VIR_ERR_NO_MEMORY,
2396+ _("scheduler"));
2397+ return NULL;
2398+ }
2399+
2400+ *nparams = 0;
2401+ for (i = 0; sched_fields[i].field != NULL; i++) {
2402+ /* only returns fields which are set */
2403+ if (guest->sched.set_mask & sched_fields[i].id)
2404+ (*nparams)++;
2405+ }
2406+
2407+ return ret;
2408+}
2409+
2410+static int
2411+vserverDomainGetSchedulerParams(virDomainPtr domain,
2412+ virSchedParameterPtr params,
2413+ int *nparams)
2414+{
2415+ int i, j;
2416+ GET_DOMAIN(domain, -1);
2417+
2418+ for (i = 0, j = 0; sched_fields[i].field != NULL && i < *nparams; i++) {
2419+ /* skip unset fields */
2420+ if (!(guest->sched.set_mask & sched_fields[i].id))
2421+ continue;
2422+
2423+ params[j].type = sched_fields[i].type;
2424+ strncpy(params[j].field, sched_fields[i].field, sizeof(params[j].field) - 1);
2425+ switch (sched_fields[i].id) {
2426+ case VC_VXSM_FILL_RATE:
2427+ params[j].value.ui = guest->sched.fill_rate;
2428+ break;
2429+ case VC_VXSM_INTERVAL:
2430+ params[j].value.ui = guest->sched.interval;
2431+ break;
2432+ case VC_VXSM_FILL_RATE2:
2433+ params[j].value.ui = guest->sched.fill_rate2;
2434+ break;
2435+ case VC_VXSM_INTERVAL2:
2436+ params[j].value.ui = guest->sched.interval2;
2437+ break;
2438+ case VC_VXSM_TOKENS_MIN:
2439+ params[j].value.ui = guest->sched.tokens_min;
2440+ break;
2441+ case VC_VXSM_TOKENS_MAX:
2442+ params[j].value.ui = guest->sched.tokens_max;
2443+ break;
2444+ case VC_VXSM_PRIO_BIAS:
2445+ params[j].value.i = guest->sched.priority_bias;
2446+ break;
2447+ case VC_VXSM_IDLE_TIME:
2448+ params[j].value.b = guest->sched.set_mask & VC_VXSM_IDLE_TIME;
2449+ break;
2450+ }
2451+ j++;
2452+ }
2453+ *nparams = j;
2454+
2455+ return 0;
2456+}
2457+
2458+static int
2459+vserverDomainSetSchedulerParams(virDomainPtr domain,
2460+ virSchedParameterPtr params,
2461+ int nparams)
2462+{
2463+ int i, j, cret;
2464+ GET_DOMAIN(domain, -1);
2465+
2466+ for (i = 0; i < nparams; i++) {
2467+ for (j = 0; sched_fields[j].field != NULL; j++) {
2468+ if (STREQ(sched_fields[j].field, params[i].field))
2469+ break;
2470+ }
2471+ if (sched_fields[j].field == NULL) {
2472+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "field");
2473+ return -1;
2474+ }
2475+ if (sched_fields[j].type != params[i].type) {
2476+ vserverError(domain->conn, domain, NULL, VIR_ERR_INVALID_ARG, "type");
2477+ return -1;
2478+ }
2479+ switch (sched_fields[j].id) {
2480+ case VC_VXSM_FILL_RATE:
2481+ guest->sched.fill_rate = params[i].value.ui;
2482+ cret = vserverWriteToConfig(guest, "sched/fill-rate", "%u\n",
2483+ params[i].value.ui);
2484+ break;
2485+ case VC_VXSM_INTERVAL:
2486+ guest->sched.interval = params[i].value.ui;
2487+ cret = vserverWriteToConfig(guest, "sched/interval", "%u\n",
2488+ params[i].value.ui);
2489+ break;
2490+ case VC_VXSM_FILL_RATE2:
2491+ guest->sched.fill_rate2 = params[i].value.ui;
2492+ cret = vserverWriteToConfig(guest, "sched/fill-rate2", "%u\n",
2493+ params[i].value.ui);
2494+ break;
2495+ case VC_VXSM_INTERVAL2:
2496+ guest->sched.interval2 = params[i].value.ui;
2497+ cret = vserverWriteToConfig(guest, "sched/interval2", "%u\n",
2498+ params[i].value.ui);
2499+ break;
2500+ case VC_VXSM_TOKENS_MIN:
2501+ guest->sched.tokens_min = params[i].value.ui;
2502+ cret = vserverWriteToConfig(guest, "sched/tokens-min", "%u\n",
2503+ params[i].value.ui);
2504+ break;
2505+ case VC_VXSM_TOKENS_MAX:
2506+ guest->sched.tokens_max = params[i].value.ui;
2507+ cret = vserverWriteToConfig(guest, "sched/tokens-max", "%u\n",
2508+ params[i].value.ui);
2509+ break;
2510+ case VC_VXSM_PRIO_BIAS:
2511+ guest->sched.priority_bias = params[i].value.i;
2512+ cret = vserverWriteToConfig(guest, "sched/prio-bias", "%d\n",
2513+ params[i].value.i);
2514+ break;
2515+ case VC_VXSM_IDLE_TIME:
2516+ cret = vserverWriteToConfig(guest, "sched/idle-time", "%b",
2517+ params[i].value.b);
2518+ break;
2519+ default:
2520+ vserverError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
2521+ "Unknown scheduler parameter");
2522+ return -1;
2523+ }
2524+ if (cret == -1) {
2525+ vserverError(domain->conn, domain, NULL, VIR_ERR_SYSTEM_ERROR,
2526+ "vserverWriteToConfig");
2527+ return -1;
2528+ }
2529+ guest->sched.set_mask |= sched_fields[j].id;
2530+ }
2531+
2532+ return 0;
2533+}
2534+
2535+
2536+virDriver vserverDriver = {
2537+ VIR_DRV_VSERVER,
2538+ "Linux-VServer",
2539+ LIBVIR_VERSION_NUMBER,
2540+ vserverOpen,
2541+ vserverClose,
2542+ NULL, /* supports_feature */
2543+ vserverGetType,
2544+ vserverGetVersion,
2545+ vserverGetHostname,
2546+ vserverGetURI,
2547+ NULL, /* getMaxVcpus */
2548+ vserverNodeGetInfo,
2549+ NULL, /* getCapabilties */
2550+ vserverListDomains,
2551+ vserverNumOfDomains,
2552+ vserverDomainCreateLinux,
2553+ vserverDomainLookupByID,
2554+ vserverDomainLookupByUUID,
2555+ vserverDomainLookupByName,
2556+ vserverDomainSuspend,
2557+ vserverDomainResume,
2558+ vserverDomainShutdown,
2559+ vserverDomainReboot,
2560+ vserverDomainDestroy,
2561+ vserverDomainGetOSType,
2562+ vserverDomainGetMaxMemory,
2563+ vserverDomainSetMaxMemory,
2564+ NULL, /* domainSetMemory */
2565+ vserverDomainGetInfo,
2566+ NULL, /* domainSave */
2567+ NULL, /* domainRestore */
2568+ NULL, /* domainCoreDump */
2569+ NULL, /* domainSetVcpus */
2570+ NULL, /* domainPinVcpu */
2571+ NULL, /* domainGetVcpus */
2572+ NULL, /* domainGetMaxVcpus */
2573+ vserverDomainDumpXML,
2574+ vserverListDefinedDomains,
2575+ vserverNumOfDefinedDomains,
2576+ vserverDomainCreate,
2577+ vserverDomainDefineXML,
2578+ vserverDomainUndefine,
2579+ vserverDomainAttachDevice,
2580+ vserverDomainDetachDevice,
2581+ vserverDomainGetAutostart,
2582+ vserverDomainSetAutostart,
2583+ vserverDomainGetSchedulerType,
2584+ vserverDomainGetSchedulerParams,
2585+ vserverDomainSetSchedulerParams,
2586+ NULL, /* domainMigratePrepare */
2587+ NULL, /* domainMigratePerform */
2588+ NULL, /* domainMigrateFinish */
2589+ NULL, /* domainBlockStats */
2590+ NULL, /* domainInterfaceStats */
2591+ NULL, /* nodeGetCellsFreeMemory */
2592+ NULL, /* getFreeMemory */
2593+};
2594+
2595+int vserverRegister(void)
2596+{
2597+ if (virRegisterDriver(&vserverDriver) < 0)
2598+ return -1;
2599+ return 0;
2600+}
2601+
2602+#endif
eb319e62
ER
2603--- libvirt-0.4.0.orig/src/vserver/vserver_driver.h 1970-01-01 01:00:00.000000000 +0100
2604+++ libvirt-0.4.0.vserver/src/vserver/vserver_driver.h 2008-01-09 19:14:08.000000000 +0100
bd1fcfb7
ER
2605@@ -0,0 +1,137 @@
2606+/*
2607+ * Core driver for managing Linux-VServer guests
2608+ *
2609+ * Copyright (C) 2007 Daniel Hokka Zakrisson
2610+ *
2611+ * This library is free software; you can redistribute it and/or
2612+ * modify it under the terms of the GNU Lesser General Public
2613+ * License as published by the Free Software Foundation; either
2614+ * version 2.1 of the License, or (at your option) any later version.
2615+ *
2616+ * This library is distributed in the hope that it will be useful,
2617+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2618+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2619+ * Lesser General Public License for more details.
2620+ *
2621+ * You should have received a copy of the GNU Lesser General Public
2622+ * License along with this library; if not, write to the Free Software
2623+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2624+ *
2625+ * Author: Daniel Hokka Zakrisson <daniel hozac com>
2626+ */
2627+
2628+#ifdef WITH_VSERVER
2629+
2630+/* Kind of a hack */
2631+#ifdef IN_VSERVER
2632+#ifndef HAVE_XID_T
2633+typedef unsigned int xid_t;
2634+#endif
2635+#ifndef HAVE_NID_T
2636+typedef unsigned int nid_t;
2637+#endif
2638+#ifndef HAVE_TAG_T
2639+typedef unsigned int tag_t;
2640+#endif
2641+#include <vserver.h>
2642+
2643+#define VSERVER_NAME_MAX 64
2644+#define VSERVER_UTS_MAX 255
2645+
2646+enum vserver_initstyle {
2647+ VSERVER_INIT_NONE,
2648+ VSERVER_INIT_SYSV,
2649+ VSERVER_INIT_PLAIN,
2650+ VSERVER_INIT_GENTOO,
2651+ VSERVER_INIT_MINIT,
2652+};
2653+
2654+struct vserver_ip {
2655+ char interface[IFNAMSIZ+1];
2656+ struct vc_net_addr addr;
2657+ struct vserver_ip *next;
2658+};
2659+
2660+enum fstab_flags {
2661+ VSERVER_FSTAB_SHOW=1,
2662+ VSERVER_FSTAB_OUTPUT=2,
2663+};
2664+struct vserver_fstab {
2665+ char *source;
2666+ const char *source_type;
2667+ char *target;
2668+ char *fstype;
2669+ char *options;
2670+ char *rest;
2671+ int flags;
2672+ struct vserver_fstab *next;
2673+};
2674+
2675+struct vserver_guest {
2676+ xid_t xid;
2677+ char name[VSERVER_NAME_MAX];
2678+ unsigned char uuid[VIR_UUID_BUFLEN];
2679+ char *path;
2680+
2681+ struct {
2682+ char hostname[VSERVER_UTS_MAX];
2683+ char machine[VSERVER_UTS_MAX];
2684+ char release[VSERVER_UTS_MAX];
2685+ char version[VSERVER_UTS_MAX];
2686+ } uts;
2687+
2688+ struct vserver_ip *ips;
2689+
2690+ struct vc_set_sched sched;
2691+ unsigned long rss_hard;
2692+
2693+ char autostart;
2694+ enum vserver_initstyle initstyle;
2695+
2696+ int status;
2697+
2698+ struct vserver_fstab *fstab;
2699+
2700+ struct vserver_guest *next;
2701+};
2702+
2703+struct vserver_driver {
2704+ struct vserver_guest *guests;
2705+ xmlChar *uri;
2706+ unsigned int active_guests;
2707+ unsigned int inactive_guests;
2708+ unsigned int initialized : 1;
2709+};
2710+
2711+
2712+#define list_add_tail(list, elem) \
2713+ do { \
2714+ __typeof__(list) iter; \
2715+ if (list) { \
2716+ for (iter = list; iter->next; iter = iter->next) \
2717+ ; \
2718+ iter->next = elem; \
2719+ } \
2720+ else \
2721+ list = elem; \
2722+ } while (0)
2723+
2724+static inline int
2725+vserverIsRunning(struct vserver_guest *guest) {
2726+ if (guest->status == VIR_DOMAIN_RUNNING || guest->status == VIR_DOMAIN_PAUSED)
2727+ return 1;
2728+ else
2729+ return 0;
2730+}
2731+
2732+
2733+int vserverContextIsRunning(const char *path);
2734+int vserverRunCommand(int do_daemon, const char *cmd, ...);
2735+void vserverError(virConnectPtr con, virDomainPtr dom, virNetworkPtr net,
2736+ virErrorNumber error, const char *info);
2737+#endif
2738+
2739+
2740+extern int vserverRegister(void);
2741+
2742+#endif
This page took 0.370036 seconds and 4 git commands to generate.