Add an initial User Mode Linux Driver

This commit is contained in:
Daniel P. Berrange 2008-11-19 16:58:23 +00:00
parent 6d04effac7
commit 714bef5b6a
17 changed files with 2350 additions and 24 deletions

View File

@ -1,3 +1,20 @@
Wed Nov 19 16:51:00 GMT 2008 Daniel Berrange <berrange@redhat.com>
Add User Mode Linux driver
* src/uml_driver.c, src/uml_driver.h, src/uml_conf.c,
src/uml_conf.h: Core UML driver code
* src/domain_conf.c, src/domain_conf.h: Add UML disk
bus type. Fix paravirt console handling for non-HVM domains
* src/driver.h: Add UML driver number
* src/virterror.h: Add error code for UML driver
* src/qemu_conf.c: Add disk bus enum entry for UML
* src/Makefile.am: Build UML driver
* qemud/qemud.c: Initialize UML driver
* qemud/Makefile.am: Link to UML driver library
* docs/drvuml.html.in: Basic docs for the UML driver
* configure.in: Flag for enabling UML driver
* include/libvirt/virterror.h: Add constant for UML driver
Wed Nov 19 16:22:00 GMT 2008 Daniel Berrange <berrange@redhat.com>
Add virFreeCallback to event loop APIs.

View File

@ -149,6 +149,8 @@ AC_ARG_WITH([xen],
[ --with-xen add XEN support (on)],[],[with_xen=yes])
AC_ARG_WITH([qemu],
[ --with-qemu add QEMU/KVM support (on)],[],[with_qemu=yes])
AC_ARG_WITH([uml],
[ --with-uml add UML support (on)],[],[with_uml=yes])
AC_ARG_WITH([openvz],
[ --with-openvz add OpenVZ support (on)],[],[with_openvz=yes])
AC_ARG_WITH([lxc],
@ -253,6 +255,11 @@ if test "$with_qemu" = "yes" ; then
fi
AM_CONDITIONAL([WITH_QEMU], [test "$with_qemu" = "yes"])
if test "$with_uml" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_UML], 1, [whether UML driver is enabled])
fi
AM_CONDITIONAL([WITH_UML], [test "$with_uml" = "yes"])
if test "$with_test" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_TEST], 1, [whether Test driver is enabled])
fi
@ -1098,6 +1105,7 @@ AC_MSG_NOTICE([])
AC_MSG_NOTICE([ Xen: $with_xen])
AC_MSG_NOTICE([ Proxy: $with_xen_proxy])
AC_MSG_NOTICE([ QEMU: $with_qemu])
AC_MSG_NOTICE([ UML: $with_uml])
AC_MSG_NOTICE([ OpenVZ: $with_openvz])
AC_MSG_NOTICE([ LXC: $with_lxc])
AC_MSG_NOTICE([ Test: $with_test])

79
docs/drvuml.html.in Normal file
View File

