2007-02-14 01:40:09 +00:00
|
|
|
/*
|
|
|
|
* config.c: VM configuration management
|
|
|
|
*
|
2008-02-07 16:49:29 +00:00
|
|
|
* Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
|
2007-02-14 01:40:09 +00:00
|
|
|
* 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>
|
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-11-26 11:50:16 +00:00
|
|
|
|
|
|
|
#ifdef WITH_QEMU
|
2007-02-14 15:42:55 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2007-02-23 17:15:18 +00:00
|
|
|
#include <sys/wait.h>
|
2007-04-10 23:17:46 +00:00
|
|
|
#include <arpa/inet.h>
|
2007-04-16 13:14:28 +00:00
|
|
|
#include <sys/utsname.h>
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
#include <libxml/uri.h>
|
|
|
|
|
Wed Dec 5 13:48:00 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
* python/libvir.c, python/libvirt_wrap.h, qemud/qemud.c,
qemud/remote.c, src/internal.h, src/openvz_conf.c,
src/openvz_driver.c, src/proxy_internal.h, src/qemu_conf.c,
src/qemu_driver.c, src/remote_internal.h, src/test.h, src/util.c,
src/xen_unified.c, src/xen_unified.h, tests/nodeinfotest.c,
tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c, tests/reconnect.c,
tests/sexpr2xmltest.c, tests/virshtest.c, tests/xencapstest.c,
tests/xmconfigtest.c, tests/xml2sexprtest.c:
Change #include <> to #include "" for local includes.
Removed many includes from src/internal.h and put them in
the C files which actually use them.
Removed <ansidecl.h> - unused.
Added a comment around __func__.
Removed a clashing redefinition of VERSION symbol.
All limits (PATH_MAX etc) now done in src/internal.h, so we
don't need to include those headers in other files.
2007-12-05 13:56:22 +00:00
|
|
|
#include "libvirt/virterror.h"
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-06-27 00:12:29 +00:00
|
|
|
#include "qemu_conf.h"
|
2007-02-26 15:32:27 +00:00
|
|
|
#include "uuid.h"
|
2007-06-27 00:12:29 +00:00
|
|
|
#include "buf.h"
|
2007-10-12 16:05:44 +00:00
|
|
|
#include "conf.h"
|
2007-12-03 14:30:46 +00:00
|
|
|
#include "util.h"
|
2007-06-26 22:13:21 +00:00
|
|
|
|
2007-06-26 23:48:46 +00:00
|
|
|
#define qemudLog(level, msg...) fprintf(stderr, msg)
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
void qemudReportError(virConnectPtr conn,
|
|
|
|
virDomainPtr dom,
|
|
|
|
virNetworkPtr net,
|
|
|
|
int code, const char *fmt, ...) {
|
|
|
|
va_list args;
|
|
|
|
char errorMessage[QEMUD_MAX_ERROR_LEN];
|
2008-02-28 11:17:49 +00:00
|
|
|
const char *virerr;
|
2007-06-26 22:13:21 +00:00
|
|
|
|
|
|
|
if (fmt) {
|
|
|
|
va_start(args, fmt);
|
|
|
|
vsnprintf(errorMessage, QEMUD_MAX_ERROR_LEN-1, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
} else {
|
|
|
|
errorMessage[0] = '\0';
|
|
|
|
}
|
2008-02-28 11:17:49 +00:00
|
|
|
|
2008-03-03 18:11:16 +00:00
|
|
|
virerr = __virErrorMsg(code, (errorMessage[0] ? errorMessage : NULL));
|
2007-06-26 22:13:21 +00:00
|
|
|
__virRaiseError(conn, dom, net, VIR_FROM_QEMU, code, VIR_ERR_ERROR,
|
2008-02-28 11:17:49 +00:00
|
|
|
virerr, errorMessage, NULL, -1, -1, virerr, errorMessage);
|
2007-06-26 22:13:21 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 16:05:44 +00:00
|
|
|
int qemudLoadDriverConfig(struct qemud_driver *driver,
|
|
|
|
const char *filename) {
|
|
|
|
virConfPtr conf;
|
|
|
|
virConfValuePtr p;
|
|
|
|
|
|
|
|
/* Setup 2 critical defaults */
|
|
|
|
strcpy(driver->vncListen, "127.0.0.1");
|
|
|
|
if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
|
|
|
|
"vncTLSx509certdir");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Just check the file is readable before opening it, otherwise
|
|
|
|
* libvirt emits an error.
|
|
|
|
*/
|
|
|
|
if (access (filename, R_OK) == -1) return 0;
|
|
|
|
|
|
|
|
conf = virConfReadFile (filename);
|
|
|
|
if (!conf) return 0;
|
|
|
|
|
|
|
|
|
|
|
|
#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"remoteReadConfigFile: %s: %s: expected type " #typ "\n", \
|
|
|
|
filename, (name)); \
|
|
|
|
virConfFree(conf); \
|
|
|
|
return -1; \
|
|
|
|
}
|
|
|
|
|
|
|
|
p = virConfGetValue (conf, "vnc_tls");
|
|
|
|
CHECK_TYPE ("vnc_tls", VIR_CONF_LONG);
|
|
|
|
if (p) driver->vncTLS = p->l;
|
|
|
|
|
|
|
|
p = virConfGetValue (conf, "vnc_tls_x509_verify");
|
|
|
|
CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG);
|
|
|
|
if (p) driver->vncTLSx509verify = p->l;
|
|
|
|
|
|
|
|
p = virConfGetValue (conf, "vnc_tls_x509_cert_dir");
|
|
|
|
CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING);
|
|
|
|
if (p && p->str) {
|
|
|
|
free(driver->vncTLSx509certdir);
|
|
|
|
if (!(driver->vncTLSx509certdir = strdup(p->str))) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
|
|
|
|
"vncTLSx509certdir");
|
|
|
|
virConfFree(conf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p = virConfGetValue (conf, "vnc_listen");
|
|
|
|
CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
|
|
|
|
if (p && p->str) {
|
|
|
|
strncpy(driver->vncListen, p->str, sizeof(driver->vncListen));
|
|
|
|
driver->vncListen[sizeof(driver->vncListen)-1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
virConfFree (conf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-26 22:42:47 +00:00
|
|
|
struct qemud_vm *qemudFindVMByID(const struct qemud_driver *driver, int id) {
|
|
|
|
struct qemud_vm *vm = driver->vms;
|
|
|
|
|
|
|
|
while (vm) {
|
|
|
|
if (qemudIsActiveVM(vm) && vm->id == id)
|
|
|
|
return vm;
|
|
|
|
vm = vm->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_vm *qemudFindVMByUUID(const struct qemud_driver *driver,
|
|
|
|
const unsigned char *uuid) {
|
|
|
|
struct qemud_vm *vm = driver->vms;
|
|
|
|
|
|
|
|
while (vm) {
|
2007-08-09 20:19:12 +00:00
|
|
|
if (!memcmp(vm->def->uuid, uuid, VIR_UUID_BUFLEN))
|
2007-06-26 22:42:47 +00:00
|
|
|
return vm;
|
|
|
|
vm = vm->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_vm *qemudFindVMByName(const struct qemud_driver *driver,
|
|
|
|
const char *name) {
|
|
|
|
struct qemud_vm *vm = driver->vms;
|
|
|
|
|
|
|
|
while (vm) {
|
|
|
|
if (!strcmp(vm->def->name, name))
|
|
|
|
return vm;
|
|
|
|
vm = vm->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver,
|
|
|
|
const unsigned char *uuid) {
|
|
|
|
struct qemud_network *network = driver->networks;
|
|
|
|
|
|
|
|
while (network) {
|
2007-08-09 20:19:12 +00:00
|
|
|
if (!memcmp(network->def->uuid, uuid, VIR_UUID_BUFLEN))
|
2007-06-26 22:42:47 +00:00
|
|
|
return network;
|
|
|
|
network = network->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver,
|
|
|
|
const char *name) {
|
|
|
|
struct qemud_network *network = driver->networks;
|
|
|
|
|
|
|
|
while (network) {
|
|
|
|
if (!strcmp(network->def->name, name))
|
|
|
|
return network;
|
|
|
|
network = network->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
/* Free all memory associated with a struct qemud_vm object */
|
|
|
|
void qemudFreeVMDef(struct qemud_vm_def *def) {
|
|
|
|
struct qemud_vm_disk_def *disk = def->disks;
|
|
|
|
struct qemud_vm_net_def *net = def->nets;
|
2007-07-31 14:27:12 +00:00
|
|
|
struct qemud_vm_input_def *input = def->inputs;
|
2007-02-14 17:05:55 +00:00
|
|
|
|
|
|
|
while (disk) {
|
|
|
|
struct qemud_vm_disk_def *prev = disk;
|
|
|
|
disk = disk->next;
|
|
|
|
free(prev);
|
|
|
|
}
|
|
|
|
while (net) {
|
|
|
|
struct qemud_vm_net_def *prev = net;
|
|
|
|
net = net->next;
|
|
|
|
free(prev);
|
|
|
|
}
|
2007-07-31 14:27:12 +00:00
|
|
|
while (input) {
|
|
|
|
struct qemud_vm_input_def *prev = input;
|
|
|
|
input = input->next;
|
|
|
|
free(prev);
|
|
|
|
}
|
2008-01-15 15:18:33 +00:00
|
|
|
xmlFree(def->keymap);
|
2007-02-15 15:52:28 +00:00
|
|
|
free(def);
|
2007-02-14 17:05:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void qemudFreeVM(struct qemud_vm *vm) {
|
|
|
|
qemudFreeVMDef(vm->def);
|
|
|
|
if (vm->newDef)
|
|
|
|
qemudFreeVMDef(vm->newDef);
|
|
|
|
free(vm);
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-02-14 15:53:14 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
/* The list of possible machine types for various architectures,
|
|
|
|
as supported by QEMU - taken from 'qemu -M ?' for each arch */
|
2008-02-27 04:35:08 +00:00
|
|
|
static const char *const arch_info_hvm_x86_machines[] = {
|
|
|
|
"pc", "isapc"
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
2008-02-27 04:35:08 +00:00
|
|
|
static const char *const arch_info_hvm_mips_machines[] = {
|
|
|
|
"mips"
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
2008-02-27 04:35:08 +00:00
|
|
|
static const char *const arch_info_hvm_sparc_machines[] = {
|
|
|
|
"sun4m"
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
2008-02-27 04:35:08 +00:00
|
|
|
static const char *const arch_info_hvm_ppc_machines[] = {
|
|
|
|
"g3bw", "mac99", "prep"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *const arch_info_xen_x86_machines[] = {
|
|
|
|
"xenner"
|
|
|
|
};
|
|
|
|
|
|
|
|
struct qemu_feature_flags {
|
|
|
|
const char *name;
|
|
|
|
const int default_on;
|
|
|
|
const int toggle;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct qemu_arch_info {
|
|
|
|
const char *arch;
|
|
|
|
int wordsize;
|
|
|
|
const char *const *machines;
|
|
|
|
int nmachines;
|
|
|
|
const char *binary;
|
|
|
|
const struct qemu_feature_flags *flags;
|
|
|
|
int nflags;
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
|
|
|
|
2007-07-30 09:59:05 +00:00
|
|
|
/* Feature flags for the architecture info */
|
2008-01-14 14:05:25 +00:00
|
|
|
static const struct qemu_feature_flags const arch_info_i686_flags [] = {
|
2008-02-27 04:35:08 +00:00
|
|
|
{ "pae", 1, 0 },
|
|
|
|
{ "nonpae", 1, 0 },
|
2007-07-30 09:59:05 +00:00
|
|
|
{ "acpi", 1, 1 },
|
|
|
|
{ "apic", 1, 0 },
|
|
|
|
};
|
|
|
|
|
2008-01-14 14:05:25 +00:00
|
|
|
static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
|
2007-07-30 09:59:05 +00:00
|
|
|
{ "acpi", 1, 1 },
|
|
|
|
{ "apic", 1, 0 },
|
|
|
|
};
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
/* The archicture tables for supported QEMU archs */
|
2008-02-27 04:35:08 +00:00
|
|
|
static const struct qemu_arch_info const arch_info_hvm[] = {
|
|
|
|
{ "i686", 32, arch_info_hvm_x86_machines, 2,
|
|
|
|
"/usr/bin/qemu", arch_info_i686_flags, 4 },
|
|
|
|
{ "x86_64", 64, arch_info_hvm_x86_machines, 2,
|
|
|
|
"/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 },
|
|
|
|
{ "mips", 32, arch_info_hvm_mips_machines, 1,
|
|
|
|
"/usr/bin/qemu-system-mips", NULL, 0 },
|
|
|
|
{ "mipsel", 32, arch_info_hvm_mips_machines, 1,
|
|
|
|
"/usr/bin/qemu-system-mipsel", NULL, 0 },
|
|
|
|
{ "sparc", 32, arch_info_hvm_sparc_machines, 1,
|
|
|
|
"/usr/bin/qemu-system-sparc", NULL, 0 },
|
|
|
|
{ "ppc", 32, arch_info_hvm_ppc_machines, 3,
|
|
|
|
"/usr/bin/qemu-system-ppc", NULL, 0 },
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
static const struct qemu_arch_info const arch_info_xen[] = {
|
|
|
|
{ "i686", 32, arch_info_xen_x86_machines, 1,
|
|
|
|
"/usr/bin/xenner", arch_info_i686_flags, 4 },
|
|
|
|
{ "x86_64", 64, arch_info_xen_x86_machines, 1,
|
|
|
|
"/usr/bin/xenner", arch_info_x86_64_flags, 2 },
|
|
|
|
};
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
static int
|
|
|
|
qemudCapsInitGuest(virCapsPtr caps,
|
|
|
|
const char *hostmachine,
|
|
|
|
const struct qemu_arch_info *info,
|
|
|
|
int hvm) {
|
|
|
|
virCapsGuestPtr guest;
|
2007-02-14 01:40:09 +00:00
|
|
|
int i;
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps,
|
|
|
|
hvm ? "hvm" : "xen",
|
|
|
|
info->arch,
|
|
|
|
info->wordsize,
|
|
|
|
info->binary,
|
|
|
|
NULL,
|
|
|
|
info->nmachines,
|
|
|
|
info->machines)) == NULL)
|
|
|
|
return -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
if (hvm) {
|
|
|
|
/* Check for existance of base emulator */
|
|
|
|
if (access(info->binary, X_OK) == 0 &&
|
|
|
|
virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"qemu",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
return -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
/* If guest & host match, then we can accelerate */
|
|
|
|
if (STREQ(info->arch, hostmachine)) {
|
|
|
|
if (access("/dev/kqemu", F_OK) == 0 &&
|
|
|
|
virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"kqemu",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (access("/dev/kvm", F_OK) == 0 &&
|
|
|
|
virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"kvm",
|
|
|
|
"/usr/bin/qemu-kvm",
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"kvm",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
if (info->nflags) {
|
|
|
|
for (i = 0 ; i < info->nflags ; i++) {
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest,
|
|
|
|
info->flags[i].name,
|
|
|
|
info->flags[i].default_on,
|
|
|
|
info->flags[i].toggle) == NULL)
|
|
|
|
return -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
return 0;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
virCapsPtr qemudCapsInit(void) {
|
|
|
|
struct utsname utsname;
|
|
|
|
virCapsPtr caps;
|
|
|
|
int i;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
/* Really, this never fails - look at the man-page. */
|
|
|
|
uname (&utsname);
|
|
|
|
|
|
|
|
if ((caps = virCapabilitiesNew(utsname.machine,
|
|
|
|
0, 0)) == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; i++)
|
|
|
|
if (qemudCapsInitGuest(caps,
|
|
|
|
utsname.machine,
|
|
|
|
&arch_info_hvm[i], 1) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (access("/usr/bin/xenner", X_OK) == 0 &&
|
|
|
|
access("/dev/kvm", F_OK) == 0) {
|
|
|
|
for (i = 0 ; i < (sizeof(arch_info_xen)/sizeof(arch_info_xen[0])) ; i++)
|
|
|
|
/* Allow Xen 32-on-32, 32-on-64 and 64-on-64 */
|
|
|
|
if (STREQ(arch_info_xen[i].arch, utsname.machine) ||
|
|
|
|
(STREQ(utsname.machine, "x86_64") &&
|
|
|
|
STREQ(arch_info_xen[i].arch, "i686"))) {
|
|
|
|
if (qemudCapsInitGuest(caps,
|
|
|
|
utsname.machine,
|
|
|
|
&arch_info_xen[i], 0) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
return caps;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virCapabilitiesFree(caps);
|
|
|
|
return NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 17:15:18 +00:00
|
|
|
|
|
|
|
static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
|
|
|
|
pid_t child;
|
|
|
|
int newstdout[2];
|
|
|
|
|
|
|
|
*flags = 0;
|
|
|
|
*version = 0;
|
|
|
|
|
|
|
|
if (pipe(newstdout) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((child = fork()) < 0) {
|
|
|
|
close(newstdout[0]);
|
|
|
|
close(newstdout[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child == 0) { /* Kid */
|
|
|
|
if (close(STDIN_FILENO) < 0)
|
|
|
|
goto cleanup1;
|
|
|
|
if (close(STDERR_FILENO) < 0)
|
|
|
|
goto cleanup1;
|
|
|
|
if (close(newstdout[0]) < 0)
|
|
|
|
goto cleanup1;
|
|
|
|
if (dup2(newstdout[1], STDOUT_FILENO) < 0)
|
|
|
|
goto cleanup1;
|
|
|
|
|
|
|
|
/* Just in case QEMU is translated someday.. */
|
|
|
|
setenv("LANG", "C", 1);
|
|
|
|
execl(qemu, qemu, (char*)NULL);
|
|
|
|
|
|
|
|
cleanup1:
|
|
|
|
_exit(-1); /* Just in case */
|
|
|
|
} else { /* Parent */
|
2007-05-03 16:10:40 +00:00
|
|
|
char help[8192]; /* Ought to be enough to hold QEMU help screen */
|
2007-05-14 15:41:57 +00:00
|
|
|
int got = 0, ret = -1;
|
2007-02-23 17:15:18 +00:00
|
|
|
int major, minor, micro;
|
|
|
|
|
|
|
|
if (close(newstdout[1]) < 0)
|
|
|
|
goto cleanup2;
|
|
|
|
|
2007-05-03 16:10:40 +00:00
|
|
|
while (got < (sizeof(help)-1)) {
|
|
|
|
int len;
|
|
|
|
if ((len = read(newstdout[0], help+got, sizeof(help)-got-1)) <= 0) {
|
|
|
|
if (!len)
|
|
|
|
break;
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
goto cleanup2;
|
|
|
|
}
|
|
|
|
got += len;
|
2007-02-23 17:15:18 +00:00
|
|
|
}
|
|
|
|
help[got] = '\0';
|
|
|
|
|
|
|
|
if (sscanf(help, "QEMU PC emulator version %d.%d.%d", &major,&minor, µ) != 3) {
|
|
|
|
goto cleanup2;
|
|
|
|
}
|
|
|
|
|
|
|
|
*version = (major * 1000 * 1000) + (minor * 1000) + micro;
|
|
|
|
if (strstr(help, "-no-kqemu"))
|
|
|
|
*flags |= QEMUD_CMD_FLAG_KQEMU;
|
2007-05-03 16:10:40 +00:00
|
|
|
if (strstr(help, "-no-reboot"))
|
|
|
|
*flags |= QEMUD_CMD_FLAG_NO_REBOOT;
|
2007-02-23 17:15:18 +00:00
|
|
|
if (*version >= 9000)
|
|
|
|
*flags |= QEMUD_CMD_FLAG_VNC_COLON;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d",
|
|
|
|
major, minor, micro, *version, *flags);
|
|
|
|
|
|
|
|
cleanup2:
|
|
|
|
if (close(newstdout[0]) < 0)
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
rewait:
|
|
|
|
if (waitpid(child, &got, 0) != child) {
|
|
|
|
if (errno == EINTR) {
|
|
|
|
goto rewait;
|
|
|
|
}
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_ERR,
|
|
|
|
_("Unexpected exit status from qemu %d pid %lu"),
|
|
|
|
got, (unsigned long)child);
|
2007-02-23 17:15:18 +00:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
/* Check & log unexpected exit status, but don't fail,
|
|
|
|
* as there's really no need to throw an error if we did
|
|
|
|
* actually read a valid version number above */
|
|
|
|
if (WEXITSTATUS(got) != 1) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN,
|
|
|
|
_("Unexpected exit status '%d', qemu probably failed"),
|
|
|
|
got);
|
2007-02-23 17:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
int qemudExtractVersion(virConnectPtr conn,
|
2008-02-27 04:35:08 +00:00
|
|
|
struct qemud_driver *driver) {
|
|
|
|
const char *binary;
|
2007-04-16 13:14:28 +00:00
|
|
|
struct stat sb;
|
2007-09-21 21:20:32 +00:00
|
|
|
int ignored;
|
2007-02-23 17:15:18 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if (driver->qemuVersion > 0)
|
2007-02-23 17:15:18 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-02-27 04:35:08 +00:00
|
|
|
if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
|
|
|
|
"hvm",
|
|
|
|
"i686",
|
|
|
|
"qemu")) == NULL)
|
2007-02-23 17:15:18 +00:00
|
|
|
return -1;
|
|
|
|
|
2007-04-16 13:14:28 +00:00
|
|
|
if (stat(binary, &sb) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-04-16 13:14:28 +00:00
|
|
|
"Cannot find QEMU binary %s: %s", binary,
|
|
|
|
strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-09-21 21:20:32 +00:00
|
|
|
if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
|
2007-02-23 17:15:18 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
/* Parse the XML definition for a disk
|
|
|
|
* @param disk pre-allocated & zero'd disk record
|
|
|
|
* @param node XML nodeset to parse for disk definition
|
|
|
|
* @return 0 on success, -1 on failure
|
|
|
|
*/
|
|
|
|
static int qemudParseDiskXML(virConnectPtr conn,
|
|
|
|
struct qemud_vm_disk_def *disk,
|
|
|
|
xmlNodePtr node) {
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlNodePtr cur;
|
|
|
|
xmlChar *device = NULL;
|
|
|
|
xmlChar *source = NULL;
|
|
|
|
xmlChar *target = NULL;
|
|
|
|
xmlChar *type = NULL;
|
|
|
|
int typ = 0;
|
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (type != NULL) {
|
|
|
|
if (xmlStrEqual(type, BAD_CAST "file"))
|
|
|
|
typ = QEMUD_DISK_FILE;
|
|
|
|
else if (xmlStrEqual(type, BAD_CAST "block"))
|
|
|
|
typ = QEMUD_DISK_BLOCK;
|
|
|
|
else {
|
|
|
|
typ = QEMUD_DISK_FILE;
|
|
|
|
}
|
|
|
|
xmlFree(type);
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
device = xmlGetProp(node, BAD_CAST "device");
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
|
|
|
if ((source == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (typ == QEMUD_DISK_FILE)
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "file");
|
|
|
|
else
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "dev");
|
|
|
|
} else if ((target == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
|
|
|
|
target = xmlGetProp(cur, BAD_CAST "dev");
|
|
|
|
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
|
|
|
|
disk->readonly = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source == NULL) {
|
2008-03-13 09:17:45 +00:00
|
|
|
/* There is a case without the source
|
|
|
|
* to the CD-ROM device
|
|
|
|
*/
|
|
|
|
if (!device || STRNEQ((const char *) device, "cdrom")) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SOURCE,
|
|
|
|
target ? "%s" : NULL, target);
|
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-03-13 09:17:45 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (target == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_TARGET, source ? "%s" : NULL, source);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (device &&
|
|
|
|
!strcmp((const char *)device, "floppy") &&
|
|
|
|
strcmp((const char *)target, "fda") &&
|
|
|
|
strcmp((const char *)target, "fdb")) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Invalid floppy device name: %s", target);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (device &&
|
|
|
|
!strcmp((const char *)device, "cdrom") &&
|
|
|
|
strcmp((const char *)target, "hdc")) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Invalid cdrom device name: %s", target);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (device &&
|
|
|
|
!strcmp((const char *)device, "cdrom"))
|
|
|
|
disk->readonly = 1;
|
|
|
|
|
|
|
|
if ((!device || !strcmp((const char *)device, "disk")) &&
|
|
|
|
strcmp((const char *)target, "hda") &&
|
|
|
|
strcmp((const char *)target, "hdb") &&
|
|
|
|
strcmp((const char *)target, "hdc") &&
|
|
|
|
strcmp((const char *)target, "hdd")) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Invalid harddisk device name: %s", target);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2008-03-13 09:17:45 +00:00
|
|
|
strncpy(disk->src, (source ? (const char *) source : "\0"), NAME_MAX-1);
|
2007-02-14 01:40:09 +00:00
|
|
|
disk->src[NAME_MAX-1] = '\0';
|
|
|
|
|
|
|
|
strncpy(disk->dst, (const char *)target, NAME_MAX-1);
|
|
|
|
disk->dst[NAME_MAX-1] = '\0';
|
|
|
|
disk->type = typ;
|
|
|
|
|
|
|
|
if (!device)
|
|
|
|
disk->device = QEMUD_DISK_DISK;
|
|
|
|
else if (!strcmp((const char *)device, "disk"))
|
|
|
|
disk->device = QEMUD_DISK_DISK;
|
|
|
|
else if (!strcmp((const char *)device, "cdrom"))
|
|
|
|
disk->device = QEMUD_DISK_CDROM;
|
|
|
|
else if (!strcmp((const char *)device, "floppy"))
|
|
|
|
disk->device = QEMUD_DISK_FLOPPY;
|
|
|
|
else {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Invalid device type: %s", device);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlFree(device);
|
|
|
|
xmlFree(target);
|
|
|
|
xmlFree(source);
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
return 0;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (type)
|
|
|
|
xmlFree(type);
|
|
|
|
if (target)
|
|
|
|
xmlFree(target);
|
|
|
|
if (source)
|
|
|
|
xmlFree(source);
|
|
|
|
if (device)
|
|
|
|
xmlFree(device);
|
2007-10-27 01:18:38 +00:00
|
|
|
return -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
static void qemudRandomMAC(struct qemud_vm_net_def *net) {
|
|
|
|
net->mac[0] = 0x52;
|
|
|
|
net->mac[1] = 0x54;
|
|
|
|
net->mac[2] = 0x00;
|
|
|
|
net->mac[3] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
|
|
|
net->mac[4] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
|
|
|
net->mac[5] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
|
|
|
}
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
/* Parse the XML definition for a network interface
|
|
|
|
* @param net pre-allocated & zero'd net record
|
|
|
|
* @param node XML nodeset to parse for net definition
|
|
|
|
* @return 0 on success, -1 on failure
|
|
|
|
*/
|
|
|
|
static int qemudParseInterfaceXML(virConnectPtr conn,
|
|
|
|
struct qemud_vm_net_def *net,
|
|
|
|
xmlNodePtr node) {
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlNodePtr cur;
|
|
|
|
xmlChar *macaddr = NULL;
|
|
|
|
xmlChar *type = NULL;
|
2007-02-14 16:09:37 +00:00
|
|
|
xmlChar *network = NULL;
|
2007-03-13 22:43:22 +00:00
|
|
|
xmlChar *bridge = NULL;
|
|
|
|
xmlChar *ifname = NULL;
|
|
|
|
xmlChar *script = NULL;
|
|
|
|
xmlChar *address = NULL;
|
|
|
|
xmlChar *port = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
net->type = QEMUD_NET_USER;
|
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (type != NULL) {
|
|
|
|
if (xmlStrEqual(type, BAD_CAST "user"))
|
|
|
|
net->type = QEMUD_NET_USER;
|
2007-03-13 22:43:22 +00:00
|
|
|
else if (xmlStrEqual(type, BAD_CAST "ethernet"))
|
|
|
|
net->type = QEMUD_NET_ETHERNET;
|
2007-02-14 01:40:09 +00:00
|
|
|
else if (xmlStrEqual(type, BAD_CAST "server"))
|
|
|
|
net->type = QEMUD_NET_SERVER;
|
|
|
|
else if (xmlStrEqual(type, BAD_CAST "client"))
|
|
|
|
net->type = QEMUD_NET_CLIENT;
|
|
|
|
else if (xmlStrEqual(type, BAD_CAST "mcast"))
|
|
|
|
net->type = QEMUD_NET_MCAST;
|
2007-02-14 16:09:37 +00:00
|
|
|
else if (xmlStrEqual(type, BAD_CAST "network"))
|
|
|
|
net->type = QEMUD_NET_NETWORK;
|
2007-03-13 22:43:22 +00:00
|
|
|
else if (xmlStrEqual(type, BAD_CAST "bridge"))
|
|
|
|
net->type = QEMUD_NET_BRIDGE;
|
2007-02-14 01:40:09 +00:00
|
|
|
else
|
|
|
|
net->type = QEMUD_NET_USER;
|
|
|
|
xmlFree(type);
|
|
|
|
type = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
|
|
|
if ((macaddr == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
|
|
|
|
macaddr = xmlGetProp(cur, BAD_CAST "address");
|
2007-02-14 16:09:37 +00:00
|
|
|
} else if ((network == NULL) &&
|
|
|
|
(net->type == QEMUD_NET_NETWORK) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
|
|
|
network = xmlGetProp(cur, BAD_CAST "network");
|
2007-03-13 22:43:22 +00:00
|
|
|
} else if ((network == NULL) &&
|
|
|
|
(net->type == QEMUD_NET_BRIDGE) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
2007-03-27 14:46:45 +00:00
|
|
|
bridge = xmlGetProp(cur, BAD_CAST "bridge");
|
2007-03-13 22:43:22 +00:00
|
|
|
} else if ((network == NULL) &&
|
|
|
|
((net->type == QEMUD_NET_SERVER) ||
|
|
|
|
(net->type == QEMUD_NET_CLIENT) ||
|
|
|
|
(net->type == QEMUD_NET_MCAST)) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
|
|
|
address = xmlGetProp(cur, BAD_CAST "address");
|
|
|
|
port = xmlGetProp(cur, BAD_CAST "port");
|
|
|
|
} else if ((ifname == NULL) &&
|
|
|
|
((net->type == QEMUD_NET_NETWORK) ||
|
|
|
|
(net->type == QEMUD_NET_ETHERNET) ||
|
|
|
|
(net->type == QEMUD_NET_BRIDGE)) &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "target")) {
|
|
|
|
ifname = xmlGetProp(cur, BAD_CAST "dev");
|
2007-12-05 15:08:23 +00:00
|
|
|
if (STREQLEN("vnet", (const char*)ifname, 4)) {
|
|
|
|
/* An auto-generated target name, blank it out */
|
|
|
|
xmlFree(ifname);
|
|
|
|
ifname = NULL;
|
|
|
|
}
|
2007-03-13 22:43:22 +00:00
|
|
|
} else if ((script == NULL) &&
|
|
|
|
(net->type == QEMUD_NET_ETHERNET) &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "script")) {
|
|
|
|
script = xmlGetProp(cur, BAD_CAST "path");
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (macaddr) {
|
2007-02-19 15:01:20 +00:00
|
|
|
unsigned int mac[6];
|
2007-02-14 01:40:09 +00:00
|
|
|
sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
2007-02-19 15:01:20 +00:00
|
|
|
(unsigned int*)&mac[0],
|
|
|
|
(unsigned int*)&mac[1],
|
|
|
|
(unsigned int*)&mac[2],
|
|
|
|
(unsigned int*)&mac[3],
|
|
|
|
(unsigned int*)&mac[4],
|
|
|
|
(unsigned int*)&mac[5]);
|
|
|
|
net->mac[0] = mac[0];
|
|
|
|
net->mac[1] = mac[1];
|
|
|
|
net->mac[2] = mac[2];
|
|
|
|
net->mac[3] = mac[3];
|
|
|
|
net->mac[4] = mac[4];
|
|
|
|
net->mac[5] = mac[5];
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
xmlFree(macaddr);
|
2007-03-13 22:43:22 +00:00
|
|
|
macaddr = NULL;
|
|
|
|
} else {
|
|
|
|
qemudRandomMAC(net);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-02-14 16:09:37 +00:00
|
|
|
if (net->type == QEMUD_NET_NETWORK) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (network == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-14 16:09:37 +00:00
|
|
|
"No <source> 'network' attribute specified with <interface type='network'/>");
|
|
|
|
goto error;
|
2007-03-13 22:43:22 +00:00
|
|
|
} else if ((len = xmlStrlen(network)) >= (QEMUD_MAX_NAME_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-14 16:09:37 +00:00
|
|
|
"Network name '%s' too long", network);
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.network.name, (char *)network, len);
|
|
|
|
net->dst.network.name[len] = '\0';
|
|
|
|
}
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
if (network) {
|
2007-02-14 16:09:37 +00:00
|
|
|
xmlFree(network);
|
2007-03-13 22:43:22 +00:00
|
|
|
network = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ifname != NULL) {
|
|
|
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"TAP interface name '%s' is too long", ifname);
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.network.ifname, (char *)ifname, len);
|
|
|
|
net->dst.network.ifname[len] = '\0';
|
|
|
|
}
|
|
|
|
xmlFree(ifname);
|
|
|
|
ifname = NULL;
|
|
|
|
}
|
|
|
|
} else if (net->type == QEMUD_NET_ETHERNET) {
|
|
|
|
int len;
|
2007-02-14 16:09:37 +00:00
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
if (script != NULL) {
|
|
|
|
if ((len = xmlStrlen(script)) >= (PATH_MAX-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"TAP script path '%s' is too long", script);
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.ethernet.script, (char *)script, len);
|
|
|
|
net->dst.ethernet.script[len] = '\0';
|
|
|
|
}
|
|
|
|
xmlFree(script);
|
|
|
|
script = NULL;
|
|
|
|
}
|
|
|
|
if (ifname != NULL) {
|
|
|
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"TAP interface name '%s' is too long", ifname);
|
2007-02-14 16:09:37 +00:00
|
|
|
goto error;
|
|
|
|
} else {
|
2007-03-13 22:43:22 +00:00
|
|
|
strncpy(net->dst.ethernet.ifname, (char *)ifname, len);
|
|
|
|
net->dst.ethernet.ifname[len] = '\0';
|
2007-02-14 16:09:37 +00:00
|
|
|
}
|
2007-03-13 22:43:22 +00:00
|
|
|
xmlFree(ifname);
|
|
|
|
}
|
|
|
|
} else if (net->type == QEMUD_NET_BRIDGE) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (bridge == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"No <source> 'dev' attribute specified with <interface type='bridge'/>");
|
|
|
|
goto error;
|
|
|
|
} else if ((len = xmlStrlen(bridge)) >= (BR_IFNAME_MAXLEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"TAP bridge path '%s' is too long", bridge);
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.bridge.brname, (char *)bridge, len);
|
|
|
|
net->dst.bridge.brname[len] = '\0';
|
2007-02-14 16:09:37 +00:00
|
|
|
}
|
2007-03-13 22:43:22 +00:00
|
|
|
|
|
|
|
xmlFree(bridge);
|
|
|
|
bridge = NULL;
|
|
|
|
|
|
|
|
if (ifname != NULL) {
|
|
|
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"TAP interface name '%s' is too long", ifname);
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.bridge.ifname, (char *)ifname, len);
|
|
|
|
net->dst.bridge.ifname[len] = '\0';
|
|
|
|
}
|
|
|
|
xmlFree(ifname);
|
|
|
|
}
|
|
|
|
} else if (net->type == QEMUD_NET_CLIENT ||
|
|
|
|
net->type == QEMUD_NET_SERVER ||
|
|
|
|
net->type == QEMUD_NET_MCAST) {
|
2007-08-07 13:02:35 +00:00
|
|
|
int len = 0;
|
2007-03-13 22:43:22 +00:00
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (port == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"No <source> 'port' attribute specified with socket interface");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!(net->dst.socket.port = strtol((char*)port, &ret, 10)) &&
|
|
|
|
ret == (char*)port) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"Cannot parse <source> 'port' attribute with socket interface");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xmlFree(port);
|
|
|
|
port = NULL;
|
|
|
|
|
|
|
|
if (address == NULL) {
|
|
|
|
if (net->type == QEMUD_NET_CLIENT ||
|
|
|
|
net->type == QEMUD_NET_MCAST) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"No <source> 'address' attribute specified with socket interface");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else if ((len = xmlStrlen(address)) >= (BR_INET_ADDR_MAXLEN)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"IP address '%s' is too long", address);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (address == NULL) {
|
|
|
|
net->dst.socket.address[0] = '\0';
|
|
|
|
} else {
|
|
|
|
strncpy(net->dst.socket.address, (char*)address,len);
|
|
|
|
net->dst.socket.address[len] = '\0';
|
|
|
|
}
|
|
|
|
xmlFree(address);
|
2007-02-14 16:09:37 +00:00
|
|
|
}
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
return 0;
|
2007-02-14 16:09:37 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (network)
|
|
|
|
xmlFree(network);
|
2007-03-13 22:43:22 +00:00
|
|
|
if (address)
|
|
|
|
xmlFree(address);
|
|
|
|
if (port)
|
|
|
|
xmlFree(port);
|
|
|
|
if (ifname)
|
|
|
|
xmlFree(ifname);
|
|
|
|
if (script)
|
|
|
|
xmlFree(script);
|
|
|
|
if (bridge)
|
|
|
|
xmlFree(bridge);
|
2007-10-27 01:18:38 +00:00
|
|
|
return -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-18 21:08:22 +00:00
|
|
|
/* Parse the XML definition for a network interface */
|
2007-10-27 01:18:38 +00:00
|
|
|
static int qemudParseInputXML(virConnectPtr conn,
|
|
|
|
struct qemud_vm_input_def *input,
|
|
|
|
xmlNodePtr node) {
|
2007-07-18 21:08:22 +00:00
|
|
|
xmlChar *type = NULL;
|
|
|
|
xmlChar *bus = NULL;
|
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
bus = xmlGetProp(node, BAD_CAST "bus");
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "no type provide for input device");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp((const char *)type, "mouse")) {
|
|
|
|
input->type = QEMU_INPUT_TYPE_MOUSE;
|
|
|
|
} else if (!strcmp((const char *)type, "tablet")) {
|
|
|
|
input->type = QEMU_INPUT_TYPE_TABLET;
|
|
|
|
} else {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported input device type %s", (const char*)type);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bus) {
|
|
|
|
if (!strcmp((const char*)bus, "ps2")) { /* Only allow mouse */
|
|
|
|
if (input->type == QEMU_INPUT_TYPE_TABLET) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "ps2 bus does not support %s input device", (const char*)type);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
input->bus = QEMU_INPUT_BUS_PS2;
|
|
|
|
} else if (!strcmp((const char *)bus, "usb")) { /* Allow mouse & keyboard */
|
|
|
|
input->bus = QEMU_INPUT_BUS_USB;
|
|
|
|
} else {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported input bus %s", (const char*)bus);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (input->type == QEMU_INPUT_TYPE_MOUSE)
|
|
|
|
input->bus = QEMU_INPUT_BUS_PS2;
|
|
|
|
else
|
|
|
|
input->bus = QEMU_INPUT_BUS_USB;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type)
|
|
|
|
xmlFree(type);
|
|
|
|
if (bus)
|
|
|
|
xmlFree(bus);
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
return 0;
|
2007-07-18 21:08:22 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (type)
|
|
|
|
xmlFree(type);
|
|
|
|
if (bus)
|
|
|
|
xmlFree(bus);
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
return -1;
|
2007-07-18 21:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
/*
|
|
|
|
* Parses a libvirt XML definition of a guest, and populates the
|
|
|
|
* the qemud_vm struct with matching data about the guests config
|
|
|
|
*/
|
2007-07-12 15:09:01 +00:00
|
|
|
static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-14 17:05:55 +00:00
|
|
|
xmlDocPtr xml) {
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlNodePtr root = NULL;
|
|
|
|
xmlChar *prop = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
xmlXPathObjectPtr obj = NULL;
|
|
|
|
char *conv = NULL;
|
|
|
|
int i;
|
2007-02-14 17:05:55 +00:00
|
|
|
struct qemud_vm_def *def;
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(def = calloc(1, sizeof(*def)))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xmlXPathContext");
|
2007-02-14 17:05:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/* Prepare parser / xpath context */
|
|
|
|
root = xmlDocGetRootElement(xml);
|
|
|
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "incorrect root element");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xmlXPathContext");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Find out what type of QEMU virtualization to use */
|
|
|
|
if (!(prop = xmlGetProp(root, BAD_CAST "type"))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "missing domain type attribute");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp((char *)prop, "qemu"))
|
2007-02-14 17:05:55 +00:00
|
|
|
def->virtType = QEMUD_VIRT_QEMU;
|
2007-02-14 01:40:09 +00:00
|
|
|
else if (!strcmp((char *)prop, "kqemu"))
|
2007-02-14 17:05:55 +00:00
|
|
|
def->virtType = QEMUD_VIRT_KQEMU;
|
2007-02-14 01:40:09 +00:00
|
|
|
else if (!strcmp((char *)prop, "kvm"))
|
2007-02-14 17:05:55 +00:00
|
|
|
def->virtType = QEMUD_VIRT_KVM;
|
2007-02-14 01:40:09 +00:00
|
|
|
else {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "invalid domain type attribute");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
free(prop);
|
|
|
|
prop = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract domain name */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "domain name length too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->name, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract domain uuid */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-02-26 15:32:27 +00:00
|
|
|
int err;
|
2007-06-26 22:19:38 +00:00
|
|
|
if ((err = virUUIDGenerate(def->uuid))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-26 15:32:27 +00:00
|
|
|
"Failed to generate UUID: %s", strerror(err));
|
|
|
|
goto error;
|
|
|
|
}
|
2007-06-26 22:19:38 +00:00
|
|
|
} else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract domain memory */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "missing memory element");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
conv = NULL;
|
2007-02-14 17:05:55 +00:00
|
|
|
def->maxmem = strtoll((const char*)obj->stringval, &conv, 10);
|
2007-02-14 01:40:09 +00:00
|
|
|
if (conv == (const char*)obj->stringval) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "malformed memory information");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Extract domain memory */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/currentMemory[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->memory = def->maxmem;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
conv = NULL;
|
2007-02-14 17:05:55 +00:00
|
|
|
def->memory = strtoll((const char*)obj->stringval, &conv, 10);
|
|
|
|
if (def->memory > def->maxmem)
|
|
|
|
def->memory = def->maxmem;
|
2007-02-14 01:40:09 +00:00
|
|
|
if (conv == (const char*)obj->stringval) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "malformed memory information");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/* Extract domain vcpu info */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->vcpus = 1;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
conv = NULL;
|
2007-02-14 17:05:55 +00:00
|
|
|
def->vcpus = strtoll((const char*)obj->stringval, &conv, 10);
|
2007-02-14 01:40:09 +00:00
|
|
|
if (conv == (const char*)obj->stringval) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "malformed vcpu information");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/* See if ACPI feature is requested */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->features |= QEMUD_FEATURE_ACPI;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2007-02-20 17:51:41 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-05-03 16:10:40 +00:00
|
|
|
|
|
|
|
/* See if we disable reboots */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot)", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
|
|
|
def->noReboot = 0;
|
|
|
|
} else {
|
|
|
|
if (!strcmp((char*)obj->stringval, "destroy"))
|
|
|
|
def->noReboot = 1;
|
|
|
|
else
|
|
|
|
def->noReboot = 0;
|
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-05-03 16:10:40 +00:00
|
|
|
|
2007-07-16 21:30:30 +00:00
|
|
|
/* See if we set clock to localtime */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/clock/@offset)", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
|
|
|
def->localtime = 0;
|
|
|
|
} else {
|
|
|
|
if (!strcmp((char*)obj->stringval, "localtime"))
|
|
|
|
def->localtime = 1;
|
|
|
|
else
|
|
|
|
def->localtime = 0;
|
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-07-16 21:30:30 +00:00
|
|
|
|
2007-05-03 16:10:40 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
/* Extract OS type info */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2008-03-14 20:30:03 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, "no OS type");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
if (!virCapabilitiesSupportsGuestOSType(driver->caps, (const char*)obj->stringval)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, "%s", obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.type, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2008-02-27 04:35:08 +00:00
|
|
|
const char *defaultArch = virCapabilitiesDefaultGuestArch(driver->caps, def->os.type);
|
|
|
|
if (defaultArch == NULL) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture");
|
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.arch, defaultArch);
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.arch, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2008-02-27 04:35:08 +00:00
|
|
|
const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps,
|
|
|
|
def->os.type,
|
|
|
|
def->os.arch);
|
|
|
|
if (defaultMachine == NULL) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture");
|
2007-07-30 18:50:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "machine type too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.machine, defaultMachine);
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.machine, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/kernel[1])", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
|
|
|
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "kernel path too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.kernel, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/initrd[1])", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
|
|
|
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "initrd path too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.initrd, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/cmdline[1])", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
|
|
|
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "cmdline arguments too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.cmdline, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* analysis of the disk devices */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/os/boot", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
|
|
|
for (i = 0; i < obj->nodesetval->nodeNr && i < QEMUD_MAX_BOOT_DEVS ; i++) {
|
2007-02-22 10:39:38 +00:00
|
|
|
if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
|
|
|
|
continue;
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!strcmp((char *)prop, "hd")) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else if (!strcmp((char *)prop, "fd")) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else if (!strcmp((char *)prop, "cdrom")) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
|
2007-09-13 22:06:54 +00:00
|
|
|
} else if (!strcmp((char *)prop, "network")) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
2008-02-06 16:24:28 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"unknown boot dev \'%s\'", (char*)prop);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-22 10:39:38 +00:00
|
|
|
xmlFree(prop);
|
2007-03-09 03:08:34 +00:00
|
|
|
prop = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->os.nBootDevs == 0) {
|
|
|
|
def->os.nBootDevs = 1;
|
|
|
|
def->os.bootDevs[0] = QEMUD_BOOT_DISK;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2008-02-27 04:35:08 +00:00
|
|
|
const char *type = (def->virtType == QEMUD_VIRT_QEMU ? "qemu" :
|
|
|
|
def->virtType == QEMUD_VIRT_KQEMU ? "kqemu":
|
|
|
|
"kvm");
|
|
|
|
const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps,
|
|
|
|
def->os.type,
|
|
|
|
def->os.arch,
|
|
|
|
type);
|
|
|
|
if (!emulator) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported guest type");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
strcpy(def->os.binary, emulator);
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "emulator path too long");
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
strcpy(def->os.binary, (const char *)obj->stringval);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
|
|
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->graphicsType = QEMUD_GRAPHICS_NONE;
|
2007-02-20 17:51:41 +00:00
|
|
|
} else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"))) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!strcmp((char *)prop, "vnc")) {
|
2007-07-24 14:30:05 +00:00
|
|
|
xmlChar *vncport, *vnclisten;
|
2007-02-14 17:05:55 +00:00
|
|
|
def->graphicsType = QEMUD_GRAPHICS_VNC;
|
2007-07-24 14:30:05 +00:00
|
|
|
vncport = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port");
|
|
|
|
if (vncport) {
|
2007-02-14 01:40:09 +00:00
|
|
|
conv = NULL;
|
2007-07-24 14:30:05 +00:00
|
|
|
def->vncPort = strtoll((const char*)vncport, &conv, 10);
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->vncPort = -1;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2007-07-24 14:30:05 +00:00
|
|
|
vnclisten = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "listen");
|
|
|
|
if (vnclisten && *vnclisten)
|
|
|
|
strncpy(def->vncListen, (char *)vnclisten, BR_INET_ADDR_MAXLEN-1);
|
|
|
|
else
|
2007-10-12 16:05:44 +00:00
|
|
|
strcpy(def->vncListen, driver->vncListen);
|
2007-07-24 14:30:05 +00:00
|
|
|
def->vncListen[BR_INET_ADDR_MAXLEN-1] = '\0';
|
2008-01-15 15:18:33 +00:00
|
|
|
def->keymap = (char *) xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "keymap");
|
2007-07-24 14:30:05 +00:00
|
|
|
xmlFree(vncport);
|
|
|
|
xmlFree(vnclisten);
|
2007-02-14 01:40:09 +00:00
|
|
|
} else if (!strcmp((char *)prop, "sdl")) {
|
2007-02-14 17:05:55 +00:00
|
|
|
def->graphicsType = QEMUD_GRAPHICS_SDL;
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Unsupported graphics type %s", prop);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-20 17:51:41 +00:00
|
|
|
xmlFree(prop);
|
2007-03-09 03:08:34 +00:00
|
|
|
prop = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
2007-02-20 17:51:41 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/* analysis of the disk devices */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
2007-03-13 22:43:22 +00:00
|
|
|
struct qemud_vm_disk_def *prev = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
2007-12-11 21:57:29 +00:00
|
|
|
struct qemud_vm_disk_def *disk = calloc(1, sizeof(*disk));
|
2007-10-27 01:18:38 +00:00
|
|
|
if (!disk) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "disk");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (qemudParseDiskXML(conn, disk, obj->nodesetval->nodeTab[i]) < 0) {
|
|
|
|
free(disk);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
def->ndisks++;
|
2007-03-13 22:43:22 +00:00
|
|
|
disk->next = NULL;
|
|
|
|
if (i == 0) {
|
|
|
|
def->disks = disk;
|
|
|
|
} else {
|
|
|
|
prev->next = disk;
|
|
|
|
}
|
|
|
|
prev = disk;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* analysis of the network devices */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
2007-03-13 22:43:22 +00:00
|
|
|
struct qemud_vm_net_def *prev = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
2007-12-11 21:57:29 +00:00
|
|
|
struct qemud_vm_net_def *net = calloc(1, sizeof(*net));
|
2007-10-27 01:18:38 +00:00
|
|
|
if (!net) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "net");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (qemudParseInterfaceXML(conn, net, obj->nodesetval->nodeTab[i]) < 0) {
|
|
|
|
free(net);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
def->nnets++;
|
2007-03-13 22:43:22 +00:00
|
|
|
net->next = NULL;
|
|
|
|
if (i == 0) {
|
|
|
|
def->nets = net;
|
|
|
|
} else {
|
|
|
|
prev->next = net;
|
|
|
|
}
|
|
|
|
prev = net;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
2007-07-18 21:08:22 +00:00
|
|
|
|
|
|
|
/* analysis of the input devices */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/input", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
|
|
|
struct qemud_vm_input_def *prev = NULL;
|
|
|
|
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
2007-12-11 21:57:29 +00:00
|
|
|
struct qemud_vm_input_def *input = calloc(1, sizeof(*input));
|
2007-10-27 01:18:38 +00:00
|
|
|
if (!input) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "input");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (qemudParseInputXML(conn, input, obj->nodesetval->nodeTab[i]) < 0) {
|
|
|
|
free(input);
|
2007-07-18 21:08:22 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/* Mouse + PS/2 is implicit with graphics, so don't store it */
|
|
|
|
if (input->bus == QEMU_INPUT_BUS_PS2 &&
|
|
|
|
input->type == QEMU_INPUT_TYPE_MOUSE) {
|
|
|
|
free(input);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
def->ninputs++;
|
|
|
|
input->next = NULL;
|
2007-09-28 20:47:58 +00:00
|
|
|
if (def->inputs == NULL) {
|
2007-07-18 21:08:22 +00:00
|
|
|
def->inputs = input;
|
|
|
|
} else {
|
|
|
|
prev->next = input;
|
|
|
|
}
|
|
|
|
prev = input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
obj = NULL;
|
|
|
|
|
|
|
|
/* If graphics are enabled, there's an implicit PS2 mouse */
|
|
|
|
if (def->graphicsType != QEMUD_GRAPHICS_NONE) {
|
|
|
|
int hasPS2mouse = 0;
|
|
|
|
struct qemud_vm_input_def *input = def->inputs;
|
|
|
|
while (input) {
|
|
|
|
if (input->type == QEMU_INPUT_TYPE_MOUSE &&
|
|
|
|
input->bus == QEMU_INPUT_BUS_PS2)
|
|
|
|
hasPS2mouse = 1;
|
|
|
|
input = input->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasPS2mouse) {
|
2007-12-11 21:57:29 +00:00
|
|
|
input = calloc(1, sizeof(*input));
|
2007-07-18 21:08:22 +00:00
|
|
|
if (!input) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "input");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
input->type = QEMU_INPUT_TYPE_MOUSE;
|
|
|
|
input->bus = QEMU_INPUT_BUS_PS2;
|
|
|
|
input->next = def->inputs;
|
|
|
|
def->inputs = input;
|
|
|
|
def->ninputs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
return def;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
error:
|
2008-01-29 17:41:07 +00:00
|
|
|
free(prop);
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-02-14 17:05:55 +00:00
|
|
|
qemudFreeVMDef(def);
|
|
|
|
return NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-14 16:09:37 +00:00
|
|
|
static char *
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudNetworkIfaceConnect(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-14 16:09:37 +00:00
|
|
|
struct qemud_vm *vm,
|
2007-03-13 22:43:22 +00:00
|
|
|
struct qemud_vm_net_def *net,
|
|
|
|
int vlan)
|
2007-02-14 16:09:37 +00:00
|
|
|
{
|
2007-03-13 22:43:22 +00:00
|
|
|
struct qemud_network *network = NULL;
|
|
|
|
char *brname;
|
|
|
|
char *ifname;
|
2007-02-14 16:09:37 +00:00
|
|
|
char tapfdstr[4+3+32+7];
|
|
|
|
char *retval = NULL;
|
|
|
|
int err;
|
|
|
|
int tapfd = -1;
|
|
|
|
int *tapfds;
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
if (net->type == QEMUD_NET_NETWORK) {
|
2007-06-26 22:13:21 +00:00
|
|
|
if (!(network = qemudFindNetworkByName(driver, net->dst.network.name))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"Network '%s' not found", net->dst.network.name);
|
|
|
|
goto error;
|
|
|
|
} else if (network->bridge[0] == '\0') {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"Network '%s' not active", net->dst.network.name);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
brname = network->bridge;
|
|
|
|
if (net->dst.network.ifname[0] == '\0' ||
|
2007-12-05 15:08:23 +00:00
|
|
|
STREQLEN(net->dst.network.ifname, "vnet", 4) ||
|
2007-03-13 22:43:22 +00:00
|
|
|
strchr(net->dst.network.ifname, '%')) {
|
|
|
|
strcpy(net->dst.network.ifname, "vnet%d");
|
|
|
|
}
|
|
|
|
ifname = net->dst.network.ifname;
|
|
|
|
} else if (net->type == QEMUD_NET_BRIDGE) {
|
|
|
|
brname = net->dst.bridge.brname;
|
|
|
|
if (net->dst.bridge.ifname[0] == '\0' ||
|
2007-12-05 15:08:23 +00:00
|
|
|
STREQLEN(net->dst.bridge.ifname, "vnet", 4) ||
|
2007-03-13 22:43:22 +00:00
|
|
|
strchr(net->dst.bridge.ifname, '%')) {
|
|
|
|
strcpy(net->dst.bridge.ifname, "vnet%d");
|
|
|
|
}
|
|
|
|
ifname = net->dst.bridge.ifname;
|
|
|
|
} else {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"Network type %d is not supported", net->type);
|
2007-02-14 16:09:37 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if (!driver->brctl && (err = brInit(&driver->brctl))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-05-14 15:41:57 +00:00
|
|
|
"cannot initialize bridge support: %s", strerror(err));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if ((err = brAddTap(driver->brctl, brname,
|
2007-03-13 22:43:22 +00:00
|
|
|
ifname, BR_IFNAME_MAXLEN, &tapfd))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-14 16:09:37 +00:00
|
|
|
"Failed to add tap interface '%s' to bridge '%s' : %s",
|
2007-03-13 22:43:22 +00:00
|
|
|
ifname, brname, strerror(err));
|
2007-02-14 16:09:37 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2008-03-14 20:30:03 +00:00
|
|
|
snprintf(tapfdstr, sizeof(tapfdstr),
|
|
|
|
"tap,fd=%d,script=,vlan=%d,ifname=%s",
|
|
|
|
tapfd, vlan, ifname);
|
2007-02-14 16:09:37 +00:00
|
|
|
|
|
|
|
if (!(retval = strdup(tapfdstr)))
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(tapfds = realloc(vm->tapfds, sizeof(*tapfds) * (vm->ntapfds+2))))
|
2007-02-14 16:09:37 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
vm->tapfds = tapfds;
|
|
|
|
vm->tapfds[vm->ntapfds++] = tapfd;
|
|
|
|
vm->tapfds[vm->ntapfds] = -1;
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
no_memory:
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "tapfds");
|
2007-02-14 16:09:37 +00:00
|
|
|
error:
|
2008-01-29 17:41:07 +00:00
|
|
|
free(retval);
|
2007-02-14 16:09:37 +00:00
|
|
|
if (tapfd != -1)
|
|
|
|
close(tapfd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
/*
|
|
|
|
* Constructs a argv suitable for launching qemu with config defined
|
|
|
|
* for a given virtual machine.
|
|
|
|
*/
|
2007-07-12 15:09:01 +00:00
|
|
|
int qemudBuildCommandLine(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-14 01:40:09 +00:00
|
|
|
struct qemud_vm *vm,
|
2007-02-14 15:54:47 +00:00
|
|
|
char ***argv) {
|
|
|
|
int len, n = -1, i;
|
2007-02-14 01:40:09 +00:00
|
|
|
char memory[50];
|
|
|
|
char vcpus[50];
|
|
|
|
char boot[QEMUD_MAX_BOOT_DEVS+1];
|
2007-04-16 13:14:28 +00:00
|
|
|
struct stat sb;
|
2007-02-14 17:05:55 +00:00
|
|
|
struct qemud_vm_disk_def *disk = vm->def->disks;
|
|
|
|
struct qemud_vm_net_def *net = vm->def->nets;
|
2007-07-18 21:08:22 +00:00
|
|
|
struct qemud_vm_input_def *input = vm->def->inputs;
|
2007-04-16 13:14:28 +00:00
|
|
|
struct utsname ut;
|
|
|
|
int disableKQEMU = 0;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-09-21 21:20:32 +00:00
|
|
|
/* Make sure the binary we are about to try exec'ing exists.
|
|
|
|
* Technically we could catch the exec() failure, but that's
|
|
|
|
* in a sub-process so its hard to feed back a useful error
|
|
|
|
*/
|
|
|
|
if (stat(vm->def->os.binary, &sb) < 0) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Cannot find QEMU binary %s: %s", vm->def->os.binary,
|
|
|
|
strerror(errno));
|
2007-02-23 17:15:18 +00:00
|
|
|
return -1;
|
2007-09-21 21:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->qemuVersion == 0) {
|
|
|
|
if (qemudExtractVersionInfo(vm->def->os.binary,
|
|
|
|
&(vm->qemuVersion),
|
|
|
|
&(vm->qemuCmdFlags)) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 17:15:18 +00:00
|
|
|
|
2007-04-16 13:14:28 +00:00
|
|
|
uname(&ut);
|
|
|
|
|
2007-05-18 18:36:24 +00:00
|
|
|
/* Nasty hack make i?86 look like i686 to simplify next comparison */
|
2007-04-16 13:14:28 +00:00
|
|
|
if (ut.machine[0] == 'i' &&
|
|
|
|
ut.machine[2] == '8' &&
|
|
|
|
ut.machine[3] == '6' &&
|
|
|
|
!ut.machine[4])
|
2007-05-18 18:36:24 +00:00
|
|
|
ut.machine[1] = '6';
|
2007-04-16 13:14:28 +00:00
|
|
|
|
|
|
|
/* Need to explicitly disable KQEMU if
|
|
|
|
* 1. Arch matches host arch
|
|
|
|
* 2. Guest is 'qemu'
|
|
|
|
* 3. The qemu binary has the -no-kqemu flag
|
|
|
|
*/
|
2007-09-21 21:20:32 +00:00
|
|
|
if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
|
2007-04-16 13:14:28 +00:00
|
|
|
!strcmp(ut.machine, vm->def->os.arch) &&
|
|
|
|
vm->def->virtType == QEMUD_VIRT_QEMU)
|
|
|
|
disableKQEMU = 1;
|
|
|
|
|
2007-02-14 15:54:47 +00:00
|
|
|
len = 1 + /* qemu */
|
2007-02-14 01:40:09 +00:00
|
|
|
2 + /* machine type */
|
2007-04-16 13:14:28 +00:00
|
|
|
disableKQEMU + /* Disable kqemu */
|
2007-02-14 17:05:55 +00:00
|
|
|
2 * vm->def->ndisks + /* disks*/
|
|
|
|
(vm->def->nnets > 0 ? (4 * vm->def->nnets) : 2) + /* networks */
|
2007-07-18 21:08:22 +00:00
|
|
|
1 + /* usb */
|
|
|
|
2 * vm->def->ninputs + /* input devices */
|
2007-02-14 01:40:09 +00:00
|
|
|
2 + /* memory*/
|
|
|
|
2 + /* cpus */
|
|
|
|
2 + /* boot device */
|
|
|
|
2 + /* monitor */
|
2007-07-16 21:30:30 +00:00
|
|
|
(vm->def->localtime ? 1 : 0) + /* localtime */
|
2007-09-21 21:20:32 +00:00
|
|
|
(vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
|
2007-05-03 16:10:40 +00:00
|
|
|
vm->def->noReboot ? 1 : 0) + /* no-reboot */
|
2007-02-14 17:05:55 +00:00
|
|
|
(vm->def->features & QEMUD_FEATURE_ACPI ? 0 : 1) + /* acpi */
|
|
|
|
(vm->def->os.kernel[0] ? 2 : 0) + /* kernel */
|
|
|
|
(vm->def->os.initrd[0] ? 2 : 0) + /* initrd */
|
|
|
|
(vm->def->os.cmdline[0] ? 2 : 0) + /* cmdline */
|
|
|
|
(vm->def->graphicsType == QEMUD_GRAPHICS_VNC ? 2 :
|
2007-08-14 01:28:47 +00:00
|
|
|
(vm->def->graphicsType == QEMUD_GRAPHICS_SDL ? 0 : 1)) + /* graphics */
|
|
|
|
(vm->migrateFrom[0] ? 3 : 0); /* migrateFrom */
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2008-03-19 14:32:50 +00:00
|
|
|
snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
|
2007-03-23 16:15:07 +00:00
|
|
|
snprintf(vcpus, sizeof(vcpus), "%d", vm->def->vcpus);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(*argv = malloc(sizeof(**argv) * (len+1))))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vm->def->os.binary)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup("-M")))
|
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vm->def->os.machine)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2007-04-16 13:14:28 +00:00
|
|
|
if (disableKQEMU) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-no-kqemu")))
|
2007-02-23 17:15:18 +00:00
|
|
|
goto no_memory;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
if (!((*argv)[++n] = strdup("-m")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(memory)))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup("-smp")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(vcpus)))
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-07-24 14:30:05 +00:00
|
|
|
/*
|
|
|
|
* NB, -nographic *MUST* come before any serial, or monitor
|
|
|
|
* or parallel port flags due to QEMU craziness, where it
|
|
|
|
* decides to change the serial port & monitor to be on stdout
|
|
|
|
* if you ask for nographic. So we have to make sure we override
|
|
|
|
* these defaults ourselves...
|
|
|
|
*/
|
|
|
|
if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) {
|
|
|
|
if (!((*argv)[++n] = strdup("-nographic")))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-monitor")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup("pty")))
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-07-16 21:30:30 +00:00
|
|
|
if (vm->def->localtime) {
|
|
|
|
if (!((*argv)[++n] = strdup("-localtime")))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-09-21 21:20:32 +00:00
|
|
|
if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
|
2007-05-03 16:10:40 +00:00
|
|
|
vm->def->noReboot) {
|
|
|
|
if (!((*argv)[++n] = strdup("-no-reboot")))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!(vm->def->features & QEMUD_FEATURE_ACPI)) {
|
2007-02-23 17:15:18 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-no-acpi")))
|
|
|
|
goto no_memory;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
|
|
|
|
switch (vm->def->os.bootDevs[i]) {
|
2007-02-14 01:40:09 +00:00
|
|
|
case QEMUD_BOOT_CDROM:
|
|
|
|
boot[i] = 'd';
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_FLOPPY:
|
|
|
|
boot[i] = 'a';
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_DISK:
|
|
|
|
boot[i] = 'c';
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_NET:
|
|
|
|
boot[i] = 'n';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
boot[i] = 'c';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
boot[vm->def->os.nBootDevs] = '\0';
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-boot")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(boot)))
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (vm->def->os.kernel[0]) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-kernel")))
|
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vm->def->os.kernel)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
if (vm->def->os.initrd[0]) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-initrd")))
|
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vm->def->os.initrd)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
if (vm->def->os.cmdline[0]) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-append")))
|
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vm->def->os.cmdline)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (disk) {
|
|
|
|
char dev[NAME_MAX];
|
|
|
|
char file[PATH_MAX];
|
|
|
|
if (!strcmp(disk->dst, "hdc") &&
|
2008-03-13 09:17:45 +00:00
|
|
|
disk->device == QEMUD_DISK_CDROM) {
|
|
|
|
if (disk->src[0])
|
|
|
|
snprintf(dev, NAME_MAX, "-%s", "cdrom");
|
|
|
|
else {
|
|
|
|
/* Don't put anything on the cmdline for an empty cdrom*/
|
|
|
|
disk = disk->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else
|
2007-02-14 01:40:09 +00:00
|
|
|
snprintf(dev, NAME_MAX, "-%s", disk->dst);
|
|
|
|
snprintf(file, PATH_MAX, "%s", disk->src);
|
|
|
|
|
|
|
|
if (!((*argv)[++n] = strdup(dev)))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(file)))
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
disk = disk->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!net) {
|
|
|
|
if (!((*argv)[++n] = strdup("-net")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup("none")))
|
|
|
|
goto no_memory;
|
|
|
|
} else {
|
2007-03-13 22:43:22 +00:00
|
|
|
int vlan = 0;
|
2007-02-14 01:40:09 +00:00
|
|
|
while (net) {
|
2007-03-20 16:50:42 +00:00
|
|
|
char nic[100];
|
2007-02-14 15:51:53 +00:00
|
|
|
|
2007-03-20 16:50:42 +00:00
|
|
|
if (snprintf(nic, sizeof(nic), "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d",
|
|
|
|
net->mac[0], net->mac[1],
|
|
|
|
net->mac[2], net->mac[3],
|
|
|
|
net->mac[4], net->mac[5],
|
|
|
|
vlan) >= sizeof(nic))
|
|
|
|
goto error;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
if (!((*argv)[++n] = strdup("-net")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(nic)))
|
|
|
|
goto no_memory;
|
2007-03-13 22:43:22 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-net")))
|
|
|
|
goto no_memory;
|
2007-02-14 16:09:37 +00:00
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
switch (net->type) {
|
|
|
|
case QEMUD_NET_NETWORK:
|
|
|
|
case QEMUD_NET_BRIDGE:
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!((*argv)[++n] = qemudNetworkIfaceConnect(conn, driver, vm, net, vlan)))
|
2007-02-14 16:09:37 +00:00
|
|
|
goto error;
|
2007-03-13 22:43:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_NET_ETHERNET:
|
|
|
|
{
|
|
|
|
char arg[PATH_MAX];
|
|
|
|
if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
|
|
|
|
net->dst.ethernet.ifname,
|
|
|
|
net->dst.ethernet.script,
|
|
|
|
vlan) >= (PATH_MAX-1))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!((*argv)[++n] = strdup(arg)))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_NET_CLIENT:
|
|
|
|
case QEMUD_NET_SERVER:
|
|
|
|
case QEMUD_NET_MCAST:
|
|
|
|
{
|
|
|
|
char arg[PATH_MAX];
|
|
|
|
const char *mode = NULL;
|
|
|
|
switch (net->type) {
|
|
|
|
case QEMUD_NET_CLIENT:
|
|
|
|
mode = "connect";
|
|
|
|
break;
|
|
|
|
case QEMUD_NET_SERVER:
|
|
|
|
mode = "listen";
|
|
|
|
break;
|
|
|
|
case QEMUD_NET_MCAST:
|
|
|
|
mode = "mcast";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d",
|
|
|
|
mode,
|
|
|
|
net->dst.socket.address,
|
|
|
|
net->dst.socket.port,
|
|
|
|
vlan) >= (PATH_MAX-1))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!((*argv)[++n] = strdup(arg)))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_NET_USER:
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
char arg[PATH_MAX];
|
|
|
|
if (snprintf(arg, PATH_MAX-1, "user,vlan=%d", vlan) >= (PATH_MAX-1))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!((*argv)[++n] = strdup(arg)))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 16:09:37 +00:00
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
net = net->next;
|
2007-03-13 22:43:22 +00:00
|
|
|
vlan++;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-18 21:08:22 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-usb")))
|
|
|
|
goto no_memory;
|
|
|
|
while (input) {
|
|
|
|
if (input->bus == QEMU_INPUT_BUS_USB) {
|
|
|
|
if (!((*argv)[++n] = strdup("-usbdevice")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet")))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
input = input->next;
|
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) {
|
2007-10-12 16:05:44 +00:00
|
|
|
char vncdisplay[PATH_MAX];
|
2007-02-23 17:15:18 +00:00
|
|
|
int ret;
|
2007-10-12 16:05:44 +00:00
|
|
|
|
|
|
|
if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
|
|
|
|
char options[PATH_MAX] = "";
|
|
|
|
if (driver->vncTLS) {
|
|
|
|
strcat(options, ",tls");
|
|
|
|
if (driver->vncTLSx509verify) {
|
|
|
|
strcat(options, ",x509verify=");
|
|
|
|
} else {
|
|
|
|
strcat(options, ",x509=");
|
|
|
|
}
|
|
|
|
strncat(options, driver->vncTLSx509certdir,
|
|
|
|
sizeof(options) - (strlen(driver->vncTLSx509certdir)-1));
|
|
|
|
options[sizeof(options)-1] = '\0';
|
|
|
|
}
|
|
|
|
ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s",
|
2007-07-24 14:30:05 +00:00
|
|
|
vm->def->vncListen,
|
2007-10-12 16:05:44 +00:00
|
|
|
vm->def->vncActivePort - 5900,
|
|
|
|
options);
|
|
|
|
} else {
|
2007-07-24 14:30:05 +00:00
|
|
|
ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
|
|
|
|
vm->def->vncActivePort - 5900);
|
2007-10-12 16:05:44 +00:00
|
|
|
}
|
2007-07-24 14:30:05 +00:00
|
|
|
if (ret < 0 || ret >= (int)sizeof(vncdisplay))
|
2007-02-23 17:15:18 +00:00
|
|
|
goto error;
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (!((*argv)[++n] = strdup("-vnc")))
|
|
|
|
goto no_memory;
|
2007-07-24 14:30:05 +00:00
|
|
|
if (!((*argv)[++n] = strdup(vncdisplay)))
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2008-01-15 15:18:33 +00:00
|
|
|
if (vm->def->keymap) {
|
|
|
|
if (!((*argv)[++n] = strdup("-k")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(vm->def->keymap)))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 17:05:55 +00:00
|
|
|
} else if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) {
|
2007-07-24 14:30:05 +00:00
|
|
|
/* Nada - we added -nographic earlier in this function */
|
2007-02-14 01:40:09 +00:00
|
|
|
} else {
|
|
|
|
/* SDL is the default. no args needed */
|
|
|
|
}
|
|
|
|
|
2007-08-14 01:28:47 +00:00
|
|
|
if (vm->migrateFrom[0]) {
|
|
|
|
if (!((*argv)[++n] = strdup("-S")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup("-incoming")))
|
|
|
|
goto no_memory;
|
|
|
|
if (!((*argv)[++n] = strdup(vm->migrateFrom)))
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
(*argv)[++n] = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
no_memory:
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "argv");
|
2007-02-14 16:09:37 +00:00
|
|
|
error:
|
|
|
|
if (vm->tapfds) {
|
|
|
|
for (i = 0; vm->tapfds[i] != -1; i++)
|
|
|
|
close(vm->tapfds[i]);
|
|
|
|
free(vm->tapfds);
|
|
|
|
vm->tapfds = NULL;
|
|
|
|
vm->ntapfds = 0;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
if (argv) {
|
|
|
|
for (i = 0 ; i < n ; i++)
|
2007-02-14 15:51:53 +00:00
|
|
|
free((*argv)[i]);
|
|
|
|
free(*argv);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Save a guest's config data into a persistent file */
|
2007-07-12 15:09:01 +00:00
|
|
|
static int qemudSaveConfig(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm *vm,
|
|
|
|
struct qemud_vm_def *def) {
|
2007-02-14 01:40:09 +00:00
|
|
|
char *xml;
|
|
|
|
int fd = -1, ret = -1;
|
|
|
|
int towrite;
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(xml = qemudGenerateXML(conn, driver, vm, def, 0)))
|
2007-02-14 01:40:09 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((fd = open(vm->configFile,
|
|
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
|
|
S_IRUSR | S_IWUSR )) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-20 19:09:44 +00:00
|
|
|
"cannot create config file %s: %s",
|
|
|
|
vm->configFile, strerror(errno));
|
2007-02-14 01:40:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
towrite = strlen(xml);
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, xml, towrite) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-20 19:09:44 +00:00
|
|
|
"cannot write config file %s: %s",
|
|
|
|
vm->configFile, strerror(errno));
|
2007-02-14 01:40:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (close(fd) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-20 19:09:44 +00:00
|
|
|
"cannot save config file %s: %s",
|
|
|
|
vm->configFile, strerror(errno));
|
2007-02-14 01:40:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (fd != -1)
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
free(xml);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-10-27 01:18:38 +00:00
|
|
|
struct qemud_vm_device_def *
|
|
|
|
qemudParseVMDeviceDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
|
|
|
const char *xmlStr)
|
|
|
|
{
|
|
|
|
xmlDocPtr xml;
|
|
|
|
xmlNodePtr node;
|
2007-12-11 21:57:29 +00:00
|
|
|
struct qemud_vm_device_def *dev = calloc(1, sizeof(*dev));
|
2007-10-27 01:18:38 +00:00
|
|
|
|
|
|
|
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL,
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
node = xmlDocGetRootElement(xml);
|
|
|
|
if (node == NULL) {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, "missing root element");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
|
|
|
dev->type = QEMUD_DEVICE_DISK;
|
|
|
|
qemudParseDiskXML(conn, &(dev->data.disk), node);
|
|
|
|
} else if (xmlStrEqual(node->name, BAD_CAST "net")) {
|
|
|
|
dev->type = QEMUD_DEVICE_NET;
|
|
|
|
qemudParseInterfaceXML(conn, &(dev->data.net), node);
|
|
|
|
} else if (xmlStrEqual(node->name, BAD_CAST "input")) {
|
|
|
|
dev->type = QEMUD_DEVICE_DISK;
|
|
|
|
qemudParseInputXML(conn, &(dev->data.input), node);
|
|
|
|
} else {
|
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, "unknown device type");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (xml) xmlFreeDoc(xml);
|
2008-01-29 17:41:07 +00:00
|
|
|
free(dev);
|
2007-10-27 01:18:38 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm_def *
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudParseVMDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
const char *xmlStr,
|
|
|
|
const char *displayName) {
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlDocPtr xml;
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm_def *def = NULL;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL,
|
2007-02-14 01:40:09 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
|
2007-02-14 01:40:09 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
def = qemudParseXML(conn, driver, xml);
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_vm *
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudAssignVMDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm_def *def)
|
|
|
|
{
|
|
|
|
struct qemud_vm *vm = NULL;
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if ((vm = qemudFindVMByName(driver, def->name))) {
|
2007-02-23 08:39:49 +00:00
|
|
|
if (!qemudIsActiveVM(vm)) {
|
2007-02-14 17:05:55 +00:00
|
|
|
qemudFreeVMDef(vm->def);
|
|
|
|
vm->def = def;
|
|
|
|
} else {
|
|
|
|
if (vm->newDef)
|
|
|
|
qemudFreeVMDef(vm->newDef);
|
|
|
|
vm->newDef = def;
|
|
|
|
}
|
2007-09-21 21:20:32 +00:00
|
|
|
/* Reset version, because the emulator path might have changed */
|
|
|
|
vm->qemuVersion = 0;
|
|
|
|
vm->qemuCmdFlags = 0;
|
2007-02-23 08:48:02 +00:00
|
|
|
return vm;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(vm = calloc(1, sizeof(*vm)))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "vm");
|
2007-02-23 08:48:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-08-14 01:28:47 +00:00
|
|
|
vm->stdin = -1;
|
2007-02-23 08:48:02 +00:00
|
|
|
vm->stdout = -1;
|
|
|
|
vm->stderr = -1;
|
|
|
|
vm->monitor = -1;
|
|
|
|
vm->pid = -1;
|
|
|
|
vm->id = -1;
|
2007-06-26 22:39:53 +00:00
|
|
|
vm->state = VIR_DOMAIN_SHUTOFF;
|
2007-02-23 08:48:02 +00:00
|
|
|
vm->def = def;
|
2007-06-26 22:13:21 +00:00
|
|
|
vm->next = driver->vms;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->vms = vm;
|
|
|
|
driver->ninactivevms++;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudRemoveInactiveVM(struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm *vm)
|
|
|
|
{
|
|
|
|
struct qemud_vm *prev = NULL, *curr;
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
curr = driver->vms;
|
2007-02-23 08:48:02 +00:00
|
|
|
while (curr != vm) {
|
|
|
|
prev = curr;
|
|
|
|
curr = curr->next;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
if (curr) {
|
|
|
|
if (prev)
|
|
|
|
prev->next = curr->next;
|
|
|
|
else
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->vms = curr->next;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->ninactivevms--;
|
2007-02-14 17:05:55 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
qemudFreeVM(vm);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
int
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudSaveVMDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm *vm,
|
|
|
|
struct qemud_vm_def *def) {
|
|
|
|
if (vm->configFile[0] == '\0') {
|
|
|
|
int err;
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if ((err = virFileMakePath(driver->configDir))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 08:48:02 +00:00
|
|
|
"cannot create config directory %s: %s",
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->configDir, strerror(err));
|
2007-02-23 08:48:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (virFileBuildPath(driver->configDir, def->name, ".xml",
|
|
|
|
vm->configFile, PATH_MAX) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 08:48:02 +00:00
|
|
|
"cannot construct config file path");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 09:07:41 +00:00
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (virFileBuildPath(driver->autostartDir, def->name, ".xml",
|
|
|
|
vm->autostartLink, PATH_MAX) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 09:07:41 +00:00
|
|
|
"cannot construct autostart link path");
|
|
|
|
vm->configFile[0] = '\0';
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 08:48:02 +00:00
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
return qemudSaveConfig(conn, driver, vm, def);
|
2007-02-23 08:48:02 +00:00
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
static int qemudSaveNetworkConfig(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network *network,
|
|
|
|
struct qemud_network_def *def) {
|
2007-02-14 16:02:40 +00:00
|
|
|
char *xml;
|
|
|
|
int fd, ret = -1;
|
|
|
|
int towrite;
|
2007-02-20 16:55:56 +00:00
|
|
|
int err;
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(xml = qemudGenerateNetworkXML(conn, driver, network, def))) {
|
2007-02-14 16:02:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if ((err = virFileMakePath(driver->networkConfigDir))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-20 16:55:56 +00:00
|
|
|
"cannot create config directory %s: %s",
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->networkConfigDir, strerror(err));
|
2007-02-14 16:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd = open(network->configFile,
|
|
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
|
|
S_IRUSR | S_IWUSR )) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-20 19:09:44 +00:00
|
|
|
"cannot create config file %s: %s",
|
|
|
|
network->configFile, strerror(errno));
|
2007-02-14 16:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
towrite = strlen(xml);
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(fd, xml, towrite) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-16 15:03:21 +00:00
|
|
|
"cannot write config file %s: %s",
|
2007-02-20 19:09:44 +00:00
|
|
|
network->configFile, strerror(errno));
|
2007-02-14 16:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (close(fd) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-16 15:03:21 +00:00
|
|
|
"cannot save config file %s: %s",
|
2007-02-20 19:09:44 +00:00
|
|
|
network->configFile, strerror(errno));
|
2007-02-14 16:02:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
free(xml);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
void qemudFreeNetworkDef(struct qemud_network_def *def) {
|
|
|
|
struct qemud_dhcp_range_def *range = def->ranges;
|
|
|
|
while (range) {
|
|
|
|
struct qemud_dhcp_range_def *next = range->next;
|
|
|
|
free(range);
|
|
|
|
range = next;
|
|
|
|
}
|
|
|
|
free(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
void qemudFreeNetwork(struct qemud_network *network) {
|
|
|
|
qemudFreeNetworkDef(network->def);
|
|
|
|
if (network->newDef)
|
|
|
|
qemudFreeNetworkDef(network->newDef);
|
|
|
|
free(network);
|
|
|
|
}
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
static int qemudParseBridgeXML(struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-02-15 16:00:16 +00:00
|
|
|
struct qemud_network_def *def,
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlNodePtr node) {
|
|
|
|
xmlChar *name, *stp, *delay;
|
|
|
|
|
|
|
|
name = xmlGetProp(node, BAD_CAST "name");
|
|
|
|
if (name != NULL) {
|
2007-02-15 16:00:16 +00:00
|
|
|
strncpy(def->bridge, (const char *)name, IF_NAMESIZE-1);
|
|
|
|
def->bridge[IF_NAMESIZE-1] = '\0';
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlFree(name);
|
|
|
|
name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
stp = xmlGetProp(node, BAD_CAST "stp");
|
|
|
|
if (stp != NULL) {
|
|
|
|
if (xmlStrEqual(stp, BAD_CAST "off")) {
|
2007-02-15 16:00:16 +00:00
|
|
|
def->disableSTP = 1;
|
2007-02-14 16:02:40 +00:00
|
|
|
}
|
|
|
|
xmlFree(stp);
|
|
|
|
stp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
delay = xmlGetProp(node, BAD_CAST "delay");
|
|
|
|
if (delay != NULL) {
|
2007-02-15 16:00:16 +00:00
|
|
|
def->forwardDelay = strtol((const char *)delay, NULL, 10);
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlFree(delay);
|
|
|
|
delay = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
static int qemudParseDhcpRangesXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-02-15 16:00:16 +00:00
|
|
|
struct qemud_network_def *def,
|
2007-02-14 16:05:29 +00:00
|
|
|
xmlNodePtr node) {
|
|
|
|
|
|
|
|
xmlNodePtr cur;
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
struct qemud_dhcp_range_def *range;
|
|
|
|
xmlChar *start, *end;
|
|
|
|
|
|
|
|
if (cur->type != XML_ELEMENT_NODE ||
|
|
|
|
!xmlStrEqual(cur->name, BAD_CAST "range")) {
|
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(range = calloc(1, sizeof(*range)))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "range");
|
2007-02-14 16:05:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = xmlGetProp(cur, BAD_CAST "start");
|
|
|
|
end = xmlGetProp(cur, BAD_CAST "end");
|
|
|
|
|
|
|
|
if (start && start[0] && end && end[0]) {
|
|
|
|
strncpy(range->start, (const char *)start, BR_INET_ADDR_MAXLEN-1);
|
|
|
|
range->start[BR_INET_ADDR_MAXLEN-1] = '\0';
|
|
|
|
|
|
|
|
strncpy(range->end, (const char *)end, BR_INET_ADDR_MAXLEN-1);
|
|
|
|
range->end[BR_INET_ADDR_MAXLEN-1] = '\0';
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
range->next = def->ranges;
|
|
|
|
def->ranges = range;
|
|
|
|
def->nranges++;
|
2007-02-14 16:05:29 +00:00
|
|
|
} else {
|
|
|
|
free(range);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start)
|
|
|
|
xmlFree(start);
|
|
|
|
if (end)
|
|
|
|
xmlFree(end);
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
static int qemudParseInetXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-02-15 16:00:16 +00:00
|
|
|
struct qemud_network_def *def,
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlNodePtr node) {
|
|
|
|
xmlChar *address, *netmask;
|
2007-02-14 16:05:29 +00:00
|
|
|
xmlNodePtr cur;
|
2007-02-14 16:02:40 +00:00
|
|
|
|
|
|
|
address = xmlGetProp(node, BAD_CAST "address");
|
|
|
|
if (address != NULL) {
|
2007-02-15 16:00:16 +00:00
|
|
|
strncpy(def->ipAddress, (const char *)address, BR_INET_ADDR_MAXLEN-1);
|
|
|
|
def->ipAddress[BR_INET_ADDR_MAXLEN-1] = '\0';
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlFree(address);
|
|
|
|
address = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
netmask = xmlGetProp(node, BAD_CAST "netmask");
|
|
|
|
if (netmask != NULL) {
|
2007-02-15 16:00:16 +00:00
|
|
|
strncpy(def->netmask, (const char *)netmask, BR_INET_ADDR_MAXLEN-1);
|
|
|
|
def->netmask[BR_INET_ADDR_MAXLEN-1] = '\0';
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlFree(netmask);
|
|
|
|
netmask = NULL;
|
|
|
|
}
|
|
|
|
|
2007-04-10 23:17:46 +00:00
|
|
|
if (def->ipAddress[0] && def->netmask[0]) {
|
|
|
|
struct in_addr inaddress, innetmask;
|
|
|
|
char *netaddr;
|
|
|
|
|
|
|
|
inet_aton((const char*)def->ipAddress, &inaddress);
|
|
|
|
inet_aton((const char*)def->netmask, &innetmask);
|
|
|
|
|
|
|
|
inaddress.s_addr &= innetmask.s_addr;
|
|
|
|
|
|
|
|
netaddr = inet_ntoa(inaddress);
|
|
|
|
|
|
|
|
snprintf(def->network,sizeof(def->network)-1,
|
|
|
|
"%s/%s", netaddr, (const char *)def->netmask);
|
|
|
|
}
|
|
|
|
|
2007-02-14 16:05:29 +00:00
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "dhcp") &&
|
2007-07-12 15:09:01 +00:00
|
|
|
!qemudParseDhcpRangesXML(conn, driver, def, cur))
|
2007-02-14 16:05:29 +00:00
|
|
|
return 0;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
2007-02-14 16:02:40 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
static struct qemud_network_def *qemudParseNetworkXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-15 16:00:16 +00:00
|
|
|
xmlDocPtr xml) {
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlNodePtr root = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
2007-03-13 22:43:22 +00:00
|
|
|
xmlXPathObjectPtr obj = NULL, tmp = NULL;
|
2007-02-15 16:00:16 +00:00
|
|
|
struct qemud_network_def *def;
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(def = calloc(1, sizeof(*def)))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "network_def");
|
2007-02-15 16:00:16 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-02-14 16:02:40 +00:00
|
|
|
|
|
|
|
/* Prepare parser / xpath context */
|
|
|
|
root = xmlDocGetRootElement(xml);
|
|
|
|
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "network"))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "incorrect root element");
|
2007-02-14 16:02:40 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xmlXPathContext");
|
2007-02-14 16:02:40 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract network name */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/network/name[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL);
|
2007-02-14 16:02:40 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "network name length too long");
|
2007-02-14 16:02:40 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-02-15 16:00:16 +00:00
|
|
|
strcpy(def->name, (const char *)obj->stringval);
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract network uuid */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "string(/network/uuid[1])", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2007-02-26 15:32:27 +00:00
|
|
|
int err;
|
2007-06-26 22:19:38 +00:00
|
|
|
if ((err = virUUIDGenerate(def->uuid))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-26 15:32:27 +00:00
|
|
|
"Failed to generate UUID: %s", strerror(err));
|
|
|
|
goto error;
|
|
|
|
}
|
2007-06-26 22:19:38 +00:00
|
|
|
} else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element");
|
2007-02-14 16:02:40 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
2007-04-10 23:17:46 +00:00
|
|
|
/* Parse bridge information */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
|
2007-06-26 22:13:21 +00:00
|
|
|
if (!qemudParseBridgeXML(driver, def, obj->nodesetval->nodeTab[0])) {
|
2007-04-10 23:17:46 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
/* Parse IP information */
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
|
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!qemudParseInetXML(conn, driver, def, obj->nodesetval->nodeTab[0])) {
|
2007-04-10 23:17:46 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
/* IPv4 forwarding setup */
|
2007-03-13 22:43:22 +00:00
|
|
|
obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) &&
|
|
|
|
obj->boolval) {
|
2007-04-10 23:17:46 +00:00
|
|
|
if (!def->ipAddress[0] ||
|
|
|
|
!def->netmask[0]) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-04-10 23:17:46 +00:00
|
|
|
"Forwarding requested, but no IPv4 address/netmask provided");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
def->forward = 1;
|
|
|
|
tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt);
|
|
|
|
if ((tmp != NULL) && (tmp->type == XPATH_STRING) &&
|
|
|
|
(tmp->stringval != NULL) && (tmp->stringval[0] != 0)) {
|
|
|
|
int len;
|
|
|
|
if ((len = xmlStrlen(tmp->stringval)) >= (BR_IFNAME_MAXLEN-1)) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-03-13 22:43:22 +00:00
|
|
|
"forward device name '%s' is too long",
|
|
|
|
(char*)tmp->stringval);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
strcpy(def->forwardDev, (char*)tmp->stringval);
|
|
|
|
} else {
|
|
|
|
def->forwardDev[0] = '\0';
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(tmp);
|
|
|
|
tmp = NULL;
|
|
|
|
} else {
|
|
|
|
def->forward = 0;
|
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
return def;
|
2007-02-14 16:02:40 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
/* XXX free all the stuff in the qemud_network struct, or leave it upto
|
|
|
|
the caller ? */
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
xmlXPathFreeObject(tmp);
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-02-15 16:00:16 +00:00
|
|
|
qemudFreeNetworkDef(def);
|
|
|
|
return NULL;
|
2007-02-14 16:02:40 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network_def *
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudParseNetworkDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
const char *xmlStr,
|
|
|
|
const char *displayName) {
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlDocPtr xml;
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network_def *def;
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "network.xml", NULL,
|
2007-02-14 16:02:40 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
|
2007-02-14 16:02:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
def = qemudParseNetworkXML(conn, driver, xml);
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-02-14 16:02:40 +00:00
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qemud_network *
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudAssignNetworkDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network_def *def) {
|
|
|
|
struct qemud_network *network;
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if ((network = qemudFindNetworkByName(driver, def->name))) {
|
2007-02-23 08:39:49 +00:00
|
|
|
if (!qemudIsActiveNetwork(network)) {
|
2007-02-15 16:00:16 +00:00
|
|
|
qemudFreeNetworkDef(network->def);
|
|
|
|
network->def = def;
|
|
|
|
} else {
|
|
|
|
if (network->newDef)
|
|
|
|
qemudFreeNetworkDef(network->newDef);
|
|
|
|
network->newDef = def;
|
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
return network;
|
2007-02-14 16:02:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
if (!(network = calloc(1, sizeof(*network)))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "network");
|
2007-02-23 08:48:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
network->def = def;
|
2007-06-26 22:13:21 +00:00
|
|
|
network->next = driver->networks;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->networks = network;
|
|
|
|
driver->ninactivenetworks++;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
|
|
|
return network;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudRemoveInactiveNetwork(struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network *network)
|
|
|
|
{
|
|
|
|
struct qemud_network *prev = NULL, *curr;
|
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
curr = driver->networks;
|
2007-02-23 08:48:02 +00:00
|
|
|
while (curr != network) {
|
|
|
|
prev = curr;
|
|
|
|
curr = curr->next;
|
2007-02-14 16:02:40 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
if (curr) {
|
|
|
|
if (prev)
|
|
|
|
prev->next = curr->next;
|
|
|
|
else
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->networks = curr->next;
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->ninactivenetworks--;
|
2007-02-15 16:00:16 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
qemudFreeNetwork(network);
|
2007-02-14 16:02:40 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
int
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudSaveNetworkDef(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network *network,
|
|
|
|
struct qemud_network_def *def) {
|
|
|
|
|
|
|
|
if (network->configFile[0] == '\0') {
|
|
|
|
int err;
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if ((err = virFileMakePath(driver->networkConfigDir))) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 08:48:02 +00:00
|
|
|
"cannot create config directory %s: %s",
|
2007-06-26 22:13:21 +00:00
|
|
|
driver->networkConfigDir, strerror(err));
|
2007-02-23 08:48:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (virFileBuildPath(driver->networkConfigDir, def->name, ".xml",
|
|
|
|
network->configFile, PATH_MAX) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 08:48:02 +00:00
|
|
|
"cannot construct config file path");
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 09:07:41 +00:00
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (virFileBuildPath(driver->networkAutostartDir, def->name, ".xml",
|
|
|
|
network->autostartLink, PATH_MAX) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
2007-02-23 09:07:41 +00:00
|
|
|
"cannot construct autostart link path");
|
|
|
|
network->configFile[0] = '\0';
|
|
|
|
return -1;
|
|
|
|
}
|
2007-02-23 08:48:02 +00:00
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
return qemudSaveNetworkConfig(conn, driver, network, def);
|
2007-02-23 08:48:02 +00:00
|
|
|
}
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-02-23 09:07:41 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
static struct qemud_vm *
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudLoadConfig(struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
const char *file,
|
|
|
|
const char *path,
|
2007-02-23 09:07:41 +00:00
|
|
|
const char *xml,
|
|
|
|
const char *autostartLink) {
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm_def *def;
|
|
|
|
struct qemud_vm *vm;
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(def = qemudParseVMDef(NULL, driver, xml, file))) {
|
2007-06-26 20:51:00 +00:00
|
|
|
virErrorPtr err = virGetLastError();
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN, _("Error parsing QEMU guest config '%s' : %s"),
|
|
|
|
path, (err ? err->message :
|
|
|
|
_("BUG: unknown error - please report it\n")));
|
2007-02-23 08:48:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN,
|
|
|
|
_("QEMU guest config filename '%s'"
|
|
|
|
" does not match guest name '%s'"),
|
2007-02-23 08:48:02 +00:00
|
|
|
path, def->name);
|
|
|
|
qemudFreeVMDef(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(vm = qemudAssignVMDef(NULL, driver, def))) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN,
|
|
|
|
_("Failed to load QEMU guest config '%s': out of memory"),
|
|
|
|
path);
|
2007-02-23 08:48:02 +00:00
|
|
|
qemudFreeVMDef(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(vm->configFile, path, PATH_MAX);
|
|
|
|
vm->configFile[PATH_MAX-1] = '\0';
|
|
|
|
|
2007-02-23 09:07:41 +00:00
|
|
|
strncpy(vm->autostartLink, autostartLink, PATH_MAX);
|
|
|
|
vm->autostartLink[PATH_MAX-1] = '\0';
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
vm->autostart = virFileLinkPointsTo(vm->autostartLink, vm->configFile);
|
2007-02-23 09:07:41 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct qemud_network *
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudLoadNetworkConfig(struct qemud_driver *driver,
|
2007-02-23 08:48:02 +00:00
|
|
|
const char *file,
|
|
|
|
const char *path,
|
2007-02-23 09:07:41 +00:00
|
|
|
const char *xml,
|
|
|
|
const char *autostartLink) {
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network_def *def;
|
|
|
|
struct qemud_network *network;
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(def = qemudParseNetworkDef(NULL, driver, xml, file))) {
|
2007-06-26 20:51:00 +00:00
|
|
|
virErrorPtr err = virGetLastError();
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN, _("Error parsing network config '%s' : %s"),
|
2007-06-26 20:51:00 +00:00
|
|
|
path, err->message);
|
2007-02-23 08:48:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN,
|
|
|
|
_("Network config filename '%s'"
|
|
|
|
" does not match network name '%s'"),
|
2007-02-23 08:48:02 +00:00
|
|
|
path, def->name);
|
|
|
|
qemudFreeNetworkDef(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
if (!(network = qemudAssignNetworkDef(NULL, driver, def))) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN,
|
|
|
|
_("Failed to load network config '%s': out of memory"), path);
|
2007-02-23 08:48:02 +00:00
|
|
|
qemudFreeNetworkDef(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(network->configFile, path, PATH_MAX);
|
|
|
|
network->configFile[PATH_MAX-1] = '\0';
|
|
|
|
|
2007-02-23 09:07:41 +00:00
|
|
|
strncpy(network->autostartLink, autostartLink, PATH_MAX);
|
|
|
|
network->autostartLink[PATH_MAX-1] = '\0';
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
network->autostart = virFileLinkPointsTo(network->autostartLink, network->configFile);
|
2007-02-23 09:07:41 +00:00
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
return network;
|
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-02-14 15:53:14 +00:00
|
|
|
static
|
2007-06-26 22:13:21 +00:00
|
|
|
int qemudScanConfigDir(struct qemud_driver *driver,
|
2007-02-14 16:02:40 +00:00
|
|
|
const char *configDir,
|
2007-02-23 09:07:41 +00:00
|
|
|
const char *autostartDir,
|
2007-02-14 16:02:40 +00:00
|
|
|
int isGuest) {
|
2007-02-14 01:40:09 +00:00
|
|
|
DIR *dir;
|
|
|
|
struct dirent *entry;
|
|
|
|
|
2007-02-14 15:53:14 +00:00
|
|
|
if (!(dir = opendir(configDir))) {
|
2007-02-14 01:40:09 +00:00
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_ERR, _("Failed to open dir '%s': %s"),
|
2007-02-16 18:30:55 +00:00
|
|
|
configDir, strerror(errno));
|
2007-02-14 01:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((entry = readdir(dir))) {
|
2008-01-07 15:21:33 +00:00
|
|
|
char *xml;
|
2007-02-23 08:48:02 +00:00
|
|
|
char path[PATH_MAX];
|
2007-02-23 09:07:41 +00:00
|
|
|
char autostartLink[PATH_MAX];
|
2007-02-23 08:48:02 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
if (entry->d_name[0] == '.')
|
|
|
|
continue;
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (!virFileHasSuffix(entry->d_name, ".xml"))
|
2007-02-23 14:33:37 +00:00
|
|
|
continue;
|
|
|
|
|
2007-12-03 14:30:46 +00:00
|
|
|
if (virFileBuildPath(configDir, entry->d_name, NULL, path, PATH_MAX) < 0) {
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
qemudLog(QEMUD_WARN, _("Config filename '%s/%s' is too long"),
|
2007-02-23 08:48:02 +00:00
|
|
|
configDir, entry->d_name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
|
|
|
if (virFileBuildPath(autostartDir, entry->d_name, NULL,
|
|
|
|
autostartLink, PATH_MAX) < 0) {
|
|
|
|
qemudLog(QEMUD_WARN, _("Autostart link path '%s/%s' is too long"),
|
2007-02-23 09:07:41 +00:00
|
|
|
autostartDir, entry->d_name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-01-07 15:21:33 +00:00
|
|
|
if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
continue;
|
|
|
|
|
2007-02-23 08:48:02 +00:00
|
|
|
if (isGuest)
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink);
|
2007-02-23 08:48:02 +00:00
|
|
|
else
|
2007-06-26 22:13:21 +00:00
|
|
|
qemudLoadNetworkConfig(driver, entry->d_name, path, xml, autostartLink);
|
2008-01-07 15:21:33 +00:00
|
|
|
|
|
|
|
free(xml);
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-02-14 15:53:14 +00:00
|
|
|
/* Scan for all guest and network config files */
|
2007-06-26 22:13:21 +00:00
|
|
|
int qemudScanConfigs(struct qemud_driver *driver) {
|
|
|
|
if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir, 1) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
return -1;
|
2007-02-23 09:11:52 +00:00
|
|
|
|
2007-06-26 22:13:21 +00:00
|
|
|
if (qemudScanConfigDir(driver, driver->networkConfigDir, driver->networkAutostartDir, 0) < 0)
|
2007-02-23 09:11:52 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
2007-02-14 15:53:14 +00:00
|
|
|
}
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/* Generate an XML document describing the guest's configuration */
|
2007-07-12 15:09:01 +00:00
|
|
|
char *qemudGenerateXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_vm *vm,
|
|
|
|
struct qemud_vm_def *def,
|
|
|
|
int live) {
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferPtr buf = 0;
|
2007-02-14 01:40:09 +00:00
|
|
|
unsigned char *uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2007-02-14 01:40:09 +00:00
|
|
|
struct qemud_vm_disk_def *disk;
|
|
|
|
struct qemud_vm_net_def *net;
|
2007-07-18 21:08:22 +00:00
|
|
|
struct qemud_vm_input_def *input;
|
2007-02-14 01:40:09 +00:00
|
|
|
const char *type = NULL;
|
|
|
|
int n;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
buf = virBufferNew (QEMUD_MAX_XML_LEN);
|
2007-03-15 17:24:56 +00:00
|
|
|
if (!buf)
|
2007-02-26 14:21:21 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
switch (def->virtType) {
|
2007-02-14 01:40:09 +00:00
|
|
|
case QEMUD_VIRT_QEMU:
|
|
|
|
type = "qemu";
|
|
|
|
break;
|
|
|
|
case QEMUD_VIRT_KQEMU:
|
|
|
|
type = "kqemu";
|
|
|
|
break;
|
|
|
|
case QEMUD_VIRT_KVM:
|
|
|
|
type = "kvm";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!type) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unexpected domain type %d", def->virtType);
|
2007-02-14 01:40:09 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2007-02-23 08:39:49 +00:00
|
|
|
if (qemudIsActiveVM(vm) && live) {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, "<domain type='%s' id='%d'>\n", type, vm->id) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
} else {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, "<domain type='%s'>\n", type) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <name>%s</name>\n", def->name) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
uuid = def->uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
if (virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2008-03-19 14:32:50 +00:00
|
|
|
if (virBufferVSprintf(buf, " <memory>%lu</memory>\n", def->maxmem) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2008-03-19 14:32:50 +00:00
|
|
|
if (virBufferVSprintf(buf, " <currentMemory>%lu</currentMemory>\n", def->memory) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <vcpu>%d</vcpu>\n", def->vcpus) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <os>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->virtType == QEMUD_VIRT_QEMU) {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <type arch='%s' machine='%s'>%s</type>\n",
|
2007-02-14 17:05:55 +00:00
|
|
|
def->os.arch, def->os.machine, def->os.type) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
} else {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <type>%s</type>\n", def->os.type) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->os.kernel[0])
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <kernel>%s</kernel>\n", def->os.kernel) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->os.initrd[0])
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <initrd>%s</initrd>\n", def->os.initrd) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->os.cmdline[0])
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <cmdline>%s</cmdline>\n", def->os.cmdline) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
for (n = 0 ; n < def->os.nBootDevs ; n++) {
|
2007-02-14 01:40:09 +00:00
|
|
|
const char *boottype = "hd";
|
2007-02-14 17:05:55 +00:00
|
|
|
switch (def->os.bootDevs[n]) {
|
2007-02-14 01:40:09 +00:00
|
|
|
case QEMUD_BOOT_FLOPPY:
|
|
|
|
boottype = "fd";
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_DISK:
|
|
|
|
boottype = "hd";
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_CDROM:
|
|
|
|
boottype = "cdrom";
|
|
|
|
break;
|
|
|
|
case QEMUD_BOOT_NET:
|
2007-09-13 22:06:54 +00:00
|
|
|
boottype = "network";
|
2007-02-14 01:40:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <boot dev='%s'/>\n", boottype) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " </os>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 21:47:59 +00:00
|
|
|
if (def->features & QEMUD_FEATURE_ACPI) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <features>\n") < 0)
|
2007-02-14 21:47:59 +00:00
|
|
|
goto no_memory;
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <acpi/>\n") < 0)
|
2007-02-14 21:47:59 +00:00
|
|
|
goto no_memory;
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " </features>\n") < 0)
|
2007-02-14 21:47:59 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
2007-07-16 21:30:30 +00:00
|
|
|
virBufferVSprintf(buf, " <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc");
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <on_poweroff>destroy</on_poweroff>\n") < 0)
|
2007-05-03 16:10:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
if (def->noReboot) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <on_reboot>destroy</on_reboot>\n") < 0)
|
2007-05-03 16:10:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
} else {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <on_reboot>restart</on_reboot>\n") < 0)
|
2007-05-03 16:10:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <on_crash>destroy</on_crash>\n") < 0)
|
2007-05-03 16:10:40 +00:00
|
|
|
goto no_memory;
|
2007-02-14 21:47:59 +00:00
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <devices>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <emulator>%s</emulator>\n", def->os.binary) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
disk = def->disks;
|
2007-02-14 01:40:09 +00:00
|
|
|
while (disk) {
|
|
|
|
const char *types[] = {
|
|
|
|
"block",
|
|
|
|
"file",
|
|
|
|
};
|
|
|
|
const char *typeAttrs[] = {
|
|
|
|
"dev",
|
|
|
|
"file",
|
|
|
|
};
|
|
|
|
const char *devices[] = {
|
|
|
|
"disk",
|
|
|
|
"cdrom",
|
|
|
|
"floppy",
|
|
|
|
};
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <disk type='%s' device='%s'>\n",
|
2007-02-14 01:40:09 +00:00
|
|
|
types[disk->type], devices[disk->device]) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2008-03-13 09:17:45 +00:00
|
|
|
if (disk->src[0])
|
|
|
|
if (virBufferVSprintf(buf, " <source %s='%s'/>\n",
|
|
|
|
typeAttrs[disk->type], disk->src) < 0)
|
|
|
|
goto no_memory;
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <target dev='%s'/>\n", disk->dst) < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (disk->readonly)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <readonly/>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
if (virBufferAddLit(buf, " </disk>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
disk = disk->next;
|
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
net = def->nets;
|
2007-02-14 15:51:53 +00:00
|
|
|
while (net) {
|
2007-02-14 01:40:09 +00:00
|
|
|
const char *types[] = {
|
|
|
|
"user",
|
2007-03-13 22:43:22 +00:00
|
|
|
"ethernet",
|
2007-02-14 01:40:09 +00:00
|
|
|
"server",
|
|
|
|
"client",
|
|
|
|
"mcast",
|
2007-02-15 19:08:08 +00:00
|
|
|
"network",
|
2007-03-13 22:43:22 +00:00
|
|
|
"bridge",
|
2007-02-14 01:40:09 +00:00
|
|
|
};
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <interface type='%s'>\n",
|
2007-02-14 01:40:09 +00:00
|
|
|
types[net->type]) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
|
2007-02-14 01:40:09 +00:00
|
|
|
net->mac[0], net->mac[1], net->mac[2],
|
|
|
|
net->mac[3], net->mac[4], net->mac[5]) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
switch (net->type) {
|
|
|
|
case QEMUD_NET_NETWORK:
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <source network='%s'/>\n", net->dst.network.name) < 0)
|
2007-02-14 16:09:37 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
if (net->dst.network.ifname[0] != '\0') {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.network.ifname) < 0)
|
2007-03-13 22:43:22 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
break;
|
2007-02-14 16:09:37 +00:00
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
case QEMUD_NET_ETHERNET:
|
|
|
|
if (net->dst.ethernet.ifname[0] != '\0') {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname) < 0)
|
2007-03-13 22:43:22 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
if (net->dst.ethernet.script[0] != '\0') {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <script path='%s'/>\n", net->dst.ethernet.script) < 0)
|
2007-03-13 22:43:22 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_NET_BRIDGE:
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <source bridge='%s'/>\n", net->dst.bridge.brname) < 0)
|
2007-02-14 16:09:37 +00:00
|
|
|
goto no_memory;
|
2007-03-13 22:43:22 +00:00
|
|
|
if (net->dst.bridge.ifname[0] != '\0') {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <target dev='%s'/>\n", net->dst.bridge.ifname) < 0)
|
2007-03-13 22:43:22 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_NET_SERVER:
|
|
|
|
case QEMUD_NET_CLIENT:
|
|
|
|
case QEMUD_NET_MCAST:
|
|
|
|
if (net->dst.socket.address[0] != '\0') {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <source address='%s' port='%d'/>\n",
|
2007-03-13 22:43:22 +00:00
|
|
|
net->dst.socket.address, net->dst.socket.port) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
} else {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <source port='%d'/>\n",
|
2007-03-13 22:43:22 +00:00
|
|
|
net->dst.socket.port) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-02-14 16:09:37 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
if (virBufferAddLit(buf, " </interface>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-14 15:51:53 +00:00
|
|
|
net = net->next;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
2007-07-18 21:08:22 +00:00
|
|
|
input = def->inputs;
|
|
|
|
while (input) {
|
|
|
|
if (input->bus != QEMU_INPUT_BUS_PS2 &&
|
|
|
|
virBufferVSprintf(buf, " <input type='%s' bus='usb'/>\n",
|
|
|
|
input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet") < 0)
|
|
|
|
goto no_memory;
|
|
|
|
input = input->next;
|
|
|
|
}
|
|
|
|
/* If graphics is enable, add implicit mouse */
|
|
|
|
if (def->graphicsType != QEMUD_GRAPHICS_NONE)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <input type='mouse' bus='ps2'/>\n") < 0)
|
2007-07-18 21:08:22 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 19:07:06 +00:00
|
|
|
switch (def->graphicsType) {
|
|
|
|
case QEMUD_GRAPHICS_VNC:
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <graphics type='vnc'") < 0)
|
2007-02-15 19:07:06 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (def->vncPort &&
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferVSprintf(buf, " port='%d'",
|
2007-02-23 08:39:49 +00:00
|
|
|
qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort) < 0)
|
2007-02-15 19:07:06 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-07-24 14:30:05 +00:00
|
|
|
if (def->vncListen[0] &&
|
|
|
|
virBufferVSprintf(buf, " listen='%s'",
|
|
|
|
def->vncListen) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
2008-01-15 15:18:33 +00:00
|
|
|
if (def->keymap &&
|
|
|
|
virBufferVSprintf(buf, " keymap='%s'",
|
|
|
|
def->keymap) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, "/>\n") < 0)
|
2007-02-15 19:07:06 +00:00
|
|
|
goto no_memory;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_GRAPHICS_SDL:
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <graphics type='sdl'/>\n") < 0)
|
2007-02-15 19:07:06 +00:00
|
|
|
goto no_memory;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMUD_GRAPHICS_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-02-14 17:05:55 +00:00
|
|
|
if (def->graphicsType == QEMUD_GRAPHICS_VNC) {
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " </devices>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, "</domain>\n") < 0)
|
2007-02-14 01:40:09 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
return virBufferContentAndFree (buf);
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
no_memory:
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xml");
|
2007-02-14 01:40:09 +00:00
|
|
|
cleanup:
|
2007-06-26 22:21:22 +00:00
|
|
|
if (buf) virBufferFree (buf);
|
2007-02-14 01:40:09 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
char *qemudGenerateNetworkXML(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-04-10 23:17:46 +00:00
|
|
|
struct qemud_network *network,
|
2007-02-23 08:48:02 +00:00
|
|
|
struct qemud_network_def *def) {
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferPtr buf = 0;
|
2007-02-14 16:02:40 +00:00
|
|
|
unsigned char *uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2007-02-14 16:02:40 +00:00
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
buf = virBufferNew (QEMUD_MAX_XML_LEN);
|
2007-03-15 17:24:56 +00:00
|
|
|
if (!buf)
|
2007-02-26 14:21:21 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
if (virBufferAddLit(buf, "<network>\n") < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <name>%s</name>\n", def->name) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
uuid = def->uuid;
|
2007-08-09 20:19:12 +00:00
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
if (virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-03-13 22:43:22 +00:00
|
|
|
if (def->forward) {
|
|
|
|
if (def->forwardDev[0]) {
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferVSprintf(buf, " <forward dev='%s'/>\n",
|
2007-03-13 22:43:22 +00:00
|
|
|
def->forwardDev);
|
|
|
|
} else {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, " <forward/>\n");
|
2007-03-13 22:43:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, " <bridge");
|
2007-04-10 23:17:46 +00:00
|
|
|
if (qemudIsActiveNetwork(network)) {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " name='%s'", network->bridge) < 0)
|
2007-04-10 23:17:46 +00:00
|
|
|
goto no_memory;
|
|
|
|
} else if (def->bridge[0]) {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " name='%s'", def->bridge) < 0)
|
2007-04-10 23:17:46 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " stp='%s' forwardDelay='%d' />\n",
|
2007-04-10 23:17:46 +00:00
|
|
|
def->disableSTP ? "off" : "on",
|
|
|
|
def->forwardDelay) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
if (def->ipAddress[0] || def->netmask[0]) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <ip") < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
if (def->ipAddress[0] &&
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferVSprintf(buf, " address='%s'", def->ipAddress) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
if (def->netmask[0] &&
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferVSprintf(buf, " netmask='%s'", def->netmask) < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, ">\n") < 0)
|
2007-02-14 16:05:29 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-02-15 16:00:16 +00:00
|
|
|
if (def->ranges) {
|
|
|
|
struct qemud_dhcp_range_def *range = def->ranges;
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " <dhcp>\n") < 0)
|
2007-02-14 16:05:29 +00:00
|
|
|
goto no_memory;
|
|
|
|
while (range) {
|
2007-06-26 22:21:22 +00:00
|
|
|
if (virBufferVSprintf(buf, " <range start='%s' end='%s' />\n",
|
2007-02-14 16:05:29 +00:00
|
|
|
range->start, range->end) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
range = range->next;
|
|
|
|
}
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " </dhcp>\n") < 0)
|
2007-02-14 16:05:29 +00:00
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, " </ip>\n") < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
2007-02-14 01:40:09 +00:00
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
if (virBufferAddLit(buf, "</network>\n") < 0)
|
2007-02-14 16:02:40 +00:00
|
|
|
goto no_memory;
|
|
|
|
|
2007-06-26 22:21:22 +00:00
|
|
|
return virBufferContentAndFree (buf);
|
2007-02-14 16:02:40 +00:00
|
|
|
|
|
|
|
no_memory:
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "xml");
|
2007-06-26 22:21:22 +00:00
|
|
|
if (buf) virBufferFree (buf);
|
2007-02-14 16:02:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-12 15:09:01 +00:00
|
|
|
int qemudDeleteConfig(virConnectPtr conn,
|
|
|
|
struct qemud_driver *driver ATTRIBUTE_UNUSED,
|
2007-02-14 16:02:40 +00:00
|
|
|
const char *configFile,
|
|
|
|
const char *name) {
|
|
|
|
if (!configFile[0]) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "no config file for %s", name);
|
2007-02-14 01:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-02-14 16:02:40 +00:00
|
|
|
if (unlink(configFile) < 0) {
|
2007-07-12 15:09:01 +00:00
|
|
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot remove config for %s", name);
|
2007-02-14 16:02:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-02-14 15:58:21 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-11-26 11:50:16 +00:00
|
|
|
#endif /* WITH_QEMU */
|
2007-02-14 01:40:09 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* c-indent-level: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 4
|
|
|
|
* End:
|
|
|
|
*/
|