mirror of https://gitee.com/openkylin/libvirt.git
Add an initial User Mode Linux Driver
This commit is contained in:
parent
6d04effac7
commit
714bef5b6a
17
ChangeLog
17
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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>
|
||||
<domain type='uml'>
|
||||
<name>demo</name>
|
||||
<uuid>b4433fc2-a22e-ffb3-0a3d-9c173b395800</uuid>
|
||||
<memory>500000</memory>
|
||||
<currentMemory>500000</currentMemory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64'>uml</type>
|
||||
<kernel>/home/berrange/linux-uml-2.6.26-x86_64</kernel>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
<source file='/home/berrange/FedoraCore6-AMD64-root_fs'/>
|
||||
<target dev='ubd0' bus='uml'/>
|
||||
</disk>
|
||||
<console type='pty'/>
|
||||
</devices>
|
||||
</domain>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue