2012-07-31 18:56:05 +00:00
|
|
|
/*
|
|
|
|
* parallels_driver.c: core driver functions for managing
|
|
|
|
* Parallels Cloud Server hosts
|
|
|
|
*
|
2014-03-17 21:11:07 +00:00
|
|
|
* Copyright (C) 2014 Red Hat, Inc.
|
2012-07-31 18:56:05 +00:00
|
|
|
* Copyright (C) 2012 Parallels, Inc.
|
|
|
|
*
|
|
|
|
* 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-31 18:56:05 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
|
|
|
|
#include "datatypes.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-07-31 18:56:05 +00:00
|
|
|
#include "configmake.h"
|
2013-05-09 18:59:04 +00:00
|
|
|
#include "virfile.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2012-07-31 18:56:05 +00:00
|
|
|
#include "nodeinfo.h"
|
2012-12-11 10:59:42 +00:00
|
|
|
#include "c-ctype.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2014-06-05 05:50:05 +00:00
|
|
|
#include "cpu/cpu.h"
|
2012-07-31 18:56:05 +00:00
|
|
|
|
|
|
|
#include "parallels_driver.h"
|
2012-07-31 18:56:07 +00:00
|
|
|
#include "parallels_utils.h"
|
2012-07-31 18:56:05 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_PARALLELS
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("parallels.parallels_driver");
|
|
|
|
|
2012-07-31 18:56:05 +00:00
|
|
|
#define PRLCTL "prlctl"
|
2012-07-31 18:56:07 +00:00
|
|
|
#define PRLSRVCTL "prlsrvctl"
|
2012-07-31 18:56:05 +00:00
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
#define parallelsDomNotFoundError(domain) \
|
|
|
|
do { \
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN]; \
|
|
|
|
virUUIDFormat(domain->uuid, uuidstr); \
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, \
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr); \
|
|
|
|
} while (0)
|
|
|
|
|
2012-12-04 13:43:01 +00:00
|
|
|
#define IS_CT(def) (STREQ_NULLABLE(def->os.type, "exe"))
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int parallelsConnectClose(virConnectPtr conn);
|
2012-07-31 18:56:05 +00:00
|
|
|
|
2012-12-04 13:43:10 +00:00
|
|
|
static const char * parallelsGetDiskBusName(int bus) {
|
|
|
|
switch (bus) {
|
|
|
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
|
|
|
return "ide";
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
|
|
return "sata";
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
|
|
|
return "scsi";
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-01 03:46:22 +00:00
|
|
|
void
|
2012-07-31 18:56:05 +00:00
|
|
|
parallelsDriverLock(parallelsConnPtr driver)
|
|
|
|
{
|
|
|
|
virMutexLock(&driver->lock);
|
|
|
|
}
|
|
|
|
|
2012-08-01 03:46:22 +00:00
|
|
|
void
|
2012-07-31 18:56:05 +00:00
|
|
|
parallelsDriverUnlock(parallelsConnPtr driver)
|
|
|
|
{
|
|
|
|
virMutexUnlock(&driver->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
static void
|
|
|
|
parallelsDomObjFreePrivate(void *p)
|
|
|
|
{
|
|
|
|
parallelsDomObjPtr pdom = p;
|
|
|
|
|
|
|
|
if (!pdom)
|
|
|
|
return;
|
|
|
|
|
2014-06-05 05:50:04 +00:00
|
|
|
virBitmapFree(pdom->cpumask);
|
2012-07-31 18:56:07 +00:00
|
|
|
VIR_FREE(pdom->uuid);
|
2012-12-04 13:43:05 +00:00
|
|
|
VIR_FREE(pdom->home);
|
2012-07-31 18:56:07 +00:00
|
|
|
VIR_FREE(p);
|
|
|
|
};
|
|
|
|
|
2012-07-31 18:56:05 +00:00
|
|
|
static virCapsPtr
|
|
|
|
parallelsBuildCapabilities(void)
|
|
|
|
{
|
2014-06-05 05:50:06 +00:00
|
|
|
virCapsPtr caps = NULL;
|
|
|
|
virCPUDefPtr cpu = NULL;
|
|
|
|
virCPUDataPtr data = NULL;
|
2012-07-31 18:56:05 +00:00
|
|
|
virCapsGuestPtr guest;
|
2014-06-05 05:50:06 +00:00
|
|
|
virNodeInfo nodeinfo;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
2012-12-10 22:28:09 +00:00
|
|
|
if ((caps = virCapabilitiesNew(virArchFromHost(),
|
|
|
|
0, 0)) == NULL)
|
2013-07-04 10:13:24 +00:00
|
|
|
return NULL;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
|
|
|
if (nodeCapsInitNUMA(caps) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
2012-12-10 22:28:09 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, "hvm",
|
|
|
|
VIR_ARCH_X86_64,
|
|
|
|
"parallels",
|
2012-07-31 18:56:05 +00:00
|
|
|
NULL, 0, NULL)) == NULL)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"parallels", NULL, NULL, 0, NULL) == NULL)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
2012-12-10 22:28:09 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, "exe",
|
|
|
|
VIR_ARCH_X86_64,
|
|
|
|
"parallels",
|
2012-09-10 15:22:42 +00:00
|
|
|
NULL, 0, NULL)) == NULL)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-09-10 15:22:42 +00:00
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"parallels", NULL, NULL, 0, NULL) == NULL)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-09-10 15:22:42 +00:00
|
|
|
|
2014-06-09 07:36:30 +00:00
|
|
|
if (nodeGetInfo(&nodeinfo))
|
2014-06-05 05:50:06 +00:00
|
|
|
goto error;
|
|
|
|
|
2014-06-09 07:36:30 +00:00
|
|
|
if (VIR_ALLOC(cpu) < 0)
|
2014-06-05 05:50:06 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
cpu->arch = caps->host.arch;
|
|
|
|
cpu->type = VIR_CPU_TYPE_HOST;
|
|
|
|
cpu->sockets = nodeinfo.sockets;
|
|
|
|
cpu->cores = nodeinfo.cores;
|
|
|
|
cpu->threads = nodeinfo.threads;
|
|
|
|
|
|
|
|
caps->host.cpu = cpu;
|
|
|
|
|
|
|
|
if (!(data = cpuNodeData(cpu->arch))
|
|
|
|
|| cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
cpuDataFree(data);
|
2012-07-31 18:56:05 +00:00
|
|
|
return caps;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2013-02-01 12:26:18 +00:00
|
|
|
virObjectUnref(caps);
|
2014-06-05 05:50:06 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectGetCapabilities(virConnectPtr conn)
|
2012-07-31 18:56:05 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
|
|
|
if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
|
|
|
|
virReportOOMError();
|
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:09 +00:00
|
|
|
static int
|
|
|
|
parallelsGetSerialInfo(virDomainChrDefPtr chr,
|
|
|
|
const char *name, virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
|
|
|
chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
|
|
|
|
if (virStrToLong_i(name + strlen("serial"),
|
|
|
|
NULL, 10, &chr->target.port) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virJSONValueObjectHasKey(value, "output")) {
|
|
|
|
chr->source.type = VIR_DOMAIN_CHR_TYPE_FILE;
|
|
|
|
|
|
|
|
tmp = virJSONValueObjectGetString(value, "output");
|
|
|
|
if (!tmp) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
|
|
|
|
return -1;
|
2012-07-31 18:56:09 +00:00
|
|
|
} else if (virJSONValueObjectHasKey(value, "socket")) {
|
|
|
|
chr->source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
|
|
|
|
|
|
|
|
tmp = virJSONValueObjectGetString(value, "socket");
|
|
|
|
if (!tmp) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(chr->source.data.nix.path, tmp) < 0)
|
|
|
|
return -1;
|
2012-07-31 18:56:09 +00:00
|
|
|
chr->source.data.nix.listen = false;
|
|
|
|
} else if (virJSONValueObjectHasKey(value, "real")) {
|
|
|
|
chr->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
|
|
|
|
|
|
|
|
tmp = virJSONValueObjectGetString(value, "real");
|
|
|
|
if (!tmp) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
|
|
|
|
return -1;
|
2012-07-31 18:56:09 +00:00
|
|
|
} else {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-09-26 15:12:28 +00:00
|
|
|
parallelsAddSerialInfo(virDomainChrDefPtr **serials, size_t *nserials,
|
2012-07-31 18:56:09 +00:00
|
|
|
const char *key, virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
virDomainChrDefPtr chr = NULL;
|
|
|
|
|
|
|
|
if (!(chr = virDomainChrDefNew()))
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:09 +00:00
|
|
|
|
|
|
|
if (parallelsGetSerialInfo(chr, key, value))
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-03-07 08:33:31 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(*serials, *nserials, chr) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:09 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:09 +00:00
|
|
|
virDomainChrDefFree(chr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
static int
|
|
|
|
parallelsAddVideoInfo(virDomainDefPtr def, virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
virDomainVideoDefPtr video = NULL;
|
|
|
|
virDomainVideoAccelDefPtr accel = NULL;
|
|
|
|
const char *tmp;
|
|
|
|
char *endptr;
|
|
|
|
unsigned long mem;
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "size"))) {
|
|
|
|
parallelsParseError();
|
2013-01-23 22:04:44 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ul(tmp, &endptr, 10, &mem) < 0) {
|
|
|
|
parallelsParseError();
|
2013-01-23 22:04:44 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ(endptr, "Mb")) {
|
|
|
|
parallelsParseError();
|
2013-01-23 22:04:44 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(video) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(accel) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
2014-03-07 08:33:31 +00:00
|
|
|
if (VIR_APPEND_ELEMENT_COPY(def->videos, def->nvideos, video) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
|
|
|
|
video->vram = mem << 20;
|
|
|
|
video->heads = 1;
|
|
|
|
video->accel = accel;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2013-01-23 22:04:44 +00:00
|
|
|
VIR_FREE(accel);
|
2012-07-31 18:56:11 +00:00
|
|
|
virDomainVideoDefFree(video);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:43:01 +00:00
|
|
|
static int
|
|
|
|
parallelsGetHddInfo(virDomainDefPtr def,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
const char *key,
|
|
|
|
virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
unsigned int idx;
|
|
|
|
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
|
|
|
|
|
|
|
if (virJSONValueObjectHasKey(value, "real") == 1) {
|
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
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
2012-12-04 13:43:01 +00:00
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "real"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-03-17 21:11:07 +00:00
|
|
|
if (virDomainDiskSetSource(disk, tmp) < 0)
|
2012-12-04 13:43:01 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
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
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
|
2012-12-04 13:43:01 +00:00
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "image"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-03-17 21:11:07 +00:00
|
|
|
if (virDomainDiskSetSource(disk, tmp) < 0)
|
2012-12-04 13:43:01 +00:00
|
|
|
return -1;
|
2014-05-07 18:04:07 +00:00
|
|
|
|
|
|
|
virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP);
|
2012-12-04 13:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = virJSONValueObjectGetString(value, "port");
|
|
|
|
if (!tmp && !IS_CT(def)) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tmp) {
|
|
|
|
if (STRPREFIX(tmp, "ide")) {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
} else if (STRPREFIX(tmp, "sata")) {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_SATA;
|
|
|
|
} else if (STRPREFIX(tmp, "scsi")) {
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
|
|
|
|
} else {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *colonp;
|
|
|
|
unsigned int pos;
|
|
|
|
|
|
|
|
if (!(colonp = strchr(tmp, ':'))) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ui(colonp + 1, NULL, 10, &pos) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
|
|
|
|
disk->info.addr.drive.target = pos;
|
|
|
|
} else {
|
|
|
|
/* Actually there are no disk devices in containers, but in
|
|
|
|
* in Parallels Cloud Server we mount disk images as container's
|
|
|
|
* root fs during start, so it looks like a disk device. */
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ui(key + strlen("hdd"), NULL, 10, &idx) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(disk->dst = virIndexToDiskName(idx, "sd")))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsAddHddInfo(virDomainDefPtr def, const char *key, virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr disk = NULL;
|
|
|
|
|
2014-05-21 22:50:41 +00:00
|
|
|
if (!(disk = virDomainDiskDefNew()))
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-12-04 13:43:01 +00:00
|
|
|
|
|
|
|
if (parallelsGetHddInfo(def, disk, key, value))
|
|
|
|
goto error;
|
|
|
|
|
2014-03-07 08:33:31 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-12-04 13:43:01 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-12-04 13:43:01 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-12-11 10:59:42 +00:00
|
|
|
static inline unsigned char hex2int(char c)
|
|
|
|
{
|
|
|
|
if (c <= '9')
|
|
|
|
return c - '0';
|
|
|
|
else
|
|
|
|
return 10 + c - 'A';
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse MAC address in format XXXXXXXXXXXX.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
parallelsMacAddrParse(const char *str, virMacAddrPtr addr)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-12-11 10:59:42 +00:00
|
|
|
|
|
|
|
if (strlen(str) != 12)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
if (!c_isxdigit(str[2 * i]) || !c_isxdigit(str[2 * i + 1]))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
addr->addr[i] = (hex2int(str[2 * i]) << 4) + hex2int(str[2 * i + 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-12-11 10:59:42 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Invalid MAC address format '%s'"), str);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsGetNetInfo(virDomainNetDefPtr net,
|
|
|
|
const char *key,
|
|
|
|
virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
/* use device name, shown by prlctl as target device
|
|
|
|
* for identifying network adapter in virDomainDefineXML */
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(net->ifname, key) < 0)
|
2012-12-11 10:59:42 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "mac"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parallelsMacAddrParse(tmp, &net->mac) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-11 10:59:49 +00:00
|
|
|
if (virJSONValueObjectHasKey(value, "network")) {
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "network"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(net->data.network.name, tmp) < 0)
|
2012-12-11 10:59:49 +00:00
|
|
|
goto error;
|
|
|
|
} else if (virJSONValueObjectHasKey(value, "type")) {
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(value, "type"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ(tmp, "routed")) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(net->data.network.name,
|
|
|
|
PARALLELS_ROUTED_NETWORK_NAME) < 0)
|
2012-12-11 10:59:49 +00:00
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
parallelsParseError();
|
2012-12-11 10:59:42 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
|
2013-01-18 14:30:40 +00:00
|
|
|
if ((tmp = virJSONValueObjectGetString(value, "state")) &&
|
|
|
|
STREQ(tmp, "disconnected")) {
|
|
|
|
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
|
2012-12-11 10:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-12-11 10:59:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsAddNetInfo(virDomainDefPtr def, const char *key, virJSONValuePtr value)
|
|
|
|
{
|
|
|
|
virDomainNetDefPtr net = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(net) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-12-11 10:59:42 +00:00
|
|
|
|
|
|
|
if (parallelsGetNetInfo(net, key, value))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto error;
|
2012-12-11 10:59:42 +00:00
|
|
|
|
|
|
|
def->nets[def->nnets - 1] = net;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-12-11 10:59:42 +00:00
|
|
|
virDomainNetDefFree(net);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:09 +00:00
|
|
|
static int
|
|
|
|
parallelsAddDomainHardware(virDomainDefPtr def, virJSONValuePtr jobj)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
size_t i;
|
|
|
|
virJSONValuePtr value;
|
|
|
|
const char *key;
|
|
|
|
|
|
|
|
n = virJSONValueObjectKeysNumber(jobj);
|
|
|
|
if (n < 1)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
key = virJSONValueObjectGetKey(jobj, i);
|
|
|
|
value = virJSONValueObjectGetValue(jobj, i);
|
|
|
|
|
|
|
|
if (STRPREFIX(key, "serial")) {
|
2012-07-31 18:56:11 +00:00
|
|
|
if (parallelsAddSerialInfo(&def->serials,
|
|
|
|
&def->nserials, key, value))
|
|
|
|
goto cleanup;
|
|
|
|
if (def->nconsoles == 0) {
|
|
|
|
if (parallelsAddSerialInfo(&def->consoles,
|
|
|
|
&def->nconsoles, key, value))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else if (STREQ(key, "video")) {
|
|
|
|
if (parallelsAddVideoInfo(def, value))
|
2012-07-31 18:56:09 +00:00
|
|
|
goto cleanup;
|
2012-12-04 13:43:01 +00:00
|
|
|
} else if (STRPREFIX(key, "hdd")) {
|
|
|
|
if (parallelsAddHddInfo(def, key, value))
|
|
|
|
goto cleanup;
|
2012-12-11 10:59:42 +00:00
|
|
|
} else if (STRPREFIX(key, "net")) {
|
|
|
|
if (parallelsAddNetInfo(def, key, value))
|
|
|
|
goto cleanup;
|
2012-07-31 18:56:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:10 +00:00
|
|
|
static int
|
|
|
|
parallelsAddVNCInfo(virDomainDefPtr def, virJSONValuePtr jobj_root)
|
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
unsigned int port;
|
|
|
|
virJSONValuePtr jobj;
|
|
|
|
int ret = -1;
|
|
|
|
virDomainGraphicsDefPtr gr = NULL;
|
|
|
|
|
|
|
|
jobj = virJSONValueObjectGet(jobj_root, "Remote display");
|
|
|
|
if (!jobj) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = virJSONValueObjectGetString(jobj, "mode");
|
|
|
|
if (!tmp) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ(tmp, "off")) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(gr) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:10 +00:00
|
|
|
|
|
|
|
if (STREQ(tmp, "auto")) {
|
|
|
|
if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0)
|
|
|
|
port = 0;
|
2013-04-12 08:49:38 +00:00
|
|
|
gr->data.vnc.autoport = true;
|
2012-07-31 18:56:10 +00:00
|
|
|
} else {
|
|
|
|
if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-04-12 08:49:38 +00:00
|
|
|
gr->data.vnc.autoport = false;
|
2012-07-31 18:56:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gr->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
|
|
|
|
gr->data.vnc.port = port;
|
|
|
|
gr->data.vnc.keymap = NULL;
|
|
|
|
gr->data.vnc.socket = NULL;
|
|
|
|
gr->data.vnc.auth.passwd = NULL;
|
2013-04-10 10:54:17 +00:00
|
|
|
gr->data.vnc.auth.expires = false;
|
2012-07-31 18:56:10 +00:00
|
|
|
gr->data.vnc.auth.connected = 0;
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "address"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(gr->listens) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:10 +00:00
|
|
|
|
|
|
|
gr->nListens = 1;
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(gr->listens[0].address, tmp) < 0)
|
|
|
|
goto cleanup;
|
2012-07-31 18:56:10 +00:00
|
|
|
|
|
|
|
gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
|
|
|
|
|
2014-03-07 08:33:31 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:10 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:10 +00:00
|
|
|
virDomainGraphicsDefFree(gr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
/*
|
|
|
|
* Must be called with privconn->lock held
|
|
|
|
*/
|
|
|
|
static virDomainObjPtr
|
|
|
|
parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj)
|
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
parallelsDomObjPtr pdom = NULL;
|
|
|
|
virJSONValuePtr jobj2, jobj3;
|
|
|
|
const char *tmp;
|
|
|
|
char *endptr;
|
|
|
|
unsigned long mem;
|
|
|
|
unsigned int x;
|
|
|
|
const char *autostart;
|
|
|
|
const char *state;
|
2014-06-05 05:50:04 +00:00
|
|
|
int hostcpus;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0)
|
2013-07-04 10:13:24 +00:00
|
|
|
goto cleanup;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
2014-06-05 05:50:04 +00:00
|
|
|
if (VIR_ALLOC(pdom) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
def->virtType = VIR_DOMAIN_VIRT_PARALLELS;
|
|
|
|
def->id = -1;
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "Name"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(def->name, tmp) < 0)
|
|
|
|
goto cleanup;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "ID"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virUUIDParse(tmp, def->uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("UUID in config file malformed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "Description"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(def->description, tmp) < 0)
|
|
|
|
goto cleanup;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
|
|
|
if (!(jobj2 = virJSONValueObjectGet(jobj, "Hardware"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(jobj3 = virJSONValueObjectGet(jobj2, "cpu"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-09-10 15:22:43 +00:00
|
|
|
if (virJSONValueObjectGetNumberUint(jobj3, "cpus", &x) == 0) {
|
|
|
|
def->vcpus = x;
|
|
|
|
def->maxvcpus = x;
|
|
|
|
} else if ((tmp = virJSONValueObjectGetString(jobj3, "cpus"))) {
|
|
|
|
if (STREQ(tmp, "unlimited")) {
|
|
|
|
virNodeInfo nodeinfo;
|
|
|
|
|
2013-04-26 17:21:58 +00:00
|
|
|
if (nodeGetInfo(&nodeinfo) < 0) {
|
2012-09-10 15:22:43 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Can't get node info"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->vcpus = nodeinfo.cpus;
|
|
|
|
def->maxvcpus = def->vcpus;
|
|
|
|
} else {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-06-05 05:50:04 +00:00
|
|
|
if ((hostcpus = nodeGetCPUCount()) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj3, "mask"))) {
|
|
|
|
/* Absence of this field means that all domains cpus are available */
|
|
|
|
if (!(pdom->cpumask = virBitmapNew(hostcpus)))
|
|
|
|
goto cleanup;
|
|
|
|
virBitmapSetAll(pdom->cpumask);
|
|
|
|
} else {
|
|
|
|
if (virBitmapParse(tmp, 0, &pdom->cpumask, hostcpus) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
if (!(jobj3 = virJSONValueObjectGet(jobj2, "memory"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj3, "size"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ul(tmp, &endptr, 10, &mem) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ(endptr, "Mb")) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->mem.max_balloon = mem;
|
|
|
|
def->mem.max_balloon <<= 10;
|
|
|
|
def->mem.cur_balloon = def->mem.max_balloon;
|
|
|
|
|
2012-09-10 15:22:42 +00:00
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ(tmp, "CT")) {
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(def->os.type, "exe") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
|
|
|
|
goto cleanup;
|
2012-09-10 15:22:42 +00:00
|
|
|
} else if (STREQ(tmp, "VM")) {
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(def->os.type, "hvm") < 0)
|
|
|
|
goto cleanup;
|
2012-09-10 15:22:42 +00:00
|
|
|
}
|
2012-07-31 18:56:07 +00:00
|
|
|
|
2012-12-10 22:28:09 +00:00
|
|
|
def->os.arch = VIR_ARCH_X86_64;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
|
|
|
if (virJSONValueObjectGetNumberUint(jobj, "EnvID", &x) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
pdom->id = x;
|
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "ID"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(pdom->uuid, tmp) < 0)
|
|
|
|
goto cleanup;
|
2012-07-31 18:56:07 +00:00
|
|
|
|
2012-12-04 13:43:05 +00:00
|
|
|
if (!(tmp = virJSONValueObjectGetString(jobj, "Home"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
if (VIR_STRDUP(pdom->home, tmp) < 0)
|
|
|
|
goto cleanup;
|
2012-12-04 13:43:05 +00:00
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
if (!(state = virJSONValueObjectGetString(jobj, "State"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(autostart = virJSONValueObjectGetString(jobj, "Autostart"))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:09 +00:00
|
|
|
if (parallelsAddDomainHardware(def, jobj2) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-31 18:56:10 +00:00
|
|
|
if (parallelsAddVNCInfo(def, jobj) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-28 13:55:55 +00:00
|
|
|
if (!(dom = virDomainObjListAdd(privconn->domains, def,
|
2013-03-31 18:03:42 +00:00
|
|
|
privconn->xmlopt,
|
2013-03-28 13:55:55 +00:00
|
|
|
0, NULL)))
|
2012-07-31 18:56:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
/* dom is locked here */
|
|
|
|
|
|
|
|
dom->privateDataFreeFunc = parallelsDomObjFreePrivate;
|
|
|
|
dom->privateData = pdom;
|
|
|
|
dom->persistent = 1;
|
|
|
|
|
|
|
|
/* TODO: handle all possible states */
|
|
|
|
if (STREQ(state, "running")) {
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_BOOTED);
|
|
|
|
def->id = pdom->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ(autostart, "on"))
|
|
|
|
dom->autostart = 1;
|
|
|
|
else
|
|
|
|
dom->autostart = 0;
|
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2012-07-31 18:56:07 +00:00
|
|
|
|
|
|
|
return dom;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
virDomainDefFree(def);
|
|
|
|
parallelsDomObjFreePrivate(pdom);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must be called with privconn->lock held
|
|
|
|
*
|
|
|
|
* if domain_name is NULL - load information about all
|
|
|
|
* registered domains.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
parallelsLoadDomains(parallelsConnPtr privconn, const char *domain_name)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
int count;
|
|
|
|
size_t i;
|
2012-07-31 18:56:07 +00:00
|
|
|
virJSONValuePtr jobj;
|
|
|
|
virJSONValuePtr jobj2;
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
jobj = parallelsParseOutput(PRLCTL, "list", "-j", "-a", "-i", "-H",
|
2012-09-10 15:22:42 +00:00
|
|
|
"--vmtype", "all", domain_name, NULL);
|
2012-07-31 18:56:07 +00:00
|
|
|
if (!jobj) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = virJSONValueArraySize(jobj);
|
|
|
|
if (count < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
jobj2 = virJSONValueArrayGet(jobj, i);
|
|
|
|
if (!jobj2) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = parallelsLoadDomain(privconn, jobj2);
|
|
|
|
if (!dom)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
virJSONValueFree(jobj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-03-15 14:44:12 +00:00
|
|
|
|
|
|
|
virDomainDefParserConfig parallelsDomainDefParserConfig = {
|
|
|
|
.macPrefix = {0x42, 0x1C, 0x00},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-07-31 18:56:05 +00:00
|
|
|
static int
|
|
|
|
parallelsOpenDefault(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn;
|
|
|
|
|
2013-07-04 10:13:24 +00:00
|
|
|
if (VIR_ALLOC(privconn) < 0)
|
2012-07-31 18:56:05 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
if (virMutexInit(&privconn->lock) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot initialize mutex"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(privconn->caps = parallelsBuildCapabilities()))
|
|
|
|
goto error;
|
|
|
|
|
2013-03-15 14:44:12 +00:00
|
|
|
if (!(privconn->xmlopt = virDomainXMLOptionNew(¶llelsDomainDefParserConfig,
|
|
|
|
NULL, NULL)))
|
2013-03-05 15:17:24 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
if (!(privconn->domains = virDomainObjListNew()))
|
2012-07-31 18:56:05 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
conn->privateData = privconn;
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
if (parallelsLoadDomains(privconn, NULL))
|
|
|
|
goto error;
|
|
|
|
|
2012-07-31 18:56:05 +00:00
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2013-01-11 13:54:15 +00:00
|
|
|
virObjectUnref(privconn->domains);
|
2013-02-01 12:26:18 +00:00
|
|
|
virObjectUnref(privconn->caps);
|
2012-07-31 18:56:05 +00:00
|
|
|
virStoragePoolObjListFree(&privconn->pools);
|
|
|
|
VIR_FREE(privconn);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDrvOpenStatus
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags)
|
2012-07-31 18:56:05 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
|
|
|
if (!conn->uri)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "parallels"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* Remote driver should handle these. */
|
|
|
|
if (conn->uri->server)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* From this point on, the connection is for us. */
|
2012-08-13 15:50:13 +00:00
|
|
|
if (!STREQ_NULLABLE(conn->uri->path, "/system")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unexpected Parallels URI path '%s', try parallels:///system"),
|
|
|
|
conn->uri->path);
|
2012-07-31 18:56:05 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
2012-08-13 15:50:13 +00:00
|
|
|
if ((ret = parallelsOpenDefault(conn)) != VIR_DRV_OPEN_SUCCESS)
|
2012-07-31 18:56:05 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectClose(virConnectPtr conn)
|
2012-07-31 18:56:05 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-02-01 12:26:18 +00:00
|
|
|
virObjectUnref(privconn->caps);
|
2013-03-31 18:03:42 +00:00
|
|
|
virObjectUnref(privconn->xmlopt);
|
2013-01-11 13:54:15 +00:00
|
|
|
virObjectUnref(privconn->domains);
|
2012-07-31 18:56:05 +00:00
|
|
|
conn->privateData = NULL;
|
|
|
|
|
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
virMutexDestroy(&privconn->lock);
|
|
|
|
|
|
|
|
VIR_FREE(privconn);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
|
2012-07-31 18:56:05 +00:00
|
|
|
{
|
2012-07-31 18:56:07 +00:00
|
|
|
char *output, *sVer, *tmp;
|
|
|
|
const char *searchStr = "prlsrvctl version ";
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
output = parallelsGetOutput(PRLSRVCTL, "--help", NULL);
|
|
|
|
|
|
|
|
if (!output) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(sVer = strstr(output, searchStr))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
sVer = sVer + strlen(searchStr);
|
|
|
|
|
|
|
|
/* parallels server has versions number like 6.0.17977.782218,
|
|
|
|
* so libvirt can handle only first two numbers. */
|
|
|
|
if (!(tmp = strchr(sVer, '.'))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp = strchr(tmp + 1, '.'))) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp[0] = '\0';
|
|
|
|
if (virParseVersionString(sVer, hvVer, true) < 0) {
|
|
|
|
parallelsParseError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
VIR_FREE(output);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:39:11 +00:00
|
|
|
|
|
|
|
static char *parallelsConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return virGetHostname();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-31 18:56:07 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectListDomains(virConnectPtr conn, int *ids, int maxids)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-06-24 16:49:47 +00:00
|
|
|
n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
|
|
|
|
NULL, NULL);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectNumOfDomains(virConnectPtr conn)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-06-24 16:49:47 +00:00
|
|
|
count = virDomainObjListNumOfDomains(privconn->domains, true,
|
|
|
|
NULL, NULL);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
|
|
|
memset(names, 0, sizeof(*names) * maxnames);
|
2013-01-11 16:04:47 +00:00
|
|
|
n = virDomainObjListGetInactiveNames(privconn->domains, names,
|
2013-06-24 16:49:47 +00:00
|
|
|
maxnames, NULL, NULL);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectNumOfDefinedDomains(virConnectPtr conn)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-06-24 16:49:47 +00:00
|
|
|
count = virDomainObjListNumOfDomains(privconn->domains, false,
|
|
|
|
NULL, NULL);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsConnectListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-08-03 15:48:05 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverLock(privconn);
|
2013-06-24 16:49:47 +00:00
|
|
|
ret = virDomainObjListExport(privconn->domains, conn, domains,
|
|
|
|
NULL, flags);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainLookupByID(virConnectPtr conn, int id)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
virDomainPtr ret = NULL;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
dom = virDomainObjListFindByID(privconn->domains, id);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (dom == NULL) {
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (ret)
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (dom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
virDomainPtr ret = NULL;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
dom = virDomainObjListFindByUUID(privconn->domains, uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (dom == NULL) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (ret)
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (dom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainLookupByName(virConnectPtr conn, const char *name)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
virDomainPtr ret = NULL;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
dom = virDomainObjListFindByName(privconn->domains, name);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (dom == NULL) {
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching name '%s'"), name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virGetDomain(conn, dom->def->name, dom->def->uuid);
|
|
|
|
if (ret)
|
|
|
|
ret->id = dom->def->id;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (dom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->state = virDomainObjGetState(privdom, NULL);
|
|
|
|
info->memory = privdom->def->mem.cur_balloon;
|
|
|
|
info->maxMem = privdom->def->mem.max_balloon;
|
|
|
|
info->nrVirtCpu = privdom->def->vcpus;
|
|
|
|
info->cpuTime = 0;
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainGetOSType(virDomainPtr domain)
|
2012-07-31 18:56:07 +00:00
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:46:03 +00:00
|
|
|
ignore_value(VIR_STRDUP(ret, privdom->def->os.type));
|
2012-07-31 18:56:07 +00:00
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsDomainIsPersistent(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsDomainGetState(virDomainPtr domain,
|
|
|
|
int *state, int *reason, unsigned int flags)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
int ret = -1;
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*state = virDomainObjGetState(privdom, reason);
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
parallelsDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
/* Flags checked by virDomainDefFormat */
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
|
|
|
|
privdom->newDef ? privdom->newDef : privdom->def;
|
|
|
|
|
|
|
|
ret = virDomainDefFormat(def, flags);
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsDomainGetAutostart(virDomainPtr domain, int *autostart)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:07 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = privdom->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:07 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:07 +00:00
|
|
|
return ret;
|
2012-07-31 18:56:05 +00:00
|
|
|
}
|
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
typedef int (*parallelsChangeStateFunc)(virDomainObjPtr privdom);
|
2012-07-31 18:56:08 +00:00
|
|
|
#define PARALLELS_UUID(x) (((parallelsDomObjPtr)(x->privateData))->uuid)
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsDomainChangeState(virDomainPtr domain,
|
|
|
|
virDomainState req_state, const char *req_state_name,
|
|
|
|
parallelsChangeStateFunc chstate,
|
|
|
|
virDomainState new_state, int reason)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
virDomainObjPtr privdom;
|
|
|
|
int state;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-01-11 16:04:47 +00:00
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
2012-07-31 18:56:08 +00:00
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = virDomainObjGetState(privdom, NULL);
|
|
|
|
if (state != req_state) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not %s"),
|
|
|
|
privdom->def->name, req_state_name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chstate(privdom))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virDomainObjSetState(privdom, new_state, reason);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:08 +00:00
|
|
|
if (privdom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(privdom);
|
2012-07-31 18:56:08 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsPause(virDomainObjPtr privdom)
|
|
|
|
{
|
|
|
|
return parallelsCmdRun(PRLCTL, "pause", PARALLELS_UUID(privdom), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainSuspend(virDomainPtr domain)
|
2012-07-31 18:56:08 +00:00
|
|
|
{
|
|
|
|
return parallelsDomainChangeState(domain,
|
|
|
|
VIR_DOMAIN_RUNNING, "running",
|
|
|
|
parallelsPause,
|
|
|
|
VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsResume(virDomainObjPtr privdom)
|
|
|
|
{
|
|
|
|
return parallelsCmdRun(PRLCTL, "resume", PARALLELS_UUID(privdom), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainResume(virDomainPtr domain)
|
2012-07-31 18:56:08 +00:00
|
|
|
{
|
|
|
|
return parallelsDomainChangeState(domain,
|
|
|
|
VIR_DOMAIN_PAUSED, "paused",
|
|
|
|
parallelsResume,
|
|
|
|
VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsStart(virDomainObjPtr privdom)
|
|
|
|
{
|
|
|
|
return parallelsCmdRun(PRLCTL, "start", PARALLELS_UUID(privdom), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsDomainCreate(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
return parallelsDomainChangeState(domain,
|
|
|
|
VIR_DOMAIN_SHUTOFF, "stopped",
|
|
|
|
parallelsStart,
|
|
|
|
VIR_DOMAIN_RUNNING, VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsKill(virDomainObjPtr privdom)
|
|
|
|
{
|
|
|
|
return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), "--kill", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainDestroy(virDomainPtr domain)
|
2012-07-31 18:56:08 +00:00
|
|
|
{
|
|
|
|
return parallelsDomainChangeState(domain,
|
|
|
|
VIR_DOMAIN_RUNNING, "running",
|
|
|
|
parallelsKill,
|
|
|
|
VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsStop(virDomainObjPtr privdom)
|
|
|
|
{
|
|
|
|
return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
parallelsDomainShutdown(virDomainPtr domain)
|
2012-07-31 18:56:08 +00:00
|
|
|
{
|
|
|
|
return parallelsDomainChangeState(domain,
|
|
|
|
VIR_DOMAIN_RUNNING, "running",
|
|
|
|
parallelsStop,
|
|
|
|
VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
static int
|
|
|
|
parallelsApplyGraphicsParams(virDomainGraphicsDefPtr *oldgraphics, int nold,
|
|
|
|
virDomainGraphicsDefPtr *newgraphics, int nnew)
|
|
|
|
{
|
|
|
|
virDomainGraphicsDefPtr new, old;
|
|
|
|
|
|
|
|
/* parallels server supports only 1 VNC display per VM */
|
|
|
|
if (nold != nnew || nnew > 1)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (nnew == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (newgraphics[0]->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
old = oldgraphics[0];
|
|
|
|
new = newgraphics[0];
|
|
|
|
|
|
|
|
if (old->data.vnc.port != new->data.vnc.port &&
|
2012-09-10 15:23:44 +00:00
|
|
|
(old->data.vnc.port != 0 && new->data.vnc.port != 0)) {
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
goto error;
|
|
|
|
} else if (old->data.vnc.autoport != new->data.vnc.autoport ||
|
|
|
|
new->data.vnc.keymap != NULL ||
|
|
|
|
new->data.vnc.socket != NULL ||
|
|
|
|
!STREQ_NULLABLE(old->data.vnc.auth.passwd, new->data.vnc.auth.passwd) ||
|
|
|
|
old->data.vnc.auth.expires != new->data.vnc.auth.expires ||
|
|
|
|
old->data.vnc.auth.validTo != new->data.vnc.auth.validTo ||
|
|
|
|
old->data.vnc.auth.connected != new->data.vnc.auth.connected) {
|
|
|
|
|
|
|
|
goto error;
|
|
|
|
} else if (old->nListens != new->nListens ||
|
|
|
|
new->nListens > 1 ||
|
|
|
|
old->listens[0].type != new->listens[0].type ||
|
|
|
|
!STREQ_NULLABLE(old->listens[0].address, new->listens[0].address) ||
|
|
|
|
!STREQ_NULLABLE(old->listens[0].network, new->listens[0].network)) {
|
|
|
|
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-07-31 18:56:11 +00:00
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing display parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsApplySerialParams(virDomainChrDefPtr *oldserials, int nold,
|
|
|
|
virDomainChrDefPtr *newserials, int nnew)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i, j;
|
2012-10-26 17:23:56 +00:00
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
if (nold != nnew)
|
|
|
|
goto error;
|
|
|
|
|
2012-10-26 17:23:56 +00:00
|
|
|
for (i = 0; i < nold; i++) {
|
2012-07-31 18:56:11 +00:00
|
|
|
virDomainChrDefPtr oldserial = oldserials[i];
|
|
|
|
virDomainChrDefPtr newserial = NULL;
|
|
|
|
|
2012-10-26 17:23:56 +00:00
|
|
|
for (j = 0; j < nnew; j++) {
|
2012-07-31 18:56:11 +00:00
|
|
|
if (newserials[j]->target.port == oldserial->target.port) {
|
|
|
|
newserial = newserials[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!newserial)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (oldserial->source.type != newserial->source.type)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if ((newserial->source.type == VIR_DOMAIN_CHR_TYPE_DEV ||
|
|
|
|
newserial->source.type == VIR_DOMAIN_CHR_TYPE_FILE) &&
|
|
|
|
!STREQ_NULLABLE(oldserial->source.data.file.path,
|
|
|
|
newserial->source.data.file.path))
|
|
|
|
goto error;
|
2012-10-17 09:23:12 +00:00
|
|
|
if (newserial->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
|
2012-07-31 18:56:11 +00:00
|
|
|
(!STREQ_NULLABLE(oldserial->source.data.nix.path,
|
|
|
|
newserial->source.data.nix.path) ||
|
|
|
|
oldserial->source.data.nix.listen == newserial->source.data.nix.listen)) {
|
|
|
|
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-07-31 18:56:11 +00:00
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing serial device parameters is "
|
|
|
|
"not supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsApplyVideoParams(parallelsDomObjPtr pdom,
|
|
|
|
virDomainVideoDefPtr *oldvideos, int nold,
|
|
|
|
virDomainVideoDefPtr *newvideos, int nnew)
|
|
|
|
{
|
|
|
|
virDomainVideoDefPtr old, new;
|
|
|
|
char str_vram[32];
|
|
|
|
|
|
|
|
if (nold != 1 || nnew != 1) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Only one video device is "
|
|
|
|
"supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
old = oldvideos[0];
|
|
|
|
new = newvideos[0];
|
|
|
|
if (new->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Only VGA video device is "
|
|
|
|
"supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new->heads != 1) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Only one monitor is supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* old->accel must be always non-NULL */
|
|
|
|
if (new->accel == NULL ||
|
|
|
|
old->accel->support2d != new->accel->support2d ||
|
|
|
|
old->accel->support3d != new->accel->support3d) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing video acceleration parameters is "
|
|
|
|
"not supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->vram != new->vram) {
|
|
|
|
if (new->vram % (1 << 20) != 0) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Video RAM size should be multiple of 1Mb."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(str_vram, 31, "%d", new->vram >> 20);
|
|
|
|
str_vram[31] = '\0';
|
|
|
|
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--videosize", str_vram, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-07 18:04:08 +00:00
|
|
|
static int parallelsAddHdd(parallelsDomObjPtr pdom,
|
|
|
|
virDomainDiskDefPtr disk)
|
2012-12-04 13:43:11 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2014-05-07 18:04:08 +00:00
|
|
|
const char *src = virDomainDiskGetSource(disk);
|
|
|
|
int type = virDomainDiskGetType(disk);
|
2012-12-04 13:43:11 +00:00
|
|
|
const char *strbus;
|
|
|
|
|
|
|
|
virCommandPtr cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-add", "hdd", NULL);
|
2014-05-07 18:04:08 +00:00
|
|
|
|
|
|
|
if (type == VIR_STORAGE_TYPE_FILE) {
|
|
|
|
int format = virDomainDiskGetFormat(disk);
|
|
|
|
|
|
|
|
if (format != VIR_STORAGE_FILE_PLOOP) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("Invalid disk format: %d"), type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virCommandAddArg(cmd, "--image");
|
|
|
|
} else if (VIR_STORAGE_TYPE_BLOCK) {
|
|
|
|
virCommandAddArg(cmd, "--device");
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("Invalid disk type: %d"), type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virCommandAddArg(cmd, src);
|
2012-12-04 13:43:11 +00:00
|
|
|
|
|
|
|
if (!(strbus = parallelsGetDiskBusName(disk->bus))) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("Invalid disk bus: %d"), disk->bus);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virCommandAddArgFormat(cmd, "--iface=%s", strbus);
|
|
|
|
|
|
|
|
if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
|
|
|
|
virCommandAddArgFormat(cmd, "--position=%d",
|
|
|
|
disk->info.addr.drive.target);
|
|
|
|
|
2013-01-23 22:04:44 +00:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
2012-12-04 13:43:11 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2014-05-07 18:04:08 +00:00
|
|
|
virCommandFree(cmd);
|
2012-12-04 13:43:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:43:13 +00:00
|
|
|
static int parallelsRemoveHdd(parallelsDomObjPtr pdom,
|
|
|
|
virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
char prlname[16];
|
|
|
|
|
|
|
|
prlname[15] = '\0';
|
|
|
|
snprintf(prlname, 15, "hdd%d", virDiskNameToIndex(disk->dst));
|
|
|
|
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-del", prlname,
|
|
|
|
"--detach-only", NULL))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:43:02 +00:00
|
|
|
static int
|
2014-05-07 18:04:08 +00:00
|
|
|
parallelsApplyDisksParams(parallelsDomObjPtr pdom,
|
2012-12-04 13:43:02 +00:00
|
|
|
virDomainDiskDefPtr *olddisks, int nold,
|
|
|
|
virDomainDiskDefPtr *newdisks, int nnew)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i, j;
|
2012-12-04 13:43:02 +00:00
|
|
|
|
2012-12-04 13:43:11 +00:00
|
|
|
for (i = 0; i < nold; i++) {
|
2012-12-04 13:43:02 +00:00
|
|
|
virDomainDiskDefPtr newdisk = NULL;
|
|
|
|
virDomainDiskDefPtr olddisk = olddisks[i];
|
2012-12-04 13:43:11 +00:00
|
|
|
for (j = 0; j < nnew; j++) {
|
2012-12-04 13:43:02 +00:00
|
|
|
if (STREQ_NULLABLE(newdisks[j]->dst, olddisk->dst)) {
|
|
|
|
newdisk = newdisks[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!newdisk) {
|
2012-12-04 13:43:13 +00:00
|
|
|
if (parallelsRemoveHdd(pdom, olddisk)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("Can't remove disk '%s' "
|
|
|
|
"in the specified config"), olddisks[i]->serial);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
2012-12-04 13:43:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (olddisk->bus != newdisk->bus ||
|
|
|
|
olddisk->info.addr.drive.target != newdisk->info.addr.drive.target ||
|
2014-03-17 21:11:07 +00:00
|
|
|
!STREQ_NULLABLE(virDomainDiskGetSource(olddisk),
|
|
|
|
virDomainDiskGetSource(newdisk))) {
|
2012-12-04 13:43:02 +00:00
|
|
|
|
|
|
|
char prlname[16];
|
|
|
|
char strpos[16];
|
|
|
|
const char *strbus;
|
|
|
|
|
|
|
|
prlname[15] = '\0';
|
|
|
|
snprintf(prlname, 15, "hdd%d", virDiskNameToIndex(newdisk->dst));
|
|
|
|
|
|
|
|
strpos[15] = '\0';
|
|
|
|
snprintf(strpos, 15, "%d", newdisk->info.addr.drive.target);
|
|
|
|
|
2012-12-04 13:43:10 +00:00
|
|
|
if (!(strbus = parallelsGetDiskBusName(newdisk->bus))) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
2012-12-04 13:43:11 +00:00
|
|
|
_("Unsupported disk bus: %d"), newdisk->bus);
|
2012-12-04 13:43:10 +00:00
|
|
|
return -1;
|
2012-12-04 13:43:02 +00:00
|
|
|
}
|
2012-12-04 13:43:10 +00:00
|
|
|
|
2012-12-04 13:43:02 +00:00
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-set", prlname,
|
|
|
|
"--iface", strbus,
|
|
|
|
"--position", strpos,
|
|
|
|
"--image", newdisk->src, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:43:11 +00:00
|
|
|
for (i = 0; i < nnew; i++) {
|
|
|
|
virDomainDiskDefPtr newdisk = newdisks[i];
|
|
|
|
bool found = false;
|
|
|
|
for (j = 0; j < nold; j++)
|
|
|
|
if (STREQ_NULLABLE(olddisks[j]->dst, newdisk->dst))
|
|
|
|
found = true;
|
|
|
|
if (found)
|
|
|
|
continue;
|
|
|
|
|
2014-05-07 18:04:08 +00:00
|
|
|
if (parallelsAddHdd(pdom, newdisk))
|
2012-12-04 13:43:11 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:43:02 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-11 10:59:43 +00:00
|
|
|
static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom,
|
|
|
|
virDomainNetDefPtr oldnet,
|
|
|
|
virDomainNetDefPtr newnet)
|
|
|
|
{
|
|
|
|
bool create = false;
|
|
|
|
bool is_changed = false;
|
2013-01-23 22:04:44 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
2012-12-11 10:59:43 +00:00
|
|
|
char strmac[VIR_MAC_STRING_BUFLEN];
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-01-23 22:04:44 +00:00
|
|
|
int ret = -1;
|
2012-12-11 10:59:43 +00:00
|
|
|
|
|
|
|
if (!oldnet) {
|
|
|
|
create = true;
|
2013-07-04 10:13:24 +00:00
|
|
|
if (VIR_ALLOC(oldnet) < 0)
|
2012-12-11 10:59:43 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!create && oldnet->type != newnet->type) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing network type is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(oldnet->model, newnet->model)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing network device model is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(oldnet->data.network.portgroup,
|
|
|
|
newnet->data.network.portgroup)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing network portgroup is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!virNetDevVPortProfileEqual(oldnet->virtPortProfile,
|
|
|
|
newnet->virtPortProfile)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing virtual port profile is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newnet->tune.sndbuf_specified) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Setting send buffer size is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(oldnet->script, newnet->script)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Setting startup script is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(oldnet->filter, newnet->filter)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Changing filter params is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newnet->bandwidth != NULL) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Setting bandwidth params is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(newnet->vlan); i++) {
|
|
|
|
if (((char *)&newnet->vlan)[i] != 0) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Setting vlan params is not supported"));
|
2013-01-23 22:04:44 +00:00
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Here we know, that there are no differences, that are forbidden.
|
|
|
|
* Check is something changed, if no - do nothing */
|
|
|
|
|
|
|
|
if (create) {
|
|
|
|
cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-add", "net", NULL);
|
|
|
|
} else {
|
|
|
|
cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-set", newnet->ifname, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virMacAddrCmp(&oldnet->mac, &newnet->mac)) {
|
|
|
|
virMacAddrFormat(&newnet->mac, strmac);
|
|
|
|
virCommandAddArgFormat(cmd, "--mac=%s", strmac);
|
|
|
|
is_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(oldnet->data.network.name, newnet->data.network.name)) {
|
2012-12-11 10:59:49 +00:00
|
|
|
if (STREQ_NULLABLE(newnet->data.network.name,
|
|
|
|
PARALLELS_ROUTED_NETWORK_NAME)) {
|
|
|
|
virCommandAddArgFormat(cmd, "--type=routed");
|
|
|
|
} else {
|
|
|
|
virCommandAddArgFormat(cmd, "--network=%s",
|
|
|
|
newnet->data.network.name);
|
|
|
|
}
|
|
|
|
|
2012-12-11 10:59:43 +00:00
|
|
|
is_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldnet->linkstate != newnet->linkstate) {
|
|
|
|
if (newnet->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP) {
|
|
|
|
virCommandAddArgFormat(cmd, "--connect");
|
|
|
|
} else if (newnet->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
|
|
|
|
virCommandAddArgFormat(cmd, "--disconnect");
|
|
|
|
}
|
|
|
|
is_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!create && !is_changed) {
|
|
|
|
/* nothing changed - no need to run prlctl */
|
2013-01-23 22:04:44 +00:00
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 22:04:44 +00:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
2012-12-11 10:59:43 +00:00
|
|
|
|
2013-01-23 22:04:44 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2013-01-23 22:04:44 +00:00
|
|
|
if (create)
|
|
|
|
VIR_FREE(oldnet);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
2012-12-11 10:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
|
|
|
|
virDomainNetDefPtr *oldnets, int nold,
|
|
|
|
virDomainNetDefPtr *newnets, int nnew)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/parallels/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i, j;
|
2012-12-11 10:59:43 +00:00
|
|
|
virDomainNetDefPtr newnet;
|
|
|
|
virDomainNetDefPtr oldnet;
|
|
|
|
bool found;
|
|
|
|
|
|
|
|
for (i = 0; i < nold; i++) {
|
|
|
|
newnet = NULL;
|
|
|
|
oldnet = oldnets[i];
|
|
|
|
for (j = 0; j < nnew; j++) {
|
|
|
|
if (STREQ_NULLABLE(newnets[j]->ifname, oldnet->ifname)) {
|
|
|
|
newnet = newnets[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!newnet) {
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--device-del", oldnet->ifname, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parallelsApplyIfaceParams(pdom, oldnet, newnet) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nnew; i++) {
|
|
|
|
newnet = newnets[i];
|
|
|
|
found = false;
|
|
|
|
|
|
|
|
for (j = 0; j < nold; j++)
|
|
|
|
if (STREQ_NULLABLE(oldnets[j]->ifname, newnet->ifname))
|
|
|
|
found = true;
|
|
|
|
if (found)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (parallelsApplyIfaceParams(pdom, NULL, newnet))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
static int
|
2014-05-07 18:04:08 +00:00
|
|
|
parallelsApplyChanges(virDomainObjPtr dom, virDomainDefPtr new)
|
2012-07-31 18:56:11 +00:00
|
|
|
{
|
|
|
|
char buf[32];
|
2014-04-23 14:35:00 +00:00
|
|
|
size_t i;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
virDomainDefPtr old = dom->def;
|
|
|
|
parallelsDomObjPtr pdom = dom->privateData;
|
|
|
|
|
|
|
|
if (new->description && !STREQ_NULLABLE(old->description, new->description)) {
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--description", new->description, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new->name && !STREQ_NULLABLE(old->name, new->name)) {
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--name", new->name, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new->title && !STREQ_NULLABLE(old->title, new->title)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("titles are not supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new->blkio.ndevices > 0) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("blkio parameters are not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->mem.max_balloon != new->mem.max_balloon) {
|
|
|
|
if (new->mem.max_balloon != new->mem.cur_balloon) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing balloon parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new->mem.max_balloon % (1 << 10) != 0) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Memory size should be multiple of 1Mb."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, 31, "%llu", new->mem.max_balloon >> 10);
|
|
|
|
buf[31] = '\0';
|
|
|
|
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--memsize", buf, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->mem.hugepage_backed != new->mem.hugepage_backed ||
|
|
|
|
old->mem.hard_limit != new->mem.hard_limit ||
|
|
|
|
old->mem.soft_limit != new->mem.soft_limit ||
|
|
|
|
old->mem.min_guarantee != new->mem.min_guarantee ||
|
|
|
|
old->mem.swap_hard_limit != new->mem.swap_hard_limit) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Memory parameter is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->vcpus != new->vcpus) {
|
|
|
|
if (new->vcpus != new->maxvcpus) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("current vcpus must be equal to maxvcpus"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, 31, "%d", new->vcpus);
|
|
|
|
buf[31] = '\0';
|
|
|
|
|
|
|
|
if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
|
|
|
|
"--cpus", buf, NULL))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->placement_mode != new->placement_mode) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing cpu placement mode is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-09-26 12:30:02 +00:00
|
|
|
if ((old->cpumask != NULL || new->cpumask != NULL) &&
|
|
|
|
(old->cpumask == NULL || new->cpumask == NULL ||
|
|
|
|
!virBitmapEqual(old->cpumask, new->cpumask))) {
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing cpu mask is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->cputune.shares != new->cputune.shares ||
|
2014-03-04 11:39:46 +00:00
|
|
|
old->cputune.sharesSpecified != new->cputune.sharesSpecified ||
|
2012-07-31 18:56:11 +00:00
|
|
|
old->cputune.period != new->cputune.period ||
|
|
|
|
old->cputune.quota != new->cputune.quota ||
|
|
|
|
old->cputune.nvcpupin != new->cputune.nvcpupin) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("cputune is not supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->numatune.memory.mode != new->numatune.memory.mode ||
|
|
|
|
old->numatune.memory.placement_mode != new->numatune.memory.placement_mode ||
|
2012-09-26 12:30:02 +00:00
|
|
|
((old->numatune.memory.nodemask != NULL || new->numatune.memory.nodemask != NULL) &&
|
|
|
|
(old->numatune.memory.nodemask == NULL || new->numatune.memory.nodemask == NULL ||
|
|
|
|
!virBitmapEqual(old->numatune.memory.nodemask, new->numatune.memory.nodemask)))){
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("numa parameters are not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old->onReboot != new->onReboot ||
|
|
|
|
old->onPoweroff != new->onPoweroff ||
|
|
|
|
old->onCrash != new->onCrash) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("on_reboot, on_poweroff and on_crash parameters "
|
|
|
|
"are not supported by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-09-10 15:22:44 +00:00
|
|
|
/* we fill only type and arch fields in parallelsLoadDomain for
|
|
|
|
* hvm type and also init for containers, so we can check that all
|
|
|
|
* other paramenters are null and boot devices config is default */
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
if (!STREQ_NULLABLE(old->os.type, new->os.type) ||
|
2012-12-10 22:28:09 +00:00
|
|
|
old->os.arch != new->os.arch ||
|
2012-09-10 15:22:44 +00:00
|
|
|
new->os.machine != NULL || new->os.bootmenu != 0 ||
|
|
|
|
new->os.kernel != NULL || new->os.initrd != NULL ||
|
|
|
|
new->os.cmdline != NULL || new->os.root != NULL ||
|
|
|
|
new->os.loader != NULL || new->os.bootloader != NULL ||
|
|
|
|
new->os.bootloaderArgs != NULL || new->os.smbios_mode != 0 ||
|
|
|
|
new->os.bios.useserial != 0) {
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing OS parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
2012-09-10 15:22:44 +00:00
|
|
|
if (STREQ(new->os.type, "hvm")) {
|
|
|
|
if (new->os.nBootDevs != 1 ||
|
|
|
|
new->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK ||
|
|
|
|
new->os.init != NULL || new->os.initargv != NULL) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing OS parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (new->os.nBootDevs != 0 ||
|
|
|
|
!STREQ_NULLABLE(old->os.init, new->os.init) ||
|
|
|
|
(new->os.initargv != NULL && new->os.initargv[0] != NULL)) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing OS parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
if (!STREQ_NULLABLE(old->emulator, new->emulator)) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing emulator is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-04-23 14:35:00 +00:00
|
|
|
for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
|
|
|
|
if (old->features[i] != new->features[i]) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing features is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
2012-07-31 18:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (new->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
|
|
|
|
new->clock.ntimers != 0) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing clock parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parallelsApplyGraphicsParams(old->graphics, old->ngraphics,
|
|
|
|
new->graphics, new->ngraphics) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2012-12-11 10:59:43 +00:00
|
|
|
if (new->nfss != 0 ||
|
2012-07-31 18:56:11 +00:00
|
|
|
new->nsounds != 0 || new->nhostdevs != 0 ||
|
|
|
|
new->nredirdevs != 0 || new->nsmartcards != 0 ||
|
|
|
|
new->nparallels || new->nchannels != 0 ||
|
|
|
|
new->nleases != 0 || new->nhubs != 0) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing devices parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* there may be one auto-input */
|
|
|
|
if (new->ninputs > 1 ||
|
|
|
|
(new->ninputs > 1 &&
|
|
|
|
(new->inputs[0]->type != VIR_DOMAIN_INPUT_TYPE_MOUSE ||
|
|
|
|
new->inputs[0]->bus != VIR_DOMAIN_INPUT_BUS_PS2))) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("changing input devices parameters is not supported "
|
|
|
|
"by parallels driver"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (parallelsApplySerialParams(old->serials, old->nserials,
|
|
|
|
new->serials, new->nserials) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (parallelsApplySerialParams(old->consoles, old->nconsoles,
|
|
|
|
new->consoles, new->nconsoles) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (parallelsApplyVideoParams(pdom, old->videos, old->nvideos,
|
|
|
|
new->videos, new->nvideos) < 0)
|
|
|
|
return -1;
|
2014-05-07 18:04:08 +00:00
|
|
|
if (parallelsApplyDisksParams(pdom, old->disks, old->ndisks,
|
2012-12-04 13:43:02 +00:00
|
|
|
new->disks, new->ndisks) < 0)
|
|
|
|
return -1;
|
2012-12-11 10:59:43 +00:00
|
|
|
if (parallelsApplyIfacesParams(pdom, old->nets, old->nnets,
|
|
|
|
new->nets, new->nnets) < 0)
|
|
|
|
return -1;
|
2012-12-04 13:43:02 +00:00
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:13 +00:00
|
|
|
static int
|
2014-05-07 18:04:09 +00:00
|
|
|
parallelsCreateVm(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainDefPtr def)
|
2012-07-31 18:56:13 +00:00
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(def->uuid, uuidstr);
|
|
|
|
|
2014-05-07 18:04:09 +00:00
|
|
|
if (parallelsCmdRun(PRLCTL, "create", def->name, "--no-hdd",
|
2012-07-31 18:56:13 +00:00
|
|
|
"--uuid", uuidstr, NULL) < 0)
|
2014-05-07 18:04:09 +00:00
|
|
|
return -1;
|
2012-07-31 18:56:13 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-12 12:40:54 +00:00
|
|
|
static int
|
|
|
|
parallelsCreateCt(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(def->uuid, uuidstr);
|
|
|
|
|
|
|
|
if (def->nfss != 1 ||
|
|
|
|
def->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("There must be only 1 template FS for "
|
|
|
|
"container creation"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parallelsCmdRun(PRLCTL, "create", def->name, "--vmtype", "ct",
|
|
|
|
"--uuid", uuidstr,
|
|
|
|
"--ostemplate", def->fss[0]->src, NULL) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
error:
|
2012-09-12 12:40:54 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:56:11 +00:00
|
|
|
static virDomainPtr
|
|
|
|
parallelsDomainDefineXML(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = conn->privateData;
|
|
|
|
virDomainPtr ret = NULL;
|
|
|
|
virDomainDefPtr def;
|
2014-04-23 14:35:02 +00:00
|
|
|
virDomainObjPtr olddom = NULL;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
2013-03-28 13:55:55 +00:00
|
|
|
if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_PARALLELS,
|
2012-07-31 18:56:11 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)) == NULL) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Can't parse XML desc"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 14:46:58 +00:00
|
|
|
olddom = virDomainObjListFindByUUID(privconn->domains, def->uuid);
|
|
|
|
if (olddom == NULL) {
|
|
|
|
virResetLastError();
|
2012-09-12 12:40:54 +00:00
|
|
|
if (STREQ(def->os.type, "hvm")) {
|
|
|
|
if (parallelsCreateVm(conn, def))
|
|
|
|
goto cleanup;
|
|
|
|
} else if (STREQ(def->os.type, "exe")) {
|
|
|
|
if (parallelsCreateCt(conn, def))
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Unsupported OS type: %s"), def->os.type);
|
2012-07-31 18:56:11 +00:00
|
|
|
goto cleanup;
|
2012-09-12 12:40:54 +00:00
|
|
|
}
|
2012-07-31 18:56:13 +00:00
|
|
|
if (parallelsLoadDomains(privconn, def->name))
|
|
|
|
goto cleanup;
|
2013-01-11 16:04:47 +00:00
|
|
|
olddom = virDomainObjListFindByName(privconn->domains, def->name);
|
2012-12-04 13:43:12 +00:00
|
|
|
if (!olddom) {
|
2012-07-31 18:56:13 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Domain for '%s' is not defined after creation"),
|
2012-08-03 16:22:08 +00:00
|
|
|
def->name ? def->name : _("(unnamed)"));
|
2012-07-31 18:56:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-07-31 18:56:11 +00:00
|
|
|
}
|
|
|
|
|
2014-05-07 18:04:08 +00:00
|
|
|
if (parallelsApplyChanges(olddom, def) < 0) {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(olddom);
|
2012-12-04 13:43:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(olddom);
|
2012-12-04 13:43:12 +00:00
|
|
|
|
2014-04-23 14:35:02 +00:00
|
|
|
ret = virGetDomain(conn, def->name, def->uuid);
|
2012-07-31 18:56:11 +00:00
|
|
|
if (ret)
|
2014-04-23 14:35:02 +00:00
|
|
|
ret->id = def->id;
|
2012-07-31 18:56:11 +00:00
|
|
|
|
2014-03-25 06:57:01 +00:00
|
|
|
cleanup:
|
2012-07-31 18:56:11 +00:00
|
|
|
virDomainDefFree(def);
|
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-04-26 17:21:58 +00:00
|
|
|
static int
|
|
|
|
parallelsNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virNodeInfoPtr nodeinfo)
|
|
|
|
{
|
|
|
|
return nodeGetInfo(nodeinfo);
|
|
|
|
}
|
|
|
|
|
2014-04-23 14:35:03 +00:00
|
|
|
static int parallelsConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Encryption is not relevant / applicable to way we talk to PCS */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* We run CLI tools directly so this is secure */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parallelsConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-04-26 17:21:58 +00:00
|
|
|
|
2014-06-05 05:50:05 +00:00
|
|
|
static char *
|
|
|
|
parallelsConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
const char **xmlCPUs,
|
|
|
|
unsigned int ncpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
|
|
|
|
|
|
|
|
return cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-05 05:50:04 +00:00
|
|
|
static int
|
|
|
|
parallelsDomainGetVcpus(virDomainPtr domain,
|
|
|
|
virVcpuInfoPtr info,
|
|
|
|
int maxinfo,
|
|
|
|
unsigned char *cpumaps,
|
|
|
|
int maplen)
|
|
|
|
{
|
|
|
|
parallelsConnPtr privconn = domain->conn->privateData;
|
|
|
|
parallelsDomObjPtr privdomdata = NULL;
|
|
|
|
virDomainObjPtr privdom = NULL;
|
|
|
|
size_t i;
|
|
|
|
int v, maxcpu, hostcpus;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
parallelsDriverLock(privconn);
|
|
|
|
privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
|
|
|
parallelsDriverUnlock(privconn);
|
|
|
|
|
|
|
|
if (privdom == NULL) {
|
|
|
|
parallelsDomNotFoundError(domain);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(privdom)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s",
|
|
|
|
_("cannot list vcpu pinning for an inactive domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
privdomdata = privdom->privateData;
|
|
|
|
if ((hostcpus = nodeGetCPUCount()) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
maxcpu = maplen * 8;
|
|
|
|
if (maxcpu > hostcpus)
|
|
|
|
maxcpu = hostcpus;
|
|
|
|
|
|
|
|
if (maxinfo >= 1) {
|
|
|
|
if (info != NULL) {
|
|
|
|
memset(info, 0, sizeof(*info) * maxinfo);
|
|
|
|
for (i = 0; i < maxinfo; i++) {
|
|
|
|
info[i].number = i;
|
|
|
|
info[i].state = VIR_VCPU_RUNNING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cpumaps != NULL) {
|
|
|
|
unsigned char *tmpmap = NULL;
|
|
|
|
int tmpmapLen = 0;
|
|
|
|
|
|
|
|
memset(cpumaps, 0, maplen * maxinfo);
|
|
|
|
virBitmapToData(privdomdata->cpumask, &tmpmap, &tmpmapLen);
|
|
|
|
if (tmpmapLen > maplen)
|
|
|
|
tmpmapLen = maplen;
|
|
|
|
|
|
|
|
for (v = 0; v < maxinfo; v++) {
|
|
|
|
unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
|
|
|
|
memcpy(cpumap, tmpmap, tmpmapLen);
|
|
|
|
}
|
|
|
|
VIR_FREE(tmpmap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = maxinfo;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (privdom)
|
|
|
|
virObjectUnlock(privdom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-31 18:56:05 +00:00
|
|
|
static virDriver parallelsDriver = {
|
|
|
|
.no = VIR_DRV_PARALLELS,
|
|
|
|
.name = "Parallels",
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectOpen = parallelsConnectOpen, /* 0.10.0 */
|
|
|
|
.connectClose = parallelsConnectClose, /* 0.10.0 */
|
|
|
|
.connectGetVersion = parallelsConnectGetVersion, /* 0.10.0 */
|
2013-04-26 16:39:11 +00:00
|
|
|
.connectGetHostname = parallelsConnectGetHostname, /* 0.10.0 */
|
2013-04-26 17:21:58 +00:00
|
|
|
.nodeGetInfo = parallelsNodeGetInfo, /* 0.10.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectGetCapabilities = parallelsConnectGetCapabilities, /* 0.10.0 */
|
2014-06-05 05:50:05 +00:00
|
|
|
.connectBaselineCPU = parallelsConnectBaselineCPU, /* 1.2.6 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectListDomains = parallelsConnectListDomains, /* 0.10.0 */
|
|
|
|
.connectNumOfDomains = parallelsConnectNumOfDomains, /* 0.10.0 */
|
|
|
|
.connectListDefinedDomains = parallelsConnectListDefinedDomains, /* 0.10.0 */
|
|
|
|
.connectNumOfDefinedDomains = parallelsConnectNumOfDefinedDomains, /* 0.10.0 */
|
|
|
|
.connectListAllDomains = parallelsConnectListAllDomains, /* 0.10.0 */
|
|
|
|
.domainLookupByID = parallelsDomainLookupByID, /* 0.10.0 */
|
|
|
|
.domainLookupByUUID = parallelsDomainLookupByUUID, /* 0.10.0 */
|
|
|
|
.domainLookupByName = parallelsDomainLookupByName, /* 0.10.0 */
|
|
|
|
.domainGetOSType = parallelsDomainGetOSType, /* 0.10.0 */
|
|
|
|
.domainGetInfo = parallelsDomainGetInfo, /* 0.10.0 */
|
2012-07-31 18:56:07 +00:00
|
|
|
.domainGetState = parallelsDomainGetState, /* 0.10.0 */
|
|
|
|
.domainGetXMLDesc = parallelsDomainGetXMLDesc, /* 0.10.0 */
|
|
|
|
.domainIsPersistent = parallelsDomainIsPersistent, /* 0.10.0 */
|
|
|
|
.domainGetAutostart = parallelsDomainGetAutostart, /* 0.10.0 */
|
2014-06-05 05:50:04 +00:00
|
|
|
.domainGetVcpus = parallelsDomainGetVcpus, /* 1.2.6 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.domainSuspend = parallelsDomainSuspend, /* 0.10.0 */
|
|
|
|
.domainResume = parallelsDomainResume, /* 0.10.0 */
|
|
|
|
.domainDestroy = parallelsDomainDestroy, /* 0.10.0 */
|
|
|
|
.domainShutdown = parallelsDomainShutdown, /* 0.10.0 */
|
2012-07-31 18:56:08 +00:00
|
|
|
.domainCreate = parallelsDomainCreate, /* 0.10.0 */
|
2012-07-31 18:56:11 +00:00
|
|
|
.domainDefineXML = parallelsDomainDefineXML, /* 0.10.0 */
|
2014-04-23 14:35:03 +00:00
|
|
|
.connectIsEncrypted = parallelsConnectIsEncrypted, /* 1.2.5 */
|
|
|
|
.connectIsSecure = parallelsConnectIsSecure, /* 1.2.5 */
|
|
|
|
.connectIsAlive = parallelsConnectIsAlive, /* 1.2.5 */
|
2012-07-31 18:56:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* parallelsRegister:
|
|
|
|
*
|
|
|
|
* Registers the parallels driver
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
parallelsRegister(void)
|
|
|
|
{
|
|
|
|
char *prlctl_path;
|
|
|
|
|
|
|
|
prlctl_path = virFindFileInPath(PRLCTL);
|
|
|
|
if (!prlctl_path) {
|
|
|
|
VIR_DEBUG("%s", _("Can't find prlctl command in the PATH env"));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(prlctl_path);
|
|
|
|
|
|
|
|
if (virRegisterDriver(¶llelsDriver) < 0)
|
|
|
|
return -1;
|
2012-08-01 03:46:22 +00:00
|
|
|
if (parallelsStorageRegister())
|
|
|
|
return -1;
|
2012-12-11 10:59:45 +00:00
|
|
|
if (parallelsNetworkRegister())
|
|
|
|
return -1;
|
2012-07-31 18:56:05 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|