2011-02-21 13:40:10 +00:00
|
|
|
/*
|
|
|
|
* xen_xm.c: Xen XM parsing functions
|
|
|
|
*
|
2014-03-24 18:14:48 +00:00
|
|
|
* Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
|
2011-02-21 13:40:10 +00:00
|
|
|
* Copyright (C) 2011 Univention GmbH
|
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-02-21 13:40:10 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
* Author: Markus Groß <gross@univention.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2011-02-21 13:40:10 +00:00
|
|
|
#include "verify.h"
|
|
|
|
#include "xenxs_private.h"
|
|
|
|
#include "xen_xm.h"
|
2011-04-14 16:05:14 +00:00
|
|
|
#include "domain_conf.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2014-08-16 02:52:15 +00:00
|
|
|
#include "xen_common.h"
|
2014-08-07 18:32:54 +00:00
|
|
|
|
2016-01-20 18:36:26 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_XENXM
|
2014-08-07 18:32:54 +00:00
|
|
|
|
2015-03-20 00:28:49 +00:00
|
|
|
static int
|
|
|
|
xenParseXMOS(virConfPtr conf, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2015-03-20 00:28:49 +00:00
|
|
|
const char *boot;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(def->os.loader) < 0 ||
|
|
|
|
xenConfigCopyString(conf, "kernel", &def->os.loader->path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
|
|
|
|
switch (boot[i]) {
|
|
|
|
case 'a':
|
|
|
|
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
default:
|
|
|
|
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
def->os.nBootDevs++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *extra, *root;
|
|
|
|
|
|
|
|
if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
|
|
|
|
return -1;
|
|
|
|
if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (xenConfigGetString(conf, "root", &root, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (root) {
|
|
|
|
if (virAsprintf(&def->os.cmdline, "root=%s %s", root, extra) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(def->os.cmdline, extra) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-07 18:32:55 +00:00
|
|
|
static int
|
2015-12-05 02:11:39 +00:00
|
|
|
xenParseXMDisk(virConfPtr conf, virDomainDefPtr def)
|
2014-03-18 08:14:16 +00:00
|
|
|
{
|
2011-02-21 13:40:10 +00:00
|
|
|
virDomainDiskDefPtr disk = NULL;
|
2015-04-17 00:11:06 +00:00
|
|
|
int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
|
2014-08-07 18:32:55 +00:00
|
|
|
virConfValuePtr list = virConfGetValue(conf, "disk");
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
if (list && list->type == VIR_CONF_LIST) {
|
|
|
|
list = list->list;
|
|
|
|
while (list) {
|
|
|
|
char *head;
|
|
|
|
char *offset;
|
|
|
|
char *tmp;
|
2014-03-24 18:14:48 +00:00
|
|
|
const char *src;
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
|
|
|
|
goto skipdisk;
|
|
|
|
|
2014-08-07 18:32:55 +00:00
|
|
|
head = list->str;
|
2015-05-13 07:00:02 +00:00
|
|
|
if (!(disk = virDomainDiskDefNew(NULL)))
|
2014-08-07 18:32:55 +00:00
|
|
|
return -1;
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Disks have 3 components, SOURCE,DEST-DEVICE,MODE
|
|
|
|
* eg, phy:/dev/HostVG/XenGuest1,xvda,w
|
|
|
|
* The SOURCE is usually prefixed with a driver type,
|
|
|
|
* and optionally driver sub-type
|
|
|
|
* The DEST-DEVICE is optionally post-fixed with disk type
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Extract the source file path*/
|
|
|
|
if (!(offset = strchr(head, ',')))
|
|
|
|
goto skipdisk;
|
|
|
|
|
|
|
|
if (offset == head) {
|
2014-03-24 18:14:48 +00:00
|
|
|
/* No source file given, eg CDROM with no media */
|
|
|
|
ignore_value(virDomainDiskSetSource(disk, NULL));
|
2011-02-21 13:40:10 +00:00
|
|
|
} else {
|
2014-03-24 18:14:48 +00:00
|
|
|
if (VIR_STRNDUP(tmp, head, offset - head) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2014-03-24 18:14:48 +00:00
|
|
|
if (virDomainDiskSetSource(disk, tmp) < 0) {
|
|
|
|
VIR_FREE(tmp);
|
2011-02-21 13:40:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-03-24 18:14:48 +00:00
|
|
|
VIR_FREE(tmp);
|
2011-02-21 13:40:10 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 18:32:55 +00:00
|
|
|
head = offset + 1;
|
2011-02-21 13:40:10 +00:00
|
|
|
/* Remove legacy ioemu: junk */
|
|
|
|
if (STRPREFIX(head, "ioemu:"))
|
|
|
|
head = head + 6;
|
|
|
|
|
|
|
|
/* Extract the dest device name */
|
|
|
|
if (!(offset = strchr(head, ',')))
|
|
|
|
goto skipdisk;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2011-02-21 13:40:10 +00:00
|
|
|
if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2011-02-21 13:40:10 +00:00
|
|
|
if (virStrncpy(disk->dst, head, offset - head,
|
|
|
|
(offset - head) + 1) == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Dest file %s too big for destination"), head);
|
2011-02-21 13:40:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-08-07 18:32:55 +00:00
|
|
|
head = offset + 1;
|
2011-02-21 13:40:10 +00:00
|
|
|
/* Extract source driver type */
|
2014-03-24 18:14:48 +00:00
|
|
|
src = virDomainDiskGetSource(disk);
|
|
|
|
if (src) {
|
|
|
|
size_t len;
|
2011-02-21 13:40:10 +00:00
|
|
|
/* The main type phy:, file:, tap: ... */
|
2014-03-24 18:14:48 +00:00
|
|
|
if ((tmp = strchr(src, ':')) != NULL) {
|
|
|
|
len = tmp - src;
|
|
|
|
if (VIR_STRNDUP(tmp, src, len) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2014-03-24 18:14:48 +00:00
|
|
|
if (virDomainDiskSetDriver(disk, tmp) < 0) {
|
|
|
|
VIR_FREE(tmp);
|
2011-02-21 13:40:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-03-24 18:14:48 +00:00
|
|
|
VIR_FREE(tmp);
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
/* Strip the prefix we found off the source file name */
|
2014-03-24 18:14:48 +00:00
|
|
|
if (virDomainDiskSetSource(disk, src + len + 1) < 0)
|
|
|
|
goto cleanup;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2014-03-24 18:14:48 +00:00
|
|
|
src = virDomainDiskGetSource(disk);
|
2011-02-21 13:40:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* And the sub-type for tap:XXX: type */
|
2014-03-24 18:14:48 +00:00
|
|
|
if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap")) {
|
2012-10-15 21:47:42 +00:00
|
|
|
char *driverType;
|
|
|
|
|
2014-03-24 18:14:48 +00:00
|
|
|
if (!(tmp = strchr(src, ':')))
|
2011-02-21 13:40:10 +00:00
|
|
|
goto skipdisk;
|
2014-03-24 18:14:48 +00:00
|
|
|
len = tmp - src;
|
2012-10-15 21:47:42 +00:00
|
|
|
|
2014-03-24 18:14:48 +00:00
|
|
|
if (VIR_STRNDUP(driverType, src, len) < 0)
|
2013-05-03 12:51:56 +00:00
|
|
|
goto cleanup;
|
2014-08-07 18:32:55 +00:00
|
|
|
|
2012-10-15 21:47:42 +00:00
|
|
|
if (STREQ(driverType, "aio"))
|
2014-03-24 18:14:48 +00:00
|
|
|
virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
|
2012-10-15 21:47:42 +00:00
|
|
|
else
|
2014-03-24 18:14:48 +00:00
|
|
|
virDomainDiskSetFormat(disk,
|
|
|
|
virStorageFileFormatTypeFromString(driverType));
|
2012-10-15 21:47:42 +00:00
|
|
|
VIR_FREE(driverType);
|
2014-03-24 18:14:48 +00:00
|
|
|
if (virDomainDiskGetFormat(disk) <= 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2012-10-15 21:47:42 +00:00
|
|
|
_("Unknown driver type %s"),
|
2014-03-24 18:14:48 +00:00
|
|
|
src);
|
2011-02-21 13:40:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Strip the prefix we found off the source file name */
|
2014-03-24 18:14:48 +00:00
|
|
|
if (virDomainDiskSetSource(disk, src + len + 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
src = virDomainDiskGetSource(disk);
|
2011-02-21 13:40:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No source, or driver name, so fix to phy: */
|
2014-03-24 18:14:48 +00:00
|
|
|
if (!virDomainDiskGetDriver(disk) &&
|
|
|
|
virDomainDiskSetDriver(disk, "phy") < 0)
|
2013-05-03 12:51:56 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
/* phy: type indicates a block device */
|
2014-03-24 18:14:48 +00:00
|
|
|
virDomainDiskSetType(disk,
|
|
|
|
STREQ(virDomainDiskGetDriver(disk), "phy") ?
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
VIR_STORAGE_TYPE_BLOCK :
|
|
|
|
VIR_STORAGE_TYPE_FILE);
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
/* Check for a :cdrom/:disk postfix */
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
|
|
|
if ((tmp = strchr(disk->dst, ':')) != NULL) {
|
|
|
|
if (STREQ(tmp, ":cdrom"))
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
|
|
|
tmp[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STRPREFIX(disk->dst, "xvd") || !hvm) {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
|
|
|
|
} else if (STRPREFIX(disk->dst, "sd")) {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
|
|
|
|
} else {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ(head, "r") ||
|
|
|
|
STREQ(head, "ro"))
|
2014-06-24 13:15:55 +00:00
|
|
|
disk->src->readonly = true;
|
2011-02-21 13:40:10 +00:00
|
|
|
else if ((STREQ(head, "w!")) ||
|
|
|
|
(STREQ(head, "!")))
|
2014-06-24 13:15:55 +00:00
|
|
|
disk->src->shared = true;
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
/* Maintain list in sorted order according to target device name */
|
2014-03-07 08:33:31 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:10 +00:00
|
|
|
|
|
|
|
skipdisk:
|
|
|
|
list = list->next;
|
|
|
|
virDomainDiskDefFree(disk);
|
2014-08-27 11:48:37 +00:00
|
|
|
disk = NULL;
|
2011-02-21 13:40:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 18:32:55 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-07 18:32:56 +00:00
|
|
|
static int
|
2014-08-16 02:52:15 +00:00
|
|
|
xenFormatXMDisk(virConfValuePtr list,
|
2015-12-05 02:11:39 +00:00
|
|
|
virDomainDiskDefPtr disk)
|
2014-08-07 18:32:56 +00:00
|
|
|
{
|
2014-08-16 02:52:15 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
virConfValuePtr val, tmp;
|
|
|
|
const char *src = virDomainDiskGetSource(disk);
|
|
|
|
int format = virDomainDiskGetFormat(disk);
|
|
|
|
const char *driver = virDomainDiskGetDriver(disk);
|
2014-08-07 18:32:56 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
if (src) {
|
|
|
|
if (format) {
|
|
|
|
const char *type;
|
2014-08-07 18:32:56 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
if (format == VIR_STORAGE_FILE_RAW)
|
|
|
|
type = "aio";
|
|
|
|
else
|
|
|
|
type = virStorageFileFormatTypeToString(format);
|
|
|
|
virBufferAsprintf(&buf, "%s:", driver);
|
|
|
|
if (STREQ(driver, "tap"))
|
|
|
|
virBufferAsprintf(&buf, "%s:", type);
|
2014-08-07 18:32:56 +00:00
|
|
|
} else {
|
2014-08-16 02:52:15 +00:00
|
|
|
switch (virDomainDiskGetType(disk)) {
|
|
|
|
case VIR_STORAGE_TYPE_FILE:
|
|
|
|
virBufferAddLit(&buf, "file:");
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_TYPE_BLOCK:
|
|
|
|
virBufferAddLit(&buf, "phy:");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unsupported disk type %s"),
|
|
|
|
virStorageTypeToString(virDomainDiskGetType(disk)));
|
2014-08-07 18:32:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2014-08-16 02:52:15 +00:00
|
|
|
virBufferAdd(&buf, src, -1);
|
2014-08-07 18:32:56 +00:00
|
|
|
}
|
2014-08-16 02:52:15 +00:00
|
|
|
virBufferAddLit(&buf, ",");
|
2014-08-07 18:32:56 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
virBufferAdd(&buf, disk->dst, -1);
|
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
|
|
|
virBufferAddLit(&buf, ":cdrom");
|
2014-08-07 18:32:56 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
if (disk->src->readonly)
|
|
|
|
virBufferAddLit(&buf, ",r");
|
|
|
|
else if (disk->src->shared)
|
|
|
|
virBufferAddLit(&buf, ",!");
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, ",w");
|
|
|
|
if (disk->transient) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("transient disks not supported yet"));
|
2014-08-11 21:21:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
if (virBufferCheckError(&buf) < 0)
|
|
|
|
goto cleanup;
|
2014-08-11 21:21:28 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
if (VIR_ALLOC(val) < 0)
|
|
|
|
goto cleanup;
|
2014-08-11 21:21:28 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
val->type = VIR_CONF_STRING;
|
|
|
|
val->str = virBufferContentAndReset(&buf);
|
|
|
|
tmp = list->list;
|
|
|
|
while (tmp && tmp->next)
|
|
|
|
tmp = tmp->next;
|
|
|
|
if (tmp)
|
|
|
|
tmp->next = val;
|
|
|
|
else
|
|
|
|
list->list = val;
|
2014-08-11 21:21:28 +00:00
|
|
|
|
|
|
|
return 0;
|
2014-08-11 21:21:29 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
cleanup:
|
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
return -1;
|
2014-08-11 21:21:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-11 21:21:30 +00:00
|
|
|
static int
|
2015-12-05 02:11:39 +00:00
|
|
|
xenFormatXMDisks(virConfPtr conf, virDomainDefPtr def)
|
2014-08-11 21:21:30 +00:00
|
|
|
{
|
|
|
|
virConfValuePtr diskVal = NULL;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(diskVal) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
diskVal->type = VIR_CONF_LIST;
|
|
|
|
diskVal->list = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
|
|
|
if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
|
|
|
|
continue;
|
|
|
|
|
2015-12-05 02:11:39 +00:00
|
|
|
if (xenFormatXMDisk(diskVal, def->disks[i]) < 0)
|
2014-08-11 21:21:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (diskVal->list != NULL) {
|
|
|
|
int ret = virConfSetValue(conf, "disk", diskVal);
|
|
|
|
diskVal = NULL;
|
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
VIR_FREE(diskVal);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virConfFreeValue(diskVal);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-06 14:36:13 +00:00
|
|
|
static int
|
|
|
|
xenParseXMInputDevs(virConfPtr conf, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2015-03-06 14:36:13 +00:00
|
|
|
if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
if (str &&
|
|
|
|
(STREQ(str, "tablet") ||
|
|
|
|
STREQ(str, "mouse") ||
|
|
|
|
STREQ(str, "keyboard"))) {
|
|
|
|
virDomainInputDefPtr input;
|
|
|
|
if (VIR_ALLOC(input) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
input->bus = VIR_DOMAIN_INPUT_BUS_USB;
|
|
|
|
if (STREQ(str, "mouse"))
|
|
|
|
input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
|
|
|
|
else if (STREQ(str, "tablet"))
|
|
|
|
input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
|
|
|
|
else if (STREQ(str, "keyboard"))
|
|
|
|
input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
|
|
|
|
if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) {
|
|
|
|
virDomainInputDefFree(input);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
/*
|
|
|
|
* Convert an XM config record into a virDomainDef object.
|
|
|
|
*/
|
|
|
|
virDomainDefPtr
|
|
|
|
xenParseXM(virConfPtr conf,
|
2015-11-28 04:33:55 +00:00
|
|
|
virCapsPtr caps,
|
|
|
|
virDomainXMLOptionPtr xmlopt)
|
2014-08-11 21:21:34 +00:00
|
|
|
{
|
2014-08-16 02:52:15 +00:00
|
|
|
virDomainDefPtr def = NULL;
|
2014-08-11 21:21:34 +00:00
|
|
|
|
2015-02-16 15:30:11 +00:00
|
|
|
if (!(def = virDomainDefNew()))
|
2014-08-16 02:52:15 +00:00
|
|
|
return NULL;
|
2014-08-11 21:21:34 +00:00
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
def->virtType = VIR_DOMAIN_VIRT_XEN;
|
|
|
|
def->id = -1;
|
2014-08-13 20:46:16 +00:00
|
|
|
|
2015-12-05 02:11:39 +00:00
|
|
|
if (xenParseConfigCommon(conf, def, caps) < 0)
|
2014-08-13 20:46:16 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-20 00:28:49 +00:00
|
|
|
if (xenParseXMOS(conf, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-12-05 02:11:39 +00:00
|
|
|
if (xenParseXMDisk(conf, def) < 0)
|
2014-08-16 02:52:15 +00:00
|
|
|
goto cleanup;
|
2014-08-13 20:46:16 +00:00
|
|
|
|
2015-03-06 14:36:13 +00:00
|
|
|
if (xenParseXMInputDevs(conf, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-11-28 04:33:55 +00:00
|
|
|
if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
|
|
|
|
xmlopt) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
return def;
|
2014-08-13 20:46:16 +00:00
|
|
|
|
|
|
|
cleanup:
|
2014-08-16 02:52:15 +00:00
|
|
|
virDomainDefFree(def);
|
|
|
|
return NULL;
|
2014-08-11 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
2015-03-20 00:28:49 +00:00
|
|
|
static int
|
|
|
|
xenFormatXMOS(virConfPtr conf, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2015-03-20 00:28:49 +00:00
|
|
|
char boot[VIR_DOMAIN_BOOT_LAST+1];
|
|
|
|
if (xenConfigSetString(conf, "builder", "hvm") < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->os.loader && def->os.loader->path &&
|
|
|
|
xenConfigSetString(conf, "kernel", def->os.loader->path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < def->os.nBootDevs; i++) {
|
|
|
|
switch (def->os.bootDevs[i]) {
|
|
|
|
case VIR_DOMAIN_BOOT_FLOPPY:
|
|
|
|
boot[i] = 'a';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_CDROM:
|
|
|
|
boot[i] = 'd';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_NET:
|
|
|
|
boot[i] = 'n';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_DISK:
|
|
|
|
default:
|
|
|
|
boot[i] = 'c';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!def->os.nBootDevs) {
|
|
|
|
boot[0] = 'c';
|
|
|
|
boot[1] = '\0';
|
|
|
|
} else {
|
|
|
|
boot[def->os.nBootDevs] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xenConfigSetString(conf, "boot", boot) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* XXX floppy disks */
|
|
|
|
} else {
|
|
|
|
if (def->os.bootloader &&
|
|
|
|
xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->os.bootloaderArgs &&
|
|
|
|
xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->os.kernel &&
|
|
|
|
xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->os.initrd &&
|
|
|
|
xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->os.cmdline &&
|
|
|
|
xenConfigSetString(conf, "extra", def->os.cmdline) < 0)
|
|
|
|
return -1;
|
|
|
|
} /* !hvm */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-06 14:36:13 +00:00
|
|
|
static int
|
|
|
|
xenFormatXMInputDevs(virConfPtr conf, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
const char *devtype;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2015-03-06 14:36:13 +00:00
|
|
|
for (i = 0; i < def->ninputs; i++) {
|
|
|
|
if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
|
|
|
|
if (xenConfigSetInt(conf, "usb", 1) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (def->inputs[i]->type) {
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_MOUSE:
|
|
|
|
devtype = "mouse";
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_TABLET:
|
|
|
|
devtype = "tablet";
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_KBD:
|
|
|
|
devtype = "keyboard";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (xenConfigSetString(conf, "usbdevice", devtype) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-11 21:21:35 +00:00
|
|
|
|
|
|
|
/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
|
|
|
|
either 32, or 64 on a platform where long is big enough. */
|
|
|
|
verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
|
|
|
|
|
2014-08-16 02:52:15 +00:00
|
|
|
/*
|
2015-03-19 15:53:00 +00:00
|
|
|
* Convert a virDomainDef object into an XM config record.
|
2014-08-16 02:52:15 +00:00
|
|
|
*/
|
2014-08-11 21:21:35 +00:00
|
|
|
virConfPtr
|
|
|
|
xenFormatXM(virConnectPtr conn,
|
2015-12-05 02:11:39 +00:00
|
|
|
virDomainDefPtr def)
|
2014-08-11 21:21:35 +00:00
|
|
|
{
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
|
|
|
|
if (!(conf = virConfNew()))
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-12-05 02:11:39 +00:00
|
|
|
if (xenFormatConfigCommon(conf, def, conn) < 0)
|
2014-08-11 21:21:35 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-20 00:28:49 +00:00
|
|
|
if (xenFormatXMOS(conf, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-12-05 02:11:39 +00:00
|
|
|
if (xenFormatXMDisks(conf, def) < 0)
|
2014-08-11 21:21:34 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:11 +00:00
|
|
|
|
2015-03-06 14:36:13 +00:00
|
|
|
if (xenFormatXMInputDevs(conf, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-21 13:40:11 +00:00
|
|
|
return conf;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-02-21 13:40:11 +00:00
|
|
|
if (conf)
|
|
|
|
virConfFree(conf);
|
2012-03-22 11:33:35 +00:00
|
|
|
return NULL;
|
2011-02-25 14:41:12 +00:00
|
|
|
}
|