@ -0,0 +1,79 @@
<html>
<body>
<h1>User Mode Linux driver</h1>
<p>
The UML driver for libvirt allows use and management of paravirtualized
guests built for User Mode Linux. UML requires no special support in
the host kernel, so can be used by any user of any linux system, provided
they have enough free RAM for their guest's needs, though there are
certain restrictions on network connectivity unless the adminstrator
has pre-created TAP devices.
</p>
<h2>Connections to UML driver</h2>
<p>
The libvirt UML driver follows the QEMU driver in providing two
types of connection. There is one privileged instance per host,
which runs as root. This is called the "system" instance, and allows
full use of all host resources. Then, there is a per-user unprivileged
"session", instance. This has more restricted capabilities, and may
require the host administrator to setup certain resources ahead of
time to allow full integration with the network. Example connection
URIs are
</p>
<pre>
uml:///system (local access, system instance)
uml:///session (local access, session instance)
uml://example.com/system (remote access, TLS/x509)
uml+tcp://example.com/system (remote access, SASl/Kerberos)
uml+ssh://root@example.com/system (remote access, SSH tunnelled)
</pre>
<h2>Example XML configuration</h2>
<p>
User mode Linux driver only supports directly kernel boot at
this time. A future driver enhancement may allow a paravirt
bootloader in a similar style to Xen's pygrub. For now though,
the UML kernel must be stored on the host and referenced
explicitly in the "os" element. Since UML is a paravirtualized
technology, the kernel "type" is set to "uml"
</p>
<p>
There is not yet support for networking in the driver, but
disks can be specified in the usual libvirt manner. The main
variation is the target device naming scheme "ubd0", and
bus type of "uml".
</p>
<p>
Once booted the primary console is connected toa PTY, and
thus accessible with "virsh console" or equivalent tools
</p>
<pre>
&lt;domain type='uml'&gt;
&lt;name&gt;demo&lt;/name&gt;
&lt;uuid&gt;b4433fc2-a22e-ffb3-0a3d-9c173b395800&lt;/uuid&gt;
&lt;memory&gt;500000&lt;/memory&gt;
&lt;currentMemory&gt;500000&lt;/currentMemory&gt;
&lt;vcpu&gt;1&lt;/vcpu&gt;
&lt;os&gt;
&lt;type arch='x86_64'&gt;uml&lt;/type&gt;
&lt;kernel&gt;/home/berrange/linux-uml-2.6.26-x86_64&lt;/kernel&gt;
&lt;/os&gt;
&lt;devices&gt;
&lt;disk type='file' device='disk'&gt;
&lt;source file='/home/berrange/FedoraCore6-AMD64-root_fs'/&gt;
&lt;target dev='ubd0' bus='uml'/&gt;
&lt;/disk&gt;
&lt;console type='pty'/&gt;
&lt;/devices&gt;
&lt;/domain&gt;
</pre>
</body>
</html>

View File

@ -124,6 +124,10 @@
<a href="drvopenvz.html">OpenVZ</a>
<span>Driver for the OpenVZ container technology</span>
</li>
<li>
<a href="drvuml.html">UML</a>
<span>Driver for the User Mode Linux technology</span>
</li>
<li>
<a href="storage.html">Storage</a>
<span>Driver for the storage management APIs</span>

View File

@ -58,6 +58,7 @@ typedef enum {
VIR_FROM_STORAGE, /* Error from storage driver */
VIR_FROM_NETWORK, /* Error from network config */
VIR_FROM_DOMAIN, /* Error from domain config */
VIR_FROM_UML, /* Error at the UML driver */
} virErrorDomain;

View File

@ -99,6 +99,10 @@ if WITH_LXC
libvirtd_LDADD += ../src/libvirt_driver_lxc.la
endif
if WITH_UML
libvirtd_LDADD += ../src/libvirt_driver_uml.la
endif
if WITH_STORAGE_DIR
libvirtd_LDADD += ../src/libvirt_driver_storage.la
endif

View File

