[libvirt] [PATCH v3 06/12] parallels: rewrite parallelsApplyConfig with SDK
Maxim Nestratov
mnestratov at parallels.com
Tue Nov 25 13:17:33 UTC 2014
18.11.2014 16:17, Dmitry Guryanov пишет:
> Rewrite code, which applies domain configuration given
> to virDomainDefineXML function to the VM of container
> registered in PCS.
>
> This code first check if there are unsupported parameters
> in domain XML and if yes - reports error. Some of such
> parameters are not supported by PCS, for some - it's not
> obvious, how to convert them into PCS's corresponding params,
> so let's put off it, and implement only basic params in
> this patch.
>
> Signed-off-by: Dmitry Guryanov <dguryanov at parallels.com>
> ---
> src/parallels/parallels_driver.c | 737 +------------------------------
> src/parallels/parallels_sdk.c | 930 +++++++++++++++++++++++++++++++++++++++
> src/parallels/parallels_sdk.h | 4 +
> 3 files changed, 935 insertions(+), 736 deletions(-)
>
> diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
> index 658969f..55ee003 100644
> --- a/src/parallels/parallels_driver.c
> +++ b/src/parallels/parallels_driver.c
> @@ -65,19 +65,6 @@ VIR_LOG_INIT("parallels.parallels_driver");
>
> 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)
> {
> @@ -671,728 +658,6 @@ parallelsDomainGetAutostart(virDomainPtr domain, int *autostart)
> }
>
> 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)
> {
> char uuidstr[VIR_UUID_STRING_BUFLEN];
> @@ -1479,7 +744,7 @@ parallelsDomainDefineXML(virConnectPtr conn, const char *xml)
> }
> }
>
> - if (parallelsApplyChanges(olddom, def) < 0) {
> + if (prlsdkApplyConfig(conn, olddom, def) < 0) {
> virObjectUnlock(olddom);
> goto cleanup;
> }
> diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
> index d42456f..bccb2d7 100644
> --- a/src/parallels/parallels_sdk.c
> +++ b/src/parallels/parallels_sdk.c
> @@ -28,6 +28,7 @@
> #include "nodeinfo.h"
> #include "virlog.h"
> #include "datatypes.h"
> +#include "domain_conf.h"
>
> #include "parallels_sdk.h"
>
> @@ -1608,3 +1609,932 @@ prlsdkDomainChangeState(virDomainPtr domain,
> 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 ||
> + def->onPoweroff ||
> + def->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 (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->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("Setting disk cache mode is not "
> + "supported by parallels driver yet."));
> + 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;
> + 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
> +
> +const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
> +{
> + snprintf(macstr, VIR_MAC_STRING_BUFLEN,
> + "%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);
> +
> + 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);
> +
> + return 0;
> + cleanup:
> + PrlHandle_Free(sdkdisk);
> + return ret;
> +}
> +
> +static int
> +prlsdkDoApplyConfig(PRL_HANDLE sdkdom,
> + virDomainDefPtr def)
> +{
> + PRL_RESULT pret;
> + size_t i;
> +
> + if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
> + return -1;
> +
> + if (def->description) {
> + pret = PrlVmCfg_SetDescription(sdkdom, def->description);
> + prlsdkCheckRetGoto(pret, error);
> + }
> +
Uuid should be applied here via PrlVmCfg_SetUuid
> + if (def->name) {
> + pret = PrlVmCfg_SetName(sdkdom, def->name);
> + 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;
> +}
> diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
> index 1e26672..8de077c 100644
> --- a/src/parallels/parallels_sdk.h
> +++ b/src/parallels/parallels_sdk.h
> @@ -44,3 +44,7 @@ typedef int (*prlsdkChangeStateFunc)(parallelsConnPtr privconn, PRL_HANDLE sdkdo
> int
> prlsdkDomainChangeState(virDomainPtr domain,
> prlsdkChangeStateFunc chstate);
> +int
> +prlsdkApplyConfig(virConnectPtr conn,
> + virDomainObjPtr dom,
> + virDomainDefPtr new);
More information about the libvir-list
mailing list