mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-08-25 13:50:09 +03:00
parallels: get domain info with SDK
Obtain information about domains using parallels sdk instead of prlctl. prlsdkLoadDomains functions behaves as former parallelsLoadDomains with NULL as second parameter (name) - it fills parallelsConn.domains list. prlsdkLoadDomain is now able to update specified domain by given virDomainObjPtr. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com>
This commit is contained in:
committed by
Peter Krempa
parent
d211ba7c49
commit
7039bb3cd1
@ -49,7 +49,6 @@
|
|||||||
#include "virfile.h"
|
#include "virfile.h"
|
||||||
#include "virstoragefile.h"
|
#include "virstoragefile.h"
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
#include "c-ctype.h"
|
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
@ -99,21 +98,6 @@ parallelsDriverUnlock(parallelsConnPtr driver)
|
|||||||
virMutexUnlock(&driver->lock);
|
virMutexUnlock(&driver->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
parallelsDomObjFreePrivate(void *p)
|
|
||||||
{
|
|
||||||
parallelsDomObjPtr pdom = p;
|
|
||||||
|
|
||||||
if (!pdom)
|
|
||||||
return;
|
|
||||||
|
|
||||||
virBitmapFree(pdom->cpumask);
|
|
||||||
VIR_FREE(pdom->uuid);
|
|
||||||
VIR_FREE(pdom->home);
|
|
||||||
VIR_FREE(p);
|
|
||||||
};
|
|
||||||
|
|
||||||
static virCapsPtr
|
static virCapsPtr
|
||||||
parallelsBuildCapabilities(void)
|
parallelsBuildCapabilities(void)
|
||||||
{
|
{
|
||||||
@ -190,729 +174,6 @@ parallelsConnectGetCapabilities(virConnectPtr conn)
|
|||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
} else if (virJSONValueObjectHasKey(value, "socket")) {
|
|
||||||
chr->source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
|
|
||||||
|
|
||||||
tmp = virJSONValueObjectGetString(value, "socket");
|
|
||||||
if (!tmp) {
|
|
||||||
parallelsParseError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(chr->source.data.nix.path, tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(chr->source.data.file.path, tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
parallelsParseError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
parallelsAddSerialInfo(virDomainChrDefPtr **serials, size_t *nserials,
|
|
||||||
const char *key, virJSONValuePtr value)
|
|
||||||
{
|
|
||||||
virDomainChrDefPtr chr = NULL;
|
|
||||||
|
|
||||||
if (!(chr = virDomainChrDefNew()))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (parallelsGetSerialInfo(chr, key, value))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (VIR_APPEND_ELEMENT(*serials, *nserials, chr) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virDomainChrDefFree(chr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virStrToLong_ul(tmp, &endptr, 10, &mem) < 0) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!STREQ(endptr, "Mb")) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_ALLOC(video) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(accel) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (VIR_APPEND_ELEMENT_COPY(def->videos, def->nvideos, video) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
|
|
||||||
video->vram = mem << 20;
|
|
||||||
video->heads = 1;
|
|
||||||
video->accel = accel;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
VIR_FREE(accel);
|
|
||||||
virDomainVideoDefFree(video);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(value, "real"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virDomainDiskSetSource(disk, tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(value, "image"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virDomainDiskSetSource(disk, tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_PLOOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!(disk = virDomainDiskDefNew()))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (parallelsGetHddInfo(def, disk, key, value))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
virDomainDiskDefFree(disk);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
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;
|
|
||||||
error:
|
|
||||||
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 */
|
|
||||||
if (VIR_STRDUP(net->ifname, key) < 0)
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (virJSONValueObjectHasKey(value, "network")) {
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(value, "network"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(net->data.network.name, tmp) < 0)
|
|
||||||
goto error;
|
|
||||||
} else if (virJSONValueObjectHasKey(value, "type")) {
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(value, "type"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!STREQ(tmp, "routed")) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(net->data.network.name,
|
|
||||||
PARALLELS_ROUTED_NETWORK_NAME) < 0)
|
|
||||||
goto error;
|
|
||||||
} else {
|
|
||||||
parallelsParseError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
|
|
||||||
if ((tmp = virJSONValueObjectGetString(value, "state")) &&
|
|
||||||
STREQ(tmp, "disconnected")) {
|
|
||||||
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
parallelsAddNetInfo(virDomainDefPtr def, const char *key, virJSONValuePtr value)
|
|
||||||
{
|
|
||||||
virDomainNetDefPtr net = NULL;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(net) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (parallelsGetNetInfo(net, key, value))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
def->nets[def->nnets - 1] = net;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
virDomainNetDefFree(net);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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")) {
|
|
||||||
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))
|
|
||||||
goto cleanup;
|
|
||||||
} else if (STRPREFIX(key, "hdd")) {
|
|
||||||
if (parallelsAddHddInfo(def, key, value))
|
|
||||||
goto cleanup;
|
|
||||||
} else if (STRPREFIX(key, "net")) {
|
|
||||||
if (parallelsAddNetInfo(def, key, value))
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (STREQ(tmp, "auto")) {
|
|
||||||
if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0)
|
|
||||||
port = 0;
|
|
||||||
gr->data.vnc.autoport = true;
|
|
||||||
} else {
|
|
||||||
if (virJSONValueObjectGetNumberUint(jobj, "port", &port) < 0) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
gr->data.vnc.autoport = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
gr->data.vnc.auth.expires = false;
|
|
||||||
gr->data.vnc.auth.connected = 0;
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(jobj, "address"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_ALLOC(gr->listens) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
gr->nListens = 1;
|
|
||||||
|
|
||||||
if (VIR_STRDUP(gr->listens[0].address, tmp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
|
|
||||||
|
|
||||||
if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virDomainGraphicsDefFree(gr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
int hostcpus;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(def) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(pdom) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
def->virtType = VIR_DOMAIN_VIRT_PARALLELS;
|
|
||||||
def->id = -1;
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(jobj, "Name"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (VIR_STRDUP(def->name, tmp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (VIR_STRDUP(def->description, tmp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(jobj2 = virJSONValueObjectGet(jobj, "Hardware"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(jobj3 = virJSONValueObjectGet(jobj2, "cpu"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virJSONValueObjectGetNumberUint(jobj3, "cpus", &x) == 0) {
|
|
||||||
def->vcpus = x;
|
|
||||||
def->maxvcpus = x;
|
|
||||||
} else if ((tmp = virJSONValueObjectGetString(jobj3, "cpus"))) {
|
|
||||||
if (STREQ(tmp, "unlimited")) {
|
|
||||||
virNodeInfo nodeinfo;
|
|
||||||
|
|
||||||
if (nodeGetInfo(&nodeinfo) < 0) {
|
|
||||||
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 {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (STREQ(tmp, "CT")) {
|
|
||||||
if (VIR_STRDUP(def->os.type, "exe") < 0)
|
|
||||||
goto cleanup;
|
|
||||||
if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
|
|
||||||
goto cleanup;
|
|
||||||
} else if (STREQ(tmp, "VM")) {
|
|
||||||
if (VIR_STRDUP(def->os.type, "hvm") < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
def->os.arch = VIR_ARCH_X86_64;
|
|
||||||
|
|
||||||
if (virJSONValueObjectGetNumberUint(jobj, "EnvID", &x) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
pdom->id = x;
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(jobj, "ID"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (VIR_STRDUP(pdom->uuid, tmp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(tmp = virJSONValueObjectGetString(jobj, "Home"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_STRDUP(pdom->home, tmp) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(state = virJSONValueObjectGetString(jobj, "State"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(autostart = virJSONValueObjectGetString(jobj, "Autostart"))) {
|
|
||||||
parallelsParseError();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parallelsAddDomainHardware(def, jobj2) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (parallelsAddVNCInfo(def, jobj) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!(dom = virDomainObjListAdd(privconn->domains, def,
|
|
||||||
privconn->xmlopt,
|
|
||||||
0, NULL)))
|
|
||||||
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;
|
|
||||||
|
|
||||||
virObjectUnlock(dom);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
size_t i;
|
|
||||||
virJSONValuePtr jobj;
|
|
||||||
virJSONValuePtr jobj2;
|
|
||||||
virDomainObjPtr dom = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
jobj = parallelsParseOutput(PRLCTL, "list", "-j", "-a", "-i", "-H",
|
|
||||||
"--vmtype", "all", domain_name, NULL);
|
|
||||||
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;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virJSONValueFree(jobj);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parallelsDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
parallelsDomainDefPostParse(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||||
virCapsPtr caps ATTRIBUTE_UNUSED,
|
virCapsPtr caps ATTRIBUTE_UNUSED,
|
||||||
@ -972,7 +233,7 @@ parallelsOpenDefault(virConnectPtr conn)
|
|||||||
|
|
||||||
conn->privateData = privconn;
|
conn->privateData = privconn;
|
||||||
|
|
||||||
if (parallelsLoadDomains(privconn, NULL))
|
if (prlsdkLoadDomains(privconn))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return VIR_DRV_OPEN_SUCCESS;
|
return VIR_DRV_OPEN_SUCCESS;
|
||||||
@ -2292,6 +1553,7 @@ parallelsDomainDefineXML(virConnectPtr conn, const char *xml)
|
|||||||
virDomainPtr ret = NULL;
|
virDomainPtr ret = NULL;
|
||||||
virDomainDefPtr def;
|
virDomainDefPtr def;
|
||||||
virDomainObjPtr olddom = NULL;
|
virDomainObjPtr olddom = NULL;
|
||||||
|
virDomainObjPtr dom = NULL;
|
||||||
|
|
||||||
parallelsDriverLock(privconn);
|
parallelsDriverLock(privconn);
|
||||||
if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
|
if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
|
||||||
@ -2316,7 +1578,10 @@ parallelsDomainDefineXML(virConnectPtr conn, const char *xml)
|
|||||||
_("Unsupported OS type: %s"), def->os.type);
|
_("Unsupported OS type: %s"), def->os.type);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (parallelsLoadDomains(privconn, def->name))
|
dom = prlsdkAddDomain(privconn, def->uuid);
|
||||||
|
if (dom)
|
||||||
|
virObjectUnlock(dom);
|
||||||
|
else
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
olddom = virDomainObjListFindByName(privconn->domains, def->name);
|
olddom = virDomainObjListFindByName(privconn->domains, def->name);
|
||||||
if (!olddom) {
|
if (!olddom) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,3 +28,7 @@ int prlsdkInit(parallelsConnPtr privconn);
|
|||||||
void prlsdkDeinit(void);
|
void prlsdkDeinit(void);
|
||||||
int prlsdkConnect(parallelsConnPtr privconn);
|
int prlsdkConnect(parallelsConnPtr privconn);
|
||||||
void prlsdkDisconnect(parallelsConnPtr privconn);
|
void prlsdkDisconnect(parallelsConnPtr privconn);
|
||||||
|
int
|
||||||
|
prlsdkLoadDomains(parallelsConnPtr privconn);
|
||||||
|
virDomainObjPtr
|
||||||
|
prlsdkAddDomain(parallelsConnPtr privconn, const unsigned char *uuid);
|
||||||
|
@ -62,6 +62,7 @@ struct parallelsDomObj {
|
|||||||
char *uuid;
|
char *uuid;
|
||||||
char *home;
|
char *home;
|
||||||
virBitmapPtr cpumask;
|
virBitmapPtr cpumask;
|
||||||
|
PRL_HANDLE sdkdom;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct parallelsDomObj *parallelsDomObjPtr;
|
typedef struct parallelsDomObj *parallelsDomObjPtr;
|
||||||
|
Reference in New Issue
Block a user