@ -67,6 +67,9 @@
#ifdef WITH_LXC
#include "lxc_driver.h"
#endif
#ifdef WITH_UML
#include "uml_driver.h"
#endif
#ifdef WITH_NETWORK
#include "network_driver.h"
#endif
@ -751,6 +754,9 @@ static struct qemud_server *qemudInitialize(int sigread) {
#ifdef WITH_LXC
lxcRegister();
#endif
#ifdef WITH_UML
umlRegister();
#endif
#ifdef WITH_NETWORK
networkRegister();
#endif

View File

@ -117,6 +117,10 @@ QEMU_DRIVER_SOURCES = \
qemu_conf.c qemu_conf.h \
qemu_driver.c qemu_driver.h
UML_DRIVER_SOURCES = \
uml_conf.c uml_conf.h \
uml_driver.c uml_driver.h
NETWORK_DRIVER_SOURCES = \
network_driver.h network_driver.c
@ -210,6 +214,12 @@ noinst_LTLIBRARIES += libvirt_driver_lxc.la
libvirt_driver_lxc_la_SOURCES = $(LXC_DRIVER_SOURCES)
endif
if WITH_UML
noinst_LTLIBRARIES += libvirt_driver_uml.la
# Stateful, so linked to daemon instead
#libvirt_la_LIBADD += libvirt_driver_uml.la
libvirt_driver_uml_la_SOURCES = $(UML_DRIVER_SOURCES)
endif
if WITH_NETWORK
noinst_LTLIBRARIES += libvirt_driver_network.la
@ -247,6 +257,7 @@ EXTRA_DIST += \
$(XEN_DRIVER_SOURCES) \
$(QEMU_DRIVER_SOURCES) \
$(LXC_DRIVER_SOURCES) \
$(UML_DRIVER_SOURCES) \
$(OPENVZ_DRIVER_SOURCES) \
$(NETWORK_DRIVER_SOURCES) \
$(STORAGE_DRIVER_SOURCES) \

View File

@ -86,7 +86,8 @@ VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
"scsi",
"virtio",
"xen",
"usb")
"usb",
"uml")
VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
"mount",
@ -610,7 +611,8 @@ virDomainDiskDefParseXML(virConnectPtr conn,
!STRPREFIX((const char *)target, "hd") &&
!STRPREFIX((const char *)target, "sd") &&
!STRPREFIX((const char *)target, "vd") &&
!STRPREFIX((const char *)target, "xvd")) {
!STRPREFIX((const char *)target, "xvd") &&
!STRPREFIX((const char *)target, "ubd")) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("Invalid harddisk device name: %s"), target);
goto error;
@ -634,6 +636,8 @@ virDomainDiskDefParseXML(virConnectPtr conn,
def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
else if (STRPREFIX(target, "xvd"))
def->bus = VIR_DOMAIN_DISK_BUS_XEN;
else if (STRPREFIX(target, "ubd"))
def->bus = VIR_DOMAIN_DISK_BUS_UML;
else
def->bus = VIR_DOMAIN_DISK_BUS_IDE;
}
@ -1879,13 +1883,16 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
}
if (STREQ(def->os.type, "xen") ||
STREQ(def->os.type, "hvm")) {
STREQ(def->os.type, "hvm") ||
STREQ(def->os.type, "uml")) {
def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt);
def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt);
def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt);
def->os.root = virXPathString(conn, "string(./os/root[1])", ctxt);
def->os.loader = virXPathString(conn, "string(./os/loader[1])", ctxt);
}
if (STREQ(def->os.type, "hvm")) {
/* analysis of the boot devices */
if ((n = virXPathNodeSet(conn, "./os/boot", ctxt, &nodes)) < 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
@ -2016,32 +2023,30 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
}
VIR_FREE(nodes);
/*
* If no serial devices were listed, then look for console
* devices which is the legacy syntax for the same thing
*/
if (def->nserials == 0) {
if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
node);
if (!chr)
goto error;
if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
node);
if (!chr)
goto error;
chr->dstPort = 0;
/*
* For HVM console actually created a serial device
* while for non-HVM it was a parvirt console
*/
if (STREQ(def->os.type, "hvm")) {
chr->dstPort = 0;
/*
* For HVM console actually created a serial device
* while for non-HVM it was a parvirt console
*/
if (STREQ(def->os.type, "hvm")) {
if (def->nserials != 0) {
virDomainChrDefFree(chr);
} else {
if (VIR_ALLOC_N(def->serials, 1) < 0) {
virDomainChrDefFree(chr);
goto no_memory;
}
def->nserials = 1;
def->serials[0] = chr;
} else {
def->console = chr;
}
} else {
def->console = chr;
}
}

View File

@ -75,6 +75,7 @@ enum virDomainDiskBus {
VIR_DOMAIN_DISK_BUS_VIRTIO,
VIR_DOMAIN_DISK_BUS_XEN,
VIR_DOMAIN_DISK_BUS_USB,
VIR_DOMAIN_DISK_BUS_UML,
VIR_DOMAIN_DISK_BUS_LAST
};

View File

