1 /*
2  * vz_driver.c: core driver functions for managing
3  * Parallels Cloud Server hosts
4  *
5  * Copyright (C) 2014-2015 Red Hat, Inc.
6  * Copyright (C) 2012 Parallels, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 #include <config.h>
25 
26 #include <sys/types.h>
27 #include <sys/poll.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <pwd.h>
33 #include <sys/time.h>
34 #include <sys/statvfs.h>
35 
36 #include "datatypes.h"
37 #include "virerror.h"
38 #include "viralloc.h"
39 #include "virlog.h"
40 #include "vircommand.h"
41 #include "configmake.h"
42 #include "virfile.h"
43 #include "virpidfile.h"
44 #include "virstoragefile.h"
45 #include "virstring.h"
46 #include "cpu/cpu.h"
47 #include "virtypedparam.h"
48 #include "virhostmem.h"
49 #include "virhostcpu.h"
50 #include "viraccessapicheck.h"
51 #include "virutil.h"
52 
53 #include "vz_driver.h"
54 #include "vz_utils.h"
55 #include "vz_sdk.h"
56 
57 #define VIR_FROM_THIS VIR_FROM_PARALLELS
58 
59 VIR_LOG_INIT("parallels.parallels_driver");
60 
61 #define PRLCTL                      "prlctl"
62 
63 #define VZ_STATEDIR RUNSTATEDIR "/libvirt/vz"
64 
65 static virClass *vzDriverClass;
66 
67 static bool vz_driver_privileged;
68 /* pid file FD, ensures two copies of the driver can't use the same root */
69 static int vz_driver_lock_fd = -1;
70 static virMutex vz_driver_lock;
71 static struct _vzDriver *vz_driver;
72 static struct _vzConn *vz_conn_list;
73 
74 static struct _vzDriver *
75 vzDriverObjNew(void);
76 
77 static int
vzCapsAddGuestDomain(virCaps * caps,virDomainOSType ostype,virArch arch,const char * emulator,virDomainVirtType virt_type)78 vzCapsAddGuestDomain(virCaps *caps,
79                      virDomainOSType ostype,
80                      virArch arch,
81                      const char * emulator,
82                      virDomainVirtType virt_type)
83 {
84     virCapsGuest *guest;
85 
86     guest = virCapabilitiesAddGuest(caps, ostype, arch,
87                                     emulator, NULL, 0, NULL);
88 
89     virCapabilitiesAddGuestDomain(guest, virt_type, NULL, NULL, 0, NULL);
90 
91     return 0;
92 }
93 
94 static virCaps *
vzBuildCapabilities(void)95 vzBuildCapabilities(void)
96 {
97     virCaps *caps = NULL;
98     virNodeInfo nodeinfo;
99     virDomainOSType ostypes[] = {
100         VIR_DOMAIN_OSTYPE_HVM,
101         VIR_DOMAIN_OSTYPE_EXE
102     };
103     virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 };
104     const char *const emulators[] = { "vz", "parallels"};
105     virDomainVirtType virt_types[] = {
106         VIR_DOMAIN_VIRT_VZ,
107         VIR_DOMAIN_VIRT_PARALLELS
108     };
109     size_t i, j, k;
110 
111     G_STATIC_ASSERT(G_N_ELEMENTS(archs) == G_N_ELEMENTS(emulators));
112 
113     if ((caps = virCapabilitiesNew(virArchFromHost(),
114                                    false, false)) == NULL)
115         return NULL;
116 
117     if (!(caps->host.numa = virCapabilitiesHostNUMANewHost()))
118         goto error;
119 
120     if (virCapabilitiesInitCaches(caps) < 0)
121         goto error;
122 
123     for (i = 0; i < G_N_ELEMENTS(ostypes); i++)
124         for (j = 0; j < G_N_ELEMENTS(archs); j++)
125             for (k = 0; k < G_N_ELEMENTS(emulators); k++)
126                 if (vzCapsAddGuestDomain(caps, ostypes[i], archs[j],
127                                          emulators[k], virt_types[k]) < 0)
128                     goto error;
129 
130     if (virCapabilitiesGetNodeInfo(&nodeinfo))
131         goto error;
132 
133     if (!(caps->host.cpu = virCPUGetHost(caps->host.arch, VIR_CPU_TYPE_HOST,
134                                          &nodeinfo, NULL)))
135         goto error;
136 
137     if (virCapabilitiesAddHostMigrateTransport(caps, "vzmigr") < 0)
138         goto error;
139 
140     return caps;
141 
142  error:
143     virObjectUnref(caps);
144     return NULL;
145 }
146 
vzDriverDispose(void * obj)147 static void vzDriverDispose(void * obj)
148 {
149     struct _vzDriver *driver = obj;
150 
151     prlsdkDisconnect(driver);
152     virObjectUnref(driver->domains);
153     virObjectUnref(driver->caps);
154     virObjectUnref(driver->xmlopt);
155     virObjectUnref(driver->domainEventState);
156     virSysinfoDefFree(driver->hostsysinfo);
157 }
158 
vzDriverOnceInit(void)159 static int vzDriverOnceInit(void)
160 {
161     if (!VIR_CLASS_NEW(vzDriver, virClassForObjectLockable()))
162         return -1;
163 
164     return 0;
165 }
166 VIR_ONCE_GLOBAL_INIT(vzDriver);
167 
168 struct _vzDriver *
vzGetDriverConnection(void)169 vzGetDriverConnection(void)
170 {
171     if (!vz_driver_privileged) {
172         virReportError(VIR_ERR_INTERNAL_ERROR,
173                        "%s", _("vz state driver is not active"));
174         return NULL;
175     }
176     virMutexLock(&vz_driver_lock);
177     if (!vz_driver)
178         vz_driver = vzDriverObjNew();
179     virObjectRef(vz_driver);
180     virMutexUnlock(&vz_driver_lock);
181 
182     return vz_driver;
183 }
184 
185 void
vzDestroyDriverConnection(void)186 vzDestroyDriverConnection(void)
187 {
188     struct _vzDriver *driver;
189     struct _vzConn *privconn_list;
190 
191     virMutexLock(&vz_driver_lock);
192     driver = g_steal_pointer(&vz_driver);
193     privconn_list = g_steal_pointer(&vz_conn_list);
194     virMutexUnlock(&vz_driver_lock);
195 
196     while (privconn_list) {
197         struct _vzConn *privconn = privconn_list;
198         privconn_list = privconn->next;
199         virConnectCloseCallbackDataCall(privconn->closeCallback,
200                                         VIR_CONNECT_CLOSE_REASON_EOF);
201     }
202     virObjectUnref(driver);
203 }
204 
205 static char *
vzConnectGetCapabilities(virConnectPtr conn)206 vzConnectGetCapabilities(virConnectPtr conn)
207 {
208     struct _vzConn *privconn = conn->privateData;
209 
210     if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
211         return NULL;
212 
213     return virCapabilitiesFormatXML(privconn->driver->caps);
214 }
215 
216 static int
vzDomainDefAddDefaultInputDevices(virDomainDef * def)217 vzDomainDefAddDefaultInputDevices(virDomainDef *def)
218 {
219     int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS :
220                            VIR_DOMAIN_INPUT_BUS_PS2;
221 
222     if (def->ngraphics == 0)
223         return 0;
224 
225     if (virDomainDefMaybeAddInput(def,
226                                   VIR_DOMAIN_INPUT_TYPE_MOUSE,
227                                   bus) < 0)
228         return -1;
229 
230     if (virDomainDefMaybeAddInput(def,
231                                   VIR_DOMAIN_INPUT_TYPE_KBD,
232                                   bus) < 0)
233         return -1;
234 
235     return 0;
236 }
237 
238 static int
vzDomainDefPostParse(virDomainDef * def,unsigned int parseFlags G_GNUC_UNUSED,void * opaque,void * parseOpaque G_GNUC_UNUSED)239 vzDomainDefPostParse(virDomainDef *def,
240                      unsigned int parseFlags G_GNUC_UNUSED,
241                      void *opaque,
242                      void *parseOpaque G_GNUC_UNUSED)
243 {
244     struct _vzDriver *driver = opaque;
245     if (!virCapabilitiesDomainSupported(driver->caps, def->os.type,
246                                         def->os.arch,
247                                         def->virtType))
248         return -1;
249 
250     if (vzDomainDefAddDefaultInputDevices(def) < 0)
251         return -1;
252 
253     return 0;
254 }
255 
256 static int
vzDomainDefValidate(const virDomainDef * def,void * opaque,void * parseOpaque G_GNUC_UNUSED)257 vzDomainDefValidate(const virDomainDef *def,
258                     void *opaque,
259                     void *parseOpaque G_GNUC_UNUSED)
260 {
261     if (vzCheckUnsupportedControllers(def, opaque) < 0)
262         return -1;
263 
264     return 0;
265 }
266 
267 static int
vzDomainDeviceDefPostParse(virDomainDeviceDef * dev,const virDomainDef * def,unsigned int parseFlags G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED,void * parseOpaque G_GNUC_UNUSED)268 vzDomainDeviceDefPostParse(virDomainDeviceDef *dev,
269                            const virDomainDef *def,
270                            unsigned int parseFlags G_GNUC_UNUSED,
271                            void *opaque G_GNUC_UNUSED,
272                            void *parseOpaque G_GNUC_UNUSED)
273 {
274     if (dev->type == VIR_DOMAIN_DEVICE_NET &&
275         (dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
276          dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
277         dev->data.net->model == VIR_DOMAIN_NET_MODEL_UNKNOWN &&
278         def->os.type == VIR_DOMAIN_OSTYPE_HVM)
279         dev->data.net->model = VIR_DOMAIN_NET_MODEL_E1000;
280 
281     if (dev->type == VIR_DOMAIN_DEVICE_VIDEO &&
282         dev->data.video->type == VIR_DOMAIN_VIDEO_TYPE_DEFAULT) {
283         if (def->os.type == VIR_DOMAIN_OSTYPE_HVM)
284             dev->data.video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
285         else
286             dev->data.video->type = VIR_DOMAIN_VIDEO_TYPE_PARALLELS;
287     }
288 
289     return 0;
290 }
291 
292 static int
vzDomainDeviceDefValidate(const virDomainDeviceDef * dev,const virDomainDef * def,void * opaque,void * parseOpaque G_GNUC_UNUSED)293 vzDomainDeviceDefValidate(const virDomainDeviceDef *dev,
294                           const virDomainDef *def,
295                           void *opaque,
296                           void *parseOpaque G_GNUC_UNUSED)
297 {
298     struct _vzDriver *driver = opaque;
299 
300     if (dev->type == VIR_DOMAIN_DEVICE_DISK)
301         return vzCheckUnsupportedDisk(def, dev->data.disk, &driver->vzCaps);
302     else if (dev->type == VIR_DOMAIN_DEVICE_GRAPHICS)
303         return vzCheckUnsupportedGraphics(dev->data.graphics);
304 
305     return 0;
306 }
307 
308 static virDomainXMLPrivateDataCallbacks vzDomainXMLPrivateDataCallbacksPtr = {
309     .alloc = vzDomObjAlloc,
310     .free = vzDomObjFree,
311 };
312 
313 static virDomainDefParserConfig vzDomainDefParserConfig = {
314     .macPrefix = {0x42, 0x1C, 0x00},
315     .domainPostParseCallback = vzDomainDefPostParse,
316     .devicesPostParseCallback = vzDomainDeviceDefPostParse,
317     .domainValidateCallback = vzDomainDefValidate,
318     .deviceValidateCallback = vzDomainDeviceDefValidate,
319 };
320 
321 static struct _vzDriver *
vzDriverObjNew(void)322 vzDriverObjNew(void)
323 {
324     struct _vzDriver *driver;
325 
326     if (vzDriverInitialize() < 0)
327         return NULL;
328 
329     if (!(driver = virObjectLockableNew(vzDriverClass)))
330         return NULL;
331 
332     vzDomainDefParserConfig.priv = driver;
333 
334     if (!(driver->caps = vzBuildCapabilities()) ||
335         !(driver->xmlopt = virDomainXMLOptionNew(&vzDomainDefParserConfig,
336                                                  &vzDomainXMLPrivateDataCallbacksPtr,
337                                                  NULL, NULL, NULL)) ||
338         !(driver->domains = virDomainObjListNew()) ||
339         !(driver->domainEventState = virObjectEventStateNew()) ||
340         (vzInitVersion(driver) < 0) ||
341         (prlsdkConnect(driver) < 0)) {
342         virObjectUnref(driver);
343         return NULL;
344     }
345 
346     driver->hostsysinfo = virSysinfoRead();
347     ignore_value(prlsdkLoadDomains(driver));
348 
349     /* As far as waitDomainJob finally calls virReportErrorHelper
350      * and we are not going to report it, reset it explicitly */
351     virResetLastError();
352 
353     return driver;
354 }
355 
356 static virDrvOpenStatus
vzConnectOpen(virConnectPtr conn,virConnectAuthPtr auth G_GNUC_UNUSED,virConf * conf G_GNUC_UNUSED,unsigned int flags)357 vzConnectOpen(virConnectPtr conn,
358               virConnectAuthPtr auth G_GNUC_UNUSED,
359               virConf *conf G_GNUC_UNUSED,
360               unsigned int flags)
361 {
362     struct _vzDriver *driver = NULL;
363     struct _vzConn *privconn = NULL;
364 
365     virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
366 
367     /* From this point on, the connection is for us. */
368     if (STRNEQ(conn->uri->path, "/system")) {
369         virReportError(VIR_ERR_INTERNAL_ERROR,
370                        _("Unexpected Virtuozzo URI path '%s', try vz:///system"),
371                        conn->uri->path);
372         return VIR_DRV_OPEN_ERROR;
373     }
374 
375     if (virConnectOpenEnsureACL(conn) < 0)
376         return VIR_DRV_OPEN_ERROR;
377 
378     if (!(driver = vzGetDriverConnection()))
379         return VIR_DRV_OPEN_ERROR;
380 
381     privconn = g_new0(vzConn, 1);
382 
383     conn->privateData = privconn;
384     privconn->driver = driver;
385 
386     if (!(privconn->closeCallback = virNewConnectCloseCallbackData()))
387         goto error;
388 
389     virMutexLock(&vz_driver_lock);
390     privconn->next = vz_conn_list;
391     vz_conn_list = privconn;
392     virMutexUnlock(&vz_driver_lock);
393 
394     return VIR_DRV_OPEN_SUCCESS;
395 
396  error:
397 
398     conn->privateData = NULL;
399     virObjectUnref(driver);
400     VIR_FREE(privconn);
401     return VIR_DRV_OPEN_ERROR;
402 }
403 
404 static int
vzConnectClose(virConnectPtr conn)405 vzConnectClose(virConnectPtr conn)
406 {
407     struct _vzConn *curr;
408     struct _vzConn **prev = &vz_conn_list;
409     struct _vzConn *privconn = conn->privateData;
410 
411     if (!privconn)
412         return 0;
413 
414     virMutexLock(&vz_driver_lock);
415     for (curr = vz_conn_list; curr; prev = &curr->next, curr = curr->next) {
416         if (curr == privconn) {
417             *prev = curr->next;
418             break;
419         }
420     }
421 
422     virMutexUnlock(&vz_driver_lock);
423 
424     virObjectUnref(privconn->closeCallback);
425     virObjectUnref(privconn->driver);
426     VIR_FREE(privconn);
427     conn->privateData = NULL;
428     return 0;
429 }
430 
431 static int
vzConnectGetVersion(virConnectPtr conn,unsigned long * hvVer)432 vzConnectGetVersion(virConnectPtr conn, unsigned long *hvVer)
433 {
434     struct _vzConn *privconn = conn->privateData;
435 
436     if (virConnectGetVersionEnsureACL(conn) < 0)
437         return -1;
438 
439     *hvVer = privconn->driver->vzVersion;
440     return 0;
441 }
442 
443 
vzConnectGetHostname(virConnectPtr conn)444 static char *vzConnectGetHostname(virConnectPtr conn)
445 {
446     if (virConnectGetHostnameEnsureACL(conn) < 0)
447         return NULL;
448 
449     return virGetHostname();
450 }
451 
452 static char *
vzConnectGetSysinfo(virConnectPtr conn,unsigned int flags)453 vzConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
454 {
455     struct _vzConn *privconn = conn->privateData;
456     struct _vzDriver *driver = privconn->driver;
457     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
458 
459     virCheckFlags(0, NULL);
460 
461     if (virConnectGetSysinfoEnsureACL(conn) < 0)
462         return NULL;
463 
464     if (!driver->hostsysinfo) {
465         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
466                        _("Host SMBIOS information is not available"));
467         return NULL;
468     }
469 
470     if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
471         return NULL;
472 
473     return virBufferContentAndReset(&buf);
474 }
475 
476 static int
vzConnectListDomains(virConnectPtr conn,int * ids,int maxids)477 vzConnectListDomains(virConnectPtr conn, int *ids, int maxids)
478 {
479     struct _vzConn *privconn = conn->privateData;
480 
481     if (virConnectListDomainsEnsureACL(conn) < 0)
482         return -1;
483 
484     return virDomainObjListGetActiveIDs(privconn->driver->domains, ids,
485                                         maxids, virConnectListDomainsCheckACL,
486                                         conn);
487 }
488 
489 static int
vzConnectNumOfDomains(virConnectPtr conn)490 vzConnectNumOfDomains(virConnectPtr conn)
491 {
492     struct _vzConn *privconn = conn->privateData;
493 
494     if (virConnectNumOfDomainsEnsureACL(conn) < 0)
495         return -1;
496 
497     return virDomainObjListNumOfDomains(privconn->driver->domains, true,
498                                         virConnectNumOfDomainsCheckACL, conn);
499 }
500 
501 static int
vzConnectListDefinedDomains(virConnectPtr conn,char ** const names,int maxnames)502 vzConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
503 {
504     struct _vzConn *privconn = conn->privateData;
505 
506     if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
507         return -1;
508 
509     memset(names, 0, sizeof(*names) * maxnames);
510     return virDomainObjListGetInactiveNames(privconn->driver->domains, names,
511                                             maxnames,
512                                             virConnectListDefinedDomainsCheckACL,
513                                             conn);
514 }
515 
516 static int
vzConnectNumOfDefinedDomains(virConnectPtr conn)517 vzConnectNumOfDefinedDomains(virConnectPtr conn)
518 {
519     struct _vzConn *privconn = conn->privateData;
520 
521     if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
522         return -1;
523 
524     return virDomainObjListNumOfDomains(privconn->driver->domains, false,
525                                         virConnectNumOfDefinedDomainsCheckACL,
526                                         conn);
527 }
528 
529 static int
vzConnectListAllDomains(virConnectPtr conn,virDomainPtr ** domains,unsigned int flags)530 vzConnectListAllDomains(virConnectPtr conn,
531                         virDomainPtr **domains,
532                         unsigned int flags)
533 {
534     struct _vzConn *privconn = conn->privateData;
535 
536     virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
537 
538     if (virConnectListAllDomainsEnsureACL(conn) < 0)
539         return -1;
540 
541     return virDomainObjListExport(privconn->driver->domains, conn, domains,
542                                   virConnectListAllDomainsCheckACL, flags);
543 }
544 
545 static virDomainPtr
vzDomainLookupByID(virConnectPtr conn,int id)546 vzDomainLookupByID(virConnectPtr conn, int id)
547 {
548     struct _vzConn *privconn = conn->privateData;
549     virDomainPtr ret = NULL;
550     virDomainObj *dom;
551 
552     dom = virDomainObjListFindByID(privconn->driver->domains, id);
553 
554     if (dom == NULL) {
555         virReportError(VIR_ERR_NO_DOMAIN, NULL);
556         return NULL;
557     }
558 
559     if (virDomainLookupByIDEnsureACL(conn, dom->def) < 0)
560         goto cleanup;
561 
562     ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
563 
564  cleanup:
565     virDomainObjEndAPI(&dom);
566     return ret;
567 }
568 
569 static virDomainPtr
vzDomainLookupByUUID(virConnectPtr conn,const unsigned char * uuid)570 vzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
571 {
572     struct _vzConn *privconn = conn->privateData;
573     virDomainPtr ret = NULL;
574     virDomainObj *dom;
575 
576     dom = virDomainObjListFindByUUID(privconn->driver->domains, uuid);
577 
578     if (dom == NULL) {
579         char uuidstr[VIR_UUID_STRING_BUFLEN];
580         virUUIDFormat(uuid, uuidstr);
581         virReportError(VIR_ERR_NO_DOMAIN,
582                        _("no domain with matching uuid '%s'"), uuidstr);
583         return NULL;
584     }
585 
586     if (virDomainLookupByUUIDEnsureACL(conn, dom->def) < 0)
587         goto cleanup;
588 
589     ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
590 
591  cleanup:
592     virDomainObjEndAPI(&dom);
593     return ret;
594 }
595 
596 static virDomainPtr
vzDomainLookupByName(virConnectPtr conn,const char * name)597 vzDomainLookupByName(virConnectPtr conn, const char *name)
598 {
599     struct _vzConn *privconn = conn->privateData;
600     virDomainPtr ret = NULL;
601     virDomainObj *dom;
602 
603     dom = virDomainObjListFindByName(privconn->driver->domains, name);
604 
605     if (dom == NULL) {
606         virReportError(VIR_ERR_NO_DOMAIN,
607                        _("no domain with matching name '%s'"), name);
608         return NULL;
609     }
610 
611     if (virDomainLookupByNameEnsureACL(conn, dom->def) < 0)
612         goto cleanup;
613 
614     ret = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id);
615 
616  cleanup:
617     virDomainObjEndAPI(&dom);
618     return ret;
619 }
620 
621 static int
vzDomainGetInfo(virDomainPtr domain,virDomainInfoPtr info)622 vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
623 {
624     virDomainObj *dom;
625     struct vzDomObj *privdom;
626     int ret = -1;
627 
628     if (!(dom = vzDomObjFromDomain(domain)))
629         goto cleanup;
630 
631     if (virDomainGetInfoEnsureACL(domain->conn, dom->def) < 0)
632         goto cleanup;
633 
634     info->state = virDomainObjGetState(dom, NULL);
635     info->memory = dom->def->mem.cur_balloon;
636     info->maxMem = virDomainDefGetMemoryTotal(dom->def);
637     info->nrVirtCpu = virDomainDefGetVcpus(dom->def);
638     info->cpuTime = 0;
639 
640     privdom = dom->privateData;
641 
642     if (PRL_INVALID_HANDLE != privdom->stats && virDomainObjIsActive(dom)) {
643         unsigned long long vtime;
644         size_t i;
645 
646         for (i = 0; i < virDomainDefGetVcpus(dom->def); ++i) {
647             if (prlsdkGetVcpuStats(privdom->stats, i, &vtime) < 0) {
648                 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
649                                _("cannot read cputime for domain"));
650                 goto cleanup;
651             }
652             info->cpuTime += vtime;
653         }
654     }
655     ret = 0;
656 
657  cleanup:
658     virDomainObjEndAPI(&dom);
659     return ret;
660 }
661 
662 static char *
vzDomainGetOSType(virDomainPtr domain)663 vzDomainGetOSType(virDomainPtr domain)
664 {
665     virDomainObj *dom;
666     char *ret = NULL;
667 
668     if (!(dom = vzDomObjFromDomain(domain)))
669         return NULL;
670 
671     if (virDomainGetOSTypeEnsureACL(domain->conn, dom->def) < 0)
672         goto cleanup;
673 
674     ret = g_strdup(virDomainOSTypeToString(dom->def->os.type));
675 
676  cleanup:
677     virDomainObjEndAPI(&dom);
678     return ret;
679 }
680 
681 static int
vzDomainIsPersistent(virDomainPtr domain)682 vzDomainIsPersistent(virDomainPtr domain)
683 {
684     virDomainObj *dom;
685     int ret = -1;
686 
687     if (!(dom = vzDomObjFromDomain(domain)))
688         return -1;
689 
690     if (virDomainIsPersistentEnsureACL(domain->conn, dom->def) < 0)
691         goto cleanup;
692 
693     ret = 1;
694 
695  cleanup:
696     virDomainObjEndAPI(&dom);
697     return ret;
698 }
699 
700 static int
vzDomainGetState(virDomainPtr domain,int * state,int * reason,unsigned int flags)701 vzDomainGetState(virDomainPtr domain,
702                  int *state, int *reason, unsigned int flags)
703 {
704     virDomainObj *dom;
705     int ret = -1;
706 
707     virCheckFlags(0, -1);
708 
709     if (!(dom = vzDomObjFromDomain(domain)))
710         return -1;
711 
712     if (virDomainGetStateEnsureACL(domain->conn, dom->def) < 0)
713         goto cleanup;
714 
715     *state = virDomainObjGetState(dom, reason);
716     ret = 0;
717 
718  cleanup:
719     virDomainObjEndAPI(&dom);
720     return ret;
721 }
722 
723 static char *
vzDomainGetXMLDesc(virDomainPtr domain,unsigned int flags)724 vzDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
725 {
726     struct _vzConn *privconn = domain->conn->privateData;
727     struct _vzDriver *driver = privconn->driver;
728     virDomainDef *def;
729     virDomainObj *dom;
730     char *ret = NULL;
731 
732     virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
733 
734     if (!(dom = vzDomObjFromDomain(domain)))
735         return NULL;
736 
737     if (virDomainGetXMLDescEnsureACL(domain->conn, dom->def, flags) < 0)
738         goto cleanup;
739 
740     def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
741         dom->newDef ? dom->newDef : dom->def;
742 
743     ret = virDomainDefFormat(def, driver->xmlopt, flags);
744 
745  cleanup:
746     virDomainObjEndAPI(&dom);
747     return ret;
748 }
749 
750 static int
vzDomainGetAutostart(virDomainPtr domain,int * autostart)751 vzDomainGetAutostart(virDomainPtr domain, int *autostart)
752 {
753     virDomainObj *dom;
754     int ret = -1;
755 
756     if (!(dom = vzDomObjFromDomain(domain)))
757         return -1;
758 
759     if (virDomainGetAutostartEnsureACL(domain->conn, dom->def) < 0)
760         goto cleanup;
761 
762     *autostart = dom->autostart;
763     ret = 0;
764 
765  cleanup:
766     virDomainObjEndAPI(&dom);
767     return ret;
768 }
769 
770 static int
vzEnsureDomainExists(virDomainObj * dom)771 vzEnsureDomainExists(virDomainObj *dom)
772 {
773     char uuidstr[VIR_UUID_STRING_BUFLEN];
774 
775     if (!dom->removing)
776         return 0;
777 
778     virUUIDFormat(dom->def->uuid, uuidstr);
779     virReportError(VIR_ERR_NO_DOMAIN,
780                    _("no domain with matching uuid '%s' (%s)"),
781                    uuidstr, dom->def->name);
782 
783     return -1;
784 }
785 
786 static virDomainPtr
vzDomainDefineXMLFlags(virConnectPtr conn,const char * xml,unsigned int flags)787 vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
788 {
789     struct _vzConn *privconn = conn->privateData;
790     virDomainPtr retdom = NULL;
791     virDomainDef *def;
792     virDomainObj *dom = NULL;
793     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
794     struct _vzDriver *driver = privconn->driver;
795     bool job = false;
796 
797     virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
798 
799     if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
800         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
801 
802     if ((def = virDomainDefParseString(xml, driver->xmlopt,
803                                        NULL, parse_flags)) == NULL)
804         goto cleanup;
805 
806     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
807         goto cleanup;
808 
809     if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
810         goto cleanup;
811 
812     dom = virDomainObjListFindByUUID(driver->domains, def->uuid);
813     if (dom == NULL) {
814         virResetLastError();
815         if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
816             if (prlsdkCreateVm(driver, def))
817                 goto cleanup;
818         } else if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
819             if (prlsdkCreateCt(conn, def))
820                 goto cleanup;
821         } else {
822             virReportError(VIR_ERR_INVALID_ARG,
823                            _("Unsupported OS type: %s"),
824                            virDomainOSTypeToString(def->os.type));
825             goto cleanup;
826         }
827 
828         if (!(dom = prlsdkAddDomainByUUID(driver, def->uuid)))
829             goto cleanup;
830     } else {
831         int state, reason;
832 
833         state = virDomainObjGetState(dom, &reason);
834 
835         if (state == VIR_DOMAIN_SHUTOFF &&
836             reason == VIR_DOMAIN_SHUTOFF_SAVED) {
837 
838             /* PCS doesn't store domain config in managed save state file.
839              * It's forbidden to change config for VMs in this state.
840              * It's possible to change config for containers, but after
841              * restoring domain will have that new config, not a config,
842              * which domain had at the moment of virDomainManagedSave.
843              *
844              * So forbid this operation, if config is changed. If it's
845              * not changed - just do nothing. */
846 
847             if (!virDomainDefCheckABIStability(dom->def, def, driver->xmlopt)) {
848                 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
849                                _("Can't change domain configuration "
850                                  "in managed save state"));
851                 goto cleanup;
852             }
853         } else {
854             if (vzDomainObjBeginJob(dom) < 0)
855                 goto cleanup;
856             job = true;
857 
858             if (vzEnsureDomainExists(dom) < 0)
859                 goto cleanup;
860 
861             if (prlsdkApplyConfig(driver, dom, def))
862                 goto cleanup;
863 
864             if (prlsdkUpdateDomain(driver, dom))
865                 goto cleanup;
866         }
867     }
868 
869     retdom = virGetDomain(conn, def->name, def->uuid, def->id);
870 
871  cleanup:
872     if (job)
873         vzDomainObjEndJob(dom);
874     virDomainObjEndAPI(&dom);
875     virDomainDefFree(def);
876     return retdom;
877 }
878 
879 static virDomainPtr
vzDomainDefineXML(virConnectPtr conn,const char * xml)880 vzDomainDefineXML(virConnectPtr conn, const char *xml)
881 {
882     return vzDomainDefineXMLFlags(conn, xml, 0);
883 }
884 
885 
886 static int
vzNodeGetInfo(virConnectPtr conn,virNodeInfoPtr nodeinfo)887 vzNodeGetInfo(virConnectPtr conn,
888               virNodeInfoPtr nodeinfo)
889 {
890     if (virNodeGetInfoEnsureACL(conn) < 0)
891         return -1;
892 
893     return virCapabilitiesGetNodeInfo(nodeinfo);
894 }
895 
vzConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)896 static int vzConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
897 {
898     /* Encryption is not relevant / applicable to way we talk to PCS */
899     return 0;
900 }
901 
vzConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)902 static int vzConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
903 {
904     /* We run CLI tools directly so this is secure */
905     return 1;
906 }
907 
vzConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)908 static int vzConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
909 {
910     return 1;
911 }
912 
913 
914 static char *
vzConnectBaselineCPU(virConnectPtr conn,const char ** xmlCPUs,unsigned int ncpus,unsigned int flags)915 vzConnectBaselineCPU(virConnectPtr conn,
916                      const char **xmlCPUs,
917                      unsigned int ncpus,
918                      unsigned int flags)
919 {
920     virCPUDef **cpus = NULL;
921     virCPUDef *cpu = NULL;
922     char *cpustr = NULL;
923 
924     virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
925 
926     if (virConnectBaselineCPUEnsureACL(conn) < 0)
927         return NULL;
928 
929     if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
930         goto cleanup;
931 
932     if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL, false)))
933         goto cleanup;
934 
935     if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
936         virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
937         goto cleanup;
938 
939     cpustr = virCPUDefFormat(cpu, NULL);
940 
941  cleanup:
942     virCPUDefListFree(cpus);
943     virCPUDefFree(cpu);
944 
945     return cpustr;
946 }
947 
948 
949 static int
vzDomainGetVcpus(virDomainPtr domain,virVcpuInfoPtr info,int maxinfo,unsigned char * cpumaps,int maplen)950 vzDomainGetVcpus(virDomainPtr domain,
951                  virVcpuInfoPtr info,
952                  int maxinfo,
953                  unsigned char *cpumaps,
954                  int maplen)
955 {
956     virDomainObj *dom = NULL;
957     size_t i;
958     int ret = -1;
959 
960     if (!(dom = vzDomObjFromDomain(domain)))
961         return -1;
962 
963     if (virDomainGetVcpusEnsureACL(domain->conn, dom->def) < 0)
964         goto cleanup;
965 
966     if (!virDomainObjIsActive(dom)) {
967         virReportError(VIR_ERR_OPERATION_INVALID,
968                        "%s",
969                        _("cannot list vcpu pinning for an inactive domain"));
970         goto cleanup;
971     }
972 
973     if (maxinfo >= 1) {
974         if (info != NULL) {
975         struct vzDomObj *privdom;
976 
977             memset(info, 0, sizeof(*info) * maxinfo);
978             privdom = dom->privateData;
979 
980             for (i = 0; i < maxinfo; i++) {
981                 info[i].number = i;
982                 info[i].state = VIR_VCPU_RUNNING;
983                 if (prlsdkGetVcpuStats(privdom->stats, i, &info[i].cpuTime) < 0)
984                     goto cleanup;
985             }
986         }
987         if (cpumaps != NULL) {
988             memset(cpumaps, 0, maplen * maxinfo);
989             for (i = 0; i < maxinfo; i++)
990                 virBitmapToDataBuf(dom->def->cpumask,
991                                    VIR_GET_CPUMAP(cpumaps, maplen, i),
992                                    maplen);
993         }
994     }
995     ret = maxinfo;
996 
997  cleanup:
998     virDomainObjEndAPI(&dom);
999     return ret;
1000 }
1001 
1002 
1003 static int
vzNodeGetCPUMap(virConnectPtr conn,unsigned char ** cpumap,unsigned int * online,unsigned int flags)1004 vzNodeGetCPUMap(virConnectPtr conn,
1005                 unsigned char **cpumap,
1006                 unsigned int *online,
1007                 unsigned int flags)
1008 {
1009     if (virNodeGetCPUMapEnsureACL(conn) < 0)
1010         return -1;
1011 
1012     return virHostCPUGetMap(cpumap, online, flags);
1013 }
1014 
1015 static int
vzConnectDomainEventRegisterAny(virConnectPtr conn,virDomainPtr domain,int eventID,virConnectDomainEventGenericCallback callback,void * opaque,virFreeCallback freecb)1016 vzConnectDomainEventRegisterAny(virConnectPtr conn,
1017                                 virDomainPtr domain,
1018                                 int eventID,
1019                                 virConnectDomainEventGenericCallback callback,
1020                                 void *opaque,
1021                                 virFreeCallback freecb)
1022 {
1023     int ret = -1;
1024     struct _vzConn *privconn = conn->privateData;
1025 
1026     if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
1027         return -1;
1028 
1029     if (virDomainEventStateRegisterID(conn,
1030                                       privconn->driver->domainEventState,
1031                                       domain, eventID,
1032                                       callback, opaque, freecb, &ret) < 0)
1033         ret = -1;
1034     return ret;
1035 }
1036 
1037 static int
vzConnectDomainEventDeregisterAny(virConnectPtr conn,int callbackID)1038 vzConnectDomainEventDeregisterAny(virConnectPtr conn,
1039                                   int callbackID)
1040 {
1041     struct _vzConn *privconn = conn->privateData;
1042 
1043     if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
1044         return -1;
1045 
1046     if (virObjectEventStateDeregisterID(conn,
1047                                         privconn->driver->domainEventState,
1048                                         callbackID, true) < 0)
1049         return -1;
1050 
1051     return 0;
1052 }
1053 
1054 static int
vzDomainSuspend(virDomainPtr domain)1055 vzDomainSuspend(virDomainPtr domain)
1056 {
1057     struct _vzConn *privconn = domain->conn->privateData;
1058     virDomainObj *dom;
1059     int ret = -1;
1060     bool job = false;
1061 
1062     if (!(dom = vzDomObjFromDomain(domain)))
1063         return -1;
1064 
1065     if (virDomainSuspendEnsureACL(domain->conn, dom->def) < 0)
1066         goto cleanup;
1067 
1068     if (vzDomainObjBeginJob(dom) < 0)
1069         goto cleanup;
1070     job = true;
1071 
1072     if (vzEnsureDomainExists(dom) < 0)
1073         goto cleanup;
1074 
1075     if (prlsdkPause(dom) < 0)
1076         goto cleanup;
1077 
1078     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1079         goto cleanup;
1080 
1081     ret = 0;
1082 
1083  cleanup:
1084     if (job)
1085         vzDomainObjEndJob(dom);
1086     virDomainObjEndAPI(&dom);
1087 
1088     return ret;
1089 }
1090 
1091 static int
vzDomainResume(virDomainPtr domain)1092 vzDomainResume(virDomainPtr domain)
1093 {
1094     struct _vzConn *privconn = domain->conn->privateData;
1095     virDomainObj *dom;
1096     int ret = -1;
1097     bool job = false;
1098 
1099     if (!(dom = vzDomObjFromDomain(domain)))
1100         return -1;
1101 
1102     if (virDomainResumeEnsureACL(domain->conn, dom->def) < 0)
1103         goto cleanup;
1104 
1105     if (vzDomainObjBeginJob(dom) < 0)
1106         goto cleanup;
1107     job = true;
1108 
1109     if (vzEnsureDomainExists(dom) < 0)
1110         goto cleanup;
1111 
1112     if (prlsdkResume(dom) < 0)
1113         goto cleanup;
1114 
1115     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1116         goto cleanup;
1117 
1118     ret = 0;
1119 
1120  cleanup:
1121     if (job)
1122         vzDomainObjEndJob(dom);
1123     virDomainObjEndAPI(&dom);
1124 
1125     return ret;
1126 }
1127 
1128 static int
vzDomainCreateWithFlags(virDomainPtr domain,unsigned int flags)1129 vzDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
1130 {
1131     struct _vzConn *privconn = domain->conn->privateData;
1132     virDomainObj *dom;
1133     int ret = -1;
1134     bool job = false;
1135 
1136     virCheckFlags(0, -1);
1137 
1138     if (!(dom = vzDomObjFromDomain(domain)))
1139         return -1;
1140 
1141     if (virDomainCreateWithFlagsEnsureACL(domain->conn, dom->def) < 0)
1142         goto cleanup;
1143 
1144     if (vzDomainObjBeginJob(dom) < 0)
1145         goto cleanup;
1146     job = true;
1147 
1148     if (vzEnsureDomainExists(dom) < 0)
1149         goto cleanup;
1150 
1151     if (prlsdkStart(dom) < 0)
1152         goto cleanup;
1153 
1154     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1155         goto cleanup;
1156 
1157     ret = 0;
1158 
1159  cleanup:
1160     if (job)
1161         vzDomainObjEndJob(dom);
1162     virDomainObjEndAPI(&dom);
1163 
1164     return ret;
1165 }
1166 
1167 static int
vzDomainDestroyFlags(virDomainPtr domain,unsigned int flags)1168 vzDomainDestroyFlags(virDomainPtr domain, unsigned int flags)
1169 {
1170     struct _vzConn *privconn = domain->conn->privateData;
1171     virDomainObj *dom;
1172     int ret = -1;
1173     bool job = false;
1174 
1175     virCheckFlags(0, -1);
1176 
1177     if (!(dom = vzDomObjFromDomain(domain)))
1178         return -1;
1179 
1180     if (virDomainDestroyFlagsEnsureACL(domain->conn, dom->def) < 0)
1181         goto cleanup;
1182 
1183     if (vzDomainObjBeginJob(dom) < 0)
1184         goto cleanup;
1185     job = true;
1186 
1187     if (vzEnsureDomainExists(dom) < 0)
1188         goto cleanup;
1189 
1190     if (prlsdkKill(dom) < 0)
1191         goto cleanup;
1192 
1193     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1194         goto cleanup;
1195 
1196     ret = 0;
1197 
1198  cleanup:
1199     if (job)
1200         vzDomainObjEndJob(dom);
1201     virDomainObjEndAPI(&dom);
1202 
1203     return ret;
1204 }
1205 
1206 static int
vzDomainDestroy(virDomainPtr dom)1207 vzDomainDestroy(virDomainPtr dom)
1208 {
1209     return vzDomainDestroyFlags(dom, 0);
1210 }
1211 
1212 static int
vzDomainShutdownFlags(virDomainPtr domain,unsigned int flags)1213 vzDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
1214 {
1215     struct _vzConn *privconn = domain->conn->privateData;
1216     virDomainObj *dom;
1217     int ret = -1;
1218     bool job = false;
1219 
1220     virCheckFlags(0, -1);
1221 
1222     if (!(dom = vzDomObjFromDomain(domain)))
1223         return -1;
1224 
1225     if (virDomainShutdownFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
1226         goto cleanup;
1227 
1228     if (vzDomainObjBeginJob(dom) < 0)
1229         goto cleanup;
1230     job = true;
1231 
1232     if (vzEnsureDomainExists(dom) < 0)
1233         goto cleanup;
1234 
1235     if (prlsdkStop(dom) < 0)
1236         goto cleanup;
1237 
1238     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1239         goto cleanup;
1240 
1241     ret = 0;
1242 
1243  cleanup:
1244     if (job)
1245         vzDomainObjEndJob(dom);
1246     virDomainObjEndAPI(&dom);
1247 
1248     return ret;
1249 }
1250 
vzDomainShutdown(virDomainPtr dom)1251 static int vzDomainShutdown(virDomainPtr dom)
1252 {
1253     return vzDomainShutdownFlags(dom, 0);
1254 }
1255 
1256 static int
vzDomainReboot(virDomainPtr domain,unsigned int flags)1257 vzDomainReboot(virDomainPtr domain, unsigned int flags)
1258 {
1259     struct _vzConn *privconn = domain->conn->privateData;
1260     virDomainObj *dom;
1261     int ret = -1;
1262     bool job = false;
1263 
1264     virCheckFlags(0, -1);
1265 
1266     if (!(dom = vzDomObjFromDomain(domain)))
1267         return -1;
1268 
1269     if (virDomainRebootEnsureACL(domain->conn, dom->def, flags) < 0)
1270         goto cleanup;
1271 
1272     if (vzDomainObjBeginJob(dom) < 0)
1273         goto cleanup;
1274     job = true;
1275 
1276     if (vzEnsureDomainExists(dom) < 0)
1277         goto cleanup;
1278 
1279     if (prlsdkRestart(dom) < 0)
1280         goto cleanup;
1281 
1282     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1283         goto cleanup;
1284 
1285     ret = 0;
1286 
1287  cleanup:
1288     if (job)
1289         vzDomainObjEndJob(dom);
1290     virDomainObjEndAPI(&dom);
1291 
1292     return ret;
1293 }
1294 
vzDomainIsActive(virDomainPtr domain)1295 static int vzDomainIsActive(virDomainPtr domain)
1296 {
1297     virDomainObj *dom = NULL;
1298     int ret = -1;
1299 
1300     if (!(dom = vzDomObjFromDomain(domain)))
1301         return -1;
1302 
1303     if (virDomainIsActiveEnsureACL(domain->conn, dom->def) < 0)
1304         goto cleanup;
1305 
1306     ret = virDomainObjIsActive(dom);
1307 
1308  cleanup:
1309     virDomainObjEndAPI(&dom);
1310 
1311     return ret;
1312 }
1313 
1314 static int
vzDomainCreate(virDomainPtr domain)1315 vzDomainCreate(virDomainPtr domain)
1316 {
1317     return vzDomainCreateWithFlags(domain, 0);
1318 }
1319 
1320 static int
vzDomainUndefineFlags(virDomainPtr domain,unsigned int flags)1321 vzDomainUndefineFlags(virDomainPtr domain,
1322                       unsigned int flags)
1323 {
1324     struct _vzConn *privconn = domain->conn->privateData;
1325     virDomainObj *dom = NULL;
1326     int ret = -1;
1327     bool job = false;
1328 
1329     virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
1330                   VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
1331 
1332     if (!(dom = vzDomObjFromDomain(domain)))
1333         return -1;
1334 
1335     if (virDomainUndefineFlagsEnsureACL(domain->conn, dom->def) < 0)
1336         goto cleanup;
1337 
1338     if (vzDomainObjBeginJob(dom) < 0)
1339         goto cleanup;
1340     job = true;
1341 
1342     if (vzEnsureDomainExists(dom) < 0)
1343         goto cleanup;
1344 
1345     ret = prlsdkUnregisterDomain(privconn->driver, dom, flags);
1346 
1347  cleanup:
1348 
1349     if (job)
1350         vzDomainObjEndJob(dom);
1351     virDomainObjEndAPI(&dom);
1352 
1353     return ret;
1354 }
1355 
1356 static int
vzDomainUndefine(virDomainPtr domain)1357 vzDomainUndefine(virDomainPtr domain)
1358 {
1359     return vzDomainUndefineFlags(domain, 0);
1360 }
1361 
1362 static int
vzDomainHasManagedSaveImage(virDomainPtr domain,unsigned int flags)1363 vzDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
1364 {
1365     virDomainObj *dom = NULL;
1366     int state, reason;
1367     int ret = -1;
1368 
1369     virCheckFlags(0, -1);
1370 
1371     if (!(dom = vzDomObjFromDomain(domain)))
1372         return -1;
1373 
1374     if (virDomainHasManagedSaveImageEnsureACL(domain->conn, dom->def) < 0)
1375         goto cleanup;
1376 
1377     state = virDomainObjGetState(dom, &reason);
1378     if (state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED)
1379         ret = 1;
1380     else
1381         ret = 0;
1382 
1383  cleanup:
1384     virDomainObjEndAPI(&dom);
1385 
1386     return ret;
1387 }
1388 
1389 static int
vzDomainManagedSave(virDomainPtr domain,unsigned int flags)1390 vzDomainManagedSave(virDomainPtr domain, unsigned int flags)
1391 {
1392     struct _vzConn *privconn = domain->conn->privateData;
1393     virDomainObj *dom = NULL;
1394     int state, reason;
1395     int ret = -1;
1396     bool job = false;
1397 
1398     virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
1399                   VIR_DOMAIN_SAVE_PAUSED, -1);
1400 
1401     if (!(dom = vzDomObjFromDomain(domain)))
1402         return -1;
1403 
1404     if (virDomainManagedSaveEnsureACL(domain->conn, dom->def) < 0)
1405         goto cleanup;
1406 
1407     if (vzDomainObjBeginJob(dom) < 0)
1408         goto cleanup;
1409     job = true;
1410 
1411     if (vzEnsureDomainExists(dom) < 0)
1412         goto cleanup;
1413 
1414     state = virDomainObjGetState(dom, &reason);
1415 
1416     if (state == VIR_DOMAIN_RUNNING && (flags & VIR_DOMAIN_SAVE_PAUSED) &&
1417         prlsdkPause(dom) < 0)
1418         goto cleanup;
1419 
1420     if (prlsdkSuspend(dom) < 0)
1421         goto cleanup;
1422 
1423     if (prlsdkUpdateDomain(privconn->driver, dom) < 0)
1424         goto cleanup;
1425 
1426     ret = 0;
1427 
1428  cleanup:
1429     if (job)
1430         vzDomainObjEndJob(dom);
1431     virDomainObjEndAPI(&dom);
1432     return ret;
1433 }
1434 
1435 static int
vzDomainManagedSaveRemove(virDomainPtr domain,unsigned int flags)1436 vzDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
1437 {
1438     virDomainObj *dom = NULL;
1439     int state, reason;
1440     int ret = -1;
1441 
1442     virCheckFlags(0, -1);
1443 
1444     if (!(dom = vzDomObjFromDomain(domain)))
1445         return -1;
1446 
1447     if (virDomainManagedSaveRemoveEnsureACL(domain->conn, dom->def) < 0)
1448         goto cleanup;
1449 
1450     state = virDomainObjGetState(dom, &reason);
1451 
1452     if (!(state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED))
1453         goto cleanup;
1454 
1455     ret = prlsdkDomainManagedSaveRemove(dom);
1456 
1457  cleanup:
1458     virDomainObjEndAPI(&dom);
1459     return ret;
1460 }
1461 
vzCheckConfigUpdateFlags(virDomainObj * dom,unsigned int * flags)1462 static int vzCheckConfigUpdateFlags(virDomainObj *dom, unsigned int *flags)
1463 {
1464     if (virDomainObjUpdateModificationImpact(dom, flags) < 0)
1465         return -1;
1466 
1467     if (!(*flags & VIR_DOMAIN_AFFECT_CONFIG)) {
1468         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1469                        _("domain config update needs VIR_DOMAIN_AFFECT_CONFIG "
1470                          "flag to be set"));
1471         return -1;
1472     }
1473 
1474     if (virDomainObjIsActive(dom) && !(*flags & VIR_DOMAIN_AFFECT_LIVE)) {
1475         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1476                        _("Updates on a running domain need "
1477                          "VIR_DOMAIN_AFFECT_LIVE flag"));
1478         return -1;
1479     }
1480 
1481     return 0;
1482 }
1483 
vzDomainAttachDeviceFlags(virDomainPtr domain,const char * xml,unsigned int flags)1484 static int vzDomainAttachDeviceFlags(virDomainPtr domain, const char *xml,
1485                                      unsigned int flags)
1486 {
1487     int ret = -1;
1488     struct _vzConn *privconn = domain->conn->privateData;
1489     virDomainDeviceDef *dev = NULL;
1490     virDomainObj *dom = NULL;
1491     struct _vzDriver *driver = privconn->driver;
1492     bool job = false;
1493 
1494     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1495                   VIR_DOMAIN_AFFECT_CONFIG, -1);
1496 
1497     if (!(dom = vzDomObjFromDomain(domain)))
1498         return -1;
1499 
1500     if (vzCheckConfigUpdateFlags(dom, &flags) < 0)
1501         goto cleanup;
1502 
1503     if (virDomainAttachDeviceFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
1504         goto cleanup;
1505 
1506     dev = virDomainDeviceDefParse(xml, dom->def,
1507                                   driver->xmlopt, NULL, VIR_DOMAIN_XML_INACTIVE);
1508     if (dev == NULL)
1509         goto cleanup;
1510 
1511     if (vzDomainObjBeginJob(dom) < 0)
1512         goto cleanup;
1513     job = true;
1514 
1515     if (vzEnsureDomainExists(dom) < 0)
1516         goto cleanup;
1517 
1518     if (prlsdkAttachDevice(driver, dom, dev) < 0)
1519         goto cleanup;
1520 
1521     if (prlsdkUpdateDomain(driver, dom) < 0)
1522         goto cleanup;
1523 
1524     ret = 0;
1525  cleanup:
1526     virDomainDeviceDefFree(dev);
1527     if (job)
1528         vzDomainObjEndJob(dom);
1529     virDomainObjEndAPI(&dom);
1530     return ret;
1531 }
1532 
vzDomainAttachDevice(virDomainPtr domain,const char * xml)1533 static int vzDomainAttachDevice(virDomainPtr domain, const char *xml)
1534 {
1535     return vzDomainAttachDeviceFlags(domain, xml,
1536                                      VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
1537 }
1538 
vzDomainDetachDeviceFlags(virDomainPtr domain,const char * xml,unsigned int flags)1539 static int vzDomainDetachDeviceFlags(virDomainPtr domain, const char *xml,
1540                                      unsigned int flags)
1541 {
1542     int ret = -1;
1543     struct _vzConn *privconn = domain->conn->privateData;
1544     virDomainDeviceDef *dev = NULL;
1545     virDomainObj *dom = NULL;
1546     struct _vzDriver *driver = privconn->driver;
1547     bool job = false;
1548 
1549     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1550                   VIR_DOMAIN_AFFECT_CONFIG, -1);
1551 
1552     dom = vzDomObjFromDomain(domain);
1553     if (dom == NULL)
1554         return -1;
1555 
1556     if (vzCheckConfigUpdateFlags(dom, &flags) < 0)
1557         goto cleanup;
1558 
1559     if (virDomainDetachDeviceFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
1560         goto cleanup;
1561 
1562     dev = virDomainDeviceDefParse(xml, dom->def,
1563                                   driver->xmlopt, NULL,
1564                                   VIR_DOMAIN_XML_INACTIVE |
1565                                   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
1566     if (dev == NULL)
1567         goto cleanup;
1568 
1569     if (vzDomainObjBeginJob(dom) < 0)
1570         goto cleanup;
1571     job = true;
1572 
1573     if (vzEnsureDomainExists(dom) < 0)
1574         goto cleanup;
1575 
1576     if (prlsdkDetachDevice(driver, dom, dev) < 0)
1577         goto cleanup;
1578 
1579     if (prlsdkUpdateDomain(driver, dom) < 0)
1580         goto cleanup;
1581 
1582     ret = 0;
1583  cleanup:
1584     virDomainDeviceDefFree(dev);
1585     if (job)
1586         vzDomainObjEndJob(dom);
1587     virDomainObjEndAPI(&dom);
1588 
1589     return ret;
1590 }
1591 
vzDomainDetachDevice(virDomainPtr domain,const char * xml)1592 static int vzDomainDetachDevice(virDomainPtr domain, const char *xml)
1593 {
1594     return vzDomainDetachDeviceFlags(domain, xml,
1595                                      VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
1596 }
1597 
1598 static int
vzDomainSetUserPassword(virDomainPtr domain,const char * user,const char * password,unsigned int flags)1599 vzDomainSetUserPassword(virDomainPtr domain,
1600                         const char *user,
1601                         const char *password,
1602                         unsigned int flags)
1603 {
1604     virDomainObj *dom = NULL;
1605     int ret = -1;
1606     bool job = false;
1607 
1608     virCheckFlags(0, -1);
1609     if (!(dom = vzDomObjFromDomain(domain)))
1610         return -1;
1611 
1612     if (virDomainSetUserPasswordEnsureACL(domain->conn, dom->def) < 0)
1613         goto cleanup;
1614 
1615     if (vzDomainObjBeginJob(dom) < 0)
1616         goto cleanup;
1617     job = true;
1618 
1619     if (vzEnsureDomainExists(dom) < 0)
1620         goto cleanup;
1621 
1622     ret = prlsdkDomainSetUserPassword(dom, user, password);
1623 
1624  cleanup:
1625     if (job)
1626         vzDomainObjEndJob(dom);
1627     virDomainObjEndAPI(&dom);
1628     return ret;
1629 }
1630 
vzDomainUpdateDeviceFlags(virDomainPtr domain,const char * xml,unsigned int flags)1631 static int vzDomainUpdateDeviceFlags(virDomainPtr domain,
1632                                      const char *xml,
1633                                      unsigned int flags)
1634 {
1635     int ret = -1;
1636     struct _vzConn *privconn = domain->conn->privateData;
1637     virDomainObj *dom = NULL;
1638     virDomainDeviceDef *dev = NULL;
1639     struct _vzDriver *driver = privconn->driver;
1640     bool job = false;
1641 
1642     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1643                   VIR_DOMAIN_AFFECT_CONFIG, -1);
1644 
1645     if (!(dom = vzDomObjFromDomain(domain)))
1646         return -1;
1647 
1648     if (virDomainUpdateDeviceFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
1649         goto cleanup;
1650 
1651     if (vzCheckConfigUpdateFlags(dom, &flags) < 0)
1652         goto cleanup;
1653 
1654     if (!(dev = virDomainDeviceDefParse(xml, dom->def,
1655                                         driver->xmlopt, NULL,
1656                                         VIR_DOMAIN_XML_INACTIVE)))
1657         goto cleanup;
1658 
1659     if (vzDomainObjBeginJob(dom) < 0)
1660         goto cleanup;
1661     job = true;
1662 
1663     if (vzEnsureDomainExists(dom) < 0)
1664         goto cleanup;
1665 
1666     if (prlsdkUpdateDevice(driver, dom, dev) < 0)
1667         goto cleanup;
1668 
1669     if (prlsdkUpdateDomain(driver, dom) < 0)
1670         goto cleanup;
1671 
1672     ret = 0;
1673  cleanup:
1674 
1675     virDomainDeviceDefFree(dev);
1676     if (job)
1677         vzDomainObjEndJob(dom);
1678     virDomainObjEndAPI(&dom);
1679     return ret;
1680 }
1681 
1682 
1683 static unsigned long long
vzDomainGetMaxMemory(virDomainPtr domain)1684 vzDomainGetMaxMemory(virDomainPtr domain)
1685 {
1686     virDomainObj *dom = NULL;
1687     int ret = -1;
1688 
1689     if (!(dom = vzDomObjFromDomain(domain)))
1690         return -1;
1691 
1692     if (virDomainGetMaxMemoryEnsureACL(domain->conn, dom->def) < 0)
1693         goto cleanup;
1694 
1695     ret = virDomainDefGetMemoryTotal(dom->def);
1696 
1697  cleanup:
1698     virDomainObjEndAPI(&dom);
1699     return ret;
1700 }
1701 
1702 static int
vzDomainBlockStatsImpl(virDomainObj * dom,const char * path,virDomainBlockStatsPtr stats)1703 vzDomainBlockStatsImpl(virDomainObj *dom,
1704                        const char *path,
1705                        virDomainBlockStatsPtr stats)
1706 {
1707     struct vzDomObj *privdom = dom->privateData;
1708     size_t i;
1709     int idx;
1710 
1711     if (*path) {
1712         if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
1713             virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
1714             return -1;
1715         }
1716         if (prlsdkGetBlockStats(privdom->stats,
1717                                 dom->def->disks[idx],
1718                                 stats,
1719                                 IS_CT(dom->def)) < 0)
1720             return -1;
1721     } else {
1722         virDomainBlockStatsStruct s;
1723 
1724 #define PARALLELS_ZERO_STATS(VAR, TYPE, NAME) \
1725         stats->VAR = 0;
1726 
1727         PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)
1728 
1729 #undef PARALLELS_ZERO_STATS
1730 
1731         for (i = 0; i < dom->def->ndisks; i++) {
1732             if (prlsdkGetBlockStats(privdom->stats,
1733                                     dom->def->disks[i],
1734                                     &s,
1735                                     IS_CT(dom->def)) < 0)
1736                 return -1;
1737 
1738 #define PARALLELS_SUM_STATS(VAR, TYPE, NAME) \
1739     if (s.VAR != -1) \
1740         stats->VAR += s.VAR;
1741 
1742         PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
1743 
1744 #undef PARALLELS_SUM_STATS
1745         }
1746     }
1747     stats->errs = -1;
1748     return 0;
1749 }
1750 
1751 static int
vzDomainBlockStats(virDomainPtr domain,const char * path,virDomainBlockStatsPtr stats)1752 vzDomainBlockStats(virDomainPtr domain,
1753                    const char *path,
1754                    virDomainBlockStatsPtr stats)
1755 {
1756     virDomainObj *dom;
1757     int ret = -1;
1758 
1759     if (!(dom = vzDomObjFromDomain(domain)))
1760         return -1;
1761 
1762     if (virDomainBlockStatsEnsureACL(domain->conn, dom->def) < 0)
1763         goto cleanup;
1764 
1765     if (vzDomainBlockStatsImpl(dom, path, stats) < 0)
1766         goto cleanup;
1767 
1768     ret = 0;
1769 
1770  cleanup:
1771     virDomainObjEndAPI(&dom);
1772 
1773     return ret;
1774 }
1775 
1776 static int
vzDomainBlockStatsToParams(virDomainBlockStatsPtr stats,virTypedParameterPtr params,int * nparams)1777 vzDomainBlockStatsToParams(virDomainBlockStatsPtr stats,
1778                            virTypedParameterPtr params,
1779                            int *nparams)
1780 {
1781     size_t i;
1782 
1783     if (*nparams == 0) {
1784 #define PARALLELS_COUNT_STATS(VAR, TYPE, NAME) \
1785         if ((stats->VAR) != -1) \
1786             ++*nparams;
1787 
1788         PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)
1789 
1790 #undef PARALLELS_COUNT_STATS
1791         return 0;
1792     }
1793 
1794     i = 0;
1795 #define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME) \
1796     if (i < *nparams && (stats->VAR) != -1) { \
1797         if (virTypedParameterAssign(params + i, TYPE, \
1798                                     VIR_TYPED_PARAM_LLONG, (stats->VAR)) < 0) \
1799             return -1; \
1800         i++; \
1801     }
1802 
1803     PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)
1804 
1805 #undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM
1806 
1807     *nparams = i;
1808     return 0;
1809 }
1810 
1811 static int
vzDomainBlockStatsFlags(virDomainPtr domain,const char * path,virTypedParameterPtr params,int * nparams,unsigned int flags)1812 vzDomainBlockStatsFlags(virDomainPtr domain,
1813                         const char *path,
1814                         virTypedParameterPtr params,
1815                         int *nparams,
1816                         unsigned int flags)
1817 {
1818     virDomainBlockStatsStruct stats;
1819     virDomainObj *dom;
1820     int ret = -1;
1821 
1822     virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
1823     /* We don't return strings, and thus trivially support this flag.  */
1824     flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
1825 
1826     if (!(dom = vzDomObjFromDomain(domain)))
1827         return -1;
1828 
1829     if (virDomainBlockStatsFlagsEnsureACL(domain->conn, dom->def) < 0)
1830         goto cleanup;
1831 
1832     if (vzDomainBlockStatsImpl(dom, path, &stats) < 0)
1833         goto cleanup;
1834 
1835     if (vzDomainBlockStatsToParams(&stats, params, nparams) < 0)
1836         goto cleanup;
1837 
1838     ret = 0;
1839 
1840  cleanup:
1841     virDomainObjEndAPI(&dom);
1842 
1843     return ret;
1844 }
1845 
1846 static int
vzDomainInterfaceStats(virDomainPtr domain,const char * device,virDomainInterfaceStatsPtr stats)1847 vzDomainInterfaceStats(virDomainPtr domain,
1848                          const char *device,
1849                          virDomainInterfaceStatsPtr stats)
1850 {
1851     virDomainObj *dom = NULL;
1852     struct vzDomObj *privdom;
1853     int ret = -1;
1854 
1855     if (!(dom = vzDomObjFromDomain(domain)))
1856         return -1;
1857 
1858     if (virDomainInterfaceStatsEnsureACL(domain->conn, dom->def) < 0)
1859         goto cleanup;
1860 
1861     privdom = dom->privateData;
1862 
1863     ret = prlsdkGetNetStats(privdom->stats, privdom->sdkdom, device, stats);
1864 
1865  cleanup:
1866     virDomainObjEndAPI(&dom);
1867 
1868     return ret;
1869 }
1870 
1871 static int
vzDomainMemoryStats(virDomainPtr domain,virDomainMemoryStatPtr stats,unsigned int nr_stats,unsigned int flags)1872 vzDomainMemoryStats(virDomainPtr domain,
1873                     virDomainMemoryStatPtr stats,
1874                     unsigned int nr_stats,
1875                     unsigned int flags)
1876 {
1877     virDomainObj *dom = NULL;
1878     struct vzDomObj *privdom;
1879     int ret = -1;
1880 
1881     virCheckFlags(0, -1);
1882     if (!(dom = vzDomObjFromDomain(domain)))
1883         return -1;
1884 
1885     if (virDomainMemoryStatsEnsureACL(domain->conn, dom->def) < 0)
1886         goto cleanup;
1887 
1888     privdom = dom->privateData;
1889 
1890     ret = prlsdkGetMemoryStats(privdom->stats, stats, nr_stats);
1891 
1892  cleanup:
1893     virDomainObjEndAPI(&dom);
1894 
1895     return ret;
1896 }
1897 
1898 static int
vzDomainGetVcpusFlags(virDomainPtr domain,unsigned int flags)1899 vzDomainGetVcpusFlags(virDomainPtr domain,
1900                       unsigned int flags)
1901 {
1902     virDomainObj *dom;
1903     int ret = -1;
1904 
1905     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1906                   VIR_DOMAIN_AFFECT_CONFIG |
1907                   VIR_DOMAIN_VCPU_MAXIMUM, -1);
1908 
1909     if (!(dom = vzDomObjFromDomain(domain)))
1910         return -1;
1911 
1912     if (virDomainGetVcpusFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
1913         goto cleanup;
1914 
1915     if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
1916         ret = virDomainDefGetVcpusMax(dom->def);
1917     else
1918         ret = virDomainDefGetVcpus(dom->def);
1919 
1920  cleanup:
1921     virDomainObjEndAPI(&dom);
1922 
1923     return ret;
1924 }
1925 
vzDomainGetMaxVcpus(virDomainPtr domain)1926 static int vzDomainGetMaxVcpus(virDomainPtr domain)
1927 {
1928     return vzDomainGetVcpusFlags(domain, (VIR_DOMAIN_AFFECT_LIVE |
1929                                           VIR_DOMAIN_VCPU_MAXIMUM));
1930 }
1931 
vzDomainIsUpdated(virDomainPtr domain)1932 static int vzDomainIsUpdated(virDomainPtr domain)
1933 {
1934     virDomainObj *dom;
1935     int ret = -1;
1936 
1937     /* As far as VZ domains are always updated (e.g. current==persistent),
1938      * we just check for domain existence */
1939     if (!(dom = vzDomObjFromDomain(domain)))
1940         return -1;
1941 
1942     if (virDomainIsUpdatedEnsureACL(domain->conn, dom->def) < 0)
1943         goto cleanup;
1944 
1945     ret = 0;
1946 
1947  cleanup:
1948     virDomainObjEndAPI(&dom);
1949     return ret;
1950 }
1951 
vzConnectGetMaxVcpus(virConnectPtr conn,const char * type)1952 static int vzConnectGetMaxVcpus(virConnectPtr conn,
1953                                 const char *type)
1954 {
1955     if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
1956         return -1;
1957 
1958     /* As far as we have no limitation for containers
1959      * we report maximum */
1960     if (type == NULL || STRCASEEQ(type, "vz") || STRCASEEQ(type, "parallels"))
1961         return 1028;
1962 
1963     virReportError(VIR_ERR_INVALID_ARG,
1964                    _("unknown type '%s'"), type);
1965     return -1;
1966 }
1967 
1968 static int
vzNodeGetCPUStats(virConnectPtr conn,int cpuNum,virNodeCPUStatsPtr params,int * nparams,unsigned int flags)1969 vzNodeGetCPUStats(virConnectPtr conn,
1970                   int cpuNum,
1971                   virNodeCPUStatsPtr params,
1972                   int *nparams,
1973                   unsigned int flags)
1974 {
1975     if (virNodeGetCPUStatsEnsureACL(conn) < 0)
1976         return -1;
1977 
1978     return virHostCPUGetStats(cpuNum, params, nparams, flags);
1979 }
1980 
1981 static int
vzNodeGetMemoryStats(virConnectPtr conn,int cellNum,virNodeMemoryStatsPtr params,int * nparams,unsigned int flags)1982 vzNodeGetMemoryStats(virConnectPtr conn,
1983                      int cellNum,
1984                      virNodeMemoryStatsPtr params,
1985                      int *nparams,
1986                      unsigned int flags)
1987 {
1988     if (virNodeGetMemoryStatsEnsureACL(conn) < 0)
1989         return -1;
1990 
1991     return virHostMemGetStats(cellNum, params, nparams, flags);
1992 }
1993 
1994 static int
vzNodeGetCellsFreeMemory(virConnectPtr conn,unsigned long long * freeMems,int startCell,int maxCells)1995 vzNodeGetCellsFreeMemory(virConnectPtr conn,
1996                          unsigned long long *freeMems,
1997                          int startCell,
1998                          int maxCells)
1999 {
2000     if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
2001         return -1;
2002 
2003     return virHostMemGetCellsFree(freeMems, startCell, maxCells);
2004 }
2005 
2006 static unsigned long long
vzNodeGetFreeMemory(virConnectPtr conn)2007 vzNodeGetFreeMemory(virConnectPtr conn)
2008 {
2009     unsigned long long freeMem;
2010 
2011     if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
2012         return -1;
2013 
2014     if (virHostMemGetInfo(NULL, &freeMem) < 0)
2015         return 0;
2016     return freeMem;
2017 }
2018 
2019 static int
vzConnectRegisterCloseCallback(virConnectPtr conn,virConnectCloseFunc cb,void * opaque,virFreeCallback freecb)2020 vzConnectRegisterCloseCallback(virConnectPtr conn,
2021                                virConnectCloseFunc cb,
2022                                void *opaque,
2023                                virFreeCallback freecb)
2024 {
2025     struct _vzConn *privconn = conn->privateData;
2026     int ret = -1;
2027 
2028     if (virConnectRegisterCloseCallbackEnsureACL(conn) < 0)
2029         return -1;
2030 
2031     virObjectLock(privconn->driver);
2032 
2033     if (virConnectCloseCallbackDataGetCallback(privconn->closeCallback) != NULL) {
2034         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2035                        _("A close callback is already registered"));
2036         goto cleanup;
2037     }
2038 
2039     virConnectCloseCallbackDataRegister(privconn->closeCallback, conn, cb,
2040                                         opaque, freecb);
2041     ret = 0;
2042 
2043  cleanup:
2044     virObjectUnlock(privconn->driver);
2045 
2046     return ret;
2047 }
2048 
2049 static int
vzConnectUnregisterCloseCallback(virConnectPtr conn,virConnectCloseFunc cb)2050 vzConnectUnregisterCloseCallback(virConnectPtr conn, virConnectCloseFunc cb)
2051 {
2052     struct _vzConn *privconn = conn->privateData;
2053     int ret = -1;
2054 
2055     if (virConnectUnregisterCloseCallbackEnsureACL(conn) < 0)
2056         return -1;
2057 
2058     virObjectLock(privconn->driver);
2059 
2060     if (virConnectCloseCallbackDataGetCallback(privconn->closeCallback) != cb) {
2061         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2062                        _("A different callback was requested"));
2063         goto cleanup;
2064     }
2065 
2066     virConnectCloseCallbackDataUnregister(privconn->closeCallback, cb);
2067     ret = 0;
2068 
2069  cleanup:
2070     virObjectUnlock(privconn->driver);
2071 
2072     return ret;
2073 }
2074 
vzDomainSetMemoryFlags(virDomainPtr domain,unsigned long memory,unsigned int flags)2075 static int vzDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
2076                                   unsigned int flags)
2077 {
2078     virDomainObj *dom = NULL;
2079     int ret = -1;
2080     bool job = false;
2081 
2082     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2083                   VIR_DOMAIN_AFFECT_CONFIG, -1);
2084 
2085     if (!(dom = vzDomObjFromDomain(domain)))
2086         return -1;
2087 
2088     if (vzCheckConfigUpdateFlags(dom, &flags) < 0)
2089         goto cleanup;
2090 
2091     if (virDomainSetMemoryFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
2092         goto cleanup;
2093 
2094     if (vzDomainObjBeginJob(dom) < 0)
2095         goto cleanup;
2096     job = true;
2097 
2098     if (vzEnsureDomainExists(dom) < 0)
2099         goto cleanup;
2100 
2101     ret = prlsdkSetMemsize(dom, memory >> 10);
2102 
2103  cleanup:
2104 
2105     if (job)
2106         vzDomainObjEndJob(dom);
2107     virDomainObjEndAPI(&dom);
2108     return ret;
2109 }
2110 
vzDomainSetMemory(virDomainPtr domain,unsigned long memory)2111 static int vzDomainSetMemory(virDomainPtr domain, unsigned long memory)
2112 {
2113     virDomainObj *dom = NULL;
2114     int ret = -1;
2115     bool job = false;
2116 
2117     if (!(dom = vzDomObjFromDomain(domain)))
2118         return -1;
2119 
2120     if (virDomainSetMemoryEnsureACL(domain->conn, dom->def) < 0)
2121         goto cleanup;
2122 
2123     if (vzDomainObjBeginJob(dom) < 0)
2124         goto cleanup;
2125     job = true;
2126 
2127     if (vzEnsureDomainExists(dom) < 0)
2128         goto cleanup;
2129 
2130     ret = prlsdkSetMemsize(dom, memory >> 10);
2131 
2132  cleanup:
2133 
2134     if (job)
2135         vzDomainObjEndJob(dom);
2136     virDomainObjEndAPI(&dom);
2137     return ret;
2138 }
2139 
2140 static virDomainMomentObj *
vzSnapObjFromName(virDomainSnapshotObjList * snapshots,const char * name)2141 vzSnapObjFromName(virDomainSnapshotObjList *snapshots, const char *name)
2142 {
2143     virDomainMomentObj *snap = NULL;
2144     snap = virDomainSnapshotFindByName(snapshots, name);
2145     if (!snap)
2146         virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
2147                        _("no domain snapshot with matching name '%s'"), name);
2148 
2149     return snap;
2150 }
2151 
2152 static virDomainMomentObj *
vzSnapObjFromSnapshot(virDomainSnapshotObjList * snapshots,virDomainSnapshotPtr snapshot)2153 vzSnapObjFromSnapshot(virDomainSnapshotObjList *snapshots,
2154                       virDomainSnapshotPtr snapshot)
2155 {
2156     return vzSnapObjFromName(snapshots, snapshot->name);
2157 }
2158 
2159 static int
vzDomainSnapshotNum(virDomainPtr domain,unsigned int flags)2160 vzDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
2161 {
2162     virDomainObj *dom;
2163     virDomainSnapshotObjList *snapshots = NULL;
2164     int n = -1;
2165 
2166     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
2167                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2168 
2169     if (!(dom = vzDomObjFromDomain(domain)))
2170         return -1;
2171 
2172     if (virDomainSnapshotNumEnsureACL(domain->conn, dom->def) < 0)
2173         goto cleanup;
2174 
2175     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2176         goto cleanup;
2177 
2178     n = virDomainSnapshotObjListNum(snapshots, NULL, flags);
2179 
2180  cleanup:
2181     virDomainSnapshotObjListFree(snapshots);
2182     virDomainObjEndAPI(&dom);
2183 
2184     return n;
2185 }
2186 
2187 static int
vzDomainSnapshotListNames(virDomainPtr domain,char ** names,int nameslen,unsigned int flags)2188 vzDomainSnapshotListNames(virDomainPtr domain,
2189                           char **names,
2190                           int nameslen,
2191                           unsigned int flags)
2192 {
2193     virDomainObj *dom;
2194     virDomainSnapshotObjList *snapshots = NULL;
2195     int n = -1;
2196 
2197     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
2198                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2199 
2200     if (!(dom = vzDomObjFromDomain(domain)))
2201         return -1;
2202 
2203     if (virDomainSnapshotListNamesEnsureACL(domain->conn, dom->def) < 0)
2204         goto cleanup;
2205 
2206     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2207         goto cleanup;
2208 
2209     n = virDomainSnapshotObjListGetNames(snapshots, NULL, names, nameslen, flags);
2210 
2211  cleanup:
2212     virDomainSnapshotObjListFree(snapshots);
2213     virDomainObjEndAPI(&dom);
2214 
2215     return n;
2216 }
2217 
2218 static int
vzDomainListAllSnapshots(virDomainPtr domain,virDomainSnapshotPtr ** snaps,unsigned int flags)2219 vzDomainListAllSnapshots(virDomainPtr domain,
2220                          virDomainSnapshotPtr **snaps,
2221                          unsigned int flags)
2222 {
2223     virDomainObj *dom;
2224     virDomainSnapshotObjList *snapshots = NULL;
2225     int n = -1;
2226 
2227     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
2228                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2229 
2230     if (!(dom = vzDomObjFromDomain(domain)))
2231         return -1;
2232 
2233     if (virDomainListAllSnapshotsEnsureACL(domain->conn, dom->def) < 0)
2234         goto cleanup;
2235 
2236     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2237         goto cleanup;
2238 
2239     n = virDomainListSnapshots(snapshots, NULL, domain, snaps, flags);
2240 
2241  cleanup:
2242     virDomainSnapshotObjListFree(snapshots);
2243     virDomainObjEndAPI(&dom);
2244 
2245     return n;
2246 }
2247 
2248 static char *
vzDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,unsigned int flags)2249 vzDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, unsigned int flags)
2250 {
2251     virDomainObj *dom;
2252     char *xml = NULL;
2253     virDomainMomentObj *snap;
2254     char uuidstr[VIR_UUID_STRING_BUFLEN];
2255     virDomainSnapshotObjList *snapshots = NULL;
2256     struct _vzConn *privconn = snapshot->domain->conn->privateData;
2257 
2258     virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
2259 
2260     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2261         return NULL;
2262 
2263     if (virDomainSnapshotGetXMLDescEnsureACL(snapshot->domain->conn, dom->def, flags) < 0)
2264         goto cleanup;
2265 
2266     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2267         goto cleanup;
2268 
2269     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2270         goto cleanup;
2271 
2272     virUUIDFormat(snapshot->domain->uuid, uuidstr);
2273 
2274     xml = virDomainSnapshotDefFormat(uuidstr, virDomainSnapshotObjGetDef(snap),
2275                                      privconn->driver->xmlopt,
2276                                      virDomainSnapshotFormatConvertXMLFlags(flags));
2277 
2278  cleanup:
2279     virDomainSnapshotObjListFree(snapshots);
2280     virDomainObjEndAPI(&dom);
2281 
2282     return xml;
2283 }
2284 
2285 static int
vzDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,unsigned int flags)2286 vzDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, unsigned int flags)
2287 {
2288     virDomainObj *dom;
2289     virDomainMomentObj *snap;
2290     virDomainSnapshotObjList *snapshots = NULL;
2291     int n = -1;
2292 
2293     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
2294                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2295 
2296     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2297         return -1;
2298 
2299     if (virDomainSnapshotNumChildrenEnsureACL(snapshot->domain->conn, dom->def) < 0)
2300         goto cleanup;
2301 
2302     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2303         goto cleanup;
2304 
2305     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2306         goto cleanup;
2307 
2308     n = virDomainSnapshotObjListNum(snapshots, snap, flags);
2309 
2310  cleanup:
2311     virDomainSnapshotObjListFree(snapshots);
2312     virDomainObjEndAPI(&dom);
2313 
2314     return n;
2315 }
2316 
2317 static int
vzDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,char ** names,int nameslen,unsigned int flags)2318 vzDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
2319                                   char **names,
2320                                   int nameslen,
2321                                   unsigned int flags)
2322 {
2323     virDomainObj *dom;
2324     virDomainMomentObj *snap;
2325     virDomainSnapshotObjList *snapshots = NULL;
2326     int n = -1;
2327 
2328     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
2329                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2330 
2331     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2332         return -1;
2333 
2334     if (virDomainSnapshotListChildrenNamesEnsureACL(snapshot->domain->conn, dom->def) < 0)
2335         goto cleanup;
2336 
2337     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2338         goto cleanup;
2339 
2340     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2341         goto cleanup;
2342 
2343     n = virDomainSnapshotObjListGetNames(snapshots, snap, names, nameslen, flags);
2344 
2345  cleanup:
2346     virDomainSnapshotObjListFree(snapshots);
2347     virDomainObjEndAPI(&dom);
2348 
2349     return n;
2350 }
2351 
2352 static int
vzDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,virDomainSnapshotPtr ** snaps,unsigned int flags)2353 vzDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
2354                                 virDomainSnapshotPtr **snaps,
2355                                 unsigned int flags)
2356 {
2357     virDomainObj *dom;
2358     virDomainMomentObj *snap;
2359     virDomainSnapshotObjList *snapshots = NULL;
2360     int n = -1;
2361 
2362     virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
2363                   VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
2364 
2365     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2366         return -1;
2367 
2368     if (virDomainSnapshotListAllChildrenEnsureACL(snapshot->domain->conn, dom->def) < 0)
2369         goto cleanup;
2370 
2371     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2372         goto cleanup;
2373 
2374     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2375         goto cleanup;
2376 
2377     n = virDomainListSnapshots(snapshots, snap, snapshot->domain, snaps, flags);
2378 
2379  cleanup:
2380     virDomainSnapshotObjListFree(snapshots);
2381     virDomainObjEndAPI(&dom);
2382 
2383     return n;
2384 }
2385 
2386 static virDomainSnapshotPtr
vzDomainSnapshotLookupByName(virDomainPtr domain,const char * name,unsigned int flags)2387 vzDomainSnapshotLookupByName(virDomainPtr domain,
2388                              const char *name,
2389                              unsigned int flags)
2390 {
2391     virDomainObj *dom;
2392     virDomainMomentObj *snap;
2393     virDomainSnapshotPtr snapshot = NULL;
2394     virDomainSnapshotObjList *snapshots = NULL;
2395 
2396     virCheckFlags(0, NULL);
2397 
2398     if (!(dom = vzDomObjFromDomain(domain)))
2399         return NULL;
2400 
2401     if (virDomainSnapshotLookupByNameEnsureACL(domain->conn, dom->def) < 0)
2402         goto cleanup;
2403 
2404     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2405         goto cleanup;
2406 
2407     if (!(snap = vzSnapObjFromName(snapshots, name)))
2408         goto cleanup;
2409 
2410     snapshot = virGetDomainSnapshot(domain, snap->def->name);
2411 
2412  cleanup:
2413     virDomainObjEndAPI(&dom);
2414     virDomainSnapshotObjListFree(snapshots);
2415 
2416     return snapshot;
2417 }
2418 
2419 static int
vzDomainHasCurrentSnapshot(virDomainPtr domain,unsigned int flags)2420 vzDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
2421 {
2422     virDomainObj *dom;
2423     virDomainSnapshotObjList *snapshots = NULL;
2424     int ret = -1;
2425 
2426     virCheckFlags(0, -1);
2427 
2428     if (!(dom = vzDomObjFromDomain(domain)))
2429         return -1;
2430 
2431     if (virDomainHasCurrentSnapshotEnsureACL(domain->conn, dom->def) < 0)
2432         goto cleanup;
2433 
2434     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2435         goto cleanup;
2436 
2437     ret = virDomainSnapshotGetCurrent(snapshots) != NULL;
2438 
2439  cleanup:
2440     virDomainSnapshotObjListFree(snapshots);
2441     virDomainObjEndAPI(&dom);
2442 
2443     return ret;
2444 }
2445 
2446 static virDomainSnapshotPtr
vzDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,unsigned int flags)2447 vzDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags)
2448 {
2449     virDomainObj *dom;
2450     virDomainMomentObj *snap;
2451     virDomainSnapshotPtr parent = NULL;
2452     virDomainSnapshotObjList *snapshots = NULL;
2453 
2454     virCheckFlags(0, NULL);
2455 
2456     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2457         return NULL;
2458 
2459     if (virDomainSnapshotGetParentEnsureACL(snapshot->domain->conn, dom->def) < 0)
2460         goto cleanup;
2461 
2462     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2463         goto cleanup;
2464 
2465     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2466         goto cleanup;
2467 
2468     if (!snap->def->parent_name) {
2469         virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
2470                        _("snapshot '%s' does not have a parent"),
2471                        snap->def->name);
2472         goto cleanup;
2473     }
2474 
2475     parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent_name);
2476 
2477  cleanup:
2478     virDomainSnapshotObjListFree(snapshots);
2479     virDomainObjEndAPI(&dom);
2480 
2481     return parent;
2482 }
2483 
2484 static virDomainSnapshotPtr
vzDomainSnapshotCurrent(virDomainPtr domain,unsigned int flags)2485 vzDomainSnapshotCurrent(virDomainPtr domain, unsigned int flags)
2486 {
2487     virDomainObj *dom;
2488     virDomainSnapshotPtr snapshot = NULL;
2489     virDomainSnapshotObjList *snapshots = NULL;
2490     virDomainMomentObj *current;
2491 
2492     virCheckFlags(0, NULL);
2493 
2494     if (!(dom = vzDomObjFromDomain(domain)))
2495         return NULL;
2496 
2497     if (virDomainSnapshotCurrentEnsureACL(domain->conn, dom->def) < 0)
2498         goto cleanup;
2499 
2500     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2501         goto cleanup;
2502 
2503     if (!(current = virDomainSnapshotGetCurrent(snapshots))) {
2504         virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
2505                        _("the domain does not have a current snapshot"));
2506         goto cleanup;
2507     }
2508 
2509     snapshot = virGetDomainSnapshot(domain, current->def->name);
2510 
2511  cleanup:
2512     virDomainSnapshotObjListFree(snapshots);
2513     virDomainObjEndAPI(&dom);
2514 
2515     return snapshot;
2516 }
2517 
2518 static int
vzDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,unsigned int flags)2519 vzDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags)
2520 {
2521     virDomainObj *dom;
2522     int ret = -1;
2523     virDomainSnapshotObjList *snapshots = NULL;
2524     virDomainMomentObj *current;
2525 
2526     virCheckFlags(0, -1);
2527 
2528     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2529         return -1;
2530 
2531     if (virDomainSnapshotIsCurrentEnsureACL(snapshot->domain->conn, dom->def) < 0)
2532         goto cleanup;
2533 
2534     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2535         goto cleanup;
2536 
2537     current = virDomainSnapshotGetCurrent(snapshots);
2538     ret = current && STREQ(snapshot->name, current->def->name);
2539 
2540  cleanup:
2541     virDomainSnapshotObjListFree(snapshots);
2542     virDomainObjEndAPI(&dom);
2543 
2544     return ret;
2545 }
2546 
2547 static int
vzDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,unsigned int flags)2548 vzDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
2549                               unsigned int flags)
2550 {
2551     virDomainObj *dom;
2552     int ret = -1;
2553     virDomainMomentObj *snap;
2554     virDomainSnapshotObjList *snapshots = NULL;
2555 
2556     virCheckFlags(0, -1);
2557 
2558     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2559         return -1;
2560 
2561     if (virDomainSnapshotHasMetadataEnsureACL(snapshot->domain->conn, dom->def) < 0)
2562         goto cleanup;
2563 
2564     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2565         goto cleanup;
2566 
2567     if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
2568         goto cleanup;
2569 
2570     ret = 1;
2571 
2572  cleanup:
2573     virDomainSnapshotObjListFree(snapshots);
2574     virDomainObjEndAPI(&dom);
2575 
2576     return ret;
2577 }
2578 
2579 static virDomainSnapshotPtr
vzDomainSnapshotCreateXML(virDomainPtr domain,const char * xmlDesc,unsigned int flags)2580 vzDomainSnapshotCreateXML(virDomainPtr domain,
2581                           const char *xmlDesc,
2582                           unsigned int flags)
2583 {
2584     virDomainSnapshotPtr snapshot = NULL;
2585     virDomainObj *dom;
2586     struct _vzConn *privconn = domain->conn->privateData;
2587     struct _vzDriver *driver = privconn->driver;
2588     unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
2589     virDomainSnapshotObjList *snapshots = NULL;
2590     virDomainMomentObj *current;
2591     bool job = false;
2592     g_autoptr(virDomainSnapshotDef) def = NULL;
2593 
2594     virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE, NULL);
2595 
2596     if (!(dom = vzDomObjFromDomain(domain)))
2597         return NULL;
2598 
2599     if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, dom->def, flags) < 0)
2600         goto cleanup;
2601 
2602     if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_VALIDATE)
2603         parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_VALIDATE;
2604 
2605     if (!(def = virDomainSnapshotDefParseString(xmlDesc,
2606                                                 driver->xmlopt, NULL, NULL,
2607                                                 parse_flags)))
2608         goto cleanup;
2609 
2610     if (def->ndisks > 0) {
2611         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2612                        _("configuring disks is not supported for vz snapshots"));
2613         goto cleanup;
2614     }
2615 
2616     if (def->memory) {
2617         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2618                        _("configuring memory location is not supported"));
2619         goto cleanup;
2620     }
2621 
2622     if (vzDomainObjBeginJob(dom) < 0)
2623         goto cleanup;
2624     job = true;
2625 
2626     if (vzEnsureDomainExists(dom) < 0)
2627         goto cleanup;
2628 
2629     /* snapshot name is ignored, it will be set to auto generated by sdk uuid */
2630     if (prlsdkCreateSnapshot(dom, def->parent.description) < 0)
2631         goto cleanup;
2632 
2633     if (!(snapshots = prlsdkLoadSnapshots(dom)))
2634         goto cleanup;
2635 
2636     if (!(current = virDomainSnapshotGetCurrent(snapshots))) {
2637         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2638                        _("can't find created snapshot"));
2639         goto cleanup;
2640     }
2641 
2642     /* hopefully new current snapshot is newly created one */
2643     snapshot = virGetDomainSnapshot(domain, current->def->name);
2644 
2645  cleanup:
2646     virDomainSnapshotObjListFree(snapshots);
2647     if (job)
2648         vzDomainObjEndJob(dom);
2649     virDomainObjEndAPI(&dom);
2650 
2651     return snapshot;
2652 }
2653 
2654 static int
vzDomainSnapshotDelete(virDomainSnapshotPtr snapshot,unsigned int flags)2655 vzDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags)
2656 {
2657     virDomainObj *dom;
2658     int ret = -1;
2659 
2660     virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1);
2661 
2662     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2663         return -1;
2664 
2665     if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, dom->def) < 0)
2666         goto cleanup;
2667 
2668     ret = prlsdkDeleteSnapshot(dom, snapshot->name,
2669                                flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN);
2670 
2671  cleanup:
2672     virDomainObjEndAPI(&dom);
2673 
2674     return ret;
2675 }
2676 
2677 static int
vzDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,unsigned int flags)2678 vzDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags)
2679 {
2680     virDomainObj *dom;
2681     int ret = -1;
2682     bool job = false;
2683 
2684     virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, -1);
2685 
2686     if (!(dom = vzDomObjFromDomain(snapshot->domain)))
2687         return -1;
2688 
2689     if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, dom->def) < 0)
2690         goto cleanup;
2691 
2692     if (vzDomainObjBeginJob(dom) < 0)
2693         goto cleanup;
2694     job = true;
2695 
2696     if (vzEnsureDomainExists(dom) < 0)
2697         goto cleanup;
2698 
2699     ret = prlsdkSwitchToSnapshot(dom, snapshot->name,
2700                                  flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED);
2701  cleanup:
2702     if (job)
2703         vzDomainObjEndJob(dom);
2704     virDomainObjEndAPI(&dom);
2705 
2706     return ret;
2707 }
2708 
2709 enum vzMigrationCookieFeatures {
2710     VZ_MIGRATION_COOKIE_SESSION_UUID  = (1 << 0),
2711     VZ_MIGRATION_COOKIE_DOMAIN_UUID = (1 << 1),
2712     VZ_MIGRATION_COOKIE_DOMAIN_NAME = (1 << 1),
2713 };
2714 
2715 typedef struct _vzMigrationCookie vzMigrationCookie;
2716 struct _vzMigrationCookie {
2717     unsigned char *session_uuid;
2718     unsigned char *uuid;
2719     char *name;
2720 };
2721 
2722 static void
vzMigrationCookieFree(vzMigrationCookie * mig)2723 vzMigrationCookieFree(vzMigrationCookie *mig)
2724 {
2725     if (!mig)
2726         return;
2727 
2728     g_free(mig->session_uuid);
2729     g_free(mig->uuid);
2730     g_free(mig->name);
2731     g_free(mig);
2732 }
2733 
2734 static int
vzBakeCookie(struct _vzDriver * driver,virDomainObj * dom,char ** cookieout,int * cookieoutlen,unsigned int flags)2735 vzBakeCookie(struct _vzDriver *driver,
2736              virDomainObj *dom,
2737              char **cookieout, int *cookieoutlen,
2738              unsigned int flags)
2739 {
2740     char uuidstr[VIR_UUID_STRING_BUFLEN];
2741     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2742 
2743     if (!cookieout || !cookieoutlen) {
2744         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2745                        _("Migration cookie parameters are not provided."));
2746         return -1;
2747     }
2748 
2749     *cookieout = NULL;
2750     *cookieoutlen = 0;
2751 
2752     virBufferAddLit(&buf, "<vz-migration>\n");
2753     virBufferAdjustIndent(&buf, 2);
2754 
2755     if (flags & VZ_MIGRATION_COOKIE_SESSION_UUID) {
2756         virUUIDFormat(driver->session_uuid, uuidstr);
2757         virBufferAsprintf(&buf, "<session-uuid>%s</session-uuid>\n", uuidstr);
2758     }
2759 
2760     if (flags & VZ_MIGRATION_COOKIE_DOMAIN_UUID) {
2761         unsigned char fakeuuid[VIR_UUID_BUFLEN] = { 0 };
2762 
2763         /* if dom is NULL just pass some parsable uuid for backward compat.
2764          * It is not used by peer */
2765         virUUIDFormat(dom ? dom->def->uuid : fakeuuid, uuidstr);
2766         virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
2767     }
2768 
2769     if (flags & VZ_MIGRATION_COOKIE_DOMAIN_NAME) {
2770         /* if dom is NULL just pass some name for backward compat.
2771          * It is not used by peer */
2772         virBufferAsprintf(&buf, "<name>%s</name>\n", dom ? dom->def->name :
2773                                                            "__fakename__");
2774     }
2775 
2776     virBufferAdjustIndent(&buf, -2);
2777     virBufferAddLit(&buf, "</vz-migration>\n");
2778 
2779     *cookieout = virBufferContentAndReset(&buf);
2780     *cookieoutlen = strlen(*cookieout) + 1;
2781 
2782     return 0;
2783 }
2784 
2785 static vzMigrationCookie *
vzEatCookie(const char * cookiein,int cookieinlen,unsigned int flags)2786 vzEatCookie(const char *cookiein, int cookieinlen, unsigned int flags)
2787 {
2788     g_autoptr(xmlDoc) doc = NULL;
2789     g_autoptr(xmlXPathContext) ctx = NULL;
2790     vzMigrationCookie *mig = NULL;
2791 
2792     mig = g_new0(vzMigrationCookie, 1);
2793 
2794     if (!cookiein || cookieinlen <= 0 || cookiein[cookieinlen - 1] != '\0') {
2795         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2796                        _("Invalid migration cookie"));
2797         goto error;
2798     }
2799 
2800     if (!(doc = virXMLParseStringCtxt(cookiein,
2801                                       _("(_migration_cookie)"), &ctx)))
2802         goto error;
2803 
2804     if (flags & VZ_MIGRATION_COOKIE_SESSION_UUID) {
2805         g_autofree char *tmp = NULL;
2806         mig->session_uuid = g_new0(unsigned char, VIR_UUID_BUFLEN);
2807 
2808         if ((!(tmp = virXPathString("string(./session-uuid[1])", ctx))
2809             || (virUUIDParse(tmp, mig->session_uuid) < 0))) {
2810             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2811                            _("missing or malformed session-uuid element "
2812                              "in migration data"));
2813             goto error;
2814         }
2815     }
2816 
2817     if (flags & VZ_MIGRATION_COOKIE_DOMAIN_UUID) {
2818         g_autofree char *tmp = NULL;
2819         mig->uuid = g_new0(unsigned char, VIR_UUID_BUFLEN);
2820 
2821         if ((!(tmp = virXPathString("string(./uuid[1])", ctx))
2822             || (virUUIDParse(tmp, mig->uuid) < 0))) {
2823             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2824                            _("missing or malformed uuid element in migration data"));
2825             goto error;
2826         }
2827     }
2828 
2829     if ((flags & VZ_MIGRATION_COOKIE_DOMAIN_NAME)
2830         && !(mig->name = virXPathString("string(./name[1])", ctx))) {
2831         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2832                        _("missing name element in migration data"));
2833         goto error;
2834     }
2835 
2836     return mig;
2837 
2838  error:
2839     vzMigrationCookieFree(mig);
2840     return NULL;
2841 }
2842 
2843 #define VZ_MIGRATION_FLAGS         (VIR_MIGRATE_PAUSED | \
2844                                     VIR_MIGRATE_PEER2PEER | \
2845                                     VIR_MIGRATE_LIVE | \
2846                                     VIR_MIGRATE_UNDEFINE_SOURCE | \
2847                                     VIR_MIGRATE_PERSIST_DEST | \
2848                                     VIR_MIGRATE_NON_SHARED_INC)
2849 
2850 #define VZ_MIGRATION_PARAMETERS \
2851     VIR_MIGRATE_PARAM_DEST_XML,         VIR_TYPED_PARAM_STRING, \
2852     VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \
2853     VIR_MIGRATE_PARAM_DEST_NAME,        VIR_TYPED_PARAM_STRING, \
2854     VIR_MIGRATE_PARAM_BANDWIDTH,        VIR_TYPED_PARAM_ULLONG, \
2855     NULL
2856 
2857 static char *
vzDomainMigrateBeginStep(virDomainObj * dom,struct _vzDriver * driver,virTypedParameterPtr params,int nparams,char ** cookieout,int * cookieoutlen)2858 vzDomainMigrateBeginStep(virDomainObj *dom,
2859                          struct _vzDriver *driver,
2860                          virTypedParameterPtr params,
2861                          int nparams,
2862                          char **cookieout,
2863                          int *cookieoutlen)
2864 {
2865     /* we can't do this check via VZ_MIGRATION_PARAMETERS as on preparation
2866      * step domain xml will be passed via this parameter and it is a common
2867      * style to use single allowed parameter list definition in all steps */
2868     if (virTypedParamsGet(params, nparams, VIR_MIGRATE_PARAM_DEST_XML)) {
2869         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2870                        _("Changing destination XML is not supported"));
2871         return NULL;
2872     }
2873 
2874     /* session uuid, domain uuid and domain name are for backward compat */
2875     if (vzBakeCookie(driver, dom, cookieout, cookieoutlen,
2876                      VZ_MIGRATION_COOKIE_SESSION_UUID
2877                      | VZ_MIGRATION_COOKIE_DOMAIN_UUID
2878                      | VZ_MIGRATION_COOKIE_DOMAIN_NAME) < 0)
2879         return NULL;
2880 
2881     return virDomainDefFormat(dom->def, driver->xmlopt,
2882                               VIR_DOMAIN_XML_MIGRATABLE);
2883 }
2884 
2885 static char *
vzDomainMigrateBegin3Params(virDomainPtr domain,virTypedParameterPtr params,int nparams,char ** cookieout,int * cookieoutlen,unsigned int flags)2886 vzDomainMigrateBegin3Params(virDomainPtr domain,
2887                             virTypedParameterPtr params,
2888                             int nparams,
2889                             char **cookieout,
2890                             int *cookieoutlen,
2891                             unsigned int flags)
2892 {
2893     char *xml = NULL;
2894     virDomainObj *dom = NULL;
2895     struct _vzConn *privconn = domain->conn->privateData;
2896     unsigned long long bandwidth = 0;
2897 
2898     virCheckFlags(VZ_MIGRATION_FLAGS, NULL);
2899 
2900     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
2901         goto cleanup;
2902 
2903     if (virTypedParamsGetULLong(params, nparams, VIR_MIGRATE_PARAM_BANDWIDTH,
2904                                 &bandwidth) < 0)
2905         goto cleanup;
2906 
2907     if (bandwidth > 0) {
2908         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2909                        _("Bandwidth rate limiting is not supported"));
2910         goto cleanup;
2911     }
2912 
2913     if (!(dom = vzDomObjFromDomain(domain)))
2914         goto cleanup;
2915 
2916     if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, dom->def) < 0)
2917         goto cleanup;
2918 
2919     xml = vzDomainMigrateBeginStep(dom, privconn->driver, params, nparams,
2920                                    cookieout, cookieoutlen);
2921 
2922  cleanup:
2923 
2924     virDomainObjEndAPI(&dom);
2925     return xml;
2926 }
2927 
2928 static char*
vzMigrationCreateURI(void)2929 vzMigrationCreateURI(void)
2930 {
2931     char *hostname = NULL;
2932     char *uri = NULL;
2933 
2934     if (!(hostname = virGetHostname()))
2935         goto cleanup;
2936 
2937     if (STRPREFIX(hostname, "localhost")) {
2938         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2939                        _("hostname on destination resolved to localhost,"
2940                          " but migration requires an FQDN"));
2941         goto cleanup;
2942     }
2943 
2944     uri = g_strdup_printf("vzmigr://%s", hostname);
2945 
2946  cleanup:
2947     VIR_FREE(hostname);
2948     return uri;
2949 }
2950 
2951 static int
vzDomainMigratePrepare3Params(virConnectPtr conn,virTypedParameterPtr params,int nparams,const char * cookiein G_GNUC_UNUSED,int cookieinlen G_GNUC_UNUSED,char ** cookieout,int * cookieoutlen,char ** uri_out,unsigned int flags)2952 vzDomainMigratePrepare3Params(virConnectPtr conn,
2953                               virTypedParameterPtr params,
2954                               int nparams,
2955                               const char *cookiein G_GNUC_UNUSED,
2956                               int cookieinlen G_GNUC_UNUSED,
2957                               char **cookieout,
2958                               int *cookieoutlen,
2959                               char **uri_out,
2960                               unsigned int flags)
2961 {
2962     struct _vzConn *privconn = conn->privateData;
2963     struct _vzDriver *driver = privconn->driver;
2964     const char *miguri = NULL;
2965     const char *dname = NULL;
2966     const char *dom_xml = NULL;
2967     virDomainDef *def = NULL;
2968     int ret = -1;
2969 
2970     virCheckFlags(VZ_MIGRATION_FLAGS, -1);
2971 
2972     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
2973         goto cleanup;
2974 
2975     if (virTypedParamsGetString(params, nparams,
2976                                 VIR_MIGRATE_PARAM_URI, &miguri) < 0 ||
2977         virTypedParamsGetString(params, nparams,
2978                                 VIR_MIGRATE_PARAM_DEST_XML, &dom_xml) < 0 ||
2979         virTypedParamsGetString(params, nparams,
2980                                 VIR_MIGRATE_PARAM_DEST_NAME, &dname) < 0)
2981         goto cleanup;
2982 
2983     /* We must set uri_out if miguri is not set. This is direct
2984      * managed migration requirement */
2985     if (!miguri && !(*uri_out = vzMigrationCreateURI()))
2986         goto cleanup;
2987 
2988     /* domain uuid and domain name are for backward compat */
2989     if (vzBakeCookie(privconn->driver, NULL,
2990                      cookieout, cookieoutlen,
2991                      VZ_MIGRATION_COOKIE_SESSION_UUID
2992                      | VZ_MIGRATION_COOKIE_DOMAIN_UUID
2993                      | VZ_MIGRATION_COOKIE_DOMAIN_NAME) < 0)
2994         goto cleanup;
2995 
2996     if (!(def = virDomainDefParseString(dom_xml, driver->xmlopt,
2997                                         NULL,
2998                                         VIR_DOMAIN_DEF_PARSE_INACTIVE)))
2999         goto cleanup;
3000 
3001     if (dname) {
3002         VIR_FREE(def->name);
3003         def->name = g_strdup(dname);
3004     }
3005 
3006     if (virDomainMigratePrepare3ParamsEnsureACL(conn, def) < 0)
3007         goto cleanup;
3008 
3009     ret = 0;
3010 
3011  cleanup:
3012     virDomainDefFree(def);
3013     return ret;
3014 }
3015 
3016 static int
vzConnectSupportsFeature(virConnectPtr conn G_GNUC_UNUSED,int feature)3017 vzConnectSupportsFeature(virConnectPtr conn G_GNUC_UNUSED, int feature)
3018 {
3019     if (virConnectSupportsFeatureEnsureACL(conn) < 0)
3020         return -1;
3021 
3022     switch ((virDrvFeature) feature) {
3023     case VIR_DRV_FEATURE_MIGRATION_PARAMS:
3024     case VIR_DRV_FEATURE_MIGRATION_P2P:
3025     case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
3026         return 1;
3027     case VIR_DRV_FEATURE_FD_PASSING:
3028     case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
3029     case VIR_DRV_FEATURE_MIGRATION_DIRECT:
3030     case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
3031     case VIR_DRV_FEATURE_MIGRATION_V1:
3032     case VIR_DRV_FEATURE_MIGRATION_V2:
3033     case VIR_DRV_FEATURE_MIGRATION_V3:
3034     case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
3035     case VIR_DRV_FEATURE_REMOTE:
3036     case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
3037     case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
3038     case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
3039     case VIR_DRV_FEATURE_XML_MIGRATABLE:
3040     default:
3041         return 0;
3042     }
3043 }
3044 
3045 static virURI *
vzParseVzURI(const char * uri_str)3046 vzParseVzURI(const char *uri_str)
3047 {
3048     virURI *uri = NULL;
3049 
3050     if (!(uri = virURIParse(uri_str)))
3051         goto error;
3052 
3053     if (!uri->scheme || !uri->server) {
3054         virReportError(VIR_ERR_INVALID_ARG,
3055                        _("scheme and host are mandatory vz migration URI: %s"),
3056                        uri_str);
3057         goto error;
3058     }
3059 
3060     if (uri->user || uri->path || uri->query || uri->fragment) {
3061         virReportError(VIR_ERR_INVALID_ARG,
3062                        _("only scheme, host and port are supported in "
3063                          "vz migration URI: %s"), uri_str);
3064         goto error;
3065     }
3066 
3067     if (STRNEQ(uri->scheme, "vzmigr")) {
3068         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
3069                        _("unsupported scheme %s in migration URI %s"),
3070                        uri->scheme, uri_str);
3071         goto error;
3072     }
3073 
3074     return uri;
3075 
3076  error:
3077     virURIFree(uri);
3078     return NULL;
3079 }
3080 
3081 static int
vzDomainMigratePerformStep(virDomainObj * dom,struct _vzDriver * driver,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,unsigned int flags)3082 vzDomainMigratePerformStep(virDomainObj *dom,
3083                            struct _vzDriver *driver,
3084                            virTypedParameterPtr params,
3085                            int nparams,
3086                            const char *cookiein,
3087                            int cookieinlen,
3088                            unsigned int flags)
3089 {
3090     int ret = -1;
3091     struct vzDomObj *privdom = dom->privateData;
3092     virURI *vzuri = NULL;
3093     const char *miguri = NULL;
3094     const char *dname = NULL;
3095     vzMigrationCookie *mig = NULL;
3096     bool job = false;
3097 
3098     if (virTypedParamsGetString(params, nparams,
3099                                 VIR_MIGRATE_PARAM_URI, &miguri) < 0 ||
3100         virTypedParamsGetString(params, nparams,
3101                                 VIR_MIGRATE_PARAM_DEST_NAME, &dname) < 0)
3102         goto cleanup;
3103 
3104     if (!miguri) {
3105         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3106                        _("migrate uri is not set"));
3107         goto cleanup;
3108     }
3109 
3110     if (!(mig = vzEatCookie(cookiein, cookieinlen,
3111                             VZ_MIGRATION_COOKIE_SESSION_UUID)))
3112         goto cleanup;
3113 
3114     if (vzDomainObjBeginJob(dom) < 0)
3115         goto cleanup;
3116     job = true;
3117     privdom->job.hasProgress = true;
3118 
3119     if (vzEnsureDomainExists(dom) < 0)
3120         goto cleanup;
3121 
3122     if (!(vzuri = vzParseVzURI(miguri)))
3123         goto cleanup;
3124 
3125     if (prlsdkMigrate(dom, vzuri, mig->session_uuid, dname, flags) < 0)
3126         goto cleanup;
3127 
3128     virDomainObjListRemove(driver->domains, dom);
3129 
3130     ret = 0;
3131 
3132  cleanup:
3133     if (job)
3134         vzDomainObjEndJob(dom);
3135     virURIFree(vzuri);
3136     vzMigrationCookieFree(mig);
3137 
3138     return ret;
3139 }
3140 
3141 static int
vzDomainMigratePerformP2P(virDomainObj * dom,struct _vzDriver * driver,const char * dconnuri,virTypedParameterPtr orig_params,int nparams,unsigned int flags)3142 vzDomainMigratePerformP2P(virDomainObj *dom,
3143                           struct _vzDriver *driver,
3144                           const char *dconnuri,
3145                           virTypedParameterPtr orig_params,
3146                           int nparams,
3147                           unsigned int flags)
3148 {
3149     virDomainPtr ddomain = NULL;
3150     char *uri = NULL;
3151     char *cookiein = NULL;
3152     char *cookieout = NULL;
3153     char *dom_xml = NULL;
3154     int cookieinlen = 0;
3155     int cookieoutlen = 0;
3156     virErrorPtr orig_err = NULL;
3157     int cancelled = 1;
3158     virConnectPtr dconn = NULL;
3159     virTypedParameterPtr params = NULL;
3160     int ret = -1;
3161     int maxparams = nparams;
3162 
3163     if (virTypedParamsCopy(&params, orig_params, nparams) < 0)
3164         return -1;
3165 
3166     if (!(dconn = virConnectOpen(dconnuri)))
3167         goto done;
3168 
3169     if (!(dom_xml = vzDomainMigrateBeginStep(dom, driver, params, nparams,
3170                                              &cookieout, &cookieoutlen)))
3171         goto done;
3172 
3173     if (virTypedParamsAddString(&params, &nparams, &maxparams,
3174                                 VIR_MIGRATE_PARAM_DEST_XML, dom_xml) < 0)
3175         goto done;
3176 
3177     cookiein = g_steal_pointer(&cookieout);
3178     cookieinlen = cookieoutlen;
3179     cookieoutlen = 0;
3180     virObjectUnlock(dom);
3181     ret = dconn->driver->domainMigratePrepare3Params
3182             (dconn, params, nparams, cookiein, cookieinlen,
3183              &cookieout, &cookieoutlen, &uri, flags);
3184     virObjectLock(dom);
3185     if (ret < 0)
3186         goto done;
3187     ret = -1;
3188 
3189     /* preparation step was successful, thus on any error we must perform
3190      * finish step to finalize migration on target
3191      */
3192     if (uri && virTypedParamsReplaceString(&params, &nparams,
3193                                            VIR_MIGRATE_PARAM_URI, uri) < 0) {
3194         virErrorPreserveLast(&orig_err);
3195         goto finish;
3196     }
3197 
3198     VIR_FREE(cookiein);
3199     cookiein = g_steal_pointer(&cookieout);
3200     cookieinlen = cookieoutlen;
3201     cookieoutlen = 0;
3202     if (vzDomainMigratePerformStep(dom, driver, params, nparams, cookiein,
3203                                    cookieinlen, flags) < 0) {
3204         virErrorPreserveLast(&orig_err);
3205         goto finish;
3206     }
3207 
3208     cancelled = 0;
3209 
3210  finish:
3211     if (virTypedParamsGetString(params, nparams,
3212                                 VIR_MIGRATE_PARAM_DEST_NAME, NULL) <= 0 &&
3213         virTypedParamsReplaceString(&params, &nparams,
3214                                     VIR_MIGRATE_PARAM_DEST_NAME,
3215                                     dom->def->name) < 0)
3216         goto done;
3217 
3218     virObjectUnlock(dom);
3219     ddomain = dconn->driver->domainMigrateFinish3Params(dconn, params, nparams,
3220                                                         NULL, 0, NULL, NULL,
3221                                                         flags, cancelled);
3222     virObjectLock(dom);
3223     if (ddomain)
3224         ret = 0;
3225     virObjectUnref(ddomain);
3226 
3227     /* confirm step is NOOP thus no need to call it */
3228 
3229  done:
3230     virErrorRestore(&orig_err);
3231     VIR_FREE(dom_xml);
3232     VIR_FREE(uri);
3233     VIR_FREE(cookiein);
3234     VIR_FREE(cookieout);
3235     virTypedParamsFree(params, nparams);
3236     virObjectUnref(dconn);
3237     return ret;
3238 }
3239 
3240 static int
vzDomainMigratePerform3Params(virDomainPtr domain,const char * dconnuri,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout G_GNUC_UNUSED,int * cookieoutlen G_GNUC_UNUSED,unsigned int flags)3241 vzDomainMigratePerform3Params(virDomainPtr domain,
3242                               const char *dconnuri,
3243                               virTypedParameterPtr params,
3244                               int nparams,
3245                               const char *cookiein,
3246                               int cookieinlen,
3247                               char **cookieout G_GNUC_UNUSED,
3248                               int *cookieoutlen G_GNUC_UNUSED,
3249                               unsigned int flags)
3250 {
3251     int ret = -1;
3252     virDomainObj *dom;
3253     struct _vzConn *privconn = domain->conn->privateData;
3254 
3255     virCheckFlags(VZ_MIGRATION_FLAGS, -1);
3256 
3257     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
3258         return -1;
3259 
3260     if (!(dom = vzDomObjFromDomain(domain)))
3261         return -1;
3262 
3263     if (virDomainMigratePerform3ParamsEnsureACL(domain->conn, dom->def) < 0)
3264         goto cleanup;
3265 
3266     if (flags & VIR_MIGRATE_PEER2PEER)
3267         ret = vzDomainMigratePerformP2P(dom, privconn->driver, dconnuri,
3268                                         params, nparams, flags);
3269     else
3270         ret = vzDomainMigratePerformStep(dom, privconn->driver, params, nparams,
3271                                          cookiein, cookieinlen, flags);
3272 
3273  cleanup:
3274     virDomainObjEndAPI(&dom);
3275 
3276     return ret;
3277 }
3278 
3279 static virDomainPtr
vzDomainMigrateFinish3Params(virConnectPtr dconn,virTypedParameterPtr params,int nparams,const char * cookiein G_GNUC_UNUSED,int cookieinlen G_GNUC_UNUSED,char ** cookieout G_GNUC_UNUSED,int * cookieoutlen G_GNUC_UNUSED,unsigned int flags,int cancelled)3280 vzDomainMigrateFinish3Params(virConnectPtr dconn,
3281                              virTypedParameterPtr params,
3282                              int nparams,
3283                              const char *cookiein G_GNUC_UNUSED,
3284                              int cookieinlen G_GNUC_UNUSED,
3285                              char **cookieout G_GNUC_UNUSED,
3286                              int *cookieoutlen G_GNUC_UNUSED,
3287                              unsigned int flags,
3288                              int cancelled)
3289 {
3290     virDomainObj *dom = NULL;
3291     virDomainPtr domain = NULL;
3292     struct _vzConn *privconn = dconn->privateData;
3293     struct _vzDriver *driver = privconn->driver;
3294     const char *name = NULL;
3295 
3296     virCheckFlags(VZ_MIGRATION_FLAGS, NULL);
3297 
3298     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
3299         return NULL;
3300 
3301     if (cancelled)
3302         return NULL;
3303 
3304     if (virTypedParamsGetString(params, nparams,
3305                                 VIR_MIGRATE_PARAM_DEST_NAME, &name) < 0)
3306         return NULL;
3307 
3308 
3309     if (!(dom = prlsdkAddDomainByName(driver, name)))
3310         goto cleanup;
3311 
3312     /* At first glace at may look strange that we add domain and
3313      * then check ACL but we touch only cache and not real system state */
3314     if (virDomainMigrateFinish3ParamsEnsureACL(dconn, dom->def) < 0)
3315         goto cleanup;
3316 
3317     domain = virGetDomain(dconn, dom->def->name, dom->def->uuid, dom->def->id);
3318 
3319  cleanup:
3320     /* In this situation we have to restore domain on source. But the migration
3321      * is already finished. */
3322     if (!domain)
3323         VIR_WARN("Can't provide domain '%s' after successful migration.", name);
3324     virDomainObjEndAPI(&dom);
3325     return domain;
3326 }
3327 
3328 static int
vzDomainMigrateConfirm3Params(virDomainPtr domain G_GNUC_UNUSED,virTypedParameterPtr params,int nparams,const char * cookiein G_GNUC_UNUSED,int cookieinlen G_GNUC_UNUSED,unsigned int flags,int cancelled G_GNUC_UNUSED)3329 vzDomainMigrateConfirm3Params(virDomainPtr domain G_GNUC_UNUSED,
3330                               virTypedParameterPtr params,
3331                               int nparams,
3332                               const char *cookiein G_GNUC_UNUSED,
3333                               int cookieinlen G_GNUC_UNUSED,
3334                               unsigned int flags,
3335                               int cancelled G_GNUC_UNUSED)
3336 {
3337     virCheckFlags(VZ_MIGRATION_FLAGS, -1);
3338 
3339     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
3340         return -1;
3341 
3342     return 0;
3343 }
3344 
3345 static int
vzDomainGetJobInfoImpl(virDomainObj * dom,virDomainJobInfoPtr info)3346 vzDomainGetJobInfoImpl(virDomainObj *dom, virDomainJobInfoPtr info)
3347 {
3348     struct vzDomObj *privdom = dom->privateData;
3349     struct _vzDomainJobObj *job = &privdom->job;
3350 
3351     memset(info, 0, sizeof(*info));
3352 
3353     if (!job->active || !job->hasProgress)
3354         return 0;
3355 
3356     if (vzDomainJobUpdateTime(job) < 0)
3357         return -1;
3358 
3359     info->type = VIR_DOMAIN_JOB_UNBOUNDED;
3360     info->dataTotal = 100;
3361     info->dataProcessed = job->progress;
3362     info->dataRemaining = 100 - job->progress;
3363     info->timeElapsed = job->elapsed;
3364 
3365     return 0;
3366 }
3367 
3368 static int
vzDomainGetJobInfo(virDomainPtr domain,virDomainJobInfoPtr info)3369 vzDomainGetJobInfo(virDomainPtr domain, virDomainJobInfoPtr info)
3370 {
3371     virDomainObj *dom;
3372     int ret = -1;
3373 
3374     if (!(dom = vzDomObjFromDomain(domain)))
3375         return -1;
3376 
3377     if (virDomainGetJobInfoEnsureACL(domain->conn, dom->def) < 0)
3378         goto cleanup;
3379 
3380     ret = vzDomainGetJobInfoImpl(dom, info);
3381 
3382  cleanup:
3383     virDomainObjEndAPI(&dom);
3384     return ret;
3385 }
3386 
3387 static int
vzDomainJobInfoToParams(virDomainJobInfoPtr info,int * type,virTypedParameterPtr * params,int * nparams)3388 vzDomainJobInfoToParams(virDomainJobInfoPtr info,
3389                         int *type,
3390                         virTypedParameterPtr *params,
3391                         int *nparams)
3392 {
3393     virTypedParameterPtr par = NULL;
3394     int maxpar = 0;
3395     int npar = 0;
3396 
3397     if (virTypedParamsAddULLong(&par, &npar, &maxpar,
3398                                 VIR_DOMAIN_JOB_TIME_ELAPSED,
3399                                 info->timeElapsed) < 0 ||
3400         virTypedParamsAddULLong(&par, &npar, &maxpar,
3401                                 VIR_DOMAIN_JOB_DATA_TOTAL,
3402                                 info->dataTotal) < 0 ||
3403         virTypedParamsAddULLong(&par, &npar, &maxpar,
3404                                 VIR_DOMAIN_JOB_DATA_PROCESSED,
3405                                 info->dataProcessed) < 0 ||
3406         virTypedParamsAddULLong(&par, &npar, &maxpar,
3407                                 VIR_DOMAIN_JOB_DATA_REMAINING,
3408                                 info->dataRemaining) < 0)
3409         goto error;
3410 
3411 
3412     *type = info->type;
3413     *params = par;
3414     *nparams = npar;
3415     return 0;
3416 
3417  error:
3418     virTypedParamsFree(par, npar);
3419     return -1;
3420 }
3421 
3422 static int
vzDomainGetJobStats(virDomainPtr domain,int * type,virTypedParameterPtr * params,int * nparams,unsigned int flags)3423 vzDomainGetJobStats(virDomainPtr domain,
3424                     int *type,
3425                     virTypedParameterPtr *params,
3426                     int *nparams,
3427                     unsigned int flags)
3428 {
3429     virDomainJobInfo info;
3430     virDomainObj *dom;
3431     int ret = -1;
3432 
3433     virCheckFlags(0, -1);
3434 
3435     if (!(dom = vzDomObjFromDomain(domain)))
3436         return -1;
3437 
3438     if (virDomainGetJobStatsEnsureACL(domain->conn, dom->def) < 0)
3439         goto cleanup;
3440 
3441     if (vzDomainGetJobInfoImpl(dom, &info) < 0)
3442         goto cleanup;
3443 
3444     if (info.type == VIR_DOMAIN_JOB_NONE) {
3445         *type = VIR_DOMAIN_JOB_NONE;
3446         *params = NULL;
3447         *nparams = 0;
3448         ret = 0;
3449         goto cleanup;
3450     }
3451 
3452     ret = vzDomainJobInfoToParams(&info, type, params, nparams);
3453 
3454  cleanup:
3455     virDomainObjEndAPI(&dom);
3456 
3457     return ret;
3458 }
3459 
3460 #define VZ_ADD_STAT_PARAM_UUL(group, field, counter) \
3461 do { \
3462     if (stat.field != -1) { \
3463         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
3464                    group ".%zu." counter, i); \
3465         if (virTypedParamsAddULLong(&record->params, \
3466                                     &record->nparams, \
3467                                     maxparams, \
3468                                     param_name, \
3469                                     stat.field) < 0) \
3470             return -1; \
3471     } \
3472 } while (0)
3473 
3474 static int
vzDomainGetBlockStats(virDomainObj * dom,virDomainStatsRecordPtr record,int * maxparams)3475 vzDomainGetBlockStats(virDomainObj *dom,
3476                       virDomainStatsRecordPtr record,
3477                       int *maxparams)
3478 {
3479     struct vzDomObj *privdom = dom->privateData;
3480     size_t i;
3481     char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
3482 
3483     if (virTypedParamsAddUInt(&record->params,
3484                               &record->nparams,
3485                               maxparams,
3486                               "block.count",
3487                               dom->def->ndisks) < 0)
3488         return -1;
3489 
3490     for (i = 0; i < dom->def->ndisks; i++) {
3491         virDomainBlockStatsStruct stat;
3492         virDomainDiskDef *disk = dom->def->disks[i];
3493 
3494         if (prlsdkGetBlockStats(privdom->stats,
3495                                 disk,
3496                                 &stat,
3497                                 IS_CT(dom->def)) < 0)
3498             return -1;
3499 
3500         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
3501                    "block.%zu.name", i);
3502         if (virTypedParamsAddString(&record->params,
3503                                     &record->nparams,
3504                                     maxparams,
3505                                     param_name,
3506                                     disk->dst) < 0)
3507             return -1;
3508 
3509         if (virStorageSourceIsLocalStorage(disk->src) && disk->src->path) {
3510             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
3511                        "block.%zu.path", i);
3512             if (virTypedParamsAddString(&record->params,
3513                                         &record->nparams,
3514                                         maxparams,
3515                                         param_name,
3516                                         disk->src->path) < 0)
3517                 return -1;
3518         }
3519 
3520         VZ_ADD_STAT_PARAM_UUL("block", rd_req, "rd.reqs");
3521         VZ_ADD_STAT_PARAM_UUL("block", rd_bytes, "rd.bytes");
3522         VZ_ADD_STAT_PARAM_UUL("block", wr_req, "wr.reqs");
3523         VZ_ADD_STAT_PARAM_UUL("block", wr_bytes, "wr.bytes");
3524 
3525         if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
3526             g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
3527                        "block.%zu.capacity", i);
3528             if (virTypedParamsAddULLong(&record->params,
3529                                         &record->nparams,
3530                                         maxparams,
3531                                         param_name,
3532                                         disk->src->capacity) < 0)
3533                 return -1;
3534         }
3535 
3536     }
3537 
3538     return 0;
3539 }
3540 
3541 static int
vzDomainGetNetStats(virDomainObj * dom,virDomainStatsRecordPtr record,int * maxparams)3542 vzDomainGetNetStats(virDomainObj *dom,
3543                     virDomainStatsRecordPtr record,
3544                     int *maxparams)
3545 {
3546     struct vzDomObj *privdom = dom->privateData;
3547     size_t i;
3548     char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
3549 
3550     if (virTypedParamsAddUInt(&record->params,
3551                               &record->nparams,
3552                               maxparams,
3553                               "net.count",
3554                               dom->def->nnets) < 0)
3555         return -1;
3556 
3557     for (i = 0; i < dom->def->nnets; i++) {
3558         virDomainInterfaceStatsStruct stat;
3559         virDomainNetDef *net = dom->def->nets[i];
3560 
3561         if (prlsdkGetNetStats(privdom->stats, privdom->sdkdom, net->ifname,
3562                               &stat) < 0)
3563             return -1;
3564 
3565         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "net.%zu.name", i);
3566         if (virTypedParamsAddString(&record->params,
3567                                     &record->nparams,
3568                                     maxparams,
3569                                     param_name,
3570                                     net->ifname) < 0)
3571             return -1;
3572 
3573         VZ_ADD_STAT_PARAM_UUL("net", rx_bytes, "rx.bytes");
3574         VZ_ADD_STAT_PARAM_UUL("net", rx_packets, "rx.pkts");
3575         VZ_ADD_STAT_PARAM_UUL("net", tx_bytes, "tx.bytes");
3576         VZ_ADD_STAT_PARAM_UUL("net", tx_packets, "tx.pkts");
3577     }
3578 
3579     return 0;
3580 }
3581 
3582 static int
vzDomainGetVCPUStats(virDomainObj * dom,virDomainStatsRecordPtr record,int * maxparams)3583 vzDomainGetVCPUStats(virDomainObj *dom,
3584                      virDomainStatsRecordPtr record,
3585                      int *maxparams)
3586 {
3587     struct vzDomObj *privdom = dom->privateData;
3588     size_t i;
3589     char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
3590 
3591     if (virTypedParamsAddUInt(&record->params,
3592                               &record->nparams,
3593                               maxparams,
3594                               "vcpu.current",
3595                               virDomainDefGetVcpus(dom->def)) < 0)
3596         return -1;
3597 
3598     if (virTypedParamsAddUInt(&record->params,
3599                               &record->nparams,
3600                               maxparams,
3601                               "vcpu.maximum",
3602                               virDomainDefGetVcpusMax(dom->def)) < 0)
3603         return -1;
3604 
3605     for (i = 0; i < virDomainDefGetVcpusMax(dom->def); i++) {
3606         int state = dom->def->vcpus[i]->online ? VIR_VCPU_RUNNING :
3607                                                  VIR_VCPU_OFFLINE;
3608         unsigned long long time;
3609 
3610         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "vcpu.%zu.state", i);
3611         if (virTypedParamsAddInt(&record->params,
3612                                  &record->nparams,
3613                                  maxparams,
3614                                  param_name,
3615                                  state) < 0)
3616             return -1;
3617 
3618         if (prlsdkGetVcpuStats(privdom->stats, i, &time) < 0)
3619             return -1;
3620 
3621         g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "vcpu.%zu.time", i);
3622         if (virTypedParamsAddULLong(&record->params,
3623                                     &record->nparams,
3624                                     maxparams,
3625                                     param_name,
3626                                     time) < 0)
3627             return -1;
3628     }
3629 
3630     return 0;
3631 }
3632 
3633 static int
vzDomainGetBalloonStats(virDomainObj * dom,virDomainStatsRecordPtr record,int * maxparams)3634 vzDomainGetBalloonStats(virDomainObj *dom,
3635                         virDomainStatsRecordPtr record,
3636                         int *maxparams)
3637 {
3638     struct vzDomObj *privdom = dom->privateData;
3639     virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR];
3640     size_t i;
3641     int n;
3642 
3643     if (virTypedParamsAddULLong(&record->params,
3644                                 &record->nparams,
3645                                 maxparams,
3646                                 "balloon.maximum",
3647                                 virDomainDefGetMemoryTotal(dom->def)) < 0)
3648         return -1;
3649 
3650     if (virTypedParamsAddULLong(&record->params,
3651                                 &record->nparams,
3652                                 maxparams,
3653                                 "balloon.current",
3654                                 virDomainDefGetMemoryTotal(dom->def)) < 0)
3655         return -1;
3656 
3657     n = prlsdkGetMemoryStats(privdom->stats, stats, VIR_DOMAIN_MEMORY_STAT_NR);
3658     if (n < 0)
3659         return -1;
3660 
3661 #define STORE_MEM_RECORD(TAG, NAME) \
3662     if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ ##TAG) \
3663         if (virTypedParamsAddULLong(&record->params, \
3664                                     &record->nparams, \
3665                                     maxparams, \
3666                                     "balloon." NAME, \
3667                                     stats[i].val) < 0) \
3668             return -1;
3669 
3670     for (i = 0; i < n; i++) {
3671         STORE_MEM_RECORD(SWAP_IN, "swap_in")
3672         STORE_MEM_RECORD(SWAP_OUT, "swap_out")
3673         STORE_MEM_RECORD(MAJOR_FAULT, "major_fault")
3674         STORE_MEM_RECORD(MINOR_FAULT, "minor_fault")
3675         STORE_MEM_RECORD(AVAILABLE, "available")
3676         STORE_MEM_RECORD(UNUSED, "unused")
3677     }
3678 
3679 #undef STORE_MEM_RECORD
3680 
3681     return 0;
3682 }
3683 
3684 static int
vzDomainGetStateStats(virDomainObj * dom,virDomainStatsRecordPtr record,int * maxparams)3685 vzDomainGetStateStats(virDomainObj *dom,
3686                       virDomainStatsRecordPtr record,
3687                       int *maxparams)
3688 {
3689     if (virTypedParamsAddInt(&record->params,
3690                              &record->nparams,
3691                              maxparams,
3692                              "state.state",
3693                              dom->state.state) < 0)
3694         return -1;
3695 
3696     if (virTypedParamsAddInt(&record->params,
3697                              &record->nparams,
3698                              maxparams,
3699                              "state.reason",
3700                              dom->state.reason) < 0)
3701         return -1;
3702 
3703     return 0;
3704 }
3705 
3706 static virDomainStatsRecordPtr
vzDomainGetAllStats(virConnectPtr conn,virDomainObj * dom)3707 vzDomainGetAllStats(virConnectPtr conn,
3708                     virDomainObj *dom)
3709 {
3710     virDomainStatsRecordPtr stat;
3711     int maxparams = 0;
3712 
3713     stat = g_new0(virDomainStatsRecord, 1);
3714 
3715     if (vzDomainGetStateStats(dom, stat, &maxparams) < 0)
3716         goto error;
3717 
3718     if (vzDomainGetBlockStats(dom, stat, &maxparams) < 0)
3719         goto error;
3720 
3721     if (vzDomainGetNetStats(dom, stat, &maxparams) < 0)
3722         goto error;
3723 
3724     if (vzDomainGetVCPUStats(dom, stat, &maxparams) < 0)
3725         goto error;
3726 
3727     if (vzDomainGetBalloonStats(dom, stat, &maxparams) < 0)
3728         goto error;
3729 
3730     if (!(stat->dom = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id)))
3731         goto error;
3732 
3733     return stat;
3734 
3735  error:
3736     virTypedParamsFree(stat->params, stat->nparams);
3737     virObjectUnref(stat->dom);
3738     VIR_FREE(stat);
3739     return NULL;
3740 }
3741 
3742 static int
vzConnectGetAllDomainStats(virConnectPtr conn,virDomainPtr * domains,unsigned int ndomains,unsigned int stats,virDomainStatsRecordPtr ** retStats,unsigned int flags)3743 vzConnectGetAllDomainStats(virConnectPtr conn,
3744                            virDomainPtr *domains,
3745                            unsigned int ndomains,
3746                            unsigned int stats,
3747                            virDomainStatsRecordPtr **retStats,
3748                            unsigned int flags)
3749 {
3750     struct _vzConn *privconn = conn->privateData;
3751     struct _vzDriver *driver = privconn->driver;
3752     unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
3753                                    VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
3754                                    VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
3755     unsigned int supported = VIR_DOMAIN_STATS_STATE |
3756                              VIR_DOMAIN_STATS_VCPU |
3757                              VIR_DOMAIN_STATS_INTERFACE |
3758                              VIR_DOMAIN_STATS_BALLOON |
3759                              VIR_DOMAIN_STATS_BLOCK;
3760     virDomainObj **doms = NULL;
3761     size_t ndoms;
3762     virDomainStatsRecordPtr *tmpstats = NULL;
3763     int nstats = 0;
3764     int ret = -1;
3765     size_t i;
3766 
3767     virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
3768                   VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
3769                   VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE |
3770                   VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1);
3771 
3772     if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
3773         return -1;
3774 
3775     if (!stats) {
3776         stats = supported;
3777     } else if ((flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS) &&
3778                (stats & ~supported)) {
3779         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
3780                        _("Stats types bits 0x%x are not supported by this daemon"),
3781                        stats & ~supported);
3782         return -1;
3783     }
3784 
3785     if (ndomains) {
3786         if (virDomainObjListConvert(driver->domains, conn, domains, ndomains, &doms,
3787                                     &ndoms, virConnectGetAllDomainStatsCheckACL,
3788                                     lflags, true) < 0)
3789             return -1;
3790     } else {
3791         if (virDomainObjListCollect(driver->domains, conn, &doms, &ndoms,
3792                                     virConnectGetAllDomainStatsCheckACL,
3793                                     lflags) < 0)
3794             return -1;
3795     }
3796 
3797     tmpstats = g_new0(virDomainStatsRecordPtr, ndoms + 1);
3798 
3799     for (i = 0; i < ndoms; i++) {
3800         virDomainStatsRecordPtr tmp;
3801         virDomainObj *dom = doms[i];
3802 
3803         virObjectLock(dom);
3804         tmp = vzDomainGetAllStats(conn, dom);
3805         virObjectUnlock(dom);
3806 
3807         if (!tmp)
3808             goto cleanup;
3809 
3810         tmpstats[nstats++] = tmp;
3811     }
3812 
3813     *retStats = g_steal_pointer(&tmpstats);
3814     ret = nstats;
3815 
3816  cleanup:
3817     virDomainStatsRecordListFree(tmpstats);
3818     virObjectListFreeCount(doms, ndoms);
3819 
3820     return ret;
3821 }
3822 
3823 #undef VZ_ADD_STAT_PARAM_UUL
3824 
3825 static int
vzDomainAbortJob(virDomainPtr domain)3826 vzDomainAbortJob(virDomainPtr domain)
3827 {
3828     virDomainObj *dom;
3829     int ret = -1;
3830 
3831     if (!(dom = vzDomObjFromDomain(domain)))
3832         return -1;
3833 
3834     if (virDomainAbortJobEnsureACL(domain->conn, dom->def) < 0)
3835         goto cleanup;
3836 
3837     ret = prlsdkCancelJob(dom);
3838 
3839  cleanup:
3840     virDomainObjEndAPI(&dom);
3841 
3842     return ret;
3843 }
3844 
3845 static int
vzDomainReset(virDomainPtr domain,unsigned int flags)3846 vzDomainReset(virDomainPtr domain, unsigned int flags)
3847 {
3848     virDomainObj *dom = NULL;
3849     int ret = -1;
3850     bool job = false;
3851 
3852     virCheckFlags(0, -1);
3853 
3854     if (!(dom = vzDomObjFromDomain(domain)))
3855         return -1;
3856 
3857     if (virDomainResetEnsureACL(domain->conn, dom->def) < 0)
3858         goto cleanup;
3859 
3860     if (vzDomainObjBeginJob(dom) < 0)
3861         goto cleanup;
3862     job = true;
3863 
3864     if (vzEnsureDomainExists(dom) < 0)
3865         goto cleanup;
3866 
3867     ret = prlsdkReset(dom);
3868 
3869  cleanup:
3870     if (job)
3871         vzDomainObjEndJob(dom);
3872     virDomainObjEndAPI(&dom);
3873     return ret;
3874 }
3875 
vzDomainSetVcpusFlags(virDomainPtr domain,unsigned int nvcpus,unsigned int flags)3876 static int vzDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
3877                                  unsigned int flags)
3878 {
3879     virDomainObj *dom = NULL;
3880     int ret = -1;
3881     bool job = false;
3882 
3883     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
3884                   VIR_DOMAIN_AFFECT_CONFIG, -1);
3885 
3886     if (!(dom = vzDomObjFromDomain(domain)))
3887         goto cleanup;
3888 
3889     if (vzCheckConfigUpdateFlags(dom, &flags) < 0)
3890         goto cleanup;
3891 
3892     if (virDomainSetVcpusFlagsEnsureACL(domain->conn, dom->def, flags) < 0)
3893         goto cleanup;
3894 
3895     if (vzDomainObjBeginJob(dom) < 0)
3896         goto cleanup;
3897     job = true;
3898 
3899     if (vzEnsureDomainExists(dom) < 0)
3900         goto cleanup;
3901 
3902     ret = prlsdkSetCpuCount(dom, nvcpus);
3903 
3904  cleanup:
3905     if (job)
3906         vzDomainObjEndJob(dom);
3907     virDomainObjEndAPI(&dom);
3908     return ret;
3909 }
3910 
vzDomainSetVcpus(virDomainPtr dom,unsigned int nvcpus)3911 static int vzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
3912 {
3913     return vzDomainSetVcpusFlags(dom, nvcpus,
3914                                  VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);
3915 }
3916 static int
vzDomainBlockResize(virDomainPtr domain,const char * path,unsigned long long size,unsigned int flags)3917 vzDomainBlockResize(virDomainPtr domain,
3918                     const char *path,
3919                     unsigned long long size,
3920                     unsigned int flags)
3921 {
3922     virDomainObj *dom = NULL;
3923     virDomainDiskDef *disk = NULL;
3924     int ret = -1;
3925     bool job = false;
3926 
3927     virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
3928 
3929     if (!(dom = vzDomObjFromDomain(domain)))
3930         goto cleanup;
3931 
3932     if (virDomainBlockResizeEnsureACL(domain->conn, dom->def) < 0)
3933         goto cleanup;
3934 
3935     if (path[0] == '\0') {
3936         virReportError(VIR_ERR_INVALID_ARG,
3937                        "%s", _("empty path"));
3938         goto cleanup;
3939     }
3940 
3941     /* sdk wants Mb */
3942     if (flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES)
3943         size /= 1024;
3944     size /= 1024;
3945 
3946     if (vzDomainObjBeginJob(dom) < 0)
3947         goto cleanup;
3948     job = true;
3949 
3950     if (vzEnsureDomainExists(dom) < 0)
3951         goto cleanup;
3952 
3953     if (virDomainObjCheckActive(dom) < 0)
3954         goto cleanup;
3955 
3956     if (!(disk = virDomainDiskByName(dom->def, path, false))) {
3957         virReportError(VIR_ERR_INVALID_ARG,
3958                        _("invalid path: %s"), path);
3959         goto cleanup;
3960     }
3961 
3962     ret = prlsdkResizeImage(dom, disk, size);
3963 
3964  cleanup:
3965     if (job)
3966         vzDomainObjEndJob(dom);
3967     virDomainObjEndAPI(&dom);
3968     return ret;
3969 }
3970 
3971 static virHypervisorDriver vzHypervisorDriver = {
3972     .name = "vz",
3973     .connectOpen = vzConnectOpen,            /* 0.10.0 */
3974     .connectClose = vzConnectClose,          /* 0.10.0 */
3975     .connectGetVersion = vzConnectGetVersion,   /* 0.10.0 */
3976     .connectGetHostname = vzConnectGetHostname,      /* 0.10.0 */
3977     .connectGetSysinfo = vzConnectGetSysinfo, /* 1.3.4 */
3978     .connectGetMaxVcpus = vzConnectGetMaxVcpus, /* 1.2.21 */
3979     .nodeGetInfo = vzNodeGetInfo,      /* 0.10.0 */
3980     .nodeGetCPUStats = vzNodeGetCPUStats,      /* 1.2.21 */
3981     .nodeGetMemoryStats = vzNodeGetMemoryStats, /* 1.2.21 */
3982     .nodeGetCellsFreeMemory = vzNodeGetCellsFreeMemory, /* 1.2.21 */
3983     .nodeGetFreeMemory = vzNodeGetFreeMemory, /* 1.2.21 */
3984     .connectGetCapabilities = vzConnectGetCapabilities,      /* 0.10.0 */
3985     .connectBaselineCPU = vzConnectBaselineCPU, /* 1.2.6 */
3986     .connectListDomains = vzConnectListDomains,      /* 0.10.0 */
3987     .connectNumOfDomains = vzConnectNumOfDomains,    /* 0.10.0 */
3988     .connectListDefinedDomains = vzConnectListDefinedDomains,        /* 0.10.0 */
3989     .connectNumOfDefinedDomains = vzConnectNumOfDefinedDomains,      /* 0.10.0 */
3990     .connectListAllDomains = vzConnectListAllDomains, /* 0.10.0 */
3991     .domainLookupByID = vzDomainLookupByID,    /* 0.10.0 */
3992     .domainLookupByUUID = vzDomainLookupByUUID,        /* 0.10.0 */
3993     .domainLookupByName = vzDomainLookupByName,        /* 0.10.0 */
3994     .domainGetOSType = vzDomainGetOSType,    /* 0.10.0 */
3995     .domainGetInfo = vzDomainGetInfo,  /* 0.10.0 */
3996     .domainGetState = vzDomainGetState,        /* 0.10.0 */
3997     .domainGetXMLDesc = vzDomainGetXMLDesc,    /* 0.10.0 */
3998     .domainIsPersistent = vzDomainIsPersistent,        /* 0.10.0 */
3999     .domainGetAutostart = vzDomainGetAutostart,        /* 0.10.0 */
4000     .domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
4001     .domainSuspend = vzDomainSuspend,    /* 0.10.0 */
4002     .domainResume = vzDomainResume,    /* 0.10.0 */
4003     .domainDestroy = vzDomainDestroy,  /* 0.10.0 */
4004     .domainDestroyFlags = vzDomainDestroyFlags,  /* 2.2.0 */
4005     .domainShutdown = vzDomainShutdown, /* 0.10.0 */
4006     .domainShutdownFlags = vzDomainShutdownFlags, /* 2.2.0 */
4007     .domainCreate = vzDomainCreate,    /* 0.10.0 */
4008     .domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
4009     .domainReboot = vzDomainReboot, /* 1.3.0 */
4010     .domainDefineXML = vzDomainDefineXML,      /* 0.10.0 */
4011     .domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */
4012     .domainUndefine = vzDomainUndefine, /* 1.2.10 */
4013     .domainUndefineFlags = vzDomainUndefineFlags, /* 1.2.10 */
4014     .domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
4015     .domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
4016     .domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
4017     .domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
4018     .domainIsActive = vzDomainIsActive, /* 1.2.10 */
4019     .domainIsUpdated = vzDomainIsUpdated,     /* 1.2.21 */
4020     .domainSetVcpus = vzDomainSetVcpus, /* 3.3.0 */
4021     .domainSetVcpusFlags = vzDomainSetVcpusFlags, /* 3.3.0 */
4022     .domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
4023     .domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
4024     .domainSetUserPassword = vzDomainSetUserPassword, /* 2.0.0 */
4025     .connectDomainEventRegisterAny = vzConnectDomainEventRegisterAny, /* 1.2.10 */
4026     .connectDomainEventDeregisterAny = vzConnectDomainEventDeregisterAny, /* 1.2.10 */
4027     .nodeGetCPUMap = vzNodeGetCPUMap, /* 1.2.8 */
4028     .connectIsEncrypted = vzConnectIsEncrypted, /* 1.2.5 */
4029     .connectIsSecure = vzConnectIsSecure, /* 1.2.5 */
4030     .connectIsAlive = vzConnectIsAlive, /* 1.2.5 */
4031     .domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
4032     .domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
4033     .domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
4034     .domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
4035     .domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
4036     .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
4037     .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
4038     .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
4039     .connectRegisterCloseCallback = vzConnectRegisterCloseCallback, /* 1.3.2 */
4040     .connectUnregisterCloseCallback = vzConnectUnregisterCloseCallback, /* 1.3.2 */
4041     .domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
4042     .domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
4043     .domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
4044     .domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
4045     .domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
4046     .domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
4047     .domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
4048     .domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
4049     .domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
4050     .domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
4051     .domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
4052     .domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
4053     .domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
4054     .domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
4055     .domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
4056     .domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */
4057     .domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
4058     .domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */
4059     .connectSupportsFeature = vzConnectSupportsFeature, /* 1.3.5 */
4060     .domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
4061     .domainMigratePrepare3Params = vzDomainMigratePrepare3Params, /* 1.3.5 */
4062     .domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */
4063     .domainMigrateFinish3Params = vzDomainMigrateFinish3Params, /* 1.3.5 */
4064     .domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
4065     .domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
4066     .domainGetJobInfo = vzDomainGetJobInfo, /* 2.2.0 */
4067     .domainGetJobStats = vzDomainGetJobStats, /* 2.2.0 */
4068     .connectGetAllDomainStats = vzConnectGetAllDomainStats, /* 3.1.0 */
4069     .domainAbortJob = vzDomainAbortJob, /* 3.1.0 */
4070     .domainReset = vzDomainReset, /* 3.1.0 */
4071     .domainBlockResize = vzDomainBlockResize, /* 3.3.0 */
4072 };
4073 
4074 static virConnectDriver vzConnectDriver = {
4075     .localOnly = true,
4076     .uriSchemes = (const char *[]){ "vz", NULL },
4077     .hypervisorDriver = &vzHypervisorDriver,
4078 };
4079 
4080 static int
vzStateCleanup(void)4081 vzStateCleanup(void)
4082 {
4083     if (vz_driver_privileged) {
4084         virObjectUnref(vz_driver);
4085         vz_driver = NULL;
4086         if (vz_driver_lock_fd != -1)
4087             virPidFileRelease(VZ_STATEDIR, "driver", vz_driver_lock_fd);
4088         virMutexDestroy(&vz_driver_lock);
4089         prlsdkDeinit();
4090     }
4091     return 0;
4092 }
4093 
4094 static int
vzStateInitialize(bool privileged,const char * root,virStateInhibitCallback callback G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)4095 vzStateInitialize(bool privileged,
4096                   const char *root,
4097                   virStateInhibitCallback callback G_GNUC_UNUSED,
4098                   void *opaque G_GNUC_UNUSED)
4099 {
4100     if (!privileged)
4101         return VIR_DRV_STATE_INIT_SKIPPED;
4102 
4103     if (root != NULL) {
4104         virReportError(VIR_ERR_INVALID_ARG, "%s",
4105                        _("Driver does not support embedded mode"));
4106         return -1;
4107     }
4108 
4109     vz_driver_privileged = privileged;
4110 
4111     if (g_mkdir_with_parents(VZ_STATEDIR, S_IRWXU) < 0) {
4112         virReportSystemError(errno, _("cannot create state directory '%s'"),
4113                              VZ_STATEDIR);
4114         return VIR_DRV_STATE_INIT_ERROR;
4115     }
4116 
4117     if ((vz_driver_lock_fd =
4118          virPidFileAcquire(VZ_STATEDIR, "driver", false, getpid())) < 0)
4119         return VIR_DRV_STATE_INIT_ERROR;
4120 
4121     if (prlsdkInit() < 0) {
4122         VIR_DEBUG("%s", _("Can't initialize Parallels SDK"));
4123         return VIR_DRV_STATE_INIT_ERROR;
4124     }
4125 
4126     if (virMutexInit(&vz_driver_lock) < 0)
4127         goto error;
4128 
4129     /* Failing to create driver here is not fatal and only means
4130      * that next driver client will try once more when connecting */
4131     vz_driver = vzDriverObjNew();
4132     return VIR_DRV_STATE_INIT_COMPLETE;
4133 
4134  error:
4135     vzStateCleanup();
4136     return VIR_DRV_STATE_INIT_ERROR;
4137 }
4138 
4139 static virStateDriver vzStateDriver = {
4140     .name = "vz",
4141     .stateInitialize = vzStateInitialize,
4142     .stateCleanup = vzStateCleanup,
4143 };
4144 
4145 /* Parallels domain type backward compatibility */
4146 static virHypervisorDriver parallelsHypervisorDriver;
4147 static virConnectDriver parallelsConnectDriver = {
4148     .localOnly = true,
4149     .uriSchemes = (const char *[]){ "parallels", NULL },
4150     .hypervisorDriver = &parallelsHypervisorDriver,
4151 };
4152 
4153 /**
4154  * vzRegister:
4155  *
4156  * Registers the vz driver
4157  */
4158 int
vzRegister(void)4159 vzRegister(void)
4160 {
4161     char *prlctl_path;
4162 
4163     prlctl_path = virFindFileInPath(PRLCTL);
4164     if (!prlctl_path) {
4165         VIR_DEBUG("%s", _("Can't find prlctl command in the PATH env"));
4166         return 0;
4167     }
4168 
4169     VIR_FREE(prlctl_path);
4170 
4171     /* Backward compatibility with Parallels domain type */
4172     parallelsHypervisorDriver = vzHypervisorDriver;
4173     parallelsHypervisorDriver.name = "Parallels";
4174     if (virRegisterConnectDriver(&parallelsConnectDriver, true) < 0)
4175         return -1;
4176 
4177     if (virRegisterConnectDriver(&vzConnectDriver, true) < 0)
4178         return -1;
4179 
4180     if (virRegisterStateDriver(&vzStateDriver) < 0)
4181         return -1;
4182 
4183     return 0;
4184 }
4185