1 /*
2 * vz_sdk.c: core driver functions for managing
3 * Parallels Cloud Server hosts
4 *
5 * Copyright (C) 2014 Parallels, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include <config.h>
24 #include <stdarg.h>
25
26 #include "virerror.h"
27 #include "viralloc.h"
28 #include "virstring.h"
29 #include "virlog.h"
30 #include "datatypes.h"
31 #include "domain_conf.h"
32 #include "storage_conf.h"
33 #include "virtime.h"
34 #include "virhostcpu.h"
35 #include "virsocketaddr.h"
36 #include "virutil.h"
37
38 #include "vz_sdk.h"
39
40 #define VIR_FROM_THIS VIR_FROM_PARALLELS
41 #define JOB_INFINIT_WAIT_TIMEOUT UINT_MAX
42
43 static int
44 prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid);
45 static void
46 prlsdkConvertError(PRL_RESULT pret);
47 static PRL_RESULT
48 prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque);
49
50 VIR_LOG_INIT("parallels.sdk");
51
52 static PRL_HANDLE
53 prlsdkFindNetByMAC(PRL_HANDLE sdkdom, virMacAddr *mac);
54 static PRL_HANDLE
55 prlsdkGetDisk(PRL_HANDLE sdkdom, virDomainDiskDef *disk);
56 static bool
57 prlsdkInBootList(PRL_HANDLE sdkdom,
58 PRL_HANDLE sdktargetdev);
59
60 /*
61 * Log error description
62 */
63 static void
logPrlErrorHelper(PRL_RESULT err,const char * filename,const char * funcname,size_t linenr)64 logPrlErrorHelper(PRL_RESULT err, const char *filename,
65 const char *funcname, size_t linenr)
66 {
67 char *msg1 = NULL, *msg2 = NULL;
68 PRL_UINT32 len = 0;
69
70 /* Get required buffer length */
71 PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, NULL, &len);
72
73 msg1 = g_new0(char, len);
74
75 /* get short error description */
76 PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, msg1, &len);
77
78 PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, NULL, &len);
79
80 msg2 = g_new0(char, len);
81
82 /* get long error description */
83 PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, msg2, &len);
84
85 virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
86 filename, funcname, linenr,
87 _("%s %s"), msg1, msg2);
88
89 VIR_FREE(msg1);
90 VIR_FREE(msg2);
91 }
92
93 #define logPrlError(code) \
94 logPrlErrorHelper(code, __FILE__, \
95 __FUNCTION__, __LINE__)
96
97 #define prlsdkCheckRetGoto(ret, label) \
98 do { \
99 if (PRL_FAILED(ret)) { \
100 logPrlError(ret); \
101 goto label; \
102 } \
103 } while (0)
104
105 #define prlsdkCheckRetExit(ret, code) \
106 do { \
107 if (PRL_FAILED(ret)) { \
108 logPrlError(ret); \
109 return code; \
110 } \
111 } while (0)
112
113 static void
logPrlEventErrorHelper(PRL_HANDLE event,const char * filename,const char * funcname,size_t linenr)114 logPrlEventErrorHelper(PRL_HANDLE event, const char *filename,
115 const char *funcname, size_t linenr)
116 {
117 char *msg1 = NULL, *msg2 = NULL;
118 PRL_UINT32 len = 0;
119
120 PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, NULL, &len);
121
122 msg1 = g_new0(char, len);
123
124 PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, msg1, &len);
125
126 PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, NULL, &len);
127
128 msg2 = g_new0(char, len);
129
130 PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, msg2, &len);
131
132 virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
133 filename, funcname, linenr,
134 _("%s %s"), msg1, msg2);
135 VIR_FREE(msg1);
136 VIR_FREE(msg2);
137 }
138
139 static PRL_RESULT
getJobResultHelper(PRL_HANDLE job,unsigned int timeout,PRL_HANDLE * result,const char * filename,const char * funcname,size_t linenr)140 getJobResultHelper(PRL_HANDLE job, unsigned int timeout, PRL_HANDLE *result,
141 const char *filename, const char *funcname,
142 size_t linenr)
143 {
144 PRL_RESULT ret, retCode;
145
146 if (PRL_FAILED(ret = PrlJob_Wait(job, timeout))) {
147 logPrlErrorHelper(ret, filename, funcname, linenr);
148 goto cleanup;
149 }
150
151 if (PRL_FAILED(ret = PrlJob_GetRetCode(job, &retCode))) {
152 logPrlErrorHelper(ret, filename, funcname, linenr);
153 goto cleanup;
154 }
155
156 if (retCode) {
157 PRL_HANDLE err_handle;
158
159 ret = retCode;
160
161 /* Sometimes it's possible to get additional error info. */
162 if (PRL_FAILED(retCode = PrlJob_GetError(job, &err_handle))) {
163 logPrlErrorHelper(ret, filename, funcname, linenr);
164 goto cleanup;
165 }
166
167 if (PRL_FAILED(retCode = PrlEvent_GetErrCode(err_handle, &retCode))) {
168 logPrlErrorHelper(ret, filename, funcname, linenr);
169 if (PRL_ERR_NO_DATA != retCode)
170 logPrlError(retCode);
171 PrlHandle_Free(err_handle);
172 goto cleanup;
173 }
174
175 logPrlEventErrorHelper(err_handle, filename, funcname, linenr);
176
177 PrlHandle_Free(err_handle);
178 } else {
179 ret = PrlJob_GetResult(job, result);
180 if (PRL_FAILED(ret)) {
181 logPrlErrorHelper(ret, filename, funcname, linenr);
182 PrlHandle_Free(*result);
183 *result = NULL;
184 goto cleanup;
185 }
186
187 ret = PRL_ERR_SUCCESS;
188 }
189
190 cleanup:
191 PrlHandle_Free(job);
192 return ret;
193 }
194
195 #define getJobResult(job, result) \
196 getJobResultHelper(job, JOB_INFINIT_WAIT_TIMEOUT, \
197 result, __FILE__, __FUNCTION__, __LINE__)
198
199 static PRL_RESULT
getDomainJobResultHelper(PRL_HANDLE job,virDomainObj * dom,unsigned int timeout,PRL_HANDLE * result,const char * filename,const char * funcname,size_t linenr)200 getDomainJobResultHelper(PRL_HANDLE job, virDomainObj *dom,
201 unsigned int timeout, PRL_HANDLE *result,
202 const char *filename, const char *funcname,
203 size_t linenr)
204 {
205 PRL_RESULT pret;
206
207 if (dom)
208 virObjectUnlock(dom);
209 pret = getJobResultHelper(job, timeout, result, filename, funcname, linenr);
210 if (dom)
211 virObjectLock(dom);
212
213 return pret;
214 }
215
216 #define getDomainJobResult(job, dom, result) \
217 getDomainJobResultHelper(job, dom, JOB_INFINIT_WAIT_TIMEOUT, \
218 result, __FILE__, __FUNCTION__, __LINE__)
219
220 static PRL_RESULT
waitJobHelper(PRL_HANDLE job,unsigned int timeout,const char * filename,const char * funcname,size_t linenr)221 waitJobHelper(PRL_HANDLE job, unsigned int timeout,
222 const char *filename, const char *funcname,
223 size_t linenr)
224 {
225 PRL_HANDLE result = PRL_INVALID_HANDLE;
226 PRL_RESULT ret;
227
228 ret = getJobResultHelper(job, timeout, &result,
229 filename, funcname, linenr);
230 PrlHandle_Free(result);
231 return ret;
232 }
233
234 #define waitJob(job) \
235 waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT, __FILE__, \
236 __FUNCTION__, __LINE__)
237
238 static PRL_RESULT
waitDomainJobHelper(PRL_HANDLE job,virDomainObj * dom,unsigned int timeout,const char * filename,const char * funcname,size_t linenr)239 waitDomainJobHelper(PRL_HANDLE job, virDomainObj *dom, unsigned int timeout,
240 const char *filename, const char *funcname,
241 size_t linenr)
242 {
243 struct vzDomObj *pdom = dom->privateData;
244 PRL_RESULT ret;
245
246 if (pdom->job.cancelled) {
247 virReportError(VIR_ERR_OPERATION_ABORTED, "%s",
248 _("Operation cancelled by client"));
249 return PRL_ERR_FAILURE;
250 }
251
252 pdom->job.sdkJob = job;
253
254 virObjectUnlock(dom);
255 ret = waitJobHelper(job, timeout, filename, funcname, linenr);
256 virObjectLock(dom);
257
258 pdom->job.sdkJob = NULL;
259
260 return ret;
261 }
262
263 #define waitDomainJob(job, dom) \
264 waitDomainJobHelper(job, dom, JOB_INFINIT_WAIT_TIMEOUT, __FILE__, \
265 __FUNCTION__, __LINE__)
266
267 typedef PRL_RESULT (*prlsdkParamGetterType)(PRL_HANDLE, char*, PRL_UINT32*);
268
269 int
prlsdkCancelJob(virDomainObj * dom)270 prlsdkCancelJob(virDomainObj *dom)
271 {
272 struct vzDomObj *privdom = dom->privateData;
273 PRL_RESULT pret;
274 PRL_HANDLE job;
275
276 if (!privdom->job.active) {
277 virReportError(VIR_ERR_OPERATION_INVALID,
278 "%s", _("no job is active on the domain"));
279 return -1;
280 }
281
282 privdom->job.cancelled = true;
283 job = PrlJob_Cancel(privdom->job.sdkJob);
284
285 virObjectUnlock(dom);
286 pret = waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT,
287 __FILE__, __FUNCTION__, __LINE__);
288 virObjectLock(dom);
289
290 return PRL_FAILED(pret) ? -1 : 0;
291 }
292
293 static char*
prlsdkGetStringParamVar(prlsdkParamGetterType getter,PRL_HANDLE handle)294 prlsdkGetStringParamVar(prlsdkParamGetterType getter, PRL_HANDLE handle)
295 {
296 PRL_RESULT pret;
297 PRL_UINT32 buflen = 0;
298 char *str = NULL;
299
300 pret = getter(handle, NULL, &buflen);
301 prlsdkCheckRetGoto(pret, error);
302
303 str = g_new0(char, buflen);
304
305 pret = getter(handle, str, &buflen);
306 prlsdkCheckRetGoto(pret, error);
307
308 return str;
309
310 error:
311 VIR_FREE(str);
312 return NULL;
313 }
314
315 static PRL_RESULT
prlsdkGetStringParamBuf(prlsdkParamGetterType getter,PRL_HANDLE handle,char * buf,size_t size)316 prlsdkGetStringParamBuf(prlsdkParamGetterType getter,
317 PRL_HANDLE handle, char *buf, size_t size)
318 {
319 PRL_UINT32 buflen = size;
320 return getter(handle, buf, &buflen);
321 }
322
323 int
prlsdkInit(void)324 prlsdkInit(void)
325 {
326 PRL_RESULT ret;
327
328 /* Disable console output */
329 PrlApi_SwitchConsoleLogging(0);
330
331 ret = PrlApi_InitEx(PARALLELS_API_VER, PAM_SERVER, 0, 0);
332 if (PRL_FAILED(ret)) {
333 logPrlError(ret);
334 return -1;
335 }
336
337 return 0;
338 };
339
340 void
prlsdkDeinit(void)341 prlsdkDeinit(void)
342 {
343 PrlApi_Deinit();
344 };
345
346 int
prlsdkConnect(struct _vzDriver * driver)347 prlsdkConnect(struct _vzDriver *driver)
348 {
349 int ret = -1;
350 PRL_RESULT pret;
351 PRL_HANDLE job = PRL_INVALID_HANDLE;
352 PRL_HANDLE result = PRL_INVALID_HANDLE;
353 PRL_HANDLE response = PRL_INVALID_HANDLE;
354 char session_uuid[VIR_UUID_STRING_BRACED_BUFLEN];
355
356 pret = PrlSrv_Create(&driver->server);
357 prlsdkCheckRetExit(pret, -1);
358
359 job = PrlSrv_LoginLocalEx(driver->server, NULL, 0,
360 PSL_HIGH_SECURITY, PACF_NON_INTERACTIVE_MODE);
361 if (PRL_FAILED(getJobResult(job, &result)))
362 goto destroy;
363
364 pret = PrlResult_GetParam(result, &response);
365 prlsdkCheckRetGoto(pret, logoff);
366
367 pret = prlsdkGetStringParamBuf(PrlLoginResponse_GetSessionUuid,
368 response, session_uuid, sizeof(session_uuid));
369 prlsdkCheckRetGoto(pret, logoff);
370
371 if (prlsdkUUIDParse(session_uuid, driver->session_uuid) < 0)
372 goto logoff;
373
374 pret = PrlSrv_RegEventHandler(driver->server,
375 prlsdkEventsHandler,
376 driver);
377 prlsdkCheckRetGoto(pret, logoff);
378
379 ret = 0;
380
381 cleanup:
382 PrlHandle_Free(result);
383 PrlHandle_Free(response);
384
385 return ret;
386
387 logoff:
388 job = PrlSrv_Logoff(driver->server);
389 waitJob(job);
390
391 destroy:
392 PrlHandle_Free(driver->server);
393 driver->server = PRL_INVALID_HANDLE;
394
395 goto cleanup;
396 }
397
398 void
prlsdkDisconnect(struct _vzDriver * driver)399 prlsdkDisconnect(struct _vzDriver *driver)
400 {
401 PRL_HANDLE job;
402 PRL_RESULT ret;
403
404 if (driver->server == PRL_INVALID_HANDLE)
405 return;
406
407 ret = PrlSrv_UnregEventHandler(driver->server,
408 prlsdkEventsHandler,
409 driver);
410 if (PRL_FAILED(ret))
411 logPrlError(ret);
412
413 job = PrlSrv_Logoff(driver->server);
414 waitJob(job);
415
416 PrlHandle_Free(driver->server);
417 driver->server = PRL_INVALID_HANDLE;
418 }
419
420 static int
prlsdkSdkDomainLookup(struct _vzDriver * driver,const char * id,unsigned int flags,PRL_HANDLE * sdkdom)421 prlsdkSdkDomainLookup(struct _vzDriver *driver,
422 const char *id,
423 unsigned int flags,
424 PRL_HANDLE *sdkdom)
425 {
426 PRL_HANDLE job = PRL_INVALID_HANDLE;
427 PRL_HANDLE result = PRL_INVALID_HANDLE;
428 PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
429 int ret = -1;
430
431 job = PrlSrv_GetVmConfig(driver->server, id, flags);
432 if (PRL_FAILED(getJobResult(job, &result)))
433 goto cleanup;
434
435 pret = PrlResult_GetParamByIndex(result, 0, sdkdom);
436 prlsdkCheckRetGoto(pret, cleanup);
437
438 ret = 0;
439
440 cleanup:
441 PrlHandle_Free(result);
442 return ret;
443 }
444
445 static void
prlsdkUUIDFormat(const unsigned char * uuid,char * uuidstr)446 prlsdkUUIDFormat(const unsigned char *uuid, char *uuidstr)
447 {
448 virUUIDFormat(uuid, uuidstr + 1);
449
450 uuidstr[0] = '{';
451 uuidstr[VIR_UUID_STRING_BUFLEN] = '}';
452 uuidstr[VIR_UUID_STRING_BUFLEN + 1] = '\0';
453 }
454
455 static PRL_HANDLE
prlsdkSdkDomainLookupByUUID(struct _vzDriver * driver,const unsigned char * uuid)456 prlsdkSdkDomainLookupByUUID(struct _vzDriver *driver, const unsigned char *uuid)
457 {
458 char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
459 PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
460
461 prlsdkUUIDFormat(uuid, uuidstr);
462
463 if (prlsdkSdkDomainLookup(driver, uuidstr,
464 PGVC_SEARCH_BY_UUID, &sdkdom) < 0) {
465 virUUIDFormat(uuid, uuidstr);
466 virReportError(VIR_ERR_NO_DOMAIN,
467 _("no domain with matching uuid '%s'"), uuidstr);
468 return PRL_INVALID_HANDLE;
469 }
470
471 return sdkdom;
472 }
473
474 PRL_HANDLE
prlsdkSdkDomainLookupByName(struct _vzDriver * driver,const char * name)475 prlsdkSdkDomainLookupByName(struct _vzDriver *driver, const char *name)
476 {
477 PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
478
479 if (prlsdkSdkDomainLookup(driver, name,
480 PGVC_SEARCH_BY_NAME, &sdkdom) < 0) {
481 virReportError(VIR_ERR_NO_DOMAIN,
482 _("no domain with matching name '%s'"), name);
483 return PRL_INVALID_HANDLE;
484 }
485
486 return sdkdom;
487 }
488
489 static int
prlsdkUUIDParse(const char * uuidstr,unsigned char * uuid)490 prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid)
491 {
492 char *tmp = NULL;
493 int ret = -1;
494
495 virCheckNonNullArgGoto(uuidstr, error);
496 virCheckNonNullArgGoto(uuid, error);
497
498 tmp = g_strdup(uuidstr);
499
500 tmp[strlen(tmp) - 1] = '\0';
501
502 /* trim curly braces */
503 if (virUUIDParse(tmp + 1, uuid) < 0)
504 goto error;
505
506 ret = 0;
507 error:
508 VIR_FREE(tmp);
509 return ret;
510 }
511
512 static int
prlsdkGetDomainState(virDomainObj * dom,PRL_HANDLE sdkdom,VIRTUAL_MACHINE_STATE_PTR vmState)513 prlsdkGetDomainState(virDomainObj *dom, PRL_HANDLE sdkdom, VIRTUAL_MACHINE_STATE_PTR vmState)
514 {
515 PRL_HANDLE job = PRL_INVALID_HANDLE;
516 PRL_HANDLE result = PRL_INVALID_HANDLE;
517 PRL_HANDLE vmInfo = PRL_INVALID_HANDLE;
518 PRL_RESULT pret;
519 int ret = -1;
520
521 job = PrlVm_GetState(sdkdom);
522
523 if (PRL_FAILED(getDomainJobResult(job, dom, &result)))
524 goto cleanup;
525
526 pret = PrlResult_GetParamByIndex(result, 0, &vmInfo);
527 prlsdkCheckRetGoto(pret, cleanup);
528
529 pret = PrlVmInfo_GetState(vmInfo, vmState);
530 prlsdkCheckRetGoto(pret, cleanup);
531
532 ret = 0;
533
534 cleanup:
535 PrlHandle_Free(vmInfo);
536 PrlHandle_Free(result);
537 return ret;
538 }
539
540 static int
prlsdkAddDomainVideoInfoCt(virDomainDef * def,virDomainXMLOption * xmlopt)541 prlsdkAddDomainVideoInfoCt(virDomainDef *def,
542 virDomainXMLOption *xmlopt)
543 {
544 virDomainVideoDef *video = NULL;
545
546 if (def->ngraphics == 0)
547 return 0;
548
549 if (!(video = virDomainVideoDefNew(xmlopt)))
550 return -1;
551
552 video->type = VIR_DOMAIN_VIDEO_TYPE_PARALLELS;
553 video->vram = 0;
554
555 VIR_APPEND_ELEMENT(def->videos, def->nvideos, video);
556
557 return 0;
558 }
559
560 static int
prlsdkAddDomainVideoInfoVm(PRL_HANDLE sdkdom,virDomainDef * def)561 prlsdkAddDomainVideoInfoVm(PRL_HANDLE sdkdom, virDomainDef *def)
562 {
563 virDomainVideoDef *video = NULL;
564 virDomainVideoAccelDef *accel = NULL;
565 PRL_RESULT ret;
566 PRL_UINT32 videoRam;
567
568 /* video info */
569 ret = PrlVmCfg_GetVideoRamSize(sdkdom, &videoRam);
570 prlsdkCheckRetGoto(ret, error);
571
572 video = g_new0(virDomainVideoDef, 1);
573 accel = g_new0(virDomainVideoAccelDef, 1);
574
575 VIR_APPEND_ELEMENT_COPY(def->videos, def->nvideos, video);
576
577 video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
578 video->vram = videoRam << 10; /* from mbibytes to kbibytes */
579 video->heads = 1;
580 video->accel = accel;
581
582 return 0;
583 }
584
585 static int
prlsdkGetDiskId(PRL_HANDLE disk,virDomainDiskBus * bus,char ** dst)586 prlsdkGetDiskId(PRL_HANDLE disk, virDomainDiskBus *bus, char **dst)
587 {
588 PRL_RESULT pret;
589 PRL_UINT32 pos, ifType;
590
591 pret = PrlVmDev_GetStackIndex(disk, &pos);
592 prlsdkCheckRetExit(pret, -1);
593
594 pret = PrlVmDev_GetIfaceType(disk, &ifType);
595 prlsdkCheckRetExit(pret, -1);
596
597 switch (ifType) {
598 case PMS_IDE_DEVICE:
599 *bus = VIR_DOMAIN_DISK_BUS_IDE;
600 *dst = virIndexToDiskName(pos, "hd");
601 break;
602 case PMS_SCSI_DEVICE:
603 case PMS_UNKNOWN_DEVICE:
604 *bus = VIR_DOMAIN_DISK_BUS_SCSI;
605 *dst = virIndexToDiskName(pos, "sd");
606 break;
607 case PMS_SATA_DEVICE:
608 *bus = VIR_DOMAIN_DISK_BUS_SATA;
609 *dst = virIndexToDiskName(pos, "sd");
610 break;
611 default:
612 virReportError(VIR_ERR_INTERNAL_ERROR,
613 _("Unknown disk bus: %X"), ifType);
614 return -1;
615 }
616
617 return 0;
618 }
619
620 static int
prlsdkGetDiskInfo(struct _vzDriver * driver,PRL_HANDLE prldisk,virDomainDiskDef * disk,bool isCdrom,bool isCt)621 prlsdkGetDiskInfo(struct _vzDriver *driver,
622 PRL_HANDLE prldisk,
623 virDomainDiskDef *disk,
624 bool isCdrom,
625 bool isCt)
626 {
627 char *buf = NULL;
628 PRL_RESULT pret;
629 PRL_UINT32 emulatedType;
630 PRL_UINT32 size;
631 virDomainDeviceDriveAddress *address;
632 int busIdx, devIdx;
633 int ret = -1;
634
635 pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
636 prlsdkCheckRetGoto(pret, cleanup);
637 if (emulatedType == PDT_USE_IMAGE_FILE) {
638 virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
639 if (isCdrom) {
640 virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
641 } else {
642 if (isCt)
643 virDomainDiskSetFormat(disk, driver->vzCaps.ctDiskFormat);
644 else
645 virDomainDiskSetFormat(disk, driver->vzCaps.vmDiskFormat);
646 }
647 } else {
648 virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
649 virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
650 }
651
652 if (isCdrom) {
653 disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
654 disk->src->readonly = true;
655 } else {
656 disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
657 }
658
659 if (!(buf = prlsdkGetStringParamVar(PrlVmDev_GetFriendlyName, prldisk)))
660 goto cleanup;
661
662 if (*buf != '\0')
663 virDomainDiskSetSource(disk, buf);
664
665 if (prlsdkGetDiskId(prldisk, &disk->bus, &disk->dst) < 0)
666 goto cleanup;
667
668 if (virDiskNameToBusDeviceIndex(disk, &busIdx, &devIdx) < 0)
669 goto cleanup;
670
671 address = &disk->info.addr.drive;
672 address->bus = busIdx;
673 address->target = 0;
674 address->unit = devIdx;
675
676 disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
677
678 if (!isCdrom) {
679 if (!(disk->serial = prlsdkGetStringParamVar(PrlVmDevHd_GetSerialNumber, prldisk)))
680 goto cleanup;
681
682 if (*disk->serial == '\0')
683 VIR_FREE(disk->serial);
684 }
685
686 virDomainDiskSetDriver(disk, "vz");
687
688 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
689 pret = PrlVmDevHd_GetDiskSize(prldisk, &size);
690 prlsdkCheckRetGoto(pret, cleanup);
691 /* from MiB to bytes */
692 disk->src->capacity = ((unsigned long long)size) << 20;
693 }
694
695 ret = 0;
696
697 cleanup:
698 VIR_FREE(buf);
699 return ret;
700 }
701
702 static int
prlsdkGetFSInfo(PRL_HANDLE prldisk,virDomainFSDef * fs)703 prlsdkGetFSInfo(PRL_HANDLE prldisk,
704 virDomainFSDef *fs)
705 {
706 char *buf = NULL;
707 int ret = -1;
708 g_auto(GStrv) matches = NULL;
709 virURI *uri = NULL;
710
711 fs->type = VIR_DOMAIN_FS_TYPE_FILE;
712 fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP;
713 fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
714 fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
715 fs->format = VIR_STORAGE_FILE_PLOOP;
716
717 fs->readonly = false;
718 fs->symlinksResolved = false;
719
720 if (!(buf = prlsdkGetStringParamVar(PrlVmDevHd_GetStorageURL, prldisk)))
721 goto cleanup;
722
723 if (!virStringIsEmpty(buf)) {
724 if (!(uri = virURIParse(buf)))
725 goto cleanup;
726 if (STRNEQ("libvirt", uri->scheme)) {
727 virReportError(VIR_ERR_INTERNAL_ERROR,
728 _("Unknown uri scheme: '%s'"),
729 uri->scheme);
730 goto cleanup;
731 }
732
733 if (!(matches = g_strsplit(uri->path, "/", 0)) ||
734 !matches[0]) {
735 virReportError(VIR_ERR_INTERNAL_ERROR,
736 _("splitting StorageUrl failed %s"), uri->path);
737 goto cleanup;
738 }
739 if (!matches[1]) {
740 virReportError(VIR_ERR_INTERNAL_ERROR,
741 _("can't identify pool in uri %s "), uri->path);
742 goto cleanup;
743 }
744 if (!matches[2]) {
745 virReportError(VIR_ERR_INTERNAL_ERROR,
746 _("can't identify volume in uri %s"), uri->path);
747 goto cleanup;
748 }
749 fs->type = VIR_DOMAIN_FS_TYPE_VOLUME;
750 fs->src->srcpool = g_new0(virStorageSourcePoolDef, 1);
751 fs->src->srcpool->pool = g_strdup(matches[1]);
752 fs->src->srcpool->volume = g_strdup(matches[2]);
753 VIR_FREE(buf);
754 } else {
755 fs->type = VIR_DOMAIN_FS_TYPE_FILE;
756 if (!(buf = prlsdkGetStringParamVar(PrlVmDev_GetImagePath, prldisk)))
757 goto cleanup;
758
759 fs->src->path = g_steal_pointer(&buf);
760 }
761 if (!(buf = prlsdkGetStringParamVar(PrlVmDevHd_GetMountPoint, prldisk)))
762 goto cleanup;
763
764 fs->dst = g_steal_pointer(&buf);
765
766 ret = 0;
767
768 cleanup:
769 VIR_FREE(buf);
770 return ret;
771 }
772
773 static int
prlsdkAddDomainHardDisksInfo(struct _vzDriver * driver,PRL_HANDLE sdkdom,virDomainDef * def)774 prlsdkAddDomainHardDisksInfo(struct _vzDriver *driver, PRL_HANDLE sdkdom, virDomainDef *def)
775 {
776 PRL_RESULT pret;
777 PRL_UINT32 hddCount;
778 PRL_UINT32 i;
779 PRL_HANDLE hdd = PRL_INVALID_HANDLE;
780 virDomainDiskDef *disk = NULL;
781 virDomainFSDef *fs = NULL;
782
783 pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
784 prlsdkCheckRetGoto(pret, error);
785
786 for (i = 0; i < hddCount; ++i) {
787
788 PRL_UINT32 emulatedType;
789
790 pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
791 prlsdkCheckRetGoto(pret, error);
792
793 pret = PrlVmDev_GetEmulatedType(hdd, &emulatedType);
794 prlsdkCheckRetGoto(pret, error);
795
796 if (IS_CT(def) &&
797 prlsdkInBootList(sdkdom, hdd)) {
798
799 if (!(fs = virDomainFSDefNew(NULL)))
800 goto error;
801
802 if (prlsdkGetFSInfo(hdd, fs) < 0)
803 goto error;
804
805 if (virDomainFSInsert(def, fs) < 0)
806 goto error;
807
808 fs = NULL;
809 PrlHandle_Free(hdd);
810 hdd = PRL_INVALID_HANDLE;
811 } else {
812 if (!(disk = virDomainDiskDefNew(NULL)))
813 goto error;
814
815 if (prlsdkGetDiskInfo(driver, hdd, disk, false, IS_CT(def)) < 0)
816 goto error;
817
818 virDomainDiskInsert(def, disk);
819
820 disk = NULL;
821 PrlHandle_Free(hdd);
822 hdd = PRL_INVALID_HANDLE;
823 }
824 }
825
826 return 0;
827
828 error:
829 PrlHandle_Free(hdd);
830 virDomainDiskDefFree(disk);
831 virDomainFSDefFree(fs);
832 return -1;
833 }
834
835 static int
prlsdkAddDomainOpticalDisksInfo(struct _vzDriver * driver,PRL_HANDLE sdkdom,virDomainDef * def)836 prlsdkAddDomainOpticalDisksInfo(struct _vzDriver *driver, PRL_HANDLE sdkdom, virDomainDef *def)
837 {
838 PRL_RESULT pret;
839 PRL_UINT32 cdromsCount;
840 PRL_UINT32 i;
841 PRL_HANDLE cdrom = PRL_INVALID_HANDLE;
842 virDomainDiskDef *disk = NULL;
843
844 pret = PrlVmCfg_GetOpticalDisksCount(sdkdom, &cdromsCount);
845 prlsdkCheckRetGoto(pret, error);
846
847 for (i = 0; i < cdromsCount; ++i) {
848 pret = PrlVmCfg_GetOpticalDisk(sdkdom, i, &cdrom);
849 prlsdkCheckRetGoto(pret, error);
850
851 if (!(disk = virDomainDiskDefNew(NULL)))
852 goto error;
853
854 if (prlsdkGetDiskInfo(driver, cdrom, disk, true, IS_CT(def)) < 0)
855 goto error;
856
857 PrlHandle_Free(cdrom);
858 cdrom = PRL_INVALID_HANDLE;
859
860 virDomainDiskInsert(def, disk);
861 }
862
863 return 0;
864
865 error:
866 PrlHandle_Free(cdrom);
867 virDomainDiskDefFree(disk);
868 return -1;
869 }
870
871 static virNetDevIPAddr *
prlsdkParseNetAddress(char * addr)872 prlsdkParseNetAddress(char *addr)
873 {
874 char *maskstr = NULL;
875 int nbits;
876 virSocketAddr mask;
877 virNetDevIPAddr *ip = NULL;
878 virNetDevIPAddr *ret = NULL;
879
880 if (!(maskstr = strchr(addr, '/')))
881 goto cleanup;
882
883 *maskstr = '\0';
884 ++maskstr;
885
886 ip = g_new0(virNetDevIPAddr, 1);
887
888 if (virSocketAddrParse(&ip->address, addr, AF_UNSPEC) < 0)
889 goto cleanup;
890
891 if (virSocketAddrParse(&mask, maskstr, AF_UNSPEC) < 0)
892 goto cleanup;
893
894 if ((nbits = virSocketAddrGetNumNetmaskBits(&mask)) < 0)
895 goto cleanup;
896 ip->prefix = nbits;
897
898 ret = g_steal_pointer(&ip);
899
900 cleanup:
901 if (!ret)
902 VIR_WARN("cannot parse network address '%s'", addr);
903
904 VIR_FREE(ip);
905 VIR_FREE(addr);
906
907 return ret;
908 }
909
910 static int
prlsdkGetNetAddresses(PRL_HANDLE sdknet,virDomainNetDef * net)911 prlsdkGetNetAddresses(PRL_HANDLE sdknet, virDomainNetDef *net)
912 {
913 int ret = -1;
914 PRL_HANDLE addrlist = PRL_INVALID_HANDLE;
915 PRL_UINT32 num;
916 size_t i;
917 PRL_RESULT pret;
918
919 pret = PrlVmDevNet_GetNetAddresses(sdknet, &addrlist);
920 prlsdkCheckRetGoto(pret, cleanup);
921
922 PrlStrList_GetItemsCount(addrlist, &num);
923 prlsdkCheckRetGoto(pret, cleanup);
924
925 for (i = 0; i < num; ++i) {
926 virNetDevIPAddr *ip = NULL;
927 PRL_UINT32 buflen = 0;
928 char *addr;
929
930 pret = PrlStrList_GetItem(addrlist, i, NULL, &buflen);
931 prlsdkCheckRetGoto(pret, cleanup);
932
933 addr = g_new0(char, buflen);
934
935 pret = PrlStrList_GetItem(addrlist, i, addr, &buflen);
936 prlsdkCheckRetGoto(pret, cleanup);
937
938 if (!(ip = prlsdkParseNetAddress(addr)))
939 continue;
940
941 VIR_APPEND_ELEMENT(net->guestIP.ips, net->guestIP.nips, ip);
942 }
943
944 ret = 0;
945 cleanup:
946
947 PrlHandle_Free(addrlist);
948 return ret;
949 }
950
951 static int
prlsdkGetRoutes(PRL_HANDLE sdknet,virDomainNetDef * net)952 prlsdkGetRoutes(PRL_HANDLE sdknet, virDomainNetDef *net)
953 {
954 int ret = -1;
955 char *gw = NULL;
956 char *gw6 = NULL;
957 g_autoptr(virNetDevIPRoute) route = NULL;
958
959 if (!(gw = prlsdkGetStringParamVar(PrlVmDevNet_GetDefaultGateway, sdknet)))
960 goto cleanup;
961
962 if (!(gw6 = prlsdkGetStringParamVar(PrlVmDevNet_GetDefaultGatewayIPv6, sdknet)))
963 goto cleanup;
964
965 if (*gw != '\0') {
966
967 if (!(route = virNetDevIPRouteCreate(_("Domain interface"),
968 "ipv4", VIR_SOCKET_ADDR_IPV4_ALL,
969 NULL, gw, 0, true, 0, false)))
970 goto cleanup;
971
972 VIR_APPEND_ELEMENT(net->guestIP.routes, net->guestIP.nroutes, route);
973 }
974
975 if (*gw6 != '\0') {
976 if (!(route = virNetDevIPRouteCreate(_("Domain interface"),
977 "ipv6", VIR_SOCKET_ADDR_IPV6_ALL,
978 NULL, gw6, 0, true, 0, false)))
979 goto cleanup;
980
981 VIR_APPEND_ELEMENT(net->guestIP.routes, net->guestIP.nroutes, route);
982 }
983
984 ret = 0;
985
986 cleanup:
987 VIR_FREE(gw);
988 VIR_FREE(gw6);
989
990 return ret;
991 }
992
993 static int
prlsdkGetNetInfo(PRL_HANDLE netAdapter,virDomainNetDef * net,bool isCt)994 prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDef *net, bool isCt)
995 {
996 char macstr[VIR_MAC_STRING_BUFLEN];
997 PRL_UINT32 netAdapterIndex;
998 PRL_UINT32 emulatedType;
999 PRL_RESULT pret;
1000 PRL_BOOL isConnected, isMacFilter;
1001
1002 /* use device name, shown by prlctl as target device
1003 * for identifying network adapter in virDomainDefineXML */
1004 if (!(net->ifname = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
1005 netAdapter)))
1006 return -1;
1007
1008 pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
1009 prlsdkCheckRetExit(pret, -1);
1010
1011 if (isCt && netAdapterIndex == (PRL_UINT32) -1) {
1012 /* venet devices don't have mac address and
1013 * always up */
1014 net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
1015 net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
1016 net->data.network.name = g_strdup(PARALLELS_DOMAIN_ROUTED_NETWORK_NAME);
1017 return 0;
1018 }
1019
1020 pret = prlsdkGetStringParamBuf(PrlVmDevNet_GetMacAddressCanonical,
1021 netAdapter, macstr, sizeof(macstr));
1022 prlsdkCheckRetExit(pret, -1);
1023
1024 if (virMacAddrParse(macstr, &net->mac) < 0)
1025 return -1;
1026
1027 if (prlsdkGetNetAddresses(netAdapter, net) < 0)
1028 return -1;
1029
1030 if (prlsdkGetRoutes(netAdapter, net) < 0)
1031 return -1;
1032
1033 pret = PrlVmDev_GetEmulatedType(netAdapter, &emulatedType);
1034 prlsdkCheckRetExit(pret, -1);
1035
1036 if (emulatedType == PNA_ROUTED) {
1037 net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
1038 net->data.network.name = g_strdup(PARALLELS_DOMAIN_ROUTED_NETWORK_NAME);
1039 } else {
1040 char *netid =
1041 prlsdkGetStringParamVar(PrlVmDevNet_GetVirtualNetworkId,
1042 netAdapter);
1043
1044 if (emulatedType == PNA_BRIDGE) {
1045 net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
1046 if (netid)
1047 net->data.bridge.brname = netid;
1048 } else {
1049 net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
1050 if (netid)
1051 net->data.network.name = netid;
1052 }
1053 }
1054
1055 if (!isCt) {
1056 PRL_VM_NET_ADAPTER_TYPE type;
1057 pret = PrlVmDevNet_GetAdapterType(netAdapter, &type);
1058 prlsdkCheckRetExit(pret, -1);
1059
1060 switch ((int)type) {
1061 case PNT_RTL:
1062 net->model = VIR_DOMAIN_NET_MODEL_RTL8139;
1063 break;
1064 case PNT_E1000:
1065 net->model = VIR_DOMAIN_NET_MODEL_E1000;
1066 break;
1067 case PNT_VIRTIO:
1068 net->model = VIR_DOMAIN_NET_MODEL_VIRTIO;
1069 break;
1070 default:
1071 virReportError(VIR_ERR_INTERNAL_ERROR,
1072 _("Unknown adapter type: %X"), type);
1073 return -1;
1074 }
1075 }
1076
1077 pret = PrlVmDev_IsConnected(netAdapter, &isConnected);
1078 prlsdkCheckRetExit(pret, -1);
1079
1080 if (isConnected)
1081 net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
1082 else
1083 net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
1084
1085 pret = PrlVmDevNet_IsPktFilterPreventMacSpoof(netAdapter, &isMacFilter);
1086 prlsdkCheckRetExit(pret, -1);
1087
1088 net->trustGuestRxFilters = isMacFilter ? VIR_TRISTATE_BOOL_YES :
1089 VIR_TRISTATE_BOOL_NO;
1090
1091 return 0;
1092 }
1093
1094 static int
prlsdkAddDomainNetInfo(PRL_HANDLE sdkdom,virDomainDef * def)1095 prlsdkAddDomainNetInfo(PRL_HANDLE sdkdom, virDomainDef *def)
1096 {
1097 virDomainNetDef *net = NULL;
1098 PRL_RESULT ret;
1099 PRL_HANDLE netAdapter;
1100 PRL_UINT32 netAdaptersCount;
1101 PRL_UINT32 i;
1102
1103 ret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &netAdaptersCount);
1104 prlsdkCheckRetGoto(ret, error);
1105 for (i = 0; i < netAdaptersCount; ++i) {
1106 ret = PrlVmCfg_GetNetAdapter(sdkdom, i, &netAdapter);
1107 prlsdkCheckRetGoto(ret, error);
1108
1109 net = g_new0(virDomainNetDef, 1);
1110
1111 if (prlsdkGetNetInfo(netAdapter, net, IS_CT(def)) < 0)
1112 goto error;
1113
1114 PrlHandle_Free(netAdapter);
1115 netAdapter = PRL_INVALID_HANDLE;
1116
1117 VIR_APPEND_ELEMENT(def->nets, def->nnets, net);
1118 }
1119
1120 return 0;
1121
1122 error:
1123 PrlHandle_Free(netAdapter);
1124 virDomainNetDefFree(net);
1125 return -1;
1126 }
1127
1128 static int
prlsdkGetSerialInfo(PRL_HANDLE serialPort,virDomainChrDef * chr)1129 prlsdkGetSerialInfo(PRL_HANDLE serialPort, virDomainChrDef *chr)
1130 {
1131 PRL_RESULT pret;
1132 PRL_UINT32 serialPortIndex;
1133 PRL_UINT32 emulatedType;
1134 char *friendlyName = NULL;
1135 PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode;
1136 char *uristr = NULL;
1137 virURI *uri = NULL;
1138 int ret = -1;
1139
1140 chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
1141 pret = PrlVmDev_GetIndex(serialPort, &serialPortIndex);
1142 prlsdkCheckRetGoto(pret, cleanup);
1143 chr->target.port = serialPortIndex;
1144
1145 pret = PrlVmDev_GetEmulatedType(serialPort, &emulatedType);
1146 prlsdkCheckRetGoto(pret, cleanup);
1147
1148 if (!(friendlyName = prlsdkGetStringParamVar(PrlVmDev_GetFriendlyName,
1149 serialPort)))
1150 goto cleanup;
1151
1152 pret = PrlVmDevSerial_GetSocketMode(serialPort, &socket_mode);
1153 prlsdkCheckRetGoto(pret, cleanup);
1154
1155 switch (emulatedType) {
1156 case PDT_USE_OUTPUT_FILE:
1157 chr->source->type = VIR_DOMAIN_CHR_TYPE_FILE;
1158 chr->source->data.file.path = g_steal_pointer(&friendlyName);
1159 break;
1160 case PDT_USE_SERIAL_PORT_SOCKET_MODE:
1161 chr->source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
1162 chr->source->data.nix.path = g_steal_pointer(&friendlyName);
1163 chr->source->data.nix.listen = socket_mode == PSP_SERIAL_SOCKET_SERVER;
1164 break;
1165 case PDT_USE_REAL_DEVICE:
1166 chr->source->type = VIR_DOMAIN_CHR_TYPE_DEV;
1167 chr->source->data.file.path = g_steal_pointer(&friendlyName);
1168 break;
1169 case PDT_USE_TCP:
1170 chr->source->type = VIR_DOMAIN_CHR_TYPE_TCP;
1171 uristr = g_strdup_printf("tcp://%s", friendlyName);
1172 if (!(uri = virURIParse(uristr)))
1173 goto cleanup;
1174 chr->source->data.tcp.host = g_strdup(uri->server);
1175 chr->source->data.tcp.service = g_strdup_printf("%d", uri->port);
1176 chr->source->data.tcp.listen = socket_mode == PSP_SERIAL_SOCKET_SERVER;
1177 break;
1178 case PDT_USE_UDP:
1179 chr->source->type = VIR_DOMAIN_CHR_TYPE_UDP;
1180 uristr = g_strdup_printf("udp://%s", friendlyName);
1181 if (!(uri = virURIParse(uristr)))
1182 goto cleanup;
1183 chr->source->data.udp.bindHost = g_strdup(uri->server);
1184 chr->source->data.udp.bindService = g_strdup_printf("%d", uri->port);
1185 chr->source->data.udp.connectHost = g_strdup(uri->server);
1186 chr->source->data.udp.connectService = g_strdup_printf("%d", uri->port);
1187 break;
1188 default:
1189 virReportError(VIR_ERR_INTERNAL_ERROR,
1190 _("Unknown serial type: %X"), emulatedType);
1191 goto cleanup;
1192 break;
1193 }
1194
1195 ret = 0;
1196
1197 cleanup:
1198 VIR_FREE(friendlyName);
1199 VIR_FREE(uristr);
1200 virURIFree(uri);
1201
1202 return ret;
1203 }
1204
1205
1206 static int
prlsdkAddSerialInfo(PRL_HANDLE sdkdom,virDomainChrDef *** serials,size_t * nserials)1207 prlsdkAddSerialInfo(PRL_HANDLE sdkdom,
1208 virDomainChrDef ***serials,
1209 size_t *nserials)
1210 {
1211 PRL_RESULT ret;
1212 PRL_HANDLE serialPort;
1213 PRL_UINT32 serialPortsCount;
1214 PRL_UINT32 i;
1215 virDomainChrDef *chr = NULL;
1216
1217 ret = PrlVmCfg_GetSerialPortsCount(sdkdom, &serialPortsCount);
1218 prlsdkCheckRetGoto(ret, cleanup);
1219 for (i = 0; i < serialPortsCount; ++i) {
1220 ret = PrlVmCfg_GetSerialPort(sdkdom, i, &serialPort);
1221 prlsdkCheckRetGoto(ret, cleanup);
1222
1223 if (!(chr = virDomainChrDefNew(NULL)))
1224 goto cleanup;
1225
1226 if (prlsdkGetSerialInfo(serialPort, chr))
1227 goto cleanup;
1228
1229 PrlHandle_Free(serialPort);
1230 serialPort = PRL_INVALID_HANDLE;
1231
1232 VIR_APPEND_ELEMENT(*serials, *nserials, chr);
1233 }
1234
1235 return 0;
1236
1237 cleanup:
1238 PrlHandle_Free(serialPort);
1239 virDomainChrDefFree(chr);
1240 return -1;
1241 }
1242
1243
1244 static int
prlsdkAddDomainHardware(struct _vzDriver * driver,PRL_HANDLE sdkdom,virDomainDef * def,virDomainXMLOption * xmlopt)1245 prlsdkAddDomainHardware(struct _vzDriver *driver,
1246 PRL_HANDLE sdkdom,
1247 virDomainDef *def,
1248 virDomainXMLOption *xmlopt)
1249 {
1250 if (IS_CT(def)) {
1251 if (prlsdkAddDomainVideoInfoCt(def, xmlopt) < 0)
1252 return -1;
1253 } else {
1254 if (prlsdkAddDomainVideoInfoVm(sdkdom, def) < 0)
1255 return -1;
1256 }
1257
1258 if (prlsdkAddDomainHardDisksInfo(driver, sdkdom, def) < 0)
1259 return -1;
1260
1261 if (prlsdkAddDomainOpticalDisksInfo(driver, sdkdom, def) < 0)
1262 return -1;
1263
1264 if (prlsdkAddDomainNetInfo(sdkdom, def) < 0)
1265 return -1;
1266
1267 if (prlsdkAddSerialInfo(sdkdom,
1268 &def->serials,
1269 &def->nserials) < 0)
1270 return -1;
1271
1272 return 0;
1273 }
1274
1275
1276 static int
prlsdkAddVNCInfo(PRL_HANDLE sdkdom,virDomainDef * def)1277 prlsdkAddVNCInfo(PRL_HANDLE sdkdom, virDomainDef *def)
1278 {
1279 virDomainGraphicsDef *gr = NULL;
1280 PRL_VM_REMOTE_DISPLAY_MODE vncMode;
1281 PRL_UINT32 port;
1282 PRL_RESULT pret;
1283 char *passwd = NULL;
1284
1285 pret = PrlVmCfg_GetVNCMode(sdkdom, &vncMode);
1286 prlsdkCheckRetGoto(pret, error);
1287
1288 if (vncMode == PRD_DISABLED)
1289 return 0;
1290
1291 gr = g_new0(virDomainGraphicsDef, 1);
1292
1293 if (!(passwd = prlsdkGetStringParamVar(PrlVmCfg_GetVNCPassword, sdkdom)))
1294 goto error;
1295
1296 if (*passwd != '\0') {
1297 gr->data.vnc.auth.passwd = g_steal_pointer(&passwd);
1298 }
1299
1300 pret = PrlVmCfg_GetVNCPort(sdkdom, &port);
1301 prlsdkCheckRetGoto(pret, error);
1302
1303 gr->data.vnc.autoport = (vncMode == PRD_AUTO);
1304 gr->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
1305 gr->data.vnc.port = port;
1306
1307 gr->listens = g_new0(virDomainGraphicsListenDef, 1);
1308 gr->nListens = 1;
1309
1310 if (!(gr->listens[0].address = prlsdkGetStringParamVar(PrlVmCfg_GetVNCHostName,
1311 sdkdom)))
1312 goto error;
1313
1314 gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
1315
1316 VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr);
1317
1318 return 0;
1319
1320 error:
1321 virDomainGraphicsDefFree(gr);
1322 VIR_FREE(passwd);
1323 return -1;
1324 }
1325
1326 static void
prlsdkConvertDomainState(VIRTUAL_MACHINE_STATE domainState,PRL_UINT32 envId,virDomainObj * dom)1327 prlsdkConvertDomainState(VIRTUAL_MACHINE_STATE domainState,
1328 PRL_UINT32 envId,
1329 virDomainObj *dom)
1330 {
1331 switch (domainState) {
1332 case VMS_STOPPED:
1333 case VMS_MOUNTED:
1334 virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
1335 VIR_DOMAIN_SHUTOFF_SHUTDOWN);
1336 dom->def->id = -1;
1337 break;
1338 case VMS_STARTING:
1339 case VMS_COMPACTING:
1340 case VMS_RESETTING:
1341 case VMS_PAUSING:
1342 case VMS_RECONNECTING:
1343 case VMS_RUNNING:
1344 virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
1345 VIR_DOMAIN_RUNNING_BOOTED);
1346 dom->def->id = envId;
1347 break;
1348 case VMS_PAUSED:
1349 virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
1350 VIR_DOMAIN_PAUSED_USER);
1351 dom->def->id = envId;
1352 break;
1353 case VMS_SUSPENDED:
1354 case VMS_DELETING_STATE:
1355 case VMS_SUSPENDING_SYNC:
1356 virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
1357 VIR_DOMAIN_SHUTOFF_SAVED);
1358 dom->def->id = -1;
1359 break;
1360 case VMS_STOPPING:
1361 virDomainObjSetState(dom, VIR_DOMAIN_SHUTDOWN,
1362 VIR_DOMAIN_SHUTDOWN_USER);
1363 dom->def->id = envId;
1364 break;
1365 case VMS_SNAPSHOTING:
1366 virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
1367 VIR_DOMAIN_PAUSED_SNAPSHOT);
1368 dom->def->id = envId;
1369 break;
1370 case VMS_MIGRATING:
1371 virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
1372 VIR_DOMAIN_PAUSED_MIGRATION);
1373 dom->def->id = envId;
1374 break;
1375 case VMS_SUSPENDING:
1376 virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
1377 VIR_DOMAIN_PAUSED_SAVE);
1378 dom->def->id = envId;
1379 break;
1380 case VMS_RESTORING:
1381 virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
1382 VIR_DOMAIN_RUNNING_RESTORED);
1383 dom->def->id = envId;
1384 break;
1385 case VMS_CONTINUING:
1386 virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
1387 VIR_DOMAIN_RUNNING_UNPAUSED);
1388 dom->def->id = envId;
1389 break;
1390 case VMS_RESUMING:
1391 virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
1392 VIR_DOMAIN_RUNNING_RESTORED);
1393 dom->def->id = envId;
1394 break;
1395 case VMS_UNKNOWN:
1396 default:
1397 virDomainObjSetState(dom, VIR_DOMAIN_NOSTATE,
1398 VIR_DOMAIN_NOSTATE_UNKNOWN);
1399 dom->def->id = -1;
1400 break;
1401 }
1402 }
1403
1404 static int
prlsdkConvertCpuInfo(PRL_HANDLE sdkdom,virDomainDef * def,virDomainXMLOption * xmlopt)1405 prlsdkConvertCpuInfo(PRL_HANDLE sdkdom,
1406 virDomainDef *def,
1407 virDomainXMLOption *xmlopt)
1408 {
1409 g_autofree char *buf = NULL;
1410 int hostcpus;
1411 PRL_UINT32 cpuCount;
1412 PRL_RESULT pret;
1413
1414 if ((hostcpus = virHostCPUGetCount()) < 0)
1415 return -1;
1416
1417 /* get number of CPUs */
1418 pret = PrlVmCfg_GetCpuCount(sdkdom, &cpuCount);
1419 prlsdkCheckRetExit(pret, -1);
1420
1421 if (cpuCount > hostcpus)
1422 cpuCount = hostcpus;
1423
1424 if (virDomainDefSetVcpusMax(def, cpuCount, xmlopt) < 0)
1425 return -1;
1426
1427 if (virDomainDefSetVcpus(def, cpuCount) < 0)
1428 return -1;
1429
1430 if (!(buf = prlsdkGetStringParamVar(PrlVmCfg_GetCpuMask, sdkdom)))
1431 return -1;
1432
1433 if (strlen(buf) == 0) {
1434 def->cpumask = virBitmapNew(hostcpus);
1435 virBitmapSetAll(def->cpumask);
1436 } else {
1437 if (virBitmapParse(buf, &def->cpumask, hostcpus) < 0)
1438 return -1;
1439 }
1440
1441 return 0;
1442 }
1443
1444 static int
prlsdkConvertDomainType(PRL_HANDLE sdkdom,virDomainDef * def)1445 prlsdkConvertDomainType(PRL_HANDLE sdkdom, virDomainDef *def)
1446 {
1447 PRL_VM_TYPE domainType;
1448 PRL_RESULT pret;
1449
1450 pret = PrlVmCfg_GetVmType(sdkdom, &domainType);
1451 prlsdkCheckRetExit(pret, -1);
1452
1453 switch (domainType) {
1454 case PVT_VM:
1455 def->os.type = VIR_DOMAIN_OSTYPE_HVM;
1456 break;
1457 case PVT_CT:
1458 def->os.type = VIR_DOMAIN_OSTYPE_EXE;
1459 def->os.init = g_strdup("/sbin/init");
1460 break;
1461 default:
1462 virReportError(VIR_ERR_INTERNAL_ERROR,
1463 _("Unknown domain type: %X"), domainType);
1464 return -1;
1465 }
1466
1467 return 0;
1468 }
1469
1470 static int
prlsdkConvertCpuMode(PRL_HANDLE sdkdom,virDomainDef * def)1471 prlsdkConvertCpuMode(PRL_HANDLE sdkdom, virDomainDef *def)
1472 {
1473 PRL_RESULT pret;
1474 PRL_CPU_MODE cpuMode;
1475
1476 pret = PrlVmCfg_GetCpuMode(sdkdom, &cpuMode);
1477 prlsdkCheckRetExit(pret, -1);
1478
1479 switch (cpuMode) {
1480 case PCM_CPU_MODE_32:
1481 def->os.arch = VIR_ARCH_I686;
1482 break;
1483 case PCM_CPU_MODE_64:
1484 def->os.arch = VIR_ARCH_X86_64;
1485 break;
1486 default:
1487 virReportError(VIR_ERR_INTERNAL_ERROR,
1488 _("Unknown CPU mode: %X"), cpuMode);
1489 return -1;
1490 }
1491
1492 return 0;
1493 }
1494
1495 static PRL_HANDLE
prlsdkGetDevByDevIndex(PRL_HANDLE sdkdom,PRL_DEVICE_TYPE type,PRL_UINT32 devIndex)1496 prlsdkGetDevByDevIndex(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE type, PRL_UINT32 devIndex)
1497 {
1498 PRL_RESULT pret;
1499 PRL_UINT32 index, num;
1500 PRL_HANDLE dev = PRL_INVALID_HANDLE;
1501 size_t i;
1502
1503 pret = PrlVmCfg_GetDevsCountByType(sdkdom, type, &num);
1504 prlsdkCheckRetGoto(pret, error);
1505
1506 for (i = 0; i < num; ++i) {
1507 pret = PrlVmCfg_GetDevByType(sdkdom, type, i, &dev);
1508 prlsdkCheckRetGoto(pret, error);
1509
1510 pret = PrlVmDev_GetIndex(dev, &index);
1511 prlsdkCheckRetGoto(pret, error);
1512
1513 if (index == devIndex)
1514 break;
1515
1516 PrlHandle_Free(dev);
1517 dev = PRL_INVALID_HANDLE;
1518 }
1519
1520 return dev;
1521
1522 error:
1523 PrlHandle_Free(dev);
1524 return PRL_INVALID_HANDLE;
1525 }
1526
1527 static virDomainDiskDef *
virFindDiskBootIndex(virDomainDef * def,virDomainDiskDevice type,int index)1528 virFindDiskBootIndex(virDomainDef *def, virDomainDiskDevice type, int index)
1529 {
1530 size_t i;
1531 int c = 0;
1532
1533 for (i = 0; i < def->ndisks; ++i) {
1534 if (def->disks[i]->device != type)
1535 continue;
1536 if (c == index)
1537 return def->disks[i];
1538 ++c;
1539 }
1540
1541 return NULL;
1542 }
1543
1544 static bool
prlsdkInBootList(PRL_HANDLE sdkdom,PRL_HANDLE sdktargetdev)1545 prlsdkInBootList(PRL_HANDLE sdkdom,
1546 PRL_HANDLE sdktargetdev)
1547 {
1548 bool ret = false;
1549 PRL_RESULT pret;
1550 PRL_UINT32 bootNum;
1551 PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
1552 PRL_BOOL inUse;
1553 PRL_DEVICE_TYPE sdkType, targetType;
1554 PRL_UINT32 sdkIndex, targetIndex;
1555 size_t i;
1556
1557 pret = PrlVmDev_GetType(sdktargetdev, &targetType);
1558 prlsdkCheckRetExit(pret, false);
1559
1560 pret = PrlVmDev_GetIndex(sdktargetdev, &targetIndex);
1561 prlsdkCheckRetExit(pret, false);
1562
1563 pret = PrlVmCfg_GetBootDevCount(sdkdom, &bootNum);
1564 prlsdkCheckRetExit(pret, false);
1565
1566 for (i = 0; i < bootNum; ++i) {
1567 pret = PrlVmCfg_GetBootDev(sdkdom, i, &bootDev);
1568 prlsdkCheckRetGoto(pret, cleanup);
1569
1570 pret = PrlBootDev_IsInUse(bootDev, &inUse);
1571 prlsdkCheckRetGoto(pret, cleanup);
1572
1573 if (!inUse) {
1574 PrlHandle_Free(bootDev);
1575 bootDev = PRL_INVALID_HANDLE;
1576 continue;
1577 }
1578
1579 pret = PrlBootDev_GetType(bootDev, &sdkType);
1580 prlsdkCheckRetGoto(pret, cleanup);
1581
1582 pret = PrlBootDev_GetIndex(bootDev, &sdkIndex);
1583 prlsdkCheckRetGoto(pret, cleanup);
1584
1585 PrlHandle_Free(bootDev);
1586 bootDev = PRL_INVALID_HANDLE;
1587
1588 if (sdkIndex == targetIndex && sdkType == targetType) {
1589 ret = true;
1590 break;
1591 }
1592 }
1593
1594 cleanup:
1595 PrlHandle_Free(bootDev);
1596 return ret;
1597 }
1598 static int
prlsdkBootOrderCheck(PRL_HANDLE sdkdom,PRL_DEVICE_TYPE sdkType,int sdkIndex,virDomainDef * def,int bootIndex)1599 prlsdkBootOrderCheck(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE sdkType, int sdkIndex,
1600 virDomainDef *def, int bootIndex)
1601 {
1602 char *sdkName = NULL;
1603 PRL_HANDLE dev = PRL_INVALID_HANDLE;
1604 virDomainDiskDef *disk;
1605 virDomainDiskDevice device;
1606 virDomainDiskBus bus;
1607 char *dst = NULL;
1608 int ret = -1;
1609
1610 dev = prlsdkGetDevByDevIndex(sdkdom, sdkType, sdkIndex);
1611 if (dev == PRL_INVALID_HANDLE) {
1612 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1613 _("Can't find boot device of type: %d, device index: %d"),
1614 sdkType, sdkIndex);
1615 return -1;
1616 }
1617
1618 switch ((int)sdkType) {
1619 case PDE_OPTICAL_DISK:
1620 case PDE_HARD_DISK:
1621 switch ((int)sdkType) {
1622 case PDE_OPTICAL_DISK:
1623 device = VIR_DOMAIN_DISK_DEVICE_CDROM;
1624 break;
1625 case PDE_HARD_DISK:
1626 device = VIR_DOMAIN_DISK_DEVICE_DISK;
1627 break;
1628 default:
1629 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1630 _("Unsupported disk type %d"), sdkType);
1631 goto cleanup;
1632 }
1633
1634 if (!(disk = virFindDiskBootIndex(def, device, bootIndex))) {
1635 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1636 _("Can't find boot device of type: %s, index: %d"),
1637 virDomainDiskDeviceTypeToString(device), bootIndex);
1638 goto cleanup;
1639 }
1640
1641 if (prlsdkGetDiskId(dev, &bus, &dst) < 0)
1642 goto cleanup;
1643
1644 if (!(bus == disk->bus && STREQ(disk->dst, dst)))
1645 VIR_WARN("Unrepresentable boot order configuration");
1646
1647 break;
1648 case PDE_GENERIC_NETWORK_ADAPTER:
1649 if (!(sdkName = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
1650 dev)))
1651 goto cleanup;
1652
1653 if (bootIndex >= def->nnets) {
1654 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1655 _("Can't find network boot device for index: %d"),
1656 bootIndex);
1657 goto cleanup;
1658 }
1659
1660 if (STRNEQ(sdkName, def->nets[bootIndex]->ifname))
1661 VIR_WARN("Unrepresentable boot order configuration");
1662
1663 break;
1664 default:
1665 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1666 _("Unexpected device type %d"), sdkType);
1667 goto cleanup;
1668 }
1669
1670 ret = 0;
1671
1672 cleanup:
1673
1674 VIR_FREE(sdkName);
1675 PrlHandle_Free(dev);
1676 VIR_FREE(dst);
1677 return ret;
1678 }
1679
1680 static int
prlsdkConvertBootOrderVm(PRL_HANDLE sdkdom,virDomainDef * def)1681 prlsdkConvertBootOrderVm(PRL_HANDLE sdkdom, virDomainDef *def)
1682 {
1683 int ret = -1;
1684 PRL_RESULT pret;
1685 PRL_UINT32 bootNum;
1686 PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
1687 PRL_BOOL inUse;
1688 PRL_DEVICE_TYPE sdkType;
1689 virDomainBootOrder type;
1690 PRL_UINT32 prevBootIndex = 0, bootIndex, sdkIndex;
1691 int bootUsage[VIR_DOMAIN_BOOT_LAST] = { 0 };
1692 size_t i;
1693
1694 pret = PrlVmCfg_GetBootDevCount(sdkdom, &bootNum);
1695 prlsdkCheckRetExit(pret, -1);
1696
1697 def->os.nBootDevs = 0;
1698
1699 if (bootNum > VIR_DOMAIN_MAX_BOOT_DEVS) {
1700 bootNum = VIR_DOMAIN_MAX_BOOT_DEVS;
1701 VIR_WARN("Too many boot devices");
1702 }
1703
1704 for (i = 0; i < bootNum; ++i) {
1705 pret = PrlVmCfg_GetBootDev(sdkdom, i, &bootDev);
1706 prlsdkCheckRetGoto(pret, cleanup);
1707
1708 pret = PrlBootDev_IsInUse(bootDev, &inUse);
1709 prlsdkCheckRetGoto(pret, cleanup);
1710
1711 if (!inUse)
1712 continue;
1713
1714 pret = PrlBootDev_GetSequenceIndex(bootDev, &bootIndex);
1715 prlsdkCheckRetGoto(pret, cleanup);
1716
1717 /* bootIndex is started from 1 */
1718 if (bootIndex <= prevBootIndex) {
1719 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1720 _("Unsupported boot order configuration"));
1721 goto cleanup;
1722 }
1723 prevBootIndex = bootIndex;
1724
1725 pret = PrlBootDev_GetType(bootDev, &sdkType);
1726 prlsdkCheckRetGoto(pret, cleanup);
1727
1728 if (sdkType == PDE_FLOPPY_DISK) {
1729 VIR_WARN("Skipping floppy from boot order.");
1730 continue;
1731 }
1732
1733 switch ((int)sdkType) {
1734 case PDE_OPTICAL_DISK:
1735 type = VIR_DOMAIN_BOOT_CDROM;
1736 break;
1737 case PDE_HARD_DISK:
1738 type = VIR_DOMAIN_BOOT_DISK;
1739 break;
1740 case PDE_GENERIC_NETWORK_ADAPTER:
1741 type = VIR_DOMAIN_BOOT_NET;
1742 break;
1743 default:
1744 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1745 _("Unexpected boot device type %i"), sdkType);
1746 goto cleanup;
1747 }
1748
1749 pret = PrlBootDev_GetIndex(bootDev, &sdkIndex);
1750 prlsdkCheckRetGoto(pret, cleanup);
1751
1752 if (prlsdkBootOrderCheck(sdkdom, sdkType, sdkIndex, def, bootUsage[type]) < 0)
1753 goto cleanup;
1754
1755 bootUsage[type]++;
1756 def->os.bootDevs[def->os.nBootDevs++] = type;
1757
1758 PrlHandle_Free(bootDev);
1759 bootDev = PRL_INVALID_HANDLE;
1760 }
1761
1762 ret = 0;
1763
1764 cleanup:
1765 PrlHandle_Free(bootDev);
1766 return ret;
1767 }
1768
1769 /* if dom is NULL adds new domain into domain list
1770 * if dom not NULL updates given locked dom object.
1771 *
1772 * Returned object is locked and referenced.
1773 */
1774
1775 static virDomainObj *
prlsdkLoadDomain(struct _vzDriver * driver,PRL_HANDLE sdkdom,virDomainObj * dom)1776 prlsdkLoadDomain(struct _vzDriver *driver,
1777 PRL_HANDLE sdkdom,
1778 virDomainObj *dom)
1779 {
1780 virDomainDef *def = NULL;
1781 struct vzDomObj *pdom = NULL;
1782 VIRTUAL_MACHINE_STATE domainState;
1783
1784 PRL_RESULT pret;
1785 PRL_UINT32 ram;
1786 PRL_UINT32 envId;
1787 PRL_VM_AUTOSTART_OPTION autostart;
1788 PRL_HANDLE job;
1789 char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
1790
1791 if (!(def = virDomainDefNew(driver->xmlopt)))
1792 goto error;
1793
1794 if (!(def->name = prlsdkGetStringParamVar(PrlVmCfg_GetName, sdkdom)))
1795 goto error;
1796
1797 pret = prlsdkGetStringParamBuf(PrlVmCfg_GetUuid,
1798 sdkdom, uuidstr, sizeof(uuidstr));
1799 prlsdkCheckRetGoto(pret, error);
1800
1801 if (prlsdkUUIDParse(uuidstr, def->uuid) < 0) {
1802 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1803 _("Domain UUID is malformed or empty"));
1804 goto error;
1805 }
1806
1807 def->virtType = VIR_DOMAIN_VIRT_VZ;
1808
1809 def->onReboot = VIR_DOMAIN_LIFECYCLE_ACTION_RESTART;
1810 def->onPoweroff = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY;
1811 def->onCrash = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY;
1812
1813 /* get RAM parameters */
1814 pret = PrlVmCfg_GetRamSize(sdkdom, &ram);
1815 prlsdkCheckRetGoto(pret, error);
1816 virDomainDefSetMemoryTotal(def, ram << 10); /* RAM size obtained in Mbytes,
1817 convert to Kbytes */
1818 def->mem.cur_balloon = ram << 10;
1819
1820 if (prlsdkConvertCpuInfo(sdkdom, def, driver->xmlopt) < 0)
1821 goto error;
1822
1823 if (prlsdkConvertCpuMode(sdkdom, def) < 0)
1824 goto error;
1825
1826 if (prlsdkConvertDomainType(sdkdom, def) < 0)
1827 goto error;
1828
1829 if (prlsdkAddVNCInfo(sdkdom, def) < 0)
1830 goto error;
1831
1832 /* depends on prlsdkAddVNCInfo */
1833 if (prlsdkAddDomainHardware(driver, sdkdom, def, driver->xmlopt) < 0)
1834 goto error;
1835
1836 /* depends on prlsdkAddDomainHardware */
1837 if (!IS_CT(def) && prlsdkConvertBootOrderVm(sdkdom, def) < 0)
1838 goto error;
1839
1840 pret = PrlVmCfg_GetEnvId(sdkdom, &envId);
1841 prlsdkCheckRetGoto(pret, error);
1842
1843 pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart);
1844 prlsdkCheckRetGoto(pret, error);
1845 if (autostart != PAO_VM_START_ON_LOAD &&
1846 autostart != PAO_VM_START_MANUAL) {
1847 virReportError(VIR_ERR_INTERNAL_ERROR,
1848 _("Unknown autostart mode: %X"), autostart);
1849 goto error;
1850 }
1851
1852 if (prlsdkGetDomainState(dom, sdkdom, &domainState) < 0)
1853 goto error;
1854
1855 if (!IS_CT(def) && virDomainDefAddImplicitDevices(def, driver->xmlopt) < 0)
1856 goto error;
1857
1858 if (def->ngraphics > 0) {
1859 int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS :
1860 VIR_DOMAIN_INPUT_BUS_PS2;
1861
1862 if (virDomainDefMaybeAddInput(def,
1863 VIR_DOMAIN_INPUT_TYPE_MOUSE,
1864 bus) < 0)
1865 goto error;
1866
1867 if (virDomainDefMaybeAddInput(def,
1868 VIR_DOMAIN_INPUT_TYPE_KBD,
1869 bus) < 0)
1870 goto error;
1871 }
1872
1873 if (!dom) {
1874 virDomainObj *olddom = NULL;
1875
1876 job = PrlVm_SubscribeToPerfStats(sdkdom, NULL);
1877 if (PRL_FAILED(waitJob(job)))
1878 goto error;
1879
1880 virObjectLock(driver);
1881 if (!(olddom = virDomainObjListFindByUUID(driver->domains, def->uuid)))
1882 dom = virDomainObjListAdd(driver->domains, def, driver->xmlopt, 0, NULL);
1883 virObjectUnlock(driver);
1884
1885 if (olddom) {
1886 virDomainDefFree(def);
1887 return olddom;
1888 } else if (!dom) {
1889 goto error;
1890 }
1891
1892 pdom = dom->privateData;
1893 pdom->sdkdom = sdkdom;
1894 PrlHandle_AddRef(sdkdom);
1895 dom->persistent = 1;
1896 } else {
1897 /* assign new virDomainDef without any checks
1898 * we can't use virDomainObjAssignDef, because it checks
1899 * for state and domain name */
1900 virDomainDefFree(dom->def);
1901 dom->def = def;
1902 }
1903
1904 pdom = dom->privateData;
1905 pdom->id = envId;
1906
1907 prlsdkConvertDomainState(domainState, envId, dom);
1908
1909 if (autostart == PAO_VM_START_ON_LOAD)
1910 dom->autostart = 1;
1911 else
1912 dom->autostart = 0;
1913
1914 return dom;
1915
1916 error:
1917 virDomainDefFree(def);
1918 return NULL;
1919 }
1920
1921 int
prlsdkLoadDomains(struct _vzDriver * driver)1922 prlsdkLoadDomains(struct _vzDriver *driver)
1923 {
1924 PRL_HANDLE job = PRL_INVALID_HANDLE;
1925 PRL_HANDLE result;
1926 PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
1927 PRL_UINT32 paramsCount;
1928 PRL_RESULT pret;
1929 size_t i = 0;
1930 virDomainObj *dom;
1931
1932 job = PrlSrv_GetVmListEx(driver->server, PVTF_VM | PVTF_CT);
1933
1934 if (PRL_FAILED(getJobResult(job, &result)))
1935 return -1;
1936
1937 pret = PrlResult_GetParamsCount(result, ¶msCount);
1938 prlsdkCheckRetGoto(pret, error);
1939
1940 for (i = 0; i < paramsCount; i++) {
1941 pret = PrlResult_GetParamByIndex(result, i, &sdkdom);
1942 prlsdkCheckRetGoto(pret, error);
1943
1944 dom = prlsdkLoadDomain(driver, sdkdom, NULL);
1945 virDomainObjEndAPI(&dom);
1946
1947 PrlHandle_Free(sdkdom);
1948 sdkdom = PRL_INVALID_HANDLE;
1949 }
1950
1951 PrlHandle_Free(result);
1952 return 0;
1953
1954 error:
1955 PrlHandle_Free(sdkdom);
1956 PrlHandle_Free(result);
1957 return -1;
1958 }
1959
1960 virDomainObj *
prlsdkAddDomainByUUID(struct _vzDriver * driver,const unsigned char * uuid)1961 prlsdkAddDomainByUUID(struct _vzDriver *driver, const unsigned char *uuid)
1962 {
1963 PRL_HANDLE sdkdom;
1964 virDomainObj *dom;
1965
1966 sdkdom = prlsdkSdkDomainLookupByUUID(driver, uuid);
1967 if (sdkdom == PRL_INVALID_HANDLE)
1968 return NULL;
1969
1970 dom = prlsdkLoadDomain(driver, sdkdom, NULL);
1971
1972 PrlHandle_Free(sdkdom);
1973 return dom;
1974 }
1975
1976 virDomainObj *
prlsdkAddDomainByName(struct _vzDriver * driver,const char * name)1977 prlsdkAddDomainByName(struct _vzDriver *driver, const char *name)
1978 {
1979 PRL_HANDLE sdkdom;
1980 virDomainObj *dom;
1981
1982 sdkdom = prlsdkSdkDomainLookupByName(driver, name);
1983 if (sdkdom == PRL_INVALID_HANDLE)
1984 return NULL;
1985
1986 dom = prlsdkLoadDomain(driver, sdkdom, NULL);
1987
1988 PrlHandle_Free(sdkdom);
1989 return dom;
1990 }
1991
1992 int
prlsdkUpdateDomain(struct _vzDriver * driver,virDomainObj * dom)1993 prlsdkUpdateDomain(struct _vzDriver *driver, virDomainObj *dom)
1994 {
1995 PRL_HANDLE job;
1996 struct vzDomObj *pdom = dom->privateData;
1997
1998 job = PrlVm_RefreshConfig(pdom->sdkdom);
1999 if (waitDomainJob(job, dom))
2000 return -1;
2001
2002 return prlsdkLoadDomain(driver, pdom->sdkdom, dom) ? 0 : -1;
2003 }
2004
2005 static void
prlsdkSendEvent(struct _vzDriver * driver,virDomainObj * dom,virDomainEventType lvEventType,int lvEventTypeDetails)2006 prlsdkSendEvent(struct _vzDriver *driver,
2007 virDomainObj *dom,
2008 virDomainEventType lvEventType,
2009 int lvEventTypeDetails)
2010 {
2011 virObjectEvent *event;
2012
2013 event = virDomainEventLifecycleNewFromObj(dom,
2014 lvEventType,
2015 lvEventTypeDetails);
2016 virObjectEventStateQueue(driver->domainEventState, event);
2017 }
2018
2019 static void
prlsdkNewStateToEvent(VIRTUAL_MACHINE_STATE domainState,virDomainEventType * lvEventType,int * lvEventTypeDetails)2020 prlsdkNewStateToEvent(VIRTUAL_MACHINE_STATE domainState,
2021 virDomainEventType *lvEventType,
2022 int *lvEventTypeDetails)
2023 {
2024 /* We skip all intermediate states here, because
2025 * libvirt doesn't have corresponding event types for
2026 * them */
2027 switch ((int)domainState) {
2028 case VMS_STOPPED:
2029 case VMS_MOUNTED:
2030 *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
2031 *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
2032 break;
2033 case VMS_RUNNING:
2034 *lvEventType = VIR_DOMAIN_EVENT_STARTED;
2035 *lvEventTypeDetails = VIR_DOMAIN_EVENT_STARTED_BOOTED;
2036 break;
2037 case VMS_PAUSED:
2038 *lvEventType = VIR_DOMAIN_EVENT_SUSPENDED;
2039 *lvEventTypeDetails = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
2040 break;
2041 case VMS_SUSPENDED:
2042 *lvEventType = VIR_DOMAIN_EVENT_STOPPED;
2043 *lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SAVED;
2044 break;
2045 default:
2046 VIR_DEBUG("Skip sending event about changing state to %X",
2047 domainState);
2048 break;
2049 }
2050 }
2051
2052 static void
prlsdkHandleVmStateEvent(struct _vzDriver * driver,PRL_HANDLE prlEvent,unsigned char * uuid)2053 prlsdkHandleVmStateEvent(struct _vzDriver *driver,
2054 PRL_HANDLE prlEvent,
2055 unsigned char *uuid)
2056 {
2057 PRL_RESULT pret = PRL_ERR_FAILURE;
2058 PRL_HANDLE eventParam = PRL_INVALID_HANDLE;
2059 PRL_INT32 domainState;
2060 virDomainObj *dom = NULL;
2061 struct vzDomObj *pdom;
2062 virDomainEventType lvEventType = 0;
2063 int lvEventTypeDetails = 0;
2064
2065 dom = virDomainObjListFindByUUID(driver->domains, uuid);
2066 if (dom == NULL)
2067 return;
2068
2069 pret = PrlEvent_GetParamByName(prlEvent, "vminfo_vm_state", &eventParam);
2070 prlsdkCheckRetGoto(pret, cleanup);
2071
2072 pret = PrlEvtPrm_ToInt32(eventParam, &domainState);
2073 prlsdkCheckRetGoto(pret, cleanup);
2074
2075 pdom = dom->privateData;
2076
2077 prlsdkConvertDomainState(domainState, pdom->id, dom);
2078
2079 prlsdkNewStateToEvent(domainState,
2080 &lvEventType,
2081 &lvEventTypeDetails);
2082
2083 prlsdkSendEvent(driver, dom, lvEventType, lvEventTypeDetails);
2084
2085 cleanup:
2086 PrlHandle_Free(eventParam);
2087 virDomainObjEndAPI(&dom);
2088 return;
2089 }
2090
2091 static void
prlsdkHandleVmConfigEvent(struct _vzDriver * driver,unsigned char * uuid)2092 prlsdkHandleVmConfigEvent(struct _vzDriver *driver,
2093 unsigned char *uuid)
2094 {
2095 virDomainObj *dom = NULL;
2096 bool job = false;
2097
2098 dom = virDomainObjListFindByUUID(driver->domains, uuid);
2099 if (dom == NULL)
2100 return;
2101
2102 if (vzDomainObjBeginJob(dom) < 0)
2103 goto cleanup;
2104 job = true;
2105
2106 if (dom->removing)
2107 goto cleanup;
2108
2109 if (prlsdkUpdateDomain(driver, dom) < 0)
2110 goto cleanup;
2111
2112 prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_DEFINED,
2113 VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2114
2115 cleanup:
2116 if (job)
2117 vzDomainObjEndJob(dom);
2118 virDomainObjEndAPI(&dom);
2119 return;
2120 }
2121
2122 static void
prlsdkHandleVmAddedEvent(struct _vzDriver * driver,unsigned char * uuid)2123 prlsdkHandleVmAddedEvent(struct _vzDriver *driver,
2124 unsigned char *uuid)
2125 {
2126 virDomainObj *dom = NULL;
2127
2128 if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid)) &&
2129 !(dom = prlsdkAddDomainByUUID(driver, uuid)))
2130 goto cleanup;
2131
2132 prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_DEFINED,
2133 VIR_DOMAIN_EVENT_DEFINED_ADDED);
2134
2135 cleanup:
2136 virDomainObjEndAPI(&dom);
2137 return;
2138 }
2139
2140 static void
prlsdkHandleVmRemovedEvent(struct _vzDriver * driver,unsigned char * uuid)2141 prlsdkHandleVmRemovedEvent(struct _vzDriver *driver,
2142 unsigned char *uuid)
2143 {
2144 virDomainObj *dom = NULL;
2145
2146 dom = virDomainObjListFindByUUID(driver->domains, uuid);
2147 /* domain was removed from the list from the libvirt
2148 * API function in current connection */
2149 if (dom == NULL)
2150 return;
2151
2152 prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_UNDEFINED,
2153 VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
2154
2155 virDomainObjListRemove(driver->domains, dom);
2156 virDomainObjEndAPI(&dom);
2157 return;
2158 }
2159
2160 static void
prlsdkHandlePerfEvent(struct _vzDriver * driver,PRL_HANDLE event,unsigned char * uuid)2161 prlsdkHandlePerfEvent(struct _vzDriver *driver,
2162 PRL_HANDLE event,
2163 unsigned char *uuid)
2164 {
2165 virDomainObj *dom = NULL;
2166 struct vzDomObj *privdom = NULL;
2167
2168 if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid))) {
2169 PrlHandle_Free(event);
2170 return;
2171 }
2172
2173 privdom = dom->privateData;
2174 PrlHandle_Free(privdom->stats);
2175 privdom->stats = event;
2176
2177 virDomainObjEndAPI(&dom);
2178 }
2179
2180 static void
prlsdkHandleMigrationProgress(struct _vzDriver * driver,PRL_HANDLE event,unsigned char * uuid)2181 prlsdkHandleMigrationProgress(struct _vzDriver *driver,
2182 PRL_HANDLE event,
2183 unsigned char *uuid)
2184 {
2185 virDomainObj *dom = NULL;
2186 struct vzDomObj *privdom = NULL;
2187 PRL_UINT32 progress;
2188 PRL_HANDLE param = PRL_INVALID_HANDLE;
2189 PRL_RESULT pret;
2190
2191 if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid)))
2192 return;
2193
2194 pret = PrlEvent_GetParam(event, 0, ¶m);
2195 prlsdkCheckRetGoto(pret, cleanup);
2196
2197 pret = PrlEvtPrm_ToUint32(param, &progress);
2198 prlsdkCheckRetGoto(pret, cleanup);
2199
2200 privdom = dom->privateData;
2201 privdom->job.progress = progress;
2202
2203 cleanup:
2204 PrlHandle_Free(param);
2205 virDomainObjEndAPI(&dom);
2206 }
2207
2208 static PRL_RESULT
prlsdkEventsHandler(PRL_HANDLE prlEvent,PRL_VOID_PTR opaque)2209 prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
2210 {
2211 struct _vzDriver *driver = opaque;
2212 PRL_RESULT pret = PRL_ERR_FAILURE;
2213 PRL_HANDLE_TYPE handleType;
2214 char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
2215 unsigned char uuid[VIR_UUID_BUFLEN];
2216 PRL_EVENT_TYPE prlEventType;
2217
2218 pret = PrlHandle_GetType(prlEvent, &handleType);
2219 prlsdkCheckRetGoto(pret, cleanup);
2220
2221 /* Currently, there is no need to handle anything but events */
2222 if (handleType != PHT_EVENT)
2223 goto cleanup;
2224
2225 if (driver == NULL)
2226 goto cleanup;
2227
2228 pret = prlsdkGetStringParamBuf(PrlEvent_GetIssuerId,
2229 prlEvent, uuidstr, sizeof(uuidstr));
2230 prlsdkCheckRetGoto(pret, cleanup);
2231
2232 pret = PrlEvent_GetType(prlEvent, &prlEventType);
2233 prlsdkCheckRetGoto(pret, cleanup);
2234
2235 if (prlsdkUUIDParse(uuidstr, uuid) < 0) {
2236 VIR_DEBUG("Skipping event type %d", prlEventType);
2237 goto cleanup;
2238 }
2239
2240 switch ((int)prlEventType) {
2241 case PET_DSP_EVT_VM_STATE_CHANGED:
2242 prlsdkHandleVmStateEvent(driver, prlEvent, uuid);
2243 break;
2244 case PET_DSP_EVT_VM_CONFIG_CHANGED:
2245 prlsdkHandleVmConfigEvent(driver, uuid);
2246 break;
2247 case PET_DSP_EVT_VM_CREATED:
2248 case PET_DSP_EVT_VM_ADDED:
2249 prlsdkHandleVmAddedEvent(driver, uuid);
2250 break;
2251 case PET_DSP_EVT_VM_DELETED:
2252 case PET_DSP_EVT_VM_UNREGISTERED:
2253 prlsdkHandleVmRemovedEvent(driver, uuid);
2254 break;
2255 case PET_DSP_EVT_VM_PERFSTATS:
2256 prlsdkHandlePerfEvent(driver, prlEvent, uuid);
2257 /* above function takes own of event */
2258 prlEvent = PRL_INVALID_HANDLE;
2259 break;
2260 case PET_DSP_EVT_DISP_CONNECTION_CLOSED:
2261 vzDestroyDriverConnection();
2262 break;
2263 case PET_DSP_EVT_VM_MIGRATE_PROGRESS_CHANGED:
2264 prlsdkHandleMigrationProgress(driver, prlEvent, uuid);
2265 break;
2266 default:
2267 VIR_DEBUG("Skipping event of type %d", prlEventType);
2268 }
2269
2270 cleanup:
2271 PrlHandle_Free(prlEvent);
2272 return PRL_ERR_SUCCESS;
2273 }
2274
prlsdkStart(virDomainObj * dom)2275 int prlsdkStart(virDomainObj *dom)
2276 {
2277 PRL_HANDLE job = PRL_INVALID_HANDLE;
2278 struct vzDomObj *privdom = dom->privateData;
2279 PRL_RESULT pret;
2280
2281 job = PrlVm_StartEx(privdom->sdkdom, PSM_VM_START, 0);
2282 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2283 prlsdkConvertError(pret);
2284 return -1;
2285 }
2286
2287 return 0;
2288 }
2289
prlsdkKill(virDomainObj * dom)2290 int prlsdkKill(virDomainObj *dom)
2291 {
2292 PRL_HANDLE job = PRL_INVALID_HANDLE;
2293 struct vzDomObj *privdom = dom->privateData;
2294 PRL_RESULT pret;
2295
2296 job = PrlVm_StopEx(privdom->sdkdom, PSM_KILL, 0);
2297 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2298 prlsdkConvertError(pret);
2299 return -1;
2300 }
2301
2302 return 0;
2303 }
2304
prlsdkStop(virDomainObj * dom)2305 int prlsdkStop(virDomainObj *dom)
2306 {
2307 PRL_HANDLE job = PRL_INVALID_HANDLE;
2308 struct vzDomObj *privdom = dom->privateData;
2309 PRL_RESULT pret;
2310
2311 job = PrlVm_StopEx(privdom->sdkdom, PSM_SHUTDOWN, 0);
2312 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2313 prlsdkConvertError(pret);
2314 return -1;
2315 }
2316
2317 return 0;
2318 }
2319
prlsdkPause(virDomainObj * dom)2320 int prlsdkPause(virDomainObj *dom)
2321 {
2322 PRL_HANDLE job = PRL_INVALID_HANDLE;
2323 struct vzDomObj *privdom = dom->privateData;
2324 PRL_RESULT pret;
2325
2326 job = PrlVm_Pause(privdom->sdkdom, false);
2327 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2328 prlsdkConvertError(pret);
2329 return -1;
2330 }
2331
2332 return 0;
2333 }
2334
prlsdkResume(virDomainObj * dom)2335 int prlsdkResume(virDomainObj *dom)
2336 {
2337 PRL_HANDLE job = PRL_INVALID_HANDLE;
2338 struct vzDomObj *privdom = dom->privateData;
2339 PRL_RESULT pret;
2340
2341 job = PrlVm_Resume(privdom->sdkdom);
2342 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2343 prlsdkConvertError(pret);
2344 return -1;
2345 }
2346
2347 return 0;
2348 }
2349
prlsdkSuspend(virDomainObj * dom)2350 int prlsdkSuspend(virDomainObj *dom)
2351 {
2352 PRL_HANDLE job = PRL_INVALID_HANDLE;
2353 struct vzDomObj *privdom = dom->privateData;
2354 PRL_RESULT pret;
2355
2356 job = PrlVm_Suspend(privdom->sdkdom);
2357 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2358 prlsdkConvertError(pret);
2359 return -1;
2360 }
2361
2362 return 0;
2363 }
2364
prlsdkRestart(virDomainObj * dom)2365 int prlsdkRestart(virDomainObj *dom)
2366 {
2367 PRL_HANDLE job = PRL_INVALID_HANDLE;
2368 struct vzDomObj *privdom = dom->privateData;
2369 PRL_RESULT pret;
2370
2371 job = PrlVm_Restart(privdom->sdkdom);
2372 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2373 prlsdkConvertError(pret);
2374 return -1;
2375 }
2376
2377 return 0;
2378 }
2379
prlsdkReset(virDomainObj * dom)2380 int prlsdkReset(virDomainObj *dom)
2381 {
2382 PRL_HANDLE job = PRL_INVALID_HANDLE;
2383 struct vzDomObj *privdom = dom->privateData;
2384 PRL_RESULT pret;
2385
2386 job = PrlVm_Reset(privdom->sdkdom);
2387 if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
2388 prlsdkConvertError(pret);
2389 return -1;
2390 }
2391
2392 return 0;
2393 }
2394
2395 static void
prlsdkConvertError(PRL_RESULT pret)2396 prlsdkConvertError(PRL_RESULT pret)
2397 {
2398 virErrorNumber virerr;
2399
2400 switch (pret) {
2401 case PRL_ERR_DISP_VM_IS_NOT_STARTED:
2402 case PRL_ERR_DISP_VM_IS_NOT_STOPPED:
2403 case PRL_ERR_INVALID_ACTION_REQUESTED:
2404 case PRL_ERR_UNIMPLEMENTED:
2405 virerr = VIR_ERR_OPERATION_INVALID;
2406 break;
2407 default:
2408 virerr = VIR_ERR_OPERATION_FAILED;
2409 }
2410
2411 virResetLastError();
2412 virReportError(virerr, "%s", _("Can't change domain state."));
2413 }
2414
2415 static int
prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom,virDomainDef * def)2416 prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDef *def)
2417 {
2418 size_t i;
2419 PRL_VM_TYPE vmType;
2420 PRL_RESULT pret;
2421 virDomainNumatuneMemMode memMode;
2422 int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS :
2423 VIR_DOMAIN_INPUT_BUS_PS2;
2424
2425 if (def->title) {
2426 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2427 _("titles are not supported by vz driver"));
2428 return -1;
2429 }
2430
2431 if (def->blkio.ndevices > 0) {
2432 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2433 _("blkio parameters are not supported "
2434 "by vz driver"));
2435 return -1;
2436 }
2437
2438 if (virDomainDefGetMemoryTotal(def) != def->mem.cur_balloon) {
2439 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2440 _("changing balloon parameters is not supported "
2441 "by vz driver"));
2442 return -1;
2443 }
2444
2445 if (virDomainDefGetMemoryTotal(def) % (1 << 10) != 0) {
2446 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2447 _("Memory size should be multiple of 1Mb."));
2448 return -1;
2449 }
2450
2451 if (def->mem.nhugepages ||
2452 virMemoryLimitIsSet(def->mem.hard_limit) ||
2453 virMemoryLimitIsSet(def->mem.soft_limit) ||
2454 def->mem.min_guarantee ||
2455 virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
2456
2457 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2458 _("Memory parameter is not supported "
2459 "by vz driver"));
2460 return -1;
2461 }
2462
2463 if (virDomainDefHasVcpusOffline(def)) {
2464 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2465 _("current vcpus must be equal to maxvcpus"));
2466 return -1;
2467 }
2468
2469 if (def->placement_mode) {
2470 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2471 _("changing cpu placement mode is not supported "
2472 "by vz driver"));
2473 return -1;
2474 }
2475
2476 if (def->cputune.shares ||
2477 def->cputune.sharesSpecified ||
2478 def->cputune.period ||
2479 def->cputune.quota) {
2480
2481 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2482 _("cputune is not supported by vz driver"));
2483 return -1;
2484 }
2485
2486 for (i = 0; i < virDomainDefGetVcpusMax(def); i++) {
2487 virDomainVcpuDef *vcpu = virDomainDefGetVcpu(def, i);
2488
2489 if (vcpu->cpumask &&
2490 !virBitmapEqual(def->cpumask, vcpu->cpumask)) {
2491 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2492 _("vcpupin cpumask differs from default cpumask"));
2493 return -1;
2494 }
2495 }
2496
2497
2498 /*
2499 * Though we don't support NUMA configuration at the moment
2500 * virDomainDef *always contain non zero NUMA configuration
2501 * So, just make sure this configuration doesn't differ from auto generated.
2502 */
2503 if ((virDomainNumatuneGetMode(def->numa, -1, &memMode) == 0 &&
2504 memMode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) ||
2505 virDomainNumatuneHasPerNodeBinding(def->numa)) {
2506 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2507 _("numa parameters are not supported "
2508 "by vz driver"));
2509 return -1;
2510 }
2511
2512 if (def->onReboot != VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
2513 def->onPoweroff != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
2514 def->onCrash != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY) {
2515
2516 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2517 _("on_reboot, on_poweroff and on_crash parameters "
2518 "are not supported by vz driver"));
2519 return -1;
2520 }
2521
2522 /* we fill only type and arch fields in vzLoadDomain for
2523 * hvm type and also init for containers, so we can check that all
2524 * other parameters are null and boot devices config is default */
2525
2526 if (def->os.machine != NULL || def->os.bootmenu != 0 ||
2527 def->os.kernel != NULL || def->os.initrd != NULL ||
2528 def->os.cmdline != NULL || def->os.root != NULL ||
2529 def->os.loader != NULL || def->os.bootloader != NULL ||
2530 def->os.bootloaderArgs != NULL || def->os.smbios_mode != 0 ||
2531 def->os.bios.useserial != 0) {
2532
2533 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2534 _("changing OS parameters is not supported "
2535 "by vz driver"));
2536 return -1;
2537 }
2538
2539 pret = PrlVmCfg_GetVmType(sdkdom, &vmType);
2540 if (PRL_FAILED(pret)) {
2541 logPrlError(pret);
2542 return -1;
2543 }
2544
2545 if (!(vmType == PVT_VM && !IS_CT(def)) &&
2546 !(vmType == PVT_CT && IS_CT(def))) {
2547
2548 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2549 _("changing OS type is not supported "
2550 "by vz driver"));
2551 return -1;
2552 }
2553
2554 if (!IS_CT(def)) {
2555 if (def->os.init != NULL || def->os.initargv != NULL) {
2556 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2557 _("unsupported OS parameters"));
2558 return -1;
2559 }
2560 } else {
2561 if (def->os.nBootDevs != 0 ||
2562 STRNEQ_NULLABLE(def->os.init, "/sbin/init") ||
2563 (def->os.initargv != NULL && def->os.initargv[0] != NULL)) {
2564
2565 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2566 _("unsupported OS parameters"));
2567 return -1;
2568 }
2569 }
2570
2571 if (def->emulator) {
2572 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2573 _("changing emulator is not supported "
2574 "by vz driver"));
2575 return -1;
2576 }
2577
2578 for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
2579 if (def->features[i]) {
2580 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2581 _("changing features is not supported "
2582 "by vz driver"));
2583 return -1;
2584 }
2585 }
2586
2587 if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
2588 def->clock.ntimers != 0) {
2589
2590 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2591 _("changing clock parameters is not supported "
2592 "by vz driver"));
2593 return -1;
2594 }
2595
2596 if (!IS_CT(def) && def->nfss != 0) {
2597 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2598 _("Filesystems in VMs are not supported "
2599 "by vz driver"));
2600 return -1;
2601 }
2602
2603 if (def->nsounds != 0 || def->nhostdevs != 0 ||
2604 def->nredirdevs != 0 || def->nsmartcards != 0 ||
2605 def->nparallels || def->nchannels != 0 ||
2606 def->nleases != 0 || def->nhubs != 0) {
2607
2608 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2609 _("changing devices parameters is not supported "
2610 "by vz driver"));
2611 return -1;
2612 }
2613
2614 /* check we have only default input devices */
2615 if (def->ngraphics > 0) {
2616 if (def->ninputs != 2 ||
2617 def->inputs[0]->bus != bus ||
2618 def->inputs[1]->bus != bus ||
2619 !((def->inputs[0]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE &&
2620 def->inputs[1]->type == VIR_DOMAIN_INPUT_TYPE_KBD) ||
2621 (def->inputs[0]->type == VIR_DOMAIN_INPUT_TYPE_KBD &&
2622 def->inputs[1]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE))) {
2623
2624 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2625 _("unsupported input device configuration"));
2626 return -1;
2627 }
2628 } else if (def->ninputs != 0) {
2629 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2630 _("input devices without vnc are not supported"));
2631 return -1;
2632 }
2633
2634 return 0;
2635 }
2636
prlsdkClearDevices(PRL_HANDLE sdkdom)2637 static int prlsdkClearDevices(PRL_HANDLE sdkdom)
2638 {
2639 PRL_RESULT pret;
2640 PRL_UINT32 n, i;
2641 PRL_HANDLE devList;
2642 PRL_HANDLE dev;
2643 int ret = -1;
2644
2645 pret = PrlVmCfg_GetAllDevices(sdkdom, &devList);
2646 prlsdkCheckRetGoto(pret, cleanup);
2647
2648 pret = PrlHndlList_GetItemsCount(devList, &n);
2649 prlsdkCheckRetGoto(pret, cleanup);
2650
2651 for (i = 0; i < n; i++) {
2652 pret = PrlHndlList_GetItem(devList, i, &dev);
2653 prlsdkCheckRetGoto(pret, cleanup);
2654
2655 pret = PrlVmDev_Remove(dev);
2656 PrlHandle_Free(dev);
2657 }
2658
2659 ret = 0;
2660 cleanup:
2661 PrlHandle_Free(devList);
2662 return ret;
2663 }
2664
2665 static int
prlsdkRemoveBootDevices(PRL_HANDLE sdkdom)2666 prlsdkRemoveBootDevices(PRL_HANDLE sdkdom)
2667 {
2668 PRL_RESULT pret;
2669 PRL_UINT32 i, devCount;
2670 PRL_HANDLE dev = PRL_INVALID_HANDLE;
2671 PRL_DEVICE_TYPE devType;
2672
2673 pret = PrlVmCfg_GetBootDevCount(sdkdom, &devCount);
2674 prlsdkCheckRetExit(pret, -1);
2675
2676 for (i = 0; i < devCount; i++) {
2677
2678 /* always get device by index 0, because device list resort after delete */
2679 pret = PrlVmCfg_GetBootDev(sdkdom, 0, &dev);
2680 prlsdkCheckRetExit(pret, -1);
2681
2682 pret = PrlBootDev_GetType(dev, &devType);
2683 prlsdkCheckRetExit(pret, -1);
2684
2685 pret = PrlBootDev_Remove(dev);
2686 prlsdkCheckRetExit(pret, -1);
2687 }
2688
2689 return 0;
2690 }
2691
2692 static int
prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom,PRL_UINT32 devIndex,PRL_DEVICE_TYPE devType,PRL_UINT32 bootSequence)2693 prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom,
2694 PRL_UINT32 devIndex,
2695 PRL_DEVICE_TYPE devType,
2696 PRL_UINT32 bootSequence)
2697 {
2698 PRL_RESULT pret;
2699 PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
2700
2701 pret = PrlVmCfg_CreateBootDev(sdkdom, &bootDev);
2702 prlsdkCheckRetGoto(pret, error);
2703
2704 pret = PrlBootDev_SetIndex(bootDev, devIndex);
2705 prlsdkCheckRetGoto(pret, error);
2706
2707 pret = PrlBootDev_SetType(bootDev, devType);
2708 prlsdkCheckRetGoto(pret, error);
2709
2710 pret = PrlBootDev_SetSequenceIndex(bootDev, bootSequence);
2711 prlsdkCheckRetGoto(pret, error);
2712
2713 pret = PrlBootDev_SetInUse(bootDev, PRL_TRUE);
2714 prlsdkCheckRetGoto(pret, error);
2715
2716 return 0;
2717
2718 error:
2719 if (bootDev != PRL_INVALID_HANDLE)
2720 PrlBootDev_Remove(bootDev);
2721
2722 return -1;
2723 }
2724
prlsdkCheckVideoUnsupportedParams(virDomainDef * def)2725 static int prlsdkCheckVideoUnsupportedParams(virDomainDef *def)
2726 {
2727 virDomainVideoDef *v;
2728
2729 if (IS_CT(def)) {
2730 if (def->nvideos == 0) {
2731 return 0;
2732 } else {
2733 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2734 _("Video adapters are not supported "
2735 "int containers."));
2736 return -1;
2737 }
2738 } else {
2739 if (def->nvideos != 1) {
2740 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2741 _("vz driver supports "
2742 "only one video adapter."));
2743 return -1;
2744 }
2745 }
2746
2747 v = def->videos[0];
2748
2749 if (v->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
2750 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2751 _("vz driver supports "
2752 "only VGA video adapters."));
2753 return -1;
2754 }
2755
2756 if (v->heads != 1) {
2757 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2758 _("vz driver doesn't support "
2759 "multihead video adapters."));
2760 return -1;
2761 }
2762
2763 if (v->accel != NULL && (v->accel->accel2d || v->accel->accel3d)) {
2764 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2765 _("vz driver doesn't support "
2766 "setting video acceleration parameters."));
2767 return -1;
2768 }
2769
2770 return 0;
2771 }
2772
prlsdkCheckSerialUnsupportedParams(virDomainChrDef * chr)2773 static int prlsdkCheckSerialUnsupportedParams(virDomainChrDef *chr)
2774 {
2775 if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
2776 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2777 _("Specified character device type is not supported "
2778 "by vz driver."));
2779 return -1;
2780 }
2781
2782 if (chr->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE) {
2783 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2784 _("Specified character device target type is not "
2785 "supported by vz driver."));
2786 return -1;
2787 }
2788
2789 if (chr->source->type != VIR_DOMAIN_CHR_TYPE_DEV &&
2790 chr->source->type != VIR_DOMAIN_CHR_TYPE_FILE &&
2791 chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX &&
2792 chr->source->type != VIR_DOMAIN_CHR_TYPE_TCP &&
2793 chr->source->type != VIR_DOMAIN_CHR_TYPE_UDP) {
2794
2795
2796 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2797 _("Specified character device source type is not "
2798 "supported by vz driver."));
2799 return -1;
2800 }
2801
2802 if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
2803 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2804 _("Setting device info for character devices is not "
2805 "supported by vz driver."));
2806 return -1;
2807 }
2808
2809 if (chr->source->nseclabels > 0) {
2810 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2811 _("Setting security labels is not "
2812 "supported by vz driver."));
2813 return -1;
2814 }
2815
2816 if (chr->source->type == VIR_DOMAIN_CHR_TYPE_TCP &&
2817 chr->source->data.tcp.protocol != VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW) {
2818 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2819 _("Protocol '%s' is not supported for "
2820 "tcp character device."),
2821 virDomainChrTcpProtocolTypeToString(chr->source->data.tcp.protocol));
2822 return -1;
2823 }
2824
2825 if (chr->source->type == VIR_DOMAIN_CHR_TYPE_UDP &&
2826 (STRNEQ(chr->source->data.udp.bindHost,
2827 chr->source->data.udp.connectHost) ||
2828 STRNEQ(chr->source->data.udp.bindService,
2829 chr->source->data.udp.connectService))) {
2830 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2831 _("Different bind and connect parameters for "
2832 "udp character device is not supported."));
2833 return -1;
2834 }
2835
2836 return 0;
2837 }
2838
prlsdkCheckNetUnsupportedParams(virDomainNetDef * net)2839 static int prlsdkCheckNetUnsupportedParams(virDomainNetDef *net)
2840 {
2841 if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
2842 net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) {
2843 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2844 _("Specified network adapter type is not "
2845 "supported by vz driver."));
2846 return -1;
2847 }
2848
2849 if (net->backend.tap || net->backend.vhost) {
2850 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2851 _("Interface backend parameters are not "
2852 "supported by vz driver."));
2853 return -1;
2854 }
2855
2856 if (net->data.network.portgroup) {
2857 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2858 _("Virtual network portgroups are not "
2859 "supported by vz driver."));
2860 return -1;
2861 }
2862
2863 if (net->tune.sndbuf_specified) {
2864 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2865 _("Setting interface sndbuf is not "
2866 "supported by vz driver."));
2867 return -1;
2868 }
2869
2870 if (net->script) {
2871 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2872 _("Setting interface script is not "
2873 "supported by vz driver."));
2874 return -1;
2875 }
2876
2877 if (net->ifname_guest) {
2878 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2879 _("Setting guest interface name is not "
2880 "supported by vz driver."));
2881 return -1;
2882 }
2883
2884 if (net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
2885 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2886 _("Setting device info for network devices is not "
2887 "supported by vz driver."));
2888 return -1;
2889 }
2890
2891 if (net->filter) {
2892 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2893 _("Setting network filter is not "
2894 "supported by vz driver."));
2895 return -1;
2896 }
2897
2898 if (net->bandwidth) {
2899 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2900 _("Setting network bandwidth is not "
2901 "supported by vz driver."));
2902 return -1;
2903 }
2904
2905 if (net->vlan.trunk) {
2906 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2907 _("Setting up vlans is not "
2908 "supported by vz driver."));
2909 return -1;
2910 }
2911
2912 return 0;
2913 }
2914
prlsdkCheckFSUnsupportedParams(virDomainFSDef * fs)2915 static int prlsdkCheckFSUnsupportedParams(virDomainFSDef *fs)
2916 {
2917 if (fs->type != VIR_DOMAIN_FS_TYPE_FILE &&
2918 fs->type != VIR_DOMAIN_FS_TYPE_VOLUME) {
2919 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2920 _("Only file based or volume based filesystems "
2921 "are supported by vz driver."));
2922 return -1;
2923 }
2924
2925 if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) {
2926 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2927 _("Only ploop fs driver is "
2928 "supported by vz driver."));
2929 return -1;
2930 }
2931
2932 if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
2933 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2934 _("Changing fs access mode is not "
2935 "supported by vz driver."));
2936 return -1;
2937 }
2938
2939 if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) {
2940 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2941 _("Changing fs write policy is not "
2942 "supported by vz driver."));
2943 return -1;
2944 }
2945
2946 if (fs->format != VIR_STORAGE_FILE_PLOOP) {
2947 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2948 _("Only ploop disk images are "
2949 "supported by vz driver."));
2950 return -1;
2951 }
2952
2953 if (fs->readonly) {
2954 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2955 _("Setting readonly for filesystems is "
2956 "not supported by vz driver."));
2957 return -1;
2958 }
2959
2960 if (fs->space_hard_limit || fs->space_soft_limit) {
2961 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2962 _("Setting fs quotas is not "
2963 "supported by vz driver."));
2964 return -1;
2965 }
2966
2967 return 0;
2968 }
2969
prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom,virDomainGraphicsDef * gr)2970 static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom,
2971 virDomainGraphicsDef *gr)
2972 {
2973 virDomainGraphicsListenDef *glisten;
2974 PRL_RESULT pret;
2975
2976 if (!gr) {
2977 pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED);
2978 prlsdkCheckRetExit(pret, -1);
2979 return 0;
2980 }
2981
2982 pret = PrlVmCfg_SetVNCPassword(sdkdom, gr->data.vnc.auth.passwd ? : "");
2983 prlsdkCheckRetExit(pret, -1);
2984
2985 if (gr->data.vnc.autoport) {
2986 pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_AUTO);
2987 prlsdkCheckRetExit(pret, -1);
2988 } else {
2989 pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_MANUAL);
2990 prlsdkCheckRetExit(pret, -1);
2991
2992 pret = PrlVmCfg_SetVNCPort(sdkdom, gr->data.vnc.port);
2993 prlsdkCheckRetExit(pret, -1);
2994 }
2995
2996 glisten = virDomainGraphicsGetListen(gr, 0);
2997 pret = PrlVmCfg_SetVNCHostName(sdkdom, glisten && glisten->address ?
2998 glisten->address : VIR_LOOPBACK_IPV4_ADDR);
2999 prlsdkCheckRetExit(pret, -1);
3000
3001 return 0;
3002 }
3003
prlsdkApplyVideoParams(PRL_HANDLE sdkdom G_GNUC_UNUSED,virDomainDef * def)3004 static int prlsdkApplyVideoParams(PRL_HANDLE sdkdom G_GNUC_UNUSED, virDomainDef *def)
3005 {
3006 PRL_RESULT pret;
3007
3008 if (def->nvideos == 0)
3009 return 0;
3010
3011 if (IS_CT(def)) {
3012 /* ignore video parameters */
3013 return 0;
3014 }
3015
3016 if (prlsdkCheckVideoUnsupportedParams(def))
3017 return -1;
3018
3019 pret = PrlVmCfg_SetVideoRamSize(sdkdom, def->videos[0]->vram >> 10);
3020 prlsdkCheckRetExit(pret, -1);
3021
3022 return 0;
3023 }
3024
prlsdkAddSerial(PRL_HANDLE sdkdom,virDomainChrDef * chr)3025 static int prlsdkAddSerial(PRL_HANDLE sdkdom, virDomainChrDef *chr)
3026 {
3027 PRL_RESULT pret;
3028 PRL_HANDLE sdkchr = PRL_INVALID_HANDLE;
3029 PRL_VM_DEV_EMULATION_TYPE emutype;
3030 PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode = PSP_SERIAL_SOCKET_SERVER;
3031 char *path;
3032 char *url = NULL;
3033 int ret = -1;
3034
3035 if (prlsdkCheckSerialUnsupportedParams(chr) < 0)
3036 return -1;
3037
3038 pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_SERIAL_PORT, &sdkchr);
3039 prlsdkCheckRetGoto(pret, cleanup);
3040
3041 switch (chr->source->type) {
3042 case VIR_DOMAIN_CHR_TYPE_DEV:
3043 emutype = PDT_USE_REAL_DEVICE;
3044 path = chr->source->data.file.path;
3045 break;
3046 case VIR_DOMAIN_CHR_TYPE_FILE:
3047 emutype = PDT_USE_OUTPUT_FILE;
3048 path = chr->source->data.file.path;
3049 break;
3050 case VIR_DOMAIN_CHR_TYPE_UNIX:
3051 emutype = PDT_USE_SERIAL_PORT_SOCKET_MODE;
3052 path = chr->source->data.nix.path;
3053 if (!chr->source->data.nix.listen)
3054 socket_mode = PSP_SERIAL_SOCKET_CLIENT;
3055 break;
3056 case VIR_DOMAIN_CHR_TYPE_TCP:
3057 emutype = PDT_USE_TCP;
3058 url = g_strdup_printf("%s:%s", chr->source->data.tcp.host,
3059 chr->source->data.tcp.service);
3060 if (!chr->source->data.tcp.listen)
3061 socket_mode = PSP_SERIAL_SOCKET_CLIENT;
3062 path = url;
3063 break;
3064 case VIR_DOMAIN_CHR_TYPE_UDP:
3065 emutype = PDT_USE_UDP;
3066 url = g_strdup_printf("%s:%s", chr->source->data.udp.bindHost,
3067 chr->source->data.udp.bindService);
3068 path = url;
3069 break;
3070 default:
3071 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3072 _("vz driver doesn't support "
3073 "specified serial source type."));
3074 goto cleanup;
3075 }
3076
3077 pret = PrlVmDev_SetEmulatedType(sdkchr, emutype);
3078 prlsdkCheckRetGoto(pret, cleanup);
3079
3080 pret = PrlVmDev_SetSysName(sdkchr, path);
3081 prlsdkCheckRetGoto(pret, cleanup);
3082
3083 pret = PrlVmDev_SetFriendlyName(sdkchr, path);
3084 prlsdkCheckRetGoto(pret, cleanup);
3085
3086 pret = PrlVmDevSerial_SetSocketMode(sdkchr, socket_mode);
3087 prlsdkCheckRetGoto(pret, cleanup);
3088
3089 pret = PrlVmDev_SetEnabled(sdkchr, 1);
3090 prlsdkCheckRetGoto(pret, cleanup);
3091
3092 pret = PrlVmDev_SetIndex(sdkchr, chr->target.port);
3093 prlsdkCheckRetGoto(pret, cleanup);
3094
3095 ret = 0;
3096 cleanup:
3097 PrlHandle_Free(sdkchr);
3098 VIR_FREE(url);
3099 return ret;
3100 }
3101
3102 #define PRL_MAC_STRING_BUFNAME 13
3103
prlsdkFormatMac(virMacAddr * mac,char * macstr)3104 static const char * prlsdkFormatMac(virMacAddr *mac, char *macstr)
3105 {
3106 g_snprintf(macstr, PRL_MAC_STRING_BUFNAME,
3107 "%02X%02X%02X%02X%02X%02X",
3108 mac->addr[0], mac->addr[1], mac->addr[2],
3109 mac->addr[3], mac->addr[4], mac->addr[5]);
3110 macstr[PRL_MAC_STRING_BUFNAME - 1] = '\0';
3111 return macstr;
3112 }
3113
prlsdkConfigureGateways(PRL_HANDLE sdknet,virDomainNetDef * net)3114 static int prlsdkConfigureGateways(PRL_HANDLE sdknet, virDomainNetDef *net)
3115 {
3116 int ret = -1;
3117 size_t i;
3118 virNetDevIPRoute *route4 = NULL;
3119 virNetDevIPRoute *route6 = NULL;
3120 char *gw4 = NULL, *gw6 = NULL;
3121 PRL_RESULT pret;
3122
3123 for (i = 0; i < net->guestIP.nroutes; i++) {
3124 virSocketAddr *addrdst;
3125 virSocketAddr *gateway;
3126 virSocketAddr zero;
3127
3128 addrdst = virNetDevIPRouteGetAddress(net->guestIP.routes[i]);
3129 gateway = virNetDevIPRouteGetGateway(net->guestIP.routes[i]);
3130
3131 ignore_value(virSocketAddrParse(&zero,
3132 (VIR_SOCKET_ADDR_IS_FAMILY(addrdst, AF_INET)
3133 ? VIR_SOCKET_ADDR_IPV4_ALL
3134 : VIR_SOCKET_ADDR_IPV6_ALL),
3135 VIR_SOCKET_ADDR_FAMILY(addrdst)));
3136 /* virSocketAddrParse raises an error
3137 * and we are not going to report it, reset it explicitly */
3138 virResetLastError();
3139
3140 if (!virSocketAddrEqual(addrdst, &zero)) {
3141 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3142 _("Support only default gateway"));
3143 return -1;
3144 }
3145
3146 switch (VIR_SOCKET_ADDR_FAMILY(gateway)) {
3147 case AF_INET:
3148 if (route4) {
3149 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3150 _("Support only one IPv4 default gateway"));
3151 return -1;
3152 }
3153
3154 route4 = net->guestIP.routes[i];
3155
3156 break;
3157 case AF_INET6:
3158 if (route6) {
3159 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3160 _("Support only one IPv6 default gateway"));
3161 return -1;
3162 }
3163
3164 route6 = net->guestIP.routes[i];
3165
3166 break;
3167 default:
3168 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3169 _("Unsupported address family %d "
3170 "Only IPv4 or IPv6 default gateway"),
3171 VIR_SOCKET_ADDR_FAMILY(gateway));
3172
3173 return -1;
3174 }
3175 }
3176
3177 if (route4 &&
3178 !(gw4 = virSocketAddrFormat(virNetDevIPRouteGetGateway(route4))))
3179 goto cleanup;
3180
3181 pret = PrlVmDevNet_SetDefaultGateway(sdknet, gw4 ? : "");
3182 prlsdkCheckRetGoto(pret, cleanup);
3183
3184 if (route6 &&
3185 !(gw6 = virSocketAddrFormat(virNetDevIPRouteGetGateway(route6))))
3186 goto cleanup;
3187
3188 pret = PrlVmDevNet_SetDefaultGatewayIPv6(sdknet, gw6 ? : "");
3189 prlsdkCheckRetGoto(pret, cleanup);
3190
3191 ret = 0;
3192
3193 cleanup:
3194 VIR_FREE(gw4);
3195 VIR_FREE(gw6);
3196
3197 return ret;
3198 }
3199
prlsdkConfigureNet(struct _vzDriver * driver G_GNUC_UNUSED,virDomainObj * dom G_GNUC_UNUSED,PRL_HANDLE sdkdom,virDomainNetDef * net,bool isCt,bool create)3200 static int prlsdkConfigureNet(struct _vzDriver *driver G_GNUC_UNUSED,
3201 virDomainObj *dom G_GNUC_UNUSED,
3202 PRL_HANDLE sdkdom,
3203 virDomainNetDef *net,
3204 bool isCt, bool create)
3205 {
3206 PRL_RESULT pret;
3207 PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
3208 PRL_HANDLE addrlist = PRL_INVALID_HANDLE;
3209 size_t i;
3210 int ret = -1;
3211 char macstr[PRL_MAC_STRING_BUFNAME];
3212 char *addrstr = NULL;
3213 bool ipv6present = false;
3214 bool ipv4present = false;
3215
3216 if (prlsdkCheckNetUnsupportedParams(net) < 0)
3217 return -1;
3218
3219 if (create) {
3220 pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_GENERIC_NETWORK_ADAPTER, &sdknet);
3221 prlsdkCheckRetGoto(pret, cleanup);
3222 } else {
3223 sdknet = prlsdkFindNetByMAC(sdkdom, &net->mac);
3224 if (sdknet == PRL_INVALID_HANDLE)
3225 return -1;
3226 }
3227
3228 pret = PrlVmDev_SetEnabled(sdknet, 1);
3229 prlsdkCheckRetGoto(pret, cleanup);
3230
3231 pret = PrlVmDev_SetConnected(sdknet, net->linkstate !=
3232 VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN);
3233
3234 prlsdkCheckRetGoto(pret, cleanup);
3235
3236 if (net->ifname) {
3237 pret = PrlVmDevNet_SetHostInterfaceName(sdknet, net->ifname);
3238 prlsdkCheckRetGoto(pret, cleanup);
3239 }
3240
3241 prlsdkFormatMac(&net->mac, macstr);
3242 pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
3243 prlsdkCheckRetGoto(pret, cleanup);
3244
3245 pret = PrlApi_CreateStringsList(&addrlist);
3246 prlsdkCheckRetGoto(pret, cleanup);
3247
3248 for (i = 0; i < net->guestIP.nips; i++) {
3249 char *tmpstr;
3250
3251 if (AF_INET == VIR_SOCKET_ADDR_FAMILY(&net->guestIP.ips[i]->address))
3252 ipv4present = true;
3253 else if (AF_INET6 == VIR_SOCKET_ADDR_FAMILY(&net->guestIP.ips[i]->address))
3254 ipv6present = true;
3255 else
3256 continue;
3257
3258 if (!(tmpstr = virSocketAddrFormat(&net->guestIP.ips[i]->address)))
3259 goto cleanup;
3260
3261 addrstr = g_strdup_printf("%s/%d", tmpstr, net->guestIP.ips[i]->prefix);
3262
3263 VIR_FREE(tmpstr);
3264 pret = PrlStrList_AddItem(addrlist, addrstr);
3265 prlsdkCheckRetGoto(pret, cleanup);
3266
3267 VIR_FREE(addrstr);
3268 }
3269
3270 if (ipv4present || ipv6present) {
3271 pret = PrlVmDevNet_SetNetAddresses(sdknet, addrlist);
3272 prlsdkCheckRetGoto(pret, cleanup);
3273 }
3274
3275 pret = PrlVmDevNet_SetConfigureWithDhcp(sdknet, !ipv4present);
3276 prlsdkCheckRetGoto(pret, cleanup);
3277
3278 pret = PrlVmDevNet_SetConfigureWithDhcpIPv6(sdknet, !ipv6present);
3279 prlsdkCheckRetGoto(pret, cleanup);
3280
3281 pret = PrlVmDevNet_SetAutoApply(sdknet, true);
3282 prlsdkCheckRetGoto(pret, cleanup);
3283
3284 if (prlsdkConfigureGateways(sdknet, net))
3285 goto cleanup;
3286
3287 if (isCt) {
3288 if (net->model != VIR_DOMAIN_NET_MODEL_UNKNOWN)
3289 VIR_WARN("Setting network adapter for containers is not "
3290 "supported by vz driver.");
3291 } else {
3292 if (net->model == VIR_DOMAIN_NET_MODEL_RTL8139) {
3293 pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_RTL);
3294 } else if (net->model == VIR_DOMAIN_NET_MODEL_E1000) {
3295 pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000);
3296 } else if (net->model == VIR_DOMAIN_NET_MODEL_VIRTIO) {
3297 pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_VIRTIO);
3298 } else {
3299 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3300 _("Specified network adapter model is not "
3301 "supported by vz driver."));
3302 goto cleanup;
3303 }
3304 prlsdkCheckRetGoto(pret, cleanup);
3305 }
3306
3307 if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
3308 if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) {
3309 pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
3310 prlsdkCheckRetGoto(pret, cleanup);
3311 } else {
3312 pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_NETWORK);
3313 prlsdkCheckRetGoto(pret, cleanup);
3314
3315 pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
3316 prlsdkCheckRetGoto(pret, cleanup);
3317 }
3318
3319 } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
3320
3321 pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGE);
3322 prlsdkCheckRetGoto(pret, cleanup);
3323
3324 pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.bridge.brname);
3325 prlsdkCheckRetGoto(pret, cleanup);
3326 }
3327
3328 pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet,
3329 net->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES);
3330 prlsdkCheckRetGoto(pret, cleanup);
3331
3332 ret = 0;
3333 cleanup:
3334 VIR_FREE(addrstr);
3335 PrlHandle_Free(addrlist);
3336 PrlHandle_Free(sdknet);
3337 return ret;
3338 }
3339
3340 static PRL_HANDLE
prlsdkFindNetByMAC(PRL_HANDLE sdkdom,virMacAddr * mac)3341 prlsdkFindNetByMAC(PRL_HANDLE sdkdom, virMacAddr *mac)
3342 {
3343 PRL_RESULT pret;
3344 PRL_UINT32 adaptersCount;
3345 PRL_UINT32 i;
3346 PRL_HANDLE adapter = PRL_INVALID_HANDLE;
3347 char adapterMac[PRL_MAC_STRING_BUFNAME];
3348 char expectedMac[PRL_MAC_STRING_BUFNAME];
3349 char virMac[VIR_MAC_STRING_BUFLEN];
3350
3351 prlsdkFormatMac(mac, expectedMac);
3352
3353 pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &adaptersCount);
3354 prlsdkCheckRetGoto(pret, cleanup);
3355
3356 for (i = 0; i < adaptersCount; ++i) {
3357 pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &adapter);
3358 prlsdkCheckRetGoto(pret, cleanup);
3359
3360 pret = prlsdkGetStringParamBuf(PrlVmDevNet_GetMacAddress,
3361 adapter, adapterMac, sizeof(adapterMac));
3362 prlsdkCheckRetGoto(pret, cleanup);
3363
3364 if (STREQ(adapterMac, expectedMac))
3365 return adapter;
3366
3367 PrlHandle_Free(adapter);
3368 adapter = PRL_INVALID_HANDLE;
3369 }
3370
3371 virReportError(VIR_ERR_INTERNAL_ERROR,
3372 _("No net with mac '%s'"), virMacAddrFormat(mac, virMac));
3373
3374 cleanup:
3375 PrlHandle_Free(adapter);
3376 return adapter;
3377 }
3378
prlsdkConfigureDisk(struct _vzDriver * driver,PRL_HANDLE sdkdom,virDomainDiskDef * disk,bool create)3379 static int prlsdkConfigureDisk(struct _vzDriver *driver,
3380 PRL_HANDLE sdkdom,
3381 virDomainDiskDef *disk,
3382 bool create)
3383 {
3384 PRL_RESULT pret;
3385 PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
3386 int ret = -1;
3387 PRL_VM_DEV_EMULATION_TYPE emutype;
3388 PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus;
3389 int idx;
3390 virDomainDeviceDriveAddress *drive;
3391 PRL_DEVICE_TYPE devType;
3392 PRL_CLUSTERED_DEVICE_SUBTYPE scsiModel;
3393 const char *path = disk->src->path ? : "";
3394
3395 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3396 devType = PDE_HARD_DISK;
3397 else
3398 devType = PDE_OPTICAL_DISK;
3399
3400 if (create) {
3401 pret = PrlVmCfg_CreateVmDev(sdkdom, devType, &sdkdisk);
3402 prlsdkCheckRetGoto(pret, cleanup);
3403 } else {
3404 sdkdisk = prlsdkGetDisk(sdkdom, disk);
3405 if (sdkdisk == PRL_INVALID_HANDLE)
3406 return -1;
3407 }
3408
3409 pret = PrlVmDev_SetEnabled(sdkdisk, 1);
3410 prlsdkCheckRetGoto(pret, cleanup);
3411
3412 pret = PrlVmDev_SetConnected(sdkdisk, 1);
3413 prlsdkCheckRetGoto(pret, cleanup);
3414
3415 if (disk->src->type == VIR_STORAGE_TYPE_FILE)
3416 emutype = PDT_USE_IMAGE_FILE;
3417 else
3418 emutype = PDT_USE_REAL_DEVICE;
3419
3420 pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype);
3421 prlsdkCheckRetGoto(pret, cleanup);
3422
3423 pret = PrlVmDev_SetSysName(sdkdisk, path);
3424 prlsdkCheckRetGoto(pret, cleanup);
3425
3426 pret = PrlVmDev_SetFriendlyName(sdkdisk, path);
3427 prlsdkCheckRetGoto(pret, cleanup);
3428
3429 drive = &disk->info.addr.drive;
3430
3431 switch (disk->bus) {
3432 case VIR_DOMAIN_DISK_BUS_IDE:
3433 sdkbus = PMS_IDE_DEVICE;
3434 idx = 2 * drive->bus + drive->unit;
3435 break;
3436 case VIR_DOMAIN_DISK_BUS_SCSI:
3437 sdkbus = PMS_SCSI_DEVICE;
3438 idx = drive->unit;
3439 break;
3440 case VIR_DOMAIN_DISK_BUS_SATA:
3441 sdkbus = PMS_SATA_DEVICE;
3442 idx = drive->unit;
3443 break;
3444 case VIR_DOMAIN_DISK_BUS_FDC:
3445 case VIR_DOMAIN_DISK_BUS_NONE:
3446 case VIR_DOMAIN_DISK_BUS_VIRTIO:
3447 case VIR_DOMAIN_DISK_BUS_XEN:
3448 case VIR_DOMAIN_DISK_BUS_USB:
3449 case VIR_DOMAIN_DISK_BUS_UML:
3450 case VIR_DOMAIN_DISK_BUS_SD:
3451 case VIR_DOMAIN_DISK_BUS_LAST:
3452 default:
3453 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3454 _("Specified disk bus is not "
3455 "supported by vz driver."));
3456 goto cleanup;
3457 }
3458
3459 if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
3460 if (vzGetDefaultSCSIModel(driver, &scsiModel) < 0)
3461 goto cleanup;
3462 pret = PrlVmDev_SetSubType(sdkdisk, scsiModel);
3463 prlsdkCheckRetGoto(pret, cleanup);
3464 }
3465
3466 pret = PrlVmDev_SetIfaceType(sdkdisk, sdkbus);
3467 prlsdkCheckRetGoto(pret, cleanup);
3468
3469 pret = PrlVmDev_SetStackIndex(sdkdisk, idx);
3470 prlsdkCheckRetGoto(pret, cleanup);
3471
3472 if (devType == PDE_HARD_DISK) {
3473 pret = PrlVmDevHd_SetSerialNumber(sdkdisk, disk->serial);
3474 prlsdkCheckRetGoto(pret, cleanup);
3475 }
3476
3477 return 0;
3478 cleanup:
3479 PrlHandle_Free(sdkdisk);
3480 return ret;
3481 }
3482
3483 static PRL_HANDLE
prlsdkGetDisk(PRL_HANDLE sdkdom,virDomainDiskDef * disk)3484 prlsdkGetDisk(PRL_HANDLE sdkdom, virDomainDiskDef *disk)
3485 {
3486 PRL_RESULT pret;
3487 PRL_UINT32 num;
3488 size_t i;
3489 PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
3490 virDomainDiskBus bus;
3491 char *dst = NULL;
3492 PRL_DEVICE_TYPE devType;
3493
3494 if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3495 devType = PDE_HARD_DISK;
3496 else
3497 devType = PDE_OPTICAL_DISK;
3498
3499 pret = PrlVmCfg_GetDevsCountByType(sdkdom, devType, &num);
3500 prlsdkCheckRetGoto(pret, error);
3501
3502 for (i = 0; i < num; ++i) {
3503 pret = PrlVmCfg_GetDevByType(sdkdom, devType, i, &sdkdisk);
3504 prlsdkCheckRetGoto(pret, error);
3505
3506 if (prlsdkGetDiskId(sdkdisk, &bus, &dst) < 0)
3507 goto error;
3508
3509 if (disk->bus == bus && STREQ(disk->dst, dst)) {
3510 VIR_FREE(dst);
3511 return sdkdisk;
3512 }
3513
3514 PrlHandle_Free(sdkdisk);
3515 sdkdisk = PRL_INVALID_HANDLE;
3516 VIR_FREE(dst);
3517 }
3518
3519 virReportError(VIR_ERR_INTERNAL_ERROR,
3520 _("No disk with bus '%s' and target '%s'"),
3521 virDomainDiskBusTypeToString(disk->bus), disk->dst);
3522 return PRL_INVALID_HANDLE;
3523
3524 error:
3525 VIR_FREE(dst);
3526 PrlHandle_Free(sdkdisk);
3527 return PRL_INVALID_HANDLE;
3528 }
3529
3530 int
prlsdkAttachDevice(struct _vzDriver * driver,virDomainObj * dom,virDomainDeviceDef * dev)3531 prlsdkAttachDevice(struct _vzDriver *driver,
3532 virDomainObj *dom,
3533 virDomainDeviceDef *dev)
3534 {
3535 struct vzDomObj *privdom = dom->privateData;
3536 PRL_HANDLE job = PRL_INVALID_HANDLE;
3537
3538 job = PrlVm_BeginEdit(privdom->sdkdom);
3539 if (PRL_FAILED(waitDomainJob(job, dom)))
3540 return -1;
3541
3542 switch (dev->type) {
3543 case VIR_DOMAIN_DEVICE_DISK:
3544 if (prlsdkConfigureDisk(driver, privdom->sdkdom,
3545 dev->data.disk, true) < 0)
3546 return -1;
3547
3548 break;
3549 case VIR_DOMAIN_DEVICE_NET:
3550 if (!IS_CT(dom->def)) {
3551 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3552 _("attaching network device to VM is unsupported"));
3553 return -1;
3554 }
3555
3556 if (prlsdkConfigureNet(driver, dom, privdom->sdkdom, dev->data.net,
3557 IS_CT(dom->def), true) < 0)
3558 return -1;
3559
3560 break;
3561 case VIR_DOMAIN_DEVICE_GRAPHICS:
3562 if (dom->def->ngraphics > 0) {
3563 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3564 _("domain already has VNC graphics"));
3565 return -1;
3566 }
3567
3568 if (prlsdkApplyGraphicsParams(privdom->sdkdom, dev->data.graphics) < 0)
3569 return -1;
3570
3571 break;
3572 default:
3573 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3574 _("attaching device type '%s' is unsupported"),
3575 virDomainDeviceTypeToString(dev->type));
3576 return -1;
3577 }
3578
3579 job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
3580 if (PRL_FAILED(waitDomainJob(job, dom)))
3581 return -1;
3582
3583 return 0;
3584 }
3585
3586 int
prlsdkDetachDevice(struct _vzDriver * driver G_GNUC_UNUSED,virDomainObj * dom,virDomainDeviceDef * dev)3587 prlsdkDetachDevice(struct _vzDriver *driver G_GNUC_UNUSED,
3588 virDomainObj *dom,
3589 virDomainDeviceDef *dev)
3590 {
3591 int ret = -1;
3592 struct vzDomObj *privdom = dom->privateData;
3593 PRL_HANDLE job = PRL_INVALID_HANDLE;
3594 PRL_HANDLE sdkdev = PRL_INVALID_HANDLE;
3595 PRL_RESULT pret;
3596
3597 job = PrlVm_BeginEdit(privdom->sdkdom);
3598 if (PRL_FAILED(waitDomainJob(job, dom)))
3599 goto cleanup;
3600
3601 switch (dev->type) {
3602 case VIR_DOMAIN_DEVICE_DISK:
3603 sdkdev = prlsdkGetDisk(privdom->sdkdom, dev->data.disk);
3604 if (sdkdev == PRL_INVALID_HANDLE)
3605 goto cleanup;
3606
3607 pret = PrlVmDev_Remove(sdkdev);
3608 prlsdkCheckRetGoto(pret, cleanup);
3609
3610 break;
3611 case VIR_DOMAIN_DEVICE_NET:
3612 if (!IS_CT(dom->def)) {
3613 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3614 _("detaching network device from VM is unsupported"));
3615 goto cleanup;
3616 }
3617
3618 sdkdev = prlsdkFindNetByMAC(privdom->sdkdom, &dev->data.net->mac);
3619 if (sdkdev == PRL_INVALID_HANDLE)
3620 goto cleanup;
3621
3622 pret = PrlVmDev_Remove(sdkdev);
3623 prlsdkCheckRetGoto(pret, cleanup);
3624
3625 break;
3626 case VIR_DOMAIN_DEVICE_GRAPHICS:
3627 if (dom->def->ngraphics < 1) {
3628 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3629 _("cannot find VNC graphics device"));
3630 goto cleanup;
3631 }
3632
3633 if (prlsdkApplyGraphicsParams(privdom->sdkdom, NULL) < 0)
3634 goto cleanup;
3635
3636 break;
3637 default:
3638 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3639 _("detaching device type '%s' is unsupported"),
3640 virDomainDeviceTypeToString(dev->type));
3641 goto cleanup;
3642 }
3643
3644 job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
3645 if (PRL_FAILED(waitDomainJob(job, dom)))
3646 goto cleanup;
3647
3648 ret = 0;
3649
3650 cleanup:
3651
3652 PrlHandle_Free(sdkdev);
3653 return ret;
3654 }
3655
3656 int
prlsdkUpdateDevice(struct _vzDriver * driver,virDomainObj * dom,virDomainDeviceDef * dev)3657 prlsdkUpdateDevice(struct _vzDriver *driver,
3658 virDomainObj *dom,
3659 virDomainDeviceDef *dev)
3660 {
3661 struct vzDomObj *privdom = dom->privateData;
3662 PRL_HANDLE job = PRL_INVALID_HANDLE;
3663
3664 job = PrlVm_BeginEdit(privdom->sdkdom);
3665 if (PRL_FAILED(waitDomainJob(job, dom)))
3666 return -1;
3667
3668 switch (dev->type) {
3669 case VIR_DOMAIN_DEVICE_DISK:
3670 if (prlsdkConfigureDisk(driver, privdom->sdkdom, dev->data.disk,
3671 false) < 0)
3672 return -1;
3673
3674 break;
3675 case VIR_DOMAIN_DEVICE_NET:
3676 if (prlsdkConfigureNet(driver, dom, privdom->sdkdom, dev->data.net,
3677 IS_CT(dom->def), false) < 0)
3678 return -1;
3679
3680 break;
3681 case VIR_DOMAIN_DEVICE_GRAPHICS:
3682 if (dom->def->ngraphics < 1) {
3683 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3684 _("cannot find VNC graphics device"));
3685 return -1;
3686 }
3687
3688 if (prlsdkApplyGraphicsParams(privdom->sdkdom, dev->data.graphics) < 0)
3689 return -1;
3690
3691 break;
3692 default:
3693 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3694 _("updating device type '%s' is unsupported"),
3695 virDomainDeviceTypeToString(dev->type));
3696 return -1;
3697 }
3698
3699 job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
3700 if (PRL_FAILED(waitDomainJob(job, dom)))
3701 return -1;
3702
3703 return 0;
3704 }
3705
3706 static int
prlsdkAddFS(PRL_HANDLE sdkdom,virDomainFSDef * fs)3707 prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDef *fs)
3708 {
3709 PRL_RESULT pret;
3710 PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
3711 int ret = -1;
3712 char *storage = NULL;
3713
3714 if (fs->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
3715 return 0;
3716
3717 if (prlsdkCheckFSUnsupportedParams(fs) < 0)
3718 return -1;
3719
3720 pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk);
3721 prlsdkCheckRetGoto(pret, cleanup);
3722
3723 if (fs->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
3724 storage = g_strdup_printf("libvirt://localhost/%s/%s",
3725 fs->src->srcpool->pool, fs->src->srcpool->volume);
3726 pret = PrlVmDevHd_SetStorageURL(sdkdisk, storage);
3727 prlsdkCheckRetGoto(pret, cleanup);
3728 }
3729
3730 pret = PrlVmDev_SetEnabled(sdkdisk, 1);
3731 prlsdkCheckRetGoto(pret, cleanup);
3732
3733 pret = PrlVmDev_SetConnected(sdkdisk, 1);
3734 prlsdkCheckRetGoto(pret, cleanup);
3735
3736 pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE);
3737 prlsdkCheckRetGoto(pret, cleanup);
3738
3739 pret = PrlVmDev_SetSysName(sdkdisk, fs->src->path);
3740 prlsdkCheckRetGoto(pret, cleanup);
3741
3742 pret = PrlVmDev_SetImagePath(sdkdisk, fs->src->path);
3743 prlsdkCheckRetGoto(pret, cleanup);
3744
3745 pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src->path);
3746 prlsdkCheckRetGoto(pret, cleanup);
3747
3748 pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst);
3749 prlsdkCheckRetGoto(pret, cleanup);
3750
3751 ret = 0;
3752
3753 cleanup:
3754 VIR_FREE(storage);
3755 PrlHandle_Free(sdkdisk);
3756 return ret;
3757 }
3758
3759 static int
prlsdkSetBootOrderCt(PRL_HANDLE sdkdom,virDomainDef * def)3760 prlsdkSetBootOrderCt(PRL_HANDLE sdkdom, virDomainDef *def)
3761 {
3762 size_t i;
3763 PRL_HANDLE hdd = PRL_INVALID_HANDLE;
3764 PRL_RESULT pret;
3765 bool rootfs = false;
3766 int ret = -1;
3767
3768 for (i = 0; i < def->nfss; i++) {
3769
3770 pret = prlsdkAddDeviceToBootList(sdkdom, i, PDE_HARD_DISK, i + 1);
3771 prlsdkCheckRetExit(pret, -1);
3772
3773 if (STREQ(def->fss[i]->dst, "/"))
3774 rootfs = true;
3775 }
3776
3777 if (!rootfs) {
3778 /* if we have root mounted we don't need to explicitly set boot order */
3779 pret = PrlVmCfg_GetHardDisk(sdkdom, def->nfss, &hdd);
3780 prlsdkCheckRetExit(pret, -1);
3781
3782 PrlVmDevHd_SetMountPoint(hdd, "/");
3783 prlsdkCheckRetGoto(pret, cleanup);
3784 }
3785
3786 ret = 0;
3787
3788 cleanup:
3789 PrlHandle_Free(hdd);
3790 return ret;
3791 }
3792
3793 static int
prlsdkSetBootOrderVm(PRL_HANDLE sdkdom,virDomainDef * def)3794 prlsdkSetBootOrderVm(PRL_HANDLE sdkdom, virDomainDef *def)
3795 {
3796 size_t i;
3797 int idx[VIR_DOMAIN_BOOT_LAST] = { 0 };
3798 int bootIndex = 0;
3799 PRL_RESULT pret;
3800 PRL_UINT32 num;
3801 int sdkType;
3802 virDomainBootOrder virType;
3803
3804 for (i = 0; i < def->os.nBootDevs; ++i) {
3805 virType = def->os.bootDevs[i];
3806
3807 switch ((int)virType) {
3808 case VIR_DOMAIN_BOOT_CDROM:
3809 sdkType = PDE_OPTICAL_DISK;
3810 break;
3811 case VIR_DOMAIN_BOOT_DISK:
3812 sdkType = PDE_HARD_DISK;
3813 break;
3814 case VIR_DOMAIN_BOOT_NET:
3815 sdkType = PDE_GENERIC_NETWORK_ADAPTER;
3816 break;
3817 default:
3818 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3819 _("Unsupported boot device type: '%s'"),
3820 virDomainBootTypeToString(virType));
3821 return -1;
3822 }
3823
3824 pret = PrlVmCfg_GetDevsCountByType(sdkdom, sdkType, &num);
3825 prlsdkCheckRetExit(pret, -1);
3826
3827 pret = prlsdkAddDeviceToBootList(sdkdom, idx[virType]++, sdkType, bootIndex++);
3828 prlsdkCheckRetExit(pret, -1);
3829 }
3830
3831 return 0;
3832 }
3833
3834 int
prlsdkDomainSetUserPassword(virDomainObj * dom,const char * user,const char * password)3835 prlsdkDomainSetUserPassword(virDomainObj *dom,
3836 const char *user,
3837 const char *password)
3838 {
3839 struct vzDomObj *privdom = dom->privateData;
3840 PRL_HANDLE job = PRL_INVALID_HANDLE;
3841
3842 job = PrlVm_SetUserPasswd(privdom->sdkdom,
3843 user,
3844 password,
3845 0);
3846
3847 if (PRL_FAILED(waitDomainJob(job, dom)))
3848 return -1;
3849
3850 return 0;
3851 }
3852
3853 static int
prlsdkDoApplyConfig(struct _vzDriver * driver,virDomainObj * dom,PRL_HANDLE sdkdom,virDomainDef * def)3854 prlsdkDoApplyConfig(struct _vzDriver *driver,
3855 virDomainObj *dom,
3856 PRL_HANDLE sdkdom,
3857 virDomainDef *def)
3858 {
3859 PRL_RESULT pret;
3860 size_t i;
3861 char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
3862 char *mask = NULL;
3863
3864 if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
3865 return -1;
3866
3867 if (def->description) {
3868 pret = PrlVmCfg_SetDescription(sdkdom, def->description);
3869 prlsdkCheckRetGoto(pret, error);
3870 }
3871
3872 if (def->name) {
3873 pret = PrlVmCfg_SetName(sdkdom, def->name);
3874 prlsdkCheckRetGoto(pret, error);
3875 }
3876
3877 if (def->uuid) {
3878 prlsdkUUIDFormat(def->uuid, uuidstr);
3879
3880 pret = PrlVmCfg_SetUuid(sdkdom, uuidstr);
3881 prlsdkCheckRetGoto(pret, error);
3882 }
3883
3884 pret = PrlVmCfg_SetRamSize(sdkdom, virDomainDefGetMemoryTotal(def) >> 10);
3885 prlsdkCheckRetGoto(pret, error);
3886
3887 pret = PrlVmCfg_SetCpuCount(sdkdom, virDomainDefGetVcpus(def));
3888 prlsdkCheckRetGoto(pret, error);
3889
3890 if (!(mask = virBitmapFormat(def->cpumask)))
3891 goto error;
3892
3893 pret = PrlVmCfg_SetCpuMask(sdkdom, mask);
3894 prlsdkCheckRetGoto(pret, error);
3895 VIR_FREE(mask);
3896
3897 switch ((int)def->os.arch) {
3898 case VIR_ARCH_X86_64:
3899 pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_64);
3900 break;
3901 case VIR_ARCH_I686:
3902 pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_32);
3903 break;
3904 default:
3905 virReportError(VIR_ERR_INTERNAL_ERROR,
3906 _("Unknown CPU mode: %s"),
3907 virArchToString(def->os.arch));
3908 goto error;
3909 }
3910 prlsdkCheckRetGoto(pret, error);
3911
3912 if (prlsdkClearDevices(sdkdom) < 0)
3913 goto error;
3914
3915 if (prlsdkRemoveBootDevices(sdkdom) < 0)
3916 goto error;
3917
3918 for (i = 0; i < def->nnets; i++) {
3919 if (prlsdkConfigureNet(driver, dom, sdkdom, def->nets[i],
3920 IS_CT(def), true) < 0)
3921 goto error;
3922 }
3923
3924 if (def->ngraphics > 1) {
3925 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3926 _("vz driver supports only VNC graphics"));
3927 goto error;
3928 }
3929
3930 if (prlsdkApplyGraphicsParams(sdkdom,
3931 def->ngraphics == 1 ? def->graphics[0] : NULL) < 0)
3932 goto error;
3933
3934 if (prlsdkApplyVideoParams(sdkdom, def) < 0)
3935 goto error;
3936
3937 for (i = 0; i < def->nserials; i++) {
3938 if (prlsdkAddSerial(sdkdom, def->serials[i]) < 0)
3939 goto error;
3940 }
3941
3942 /* It is important that we add filesystems first and then disks as we rely
3943 * on this information in prlsdkSetBootOrderCt */
3944 for (i = 0; i < def->nfss; i++) {
3945 if (prlsdkAddFS(sdkdom, def->fss[i]) < 0)
3946 goto error;
3947 }
3948
3949 /* filesystems first, disks go after them as we rely on this order in
3950 * prlsdkSetBootOrderCt */
3951 for (i = 0; i < def->ndisks; i++) {
3952 if (prlsdkConfigureDisk(driver, sdkdom, def->disks[i],
3953 true) < 0)
3954 goto error;
3955 }
3956
3957 if (IS_CT(def)) {
3958 if (prlsdkSetBootOrderCt(sdkdom, def) < 0)
3959 goto error;
3960 } else {
3961 if (prlsdkSetBootOrderVm(sdkdom, def) < 0)
3962 goto error;
3963 }
3964
3965 return 0;
3966
3967 error:
3968 VIR_FREE(mask);
3969
3970 return -1;
3971 }
3972
3973 int
prlsdkApplyConfig(struct _vzDriver * driver,virDomainObj * dom,virDomainDef * new)3974 prlsdkApplyConfig(struct _vzDriver *driver,
3975 virDomainObj *dom,
3976 virDomainDef *new)
3977 {
3978 struct vzDomObj *privdom = dom->privateData;
3979 PRL_HANDLE job = PRL_INVALID_HANDLE;
3980 int ret;
3981
3982 job = PrlVm_BeginEdit(privdom->sdkdom);
3983 if (PRL_FAILED(waitDomainJob(job, dom)))
3984 return -1;
3985
3986 ret = prlsdkDoApplyConfig(driver, dom, privdom->sdkdom, new);
3987
3988 if (ret == 0) {
3989 job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
3990 if (PRL_FAILED(waitDomainJob(job, dom)))
3991 ret = -1;
3992 }
3993
3994 return ret;
3995 }
3996
3997 int
prlsdkCreateVm(struct _vzDriver * driver,virDomainDef * def)3998 prlsdkCreateVm(struct _vzDriver *driver, virDomainDef *def)
3999 {
4000 PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
4001 PRL_HANDLE job = PRL_INVALID_HANDLE;
4002 PRL_HANDLE result = PRL_INVALID_HANDLE;
4003 PRL_HANDLE srvconf = PRL_INVALID_HANDLE;
4004 PRL_RESULT pret;
4005 int ret = -1;
4006
4007 pret = PrlSrv_CreateVm(driver->server, &sdkdom);
4008 prlsdkCheckRetGoto(pret, cleanup);
4009
4010 job = PrlSrv_GetSrvConfig(driver->server);
4011 if (PRL_FAILED(getJobResult(job, &result)))
4012 goto cleanup;
4013
4014 pret = PrlResult_GetParamByIndex(result, 0, &srvconf);
4015 prlsdkCheckRetGoto(pret, cleanup);
4016
4017 pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0);
4018 prlsdkCheckRetGoto(pret, cleanup);
4019
4020 pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0);
4021 prlsdkCheckRetGoto(pret, cleanup);
4022
4023 if (prlsdkDoApplyConfig(driver, NULL, sdkdom, def) < 0)
4024 goto cleanup;
4025
4026 job = PrlVm_Reg(sdkdom, "", 1);
4027 if (PRL_FAILED(waitJob(job)))
4028 goto cleanup;
4029
4030 ret = 0;
4031
4032 cleanup:
4033 PrlHandle_Free(sdkdom);
4034 PrlHandle_Free(srvconf);
4035 PrlHandle_Free(result);
4036
4037 return ret;
4038 }
4039
4040 static int
virStorageTranslatePoolLocal(virConnectPtr conn,virStorageSource * src)4041 virStorageTranslatePoolLocal(virConnectPtr conn, virStorageSource *src)
4042 {
4043 virStoragePoolPtr pool = NULL;
4044 virStorageVolPtr vol = NULL;
4045 virStorageVolInfo info;
4046 int ret = -1;
4047
4048 if (!(pool = virStoragePoolLookupByName(conn, src->srcpool->pool)))
4049 return -1;
4050 if (virStoragePoolIsActive(pool) != 1) {
4051 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4052 _("storage pool '%s' containing volume '%s' "
4053 "is not active"), src->srcpool->pool,
4054 src->srcpool->volume);
4055 goto cleanup;
4056 }
4057
4058 if (!(vol = virStorageVolLookupByName(pool, src->srcpool->volume)))
4059 goto cleanup;
4060
4061 if (virStorageVolGetInfo(vol, &info) < 0)
4062 goto cleanup;
4063
4064 if (info.type != VIR_STORAGE_VOL_PLOOP) {
4065 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4066 _("Unsupported volume format '%s'"),
4067 virStorageVolTypeToString(info.type));
4068 goto cleanup;
4069 }
4070
4071 if (!(src->path = virStorageVolGetPath(vol)))
4072 goto cleanup;
4073
4074 ret = 0;
4075
4076 cleanup:
4077 virObjectUnref(pool);
4078 virObjectUnref(vol);
4079 return ret;
4080 }
4081
4082
4083 int
prlsdkCreateCt(virConnectPtr conn,virDomainDef * def)4084 prlsdkCreateCt(virConnectPtr conn, virDomainDef *def)
4085 {
4086 PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
4087 PRL_GET_VM_CONFIG_PARAM_DATA confParam;
4088 PRL_HANDLE job = PRL_INVALID_HANDLE;
4089 PRL_HANDLE result = PRL_INVALID_HANDLE;
4090 PRL_RESULT pret;
4091 PRL_UINT32 flags;
4092 struct _vzConn *privconn = conn->privateData;
4093 struct _vzDriver *driver = privconn->driver;
4094 int ret = -1;
4095 int useTemplate = 0;
4096 size_t i;
4097
4098 for (i = 0; i < def->nfss; i++) {
4099 if (useTemplate) {
4100 virReportError(VIR_ERR_INVALID_ARG, "%s",
4101 _("Unsupported configuration"));
4102 return -1;
4103 }
4104 if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
4105 useTemplate = 1;
4106 if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
4107 if (virStorageTranslatePoolLocal(conn, def->fss[i]->src) < 0)
4108 goto cleanup;
4109 }
4110
4111 }
4112
4113 if (useTemplate && def->nfss > 1) {
4114 virReportError(VIR_ERR_INVALID_ARG, "%s",
4115 _("Unsupported configuration"));
4116 return -1;
4117 }
4118
4119 confParam.nVmType = PVT_CT;
4120 confParam.sConfigSample = "vswap.1024MB";
4121 confParam.nOsVersion = 0;
4122
4123 job = PrlSrv_GetDefaultVmConfig(driver->server, &confParam, 0);
4124 if (PRL_FAILED(getJobResult(job, &result)))
4125 goto cleanup;
4126
4127 pret = PrlResult_GetParamByIndex(result, 0, &sdkdom);
4128 prlsdkCheckRetGoto(pret, cleanup);
4129
4130 if (useTemplate) {
4131 pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src->path);
4132 prlsdkCheckRetGoto(pret, cleanup);
4133
4134 }
4135
4136 if (prlsdkDoApplyConfig(driver, NULL, sdkdom, def) < 0)
4137 goto cleanup;
4138
4139 flags = PACF_NON_INTERACTIVE_MODE;
4140 if (!useTemplate)
4141 flags |= PRNVM_PRESERVE_DISK;
4142 job = PrlVm_RegEx(sdkdom, "", flags);
4143 if (PRL_FAILED(waitJob(job)))
4144 goto cleanup;
4145
4146 ret = 0;
4147
4148 cleanup:
4149 PrlHandle_Free(sdkdom);
4150 PrlHandle_Free(result);
4151 return ret;
4152 }
4153
4154 /**
4155 * prlsdkDetachDomainHardDisks:
4156 *
4157 * @sdkdom: domain handle
4158 *
4159 * Returns 0 if hard disks were successfully detached or not detected.
4160 */
4161 static int
prlsdkDetachDomainHardDisks(virDomainObj * dom)4162 prlsdkDetachDomainHardDisks(virDomainObj *dom)
4163 {
4164 int ret = -1;
4165 PRL_RESULT pret;
4166 PRL_UINT32 hddCount;
4167 PRL_UINT32 i;
4168 PRL_HANDLE job;
4169 PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
4170 struct vzDomObj *pdom = dom->privateData;
4171 PRL_HANDLE sdkdom = pdom->sdkdom;
4172
4173 job = PrlVm_BeginEdit(sdkdom);
4174 if (PRL_FAILED(waitDomainJob(job, dom)))
4175 goto cleanup;
4176
4177 pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
4178 prlsdkCheckRetGoto(pret, cleanup);
4179
4180 for (i = 0; i < hddCount; ++i) {
4181 pret = PrlVmCfg_GetHardDisk(sdkdom, 0, &sdkdisk);
4182 prlsdkCheckRetGoto(pret, cleanup);
4183
4184 pret = PrlVmDev_Remove(sdkdisk);
4185 prlsdkCheckRetGoto(pret, cleanup);
4186
4187 PrlHandle_Free(sdkdisk);
4188 sdkdisk = PRL_INVALID_HANDLE;
4189 }
4190
4191 job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE);
4192 if (PRL_FAILED(waitDomainJob(job, dom)))
4193 goto cleanup;
4194
4195 ret = 0;
4196
4197 cleanup:
4198 PrlHandle_Free(sdkdisk);
4199 return ret;
4200 }
4201
4202 int
prlsdkUnregisterDomain(struct _vzDriver * driver,virDomainObj * dom,unsigned int flags)4203 prlsdkUnregisterDomain(struct _vzDriver *driver, virDomainObj *dom, unsigned int flags)
4204 {
4205 struct vzDomObj *privdom = dom->privateData;
4206 PRL_HANDLE job;
4207 virDomainSnapshotObjList *snapshots = NULL;
4208 VIRTUAL_MACHINE_STATE domainState;
4209 int ret = -1;
4210 int num;
4211
4212 if (prlsdkGetDomainState(dom, privdom->sdkdom, &domainState) < 0)
4213 return -1;
4214
4215 if (VMS_SUSPENDED == domainState &&
4216 !(flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE)) {
4217
4218 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4219 _("Refusing to undefine while domain managed "
4220 "save image exists"));
4221 return -1;
4222 }
4223
4224 if (!(snapshots = prlsdkLoadSnapshots(dom)))
4225 return -1;
4226
4227 if ((num = virDomainSnapshotObjListNum(snapshots, NULL, 0)) < 0)
4228 goto cleanup;
4229
4230 if (num > 0 && !(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
4231 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4232 _("Refusing to undefine while snapshots exist"));
4233 goto cleanup;
4234 }
4235
4236 if (prlsdkDetachDomainHardDisks(dom))
4237 goto cleanup;
4238
4239 job = PrlVm_Delete(privdom->sdkdom, PRL_INVALID_HANDLE);
4240 if (PRL_FAILED(waitDomainJob(job, dom)))
4241 goto cleanup;
4242
4243 prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_UNDEFINED,
4244 VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
4245
4246 virDomainObjListRemove(driver->domains, dom);
4247
4248 ret = 0;
4249 cleanup:
4250
4251 virDomainSnapshotObjListFree(snapshots);
4252 return ret;
4253 }
4254
4255 int
prlsdkDomainManagedSaveRemove(virDomainObj * dom)4256 prlsdkDomainManagedSaveRemove(virDomainObj *dom)
4257 {
4258 struct vzDomObj *privdom = dom->privateData;
4259 PRL_HANDLE job;
4260
4261 job = PrlVm_DropSuspendedState(privdom->sdkdom);
4262 if (PRL_FAILED(waitDomainJob(job, dom)))
4263 return -1;
4264
4265 return 0;
4266 }
4267
4268 static int
prlsdkExtractStatsParam(PRL_HANDLE sdkstats,const char * name,long long * val)4269 prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
4270 {
4271 PRL_HANDLE param = PRL_INVALID_HANDLE;
4272 PRL_RESULT pret;
4273 PRL_INT64 pval = 0;
4274 int ret = -1;
4275
4276 pret = PrlEvent_GetParamByName(sdkstats, name, ¶m);
4277 if (pret == PRL_ERR_NO_DATA) {
4278 *val = -1;
4279 ret = 0;
4280 goto cleanup;
4281 } else if (PRL_FAILED(pret)) {
4282 logPrlError(pret);
4283 goto cleanup;
4284 }
4285 pret = PrlEvtPrm_ToInt64(param, &pval);
4286 prlsdkCheckRetGoto(pret, cleanup);
4287
4288 *val = pval;
4289 ret = 0;
4290
4291 cleanup:
4292 PrlHandle_Free(param);
4293 return ret;
4294 }
4295
4296 #define PARALLELS_STATISTICS_TIMEOUT (60 * 1000)
4297
4298 int
prlsdkGetBlockStats(PRL_HANDLE sdkstats,virDomainDiskDef * disk,virDomainBlockStatsPtr stats,bool isCt)4299 prlsdkGetBlockStats(PRL_HANDLE sdkstats,
4300 virDomainDiskDef *disk,
4301 virDomainBlockStatsPtr stats,
4302 bool isCt)
4303 {
4304 virDomainDeviceDriveAddress *address;
4305 int idx;
4306 const char *prefix;
4307 int ret = -1;
4308 char *name = NULL;
4309
4310 address = &disk->info.addr.drive;
4311
4312 if (isCt) {
4313 prefix = "hdd";
4314 idx = address->unit;
4315 } else {
4316 switch (disk->bus) {
4317 case VIR_DOMAIN_DISK_BUS_IDE:
4318 prefix = "ide";
4319 idx = address->bus * 2 + address->unit;
4320 break;
4321 case VIR_DOMAIN_DISK_BUS_SATA:
4322 prefix = "sata";
4323 idx = address->unit;
4324 break;
4325 case VIR_DOMAIN_DISK_BUS_SCSI:
4326 prefix = "scsi";
4327 idx = address->unit;
4328 break;
4329 case VIR_DOMAIN_DISK_BUS_FDC:
4330 case VIR_DOMAIN_DISK_BUS_NONE:
4331 case VIR_DOMAIN_DISK_BUS_VIRTIO:
4332 case VIR_DOMAIN_DISK_BUS_XEN:
4333 case VIR_DOMAIN_DISK_BUS_USB:
4334 case VIR_DOMAIN_DISK_BUS_UML:
4335 case VIR_DOMAIN_DISK_BUS_SD:
4336 case VIR_DOMAIN_DISK_BUS_LAST:
4337 default:
4338 virReportError(VIR_ERR_INTERNAL_ERROR,
4339 _("Unknown disk bus: %X"), disk->bus);
4340 goto cleanup;
4341 }
4342 }
4343
4344
4345 #define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME) \
4346 name = g_strdup_printf("devices.%s%d.%s", prefix, idx, NAME); \
4347 if (prlsdkExtractStatsParam(sdkstats, name, &stats->VAL) < 0) \
4348 goto cleanup; \
4349 VIR_FREE(name);
4350
4351 PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
4352
4353 #undef PRLSDK_GET_STAT_PARAM
4354
4355 ret = 0;
4356
4357 cleanup:
4358
4359 VIR_FREE(name);
4360 return ret;
4361 }
4362
4363
4364 static PRL_HANDLE
prlsdkFindNetByPath(PRL_HANDLE sdkdom,const char * path)4365 prlsdkFindNetByPath(PRL_HANDLE sdkdom, const char *path)
4366 {
4367 PRL_UINT32 count = 0;
4368 PRL_RESULT pret;
4369 size_t i;
4370 char *name = NULL;
4371 PRL_HANDLE net = PRL_INVALID_HANDLE;
4372
4373 pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &count);
4374 prlsdkCheckRetGoto(pret, error);
4375
4376 for (i = 0; i < count; ++i) {
4377 pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &net);
4378 prlsdkCheckRetGoto(pret, error);
4379
4380 if (!(name = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
4381 net)))
4382 goto error;
4383
4384 if (STREQ(name, path))
4385 break;
4386
4387 VIR_FREE(name);
4388 PrlHandle_Free(net);
4389 net = PRL_INVALID_HANDLE;
4390 }
4391
4392 if (net == PRL_INVALID_HANDLE)
4393 virReportError(VIR_ERR_INVALID_ARG,
4394 _("invalid path, '%s' is not a known interface"), path);
4395 return net;
4396
4397 error:
4398 VIR_FREE(name);
4399 PrlHandle_Free(net);
4400 return PRL_INVALID_HANDLE;
4401 }
4402
4403 int
prlsdkGetNetStats(PRL_HANDLE sdkstats,PRL_HANDLE sdkdom,const char * device,virDomainInterfaceStatsPtr stats)4404 prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *device,
4405 virDomainInterfaceStatsPtr stats)
4406 {
4407 int ret = -1;
4408 PRL_UINT32 net_index = -1;
4409 char *name = NULL;
4410 PRL_RESULT pret;
4411 PRL_HANDLE net = PRL_INVALID_HANDLE;
4412 virMacAddr mac;
4413
4414 if (virMacAddrParse(device, &mac) == 0)
4415 net = prlsdkFindNetByMAC(sdkdom, &mac);
4416 else
4417 net = prlsdkFindNetByPath(sdkdom, device);
4418
4419 if (net == PRL_INVALID_HANDLE)
4420 goto cleanup;
4421
4422 pret = PrlVmDev_GetIndex(net, &net_index);
4423 prlsdkCheckRetGoto(pret, cleanup);
4424
4425 #define PRLSDK_GET_NET_COUNTER(VAL, NAME) \
4426 name = g_strdup_printf("net.nic%u.%s", net_index, NAME); \
4427 if (prlsdkExtractStatsParam(sdkstats, name, &stats->VAL) < 0) \
4428 goto cleanup; \
4429 VIR_FREE(name);
4430
4431 PRLSDK_GET_NET_COUNTER(rx_bytes, "bytes_in")
4432 PRLSDK_GET_NET_COUNTER(rx_packets, "pkts_in")
4433 PRLSDK_GET_NET_COUNTER(tx_bytes, "bytes_out")
4434 PRLSDK_GET_NET_COUNTER(tx_packets, "pkts_out")
4435 stats->rx_errs = -1;
4436 stats->rx_drop = -1;
4437 stats->tx_errs = -1;
4438 stats->tx_drop = -1;
4439
4440 #undef PRLSDK_GET_NET_COUNTER
4441 ret = 0;
4442
4443 cleanup:
4444 VIR_FREE(name);
4445 PrlHandle_Free(net);
4446
4447 return ret;
4448 }
4449
4450 int
prlsdkGetVcpuStats(PRL_HANDLE sdkstats,int idx,unsigned long long * vtime)4451 prlsdkGetVcpuStats(PRL_HANDLE sdkstats, int idx, unsigned long long *vtime)
4452 {
4453 char *name = NULL;
4454 long long ptime = 0;
4455 int ret = -1;
4456
4457 name = g_strdup_printf("guest.vcpu%u.time", (unsigned int)idx);
4458 if (prlsdkExtractStatsParam(sdkstats, name, &ptime) < 0)
4459 goto cleanup;
4460 *vtime = ptime == -1 ? 0 : ptime;
4461 ret = 0;
4462
4463 cleanup:
4464 VIR_FREE(name);
4465 return ret;
4466 }
4467
4468 int
prlsdkGetMemoryStats(PRL_HANDLE sdkstats,virDomainMemoryStatPtr stats,unsigned int nr_stats)4469 prlsdkGetMemoryStats(PRL_HANDLE sdkstats,
4470 virDomainMemoryStatPtr stats,
4471 unsigned int nr_stats)
4472 {
4473 long long v = 0, t = 0, u = 0;
4474 size_t i = 0;
4475
4476 #define PRLSDK_GET_COUNTER(NAME, VALUE) \
4477 if (prlsdkExtractStatsParam(sdkstats, NAME, &VALUE) < 0) \
4478 return -1; \
4479
4480 #define PRLSDK_MEMORY_STAT_SET(TAG, VALUE) \
4481 if (i < nr_stats) { \
4482 stats[i].tag = (TAG); \
4483 stats[i].val = (VALUE); \
4484 i++; \
4485 }
4486
4487 i = 0;
4488
4489 // count to kb
4490 PRLSDK_GET_COUNTER("guest.ram.swap_in", v)
4491 if (v != -1)
4492 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_SWAP_IN, v << 12)
4493
4494 PRLSDK_GET_COUNTER("guest.ram.swap_out", v)
4495 if (v != -1)
4496 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, v << 12)
4497
4498 PRLSDK_GET_COUNTER("guest.ram.minor_fault", v)
4499 if (v != -1)
4500 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, v)
4501
4502 PRLSDK_GET_COUNTER("guest.ram.major_fault", v)
4503 if (v != -1)
4504 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, v)
4505
4506 PRLSDK_GET_COUNTER("guest.ram.total", v)
4507 if (v != -1)
4508 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_AVAILABLE, v << 10)
4509
4510 PRLSDK_GET_COUNTER("guest.ram.balloon_actual", v)
4511 if (v != -1)
4512 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON, v << 10)
4513
4514 PRLSDK_GET_COUNTER("guest.ram.usage", u)
4515 PRLSDK_GET_COUNTER("guest.ram.total", t)
4516 if (u != -1 && t != -1)
4517 PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_UNUSED, (t - u) << 10)
4518
4519 #undef PRLSDK_GET_COUNTER
4520 #undef PRLSDK_MEMORY_STAT_SET
4521
4522 return i;
4523 }
4524
4525 /* memsize is in MiB */
prlsdkSetMemsize(virDomainObj * dom,unsigned int memsize)4526 int prlsdkSetMemsize(virDomainObj *dom, unsigned int memsize)
4527 {
4528 struct vzDomObj *privdom = dom->privateData;
4529 PRL_HANDLE job;
4530 PRL_RESULT pret;
4531
4532 job = PrlVm_BeginEdit(privdom->sdkdom);
4533 if (PRL_FAILED(waitDomainJob(job, dom)))
4534 return -1;
4535
4536 pret = PrlVmCfg_SetRamSize(privdom->sdkdom, memsize);
4537 prlsdkCheckRetExit(pret, -1);
4538
4539 job = PrlVm_CommitEx(privdom->sdkdom, 0);
4540 if (PRL_FAILED(waitDomainJob(job, dom)))
4541 return -1;
4542
4543 return 0;
4544 }
4545
4546 static long long
prlsdkParseDateTime(const char * str)4547 prlsdkParseDateTime(const char *str)
4548 {
4549 g_autoptr(GDateTime) then = NULL;
4550 g_autoptr(GTimeZone) tz = g_time_zone_new_utc();
4551 char *tmp;
4552 int year, mon, mday, hour, min, sec;
4553
4554 /* Expect: YYYY-MM-DD HH:MM:SS (%d-%d-%dT%d:%d:%d) eg 2010-11-28 14:29:01 */
4555 if (/* year */
4556 virStrToLong_i(str, &tmp, 10, &year) < 0 || *tmp != '-' ||
4557 /* month */
4558 virStrToLong_i(tmp+1, &tmp, 10, &mon) < 0 || *tmp != '-' ||
4559 /* day */
4560 virStrToLong_i(tmp+1, &tmp, 10, &mday) < 0 || *tmp != ' ' ||
4561 /* hour */
4562 virStrToLong_i(tmp+1, &tmp, 10, &hour) < 0 || *tmp != ':' ||
4563 /* minute */
4564 virStrToLong_i(tmp+1, &tmp, 10, &min) < 0 || *tmp != ':' ||
4565 /* second */
4566 virStrToLong_i(tmp+1, &tmp, 10, &sec) < 0 || *tmp != '\0') {
4567 virReportError(VIR_ERR_INTERNAL_ERROR,
4568 _("unexpected DateTime format: '%s'"), str);
4569 return -1;
4570 }
4571
4572 then = g_date_time_new(tz, year, mon, mday, hour, min, sec);
4573 return (long long)g_date_time_to_unix(then);
4574 }
4575
4576 static virDomainSnapshotObjList *
prlsdkParseSnapshotTree(const char * treexml)4577 prlsdkParseSnapshotTree(const char *treexml)
4578 {
4579 virDomainSnapshotObjList *ret = NULL;
4580 g_autoptr(xmlDoc) xml = NULL;
4581 g_autoptr(xmlXPathContext) ctxt = NULL;
4582 xmlNodePtr root;
4583 xmlNodePtr *nodes = NULL;
4584 virDomainSnapshotDef *def = NULL;
4585 virDomainMomentObj *snapshot;
4586 virDomainSnapshotObjList *snapshots = NULL;
4587 char *xmlstr = NULL;
4588 int n;
4589 size_t i;
4590
4591 if (!(snapshots = virDomainSnapshotObjListNew()))
4592 return NULL;
4593
4594 if (*treexml == '\0')
4595 return snapshots;
4596
4597 if (!(xml = virXMLParse(NULL, treexml, _("(snapshot_tree)"), NULL, false)))
4598 goto cleanup;
4599
4600 root = xmlDocGetRootElement(xml);
4601 if (!virXMLNodeNameEqual(root, "ParallelsSavedStates")) {
4602 virReportError(VIR_ERR_INTERNAL_ERROR,
4603 _("unexpected root element: '%s'"), root->name);
4604 goto cleanup;
4605 }
4606
4607 if (!(ctxt = virXMLXPathContextNew(xml)))
4608 goto cleanup;
4609
4610 ctxt->node = root;
4611
4612 if ((n = virXPathNodeSet("//SavedStateItem", ctxt, &nodes)) < 0) {
4613 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4614 _("cannot extract snapshot nodes"));
4615 goto cleanup;
4616 }
4617
4618 for (i = 0; i < n; i++) {
4619 if (nodes[i]->parent == root)
4620 continue;
4621
4622 def = g_new0(virDomainSnapshotDef, 1);
4623
4624 ctxt->node = nodes[i];
4625
4626 def->parent.name = virXPathString("string(./@guid)", ctxt);
4627 if (!def->parent.name) {
4628 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4629 _("missing 'guid' attribute"));
4630 goto cleanup;
4631 }
4632
4633 def->parent.parent_name = virXPathString("string(../@guid)", ctxt);
4634
4635 xmlstr = virXPathString("string(./DateTime)", ctxt);
4636 if (!xmlstr) {
4637 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4638 _("missing 'DateTime' element"));
4639 goto cleanup;
4640 }
4641 if ((def->parent.creationTime = prlsdkParseDateTime(xmlstr)) < 0)
4642 goto cleanup;
4643 VIR_FREE(xmlstr);
4644
4645 def->parent.description = virXPathString("string(./Description)", ctxt);
4646
4647 def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
4648 xmlstr = virXPathString("string(./@state)", ctxt);
4649 if (!xmlstr) {
4650 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4651 _("missing 'state' attribute"));
4652 goto cleanup;
4653 } else if (STREQ(xmlstr, "poweron")) {
4654 def->state = VIR_DOMAIN_RUNNING;
4655 def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
4656 } else if (STREQ(xmlstr, "pause")) {
4657 def->state = VIR_DOMAIN_PAUSED;
4658 def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
4659 } else if (STREQ(xmlstr, "suspend")) {
4660 def->state = VIR_DOMAIN_SHUTOFF;
4661 } else if (STREQ(xmlstr, "poweroff")) {
4662 def->state = VIR_DOMAIN_SHUTOFF;
4663 } else {
4664 virReportError(VIR_ERR_INTERNAL_ERROR,
4665 _("unexpected snapshot state: %s"), xmlstr);
4666 }
4667 VIR_FREE(xmlstr);
4668
4669 if (!(snapshot = virDomainSnapshotAssignDef(snapshots, def)))
4670 goto cleanup;
4671 def = NULL;
4672
4673 xmlstr = virXPathString("string(./@current)", ctxt);
4674 if (xmlstr && STREQ("yes", xmlstr)) {
4675 if (virDomainSnapshotGetCurrent(snapshots)) {
4676 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4677 _("too many current snapshots"));
4678 VIR_FREE(xmlstr);
4679 goto cleanup;
4680 }
4681 virDomainSnapshotSetCurrent(snapshots, snapshot);
4682 }
4683 VIR_FREE(xmlstr);
4684 }
4685
4686 if (virDomainSnapshotUpdateRelations(snapshots) < 0) {
4687 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4688 _("snapshots have inconsistent relations"));
4689 goto cleanup;
4690 }
4691
4692 ret = g_steal_pointer(&snapshots);
4693
4694 cleanup:
4695 virDomainSnapshotObjListFree(snapshots);
4696 VIR_FREE(nodes);
4697 VIR_FREE(xmlstr);
4698 VIR_FREE(def);
4699
4700 return ret;
4701 }
4702
4703 virDomainSnapshotObjList *
prlsdkLoadSnapshots(virDomainObj * dom)4704 prlsdkLoadSnapshots(virDomainObj *dom)
4705 {
4706 virDomainSnapshotObjList *ret = NULL;
4707 PRL_HANDLE job;
4708 PRL_HANDLE result = PRL_INVALID_HANDLE;
4709 struct vzDomObj *privdom = dom->privateData;
4710 char *treexml = NULL;
4711
4712 job = PrlVm_GetSnapshotsTreeEx(privdom->sdkdom, PGST_WITHOUT_SCREENSHOTS);
4713 if (PRL_FAILED(getDomainJobResult(job, dom, &result)))
4714 goto cleanup;
4715
4716 if (!(treexml = prlsdkGetStringParamVar(PrlResult_GetParamAsString, result)))
4717 goto cleanup;
4718
4719 ret = prlsdkParseSnapshotTree(treexml);
4720 cleanup:
4721
4722 PrlHandle_Free(result);
4723 VIR_FREE(treexml);
4724 return ret;
4725 }
4726
prlsdkCreateSnapshot(virDomainObj * dom,const char * description)4727 int prlsdkCreateSnapshot(virDomainObj *dom, const char *description)
4728 {
4729 struct vzDomObj *privdom = dom->privateData;
4730 PRL_HANDLE job;
4731
4732 job = PrlVm_CreateSnapshot(privdom->sdkdom, "",
4733 description ? : "");
4734 if (PRL_FAILED(waitDomainJob(job, dom)))
4735 return -1;
4736
4737 return 0;
4738 }
4739
prlsdkDeleteSnapshot(virDomainObj * dom,const char * uuid,bool children)4740 int prlsdkDeleteSnapshot(virDomainObj *dom, const char *uuid, bool children)
4741 {
4742 struct vzDomObj *privdom = dom->privateData;
4743 PRL_HANDLE job;
4744
4745 job = PrlVm_DeleteSnapshot(privdom->sdkdom, uuid, children);
4746 if (PRL_FAILED(waitDomainJob(job, dom)))
4747 return -1;
4748
4749 return 0;
4750 }
4751
prlsdkSwitchToSnapshot(virDomainObj * dom,const char * uuid,bool paused)4752 int prlsdkSwitchToSnapshot(virDomainObj *dom, const char *uuid, bool paused)
4753 {
4754 struct vzDomObj *privdom = dom->privateData;
4755 PRL_HANDLE job;
4756 PRL_UINT32 flags = 0;
4757
4758 if (paused)
4759 flags |= PSSF_SKIP_RESUME;
4760
4761 job = PrlVm_SwitchToSnapshotEx(privdom->sdkdom, uuid, flags);
4762 if (PRL_FAILED(waitDomainJob(job, dom)))
4763 return -1;
4764
4765 return 0;
4766 }
4767
4768 /* high security is default choice for 2 reasons:
4769 * 1. as this is the highest set security we can't get
4770 * reject from server with high security settings
4771 * 2. this is on par with security level of driver
4772 * connection to dispatcher
4773 */
4774
4775 #define PRLSDK_MIGRATION_FLAGS (PSL_HIGH_SECURITY | PVMT_DONT_CREATE_DISK)
4776
prlsdkMigrate(virDomainObj * dom,virURI * uri,const unsigned char * session_uuid,const char * dname,unsigned int flags)4777 int prlsdkMigrate(virDomainObj *dom, virURI *uri,
4778 const unsigned char *session_uuid,
4779 const char *dname,
4780 unsigned int flags)
4781 {
4782 struct vzDomObj *privdom = dom->privateData;
4783 PRL_HANDLE job = PRL_INVALID_HANDLE;
4784 char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
4785 PRL_UINT32 vzflags = PRLSDK_MIGRATION_FLAGS;
4786
4787 if (flags & VIR_MIGRATE_PAUSED)
4788 vzflags |= PVMT_DONT_RESUME_VM;
4789
4790 prlsdkUUIDFormat(session_uuid, uuidstr);
4791 job = PrlVm_MigrateWithRenameEx(privdom->sdkdom, uri->server,
4792 uri->port, uuidstr,
4793 dname == NULL ? "" : dname,
4794 "",
4795 vzflags,
4796 0,
4797 PRL_TRUE
4798 );
4799
4800 if (PRL_FAILED(waitDomainJob(job, dom)))
4801 return -1;
4802
4803 return 0;
4804 }
4805
prlsdkSetCpuCount(virDomainObj * dom,unsigned int count)4806 int prlsdkSetCpuCount(virDomainObj *dom, unsigned int count)
4807 {
4808 struct vzDomObj *privdom = dom->privateData;
4809 PRL_HANDLE job;
4810 PRL_RESULT pret;
4811
4812 job = PrlVm_BeginEdit(privdom->sdkdom);
4813 if (PRL_FAILED(waitDomainJob(job, dom)))
4814 return -1;
4815
4816 pret = PrlVmCfg_SetCpuCount(privdom->sdkdom, count);
4817 prlsdkCheckRetExit(pret, -1);
4818
4819 job = PrlVm_CommitEx(privdom->sdkdom, 0);
4820 if (PRL_FAILED(waitDomainJob(job, dom)))
4821 return -1;
4822
4823 return 0;
4824 }
4825
prlsdkResizeImage(virDomainObj * dom,virDomainDiskDef * disk,unsigned long long newsize)4826 int prlsdkResizeImage(virDomainObj *dom, virDomainDiskDef *disk,
4827 unsigned long long newsize)
4828 {
4829 int ret = -1;
4830 PRL_RESULT pret;
4831 struct vzDomObj *privdom = dom->privateData;
4832 PRL_UINT32 emulatedType;
4833 PRL_HANDLE job = PRL_INVALID_HANDLE;
4834 PRL_HANDLE prldisk = PRL_INVALID_HANDLE;
4835
4836 prldisk = prlsdkGetDisk(privdom->sdkdom, disk);
4837 if (prldisk == PRL_INVALID_HANDLE)
4838 goto cleanup;
4839
4840 pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
4841 prlsdkCheckRetGoto(pret, cleanup);
4842
4843 if (emulatedType != PDT_USE_IMAGE_FILE &&
4844 emulatedType != PDT_USE_FILE_SYSTEM) {
4845 virReportError(VIR_ERR_INVALID_ARG, "%s",
4846 _("Only disk image supported for resize"));
4847 goto cleanup;
4848 }
4849
4850 job = PrlVmDev_ResizeImage(prldisk, newsize,
4851 PRIF_RESIZE_LAST_PARTITION);
4852 if (PRL_FAILED(waitDomainJob(job, dom)))
4853 goto cleanup;
4854
4855 ret = 0;
4856
4857 cleanup:
4858
4859 PrlHandle_Free(prldisk);
4860 return ret;
4861 }
4862