@ -17,7 +17,8 @@ typedef enum {
VIR_DRV_QEMU = 3,
VIR_DRV_REMOTE = 4,
VIR_DRV_OPENVZ = 5,
VIR_DRV_LXC = 6
VIR_DRV_LXC = 6,
VIR_DRV_UML = 7,
} virDrvNo;

View File

@ -56,7 +56,8 @@ VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
"scsi",
"virtio",
"xen",
"usb")
"usb",
"uml")
#define qemudLog(level, msg...) fprintf(stderr, msg)

404
src/uml_conf.c Normal file
View File

@ -0,0 +1,404 @@
/*
* uml_conf.c: UML driver configuration
*
* Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <dirent.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#if HAVE_NUMACTL
#include <numa.h>
#endif
#include "uml_conf.h"
#include "uuid.h"
#include "buf.h"
#include "conf.h"
#include "util.h"
#include "memory.h"
#include "verify.h"
#define umlLog(level, msg...) fprintf(stderr, msg)
#if HAVE_NUMACTL
#define MAX_CPUS 4096
#define MAX_CPUS_MASK_SIZE (sizeof(unsigned long))
#define MAX_CPUS_MASK_LEN (MAX_CPUS / MAX_CPUS_MASK_SIZE)
#define MAX_CPUS_MASK_BYTES (MAX_CPUS / 8)
#define MASK_CPU_ISSET(mask, cpu) \
(((mask)[((cpu) / MAX_CPUS_MASK_SIZE)] >> ((cpu) % MAX_CPUS_MASK_SIZE)) & 1)
static int
umlCapsInitNUMA(virCapsPtr caps)
{
int n, i;
unsigned long *mask = NULL;
int ncpus;
int *cpus = NULL;
int ret = -1;
if (numa_available() < 0)
return 0;
if (VIR_ALLOC_N(mask, MAX_CPUS_MASK_LEN) < 0)
goto cleanup;
for (n = 0 ; n <= numa_max_node() ; n++) {
if (numa_node_to_cpus(n, mask, MAX_CPUS_MASK_BYTES) < 0)
goto cleanup;
for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
if (MASK_CPU_ISSET(mask, i))
ncpus++;
if (VIR_ALLOC_N(cpus, ncpus) < 0)
goto cleanup;
for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
if (MASK_CPU_ISSET(mask, i))
cpus[ncpus++] = i;
if (virCapabilitiesAddHostNUMACell(caps,
n,
ncpus,
cpus) < 0)
goto cleanup;
VIR_FREE(cpus);
}
ret = 0;
cleanup:
VIR_FREE(cpus);
VIR_FREE(mask);
return ret;
}
#else
static int umlCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) { return 0; }
#endif
virCapsPtr umlCapsInit(void) {
struct utsname utsname;
virCapsPtr caps;
virCapsGuestPtr guest;
/* Really, this never fails - look at the man-page. */
uname (&utsname);
if ((caps = virCapabilitiesNew(utsname.machine,
0, 0)) == NULL)
goto no_memory;
if (umlCapsInitNUMA(caps) < 0)
goto no_memory;
if ((guest = virCapabilitiesAddGuest(caps,
"uml",
utsname.machine,
STREQ(utsname.machine, "x86_64") ? 64 : 32,
NULL,
NULL,
0,
NULL)) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestDomain(guest,
"uml",
NULL,
NULL,
0,
NULL) == NULL)
goto no_memory;
return caps;
no_memory:
virCapabilitiesFree(caps);
return NULL;
}
static char *
umlBuildCommandLineChr(virConnectPtr conn,
virDomainChrDefPtr def,
const char *dev)
{
char *ret;
switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_NULL:
if (asprintf(&ret, "%s%d=null", dev, def->dstPort) < 0) {
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL;
}
break;
case VIR_DOMAIN_CHR_TYPE_PTY:
if (asprintf(&ret, "%s%d=pts", dev, def->dstPort) < 0) {
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL;
}
break;
case VIR_DOMAIN_CHR_TYPE_DEV:
if (asprintf(&ret, "%s%d=tty:%s", dev, def->dstPort,
def->data.file.path) < 0) {
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL;
}
break;
case VIR_DOMAIN_CHR_TYPE_STDIO:
if (asprintf(&ret, "%s%d=fd:0,fd:1", dev, def->dstPort) < 0) {
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL;
}
break;
case VIR_DOMAIN_CHR_TYPE_TCP:
if (def->data.tcp.listen != 1) {
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("only TCP listen is supported for chr device"));
return NULL;
}
if (asprintf(&ret, "%s%d=port:%s", dev, def->dstPort,
def->data.tcp.service) < 0) {
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL;
}
break;
case VIR_DOMAIN_CHR_TYPE_FILE:
case VIR_DOMAIN_CHR_TYPE_PIPE:
/* XXX could open the file/pipe & just pass the FDs */
case VIR_DOMAIN_CHR_TYPE_VC:
case VIR_DOMAIN_CHR_TYPE_UDP:
case VIR_DOMAIN_CHR_TYPE_UNIX:
default:
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unsupported chr device type %d"), def->type);
break;
}
return ret;
}
/*
* Constructs a argv suitable for launching uml with config defined
* for a given virtual machine.
*/
int umlBuildCommandLine(virConnectPtr conn,
struct uml_driver *driver ATTRIBUTE_UNUSED,
virDomainObjPtr vm,
const char ***retargv,
const char ***retenv,
int **tapfds,
int *ntapfds) {
int i, j;
char memory[50];
struct utsname ut;
int qargc = 0, qarga = 0;
const char **qargv = NULL;
int qenvc = 0, qenva = 0;
const char **qenv = NULL;
uname(&ut);
#define ADD_ARG_SPACE \
do { \
if (qargc == qarga) { \
qarga += 10; \
if (VIR_REALLOC_N(qargv, qarga) < 0) \
goto no_memory; \
} \
} while (0)
#define ADD_ARG(thisarg) \
do { \
ADD_ARG_SPACE; \
qargv[qargc++] = thisarg; \
} while (0)
#define ADD_ARG_LIT(thisarg) \
do { \
ADD_ARG_SPACE; \
if ((qargv[qargc++] = strdup(thisarg)) == NULL) \
goto no_memory; \
} while (0)
#define ADD_ARG_PAIR(key,val) \
do { \
char *arg; \
ADD_ARG_SPACE; \
if (asprintf(&arg, "%s=%s", key, val) < 0) \
goto no_memory; \
qargv[qargc++] = arg; \
} while (0)
#define ADD_ENV_SPACE \
do { \
if (qenvc == qenva) { \
qenva += 10; \
if (VIR_REALLOC_N(qenv, qenva) < 0) \
goto no_memory; \
} \
} while (0)
#define ADD_ENV(thisarg) \
do { \
ADD_ENV_SPACE; \
qenv[qenvc++] = thisarg; \
} while (0)
#define ADD_ENV_LIT(thisarg) \
do { \
ADD_ENV_SPACE; \
if ((qenv[qenvc++] = strdup(thisarg)) == NULL) \
goto no_memory; \
} while (0)
#define ADD_ENV_COPY(envname) \
do { \
char *val = getenv(envname); \
char *envval; \
ADD_ENV_SPACE; \
if (val != NULL) { \
if (asprintf(&envval, "%s=%s", envname, val) < 0) \
goto no_memory; \
qenv[qenvc++] = envval; \
} \
} while (0)
snprintf(memory, sizeof(memory), "%luK", vm->def->memory);
ADD_ENV_LIT("LC_ALL=C");
ADD_ENV_COPY("LD_PRELOAD");
ADD_ENV_COPY("LD_LIBRARY_PATH");
ADD_ENV_COPY("PATH");
ADD_ENV_COPY("HOME");
ADD_ENV_COPY("USER");
ADD_ENV_COPY("LOGNAME");
ADD_ENV_COPY("TMPDIR");
ADD_ARG_LIT(vm->def->os.kernel);
//ADD_ARG_PAIR("con0", "fd:0,fd:1");
ADD_ARG_PAIR("mem", memory);
ADD_ARG_PAIR("umid", vm->def->name);
if (vm->def->os.root)
ADD_ARG_PAIR("root", vm->def->os.root);
for (i = 0 ; i < vm->def->ndisks ; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
if (!STRPREFIX(disk->dst, "ubd")) {
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unsupported disk type '%s'"), disk->dst);
goto error;
}
ADD_ARG_PAIR(disk->dst, disk->src);
}
for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
char *ret;
if (i == 0 && vm->def->console)
ret = umlBuildCommandLineChr(conn, vm->def->console, "con");
else
if (asprintf(&ret, "con%d=none", i) < 0)
goto no_memory;
ADD_ARG(ret);
}
for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
virDomainChrDefPtr chr = NULL;
char *ret;
for (j = 0 ; j < vm->def->nserials ; j++)
if (vm->def->serials[j]->dstPort == i)
chr = vm->def->serials[j];
if (chr)
ret = umlBuildCommandLineChr(conn, chr, "ssl");
else
if (asprintf(&ret, "ssl%d=none", i) < 0)
goto no_memory;
ADD_ARG(ret);
}
ADD_ARG(NULL);
ADD_ENV(NULL);
*retargv = qargv;
*retenv = qenv;
return 0;
no_memory:
umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for argv string"));
error:
if (tapfds &&
*tapfds) {
for (i = 0; i < *ntapfds; i++)
close((*tapfds)[i]);
VIR_FREE(*tapfds);
*ntapfds = 0;
}
if (qargv) {
for (i = 0 ; i < qargc ; i++)
VIR_FREE((qargv)[i]);
VIR_FREE(qargv);
}
if (qenv) {
for (i = 0 ; i < qenvc ; i++)
VIR_FREE((qenv)[i]);
VIR_FREE(qenv);
}
return -1;
#undef ADD_ARG
#undef ADD_ARG_LIT
#undef ADD_ARG_SPACE
#undef ADD_USBDISK
#undef ADD_ENV
#undef ADD_ENV_COPY
#undef ADD_ENV_LIT
#undef ADD_ENV_SPACE
}

