static int parallelsConnectClose(virConnectPtr conn);
-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;
- }
-}
-
void
parallelsDriverLock(parallelsConnPtr driver)
{
return ret;
}
-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 &&
- (old->data.vnc.port != 0 && new->data.vnc.port != 0)) {
-
- 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;
- error:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("changing display parameters is not supported "
- "by parallels driver"));
- return -1;
-}
-
-static int
-parallelsApplySerialParams(virDomainChrDefPtr *oldserials, int nold,
- virDomainChrDefPtr *newserials, int nnew)
-{
- size_t i, j;
-
- if (nold != nnew)
- goto error;
-
- for (i = 0; i < nold; i++) {
- virDomainChrDefPtr oldserial = oldserials[i];
- virDomainChrDefPtr newserial = NULL;
-
- for (j = 0; j < nnew; j++) {
- 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;
- if (newserial->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
- (!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;
- error:
- virReportError(VIR_ERR_CONFIG_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_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("Only VGA video device is "
- "supported by parallels driver"));
- return -1;
- }
-
- if (new->heads != 1) {
- virReportError(VIR_ERR_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("Changing video acceleration parameters is "
- "not supported by parallels driver"));
- return -1;
-
- }
-
- if (old->vram != new->vram) {
- if (new->vram % (1 << 10) != 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Video RAM size should be multiple of 1Mb."));
- return -1;
- }
-
- snprintf(str_vram, 31, "%dK", new->vram);
- str_vram[31] = '\0';
-
- if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
- "--videosize", str_vram, NULL))
- return -1;
- }
- return 0;
-}
-
-static int parallelsAddHdd(parallelsDomObjPtr pdom,
- virDomainDiskDefPtr disk)
-{
- int ret = -1;
- const char *src = virDomainDiskGetSource(disk);
- int type = virDomainDiskGetType(disk);
- const char *strbus;
-
- virCommandPtr cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
- "--device-add", "hdd", NULL);
-
- if (type == VIR_STORAGE_TYPE_FILE) {
- int format = virDomainDiskGetFormat(disk);
-
- if (format != VIR_STORAGE_FILE_PLOOP) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Invalid disk format: %d"), type);
- goto cleanup;
- }
-
- virCommandAddArg(cmd, "--image");
- } else if (VIR_STORAGE_TYPE_BLOCK) {
- virCommandAddArg(cmd, "--device");
- } else {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Invalid disk type: %d"), type);
- goto cleanup;
- }
-
- virCommandAddArg(cmd, src);
-
- if (!(strbus = parallelsGetDiskBusName(disk->bus))) {
- virReportError(VIR_ERR_CONFIG_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);
-
- if (virCommandRun(cmd, NULL) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- virCommandFree(cmd);
- return ret;
-}
-
-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;
-}
-
-static int
-parallelsApplyDisksParams(parallelsDomObjPtr pdom,
- virDomainDiskDefPtr *olddisks, int nold,
- virDomainDiskDefPtr *newdisks, int nnew)
-{
- size_t i, j;
-
- for (i = 0; i < nold; i++) {
- virDomainDiskDefPtr newdisk = NULL;
- virDomainDiskDefPtr olddisk = olddisks[i];
- for (j = 0; j < nnew; j++) {
- if (STREQ_NULLABLE(newdisks[j]->dst, olddisk->dst)) {
- newdisk = newdisks[j];
- break;
- }
- }
-
- if (!newdisk) {
- if (parallelsRemoveHdd(pdom, olddisk)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Can't remove disk '%s' "
- "in the specified config"), olddisks[i]->serial);
- return -1;
- }
-
- continue;
- }
-
- if (olddisk->bus != newdisk->bus ||
- olddisk->info.addr.drive.target != newdisk->info.addr.drive.target ||
- !STREQ_NULLABLE(virDomainDiskGetSource(olddisk),
- virDomainDiskGetSource(newdisk))) {
-
- 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);
-
- if (!(strbus = parallelsGetDiskBusName(newdisk->bus))) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Unsupported disk bus: %d"), newdisk->bus);
- return -1;
- }
-
- if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
- "--device-set", prlname,
- "--iface", strbus,
- "--position", strpos,
- "--image", newdisk->src, NULL))
- return -1;
- }
- }
-
- 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;
-
- if (parallelsAddHdd(pdom, newdisk))
- return -1;
- }
-
- return 0;
-}
-
-static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom,
- virDomainNetDefPtr oldnet,
- virDomainNetDefPtr newnet)
-{
- bool create = false;
- bool is_changed = false;
- virCommandPtr cmd = NULL;
- char strmac[VIR_MAC_STRING_BUFLEN];
- size_t i;
- int ret = -1;
-
- if (!oldnet) {
- create = true;
- if (VIR_ALLOC(oldnet) < 0)
- return -1;
- }
-
- if (!create && oldnet->type != newnet->type) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Changing network type is not supported"));
- goto cleanup;
- }
-
- if (!STREQ_NULLABLE(oldnet->model, newnet->model)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Changing network device model is not supported"));
- goto cleanup;
- }
-
- if (!STREQ_NULLABLE(oldnet->data.network.portgroup,
- newnet->data.network.portgroup)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Changing network portgroup is not supported"));
- goto cleanup;
- }
-
- if (!virNetDevVPortProfileEqual(oldnet->virtPortProfile,
- newnet->virtPortProfile)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Changing virtual port profile is not supported"));
- goto cleanup;
- }
-
- if (newnet->tune.sndbuf_specified) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting send buffer size is not supported"));
- goto cleanup;
- }
-
- if (!STREQ_NULLABLE(oldnet->script, newnet->script)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting startup script is not supported"));
- goto cleanup;
- }
-
- if (!STREQ_NULLABLE(oldnet->filter, newnet->filter)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Changing filter params is not supported"));
- goto cleanup;
- }
-
- if (newnet->bandwidth != NULL) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting bandwidth params is not supported"));
- goto cleanup;
- }
-
- for (i = 0; i < sizeof(newnet->vlan); i++) {
- if (((char *)&newnet->vlan)[i] != 0) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting vlan params is not supported"));
- goto cleanup;
- }
- }
-
- /* 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)) {
- if (STREQ_NULLABLE(newnet->data.network.name,
- PARALLELS_ROUTED_NETWORK_NAME)) {
- virCommandAddArgFormat(cmd, "--type=routed");
- } else {
- virCommandAddArgFormat(cmd, "--network=%s",
- newnet->data.network.name);
- }
-
- 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 */
- ret = 0;
- goto cleanup;
- }
-
- if (virCommandRun(cmd, NULL) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- if (create)
- VIR_FREE(oldnet);
- virCommandFree(cmd);
- return ret;
-}
-
-static int
-parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
- virDomainNetDefPtr *oldnets, int nold,
- virDomainNetDefPtr *newnets, int nnew)
-{
- size_t i, j;
- 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;
-}
-
-static int
-parallelsApplyChanges(virDomainObjPtr dom, virDomainDefPtr new)
-{
- char buf[32];
- size_t i;
-
- 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_CONFIG_UNSUPPORTED, "%s",
- _("titles are not supported by parallels driver"));
- return -1;
- }
-
- if (new->blkio.ndevices > 0) {
- virReportError(VIR_ERR_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("changing balloon parameters is not supported "
- "by parallels driver"));
- return -1;
- }
-
- if (new->mem.max_balloon % (1 << 10) != 0) {
- virReportError(VIR_ERR_CONFIG_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.nhugepages != new->mem.nhugepages ||
- 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_CONFIG_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_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("changing cpu placement mode is not supported "
- "by parallels driver"));
- return -1;
- }
-
- if ((old->cpumask != NULL || new->cpumask != NULL) &&
- (old->cpumask == NULL || new->cpumask == NULL ||
- !virBitmapEqual(old->cpumask, new->cpumask))) {
-
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("changing cpu mask is not supported "
- "by parallels driver"));
- return -1;
- }
-
- if (old->cputune.shares != new->cputune.shares ||
- old->cputune.sharesSpecified != new->cputune.sharesSpecified ||
- old->cputune.period != new->cputune.period ||
- old->cputune.quota != new->cputune.quota ||
- old->cputune.nvcpupin != new->cputune.nvcpupin) {
-
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("cputune is not supported by parallels driver"));
- return -1;
- }
-
- if (!virDomainNumatuneEquals(old->numatune, new->numatune)) {
- virReportError(VIR_ERR_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("on_reboot, on_poweroff and on_crash parameters "
- "are not supported by parallels driver"));
- return -1;
- }
-
- /* 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 */
-
- if (!STREQ_NULLABLE(old->os.type, new->os.type) ||
- old->os.arch != new->os.arch ||
- 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) {
-
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("changing OS parameters is not supported "
- "by parallels driver"));
- return -1;
- }
- 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_CONFIG_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_CONFIG_UNSUPPORTED, "%s",
- _("changing OS parameters is not supported "
- "by parallels driver"));
- return -1;
- }
- }
-
-
- if (!STREQ_NULLABLE(old->emulator, new->emulator)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("changing emulator is not supported "
- "by parallels driver"));
- return -1;
- }
-
- for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
- if (old->features[i] != new->features[i]) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("changing features is not supported "
- "by parallels driver"));
- return -1;
- }
- }
-
- if (new->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
- new->clock.ntimers != 0) {
-
- virReportError(VIR_ERR_CONFIG_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;
-
- if (new->nfss != 0 ||
- 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_CONFIG_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_CONFIG_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;
- if (parallelsApplyDisksParams(pdom, old->disks, old->ndisks,
- new->disks, new->ndisks) < 0)
- return -1;
- if (parallelsApplyIfacesParams(pdom, old->nets, old->nnets,
- new->nets, new->nnets) < 0)
- return -1;
-
- return 0;
-}
-
static int
parallelsCreateVm(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainDefPtr def)
{
}
}
- if (parallelsApplyChanges(olddom, def) < 0) {
+ if (prlsdkApplyConfig(conn, olddom, def) < 0) {
virObjectUnlock(olddom);
goto cleanup;
}
#include "nodeinfo.h"
#include "virlog.h"
#include "datatypes.h"
+#include "domain_conf.h"
#include "parallels_sdk.h"
virObjectUnlock(dom);
return ret;
}
+
+static int
+prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+ size_t i;
+ PRL_VM_TYPE vmType;
+ PRL_RESULT pret;
+
+ if (def->title) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("titles are not supported by parallels driver"));
+ return -1;
+ }
+
+ if (def->blkio.ndevices > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("blkio parameters are not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->mem.max_balloon != def->mem.cur_balloon) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing balloon parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->mem.max_balloon % (1 << 10) != 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Memory size should be multiple of 1Mb."));
+ return -1;
+ }
+
+ if (def->mem.nhugepages ||
+ def->mem.hard_limit ||
+ def->mem.soft_limit ||
+ def->mem.min_guarantee ||
+ def->mem.swap_hard_limit) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Memory parameter is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->vcpus != def->maxvcpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("current vcpus must be equal to maxvcpus"));
+ return -1;
+ }
+
+ if (def->placement_mode) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing cpu placement mode is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->cpumask != NULL) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing cpu mask is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->cputune.shares ||
+ def->cputune.sharesSpecified ||
+ def->cputune.period ||
+ def->cputune.quota ||
+ def->cputune.nvcpupin) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("cputune is not supported by parallels driver"));
+ return -1;
+ }
+
+ if (def->numatune) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("numa parameters are not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART ||
+ def->onPoweroff != VIR_DOMAIN_LIFECYCLE_DESTROY ||
+ def->onCrash != VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("on_reboot, on_poweroff and on_crash parameters "
+ "are not supported by parallels driver"));
+ return -1;
+ }
+
+ /* 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 */
+
+ if (def->os.machine != NULL || def->os.bootmenu != 0 ||
+ def->os.kernel != NULL || def->os.initrd != NULL ||
+ def->os.cmdline != NULL || def->os.root != NULL ||
+ def->os.loader != NULL || def->os.bootloader != NULL ||
+ def->os.bootloaderArgs != NULL || def->os.smbios_mode != 0 ||
+ def->os.bios.useserial != 0) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing OS parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ pret = PrlVmCfg_GetVmType(sdkdom, &vmType);
+ if (PRL_FAILED(pret)) {
+ logPrlError(pret);
+ return -1;
+ }
+
+ if (!(vmType == PVT_VM && STREQ(def->os.type, "hvm")) &&
+ !(vmType == PVT_CT && STREQ(def->os.type, "exe"))) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing OS type is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (STREQ(def->os.type, "hvm")) {
+ if (def->os.nBootDevs != 1 ||
+ def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK ||
+ def->os.init != NULL || def->os.initargv != NULL) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing OS parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+ } else {
+ if (def->os.nBootDevs != 0 ||
+ !STREQ_NULLABLE(def->os.init, "/sbin/init") ||
+ (def->os.initargv != NULL && def->os.initargv[0] != NULL)) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing OS parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+ }
+
+ if (def->emulator) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing emulator is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
+ if (def->features[i]) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing features is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+ }
+
+ if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
+ def->clock.ntimers != 0) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing clock parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ if (def->nfss != 0 ||
+ def->nsounds != 0 || def->nhostdevs != 0 ||
+ def->nredirdevs != 0 || def->nsmartcards != 0 ||
+ def->nparallels || def->nchannels != 0 ||
+ def->nleases != 0 || def->nhubs != 0) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing devices parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ /* there may be one auto-input */
+ if (def->ninputs != 0 &&
+ (def->ninputs != 2 &&
+ def->inputs[0]->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
+ def->inputs[0]->bus != VIR_DOMAIN_INPUT_BUS_PS2 &&
+ def->inputs[1]->type != VIR_DOMAIN_INPUT_TYPE_KBD &&
+ def->inputs[1]->bus != VIR_DOMAIN_INPUT_BUS_PS2)) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("changing input devices parameters is not supported "
+ "by parallels driver"));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prlsdkClearDevices(PRL_HANDLE sdkdom)
+{
+ PRL_RESULT pret;
+ PRL_UINT32 n, i;
+ PRL_HANDLE devList;
+ PRL_HANDLE dev;
+ int ret = -1;
+
+ pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmCfg_GetAllDevices(sdkdom, &devList);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlHndlList_GetItemsCount(devList, &n);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ for (i = 0; i < n; i++) {
+ pret = PrlHndlList_GetItem(devList, i, &dev);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_Remove(dev);
+ PrlHandle_Free(dev);
+ }
+
+ ret = 0;
+ cleanup:
+ PrlHandle_Free(devList);
+ return ret;
+}
+
+static int prlsdkCheckGraphicsUnsupportedParams(virDomainDefPtr def)
+{
+ virDomainGraphicsDefPtr gr;
+
+ if (def->ngraphics == 0)
+ return 0;
+
+ if (def->ngraphics >1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server supports only "
+ "one VNC per domain."));
+ return -1;
+ }
+
+ gr = def->graphics[0];
+
+ if (gr->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server supports only "
+ "VNC graphics."));
+ return -1;
+ }
+
+ if (gr->data.vnc.websocket != 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "websockets for VNC graphics."));
+ return -1;
+ }
+
+ if (gr->data.vnc.keymap != 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "keymap setting for VNC graphics."));
+ return -1;
+ }
+
+ if (gr->data.vnc.sharePolicy == VIR_DOMAIN_GRAPHICS_VNC_SHARE_ALLOW_EXCLUSIVE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "exclusive share policy for VNC graphics."));
+ return -1;
+ }
+
+ if (gr->data.vnc.socket) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "VNC graphics over unix sockets."));
+ return -1;
+ }
+
+ if (gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL ||
+ gr->data.vnc.auth.connected == VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "given action in case of password change."));
+ return -1;
+ }
+
+ if (gr->data.vnc.auth.expires) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "setting password expire time."));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prlsdkCheckVideoUnsupportedParams(virDomainDefPtr def)
+{
+ bool isCt = STREQ(def->os.type, "exe");
+ virDomainVideoDefPtr v;
+
+ if (isCt) {
+ if (def->nvideos == 0) {
+ return 0;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Video adapters are not supported "
+ "int containers."));
+ return -1;
+ }
+ } else {
+ if (def->nvideos != 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server supports "
+ "only one video adapter."));
+ return -1;
+ }
+ }
+
+ v = def->videos[0];
+
+ if (v->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server supports "
+ "only VGA video adapters."));
+ return -1;
+ }
+
+ if (v->heads != 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "multihead video adapters."));
+ return -1;
+ }
+
+ if (v->accel == NULL || v->accel->support2d || v->accel->support3d) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "setting video acceleration parameters."));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prlsdkCheckSerialUnsupportedParams(virDomainChrDefPtr chr)
+{
+ if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified character device type is not supported "
+ "by parallels driver."));
+ return -1;
+ }
+
+ if (chr->targetTypeAttr) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified character device target type is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (chr->source.type != VIR_DOMAIN_CHR_TYPE_DEV &&
+ chr->source.type != VIR_DOMAIN_CHR_TYPE_FILE &&
+ chr->source.type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified character device source type is not "
+ "supported by Parallels Cloud Server."));
+ return -1;
+ }
+
+ if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting device info for character devices is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (chr->nseclabels > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting security labels is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prlsdkCheckNetUnsupportedParams(virDomainNetDefPtr net)
+{
+ if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified network adapter type is not "
+ "supported by Parallels Cloud Server."));
+ return -1;
+ }
+
+ if (net->backend.tap || net->backend.vhost) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Interface backend parameters are not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->data.network.portgroup) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Virtual network portgroups are not "
+ "supported by Parallels Cloud Server."));
+ return -1;
+ }
+
+ if (net->tune.sndbuf_specified) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting interface sndbuf is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->script) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting interface script is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->ifname_guest) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting guest interface name is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting device info for network devices is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->filter) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting network filter is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->bandwidth) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting network bandwidth is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (net->vlan.trunk) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting up vlans is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prlsdkCheckDiskUnsupportedParams(virDomainDiskDefPtr disk)
+{
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only hard disks are supported "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->blockio.logical_block_size ||
+ disk->blockio.physical_block_size) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk block sizes is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->blkdeviotune.total_bytes_sec ||
+ disk->blkdeviotune.read_bytes_sec ||
+ disk->blkdeviotune.write_bytes_sec ||
+ disk->blkdeviotune.total_iops_sec ||
+ disk->blkdeviotune.read_iops_sec ||
+ disk->blkdeviotune.write_iops_sec) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk io limits is not "
+ "supported by parallels driver yet."));
+ return -1;
+ }
+
+ if (disk->serial) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk serial number is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->wwn) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk wwn id is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->vendor) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk vendor is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->product) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk product id is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->error_policy != VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk error policy is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->iomode) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting disk io mode is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->copy_on_read) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Disk copy_on_read is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting up disk startup policy is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->transient) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Transient disks are not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->discard) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting up disk discard parameter is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->iothread) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting up disk io thread # is not "
+ "supported by parallels driver."));
+ return -1;
+ }
+
+ if (disk->src->type != VIR_STORAGE_TYPE_FILE &&
+ disk->src->type != VIR_STORAGE_TYPE_BLOCK) {
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only disk and block storage types are "
+ "supported by parallels driver."));
+ return -1;
+
+ }
+
+ return 0;
+}
+
+static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+ virDomainGraphicsDefPtr gr;
+ PRL_RESULT pret;
+ int ret = -1;
+
+ if (prlsdkCheckGraphicsUnsupportedParams(def))
+ return -1;
+
+ if (def->ngraphics == 0)
+ return 0;
+
+ gr = def->graphics[0];
+
+ if (gr->data.vnc.autoport) {
+ pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_AUTO);
+ prlsdkCheckRetGoto(pret, cleanup);
+ } else {
+ pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_MANUAL);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmCfg_SetVNCPort(sdkdom, gr->data.vnc.port);
+ prlsdkCheckRetGoto(pret, cleanup);
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+static int prlsdkApplyVideoParams(PRL_HANDLE sdkdom ATTRIBUTE_UNUSED, virDomainDefPtr def)
+{
+ PRL_RESULT pret;
+
+ if (def->nvideos == 0)
+ return 0;
+
+ if (IS_CT(def)) {
+ /* ignore video parameters */
+ return 0;
+ }
+
+ if (prlsdkCheckVideoUnsupportedParams(def))
+ return -1;
+
+ pret = PrlVmCfg_SetVideoRamSize(sdkdom, def->videos[0]->vram >> 10);
+ prlsdkCheckRetGoto(pret, error);
+
+ return 0;
+ error:
+ return -1;
+}
+
+static int prlsdkAddSerial(PRL_HANDLE sdkdom, virDomainChrDefPtr chr)
+{
+ PRL_RESULT pret;
+ PRL_HANDLE sdkchr = PRL_INVALID_HANDLE;
+ PRL_VM_DEV_EMULATION_TYPE emutype;
+ PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode =
+ PSP_SERIAL_SOCKET_SERVER;
+ char *path;
+ int ret = -1;
+
+ if (prlsdkCheckSerialUnsupportedParams(chr) < 0)
+ return -1;
+
+ pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_SERIAL_PORT, &sdkchr);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ switch (chr->source.type) {
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ emutype = PDT_USE_REAL_DEVICE;
+ path = chr->source.data.file.path;
+ break;
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ emutype = PDT_USE_OUTPUT_FILE;
+ path = chr->source.data.file.path;
+ break;
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ emutype = PDT_USE_SERIAL_PORT_SOCKET_MODE;
+ path = chr->source.data.nix.path;
+ if (chr->source.data.nix.listen)
+ socket_mode = PSP_SERIAL_SOCKET_SERVER;
+ else
+ socket_mode = PSP_SERIAL_SOCKET_CLIENT;
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Parallels Cloud Server doesn't support "
+ "specified serial source type."));
+ goto cleanup;
+ }
+
+ pret = PrlVmDev_SetEmulatedType(sdkchr, emutype);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetSysName(sdkchr, path);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetFriendlyName(sdkchr, path);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX) {
+ pret = PrlVmDevSerial_SetSocketMode(sdkchr, socket_mode);
+ prlsdkCheckRetGoto(pret, cleanup);
+ }
+
+ pret = PrlVmDev_SetEnabled(sdkchr, 1);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetIndex(sdkchr, chr->target.port);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ ret = 0;
+ cleanup:
+ PrlHandle_Free(sdkchr);
+ return ret;
+}
+
+#define PRL_MAC_STRING_BUFNAME 13
+
+static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
+{
+ snprintf(macstr, PRL_MAC_STRING_BUFNAME,
+ "%02X%02X%02X%02X%02X%02X",
+ mac->addr[0], mac->addr[1], mac->addr[2],
+ mac->addr[3], mac->addr[4], mac->addr[5]);
+ macstr[PRL_MAC_STRING_BUFNAME - 1] = '\0';
+ return macstr;
+}
+
+static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
+{
+ PRL_RESULT pret;
+ PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
+ int ret = -1;
+ char macstr[PRL_MAC_STRING_BUFNAME];
+
+ if (prlsdkCheckNetUnsupportedParams(net) < 0)
+ return -1;
+
+ pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_GENERIC_NETWORK_ADAPTER, &sdknet);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetEnabled(sdknet, 1);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetConnected(sdknet, net->linkstate);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (net->ifname) {
+ pret = PrlVmDevNet_SetHostInterfaceName(sdknet, net->ifname);
+ prlsdkCheckRetGoto(pret, cleanup);
+ }
+
+ prlsdkFormatMac(&net->mac, macstr);
+ pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (STREQ(net->data.network.name, PARALLELS_ROUTED_NETWORK_NAME)) {
+ pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
+ prlsdkCheckRetGoto(pret, cleanup);
+ } else {
+ pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
+ prlsdkCheckRetGoto(pret, cleanup);
+ }
+
+ if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES)
+ pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 0);
+ else if (net->trustGuestRxFilters == VIR_TRISTATE_BOOL_NO)
+ pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet, 1);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ ret = 0;
+ cleanup:
+ PrlHandle_Free(sdknet);
+ return ret;
+}
+
+static int prlsdkAddDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
+{
+ PRL_RESULT pret;
+ PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
+ int ret = -1;
+ PRL_VM_DEV_EMULATION_TYPE emutype;
+ PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus;
+
+ if (prlsdkCheckDiskUnsupportedParams(disk) < 0)
+ return -1;
+
+ pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetEnabled(sdkdisk, 1);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetConnected(sdkdisk, 1);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (disk->src->type == VIR_STORAGE_TYPE_FILE) {
+ if (virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid disk format: %d"), disk->src->type);
+ goto cleanup;
+ }
+
+ emutype = PDT_USE_IMAGE_FILE;
+ } else {
+ emutype = PDT_USE_REAL_DEVICE;
+ }
+
+ pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ switch (disk->bus) {
+ case VIR_DOMAIN_DISK_BUS_IDE:
+ sdkbus = PMS_IDE_DEVICE;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SCSI:
+ sdkbus = PMS_SCSI_DEVICE;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SATA:
+ sdkbus = PMS_SATA_DEVICE;
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified disk bus is not "
+ "supported by Parallels Cloud Server."));
+ goto cleanup;
+ }
+
+ pret = PrlVmDev_SetIfaceType(sdkdisk, sdkbus);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlVmDev_SetStackIndex(sdkdisk, disk->info.addr.drive.target);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ switch (disk->cachemode) {
+ case VIR_DOMAIN_DISK_CACHE_DISABLE:
+ pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_FALSE);
+ prlsdkCheckRetGoto(pret, cleanup);
+ break;
+ case VIR_DOMAIN_DISK_CACHE_WRITEBACK:
+ pret = PrlVmCfg_SetDiskCacheWriteBack(sdkdom, PRL_TRUE);
+ prlsdkCheckRetGoto(pret, cleanup);
+ break;
+ case VIR_DOMAIN_DISK_CACHE_DEFAULT:
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Specified disk cache mode is not "
+ "supported by Parallels Cloud Server."));
+ goto cleanup;
+ }
+
+ return 0;
+ cleanup:
+ PrlHandle_Free(sdkdisk);
+ return ret;
+}
+
+static int
+prlsdkDoApplyConfig(PRL_HANDLE sdkdom,
+ virDomainDefPtr def)
+{
+ PRL_RESULT pret;
+ size_t i;
+ char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+
+ if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
+ return -1;
+
+ if (def->description) {
+ pret = PrlVmCfg_SetDescription(sdkdom, def->description);
+ prlsdkCheckRetGoto(pret, error);
+ }
+
+ if (def->name) {
+ pret = PrlVmCfg_SetName(sdkdom, def->name);
+ prlsdkCheckRetGoto(pret, error);
+ }
+
+ if (def->uuid) {
+ prlsdkUUIDFormat(def->uuid, uuidstr);
+
+ pret = PrlVmCfg_SetUuid(sdkdom, uuidstr);
+ prlsdkCheckRetGoto(pret, error);
+ }
+
+ pret = PrlVmCfg_SetRamSize(sdkdom, def->mem.max_balloon >> 10);
+ prlsdkCheckRetGoto(pret, error);
+
+ pret = PrlVmCfg_SetCpuCount(sdkdom, def->vcpus);
+ prlsdkCheckRetGoto(pret, error);
+
+ if (prlsdkClearDevices(sdkdom) < 0)
+ goto error;
+
+ if (prlsdkApplyGraphicsParams(sdkdom, def) < 0)
+ goto error;
+
+ if (prlsdkApplyVideoParams(sdkdom, def) < 0)
+ goto error;
+
+ for (i = 0; i < def->nserials; i++) {
+ if (prlsdkAddSerial(sdkdom, def->serials[i]) < 0)
+ goto error;
+ }
+
+ for (i = 0; i < def->nnets; i++) {
+ if (prlsdkAddNet(sdkdom, def->nets[i]) < 0)
+ goto error;
+ }
+
+ for (i = 0; i < def->ndisks; i++) {
+ if (prlsdkAddDisk(sdkdom, def->disks[i]) < 0)
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ return -1;
+
+}
+
+int
+prlsdkApplyConfig(virConnectPtr conn,
+ virDomainObjPtr dom,
+ virDomainDefPtr new)
+{
+ parallelsConnPtr privconn = conn->privateData;
+ PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
+ PRL_HANDLE job = PRL_INVALID_HANDLE;
+ int ret;
+
+ sdkdom = prlsdkSdkDomainLookupByUUID(privconn, dom->def->uuid);
+ if (sdkdom == PRL_INVALID_HANDLE)
+ return -1;
+
+ job = PrlVm_BeginEdit(sdkdom);
+ if (waitJob(job, privconn->jobTimeout) < 0)
+ return -1;
+
+ ret = prlsdkDoApplyConfig(sdkdom, new);
+
+ if (ret == 0) {
+ job = PrlVm_Commit(sdkdom);
+ ret = waitJob(job, privconn->jobTimeout);
+ }
+
+ PrlHandle_Free(sdkdom);
+
+ return ret;
+}