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(¶ms, 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(¶ms, &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(¶ms, &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(¶ms, &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 = ¶llelsHypervisorDriver,
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(¶llelsConnectDriver, 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