74
src/uml_conf.h Normal file
View File

@ -0,0 +1,74 @@
/*
* config.h: VM configuration management
*
* Copyright (C) 2006, 2007 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __UML_CONF_H
#define __UML_CONF_H
#include "internal.h"
#include "bridge.h"
#include "capabilities.h"
#include "network_conf.h"
#include "domain_conf.h"
#include "virterror_internal.h"
#define umlDebug(fmt, ...) do {} while(0)
#define UML_CPUMASK_LEN CPU_SETSIZE
#define UML_MAX_CHAR_DEVICE 16
/* Main driver state */
struct uml_driver {
unsigned int umlVersion;
int nextvmid;
virDomainObjList domains;
brControl *brctl;
char *configDir;
char *autostartDir;
char *logDir;
char *monitorDir;
int inotifyFD;
int inotifyWatch;
virCapsPtr caps;
};
#define umlReportError(conn, dom, net, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_UML, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
virCapsPtr umlCapsInit (void);
int umlBuildCommandLine (virConnectPtr conn,
struct uml_driver *driver,
virDomainObjPtr dom,
const char ***retargv,
const char ***retenv,
int **tapfds,
int *ntapfds);
#endif /* __UML_CONF_H */

1676
src/uml_driver.c Normal file

File diff suppressed because it is too large Load Diff

32
src/uml_driver.h Normal file
View File

@ -0,0 +1,32 @@
/*
* uml_driver.h: user mode Linux driver
*
* Copyright (C) 2006, 2007 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef UML_DRIVER_H
#define UML_DRIVER_H
#include "internal.h"
int umlRegister(void);
#endif /* UML_DRIVER_H */

View File

@ -310,7 +310,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_DOMAIN:
dom = "Domain Config ";
break;
case VIR_FROM_UML:
dom = "UML ";
break;
}
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
domain = err->dom->name;