#include <arpa/inet.h>
#include <sys/utsname.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/uri.h>
-
#if HAVE_NUMACTL
#include <numa.h>
#endif
-#include "internal.h"
#include "qemu_conf.h"
#include "uuid.h"
#include "buf.h"
#include "memory.h"
#include "verify.h"
#include "c-ctype.h"
-#include "xml.h"
+
+VIR_ENUM_DECL(virDomainDiskQEMUBus)
+VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
+ "ide",
+ "floppy",
+ "scsi",
+ "virtio",
+ "xen")
+
#define qemudLog(level, msg...) fprintf(stderr, msg)
virNetworkPtr net,
int code, const char *fmt, ...) {
va_list args;
- char errorMessage[QEMUD_MAX_ERROR_LEN];
+ char errorMessage[1024];
const char *virerr;
if (fmt) {
va_start(args, fmt);
- vsnprintf(errorMessage, QEMUD_MAX_ERROR_LEN-1, fmt, args);
+ vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args);
va_end(args);
} else {
errorMessage[0] = '\0';
virConfValuePtr p;
/* Setup 2 critical defaults */
- strcpy(driver->vncListen, "127.0.0.1");
+ if (!(driver->vncListen = strdup("127.0.0.1"))) {
+ qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+ "%s", _("failed to allocate vncListen"));
+ return -1;
+ }
if (!(driver->vncTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-vnc"))) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate vncTLSx509certdir"));
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';
+ if (!(driver->vncListen = strdup(p->str))) {
+ qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_MEMORY,
+ "%s", _("failed to allocate vncTLSx509certdir"));
+ virConfFree(conf);
+ return -1;
+ }
}
virConfFree (conf);
return 0;
}
-
-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) {
- if (!memcmp(vm->def->uuid, uuid, VIR_UUID_BUFLEN))
- 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 (STREQ(vm->def->name, name))
- return vm;
- vm = vm->next;
- }
-
- return NULL;
-}
-
-
-/* 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;
- struct qemud_vm_input_def *input = def->inputs;
- struct qemud_vm_chr_def *serial = def->serials;
- struct qemud_vm_chr_def *parallel = def->parallels;
- struct qemud_vm_sound_def *sound = def->sounds;
-
- while (disk) {
- struct qemud_vm_disk_def *prev = disk;
- disk = disk->next;
- VIR_FREE(prev);
- }
- while (net) {
- struct qemud_vm_net_def *prev = net;
- net = net->next;
- VIR_FREE(prev);
- }
- while (input) {
- struct qemud_vm_input_def *prev = input;
- input = input->next;
- VIR_FREE(prev);
- }
- while (serial) {
- struct qemud_vm_chr_def *prev = serial;
- serial = serial->next;
- VIR_FREE(prev);
- }
- while (parallel) {
- struct qemud_vm_chr_def *prev = parallel;
- parallel = parallel->next;
- VIR_FREE(prev);
- }
- while (sound) {
- struct qemud_vm_sound_def *prev = sound;
- sound = sound->next;
- VIR_FREE(prev);
- }
- xmlFree(def->keymap);
- VIR_FREE(def);
-}
-
-void qemudFreeVM(struct qemud_vm *vm) {
- qemudFreeVMDef(vm->def);
- if (vm->newDef)
- qemudFreeVMDef(vm->newDef);
- VIR_FREE(vm);
-}
-
-
/* The list of possible machine types for various architectures,
as supported by QEMU - taken from 'qemu -M ?' for each arch */
static const char *const arch_info_hvm_x86_machines[] = {
}
-static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
+int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
pid_t child;
int newstdout[2];
- *flags = 0;
- *version = 0;
+ if (flags)
+ *flags = 0;
+ if (version)
+ *version = 0;
if (pipe(newstdout) < 0) {
return -1;
char help[8192]; /* Ought to be enough to hold QEMU help screen */
int got = 0, ret = -1;
int major, minor, micro;
+ int ver;
if (close(newstdout[1]) < 0)
goto cleanup2;
goto cleanup2;
}
- *version = (major * 1000 * 1000) + (minor * 1000) + micro;
- if (strstr(help, "-no-kqemu"))
- *flags |= QEMUD_CMD_FLAG_KQEMU;
- if (strstr(help, "-no-reboot"))
- *flags |= QEMUD_CMD_FLAG_NO_REBOOT;
- if (strstr(help, "-name"))
- *flags |= QEMUD_CMD_FLAG_NAME;
- if (strstr(help, "-drive"))
- *flags |= QEMUD_CMD_FLAG_DRIVE;
- if (strstr(help, "boot=on"))
- *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
- if (*version >= 9000)
- *flags |= QEMUD_CMD_FLAG_VNC_COLON;
+ ver = (major * 1000 * 1000) + (minor * 1000) + micro;
+ if (version)
+ *version = ver;
+ if (flags) {
+ if (strstr(help, "-no-kqemu"))
+ *flags |= QEMUD_CMD_FLAG_KQEMU;
+ if (strstr(help, "-no-reboot"))
+ *flags |= QEMUD_CMD_FLAG_NO_REBOOT;
+ if (strstr(help, "-name"))
+ *flags |= QEMUD_CMD_FLAG_NAME;
+ if (strstr(help, "-drive"))
+ *flags |= QEMUD_CMD_FLAG_DRIVE;
+ if (strstr(help, "boot=on"))
+ *flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
+ if (ver >= 9000)
+ *flags |= QEMUD_CMD_FLAG_VNC_COLON;
+ }
ret = 0;
qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d",
if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
"hvm",
- "i686",
- "qemu")) == NULL)
- return -1;
-
- if (stat(binary, &sb) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Cannot find QEMU binary %s: %s"), binary,
- strerror(errno));
- return -1;
- }
-
- if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-/* Converts def->virtType to applicable string type
- * @param type integer virt type
- * @return string type on success, NULL on fail
- */
-const char * qemudVirtTypeToString(int type) {
- switch (type) {
- case QEMUD_VIRT_QEMU:
- return "qemu";
- case QEMUD_VIRT_KQEMU:
- return "kqemu";
- case QEMUD_VIRT_KVM:
- return "kvm";
- }
- return NULL;
-}
-
-/* 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) {
- xmlNodePtr cur;
- xmlChar *device = NULL;
- xmlChar *source = NULL;
- xmlChar *target = NULL;
- xmlChar *type = NULL;
- xmlChar *bus = 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");
-
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((source == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-
- 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");
- bus = xmlGetProp(cur, BAD_CAST "bus");
- } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
- disk->readonly = 1;
- }
- }
- cur = cur->next;
- }
-
- if (source == NULL) {
- /* 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;
- }
- }
-
- if (target == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_TARGET, source ? "%s" : NULL, source);
- goto error;
- }
-
- if (device &&
- STREQ((const char *)device, "floppy") &&
- STRNEQ((const char *)target, "fda") &&
- STRNEQ((const char *)target, "fdb")) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid floppy device name: %s"), target);
- goto error;
- }
-
- if (device &&
- STREQ((const char *)device, "cdrom") &&
- STRNEQ((const char *)target, "hdc")) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid cdrom device name: %s"), target);
- goto error;
- }
-
- if (device &&
- STREQ((const char *)device, "cdrom"))
- disk->readonly = 1;
-
- if ((!device || STREQ((const char *)device, "disk")) &&
- !STRPREFIX((const char *)target, "hd") &&
- !STRPREFIX((const char *)target, "sd") &&
- !STRPREFIX((const char *)target, "vd") &&
- !STRPREFIX((const char *)target, "xvd")) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid harddisk device name: %s"), target);
- goto error;
- }
-
- strncpy(disk->src, (source ? (const char *) source : "\0"), NAME_MAX-1);
- 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 (STREQ((const char *)device, "disk"))
- disk->device = QEMUD_DISK_DISK;
- else if (STREQ((const char *)device, "cdrom"))
- disk->device = QEMUD_DISK_CDROM;
- else if (STREQ((const char *)device, "floppy"))
- disk->device = QEMUD_DISK_FLOPPY;
- else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid device type: %s"), device);
- goto error;
- }
-
- if (!bus) {
- if (disk->device == QEMUD_DISK_FLOPPY) {
- disk->bus = QEMUD_DISK_BUS_FDC;
- } else {
- if (STRPREFIX((const char *)target, "hd"))
- disk->bus = QEMUD_DISK_BUS_IDE;
- else if (STRPREFIX((const char *)target, "sd"))
- disk->bus = QEMUD_DISK_BUS_SCSI;
- else if (STRPREFIX((const char *)target, "vd"))
- disk->bus = QEMUD_DISK_BUS_VIRTIO;
- else if (STRPREFIX((const char *)target, "xvd"))
- disk->bus = QEMUD_DISK_BUS_XEN;
- else
- disk->bus = QEMUD_DISK_BUS_IDE;
- }
- } else if (STREQ((const char *)bus, "ide"))
- disk->bus = QEMUD_DISK_BUS_IDE;
- else if (STREQ((const char *)bus, "fdc"))
- disk->bus = QEMUD_DISK_BUS_FDC;
- else if (STREQ((const char *)bus, "scsi"))
- disk->bus = QEMUD_DISK_BUS_SCSI;
- else if (STREQ((const char *)bus, "virtio"))
- disk->bus = QEMUD_DISK_BUS_VIRTIO;
- else if (STREQ((const char *)bus, "xen"))
- disk->bus = QEMUD_DISK_BUS_XEN;
- else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid bus type: %s"), bus);
- goto error;
- }
-
- if (disk->device == QEMUD_DISK_FLOPPY &&
- disk->bus != QEMUD_DISK_BUS_FDC) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Invalid bus type '%s' for floppy disk"), bus);
- goto error;
- }
-
- xmlFree(device);
- xmlFree(target);
- xmlFree(source);
- xmlFree(bus);
-
- return 0;
-
- error:
- xmlFree(bus);
- xmlFree(type);
- xmlFree(target);
- xmlFree(source);
- xmlFree(device);
- return -1;
-}
-
-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)));
-}
-
-
-/* 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) {
- xmlNodePtr cur;
- xmlChar *macaddr = NULL;
- xmlChar *type = NULL;
- xmlChar *network = NULL;
- xmlChar *bridge = NULL;
- xmlChar *ifname = NULL;
- xmlChar *script = NULL;
- xmlChar *address = NULL;
- xmlChar *port = NULL;
- xmlChar *model = NULL;
-
- 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;
- else if (xmlStrEqual(type, BAD_CAST "ethernet"))
- net->type = QEMUD_NET_ETHERNET;
- 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;
- else if (xmlStrEqual(type, BAD_CAST "network"))
- net->type = QEMUD_NET_NETWORK;
- else if (xmlStrEqual(type, BAD_CAST "bridge"))
- net->type = QEMUD_NET_BRIDGE;
- 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");
- } else if ((network == NULL) &&
- (net->type == QEMUD_NET_NETWORK) &&
- (xmlStrEqual(cur->name, BAD_CAST "source"))) {
- network = xmlGetProp(cur, BAD_CAST "network");
- } else if ((network == NULL) &&
- (net->type == QEMUD_NET_BRIDGE) &&
- (xmlStrEqual(cur->name, BAD_CAST "source"))) {
- bridge = xmlGetProp(cur, BAD_CAST "bridge");
- } 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");
- if (STRPREFIX((const char*)ifname, "vnet")) {
- /* An auto-generated target name, blank it out */
- xmlFree(ifname);
- ifname = NULL;
- }
- } else if ((script == NULL) &&
- (net->type == QEMUD_NET_ETHERNET) &&
- xmlStrEqual(cur->name, BAD_CAST "script")) {
- script = xmlGetProp(cur, BAD_CAST "path");
- } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
- model = xmlGetProp (cur, BAD_CAST "type");
- }
- }
- cur = cur->next;
- }
-
- if (macaddr) {
- unsigned int mac[6];
- sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
- (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];
-
- xmlFree(macaddr);
- macaddr = NULL;
- } else {
- qemudRandomMAC(net);
- }
-
- if (net->type == QEMUD_NET_NETWORK) {
- int len;
-
- if (network == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("No <source> 'network' attribute specified with <interface type='network'/>"));
- goto error;
- } else if ((len = xmlStrlen(network)) >= (QEMUD_MAX_NAME_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Network name '%s' too long"), network);
- goto error;
- } else {
- strncpy(net->dst.network.name, (char *)network, len);
- net->dst.network.name[len] = '\0';
- }
-
- if (network) {
- xmlFree(network);
- network = NULL;
- }
-
- if (ifname != NULL) {
- if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("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;
-
- if (script != NULL) {
- if ((len = xmlStrlen(script)) >= (PATH_MAX-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("TAP interface name '%s' is too long"),
- ifname);
- goto error;
- } else {
- strncpy(net->dst.ethernet.ifname, (char *)ifname, len);
- net->dst.ethernet.ifname[len] = '\0';
- }
- xmlFree(ifname);
- }
- } else if (net->type == QEMUD_NET_BRIDGE) {
- int len;
-
- if (bridge == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("No <source> 'dev' attribute specified with <interface type='bridge'/>"));
- goto error;
- } else if ((len = xmlStrlen(bridge)) >= (BR_IFNAME_MAXLEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("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';
- }
-
- xmlFree(bridge);
- bridge = NULL;
-
- if (ifname != NULL) {
- if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("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) {
- int len = 0;
- char *ret;
-
- if (port == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("No <source> 'port' attribute specified with socket interface"));
- goto error;
- }
- if (!(net->dst.socket.port = strtol((char*)port, &ret, 10)) &&
- ret == (char*)port) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("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) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("No <source> 'address' attribute specified with socket interface"));
- goto error;
- }
- } else if ((len = xmlStrlen(address)) >= (BR_INET_ADDR_MAXLEN)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("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);
- }
-
- /* NIC model (see -net nic,model=?). We only check that it looks
- * reasonable, not that it is a supported NIC type. FWIW kvm
- * supports these types as of April 2008:
- * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
- */
- if (model != NULL) {
- int i, len;
-
- len = xmlStrlen (model);
- if (len >= QEMUD_MODEL_MAX_LEN) {
- qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
- _("Model name '%s' is too long"), model);
- goto error;
- }
- for (i = 0; i < len; ++i) {
- int char_ok = c_isalnum(model[i]) || model[i] == '_';
- if (!char_ok) {
- qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s",
- _("Model name contains invalid characters"));
- goto error;
- }
- }
- strncpy (net->model, (const char*) model, len);
- net->model[len] = '\0';
-
- xmlFree (model);
- model = NULL;
- } else
- net->model[0] = '\0';
-
- return 0;
-
- error:
- xmlFree(network);
- xmlFree(address);
- xmlFree(port);
- xmlFree(ifname);
- xmlFree(script);
- xmlFree(bridge);
- xmlFree(model);
- return -1;
-}
-
-
-/* Parse the XML definition for a character device
- * @param net pre-allocated & zero'd net record
- * @param node XML nodeset to parse for net definition
- * @return 0 on success, -1 on failure
- *
- * The XML we're dealing with looks like
- *
- * <serial type="pty">
- * <source path="/dev/pts/3"/>
- * <target port="1"/>
- * </serial>
- *
- * <serial type="dev">
- * <source path="/dev/ttyS0"/>
- * <target port="1"/>
- * </serial>
- *
- * <serial type="tcp">
- * <source mode="connect" host="0.0.0.0" service="2445"/>
- * <target port="1"/>
- * </serial>
- *
- * <serial type="tcp">
- * <source mode="bind" host="0.0.0.0" service="2445"/>
- * <target port="1"/>
- * </serial>
- *
- * <serial type="udp">
- * <source mode="bind" host="0.0.0.0" service="2445"/>
- * <source mode="connect" host="0.0.0.0" service="2445"/>
- * <target port="1"/>
- * </serial>
- *
- * <serial type="unix">
- * <source mode="bind" path="/tmp/foo"/>
- * <target port="1"/>
- * </serial>
- *
- */
-static int qemudParseCharXML(virConnectPtr conn,
- struct qemud_vm_chr_def *chr,
- int portNum,
- xmlNodePtr node) {
- xmlNodePtr cur;
- xmlChar *type = NULL;
- xmlChar *bindHost = NULL;
- xmlChar *bindService = NULL;
- xmlChar *connectHost = NULL;
- xmlChar *connectService = NULL;
- xmlChar *path = NULL;
- xmlChar *mode = NULL;
- xmlChar *protocol = NULL;
- int ret = -1;
-
- chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
- type = xmlGetProp(node, BAD_CAST "type");
- if (type != NULL) {
- if (xmlStrEqual(type, BAD_CAST "null"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
- else if (xmlStrEqual(type, BAD_CAST "vc"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_VC;
- else if (xmlStrEqual(type, BAD_CAST "pty"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
- else if (xmlStrEqual(type, BAD_CAST "dev"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_DEV;
- else if (xmlStrEqual(type, BAD_CAST "file"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_FILE;
- else if (xmlStrEqual(type, BAD_CAST "pipe"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_PIPE;
- else if (xmlStrEqual(type, BAD_CAST "stdio"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_STDIO;
- else if (xmlStrEqual(type, BAD_CAST "udp"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_UDP;
- else if (xmlStrEqual(type, BAD_CAST "tcp"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_TCP;
- else if (xmlStrEqual(type, BAD_CAST "unix"))
- chr->srcType = QEMUD_CHR_SRC_TYPE_UNIX;
- else
- chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
- }
-
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if (xmlStrEqual(cur->name, BAD_CAST "source")) {
- if (mode == NULL)
- mode = xmlGetProp(cur, BAD_CAST "mode");
-
- switch (chr->srcType) {
- case QEMUD_CHR_SRC_TYPE_PTY:
- case QEMUD_CHR_SRC_TYPE_DEV:
- case QEMUD_CHR_SRC_TYPE_FILE:
- case QEMUD_CHR_SRC_TYPE_PIPE:
- case QEMUD_CHR_SRC_TYPE_UNIX:
- if (path == NULL)
- path = xmlGetProp(cur, BAD_CAST "path");
-
- break;
-
- case QEMUD_CHR_SRC_TYPE_UDP:
- case QEMUD_CHR_SRC_TYPE_TCP:
- if (mode == NULL ||
- STREQ((const char *)mode, "connect")) {
-
- if (connectHost == NULL)
- connectHost = xmlGetProp(cur, BAD_CAST "host");
- if (connectService == NULL)
- connectService = xmlGetProp(cur, BAD_CAST "service");
- } else {
- if (bindHost == NULL)
- bindHost = xmlGetProp(cur, BAD_CAST "host");
- if (bindService == NULL)
- bindService = xmlGetProp(cur, BAD_CAST "service");
- }
-
- if (chr->srcType == QEMUD_CHR_SRC_TYPE_UDP) {
- xmlFree(mode);
- mode = NULL;
- }
- }
- } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
- if (protocol == NULL)
- protocol = xmlGetProp(cur, BAD_CAST "type");
- }
- }
- cur = cur->next;
- }
-
-
- chr->dstPort = portNum;
-
- switch (chr->srcType) {
- case QEMUD_CHR_SRC_TYPE_NULL:
- /* Nada */
- break;
-
- case QEMUD_CHR_SRC_TYPE_VC:
- break;
-
- case QEMUD_CHR_SRC_TYPE_PTY:
- /* @path attribute is an output only property - pty is auto-allocted */
- break;
-
- case QEMUD_CHR_SRC_TYPE_DEV:
- case QEMUD_CHR_SRC_TYPE_FILE:
- case QEMUD_CHR_SRC_TYPE_PIPE:
- if (path == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source path attribute for char device"));
- goto cleanup;
- }
-
- strncpy(chr->srcData.file.path, (const char *)path,
- sizeof(chr->srcData.file.path));
- NUL_TERMINATE(chr->srcData.file.path);
- break;
-
- case QEMUD_CHR_SRC_TYPE_STDIO:
- /* Nada */
- break;
-
- case QEMUD_CHR_SRC_TYPE_TCP:
- if (mode == NULL ||
- STREQ((const char *)mode, "connect")) {
- if (connectHost == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source host attribute for char device"));
- goto cleanup;
- }
- if (connectService == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source service attribute for char device"));
- goto cleanup;
- }
-
- strncpy(chr->srcData.tcp.host, (const char *)connectHost,
- sizeof(chr->srcData.tcp.host));
- NUL_TERMINATE(chr->srcData.tcp.host);
- strncpy(chr->srcData.tcp.service, (const char *)connectService,
- sizeof(chr->srcData.tcp.service));
- NUL_TERMINATE(chr->srcData.tcp.service);
-
- chr->srcData.tcp.listen = 0;
- } else {
- if (bindHost == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source host attribute for char device"));
- goto cleanup;
- }
- if (bindService == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source service attribute for char device"));
- goto cleanup;
- }
-
- strncpy(chr->srcData.tcp.host, (const char *)bindHost,
- sizeof(chr->srcData.tcp.host));
- NUL_TERMINATE(chr->srcData.tcp.host);
- strncpy(chr->srcData.tcp.service, (const char *)bindService,
- sizeof(chr->srcData.tcp.service));
- NUL_TERMINATE(chr->srcData.tcp.service);
-
- chr->srcData.tcp.listen = 1;
- }
- if (protocol != NULL &&
- STREQ((const char *)protocol, "telnet"))
- chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET;
- else
- chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_RAW;
- break;
-
- case QEMUD_CHR_SRC_TYPE_UDP:
- if (connectService == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source service attribute for char device"));
- goto cleanup;
- }
-
- if (connectHost != NULL) {
- strncpy(chr->srcData.udp.connectHost, (const char *)connectHost,
- sizeof(chr->srcData.udp.connectHost));
- NUL_TERMINATE(chr->srcData.udp.connectHost);
- }
- strncpy(chr->srcData.udp.connectService, (const char *)connectService,
- sizeof(chr->srcData.udp.connectService));
- NUL_TERMINATE(chr->srcData.udp.connectService);
-
- if (bindHost != NULL) {
- strncpy(chr->srcData.udp.bindHost, (const char *)bindHost,
- sizeof(chr->srcData.udp.bindHost));
- NUL_TERMINATE(chr->srcData.udp.bindHost);
- }
- if (bindService != NULL) {
- strncpy(chr->srcData.udp.bindService, (const char *)bindService,
- sizeof(chr->srcData.udp.bindService));
- NUL_TERMINATE(chr->srcData.udp.bindService);
- }
- break;
-
- case QEMUD_CHR_SRC_TYPE_UNIX:
- if (path == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("Missing source path attribute for char device"));
- goto cleanup;
- }
-
- if (mode != NULL &&
- STRNEQ((const char *)mode, "connect"))
- chr->srcData.nix.listen = 1;
- else
- chr->srcData.nix.listen = 0;
-
- strncpy(chr->srcData.nix.path, (const char *)path,
- sizeof(chr->srcData.nix.path));
- NUL_TERMINATE(chr->srcData.nix.path);
- break;
- }
-
- ret = 0;
-
-cleanup:
- xmlFree(mode);
- xmlFree(protocol);
- xmlFree(type);
- xmlFree(bindHost);
- xmlFree(bindService);
- xmlFree(connectHost);
- xmlFree(connectService);
- xmlFree(path);
-
- return ret;
-}
-
-
-static int qemudParseCharXMLDevices(virConnectPtr conn,
- xmlXPathContextPtr ctxt,
- const char *xpath,
- unsigned int *ndevs,
- struct qemud_vm_chr_def **devs)
-{
- xmlXPathObjectPtr obj;
- int i, ret = -1;
-
- obj = xmlXPathEval(BAD_CAST xpath, ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
- struct qemud_vm_chr_def *prev = *devs;
- if (ndevs == NULL &&
- obj->nodesetval->nodeNr > 1) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("too many character devices"));
- goto cleanup;
- }
-
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- struct qemud_vm_chr_def *chr;
- if (VIR_ALLOC(chr) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s",
- _("failed to allocate space for char device"));
- goto cleanup;
- }
-
- if (qemudParseCharXML(conn, chr, i, obj->nodesetval->nodeTab[i]) < 0) {
- VIR_FREE(chr);
- goto cleanup;
- }
- if (ndevs)
- (*ndevs)++;
- chr->next = NULL;
- if (i == 0) {
- *devs = chr;
- } else {
- prev->next = chr;
- }
- prev = chr;
- }
- }
-
- ret = 0;
-
-cleanup:
- xmlXPathFreeObject(obj);
- return ret;
-}
-
-
-/* Parse the XML definition for a network interface */
-static int qemudParseInputXML(virConnectPtr conn,
- const struct qemud_vm_def *vm,
- struct qemud_vm_input_def *input,
- xmlNodePtr node) {
- 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,
- "%s", _("missing input device type"));
- goto error;
- }
-
- if (STREQ((const char *)type, "mouse")) {
- input->type = QEMU_INPUT_TYPE_MOUSE;
- } else if (STREQ((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 (STREQ(vm->os.type, "hvm")) {
- if (STREQ((const char*)bus, "ps2")) { /* Only allow mouse */
- if (input->type != QEMU_INPUT_TYPE_MOUSE) {
- 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 (STREQ((const char *)bus, "usb")) { /* Allow mouse & tablet */
- 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 (STREQ((const char *)bus, "xen")) { /* Allow mouse only */
- input->bus = QEMU_INPUT_BUS_XEN;
- if (input->type != QEMU_INPUT_TYPE_MOUSE) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("xen bus does not support %s input device"),
- (const char*)type);
- goto error;
- }
- } else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("unsupported input bus %s"), (const char*)bus);
- goto error;
- }
- }
- } else {
- if (STREQ(vm->os.type, "hvm")) {
- if (input->type == QEMU_INPUT_TYPE_MOUSE)
- input->bus = QEMU_INPUT_BUS_PS2;
- else
- input->bus = QEMU_INPUT_BUS_USB;
- } else {
- input->bus = QEMU_INPUT_BUS_XEN;
- }
- }
-
- xmlFree(type);
- xmlFree(bus);
-
- return 0;
-
- error:
- xmlFree(type);
- xmlFree(bus);
-
- return -1;
-}
-
-static int qemudDiskCompare(const void *aptr, const void *bptr) {
- struct qemud_vm_disk_def *a = (struct qemud_vm_disk_def *) aptr;
- struct qemud_vm_disk_def *b = (struct qemud_vm_disk_def *) bptr;
- if (a->bus == b->bus)
- return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst);
- else
- return a->bus - b->bus;
-}
-
-static const char *qemudBusIdToName(int busId, int qemuIF) {
- const char *busnames[] = { "ide",
- (qemuIF ? "floppy" : "fdc"),
- "scsi",
- "virtio",
- "xen"};
- verify_true(ARRAY_CARDINALITY(busnames) == QEMUD_DISK_BUS_LAST);
-
- return busnames[busId];
-}
-
-/* Sound device helper functions */
-static int qemudSoundModelFromString(const char *model) {
- if (STREQ(model, "sb16")) {
- return QEMU_SOUND_SB16;
- } else if (STREQ(model, "es1370")) {
- return QEMU_SOUND_ES1370;
- } else if (STREQ(model, "pcspk")) {
- return QEMU_SOUND_PCSPK;
- }
-
- return -1;
-}
-
-static const char *qemudSoundModelToString(const int model) {
-
- if (model == QEMU_SOUND_SB16) {
- return "sb16";
- } else if (model == QEMU_SOUND_ES1370) {
- return "es1370";
- } else if (model == QEMU_SOUND_PCSPK) {
- return "pcspk";
- }
-
- return NULL;
-}
-
-
-static int qemudParseSoundXML(virConnectPtr conn,
- struct qemud_vm_sound_def *sound,
- const xmlNodePtr node) {
-
- int err = -1;
- xmlChar *model = NULL;
- model = xmlGetProp(node, BAD_CAST "model");
-
- if (!model) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing sound model"));
- goto error;
- }
- if ((sound->model = qemudSoundModelFromString((char *) model)) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("invalid sound model '%s'"), (char *) model);
- goto error;
- }
-
- err = 0;
- error:
- xmlFree(model);
- return err;
-}
-
-/*
- * Parses a libvirt XML definition of a guest, and populates the
- * the qemud_vm struct with matching data about the guests config
- */
-static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
- struct qemud_driver *driver,
- xmlDocPtr xml) {
- xmlNodePtr root = NULL;
- xmlChar *prop = NULL;
- xmlXPathContextPtr ctxt = NULL;
- xmlXPathObjectPtr obj = NULL;
- char *conv = NULL;
- int i;
- struct qemud_vm_def *def;
-
- if (VIR_ALLOC(def) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for xmlXPathContext"));
- return NULL;
- }
-
- /* Prepare parser / xpath context */
- root = xmlDocGetRootElement(xml);
- if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("incorrect root element"));
- goto error;
- }
-
- ctxt = xmlXPathNewContext(xml);
- if (ctxt == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for xmlXPathContext"));
- goto error;
- }
-
-
- /* Find out what type of QEMU virtualization to use */
- if (!(prop = xmlGetProp(root, BAD_CAST "type"))) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing domain type attribute"));
- goto error;
- }
-
- if (STREQ((char *)prop, "qemu"))
- def->virtType = QEMUD_VIRT_QEMU;
- else if (STREQ((char *)prop, "kqemu"))
- def->virtType = QEMUD_VIRT_KQEMU;
- else if (STREQ((char *)prop, "kvm"))
- def->virtType = QEMUD_VIRT_KVM;
- else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("invalid domain type attribute"));
- goto error;
- }
- VIR_FREE(prop);
-
-
- /* 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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_NAME, NULL);
- goto error;
- }
- if (strlen((const char *)obj->stringval) >= (QEMUD_MAX_NAME_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain name length too long"));
- goto error;
- }
- strcpy(def->name, (const char *)obj->stringval);
- 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)) {
- int err;
- if ((err = virUUIDGenerate(def->uuid))) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Failed to generate UUID: %s"), strerror(err));
- goto error;
- }
- } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed uuid element"));
- 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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing memory element"));
- goto error;
- } else {
- conv = NULL;
- def->maxmem = strtoll((const char*)obj->stringval, &conv, 10);
- if (conv == (const char*)obj->stringval) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed memory information"));
- goto error;
- }
- }
- xmlXPathFreeObject(obj);
-
-
- /* 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)) {
- def->memory = def->maxmem;
- } else {
- conv = NULL;
- def->memory = strtoll((const char*)obj->stringval, &conv, 10);
- if (def->memory > def->maxmem)
- def->memory = def->maxmem;
- if (conv == (const char*)obj->stringval) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed memory information"));
- goto error;
- }
- }
- xmlXPathFreeObject(obj);
-
- /* 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)) {
- def->vcpus = 1;
- } else {
- conv = NULL;
- def->vcpus = strtoll((const char*)obj->stringval, &conv, 10);
- if (conv == (const char*)obj->stringval) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed vcpu information"));
- goto error;
- }
- }
- xmlXPathFreeObject(obj);
-
- /* Extract domain vcpu info */
- obj = xmlXPathEval(BAD_CAST "string(/domain/vcpu[1]/@cpuset)", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_STRING) ||
- (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
- /* Allow use on all CPUS */
- memset(def->cpumask, 1, QEMUD_CPUMASK_LEN);
- } else {
- char *set = (char *)obj->stringval;
- memset(def->cpumask, 0, QEMUD_CPUMASK_LEN);
- if (virParseCpuSet(conn, (const char **)&set,
- 0, def->cpumask,
- QEMUD_CPUMASK_LEN) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed vcpu mask information"));
- goto error;
- }
- }
- xmlXPathFreeObject(obj);
-
- /* 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)) {
- def->features |= QEMUD_FEATURE_ACPI;
- }
- xmlXPathFreeObject(obj);
-
-
- /* 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 (STREQ((char*)obj->stringval, "destroy"))
- def->noReboot = 1;
- else
- def->noReboot = 0;
- }
- xmlXPathFreeObject(obj);
-
- /* 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 (STREQ((char*)obj->stringval, "localtime"))
- def->localtime = 1;
- else
- def->localtime = 0;
- }
- xmlXPathFreeObject(obj);
-
-
- /* Extract bootloader */
- obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader)", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
- strncpy(def->os.bootloader, (const char*)obj->stringval, sizeof(def->os.bootloader));
- NUL_TERMINATE(def->os.bootloader);
-
- /* Set a default OS type, since <type> is optional with bootloader */
- strcpy(def->os.type, "xen");
- }
- xmlXPathFreeObject(obj);
-
- /* 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)) {
- if (!def->os.type[0]) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
- "%s", _("no OS type"));
- goto error;
- }
- } else {
- strcpy(def->os.type, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
- obj = NULL;
-
- if (!virCapabilitiesSupportsGuestOSType(driver->caps, def->os.type)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE,
- "%s", def->os.type);
- goto error;
- }
-
- 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)) {
- 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;
- }
- if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("architecture type too long"));
- goto error;
- }
- strcpy(def->os.arch, defaultArch);
- } else {
- if (strlen((const char *)obj->stringval) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("architecture type too long"));
- goto error;
- }
- strcpy(def->os.arch, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
- 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)) {
- 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"));
- goto error;
- }
- if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("machine type too long"));
- goto error;
- }
- strcpy(def->os.machine, defaultMachine);
- } else {
- if (strlen((const char *)obj->stringval) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("architecture type too long"));
- goto error;
- }
- strcpy(def->os.machine, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
-
- if (!def->os.bootloader[0]) {
- 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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("kernel path too long"));
- goto error;
- }
- strcpy(def->os.kernel, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
-
- 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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("initrd path too long"));
- goto error;
- }
- strcpy(def->os.initrd, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
-
- 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)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("cmdline arguments too long"));
- goto error;
- }
- strcpy(def->os.cmdline, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
-
- /* 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++) {
- if (!(prop = xmlGetProp(obj->nodesetval->nodeTab[i], BAD_CAST "dev")))
- continue;
- if (STREQ((char *)prop, "hd")) {
- def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_DISK;
- } else if (STREQ((char *)prop, "fd")) {
- def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_FLOPPY;
- } else if (STREQ((char *)prop, "cdrom")) {
- def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_CDROM;
- } else if (STREQ((char *)prop, "network")) {
- def->os.bootDevs[def->os.nBootDevs++] = QEMUD_BOOT_NET;
- } else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("unknown boot device \'%s\'"), (char*)prop);
- goto error;
- }
- xmlFree(prop);
- prop = NULL;
- }
- }
- xmlXPathFreeObject(obj);
- if (def->os.nBootDevs == 0) {
- def->os.nBootDevs = 1;
- def->os.bootDevs[0] = QEMUD_BOOT_DISK;
- }
- }
-
- obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_STRING) ||
- (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
- const char *type = qemudVirtTypeToString(def->virtType);
- if (!type) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("unknown virt type"));
- goto error;
- }
- 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"));
- goto error;
- }
- strcpy(def->os.binary, emulator);
- } else {
- if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("emulator path too long"));
- goto error;
- }
- strcpy(def->os.binary, (const char *)obj->stringval);
- }
- xmlXPathFreeObject(obj);
-
- obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
- (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
- def->graphicsType = QEMUD_GRAPHICS_NONE;
- } else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type"))) {
- if (STREQ((char *)prop, "vnc")) {
- xmlChar *vncport, *vnclisten;
- def->graphicsType = QEMUD_GRAPHICS_VNC;
- vncport = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "port");
- if (vncport) {
- conv = NULL;
- def->vncPort = strtoll((const char*)vncport, &conv, 10);
- } else {
- def->vncPort = -1;
- }
- vnclisten = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "listen");
- if (vnclisten && *vnclisten)
- strncpy(def->vncListen, (char *)vnclisten, BR_INET_ADDR_MAXLEN-1);
- else
- strcpy(def->vncListen, driver->vncListen);
- def->vncListen[BR_INET_ADDR_MAXLEN-1] = '\0';
- def->keymap = (char *) xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "keymap");
- xmlFree(vncport);
- xmlFree(vnclisten);
- } else if (STREQ((char *)prop, "sdl")) {
- def->graphicsType = QEMUD_GRAPHICS_SDL;
- } else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Unsupported graphics type %s"), prop);
- goto error;
- }
- xmlFree(prop);
- prop = NULL;
- }
- xmlXPathFreeObject(obj);
-
- /* 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)) {
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- struct qemud_vm_disk_def *disk;
- if (VIR_ALLOC(disk) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for disk string"));
- goto error;
- }
- if (qemudParseDiskXML(conn, disk, obj->nodesetval->nodeTab[i]) < 0) {
- VIR_FREE(disk);
- goto error;
- }
- def->ndisks++;
- if (i == 0) {
- disk->next = NULL;
- def->disks = disk;
- } else {
- struct qemud_vm_disk_def *ptr = def->disks;
- while (ptr) {
- if (!ptr->next || qemudDiskCompare(disk, ptr->next) < 0) {
- disk->next = ptr->next;
- ptr->next = disk;
- break;
- }
- ptr = ptr->next;
- }
- }
- }
- }
- xmlXPathFreeObject(obj);
- obj = NULL;
-
- /* analysis of the character devices */
- if (qemudParseCharXMLDevices(conn, ctxt,
- "/domain/devices/parallel",
- &def->nparallels,
- &def->parallels) < 0)
- goto error;
- if (qemudParseCharXMLDevices(conn, ctxt,
- "/domain/devices/serial",
- &def->nserials,
- &def->serials) < 0)
- goto error;
-
- /*
- * If no serial devices were listed, then look for console
- * devices which is the legacy syntax for the same thing
- */
- if (def->nserials == 0) {
- obj = xmlXPathEval(BAD_CAST "/domain/devices/console", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
- struct qemud_vm_chr_def *chr;
- if (VIR_ALLOC(chr) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s",
- _("failed to allocate space for char device"));
- goto error;
- }
-
- if (qemudParseCharXML(conn, chr, 0, obj->nodesetval->nodeTab[0]) < 0) {
- VIR_FREE(chr);
- goto error;
- }
- def->nserials = 1;
- def->serials = chr;
- }
- 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)) {
- struct qemud_vm_net_def *prev = NULL;
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- struct qemud_vm_net_def *net;
- if (VIR_ALLOC(net) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for net string"));
- goto error;
- }
- if (qemudParseInterfaceXML(conn, net, obj->nodesetval->nodeTab[i]) < 0) {
- VIR_FREE(net);
- goto error;
- }
- def->nnets++;
- net->next = NULL;
- if (i == 0) {
- def->nets = net;
- } else {
- prev->next = net;
- }
- prev = net;
- }
- }
- xmlXPathFreeObject(obj);
-
- /* 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++) {
- struct qemud_vm_input_def *input;
- if (VIR_ALLOC(input) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for input string"));
- goto error;
- }
- if (qemudParseInputXML(conn, def, input, obj->nodesetval->nodeTab[i]) < 0) {
- VIR_FREE(input);
- 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) {
- VIR_FREE(input);
- continue;
- }
- def->ninputs++;
- input->next = NULL;
- if (def->inputs == NULL) {
- def->inputs = input;
- } else {
- prev->next = input;
- }
- prev = input;
- }
- }
- xmlXPathFreeObject(obj);
-
- /* Parse sound driver xml */
- obj = xmlXPathEval(BAD_CAST "/domain/devices/sound", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
- struct qemud_vm_sound_def *prev = NULL;
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-
- struct qemud_vm_sound_def *sound;
- struct qemud_vm_sound_def *check = def->sounds;
- int collision = 0;
- if (VIR_ALLOC(sound) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for sound dev"));
- goto error;
- }
- if (qemudParseSoundXML(conn, sound,
- obj->nodesetval->nodeTab[i]) < 0) {
- VIR_FREE(sound);
- goto error;
- }
-
- // Check that model type isn't already present in sound dev list
- while(check) {
- if (check->model == sound->model) {
- collision = 1;
- break;
- }
- check = check->next;
- }
- if (collision) {
- VIR_FREE(sound);
- continue;
- }
-
- def->nsounds++;
- sound->next = NULL;
- if (def->sounds == NULL) {
- def->sounds = sound;
- } else {
- prev->next = sound;
- }
- prev = sound;
- }
- }
- 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;
- }
+ "i686",
+ "qemu")) == NULL)
+ return -1;
- if (!hasPS2mouse) {
- if (VIR_ALLOC(input) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for input string"));
- goto error;
- }
- input->type = QEMU_INPUT_TYPE_MOUSE;
- input->bus = QEMU_INPUT_BUS_PS2;
- input->next = def->inputs;
- def->inputs = input;
- def->ninputs++;
- }
+ if (stat(binary, &sb) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Cannot find QEMU binary %s: %s"), binary,
+ strerror(errno));
+ return -1;
}
- xmlXPathFreeContext(ctxt);
-
- return def;
+ if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
+ return -1;
+ }
- error:
- VIR_FREE(prop);
- xmlXPathFreeObject(obj);
- xmlXPathFreeContext(ctxt);
- qemudFreeVMDef(def);
- return NULL;
+ return 0;
}
static char *
qemudNetworkIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
- struct qemud_vm_net_def *net,
+ int **tapfds,
+ int *ntapfds,
+ virDomainNetDefPtr net,
int vlan)
{
virNetworkObjPtr network = NULL;
char *brname;
- char *ifname;
char tapfdstr[4+3+32+7];
char *retval = NULL;
int err;
int tapfd = -1;
- if (net->type == QEMUD_NET_NETWORK) {
- if (!(network = virNetworkFindByName(driver->networks, net->dst.network.name))) {
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ if (!(network = virNetworkFindByName(driver->networks, net->data.network.name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Network '%s' not found"),
- net->dst.network.name);
+ net->data.network.name);
goto error;
} else if (network->def->bridge == NULL) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Network '%s' not active"),
- net->dst.network.name);
+ net->data.network.name);
goto error;
}
brname = network->def->bridge;
- if (net->dst.network.ifname[0] == '\0' ||
- STRPREFIX(net->dst.network.ifname, "vnet") ||
- 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' ||
- STRPREFIX(net->dst.bridge.ifname, "vnet") ||
- strchr(net->dst.bridge.ifname, '%')) {
- strcpy(net->dst.bridge.ifname, "vnet%d");
- }
- ifname = net->dst.bridge.ifname;
+ } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ brname = net->data.bridge.brname;
} else {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Network type %d is not supported"), net->type);
goto error;
}
+ if (!net->ifname ||
+ STRPREFIX(net->ifname, "vnet") ||
+ strchr(net->ifname, '%')) {
+ VIR_FREE(net->ifname);
+ if (!(net->ifname = strdup("vnet%d"))) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+ goto error;
+ }
+ }
+
if (!driver->brctl && (err = brInit(&driver->brctl))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot initialize bridge support: %s"),
}
if ((err = brAddTap(driver->brctl, brname,
- ifname, BR_IFNAME_MAXLEN, &tapfd))) {
+ &net->ifname, &tapfd))) {
if (errno == ENOTSUP) {
/* In this particular case, give a better diagnostic. */
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Failed to add tap interface '%s' "
"to bridge '%s' : %s"),
- ifname, brname, strerror(err));
+ net->ifname, brname, strerror(err));
}
goto error;
}
snprintf(tapfdstr, sizeof(tapfdstr),
"tap,fd=%d,script=,vlan=%d,ifname=%s",
- tapfd, vlan, ifname);
+ tapfd, vlan, net->ifname);
if (!(retval = strdup(tapfdstr)))
goto no_memory;
- if (VIR_REALLOC_N(vm->tapfds, vm->ntapfds+2) < 0)
+ if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0)
goto no_memory;
- vm->tapfds[vm->ntapfds++] = tapfd;
- vm->tapfds[vm->ntapfds] = -1;
+ (*tapfds)[(*ntapfds)++] = tapfd;
return retval;
return NULL;
}
-static int qemudBuildCommandLineChrDevStr(struct qemud_vm_chr_def *dev,
+static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
char *buf,
int buflen)
{
- switch (dev->srcType) {
- case QEMUD_CHR_SRC_TYPE_NULL:
+ switch (dev->type) {
+ case VIR_DOMAIN_CHR_TYPE_NULL:
strncpy(buf, "null", buflen);
buf[buflen-1] = '\0';
break;
- case QEMUD_CHR_SRC_TYPE_VC:
+ case VIR_DOMAIN_CHR_TYPE_VC:
strncpy(buf, "vc", buflen);
buf[buflen-1] = '\0';
break;
- case QEMUD_CHR_SRC_TYPE_PTY:
+ case VIR_DOMAIN_CHR_TYPE_PTY:
strncpy(buf, "pty", buflen);
buf[buflen-1] = '\0';
break;
- case QEMUD_CHR_SRC_TYPE_DEV:
+ case VIR_DOMAIN_CHR_TYPE_DEV:
if (snprintf(buf, buflen, "%s",
- dev->srcData.file.path) >= buflen)
+ dev->data.file.path) >= buflen)
return -1;
break;
- case QEMUD_CHR_SRC_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_FILE:
if (snprintf(buf, buflen, "file:%s",
- dev->srcData.file.path) >= buflen)
+ dev->data.file.path) >= buflen)
return -1;
break;
- case QEMUD_CHR_SRC_TYPE_PIPE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
if (snprintf(buf, buflen, "pipe:%s",
- dev->srcData.file.path) >= buflen)
+ dev->data.file.path) >= buflen)
return -1;
break;
- case QEMUD_CHR_SRC_TYPE_STDIO:
+ case VIR_DOMAIN_CHR_TYPE_STDIO:
strncpy(buf, "stdio", buflen);
buf[buflen-1] = '\0';
break;
- case QEMUD_CHR_SRC_TYPE_UDP:
+ case VIR_DOMAIN_CHR_TYPE_UDP:
if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
- dev->srcData.udp.connectHost,
- dev->srcData.udp.connectService,
- dev->srcData.udp.bindHost,
- dev->srcData.udp.bindService) >= buflen)
+ dev->data.udp.connectHost,
+ dev->data.udp.connectService,
+ dev->data.udp.bindHost,
+ dev->data.udp.bindService) >= buflen)
return -1;
break;
- case QEMUD_CHR_SRC_TYPE_TCP:
+ case VIR_DOMAIN_CHR_TYPE_TCP:
if (snprintf(buf, buflen, "%s:%s:%s%s",
- dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET ? "telnet" : "tcp",
- dev->srcData.tcp.host,
- dev->srcData.tcp.service,
- dev->srcData.tcp.listen ? ",listen" : "") >= buflen)
+ dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET ? "telnet" : "tcp",
+ dev->data.tcp.host,
+ dev->data.tcp.service,
+ dev->data.tcp.listen ? ",listen" : "") >= buflen)
return -1;
break;
- case QEMUD_CHR_SRC_TYPE_UNIX:
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
if (snprintf(buf, buflen, "unix:%s%s",
- dev->srcData.nix.path,
- dev->srcData.nix.listen ? ",listen" : "") >= buflen)
+ dev->data.nix.path,
+ dev->data.nix.listen ? ",listen" : "") >= buflen)
return -1;
break;
}
*/
int qemudBuildCommandLine(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
- char ***retargv) {
+ virDomainObjPtr vm,
+ int qemuCmdFlags,
+ char ***retargv,
+ int **tapfds,
+ int *ntapfds,
+ const char *migrateFrom) {
int i;
char memory[50];
char vcpus[50];
- char boot[QEMUD_MAX_BOOT_DEVS+1];
- struct qemud_vm_disk_def *disk = vm->def->disks;
- struct qemud_vm_net_def *net = vm->def->nets;
- struct qemud_vm_input_def *input = vm->def->inputs;
- struct qemud_vm_sound_def *sound = vm->def->sounds;
- struct qemud_vm_chr_def *serial = vm->def->serials;
- struct qemud_vm_chr_def *parallel = vm->def->parallels;
+ char boot[VIR_DOMAIN_BOOT_LAST];
+ virDomainDiskDefPtr disk = vm->def->disks;
+ virDomainNetDefPtr net = vm->def->nets;
+ virDomainInputDefPtr input = vm->def->inputs;
+ virDomainSoundDefPtr sound = vm->def->sounds;
+ virDomainChrDefPtr serial = vm->def->serials;
+ virDomainChrDefPtr parallel = vm->def->parallels;
struct utsname ut;
int disableKQEMU = 0;
int qargc = 0, qarga = 0;
char **qargv = NULL;
- if (vm->qemuVersion == 0) {
- if (qemudExtractVersionInfo(vm->def->os.binary,
- &(vm->qemuVersion),
- &(vm->qemuCmdFlags)) < 0)
- return -1;
- }
-
uname(&ut);
/* Nasty hack make i?86 look like i686 to simplify next comparison */
* 2. Guest is 'qemu'
* 3. The qemu binary has the -no-kqemu flag
*/
- if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
STREQ(ut.machine, vm->def->os.arch) &&
- vm->def->virtType == QEMUD_VIRT_QEMU)
+ vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
disableKQEMU = 1;
#define ADD_ARG_SPACE \
} while (0)
snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
- snprintf(vcpus, sizeof(vcpus), "%d", vm->def->vcpus);
+ snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
- ADD_ARG_LIT(vm->def->os.binary);
+ ADD_ARG_LIT(vm->def->emulator);
ADD_ARG_LIT("-S");
ADD_ARG_LIT("-M");
ADD_ARG_LIT(vm->def->os.machine);
ADD_ARG_LIT("-smp");
ADD_ARG_LIT(vcpus);
- if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
ADD_ARG_LIT("-name");
ADD_ARG_LIT(vm->def->name);
}
* if you ask for nographic. So we have to make sure we override
* these defaults ourselves...
*/
- if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE)
+ if (!vm->def->graphics)
ADD_ARG_LIT("-nographic");
ADD_ARG_LIT("-monitor");
if (vm->def->localtime)
ADD_ARG_LIT("-localtime");
- if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
- vm->def->noReboot)
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
+ vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
ADD_ARG_LIT("-no-reboot");
- if (!(vm->def->features & QEMUD_FEATURE_ACPI))
+ if (!(vm->def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
ADD_ARG_LIT("-no-acpi");
- if (!vm->def->os.bootloader[0]) {
+ if (!vm->def->os.bootloader) {
for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
switch (vm->def->os.bootDevs[i]) {
- case QEMUD_BOOT_CDROM:
+ case VIR_DOMAIN_BOOT_CDROM:
boot[i] = 'd';
break;
- case QEMUD_BOOT_FLOPPY:
+ case VIR_DOMAIN_BOOT_FLOPPY:
boot[i] = 'a';
break;
- case QEMUD_BOOT_DISK:
+ case VIR_DOMAIN_BOOT_DISK:
boot[i] = 'c';
break;
- case QEMUD_BOOT_NET:
+ case VIR_DOMAIN_BOOT_NET:
boot[i] = 'n';
break;
default:
ADD_ARG_LIT("-boot");
ADD_ARG_LIT(boot);
- if (vm->def->os.kernel[0]) {
+ if (vm->def->os.kernel) {
ADD_ARG_LIT("-kernel");
ADD_ARG_LIT(vm->def->os.kernel);
}
- if (vm->def->os.initrd[0]) {
+ if (vm->def->os.initrd) {
ADD_ARG_LIT("-initrd");
ADD_ARG_LIT(vm->def->os.initrd);
}
- if (vm->def->os.cmdline[0]) {
+ if (vm->def->os.cmdline) {
ADD_ARG_LIT("-append");
ADD_ARG_LIT(vm->def->os.cmdline);
}
}
/* If QEMU supports -drive param instead of old -hda, -hdb, -cdrom .. */
- if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
int bootCD = 0, bootFloppy = 0, bootDisk = 0;
/* If QEMU supports boot=on for -drive param... */
- if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
switch (vm->def->os.bootDevs[i]) {
- case QEMUD_BOOT_CDROM:
+ case VIR_DOMAIN_BOOT_CDROM:
bootCD = 1;
break;
- case QEMUD_BOOT_FLOPPY:
+ case VIR_DOMAIN_BOOT_FLOPPY:
bootFloppy = 1;
break;
- case QEMUD_BOOT_DISK:
+ case VIR_DOMAIN_BOOT_DISK:
bootDisk = 1;
break;
}
const char *media = NULL;
int bootable = 0;
int idx = virDiskNameToIndex(disk->dst);
+ const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
if (idx < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
goto error;
}
- if (disk->device == QEMUD_DISK_CDROM)
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
media = "media=cdrom,";
switch (disk->device) {
- case QEMUD_DISK_CDROM:
+ case VIR_DOMAIN_DISK_DEVICE_CDROM:
bootable = bootCD;
bootCD = 0;
break;
- case QEMUD_DISK_FLOPPY:
+ case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
bootable = bootFloppy;
bootFloppy = 0;
break;
- case QEMUD_DISK_DISK:
+ case VIR_DOMAIN_DISK_DEVICE_DISK:
bootable = bootDisk;
bootDisk = 0;
break;
}
snprintf(opt, PATH_MAX, "file=%s,if=%s,%sindex=%d%s",
- disk->src, qemudBusIdToName(disk->bus, 1),
+ disk->src, bus,
media ? media : "",
idx,
- bootable && disk->device == QEMUD_DISK_DISK
+ bootable &&
+ disk->device == VIR_DOMAIN_DISK_DEVICE_DISK
? ",boot=on" : "");
ADD_ARG_LIT("-drive");
char file[PATH_MAX];
if (STREQ(disk->dst, "hdc") &&
- disk->device == QEMUD_DISK_CDROM) {
- if (disk->src[0]) {
+ disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+ if (disk->src) {
snprintf(dev, NAME_MAX, "-%s", "cdrom");
} else {
disk = disk->next;
net->mac[2], net->mac[3],
net->mac[4], net->mac[5],
vlan,
- (net->model[0] ? ",model=" : ""), net->model) >= sizeof(nic))
+ (net->model ? ",model=" : ""),
+ (net->model ? net->model : "")) >= sizeof(nic))
goto error;
ADD_ARG_LIT("-net");
ADD_ARG_LIT("-net");
switch (net->type) {
- case QEMUD_NET_NETWORK:
- case QEMUD_NET_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
{
- char *tap = qemudNetworkIfaceConnect(conn, driver, vm, net, vlan);
+ char *tap = qemudNetworkIfaceConnect(conn, driver,
+ tapfds, ntapfds,
+ net, vlan);
if (tap == NULL)
goto error;
ADD_ARG(tap);
break;
}
- case QEMUD_NET_ETHERNET:
+ case VIR_DOMAIN_NET_TYPE_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,
+ net->ifname,
+ net->data.ethernet.script,
vlan) >= (PATH_MAX-1))
goto error;
}
break;
- case QEMUD_NET_CLIENT:
- case QEMUD_NET_SERVER:
- case QEMUD_NET_MCAST:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
{
char arg[PATH_MAX];
const char *mode = NULL;
switch (net->type) {
- case QEMUD_NET_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
mode = "connect";
break;
- case QEMUD_NET_SERVER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
mode = "listen";
break;
- case QEMUD_NET_MCAST:
+ case VIR_DOMAIN_NET_TYPE_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,
+ net->data.socket.address,
+ net->data.socket.port,
vlan) >= (PATH_MAX-1))
goto error;
}
break;
- case QEMUD_NET_USER:
+ case VIR_DOMAIN_NET_TYPE_USER:
default:
{
char arg[PATH_MAX];
ADD_ARG_LIT("-usb");
while (input) {
- if (input->bus == QEMU_INPUT_BUS_USB) {
+ if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
ADD_ARG_LIT("-usbdevice");
- ADD_ARG_LIT(input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
+ ADD_ARG_LIT(input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
}
input = input->next;
}
- if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) {
+ if (vm->def->graphics &&
+ vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
char vncdisplay[PATH_MAX];
int ret;
- if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
char options[PATH_MAX] = "";
if (driver->vncTLS) {
strcat(options, ",tls");
options[sizeof(options)-1] = '\0';
}
ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d%s",
- vm->def->vncListen,
- vm->def->vncActivePort - 5900,
+ vm->def->graphics->data.vnc.listenAddr,
+ vm->def->graphics->data.vnc.port - 5900,
options);
} else {
ret = snprintf(vncdisplay, sizeof(vncdisplay), "%d",
- vm->def->vncActivePort - 5900);
+ vm->def->graphics->data.vnc.port - 5900);
}
if (ret < 0 || ret >= (int)sizeof(vncdisplay))
goto error;
ADD_ARG_LIT("-vnc");
ADD_ARG_LIT(vncdisplay);
- if (vm->def->keymap) {
+ if (vm->def->graphics->data.vnc.keymap) {
ADD_ARG_LIT("-k");
- ADD_ARG_LIT(vm->def->keymap);
+ ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap);
}
- } else if (vm->def->graphicsType == QEMUD_GRAPHICS_NONE) {
- /* Nada - we added -nographic earlier in this function */
- } else {
+ } else if (vm->def->graphics &&
+ vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
/* SDL is the default. no args needed */
}
goto no_memory;
while(sound && size > 0) {
- const char *model = qemudSoundModelToString(sound->model);
+ const char *model = virDomainSoundModelTypeToString(sound->model);
if (!model) {
VIR_FREE(modstr);
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
ADD_ARG(modstr);
}
- if (vm->migrateFrom[0]) {
+ if (migrateFrom) {
ADD_ARG_LIT("-incoming");
- ADD_ARG_LIT(vm->migrateFrom);
+ ADD_ARG_LIT(migrateFrom);
}
ADD_ARG(NULL);
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for argv string"));
error:
- if (vm->tapfds) {
- for (i = 0; vm->tapfds[i] != -1; i++)
- close(vm->tapfds[i]);
- VIR_FREE(vm->tapfds);
- vm->tapfds = NULL;
- vm->ntapfds = 0;
+ if (tapfds &&
+ *tapfds) {
+ for (i = 0; ntapfds; i++)
+ close((*tapfds)[i]);
+ VIR_FREE(*tapfds);
+ *ntapfds = 0;
}
if (qargv) {
for (i = 0 ; i < qargc ; i++)
}
-/* Save a guest's config data into a persistent file */
-static int qemudSaveConfig(virConnectPtr conn,
- struct qemud_driver *driver,
- struct qemud_vm *vm,
- struct qemud_vm_def *def) {
- char *xml;
- int fd = -1, ret = -1;
- int towrite;
-
- if (!(xml = qemudGenerateXML(conn, driver, vm, def, 0)))
- return -1;
-
- if ((fd = open(vm->configFile,
- O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR )) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot create config file %s: %s"),
- vm->configFile, strerror(errno));
- goto cleanup;
- }
-
- towrite = strlen(xml);
- if (safewrite(fd, xml, towrite) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot write config file %s: %s"),
- vm->configFile, strerror(errno));
- goto cleanup;
- }
-
- if (close(fd) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot save config file %s: %s"),
- vm->configFile, strerror(errno));
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- if (fd != -1)
- close(fd);
-
- VIR_FREE(xml);
-
- return ret;
-}
-
-struct qemud_vm_device_def *
-qemudParseVMDeviceDef(virConnectPtr conn,
- const struct qemud_vm_def *def,
- const char *xmlStr)
-{
- xmlDocPtr xml;
- xmlNodePtr node;
- struct qemud_vm_device_def *dev;
-
- if (VIR_ALLOC(dev) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
- return NULL;
- }
-
- 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);
- goto error;
- }
-
- node = xmlDocGetRootElement(xml);
- if (node == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
- "%s", _("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 "interface")) {
- 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, def, &(dev->data.input), node);
- } else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
- dev->type = QEMUD_DEVICE_SOUND;
- qemudParseSoundXML(conn, &(dev->data.sound), node);
- } else {
- qemudReportError(conn, NULL, NULL, VIR_ERR_XML_ERROR,
- "%s", _("unknown device type"));
- goto error;
- }
-
- xmlFreeDoc(xml);
-
- return dev;
-
- error:
- if (xml) xmlFreeDoc(xml);
- VIR_FREE(dev);
- return NULL;
-}
-
-struct qemud_vm_def *
-qemudParseVMDef(virConnectPtr conn,
- struct qemud_driver *driver,
- const char *xmlStr,
- const char *displayName) {
- xmlDocPtr xml;
- struct qemud_vm_def *def = NULL;
-
- if (!(xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.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;
- }
-
- def = qemudParseXML(conn, driver, xml);
-
- xmlFreeDoc(xml);
-
- return def;
-}
-
-struct qemud_vm *
-qemudAssignVMDef(virConnectPtr conn,
- struct qemud_driver *driver,
- struct qemud_vm_def *def)
-{
- struct qemud_vm *vm = NULL;
-
- if ((vm = qemudFindVMByName(driver, def->name))) {
- if (!qemudIsActiveVM(vm)) {
- qemudFreeVMDef(vm->def);
- vm->def = def;
- } else {
- if (vm->newDef)
- qemudFreeVMDef(vm->newDef);
- vm->newDef = def;
- }
- /* Reset version, because the emulator path might have changed */
- vm->qemuVersion = 0;
- vm->qemuCmdFlags = 0;
- return vm;
- }
-
- if (VIR_ALLOC(vm) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to allocate space for vm string"));
- return NULL;
- }
-
- vm->stdin = -1;
- vm->stdout = -1;
- vm->stderr = -1;
- vm->monitor = -1;
- vm->pid = -1;
- vm->id = -1;
- vm->state = VIR_DOMAIN_SHUTOFF;
- vm->def = def;
- vm->next = driver->vms;
-
- driver->vms = vm;
- driver->ninactivevms++;
-
- return vm;
-}
-
-void
-qemudRemoveInactiveVM(struct qemud_driver *driver,
- struct qemud_vm *vm)
-{
- struct qemud_vm *prev = NULL, *curr;
-
- curr = driver->vms;
- while (curr != vm) {
- prev = curr;
- curr = curr->next;
- }
-
- if (curr) {
- if (prev)
- prev->next = curr->next;
- else
- driver->vms = curr->next;
-
- driver->ninactivevms--;
- }
-
- qemudFreeVM(vm);
-}
-
-int
-qemudSaveVMDef(virConnectPtr conn,
- struct qemud_driver *driver,
- struct qemud_vm *vm,
- struct qemud_vm_def *def) {
- if (vm->configFile[0] == '\0') {
- int err;
-
- if ((err = virFileMakePath(driver->configDir))) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot create config directory %s: %s"),
- driver->configDir, strerror(err));
- return -1;
- }
-
- if (virFileBuildPath(driver->configDir, def->name, ".xml",
- vm->configFile, PATH_MAX) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot construct config file path"));
- return -1;
- }
-
- if (virFileBuildPath(driver->autostartDir, def->name, ".xml",
- vm->autostartLink, PATH_MAX) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot construct autostart link path"));
- vm->configFile[0] = '\0';
- return -1;
- }
- }
-
- return qemudSaveConfig(conn, driver, vm, def);
-}
-
-
-static struct qemud_vm *
-qemudLoadConfig(struct qemud_driver *driver,
- const char *file,
- const char *path,
- const char *xml,
- const char *autostartLink) {
- struct qemud_vm_def *def;
- struct qemud_vm *vm;
-
- if (!(def = qemudParseVMDef(NULL, driver, xml, file))) {
- virErrorPtr err = virGetLastError();
- qemudLog(QEMUD_WARN, _("Error parsing QEMU guest config '%s' : %s"),
- path, (err ? err->message :
- _("BUG: unknown error - please report it\n")));
- return NULL;
- }
-
- if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
- qemudLog(QEMUD_WARN,
- _("QEMU guest config filename '%s'"
- " does not match guest name '%s'"),
- path, def->name);
- qemudFreeVMDef(def);
- return NULL;
- }
-
- if (!(vm = qemudAssignVMDef(NULL, driver, def))) {
- qemudLog(QEMUD_WARN,
- _("Failed to load QEMU guest config '%s': out of memory"),
- path);
- qemudFreeVMDef(def);
- return NULL;
- }
-
- strncpy(vm->configFile, path, PATH_MAX);
- vm->configFile[PATH_MAX-1] = '\0';
-
- strncpy(vm->autostartLink, autostartLink, PATH_MAX);
- vm->autostartLink[PATH_MAX-1] = '\0';
-
- vm->autostart = virFileLinkPointsTo(vm->autostartLink, vm->configFile);
-
- return vm;
-}
-
-static
-int qemudScanConfigDir(struct qemud_driver *driver,
- const char *configDir,
- const char *autostartDir) {
- DIR *dir;
- struct dirent *entry;
-
- if (!(dir = opendir(configDir))) {
- if (errno == ENOENT)
- return 0;
- qemudLog(QEMUD_ERR, _("Failed to open dir '%s': %s"),
- configDir, strerror(errno));
- return -1;
- }
-
- while ((entry = readdir(dir))) {
- char *xml;
- char path[PATH_MAX];
- char autostartLink[PATH_MAX];
-
- if (entry->d_name[0] == '.')
- continue;
-
- if (!virFileHasSuffix(entry->d_name, ".xml"))
- continue;
-
- if (virFileBuildPath(configDir, entry->d_name, NULL, path, PATH_MAX) < 0) {
- qemudLog(QEMUD_WARN, _("Config filename '%s/%s' is too long"),
- configDir, entry->d_name);
- continue;
- }
-
- if (virFileBuildPath(autostartDir, entry->d_name, NULL,
- autostartLink, PATH_MAX) < 0) {
- qemudLog(QEMUD_WARN, _("Autostart link path '%s/%s' is too long"),
- autostartDir, entry->d_name);
- continue;
- }
-
- if (virFileReadAll(path, QEMUD_MAX_XML_LEN, &xml) < 0)
- continue;
-
- qemudLoadConfig(driver, entry->d_name, path, xml, autostartLink);
-
- VIR_FREE(xml);
- }
-
- closedir(dir);
-
- return 0;
-}
-
-/* Scan for all guest and network config files */
-int qemudScanConfigs(struct qemud_driver *driver) {
- if (qemudScanConfigDir(driver, driver->configDir, driver->autostartDir) < 0)
- return -1;
-
- return 0;
-}
-
-static int qemudGenerateXMLChar(virBufferPtr buf,
- const struct qemud_vm_chr_def *dev,
- const char *type)
-{
- const char *const types[] = {
- "null",
- "vc",
- "pty",
- "dev",
- "file",
- "pipe",
- "stdio",
- "udp",
- "tcp",
- "unix"
- };
- verify_true(ARRAY_CARDINALITY(types) == QEMUD_CHR_SRC_TYPE_LAST);
-
- /* Compat with legacy <console tty='/dev/pts/5'/> syntax */
- if (STREQ(type, "console") &&
- dev->srcType == QEMUD_CHR_SRC_TYPE_PTY &&
- dev->srcData.file.path[0] != '\0') {
- virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
- type, types[dev->srcType],
- dev->srcData.file.path);
- } else {
- virBufferVSprintf(buf, " <%s type='%s'>\n",
- type, types[dev->srcType]);
- }
-
- switch (dev->srcType) {
- case QEMUD_CHR_SRC_TYPE_NULL:
- case QEMUD_CHR_SRC_TYPE_VC:
- case QEMUD_CHR_SRC_TYPE_STDIO:
- /* nada */
- break;
-
- case QEMUD_CHR_SRC_TYPE_PTY:
- case QEMUD_CHR_SRC_TYPE_DEV:
- case QEMUD_CHR_SRC_TYPE_FILE:
- case QEMUD_CHR_SRC_TYPE_PIPE:
- if (dev->srcType != QEMUD_CHR_SRC_TYPE_PTY ||
- dev->srcData.file.path[0]) {
- virBufferVSprintf(buf, " <source path='%s'/>\n",
- dev->srcData.file.path);
- }
- break;
-
- case QEMUD_CHR_SRC_TYPE_UDP:
- if (dev->srcData.udp.bindService[0] != '\0' &&
- dev->srcData.udp.bindHost[0] != '\0') {
- virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n",
- dev->srcData.udp.bindHost,
- dev->srcData.udp.bindService);
- } else if (dev->srcData.udp.bindHost[0] !='\0') {
- virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n",
- dev->srcData.udp.bindHost);
- } else if (dev->srcData.udp.bindService[0] != '\0') {
- virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n",
- dev->srcData.udp.bindService);
- }
-
- if (dev->srcData.udp.connectService[0] != '\0' &&
- dev->srcData.udp.connectHost[0] != '\0') {
- virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n",
- dev->srcData.udp.connectHost,
- dev->srcData.udp.connectService);
- } else if (dev->srcData.udp.connectHost[0] != '\0') {
- virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n",
- dev->srcData.udp.connectHost);
- } else if (dev->srcData.udp.connectService[0] != '\0') {
- virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
- dev->srcData.udp.connectService);
- }
- break;
-
- case QEMUD_CHR_SRC_TYPE_TCP:
- virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n",
- dev->srcData.tcp.listen ? "bind" : "connect",
- dev->srcData.tcp.host,
- dev->srcData.tcp.service);
- virBufferVSprintf(buf, " <protocol type='%s'/>\n",
- dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET
- ? "telnet" : "raw");
- break;
-
- case QEMUD_CHR_SRC_TYPE_UNIX:
- virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
- dev->srcData.nix.listen ? "bind" : "connect",
- dev->srcData.nix.path);
- break;
- }
-
- virBufferVSprintf(buf, " <target port='%d'/>\n",
- dev->dstPort);
-
- virBufferVSprintf(buf, " </%s>\n",
- type);
-
- return 0;
-}
-
-
-/* Generate an XML document describing the guest's configuration */
-char *qemudGenerateXML(virConnectPtr conn,
- struct qemud_driver *driver ATTRIBUTE_UNUSED,
- struct qemud_vm *vm,
- struct qemud_vm_def *def,
- int live) {
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- unsigned char *uuid;
- char uuidstr[VIR_UUID_STRING_BUFLEN];
- const struct qemud_vm_disk_def *disk;
- const struct qemud_vm_net_def *net;
- const struct qemud_vm_input_def *input;
- const struct qemud_vm_sound_def *sound;
- const struct qemud_vm_chr_def *chr;
- const char *type = NULL, *tmp;
- int n, allones = 1;
-
- if (!(type = qemudVirtTypeToString(def->virtType))) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("unexpected domain type %d"), def->virtType);
- goto cleanup;
- }
-
- if (qemudIsActiveVM(vm) && live)
- virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, vm->id);
- else
- virBufferVSprintf(&buf, "<domain type='%s'>\n", type);
-
- virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
-
- uuid = def->uuid;
- virUUIDFormat(uuid, uuidstr);
- virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
-
- virBufferVSprintf(&buf, " <memory>%lu</memory>\n", def->maxmem);
- virBufferVSprintf(&buf, " <currentMemory>%lu</currentMemory>\n", def->memory);
-
- for (n = 0 ; n < QEMUD_CPUMASK_LEN ; n++)
- if (def->cpumask[n] != 1)
- allones = 0;
-
- if (allones) {
- virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", def->vcpus);
- } else {
- char *cpumask = NULL;
- if ((cpumask = virSaveCpuSet(conn, def->cpumask, QEMUD_CPUMASK_LEN)) == NULL) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("allocating cpu mask"));
- goto cleanup;
- }
- virBufferVSprintf(&buf, " <vcpu cpuset='%s'>%d</vcpu>\n", cpumask, def->vcpus);
- VIR_FREE(cpumask);
- }
-
- if (def->os.bootloader[0])
- virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", def->os.bootloader);
- virBufferAddLit(&buf, " <os>\n");
-
- if (def->virtType == QEMUD_VIRT_QEMU)
- virBufferVSprintf(&buf, " <type arch='%s' machine='%s'>%s</type>\n",
- def->os.arch, def->os.machine, def->os.type);
- else
- virBufferVSprintf(&buf, " <type>%s</type>\n", def->os.type);
-
- if (!def->os.bootloader[0]) {
- if (def->os.kernel[0])
- virBufferVSprintf(&buf, " <kernel>%s</kernel>\n", def->os.kernel);
- if (def->os.initrd[0])
- virBufferVSprintf(&buf, " <initrd>%s</initrd>\n", def->os.initrd);
- if (def->os.cmdline[0])
- virBufferVSprintf(&buf, " <cmdline>%s</cmdline>\n", def->os.cmdline);
-
- for (n = 0 ; n < def->os.nBootDevs ; n++) {
- const char *boottype = "hd";
- switch (def->os.bootDevs[n]) {
- 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:
- boottype = "network";
- break;
- }
- virBufferVSprintf(&buf, " <boot dev='%s'/>\n", boottype);
- }
- }
-
- virBufferAddLit(&buf, " </os>\n");
-
- if (def->features & QEMUD_FEATURE_ACPI) {
- virBufferAddLit(&buf, " <features>\n");
- virBufferAddLit(&buf, " <acpi/>\n");
- virBufferAddLit(&buf, " </features>\n");
- }
-
- virBufferVSprintf(&buf, " <clock offset='%s'/>\n", def->localtime ? "localtime" : "utc");
-
- virBufferAddLit(&buf, " <on_poweroff>destroy</on_poweroff>\n");
- if (def->noReboot)
- virBufferAddLit(&buf, " <on_reboot>destroy</on_reboot>\n");
- else
- virBufferAddLit(&buf, " <on_reboot>restart</on_reboot>\n");
-
- virBufferAddLit(&buf, " <on_crash>destroy</on_crash>\n");
- virBufferAddLit(&buf, " <devices>\n");
-
- virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", def->os.binary);
-
- disk = def->disks;
- while (disk) {
- const char *types[] = {
- "block",
- "file",
- };
- const char *typeAttrs[] = {
- "dev",
- "file",
- };
- const char *devices[] = {
- "disk",
- "cdrom",
- "floppy",
- };
- virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n",
- types[disk->type], devices[disk->device]);
-
- if (disk->src[0])
- virBufferVSprintf(&buf, " <source %s='%s'/>\n",
- typeAttrs[disk->type], disk->src);
-
- virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n",
- disk->dst, qemudBusIdToName(disk->bus, 0));
-
- if (disk->readonly)
- virBufferAddLit(&buf, " <readonly/>\n");
-
- virBufferAddLit(&buf, " </disk>\n");
-
- disk = disk->next;
- }
-
- net = def->nets;
- while (net) {
- const char *types[] = {
- "user",
- "ethernet",
- "server",
- "client",
- "mcast",
- "network",
- "bridge",
- };
- virBufferVSprintf(&buf, " <interface type='%s'>\n",
- types[net->type]);
-
- virBufferVSprintf(&buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
- net->mac[0], net->mac[1], net->mac[2],
- net->mac[3], net->mac[4], net->mac[5]);
-
- switch (net->type) {
- case QEMUD_NET_NETWORK:
- virBufferVSprintf(&buf, " <source network='%s'/>\n", net->dst.network.name);
-
- if (net->dst.network.ifname[0] != '\0')
- virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.network.ifname);
- break;
-
- case QEMUD_NET_ETHERNET:
- if (net->dst.ethernet.ifname[0] != '\0')
- virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname);
- if (net->dst.ethernet.script[0] != '\0')
- virBufferVSprintf(&buf, " <script path='%s'/>\n", net->dst.ethernet.script);
- break;
-
- case QEMUD_NET_BRIDGE:
- virBufferVSprintf(&buf, " <source bridge='%s'/>\n", net->dst.bridge.brname);
- if (net->dst.bridge.ifname[0] != '\0')
- virBufferVSprintf(&buf, " <target dev='%s'/>\n", net->dst.bridge.ifname);
- break;
-
- case QEMUD_NET_SERVER:
- case QEMUD_NET_CLIENT:
- case QEMUD_NET_MCAST:
- if (net->dst.socket.address[0] != '\0')
- virBufferVSprintf(&buf, " <source address='%s' port='%d'/>\n",
- net->dst.socket.address, net->dst.socket.port);
- else
- virBufferVSprintf(&buf, " <source port='%d'/>\n",
- net->dst.socket.port);
- }
-
- if (net->model && net->model[0] != '\0') {
- virBufferVSprintf(&buf, " <model type='%s'/>\n",
- net->model);
- }
-
- virBufferAddLit(&buf, " </interface>\n");
-
- net = net->next;
- }
-
- chr = def->serials;
- while (chr) {
- if (qemudGenerateXMLChar(&buf, chr, "serial") < 0)
- goto no_memory;
-
- chr = chr->next;
- }
-
- chr = def->parallels;
- while (chr) {
- if (qemudGenerateXMLChar(&buf, chr, "parallel") < 0)
- goto no_memory;
-
- chr = chr->next;
- }
-
- /* First serial device is the primary console */
- if (def->nserials > 0 &&
- qemudGenerateXMLChar(&buf, def->serials, "console") < 0)
- goto no_memory;
-
- input = def->inputs;
- while (input) {
- if (input->bus == QEMU_INPUT_BUS_USB)
- virBufferVSprintf(&buf, " <input type='%s' bus='usb'/>\n",
- input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet");
- input = input->next;
- }
- /* If graphics is enable, add implicit mouse */
- if (def->graphicsType != QEMUD_GRAPHICS_NONE)
- virBufferVSprintf(&buf, " <input type='mouse' bus='%s'/>\n",
- STREQ(def->os.type, "hvm") ? "ps2" : "xen");
-
- switch (def->graphicsType) {
- case QEMUD_GRAPHICS_VNC:
- virBufferAddLit(&buf, " <graphics type='vnc'");
-
- if (def->vncPort)
- virBufferVSprintf(&buf, " port='%d'",
- qemudIsActiveVM(vm) && live ? def->vncActivePort : def->vncPort);
-
- if (def->vncListen[0])
- virBufferVSprintf(&buf, " listen='%s'",
- def->vncListen);
-
- if (def->keymap)
- virBufferVSprintf(&buf, " keymap='%s'",
- def->keymap);
-
- virBufferAddLit(&buf, "/>\n");
- break;
-
- case QEMUD_GRAPHICS_SDL:
- virBufferAddLit(&buf, " <graphics type='sdl'/>\n");
- break;
-
- case QEMUD_GRAPHICS_NONE:
- default:
- break;
- }
-
- sound = def->sounds;
- while(sound) {
- const char *model = qemudSoundModelToString(sound->model);
- if (!model) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "%s", _("invalid sound model"));
- goto cleanup;
- }
- virBufferVSprintf(&buf, " <sound model='%s'/>\n", model);
- sound = sound->next;
- }
-
- virBufferAddLit(&buf, " </devices>\n");
- virBufferAddLit(&buf, "</domain>\n");
-
- if (virBufferError(&buf))
- goto no_memory;
-
- return virBufferContentAndReset(&buf);
-
- no_memory:
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
- "%s", _("failed to generate XML: out of memory"));
- cleanup:
- tmp = virBufferContentAndReset(&buf);
- VIR_FREE(tmp);
- return NULL;
-}
-
-
-int qemudDeleteConfig(virConnectPtr conn,
- struct qemud_driver *driver ATTRIBUTE_UNUSED,
- const char *configFile,
- const char *name) {
- if (!configFile[0]) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("no config file for %s"), name);
- return -1;
- }
-
- if (unlink(configFile) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot remove config for %s"), name);
- return -1;
- }
-
- return 0;
-}
-
#endif /* WITH_QEMU */
#include <pwd.h>
#include <stdio.h>
#include <sys/wait.h>
-#include <libxml/uri.h>
#if HAVE_NUMACTL
#include <numa.h>
#include <sched.h>
#endif
-#include "internal.h"
+#include "qemu_driver.h"
+#include "qemu_conf.h"
#include "c-ctype.h"
#include "event.h"
#include "buf.h"
#include "util.h"
-#include "qemu_driver.h"
-#include "qemu_conf.h"
#include "nodeinfo.h"
#include "stats_linux.h"
#include "capabilities.h"
static void qemudDispatchVMEvent(int fd, int events, void *opaque);
static int qemudStartVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm);
+ virDomainObjPtr vm,
+ const char *migrateFrom);
static void qemudShutdownVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm);
+ virDomainObjPtr vm);
static int qemudStartNetworkDaemon(virConnectPtr conn,
struct qemud_driver *driver,
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
static int qemudMonitorCommand (const struct qemud_driver *driver,
- const struct qemud_vm *vm,
+ const virDomainObjPtr vm,
const char *cmd,
char **reply);
static
void qemudAutostartConfigs(struct qemud_driver *driver) {
virNetworkObjPtr network;
- struct qemud_vm *vm;
+ virDomainObjPtr vm;
network = driver->networks;
while (network != NULL) {
network = next;
}
- vm = driver->vms;
+ vm = driver->domains;
while (vm != NULL) {
- struct qemud_vm *next = vm->next;
+ virDomainObjPtr next = vm->next;
if (vm->autostart &&
- !qemudIsActiveVM(vm) &&
- qemudStartVMDaemon(NULL, driver, vm) < 0) {
+ !virDomainIsActive(vm) &&
+ qemudStartVMDaemon(NULL, driver, vm, NULL) < 0) {
virErrorPtr err = virGetLastError();
qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s"),
vm->def->name, err->message);
qemu_driver->nextvmid = 1;
if (!uid) {
- if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
- goto snprintf_error;
+ if (asprintf(&qemu_driver->logDir,
+ "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
+ goto out_of_memory;
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
goto out_of_memory;
goto out_of_memory;
}
- if (snprintf(qemu_driver->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= PATH_MAX)
- goto snprintf_error;
+ if (asprintf(&qemu_driver->logDir,
+ "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+ goto out_of_memory;
if (asprintf (&base, "%s/.libvirt", pw->pw_dir) == -1) {
qemudLog (QEMUD_ERR,
return -1;
}
- if (qemudScanConfigs(qemu_driver) < 0) {
+ if (virDomainLoadAllConfigs(NULL,
+ qemu_driver->caps,
+ &qemu_driver->domains,
+ qemu_driver->configDir,
+ qemu_driver->autostartDir) < 0) {
qemudShutdown();
return -1;
}
return 0;
- snprintf_error:
- qemudLog(QEMUD_ERR,
- "%s", _("Resulting path to long for buffer in qemudInitPaths()"));
- return -1;
-
out_of_memory:
qemudLog (QEMUD_ERR,
"%s", _("qemudStartup: out of memory"));
*/
static int
qemudReload(void) {
- qemudScanConfigs(qemu_driver);
+ virDomainLoadAllConfigs(NULL,
+ qemu_driver->caps,
+ &qemu_driver->domains,
+ qemu_driver->configDir,
+ qemu_driver->autostartDir);
+
virNetworkLoadAllConfigs(NULL,
&qemu_driver->networks,
qemu_driver->networkConfigDir,
*/
static int
qemudActive(void) {
+ virDomainObjPtr dom = qemu_driver->domains;
virNetworkObjPtr net = qemu_driver->networks;
+ while (dom) {
+ if (virDomainIsActive(dom))
+ return 1;
+ dom = dom->next;
+ }
+
while (net) {
- if (net->active)
+ if (virNetworkIsActive(net))
return 1;
net = net->next;
}
- if (qemu_driver->nactivevms)
- return 1;
-
/* Otherwise we're happy to deal with a shutdown */
return 0;
}
*/
static int
qemudShutdown(void) {
- struct qemud_vm *vm;
+ virDomainObjPtr vm;
virNetworkObjPtr network;
if (!qemu_driver)
virCapabilitiesFree(qemu_driver->caps);
/* shutdown active VMs */
- vm = qemu_driver->vms;
+ vm = qemu_driver->domains;
while (vm) {
- struct qemud_vm *next = vm->next;
- if (qemudIsActiveVM(vm))
+ virDomainObjPtr next = vm->next;
+ if (virDomainIsActive(vm))
qemudShutdownVMDaemon(NULL, qemu_driver, vm);
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(qemu_driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&qemu_driver->domains,
+ vm);
vm = next;
}
/* free inactive VMs */
- vm = qemu_driver->vms;
+ vm = qemu_driver->domains;
while (vm) {
- struct qemud_vm *next = vm->next;
- qemudFreeVM(vm);
+ virDomainObjPtr next = vm->next;
+ virDomainObjFree(vm);
vm = next;
}
- qemu_driver->vms = NULL;
- qemu_driver->nactivevms = 0;
- qemu_driver->ninactivevms = 0;
+ qemu_driver->domains = NULL;
/* shutdown active networks */
network = qemu_driver->networks;
}
qemu_driver->networks = NULL;
+ VIR_FREE(qemu_driver->logDir);
VIR_FREE(qemu_driver->configDir);
VIR_FREE(qemu_driver->autostartDir);
VIR_FREE(qemu_driver->networkConfigDir);
/* Return -1 for error, 1 to continue reading and 0 for success */
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
+ virDomainObjPtr vm,
const char *output,
int fd);
static int
qemudReadMonitorOutput(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
+ virDomainObjPtr vm,
int fd,
char *buf,
int buflen,
static int
qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
- struct qemud_vm *vm,
+ virDomainObjPtr vm,
const char *output,
int fd)
{
static int qemudOpenMonitor(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
+ virDomainObjPtr vm,
const char *monitor) {
int monfd;
char buf[1024];
return ret;
}
-static int qemudExtractMonitorPath(const char *haystack,
+static int qemudExtractMonitorPath(virConnectPtr conn,
+ const char *haystack,
size_t *offset,
- char *path, int pathmax) {
+ char **path) {
static const char needle[] = "char device redirected to";
- char *tmp;
+ char *tmp, *dev;
+ VIR_FREE(*path);
/* First look for our magic string */
- if (!(tmp = strstr(haystack + *offset, needle)))
- return -1;
-
- /* Grab all the trailing data */
- strncpy(path, tmp+sizeof(needle), pathmax-1);
- path[pathmax-1] = '\0';
-
- /* Update offset to point to where we found the needle..*/
- *offset = tmp - haystack;
+ if (!(tmp = strstr(haystack + *offset, needle))) {
+ return 1;
+ }
+ tmp += sizeof(needle);
+ dev = tmp;
/*
* And look for first whitespace character and nul terminate
* to mark end of the pty path
*/
- tmp = path;
while (*tmp) {
if (c_isspace(*tmp)) {
- *tmp = '\0';
+ if (VIR_ALLOC_N(*path, (tmp-dev)+1) < 0) {
+ qemudReportError(conn, NULL, NULL,
+ VIR_ERR_NO_MEMORY, NULL);
+ return -1;
+ }
+ strncpy(*path, dev, (tmp-dev));
+ (*path)[(tmp-dev)] = '\0';
/* ... now further update offset till we get EOL */
- *offset += (sizeof(needle)-1) + strlen(path);
+ *offset += tmp - haystack;
return 0;
}
tmp++;
* least see a \n - indicate that we want to carry
* on trying again
*/
- return -1;
+ return 1;
}
static int
qemudFindCharDevicePTYs(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm,
+ virDomainObjPtr vm,
const char *output,
int fd ATTRIBUTE_UNUSED)
{
- char monitor[PATH_MAX];
+ char *monitor = NULL;
size_t offset = 0;
- struct qemud_vm_chr_def *chr;
+ virDomainChrDefPtr chr;
+ int ret;
/* The order in which QEMU prints out the PTY paths is
the order in which it procsses its monitor, serial
ordering.... */
/* So first comes the monitor device */
- if (qemudExtractMonitorPath(output, &offset, monitor, sizeof(monitor)) < 0)
- return 1; /* keep reading */
+ if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
+ goto cleanup;
/* then the serial devices */
chr = vm->def->serials;
while (chr) {
- if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
- if (qemudExtractMonitorPath(output, &offset,
- chr->srcData.file.path,
- sizeof(chr->srcData.file.path)) < 0)
- return 1; /* keep reading */
+ if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+ if ((ret = qemudExtractMonitorPath(conn, output, &offset,
+ &chr->data.file.path)) != 0)
+ goto cleanup;
}
chr = chr->next;
}
/* and finally the parallel devices */
chr = vm->def->parallels;
while (chr) {
- if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
- if (qemudExtractMonitorPath(output, &offset,
- chr->srcData.file.path,
- sizeof(chr->srcData.file.path)) < 0)
- return 1; /* keep reading */
+ if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+ if ((ret = qemudExtractMonitorPath(conn, output, &offset,
+ &chr->data.file.path)) != 0)
+ goto cleanup;
}
chr = chr->next;
}
/* Got them all, so now open the monitor console */
- return qemudOpenMonitor(conn, driver, vm, monitor);
+ ret = qemudOpenMonitor(conn, driver, vm, monitor);
+
+cleanup:
+ VIR_FREE(monitor);
+ return ret;
}
static int qemudWaitForMonitor(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm) {
+ virDomainObjPtr vm) {
char buf[1024]; /* Plenty of space to get startup greeting */
int ret = qemudReadMonitorOutput(conn,
driver, vm, vm->stderr,
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm) {
+ virDomainObjPtr vm) {
char *qemucpus = NULL;
char *line;
int lastVcpu = -1;
/* Only KVM has seperate threads for CPUs,
others just use main QEMU process for CPU */
- if (vm->def->virtType != QEMUD_VIRT_KVM)
+ if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
vm->nvcpupids = 1;
else
vm->nvcpupids = vm->def->vcpus;
return -1;
}
- if (vm->def->virtType != QEMUD_VIRT_KVM) {
+ if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
vm->vcpupids[0] = vm->pid;
return 0;
}
static int
qemudInitCpus(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm) {
+ virDomainObjPtr vm) {
char *info = NULL;
#if HAVE_SCHED_GETAFFINITY
cpu_set_t mask;
static int qemudStartVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
- struct qemud_vm *vm) {
+ virDomainObjPtr vm,
+ const char *migrateFrom) {
char **argv = NULL, **tmp;
int i, ret;
char logfile[PATH_MAX];
struct stat sb;
+ int *tapfds = NULL;
+ int ntapfds = 0;
+ int qemuCmdFlags;
- if (qemudIsActiveVM(vm)) {
+ if (virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("VM is already active"));
return -1;
}
- if (vm->def->vncPort < 0) {
+ if (vm->def->graphics &&
+ vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ vm->def->graphics->data.vnc.autoport) {
int port = qemudNextFreeVNCPort(driver);
if (port < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to find an unused VNC port"));
return -1;
}
- vm->def->vncActivePort = port;
- } else
- vm->def->vncActivePort = vm->def->vncPort;
+ vm->def->graphics->data.vnc.port = port;
+ }
if ((strlen(driver->logDir) + /* path */
1 + /* Separator */
* 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) {
+ if (stat(vm->def->emulator, &sb) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Cannot find QEMU binary %s: %s"),
- vm->def->os.binary,
+ vm->def->emulator,
strerror(errno));
return -1;
}
+ if (qemudExtractVersionInfo(vm->def->emulator,
+ NULL,
+ &qemuCmdFlags) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Cannot determine QEMU argv syntax %s"),
+ vm->def->emulator);
+ return -1;
+ }
- if (qemudBuildCommandLine(conn, driver, vm, &argv) < 0) {
+ if (qemudBuildCommandLine(conn, driver, vm,
+ qemuCmdFlags, &argv,
+ &tapfds, &ntapfds, migrateFrom) < 0) {
close(vm->logfile);
vm->logfile = -1;
return -1;
ret = virExecNonBlock(conn, argv, &vm->pid,
vm->stdin, &vm->stdout, &vm->stderr);
if (ret == 0) {
- vm->id = driver->nextvmid++;
- vm->state = vm->migrateFrom[0] ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
-
- driver->ninactivevms--;
- driver->nactivevms++;
+ vm->def->id = driver->nextvmid++;
+ vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
}
for (i = 0 ; argv[i] ; i++)
VIR_FREE(argv[i]);
VIR_FREE(argv);
- if (vm->tapfds) {
- for (i = 0; vm->tapfds[i] != -1; i++) {
- close(vm->tapfds[i]);
- vm->tapfds[i] = -1;
+ if (tapfds) {
+ for (i = 0 ; i < ntapfds ; i++) {
+ close(tapfds[i]);
}
- VIR_FREE(vm->tapfds);
- vm->ntapfds = 0;
+ VIR_FREE(tapfds);
}
if (ret == 0) {
}
static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED,
- struct qemud_vm *vm, int fd) {
+ virDomainObjPtr vm, int fd) {
char buf[4096];
if (vm->pid < 0)
return 0;
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
- struct qemud_driver *driver, struct qemud_vm *vm) {
- if (!qemudIsActiveVM(vm))
+ struct qemud_driver *driver, virDomainObjPtr vm) {
+ if (!virDomainIsActive(vm))
return;
qemudLog(QEMUD_INFO, _("Shutting down VM '%s'"), vm->def->name);
}
vm->pid = -1;
- vm->id = -1;
+ vm->def->id = -1;
vm->state = VIR_DOMAIN_SHUTOFF;
VIR_FREE(vm->vcpupids);
vm->nvcpupids = 0;
if (vm->newDef) {
- qemudFreeVMDef(vm->def);
+ virDomainDefFree(vm->def);
vm->def = vm->newDef;
+ vm->def->id = -1;
vm->newDef = NULL;
}
-
- driver->nactivevms--;
- driver->ninactivevms++;
}
-static int qemudDispatchVMLog(struct qemud_driver *driver, struct qemud_vm *vm, int fd) {
+static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) {
if (qemudVMData(driver, vm, fd) < 0) {
qemudShutdownVMDaemon(NULL, driver, vm);
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&driver->domains,
+ vm);
}
return 0;
}
-static int qemudDispatchVMFailure(struct qemud_driver *driver, struct qemud_vm *vm,
+static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm,
int fd ATTRIBUTE_UNUSED) {
qemudShutdownVMDaemon(NULL, driver, vm);
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return 0;
}
static void qemudDispatchVMEvent(int fd, int events, void *opaque) {
struct qemud_driver *driver = (struct qemud_driver *)opaque;
- struct qemud_vm *vm = driver->vms;
+ virDomainObjPtr vm = driver->domains;
while (vm) {
- if (qemudIsActiveVM(vm) &&
+ if (virDomainIsActive(vm) &&
(vm->stdout == fd ||
vm->stderr == fd))
break;
static int
qemudMonitorCommand (const struct qemud_driver *driver ATTRIBUTE_UNUSED,
- const struct qemud_vm *vm,
+ const virDomainObjPtr vm,
const char *cmd,
char **reply) {
int size = 0;
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
- int id) {
+ int id) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID(driver, id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, id);
virDomainPtr dom;
if (!vm) {
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
- if (dom) dom->id = vm->id;
+ if (dom) dom->id = vm->def->id;
return dom;
}
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
- const unsigned char *uuid) {
+ const unsigned char *uuid) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid);
virDomainPtr dom;
if (!vm) {
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
- if (dom) dom->id = vm->id;
+ if (dom) dom->id = vm->def->id;
return dom;
}
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
- const char *name) {
+ const char *name) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm *vm = qemudFindVMByName(driver, name);
+ virDomainObjPtr vm = virDomainFindByName(driver->domains, name);
virDomainPtr dom;
if (!vm) {
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
- if (dom) dom->id = vm->id;
+ if (dom) dom->id = vm->def->id;
return dom;
}
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm *vm = driver->vms;
+ virDomainObjPtr vm = driver->domains;
int got = 0;
while (vm && got < nids) {
- if (qemudIsActiveVM(vm)) {
- ids[got] = vm->id;
+ if (virDomainIsActive(vm)) {
+ ids[got] = vm->def->id;
got++;
}
vm = vm->next;
}
static int qemudNumDomains(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- return driver->nactivevms;
+ int n = 0;
+ virDomainObjPtr dom = driver->domains;
+ while (dom) {
+ if (virDomainIsActive(dom))
+ n++;
+ dom = dom->next;
+ }
+ return n;
}
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
unsigned int flags ATTRIBUTE_UNUSED) {
- struct qemud_vm_def *def;
- struct qemud_vm *vm;
+ virDomainDefPtr def;
+ virDomainObjPtr vm;
virDomainPtr dom;
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- if (!(def = qemudParseVMDef(conn, driver, xml, NULL)))
+ if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
return NULL;
- if (!(vm = qemudAssignVMDef(conn, driver, def))) {
- qemudFreeVMDef(def);
+ if (!(vm = virDomainAssignDef(conn,
+ &driver->domains,
+ def))) {
+ virDomainDefFree(def);
return NULL;
}
- if (qemudStartVMDaemon(conn, driver, vm) < 0) {
- qemudRemoveInactiveVM(driver, vm);
+ if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return NULL;
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
- if (dom) dom->id = vm->id;
+ if (dom) dom->id = vm->def->id;
return dom;
}
static int qemudDomainSuspend(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
char *info;
- struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
static int qemudDomainResume(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
char *info;
- struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
static int qemudDomainShutdown(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
char* info;
if (!vm) {
static int qemudDomainDestroy(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
}
qemudShutdownVMDaemon(dom->conn, driver, vm);
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return 0;
}
static char *qemudDomainGetOSType(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
char *type;
if (!vm) {
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
return -1;
}
- if (qemudIsActiveVM(vm)) {
+ if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cannot set memory of an active domain"));
return -1;
}
static int qemudDomainGetInfo(virDomainPtr dom,
- virDomainInfoPtr info) {
+ virDomainInfoPtr info) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
info->state = vm->state;
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
info->cpuTime = 0;
} else {
if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
static int qemudDomainSave(virDomainPtr dom,
const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
char *command, *info;
int fd;
char *safe_path;
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
}
/* Get XML for the domain */
- xml = qemudGenerateXML(dom->conn, driver, vm, vm->def, 0);
+ xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
if (!xml) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to get domain xml"));
/* Shut it down */
qemudShutdownVMDaemon(dom->conn, driver, vm);
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return 0;
}
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
const struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
int max;
if (!vm) {
return -1;
}
- if (qemudIsActiveVM(vm)) {
+ if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
_("cannot change vcpu count of an active domain"));
return -1;
unsigned char *cpumap,
int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
cpu_set_t mask;
int i, maxcpu;
virNodeInfo nodeinfo;
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive domain"));
return -1;
unsigned char *cpumaps,
int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
virNodeInfo nodeinfo;
int i, v, maxcpu;
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive domain"));
return -1;
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
const char *type;
int ret;
return -1;
}
- if (!(type = qemudVirtTypeToString(vm->def->virtType))) {
+ if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("unknown virt type in domain definition '%d'"),
vm->def->virtType);
static int qemudDomainRestore(virConnectPtr conn,
const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm_def *def;
- struct qemud_vm *vm;
+ virDomainDefPtr def;
+ virDomainObjPtr vm;
int fd;
int ret;
char *xml;
}
/* Create a domain from this XML */
- if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) {
+ if (!(def = virDomainDefParseString(conn, driver->caps, xml))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to parse XML"));
close(fd);
VIR_FREE(xml);
/* Ensure the name and UUID don't already exist in an active VM */
- vm = qemudFindVMByUUID(driver, def->uuid);
- if (!vm) vm = qemudFindVMByName(driver, def->name);
- if (vm && qemudIsActiveVM(vm)) {
+ vm = virDomainFindByUUID(driver->domains, def->uuid);
+ if (!vm)
+ vm = virDomainFindByName(driver->domains, def->name);
+ if (vm && virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain is already active as '%s'"), vm->def->name);
close(fd);
return -1;
}
- if (!(vm = qemudAssignVMDef(conn, driver, def))) {
+ if (!(vm = virDomainAssignDef(conn,
+ &driver->domains,
+ def))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM"));
- qemudFreeVMDef(def);
+ virDomainDefFree(def);
close(fd);
return -1;
}
/* Set the migration source and start it up. */
- snprintf(vm->migrateFrom, sizeof(vm->migrateFrom), "stdio");
vm->stdin = fd;
- ret = qemudStartVMDaemon(conn, driver, vm);
+ ret = qemudStartVMDaemon(conn, driver, vm, "stdio");
close(fd);
- vm->migrateFrom[0] = '\0';
vm->stdin = -1;
if (ret < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to start VM"));
- if (!vm->configFile[0])
- qemudRemoveInactiveVM(driver, vm);
+ if (!vm->configFile)
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return -1;
}
static char *qemudDomainDumpXML(virDomainPtr dom,
- int flags ATTRIBUTE_UNUSED) {
+ int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return NULL;
}
- return qemudGenerateXML(dom->conn, driver, vm, vm->def, 1);
+ return virDomainDefFormat(dom->conn,
+ (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
+ vm->newDef : vm->def,
+ flags);
}
static int qemudListDefinedDomains(virConnectPtr conn,
char **const names, int nnames) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm *vm = driver->vms;
+ virDomainObjPtr vm = driver->domains;
int got = 0, i;
while (vm && got < nnames) {
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
if (!(names[got] = strdup(vm->def->name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for VM name string"));
static int qemudNumDefinedDomains(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- return driver->ninactivevms;
+ int n = 0;
+ virDomainObjPtr dom = driver->domains;
+ while (dom) {
+ if (!virDomainIsActive(dom))
+ n++;
+ dom = dom->next;
+ }
+ return n;
}
static int qemudDomainStart(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
return -1;
}
- return qemudStartVMDaemon(dom->conn, driver, vm);
+ return qemudStartVMDaemon(dom->conn, driver, vm, NULL);
}
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- struct qemud_vm_def *def;
- struct qemud_vm *vm;
+ virDomainDefPtr def;
+ virDomainObjPtr vm;
virDomainPtr dom;
- if (!(def = qemudParseVMDef(conn, driver, xml, NULL)))
+ if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
return NULL;
- if (!(vm = qemudAssignVMDef(conn, driver, def))) {
- qemudFreeVMDef(def);
+ if (!(vm = virDomainAssignDef(conn,
+ &driver->domains,
+ def))) {
+ virDomainDefFree(def);
return NULL;
}
- if (qemudSaveVMDef(conn, driver, vm, def) < 0) {
- qemudRemoveInactiveVM(driver, vm);
+ if (virDomainSaveConfig(conn,
+ driver->configDir,
+ driver->autostartDir,
+ vm) < 0) {
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return NULL;
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
- if (dom) dom->id = vm->id;
+ if (dom) dom->id = vm->def->id;
return dom;
}
static int qemudDomainUndefine(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
return -1;
}
- if (qemudIsActiveVM(vm)) {
+ if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot delete active domain"));
return -1;
}
- if (qemudDeleteConfig(dom->conn, driver, vm->configFile, vm->def->name) < 0)
+ if (virDomainDeleteConfig(dom->conn, vm) < 0)
return -1;
- if (unlink(vm->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR)
- qemudLog(QEMUD_WARN, _("Failed to delete autostart link '%s': %s"),
- vm->autostartLink, strerror(errno));
-
- vm->configFile[0] = '\0';
- vm->autostartLink[0] = '\0';
-
- qemudRemoveInactiveVM(driver, vm);
+ virDomainRemoveInactive(&driver->domains,
+ vm);
return 0;
}
static int qemudDomainChangeCDROM(virDomainPtr dom,
- struct qemud_vm *vm,
- struct qemud_vm_disk_def *olddisk,
- struct qemud_vm_disk_def *newdisk) {
+ virDomainObjPtr vm,
+ virDomainDiskDefPtr olddisk,
+ virDomainDiskDefPtr newdisk) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
char *cmd, *reply, *safe_path;
- if (newdisk->src[0]) {
+ if (newdisk->src) {
safe_path = qemudEscapeMonitorArg(newdisk->src);
if (!safe_path) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
static int qemudDomainAttachDevice(virDomainPtr dom,
const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
- struct qemud_vm_device_def *dev;
- struct qemud_vm_disk_def *disk;
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ virDomainDeviceDefPtr dev;
+ virDomainDiskDefPtr disk;
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot attach device on inactive domain"));
return -1;
}
- dev = qemudParseVMDeviceDef(dom->conn, vm->def, xml);
+ dev = virDomainDeviceDefParse(dom->conn, vm->def, xml);
if (dev == NULL) {
return -1;
}
- if (dev->type != QEMUD_DEVICE_DISK || dev->data.disk.device != QEMUD_DISK_CDROM) {
+ if (dev->type != VIR_DOMAIN_DEVICE_DISK ||
+ dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("only CDROM disk devices can be attached"));
VIR_FREE(dev);
disk = vm->def->disks;
while (disk) {
- if (disk->device == QEMUD_DISK_CDROM &&
- STREQ(disk->dst, dev->data.disk.dst))
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+ STREQ(disk->dst, dev->data.disk->dst))
break;
disk = disk->next;
}
return -1;
}
- if (qemudDomainChangeCDROM(dom, vm, disk, &dev->data.disk) < 0) {
+ if (qemudDomainChangeCDROM(dom, vm, disk, dev->data.disk) < 0) {
VIR_FREE(dev);
return -1;
}
static int qemudDomainGetAutostart(virDomainPtr dom,
int *autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
static int qemudDomainSetAutostart(virDomainPtr dom,
int autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
const char *p, *eol;
char qemu_dev_name[32];
size_t len;
- const struct qemud_vm *vm = qemudFindVMByID(driver, dom->id);
+ const virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
return -1;
}
- if (!qemudIsActiveVM (vm)) {
+ if (!virDomainIsActive (vm)) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
{
#ifdef __linux__
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID (driver, dom->id);
- struct qemud_vm_net_def *net;
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
+ virDomainNetDefPtr net;
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
/* Check the path is one of the domain's network interfaces. */
for (net = vm->def->nets; net; net = net->next) {
- switch (net->type) {
- case QEMUD_NET_NETWORK:
- if (STREQ (net->dst.network.ifname, path))
- goto ok;
- break;
- case QEMUD_NET_ETHERNET:
- if (STREQ (net->dst.ethernet.ifname, path))
- goto ok;
- break;
- case QEMUD_NET_BRIDGE:
- if (STREQ (net->dst.bridge.ifname, path))
- goto ok;
- break;
- }
+ if (STREQ (net->ifname, path))
+ goto ok;
}
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
unsigned int flags ATTRIBUTE_UNUSED)
{
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByUUID (driver, dom->uuid);
- int i;
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ virDomainDiskDefPtr disk;
int fd, ret = -1;
if (!vm) {
}
/* Check the path belongs to this domain. */
- for (i = 0; i < vm->def->ndisks; ++i) {
- if (STREQ (vm->def->disks[i].src, path)) goto found;
+ for (disk = vm->def->disks ; disk != NULL ; disk = disk->next) {
+ if (disk->src != NULL &&
+ STREQ (disk->src, path)) goto found;
}
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("invalid path"));
unsigned int flags)
{
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- struct qemud_vm *vm = qemudFindVMByID (driver, dom->id);
+ virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id);
char cmd[256], *info;
char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
int fd = -1, ret = -1;
return -1;
}
- if (!qemudIsActiveVM(vm)) {
+ if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
return -1;
}
static virNetworkPtr qemudNetworkCreate(virConnectPtr conn, const char *xml) {
- struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
+ struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
virNetworkDefPtr def;
virNetworkObjPtr network;
virNetworkPtr net;