2014-09-11 16:24:03 +00:00
|
|
|
/*
|
2015-06-10 07:50:00 +00:00
|
|
|
* vz_sdk.c: core driver functions for managing
|
2014-09-11 16:24:03 +00:00
|
|
|
* Parallels Cloud Server hosts
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Parallels, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2015-06-09 07:35:53 +00:00
|
|
|
#include <stdarg.h>
|
2014-09-11 16:24:03 +00:00
|
|
|
|
|
|
|
#include "virerror.h"
|
|
|
|
#include "viralloc.h"
|
2014-12-01 15:38:48 +00:00
|
|
|
#include "virstring.h"
|
|
|
|
#include "virlog.h"
|
2014-12-01 15:38:50 +00:00
|
|
|
#include "datatypes.h"
|
2014-12-01 15:38:52 +00:00
|
|
|
#include "domain_conf.h"
|
2018-02-26 09:25:50 +00:00
|
|
|
#include "storage_conf.h"
|
2015-06-09 07:35:53 +00:00
|
|
|
#include "virtime.h"
|
2016-06-10 17:21:18 +00:00
|
|
|
#include "virhostcpu.h"
|
2017-07-05 10:19:43 +00:00
|
|
|
#include "virsocketaddr.h"
|
2020-02-16 21:59:28 +00:00
|
|
|
#include "virutil.h"
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2015-06-10 07:50:00 +00:00
|
|
|
#include "vz_sdk.h"
|
2014-09-11 16:24:03 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_PARALLELS
|
|
|
|
#define JOB_INFINIT_WAIT_TIMEOUT UINT_MAX
|
|
|
|
|
2016-05-18 08:11:04 +00:00
|
|
|
static int
|
|
|
|
prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid);
|
2016-06-24 14:32:30 +00:00
|
|
|
static void
|
|
|
|
prlsdkConvertError(PRL_RESULT pret);
|
2017-02-03 07:01:55 +00:00
|
|
|
static PRL_RESULT
|
|
|
|
prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque);
|
2016-05-18 08:11:04 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
VIR_LOG_INIT("parallels.sdk");
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
static PRL_HANDLE
|
|
|
|
prlsdkFindNetByMAC(PRL_HANDLE sdkdom, virMacAddrPtr mac);
|
|
|
|
static PRL_HANDLE
|
2016-08-15 16:02:49 +00:00
|
|
|
prlsdkGetDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk);
|
2016-12-05 13:34:52 +00:00
|
|
|
static bool
|
|
|
|
prlsdkInBootList(PRL_HANDLE sdkdom,
|
|
|
|
PRL_HANDLE sdktargetdev);
|
2016-04-20 14:05:31 +00:00
|
|
|
|
2014-09-11 16:24:03 +00:00
|
|
|
/*
|
|
|
|
* Log error description
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
logPrlErrorHelper(PRL_RESULT err, const char *filename,
|
|
|
|
const char *funcname, size_t linenr)
|
|
|
|
{
|
|
|
|
char *msg1 = NULL, *msg2 = NULL;
|
|
|
|
PRL_UINT32 len = 0;
|
|
|
|
|
|
|
|
/* Get required buffer length */
|
|
|
|
PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, NULL, &len);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(msg1, len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* get short error description */
|
|
|
|
PrlApi_GetResultDescription(err, PRL_TRUE, PRL_FALSE, msg1, &len);
|
|
|
|
|
|
|
|
PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, NULL, &len);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(msg2, len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* get long error description */
|
|
|
|
PrlApi_GetResultDescription(err, PRL_FALSE, PRL_FALSE, msg2, &len);
|
|
|
|
|
|
|
|
virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
filename, funcname, linenr,
|
|
|
|
_("%s %s"), msg1, msg2);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(msg1);
|
|
|
|
VIR_FREE(msg2);
|
|
|
|
}
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define logPrlError(code) \
|
|
|
|
logPrlErrorHelper(code, __FILE__, \
|
2015-06-25 07:56:56 +00:00
|
|
|
__FUNCTION__, __LINE__)
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define prlsdkCheckRetGoto(ret, label) \
|
|
|
|
do { \
|
|
|
|
if (PRL_FAILED(ret)) { \
|
|
|
|
logPrlError(ret); \
|
|
|
|
goto label; \
|
|
|
|
} \
|
2014-12-01 15:38:48 +00:00
|
|
|
} while (0)
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define prlsdkCheckRetExit(ret, code) \
|
|
|
|
do { \
|
|
|
|
if (PRL_FAILED(ret)) { \
|
|
|
|
logPrlError(ret); \
|
|
|
|
return code; \
|
|
|
|
} \
|
2016-03-22 13:56:36 +00:00
|
|
|
} while (0)
|
|
|
|
|
2016-05-26 08:56:23 +00:00
|
|
|
static void
|
2014-09-11 16:24:03 +00:00
|
|
|
logPrlEventErrorHelper(PRL_HANDLE event, const char *filename,
|
|
|
|
const char *funcname, size_t linenr)
|
|
|
|
{
|
|
|
|
char *msg1 = NULL, *msg2 = NULL;
|
|
|
|
PRL_UINT32 len = 0;
|
|
|
|
|
|
|
|
PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, NULL, &len);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(msg1, len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
PrlEvent_GetErrString(event, PRL_TRUE, PRL_FALSE, msg1, &len);
|
|
|
|
|
|
|
|
PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, NULL, &len);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(msg2, len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
PrlEvent_GetErrString(event, PRL_FALSE, PRL_FALSE, msg2, &len);
|
|
|
|
|
|
|
|
virReportErrorHelper(VIR_FROM_THIS, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
filename, funcname, linenr,
|
|
|
|
_("%s %s"), msg1, msg2);
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(msg1);
|
|
|
|
VIR_FREE(msg2);
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:59 +00:00
|
|
|
static PRL_RESULT
|
|
|
|
getJobResultHelper(PRL_HANDLE job, unsigned int timeout, PRL_HANDLE *result,
|
2014-09-11 16:24:03 +00:00
|
|
|
const char *filename, const char *funcname,
|
|
|
|
size_t linenr)
|
|
|
|
{
|
|
|
|
PRL_RESULT ret, retCode;
|
|
|
|
|
2016-05-26 08:56:23 +00:00
|
|
|
if (PRL_FAILED(ret = PrlJob_Wait(job, timeout))) {
|
2014-09-11 16:24:03 +00:00
|
|
|
logPrlErrorHelper(ret, filename, funcname, linenr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-26 08:56:23 +00:00
|
|
|
if (PRL_FAILED(ret = PrlJob_GetRetCode(job, &retCode))) {
|
2014-09-11 16:24:03 +00:00
|
|
|
logPrlErrorHelper(ret, filename, funcname, linenr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retCode) {
|
|
|
|
PRL_HANDLE err_handle;
|
|
|
|
|
2016-05-26 08:56:23 +00:00
|
|
|
ret = retCode;
|
|
|
|
|
2014-09-11 16:24:03 +00:00
|
|
|
/* Sometimes it's possible to get additional error info. */
|
2016-05-26 08:56:23 +00:00
|
|
|
if (PRL_FAILED(retCode = PrlJob_GetError(job, &err_handle))) {
|
2014-09-11 16:24:03 +00:00
|
|
|
logPrlErrorHelper(ret, filename, funcname, linenr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-26 08:56:23 +00:00
|
|
|
if (PRL_FAILED(retCode = PrlEvent_GetErrCode(err_handle, &retCode))) {
|
|
|
|
logPrlErrorHelper(ret, filename, funcname, linenr);
|
|
|
|
if (PRL_ERR_NO_DATA != retCode)
|
|
|
|
logPrlError(retCode);
|
|
|
|
PrlHandle_Free(err_handle);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
logPrlEventErrorHelper(err_handle, filename, funcname, linenr);
|
2014-09-11 16:24:03 +00:00
|
|
|
|
|
|
|
PrlHandle_Free(err_handle);
|
|
|
|
} else {
|
2014-12-01 15:38:59 +00:00
|
|
|
ret = PrlJob_GetResult(job, result);
|
2014-09-11 16:24:03 +00:00
|
|
|
if (PRL_FAILED(ret)) {
|
|
|
|
logPrlErrorHelper(ret, filename, funcname, linenr);
|
2014-12-01 15:38:59 +00:00
|
|
|
PrlHandle_Free(*result);
|
|
|
|
*result = NULL;
|
2014-09-11 16:24:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-12-01 15:39:00 +00:00
|
|
|
|
|
|
|
ret = PRL_ERR_SUCCESS;
|
2014-12-01 15:38:59 +00:00
|
|
|
}
|
2014-09-11 16:24:03 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(job);
|
2014-12-01 15:38:59 +00:00
|
|
|
return ret;
|
2014-09-11 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define getJobResult(job, result) \
|
|
|
|
getJobResultHelper(job, JOB_INFINIT_WAIT_TIMEOUT, \
|
2015-06-25 07:56:56 +00:00
|
|
|
result, __FILE__, __FUNCTION__, __LINE__)
|
2014-09-11 16:24:03 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
static PRL_RESULT
|
|
|
|
getDomainJobResultHelper(PRL_HANDLE job, virDomainObjPtr dom,
|
|
|
|
unsigned int timeout, PRL_HANDLE *result,
|
|
|
|
const char *filename, const char *funcname,
|
|
|
|
size_t linenr)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
if (dom)
|
|
|
|
virObjectUnlock(dom);
|
|
|
|
pret = getJobResultHelper(job, timeout, result, filename, funcname, linenr);
|
|
|
|
if (dom)
|
|
|
|
virObjectLock(dom);
|
|
|
|
|
|
|
|
return pret;
|
|
|
|
}
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define getDomainJobResult(job, dom, result) \
|
|
|
|
getDomainJobResultHelper(job, dom, JOB_INFINIT_WAIT_TIMEOUT, \
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
result, __FILE__, __FUNCTION__, __LINE__)
|
|
|
|
|
2014-12-01 15:38:59 +00:00
|
|
|
static PRL_RESULT
|
2014-09-11 16:24:03 +00:00
|
|
|
waitJobHelper(PRL_HANDLE job, unsigned int timeout,
|
|
|
|
const char *filename, const char *funcname,
|
|
|
|
size_t linenr)
|
|
|
|
{
|
2014-12-01 15:38:59 +00:00
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT ret;
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2014-12-01 15:38:59 +00:00
|
|
|
ret = getJobResultHelper(job, timeout, &result,
|
|
|
|
filename, funcname, linenr);
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
return ret;
|
2014-09-11 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define waitJob(job) \
|
|
|
|
waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT, __FILE__, \
|
2015-06-25 07:56:56 +00:00
|
|
|
__FUNCTION__, __LINE__)
|
2014-09-11 16:24:03 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
static PRL_RESULT
|
|
|
|
waitDomainJobHelper(PRL_HANDLE job, virDomainObjPtr dom, unsigned int timeout,
|
|
|
|
const char *filename, const char *funcname,
|
|
|
|
size_t linenr)
|
|
|
|
{
|
2017-01-31 07:44:12 +00:00
|
|
|
vzDomObjPtr pdom = dom->privateData;
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
PRL_RESULT ret;
|
|
|
|
|
2017-01-31 07:44:12 +00:00
|
|
|
if (pdom->job.cancelled) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_ABORTED, "%s",
|
|
|
|
_("Operation cancelled by client"));
|
|
|
|
return PRL_ERR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdom->job.sdkJob = job;
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (dom)
|
|
|
|
virObjectUnlock(dom);
|
|
|
|
ret = waitJobHelper(job, timeout, filename, funcname, linenr);
|
|
|
|
if (dom)
|
|
|
|
virObjectLock(dom);
|
2017-01-31 07:44:12 +00:00
|
|
|
pdom->job.sdkJob = NULL;
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define waitDomainJob(job, dom) \
|
|
|
|
waitDomainJobHelper(job, dom, JOB_INFINIT_WAIT_TIMEOUT, __FILE__, \
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
__FUNCTION__, __LINE__)
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
typedef PRL_RESULT (*prlsdkParamGetterType)(PRL_HANDLE, char*, PRL_UINT32*);
|
|
|
|
|
2017-01-31 07:44:12 +00:00
|
|
|
int
|
|
|
|
prlsdkCancelJob(virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
|
|
|
|
if (!privdom->job.active) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("no job is active on the domain"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
privdom->job.cancelled = true;
|
|
|
|
job = PrlJob_Cancel(privdom->job.sdkJob);
|
|
|
|
|
|
|
|
virObjectUnlock(dom);
|
|
|
|
pret = waitJobHelper(job, JOB_INFINIT_WAIT_TIMEOUT,
|
|
|
|
__FILE__, __FUNCTION__, __LINE__);
|
|
|
|
virObjectLock(dom);
|
|
|
|
|
|
|
|
return PRL_FAILED(pret) ? -1 : 0;
|
|
|
|
}
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
static char*
|
|
|
|
prlsdkGetStringParamVar(prlsdkParamGetterType getter, PRL_HANDLE handle)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 buflen = 0;
|
|
|
|
char *str = NULL;
|
|
|
|
|
|
|
|
pret = getter(handle, NULL, &buflen);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(str, buflen) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
pret = getter(handle, str, &buflen);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(str);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRL_RESULT
|
|
|
|
prlsdkGetStringParamBuf(prlsdkParamGetterType getter,
|
|
|
|
PRL_HANDLE handle, char *buf, size_t size)
|
|
|
|
{
|
|
|
|
PRL_UINT32 buflen = size;
|
|
|
|
return getter(handle, buf, &buflen);
|
|
|
|
}
|
2015-05-13 14:23:00 +00:00
|
|
|
|
2014-09-11 16:24:03 +00:00
|
|
|
int
|
2015-05-13 14:23:00 +00:00
|
|
|
prlsdkInit(void)
|
2014-09-11 16:24:03 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT ret;
|
|
|
|
|
2015-05-26 14:57:00 +00:00
|
|
|
/* Disable console output */
|
|
|
|
PrlApi_SwitchConsoleLogging(0);
|
|
|
|
|
2014-09-11 16:24:03 +00:00
|
|
|
ret = PrlApi_InitEx(PARALLELS_API_VER, PAM_SERVER, 0, 0);
|
|
|
|
if (PRL_FAILED(ret)) {
|
|
|
|
logPrlError(ret);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
prlsdkDeinit(void)
|
|
|
|
{
|
|
|
|
PrlApi_Deinit();
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkConnect(vzDriverPtr driver)
|
2014-09-11 16:24:03 +00:00
|
|
|
{
|
2016-05-18 08:11:04 +00:00
|
|
|
int ret = -1;
|
|
|
|
PRL_RESULT pret;
|
2014-09-11 16:24:03 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-05-18 08:11:04 +00:00
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE response = PRL_INVALID_HANDLE;
|
2016-05-18 08:11:08 +00:00
|
|
|
char session_uuid[VIR_UUID_STRING_BRACED_BUFLEN];
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2016-05-18 08:11:04 +00:00
|
|
|
pret = PrlSrv_Create(&driver->server);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_LoginLocalEx(driver->server, NULL, 0,
|
2014-09-11 16:24:03 +00:00
|
|
|
PSL_HIGH_SECURITY, PACF_NON_INTERACTIVE_MODE);
|
2016-05-18 08:11:04 +00:00
|
|
|
if (PRL_FAILED(getJobResult(job, &result)))
|
2017-02-03 07:01:55 +00:00
|
|
|
goto destroy;
|
2016-05-18 08:11:04 +00:00
|
|
|
|
|
|
|
pret = PrlResult_GetParam(result, &response);
|
2017-02-03 07:01:55 +00:00
|
|
|
prlsdkCheckRetGoto(pret, logoff);
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2016-05-18 08:11:04 +00:00
|
|
|
pret = prlsdkGetStringParamBuf(PrlLoginResponse_GetSessionUuid,
|
|
|
|
response, session_uuid, sizeof(session_uuid));
|
2017-02-03 07:01:55 +00:00
|
|
|
prlsdkCheckRetGoto(pret, logoff);
|
2016-05-18 08:11:04 +00:00
|
|
|
|
|
|
|
if (prlsdkUUIDParse(session_uuid, driver->session_uuid) < 0)
|
2017-02-03 07:01:55 +00:00
|
|
|
goto logoff;
|
|
|
|
|
|
|
|
pret = PrlSrv_RegEventHandler(driver->server,
|
|
|
|
prlsdkEventsHandler,
|
|
|
|
driver);
|
|
|
|
prlsdkCheckRetGoto(pret, logoff);
|
2016-05-18 08:11:04 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
PrlHandle_Free(response);
|
|
|
|
|
|
|
|
return ret;
|
2017-02-03 07:01:55 +00:00
|
|
|
|
|
|
|
logoff:
|
|
|
|
job = PrlSrv_Logoff(driver->server);
|
|
|
|
waitJob(job);
|
|
|
|
|
|
|
|
destroy:
|
|
|
|
PrlHandle_Free(driver->server);
|
|
|
|
driver->server = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
goto cleanup;
|
2014-09-11 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkDisconnect(vzDriverPtr driver)
|
2014-09-11 16:24:03 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job;
|
2017-02-03 07:01:55 +00:00
|
|
|
PRL_RESULT ret;
|
|
|
|
|
|
|
|
if (driver->server == PRL_INVALID_HANDLE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ret = PrlSrv_UnregEventHandler(driver->server,
|
|
|
|
prlsdkEventsHandler,
|
|
|
|
driver);
|
|
|
|
if (PRL_FAILED(ret))
|
|
|
|
logPrlError(ret);
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_Logoff(driver->server);
|
2015-05-13 14:23:00 +00:00
|
|
|
waitJob(job);
|
2014-09-11 16:24:03 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
PrlHandle_Free(driver->server);
|
2017-02-03 07:01:55 +00:00
|
|
|
driver->server = PRL_INVALID_HANDLE;
|
2014-09-11 16:24:03 +00:00
|
|
|
}
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
static int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSdkDomainLookup(vzDriverPtr driver,
|
2014-12-01 15:38:48 +00:00
|
|
|
const char *id,
|
|
|
|
unsigned int flags,
|
|
|
|
PRL_HANDLE *sdkdom)
|
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
|
|
|
|
int ret = -1;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_GetVmConfig(driver->server, id, flags);
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(getJobResult(job, &result)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlResult_GetParamByIndex(result, 0, sdkdom);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
prlsdkUUIDFormat(const unsigned char *uuid, char *uuidstr)
|
|
|
|
{
|
|
|
|
virUUIDFormat(uuid, uuidstr + 1);
|
|
|
|
|
|
|
|
uuidstr[0] = '{';
|
|
|
|
uuidstr[VIR_UUID_STRING_BUFLEN] = '}';
|
|
|
|
uuidstr[VIR_UUID_STRING_BUFLEN + 1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRL_HANDLE
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSdkDomainLookupByUUID(vzDriverPtr driver, const unsigned char *uuid)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
2016-05-18 08:11:08 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
|
2014-12-01 15:38:48 +00:00
|
|
|
PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
prlsdkUUIDFormat(uuid, uuidstr);
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkSdkDomainLookup(driver, uuidstr,
|
2014-12-01 15:38:48 +00:00
|
|
|
PGVC_SEARCH_BY_UUID, &sdkdom) < 0) {
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sdkdom;
|
|
|
|
}
|
|
|
|
|
2016-06-08 07:17:22 +00:00
|
|
|
PRL_HANDLE
|
|
|
|
prlsdkSdkDomainLookupByName(vzDriverPtr driver, const char *name)
|
|
|
|
{
|
|
|
|
PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
if (prlsdkSdkDomainLookup(driver, name,
|
|
|
|
PGVC_SEARCH_BY_NAME, &sdkdom) < 0) {
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching name '%s'"), name);
|
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sdkdom;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
static int
|
|
|
|
prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid)
|
|
|
|
{
|
|
|
|
char *tmp = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckNonNullArgGoto(uuidstr, error);
|
|
|
|
virCheckNonNullArgGoto(uuid, error);
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
tmp = g_strdup(uuidstr);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
tmp[strlen(tmp) - 1] = '\0';
|
|
|
|
|
|
|
|
/* trim curly braces */
|
2015-09-21 11:08:41 +00:00
|
|
|
if (virUUIDParse(tmp + 1, uuid) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
prlsdkGetDomainState(virDomainObjPtr dom, PRL_HANDLE sdkdom, VIRTUAL_MACHINE_STATE_PTR vmState)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE vmInfo = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
job = PrlVm_GetState(sdkdom);
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(getDomainJobResult(job, dom, &result)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlResult_GetParamByIndex(result, 0, &vmInfo);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmInfo_GetState(vmInfo, vmState);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(vmInfo);
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-12-09 14:39:20 +00:00
|
|
|
prlsdkAddDomainVideoInfoCt(virDomainDefPtr def,
|
|
|
|
virDomainXMLOptionPtr xmlopt)
|
2016-04-20 14:05:41 +00:00
|
|
|
{
|
|
|
|
virDomainVideoDefPtr video = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (def->ngraphics == 0)
|
|
|
|
return 0;
|
|
|
|
|
2019-12-09 14:39:20 +00:00
|
|
|
if (!(video = virDomainVideoDefNew(xmlopt)))
|
2016-04-20 14:05:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
video->type = VIR_DOMAIN_VIDEO_TYPE_PARALLELS;
|
|
|
|
video->vram = 0;
|
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT(def->videos, def->nvideos, video) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virDomainVideoDefFree(video);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkAddDomainVideoInfoVm(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
|
|
|
virDomainVideoDefPtr video = NULL;
|
|
|
|
virDomainVideoAccelDefPtr accel = NULL;
|
|
|
|
PRL_RESULT ret;
|
|
|
|
PRL_UINT32 videoRam;
|
|
|
|
|
|
|
|
/* video info */
|
|
|
|
ret = PrlVmCfg_GetVideoRamSize(sdkdom, &videoRam);
|
|
|
|
prlsdkCheckRetGoto(ret, error);
|
|
|
|
|
|
|
|
if (VIR_ALLOC(video) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(accel) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT_COPY(def->videos, def->nvideos, video) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
video->type = VIR_DOMAIN_VIDEO_TYPE_VGA;
|
|
|
|
video->vram = videoRam << 10; /* from mbibytes to kbibytes */
|
|
|
|
video->heads = 1;
|
|
|
|
video->accel = accel;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(accel);
|
|
|
|
virDomainVideoDefFree(video);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-04-14 10:45:03 +00:00
|
|
|
static int
|
2016-08-15 16:02:49 +00:00
|
|
|
prlsdkGetDiskId(PRL_HANDLE disk, int *bus, char **dst)
|
2016-04-14 10:45:03 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 pos, ifType;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetStackIndex(disk, &pos);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
|
2016-08-15 16:02:49 +00:00
|
|
|
pret = PrlVmDev_GetIfaceType(disk, &ifType);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2016-04-14 10:45:03 +00:00
|
|
|
|
|
|
|
switch (ifType) {
|
|
|
|
case PMS_IDE_DEVICE:
|
|
|
|
*bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
*dst = virIndexToDiskName(pos, "hd");
|
|
|
|
break;
|
|
|
|
case PMS_SCSI_DEVICE:
|
2016-12-05 12:37:12 +00:00
|
|
|
case PMS_UNKNOWN_DEVICE:
|
2016-04-14 10:45:03 +00:00
|
|
|
*bus = VIR_DOMAIN_DISK_BUS_SCSI;
|
|
|
|
*dst = virIndexToDiskName(pos, "sd");
|
|
|
|
break;
|
|
|
|
case PMS_SATA_DEVICE:
|
|
|
|
*bus = VIR_DOMAIN_DISK_BUS_SATA;
|
|
|
|
*dst = virIndexToDiskName(pos, "sd");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown disk bus: %X"), ifType);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-06 15:54:23 +00:00
|
|
|
if (NULL == *dst)
|
|
|
|
return -1;
|
|
|
|
|
2016-04-14 10:45:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
static int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkGetDiskInfo(vzDriverPtr driver,
|
2016-03-15 07:47:49 +00:00
|
|
|
PRL_HANDLE prldisk,
|
2014-12-01 15:38:57 +00:00
|
|
|
virDomainDiskDefPtr disk,
|
2015-06-03 21:10:00 +00:00
|
|
|
bool isCdrom,
|
|
|
|
bool isCt)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
|
|
|
char *buf = NULL;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 emulatedType;
|
2016-12-12 07:56:34 +00:00
|
|
|
PRL_UINT32 size;
|
2015-04-20 06:25:00 +00:00
|
|
|
virDomainDeviceDriveAddressPtr address;
|
2016-04-14 10:45:03 +00:00
|
|
|
int busIdx, devIdx;
|
2014-12-01 15:38:48 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
if (emulatedType == PDT_USE_IMAGE_FILE) {
|
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
|
2016-03-15 07:47:49 +00:00
|
|
|
if (isCdrom) {
|
2014-12-23 13:23:34 +00:00
|
|
|
virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
|
2016-03-15 07:47:49 +00:00
|
|
|
} else {
|
|
|
|
if (isCt)
|
2016-03-28 19:11:30 +00:00
|
|
|
virDomainDiskSetFormat(disk, driver->vzCaps.ctDiskFormat);
|
2016-03-15 07:47:49 +00:00
|
|
|
else
|
2016-03-28 19:11:30 +00:00
|
|
|
virDomainDiskSetFormat(disk, driver->vzCaps.vmDiskFormat);
|
2016-03-15 07:47:49 +00:00
|
|
|
}
|
2014-12-01 15:38:48 +00:00
|
|
|
} else {
|
|
|
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
2014-12-15 12:47:24 +00:00
|
|
|
virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
2015-04-07 20:35:03 +00:00
|
|
|
if (isCdrom) {
|
2014-12-01 15:38:57 +00:00
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
2015-04-07 20:35:03 +00:00
|
|
|
disk->src->readonly = true;
|
|
|
|
} else {
|
2014-12-01 15:38:57 +00:00
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
2015-04-07 20:35:03 +00:00
|
|
|
}
|
2014-12-01 15:38:57 +00:00
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(buf = prlsdkGetStringParamVar(PrlVmDev_GetFriendlyName, prldisk)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-14 15:00:09 +00:00
|
|
|
if (*buf != '\0' && virDomainDiskSetSource(disk, buf) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-08-15 16:02:49 +00:00
|
|
|
if (prlsdkGetDiskId(prldisk, &disk->bus, &disk->dst) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-14 10:45:03 +00:00
|
|
|
if (virDiskNameToBusDeviceIndex(disk, &busIdx, &devIdx) < 0)
|
2015-04-20 06:25:00 +00:00
|
|
|
goto cleanup;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-04-14 10:45:03 +00:00
|
|
|
address = &disk->info.addr.drive;
|
|
|
|
address->bus = busIdx;
|
|
|
|
address->target = 0;
|
|
|
|
address->unit = devIdx;
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
|
|
|
|
|
2016-09-22 14:55:41 +00:00
|
|
|
if (!isCdrom) {
|
|
|
|
if (!(disk->serial = prlsdkGetStringParamVar(PrlVmDevHd_GetSerialNumber, prldisk)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (*disk->serial == '\0')
|
|
|
|
VIR_FREE(disk->serial);
|
|
|
|
}
|
|
|
|
|
2016-09-22 14:55:42 +00:00
|
|
|
if (virDomainDiskSetDriver(disk, "vz") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-12-12 07:56:34 +00:00
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
|
|
|
|
pret = PrlVmDevHd_GetDiskSize(prldisk, &size);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
/* from MiB to bytes */
|
|
|
|
disk->src->capacity = ((unsigned long long)size) << 20;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-01-13 11:27:37 +00:00
|
|
|
static int
|
|
|
|
prlsdkGetFSInfo(PRL_HANDLE prldisk,
|
|
|
|
virDomainFSDefPtr fs)
|
|
|
|
{
|
|
|
|
char *buf = NULL;
|
|
|
|
int ret = -1;
|
2016-07-14 13:52:41 +00:00
|
|
|
char **matches = NULL;
|
|
|
|
virURIPtr uri = NULL;
|
2015-01-13 11:27:37 +00:00
|
|
|
|
|
|
|
fs->type = VIR_DOMAIN_FS_TYPE_FILE;
|
|
|
|
fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP;
|
|
|
|
fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
|
|
|
|
fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
|
|
|
|
fs->format = VIR_STORAGE_FILE_PLOOP;
|
|
|
|
|
|
|
|
fs->readonly = false;
|
|
|
|
fs->symlinksResolved = false;
|
|
|
|
|
2016-07-14 13:52:41 +00:00
|
|
|
if (!(buf = prlsdkGetStringParamVar(PrlVmDevHd_GetStorageURL, prldisk)))
|
2015-01-13 11:27:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-07-14 13:52:41 +00:00
|
|
|
if (!virStringIsEmpty(buf)) {
|
|
|
|
if (!(uri = virURIParse(buf)))
|
|
|
|
goto cleanup;
|
|
|
|
if (STRNEQ("libvirt", uri->scheme)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown uri scheme: '%s'"),
|
|
|
|
uri->scheme);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(matches = virStringSplitCount(uri->path, "/", 0, NULL)) ||
|
|
|
|
!matches[0]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("splitting StorageUrl failed %s"), uri->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!matches[1]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("can't identify pool in uri %s "), uri->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!matches[2]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("can't identify volume in uri %s"), uri->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
fs->type = VIR_DOMAIN_FS_TYPE_VOLUME;
|
|
|
|
if (VIR_ALLOC(fs->src->srcpool) < 0)
|
|
|
|
goto cleanup;
|
2019-10-20 11:49:46 +00:00
|
|
|
fs->src->srcpool->pool = g_strdup(matches[1]);
|
|
|
|
fs->src->srcpool->volume = g_strdup(matches[2]);
|
2016-07-14 13:52:41 +00:00
|
|
|
VIR_FREE(buf);
|
|
|
|
} else {
|
|
|
|
fs->type = VIR_DOMAIN_FS_TYPE_FILE;
|
|
|
|
if (!(buf = prlsdkGetStringParamVar(PrlVmDev_GetImagePath, prldisk)))
|
|
|
|
goto cleanup;
|
2015-01-13 11:27:37 +00:00
|
|
|
|
2016-07-14 13:52:41 +00:00
|
|
|
fs->src->path = buf;
|
|
|
|
buf = NULL;
|
|
|
|
}
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(buf = prlsdkGetStringParamVar(PrlVmDevHd_GetMountPoint, prldisk)))
|
2015-01-13 11:27:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
fs->dst = buf;
|
|
|
|
buf = NULL;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(buf);
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(matches);
|
2015-01-13 11:27:37 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
static int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkAddDomainHardDisksInfo(vzDriverPtr driver, PRL_HANDLE sdkdom, virDomainDefPtr def)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 hddCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
PRL_HANDLE hdd = PRL_INVALID_HANDLE;
|
|
|
|
virDomainDiskDefPtr disk = NULL;
|
2015-01-13 11:27:37 +00:00
|
|
|
virDomainFSDefPtr fs = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
for (i = 0; i < hddCount; ++i) {
|
2015-06-03 21:10:00 +00:00
|
|
|
|
|
|
|
PRL_UINT32 emulatedType;
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2015-06-03 21:10:00 +00:00
|
|
|
pret = PrlVmDev_GetEmulatedType(hdd, &emulatedType);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
if (IS_CT(def) &&
|
|
|
|
prlsdkInBootList(sdkdom, hdd)) {
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2019-12-10 12:51:54 +00:00
|
|
|
if (!(fs = virDomainFSDefNew(NULL)))
|
2015-01-13 11:27:37 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (prlsdkGetFSInfo(hdd, fs) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virDomainFSInsert(def, fs) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
fs = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
PrlHandle_Free(hdd);
|
|
|
|
hdd = PRL_INVALID_HANDLE;
|
|
|
|
} else {
|
2015-05-13 07:00:02 +00:00
|
|
|
if (!(disk = virDomainDiskDefNew(NULL)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkGetDiskInfo(driver, hdd, disk, false, IS_CT(def)) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-03-22 13:56:37 +00:00
|
|
|
if (virDomainDiskInsert(def, disk) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
2015-01-13 11:27:37 +00:00
|
|
|
|
|
|
|
disk = NULL;
|
|
|
|
PrlHandle_Free(hdd);
|
|
|
|
hdd = PRL_INVALID_HANDLE;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
PrlHandle_Free(hdd);
|
|
|
|
virDomainDiskDefFree(disk);
|
2015-01-13 11:27:37 +00:00
|
|
|
virDomainFSDefFree(fs);
|
2014-12-01 15:38:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:57 +00:00
|
|
|
static int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkAddDomainOpticalDisksInfo(vzDriverPtr driver, PRL_HANDLE sdkdom, virDomainDefPtr def)
|
2014-12-01 15:38:57 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 cdromsCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
PRL_HANDLE cdrom = PRL_INVALID_HANDLE;
|
|
|
|
virDomainDiskDefPtr disk = NULL;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetOpticalDisksCount(sdkdom, &cdromsCount);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
for (i = 0; i < cdromsCount; ++i) {
|
|
|
|
pret = PrlVmCfg_GetOpticalDisk(sdkdom, i, &cdrom);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2015-05-13 07:00:02 +00:00
|
|
|
if (!(disk = virDomainDiskDefNew(NULL)))
|
2014-12-01 15:38:57 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkGetDiskInfo(driver, cdrom, disk, true, IS_CT(def)) < 0)
|
2014-12-01 15:38:57 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
PrlHandle_Free(cdrom);
|
|
|
|
cdrom = PRL_INVALID_HANDLE;
|
|
|
|
|
2016-03-22 13:56:37 +00:00
|
|
|
if (virDomainDiskInsert(def, disk) < 0)
|
2014-12-01 15:38:57 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
PrlHandle_Free(cdrom);
|
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
static virNetDevIPAddrPtr
|
2016-04-20 14:05:36 +00:00
|
|
|
prlsdkParseNetAddress(char *addr)
|
|
|
|
{
|
|
|
|
char *maskstr = NULL;
|
|
|
|
int nbits;
|
|
|
|
virSocketAddr mask;
|
2016-06-27 18:23:11 +00:00
|
|
|
virNetDevIPAddrPtr ip = NULL, ret = NULL;
|
2016-04-20 14:05:36 +00:00
|
|
|
|
|
|
|
if (!(maskstr = strchr(addr, '/')))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
*maskstr = '\0';
|
|
|
|
++maskstr;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ip) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virSocketAddrParse(&ip->address, addr, AF_UNSPEC) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virSocketAddrParse(&mask, maskstr, AF_UNSPEC) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((nbits = virSocketAddrGetNumNetmaskBits(&mask)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
ip->prefix = nbits;
|
|
|
|
|
2019-10-16 11:45:15 +00:00
|
|
|
ret = g_steal_pointer(&ip);
|
2016-04-20 14:05:36 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (!ret)
|
|
|
|
VIR_WARN("cannot parse network address '%s'", addr);
|
|
|
|
|
|
|
|
VIR_FREE(ip);
|
|
|
|
VIR_FREE(addr);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkGetNetAddresses(PRL_HANDLE sdknet, virDomainNetDefPtr net)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
PRL_HANDLE addrlist = PRL_INVALID_HANDLE;
|
|
|
|
PRL_UINT32 num;
|
|
|
|
size_t i;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_GetNetAddresses(sdknet, &addrlist);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
PrlStrList_GetItemsCount(addrlist, &num);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
for (i = 0; i < num; ++i) {
|
2016-06-28 08:09:52 +00:00
|
|
|
virNetDevIPAddrPtr ip = NULL;
|
2016-04-20 14:05:36 +00:00
|
|
|
PRL_UINT32 buflen = 0;
|
|
|
|
char *addr;
|
|
|
|
|
|
|
|
pret = PrlStrList_GetItem(addrlist, i, NULL, &buflen);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(addr, buflen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlStrList_GetItem(addrlist, i, addr, &buflen);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (!(ip = prlsdkParseNetAddress(addr)))
|
|
|
|
continue;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(net->guestIP.ips, net->guestIP.nips, ip) < 0) {
|
2016-04-20 14:05:36 +00:00
|
|
|
VIR_FREE(ip);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
PrlHandle_Free(addrlist);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:37 +00:00
|
|
|
static int
|
|
|
|
prlsdkGetRoutes(PRL_HANDLE sdknet, virDomainNetDefPtr net)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *gw = NULL;
|
|
|
|
char *gw6 = NULL;
|
2016-06-27 18:23:11 +00:00
|
|
|
virNetDevIPRoutePtr route = NULL;
|
2016-04-20 14:05:37 +00:00
|
|
|
|
|
|
|
if (!(gw = prlsdkGetStringParamVar(PrlVmDevNet_GetDefaultGateway, sdknet)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(gw6 = prlsdkGetStringParamVar(PrlVmDevNet_GetDefaultGatewayIPv6, sdknet)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (*gw != '\0') {
|
2016-06-27 18:23:11 +00:00
|
|
|
|
|
|
|
if (!(route = virNetDevIPRouteCreate(_("Domain interface"),
|
2016-04-20 14:05:37 +00:00
|
|
|
"ipv4", VIR_SOCKET_ADDR_IPV4_ALL,
|
|
|
|
NULL, gw, 0, true, 0, false)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(net->guestIP.routes, net->guestIP.nroutes, route) < 0)
|
2016-04-20 14:05:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*gw6 != '\0') {
|
2016-06-27 18:23:11 +00:00
|
|
|
if (!(route = virNetDevIPRouteCreate(_("Domain interface"),
|
2016-04-20 14:05:37 +00:00
|
|
|
"ipv6", VIR_SOCKET_ADDR_IPV6_ALL,
|
|
|
|
NULL, gw6, 0, true, 0, false)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(net->guestIP.routes, net->guestIP.nroutes, route) < 0)
|
2016-04-20 14:05:37 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-06-27 18:23:11 +00:00
|
|
|
virNetDevIPRouteFree(route);
|
2016-04-20 14:05:37 +00:00
|
|
|
VIR_FREE(gw);
|
|
|
|
VIR_FREE(gw6);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
static int
|
|
|
|
prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt)
|
|
|
|
{
|
|
|
|
char macstr[VIR_MAC_STRING_BUFLEN];
|
|
|
|
PRL_UINT32 netAdapterIndex;
|
|
|
|
PRL_UINT32 emulatedType;
|
|
|
|
PRL_RESULT pret;
|
2016-04-20 14:05:40 +00:00
|
|
|
PRL_BOOL isConnected, isMacFilter;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
/* use device name, shown by prlctl as target device
|
|
|
|
* for identifying network adapter in virDomainDefineXML */
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(net->ifname = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
|
|
|
|
netAdapter)))
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2015-03-18 08:33:53 +00:00
|
|
|
pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-03-18 08:33:53 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
if (isCt && netAdapterIndex == (PRL_UINT32) -1) {
|
|
|
|
/* venet devices don't have mac address and
|
|
|
|
* always up */
|
|
|
|
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
|
2016-08-03 11:40:20 +00:00
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
|
2019-10-20 11:49:46 +00:00
|
|
|
net->data.network.name = g_strdup(PARALLELS_DOMAIN_ROUTED_NETWORK_NAME);
|
2014-12-01 15:38:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
pret = prlsdkGetStringParamBuf(PrlVmDevNet_GetMacAddressCanonical,
|
|
|
|
netAdapter, macstr, sizeof(macstr));
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (virMacAddrParse(macstr, &net->mac) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-04-20 14:05:36 +00:00
|
|
|
if (prlsdkGetNetAddresses(netAdapter, net) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-20 14:05:36 +00:00
|
|
|
|
2016-04-20 14:05:37 +00:00
|
|
|
if (prlsdkGetRoutes(netAdapter, net) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-20 14:05:37 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
pret = PrlVmDev_GetEmulatedType(netAdapter, &emulatedType);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (emulatedType == PNA_ROUTED) {
|
2016-08-03 11:40:20 +00:00
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
|
2019-10-20 11:49:46 +00:00
|
|
|
net->data.network.name = g_strdup(PARALLELS_DOMAIN_ROUTED_NETWORK_NAME);
|
2014-12-01 15:38:48 +00:00
|
|
|
} else {
|
2016-09-05 16:39:31 +00:00
|
|
|
char *netid =
|
2016-04-13 16:05:43 +00:00
|
|
|
prlsdkGetStringParamVar(PrlVmDevNet_GetVirtualNetworkId,
|
2016-09-05 16:39:31 +00:00
|
|
|
netAdapter);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-09-05 16:39:31 +00:00
|
|
|
if (emulatedType == PNA_BRIDGE) {
|
2015-03-18 08:33:53 +00:00
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
|
2016-09-05 16:39:31 +00:00
|
|
|
if (netid)
|
|
|
|
net->data.bridge.brname = netid;
|
2016-04-20 14:05:39 +00:00
|
|
|
} else {
|
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
|
2016-09-05 16:39:31 +00:00
|
|
|
if (netid)
|
|
|
|
net->data.network.name = netid;
|
2016-04-20 14:05:39 +00:00
|
|
|
}
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
2015-04-07 20:35:05 +00:00
|
|
|
if (!isCt) {
|
|
|
|
PRL_VM_NET_ADAPTER_TYPE type;
|
|
|
|
pret = PrlVmDevNet_GetAdapterType(netAdapter, &type);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-04-07 20:35:05 +00:00
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)type) {
|
2015-04-07 20:35:05 +00:00
|
|
|
case PNT_RTL:
|
2019-01-18 00:53:14 +00:00
|
|
|
net->model = VIR_DOMAIN_NET_MODEL_RTL8139;
|
2015-04-07 20:35:05 +00:00
|
|
|
break;
|
|
|
|
case PNT_E1000:
|
2019-01-18 00:53:14 +00:00
|
|
|
net->model = VIR_DOMAIN_NET_MODEL_E1000;
|
2015-04-07 20:35:05 +00:00
|
|
|
break;
|
|
|
|
case PNT_VIRTIO:
|
2019-01-18 00:53:14 +00:00
|
|
|
net->model = VIR_DOMAIN_NET_MODEL_VIRTIO;
|
2015-04-07 20:35:05 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown adapter type: %X"), type);
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2015-04-07 20:35:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
pret = PrlVmDev_IsConnected(netAdapter, &isConnected);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (isConnected)
|
|
|
|
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
|
|
|
|
else
|
|
|
|
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
|
|
|
|
|
2016-04-20 14:05:40 +00:00
|
|
|
pret = PrlVmDevNet_IsPktFilterPreventMacSpoof(netAdapter, &isMacFilter);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2016-04-20 14:05:40 +00:00
|
|
|
|
|
|
|
net->trustGuestRxFilters = isMacFilter ? VIR_TRISTATE_BOOL_YES :
|
|
|
|
VIR_TRISTATE_BOOL_NO;
|
|
|
|
|
2020-01-06 21:57:42 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkAddDomainNetInfo(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
virDomainNetDefPtr net = NULL;
|
|
|
|
PRL_RESULT ret;
|
|
|
|
PRL_HANDLE netAdapter;
|
|
|
|
PRL_UINT32 netAdaptersCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
|
|
|
|
ret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &netAdaptersCount);
|
|
|
|
prlsdkCheckRetGoto(ret, error);
|
|
|
|
for (i = 0; i < netAdaptersCount; ++i) {
|
|
|
|
ret = PrlVmCfg_GetNetAdapter(sdkdom, i, &netAdapter);
|
|
|
|
prlsdkCheckRetGoto(ret, error);
|
|
|
|
|
|
|
|
if (VIR_ALLOC(net) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (prlsdkGetNetInfo(netAdapter, net, IS_CT(def)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
PrlHandle_Free(netAdapter);
|
|
|
|
netAdapter = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
PrlHandle_Free(netAdapter);
|
|
|
|
virDomainNetDefFree(net);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkGetSerialInfo(PRL_HANDLE serialPort, virDomainChrDefPtr chr)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 serialPortIndex;
|
|
|
|
PRL_UINT32 emulatedType;
|
|
|
|
char *friendlyName = NULL;
|
2016-05-31 09:38:32 +00:00
|
|
|
PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode;
|
2016-05-31 09:38:33 +00:00
|
|
|
char *uristr = NULL;
|
|
|
|
virURIPtr uri = NULL;
|
|
|
|
int ret = -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
|
|
|
pret = PrlVmDev_GetIndex(serialPort, &serialPortIndex);
|
2016-05-31 09:38:33 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:48 +00:00
|
|
|
chr->target.port = serialPortIndex;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetEmulatedType(serialPort, &emulatedType);
|
2016-05-31 09:38:33 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(friendlyName = prlsdkGetStringParamVar(PrlVmDev_GetFriendlyName,
|
|
|
|
serialPort)))
|
2016-05-31 09:38:33 +00:00
|
|
|
goto cleanup;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-05-31 09:38:32 +00:00
|
|
|
pret = PrlVmDevSerial_GetSocketMode(serialPort, &socket_mode);
|
2016-05-31 09:38:33 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2016-05-31 09:38:32 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
switch (emulatedType) {
|
|
|
|
case PDT_USE_OUTPUT_FILE:
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
|
|
|
chr->source->data.file.path = friendlyName;
|
2016-05-31 09:38:33 +00:00
|
|
|
friendlyName = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
case PDT_USE_SERIAL_PORT_SOCKET_MODE:
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
|
|
|
|
chr->source->data.nix.path = friendlyName;
|
|
|
|
chr->source->data.nix.listen = socket_mode == PSP_SERIAL_SOCKET_SERVER;
|
2016-05-31 09:38:33 +00:00
|
|
|
friendlyName = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
case PDT_USE_REAL_DEVICE:
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->type = VIR_DOMAIN_CHR_TYPE_DEV;
|
|
|
|
chr->source->data.file.path = friendlyName;
|
2016-05-31 09:38:33 +00:00
|
|
|
friendlyName = NULL;
|
|
|
|
break;
|
|
|
|
case PDT_USE_TCP:
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->type = VIR_DOMAIN_CHR_TYPE_TCP;
|
2019-10-22 13:26:14 +00:00
|
|
|
uristr = g_strdup_printf("tcp://%s", friendlyName);
|
2016-05-31 09:38:33 +00:00
|
|
|
if (!(uri = virURIParse(uristr)))
|
|
|
|
goto cleanup;
|
2019-10-20 11:49:46 +00:00
|
|
|
chr->source->data.tcp.host = g_strdup(uri->server);
|
2019-10-22 13:26:14 +00:00
|
|
|
chr->source->data.tcp.service = g_strdup_printf("%d", uri->port);
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->data.tcp.listen = socket_mode == PSP_SERIAL_SOCKET_SERVER;
|
2016-05-31 09:38:33 +00:00
|
|
|
break;
|
|
|
|
case PDT_USE_UDP:
|
2016-10-21 11:45:54 +00:00
|
|
|
chr->source->type = VIR_DOMAIN_CHR_TYPE_UDP;
|
2019-10-22 13:26:14 +00:00
|
|
|
uristr = g_strdup_printf("udp://%s", friendlyName);
|
2016-05-31 09:38:33 +00:00
|
|
|
if (!(uri = virURIParse(uristr)))
|
|
|
|
goto cleanup;
|
2019-10-20 11:49:46 +00:00
|
|
|
chr->source->data.udp.bindHost = g_strdup(uri->server);
|
2019-10-22 13:26:14 +00:00
|
|
|
chr->source->data.udp.bindService = g_strdup_printf("%d", uri->port);
|
2019-10-20 11:49:46 +00:00
|
|
|
chr->source->data.udp.connectHost = g_strdup(uri->server);
|
2019-10-22 13:26:14 +00:00
|
|
|
chr->source->data.udp.connectService = g_strdup_printf("%d", uri->port);
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown serial type: %X"), emulatedType);
|
2016-05-31 09:38:33 +00:00
|
|
|
goto cleanup;
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-31 09:38:33 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2014-12-01 15:38:48 +00:00
|
|
|
VIR_FREE(friendlyName);
|
2016-05-31 09:38:33 +00:00
|
|
|
VIR_FREE(uristr);
|
|
|
|
virURIFree(uri);
|
|
|
|
|
|
|
|
return ret;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkAddSerialInfo(PRL_HANDLE sdkdom,
|
|
|
|
virDomainChrDefPtr **serials,
|
|
|
|
size_t *nserials)
|
|
|
|
{
|
|
|
|
PRL_RESULT ret;
|
|
|
|
PRL_HANDLE serialPort;
|
|
|
|
PRL_UINT32 serialPortsCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
virDomainChrDefPtr chr = NULL;
|
|
|
|
|
|
|
|
ret = PrlVmCfg_GetSerialPortsCount(sdkdom, &serialPortsCount);
|
|
|
|
prlsdkCheckRetGoto(ret, cleanup);
|
|
|
|
for (i = 0; i < serialPortsCount; ++i) {
|
|
|
|
ret = PrlVmCfg_GetSerialPort(sdkdom, i, &serialPort);
|
|
|
|
prlsdkCheckRetGoto(ret, cleanup);
|
|
|
|
|
2016-06-17 10:36:11 +00:00
|
|
|
if (!(chr = virDomainChrDefNew(NULL)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (prlsdkGetSerialInfo(serialPort, chr))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
PrlHandle_Free(serialPort);
|
|
|
|
serialPort = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT(*serials, *nserials, chr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(serialPort);
|
|
|
|
virDomainChrDefFree(chr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2019-12-09 14:39:20 +00:00
|
|
|
prlsdkAddDomainHardware(vzDriverPtr driver,
|
|
|
|
PRL_HANDLE sdkdom,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainXMLOptionPtr xmlopt)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
2016-04-20 14:05:41 +00:00
|
|
|
if (IS_CT(def)) {
|
2019-12-09 14:39:20 +00:00
|
|
|
if (prlsdkAddDomainVideoInfoCt(def, xmlopt) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-20 14:05:41 +00:00
|
|
|
} else {
|
|
|
|
if (prlsdkAddDomainVideoInfoVm(sdkdom, def) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-20 14:05:41 +00:00
|
|
|
}
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkAddDomainHardDisksInfo(driver, sdkdom, def) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkAddDomainOpticalDisksInfo(driver, sdkdom, def) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:57 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
if (prlsdkAddDomainNetInfo(sdkdom, def) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (prlsdkAddSerialInfo(sdkdom,
|
|
|
|
&def->serials,
|
|
|
|
&def->nserials) < 0)
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkAddVNCInfo(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
virDomainGraphicsDefPtr gr = NULL;
|
|
|
|
PRL_VM_REMOTE_DISPLAY_MODE vncMode;
|
|
|
|
PRL_UINT32 port;
|
|
|
|
PRL_RESULT pret;
|
2016-04-20 14:05:44 +00:00
|
|
|
char *passwd = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_GetVNCMode(sdkdom, &vncMode);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
if (vncMode == PRD_DISABLED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(gr) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2016-04-20 14:05:44 +00:00
|
|
|
if (!(passwd = prlsdkGetStringParamVar(PrlVmCfg_GetVNCPassword, sdkdom)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (*passwd != '\0') {
|
|
|
|
gr->data.vnc.auth.passwd = passwd;
|
|
|
|
passwd = NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
pret = PrlVmCfg_GetVNCPort(sdkdom, &port);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
gr->data.vnc.autoport = (vncMode == PRD_AUTO);
|
|
|
|
gr->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
|
|
|
|
gr->data.vnc.port = port;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(gr->listens) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
gr->nListens = 1;
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(gr->listens[0].address = prlsdkGetStringParamVar(PrlVmCfg_GetVNCHostName,
|
|
|
|
sdkdom)))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
gr->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
|
|
|
|
|
|
|
|
if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, gr) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainGraphicsDefFree(gr);
|
2016-04-20 14:05:44 +00:00
|
|
|
VIR_FREE(passwd);
|
2014-12-01 15:38:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-03-11 08:36:17 +00:00
|
|
|
static void
|
2014-12-01 15:38:48 +00:00
|
|
|
prlsdkConvertDomainState(VIRTUAL_MACHINE_STATE domainState,
|
|
|
|
PRL_UINT32 envId,
|
|
|
|
virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
switch (domainState) {
|
|
|
|
case VMS_STOPPED:
|
|
|
|
case VMS_MOUNTED:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
|
|
|
dom->def->id = -1;
|
|
|
|
break;
|
|
|
|
case VMS_STARTING:
|
|
|
|
case VMS_COMPACTING:
|
|
|
|
case VMS_RESETTING:
|
|
|
|
case VMS_PAUSING:
|
|
|
|
case VMS_RECONNECTING:
|
|
|
|
case VMS_RUNNING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_BOOTED);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_PAUSED:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_PAUSED_USER);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_SUSPENDED:
|
|
|
|
case VMS_DELETING_STATE:
|
|
|
|
case VMS_SUSPENDING_SYNC:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SHUTOFF_SAVED);
|
|
|
|
dom->def->id = -1;
|
|
|
|
break;
|
|
|
|
case VMS_STOPPING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_SHUTDOWN,
|
|
|
|
VIR_DOMAIN_SHUTDOWN_USER);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_SNAPSHOTING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_PAUSED_SNAPSHOT);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_MIGRATING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_PAUSED_MIGRATION);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_SUSPENDING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_PAUSED_SAVE);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_RESTORING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_RESTORED);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_CONTINUING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_RESUMING:
|
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_RESTORED);
|
|
|
|
dom->def->id = envId;
|
|
|
|
break;
|
|
|
|
case VMS_UNKNOWN:
|
2016-03-11 08:36:17 +00:00
|
|
|
default:
|
2014-12-01 15:38:48 +00:00
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_NOSTATE,
|
|
|
|
VIR_DOMAIN_NOSTATE_UNKNOWN);
|
2016-03-11 08:36:17 +00:00
|
|
|
dom->def->id = -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkConvertCpuInfo(PRL_HANDLE sdkdom,
|
2016-06-29 12:55:24 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainXMLOptionPtr xmlopt)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
2020-03-05 16:17:55 +00:00
|
|
|
g_autofree char *buf = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
int hostcpus;
|
|
|
|
PRL_UINT32 cpuCount;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
2016-04-13 17:16:16 +00:00
|
|
|
if ((hostcpus = virHostCPUGetCount()) < 0)
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
/* get number of CPUs */
|
|
|
|
pret = PrlVmCfg_GetCpuCount(sdkdom, &cpuCount);
|
2020-03-05 16:17:55 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (cpuCount > hostcpus)
|
|
|
|
cpuCount = hostcpus;
|
|
|
|
|
2016-06-29 12:55:24 +00:00
|
|
|
if (virDomainDefSetVcpusMax(def, cpuCount, xmlopt) < 0)
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2015-10-16 14:10:27 +00:00
|
|
|
|
2015-10-22 08:52:05 +00:00
|
|
|
if (virDomainDefSetVcpus(def, cpuCount) < 0)
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(buf = prlsdkGetStringParamVar(PrlVmCfg_GetCpuMask, sdkdom)))
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
if (strlen(buf) == 0) {
|
2015-03-10 20:12:19 +00:00
|
|
|
if (!(def->cpumask = virBitmapNew(hostcpus)))
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2015-03-10 20:12:19 +00:00
|
|
|
virBitmapSetAll(def->cpumask);
|
2014-12-01 15:38:48 +00:00
|
|
|
} else {
|
2016-06-17 12:56:45 +00:00
|
|
|
if (virBitmapParse(buf, &def->cpumask, hostcpus) < 0)
|
2020-03-05 16:17:55 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 16:17:55 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkConvertDomainType(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
PRL_VM_TYPE domainType;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetVmType(sdkdom, &domainType);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
switch (domainType) {
|
|
|
|
case PVT_VM:
|
2015-04-17 00:11:06 +00:00
|
|
|
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
case PVT_CT:
|
2015-04-17 00:11:06 +00:00
|
|
|
def->os.type = VIR_DOMAIN_OSTYPE_EXE;
|
2019-10-20 11:49:46 +00:00
|
|
|
def->os.init = g_strdup("/sbin/init");
|
2014-12-01 15:38:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown domain type: %X"), domainType);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkConvertCpuMode(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_CPU_MODE cpuMode;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetCpuMode(sdkdom, &cpuMode);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
switch (cpuMode) {
|
|
|
|
case PCM_CPU_MODE_32:
|
|
|
|
def->os.arch = VIR_ARCH_I686;
|
|
|
|
break;
|
|
|
|
case PCM_CPU_MODE_64:
|
|
|
|
def->os.arch = VIR_ARCH_X86_64;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown CPU mode: %X"), cpuMode);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-22 13:56:38 +00:00
|
|
|
static PRL_HANDLE
|
|
|
|
prlsdkGetDevByDevIndex(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE type, PRL_UINT32 devIndex)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 index, num;
|
|
|
|
PRL_HANDLE dev = PRL_INVALID_HANDLE;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetDevsCountByType(sdkdom, type, &num);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
for (i = 0; i < num; ++i) {
|
|
|
|
pret = PrlVmCfg_GetDevByType(sdkdom, type, i, &dev);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetIndex(dev, &index);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
if (index == devIndex)
|
|
|
|
break;
|
|
|
|
|
|
|
|
PrlHandle_Free(dev);
|
|
|
|
dev = PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
|
|
|
|
error:
|
|
|
|
PrlHandle_Free(dev);
|
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainDiskDefPtr
|
|
|
|
virFindDiskBootIndex(virDomainDefPtr def, virDomainDiskDevice type, int index)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < def->ndisks; ++i) {
|
|
|
|
if (def->disks[i]->device != type)
|
|
|
|
continue;
|
|
|
|
if (c == index)
|
|
|
|
return def->disks[i];
|
|
|
|
++c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
static bool
|
|
|
|
prlsdkInBootList(PRL_HANDLE sdkdom,
|
|
|
|
PRL_HANDLE sdktargetdev)
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 bootNum;
|
|
|
|
PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
|
|
|
|
PRL_BOOL inUse;
|
|
|
|
PRL_DEVICE_TYPE sdkType, targetType;
|
|
|
|
PRL_UINT32 sdkIndex, targetIndex;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetType(sdktargetdev, &targetType);
|
2020-02-22 23:22:47 +00:00
|
|
|
prlsdkCheckRetExit(pret, false);
|
2016-12-05 13:34:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmDev_GetIndex(sdktargetdev, &targetIndex);
|
2020-02-22 23:22:47 +00:00
|
|
|
prlsdkCheckRetExit(pret, false);
|
2016-12-05 13:34:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_GetBootDevCount(sdkdom, &bootNum);
|
2020-02-22 23:22:47 +00:00
|
|
|
prlsdkCheckRetExit(pret, false);
|
2016-12-05 13:34:52 +00:00
|
|
|
|
|
|
|
for (i = 0; i < bootNum; ++i) {
|
|
|
|
pret = PrlVmCfg_GetBootDev(sdkdom, i, &bootDev);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlBootDev_IsInUse(bootDev, &inUse);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (!inUse) {
|
|
|
|
PrlHandle_Free(bootDev);
|
|
|
|
bootDev = PRL_INVALID_HANDLE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlBootDev_GetType(bootDev, &sdkType);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlBootDev_GetIndex(bootDev, &sdkIndex);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
PrlHandle_Free(bootDev);
|
|
|
|
bootDev = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
if (sdkIndex == targetIndex && sdkType == targetType) {
|
|
|
|
ret = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(bootDev);
|
|
|
|
return ret;
|
|
|
|
}
|
2016-03-22 13:56:38 +00:00
|
|
|
static int
|
|
|
|
prlsdkBootOrderCheck(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE sdkType, int sdkIndex,
|
|
|
|
virDomainDefPtr def, int bootIndex)
|
|
|
|
{
|
|
|
|
char *sdkName = NULL;
|
|
|
|
PRL_HANDLE dev = PRL_INVALID_HANDLE;
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
virDomainDiskDevice device;
|
2016-04-14 10:45:05 +00:00
|
|
|
int bus;
|
|
|
|
char *dst = NULL;
|
2016-03-22 13:56:38 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
dev = prlsdkGetDevByDevIndex(sdkdom, sdkType, sdkIndex);
|
|
|
|
if (dev == PRL_INVALID_HANDLE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Can't find boot device of type: %d, device index: %d"),
|
|
|
|
sdkType, sdkIndex);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)sdkType) {
|
2016-03-22 13:56:38 +00:00
|
|
|
case PDE_OPTICAL_DISK:
|
|
|
|
case PDE_HARD_DISK:
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)sdkType) {
|
2016-03-22 13:56:38 +00:00
|
|
|
case PDE_OPTICAL_DISK:
|
|
|
|
device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
|
|
|
break;
|
|
|
|
case PDE_HARD_DISK:
|
|
|
|
device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unsupported disk type %d"), sdkType);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(disk = virFindDiskBootIndex(def, device, bootIndex))) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2016-04-29 18:22:36 +00:00
|
|
|
_("Can't find boot device of type: %s, index: %d"),
|
2016-03-22 13:56:38 +00:00
|
|
|
virDomainDiskDeviceTypeToString(device), bootIndex);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-08-15 16:02:49 +00:00
|
|
|
if (prlsdkGetDiskId(dev, &bus, &dst) < 0)
|
2016-04-14 10:45:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(bus == disk->bus && STREQ(disk->dst, dst)))
|
|
|
|
VIR_WARN("Unrepresentable boot order configuration");
|
2016-03-22 13:56:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
case PDE_GENERIC_NETWORK_ADAPTER:
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(sdkName = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
|
|
|
|
dev)))
|
2016-03-22 13:56:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (bootIndex >= def->nnets) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2016-04-29 18:22:36 +00:00
|
|
|
_("Can't find network boot device for index: %d"),
|
2016-03-22 13:56:38 +00:00
|
|
|
bootIndex);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-04-14 10:45:05 +00:00
|
|
|
if (STRNEQ(sdkName, def->nets[bootIndex]->ifname))
|
|
|
|
VIR_WARN("Unrepresentable boot order configuration");
|
2016-03-22 13:56:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unexpected device type %d"), sdkType);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
VIR_FREE(sdkName);
|
|
|
|
PrlHandle_Free(dev);
|
2016-04-14 10:45:05 +00:00
|
|
|
VIR_FREE(dst);
|
2016-03-22 13:56:38 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2016-12-05 13:11:15 +00:00
|
|
|
prlsdkConvertBootOrderVm(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
2016-03-22 13:56:38 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 bootNum;
|
|
|
|
PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
|
|
|
|
PRL_BOOL inUse;
|
|
|
|
PRL_DEVICE_TYPE sdkType;
|
|
|
|
virDomainBootOrder type;
|
|
|
|
PRL_UINT32 prevBootIndex = 0, bootIndex, sdkIndex;
|
|
|
|
int bootUsage[VIR_DOMAIN_BOOT_LAST] = { 0 };
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetBootDevCount(sdkdom, &bootNum);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
|
|
|
|
def->os.nBootDevs = 0;
|
|
|
|
|
|
|
|
if (bootNum > VIR_DOMAIN_MAX_BOOT_DEVS) {
|
|
|
|
bootNum = VIR_DOMAIN_MAX_BOOT_DEVS;
|
|
|
|
VIR_WARN("Too many boot devices");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < bootNum; ++i) {
|
|
|
|
pret = PrlVmCfg_GetBootDev(sdkdom, i, &bootDev);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlBootDev_IsInUse(bootDev, &inUse);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2017-06-30 06:34:27 +00:00
|
|
|
if (!inUse)
|
|
|
|
continue;
|
2016-03-22 13:56:38 +00:00
|
|
|
|
|
|
|
pret = PrlBootDev_GetSequenceIndex(bootDev, &bootIndex);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
/* bootIndex is started from 1 */
|
|
|
|
if (bootIndex <= prevBootIndex) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Unsupported boot order configuration"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
prevBootIndex = bootIndex;
|
|
|
|
|
|
|
|
pret = PrlBootDev_GetType(bootDev, &sdkType);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (sdkType == PDE_FLOPPY_DISK) {
|
|
|
|
VIR_WARN("Skipping floppy from boot order.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)sdkType) {
|
2016-03-22 13:56:38 +00:00
|
|
|
case PDE_OPTICAL_DISK:
|
|
|
|
type = VIR_DOMAIN_BOOT_CDROM;
|
|
|
|
break;
|
|
|
|
case PDE_HARD_DISK:
|
|
|
|
type = VIR_DOMAIN_BOOT_DISK;
|
|
|
|
break;
|
|
|
|
case PDE_GENERIC_NETWORK_ADAPTER:
|
|
|
|
type = VIR_DOMAIN_BOOT_NET;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unexpected boot device type %i"), sdkType);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlBootDev_GetIndex(bootDev, &sdkIndex);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (prlsdkBootOrderCheck(sdkdom, sdkType, sdkIndex, def, bootUsage[type]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
bootUsage[type]++;
|
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = type;
|
|
|
|
|
|
|
|
PrlHandle_Free(bootDev);
|
|
|
|
bootDev = PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(bootDev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
/* if dom is NULL adds new domain into domain list
|
|
|
|
* if dom not NULL updates given locked dom object.
|
|
|
|
*
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
* Returned object is locked and referenced.
|
2016-06-14 08:45:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static virDomainObjPtr
|
|
|
|
prlsdkLoadDomain(vzDriverPtr driver,
|
|
|
|
PRL_HANDLE sdkdom,
|
|
|
|
virDomainObjPtr dom)
|
2016-02-10 09:39:14 +00:00
|
|
|
{
|
2014-12-01 15:38:48 +00:00
|
|
|
virDomainDefPtr def = NULL;
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr pdom = NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
VIRTUAL_MACHINE_STATE domainState;
|
|
|
|
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 ram;
|
|
|
|
PRL_UINT32 envId;
|
|
|
|
PRL_VM_AUTOSTART_OPTION autostart;
|
2016-06-03 07:11:44 +00:00
|
|
|
PRL_HANDLE job;
|
2016-06-14 08:45:57 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2015-02-16 15:30:11 +00:00
|
|
|
if (!(def = virDomainDefNew()))
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
if (!(def->name = prlsdkGetStringParamVar(PrlVmCfg_GetName, sdkdom)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
pret = prlsdkGetStringParamBuf(PrlVmCfg_GetUuid,
|
|
|
|
sdkdom, uuidstr, sizeof(uuidstr));
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
if (prlsdkUUIDParse(uuidstr, def->uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Domain UUID is malformed or empty"));
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
2016-06-14 08:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_VZ;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2017-10-10 12:32:11 +00:00
|
|
|
def->onReboot = VIR_DOMAIN_LIFECYCLE_ACTION_RESTART;
|
|
|
|
def->onPoweroff = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY;
|
2017-10-10 12:51:38 +00:00
|
|
|
def->onCrash = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
/* get RAM parameters */
|
|
|
|
pret = PrlVmCfg_GetRamSize(sdkdom, &ram);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
2015-09-16 12:25:42 +00:00
|
|
|
virDomainDefSetMemoryTotal(def, ram << 10); /* RAM size obtained in Mbytes,
|
2015-02-17 17:01:09 +00:00
|
|
|
convert to Kbytes */
|
|
|
|
def->mem.cur_balloon = ram << 10;
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2016-06-29 12:55:24 +00:00
|
|
|
if (prlsdkConvertCpuInfo(sdkdom, def, driver->xmlopt) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (prlsdkConvertCpuMode(sdkdom, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (prlsdkConvertDomainType(sdkdom, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2016-04-20 14:05:41 +00:00
|
|
|
if (prlsdkAddVNCInfo(sdkdom, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* depends on prlsdkAddVNCInfo */
|
2019-12-09 14:39:20 +00:00
|
|
|
if (prlsdkAddDomainHardware(driver, sdkdom, def, driver->xmlopt) < 0)
|
2014-12-01 15:38:48 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-03-22 13:56:38 +00:00
|
|
|
/* depends on prlsdkAddDomainHardware */
|
2016-12-29 09:58:34 +00:00
|
|
|
if (!IS_CT(def) && prlsdkConvertBootOrderVm(sdkdom, def) < 0)
|
|
|
|
goto error;
|
2016-03-22 13:56:38 +00:00
|
|
|
|
2014-12-01 15:38:48 +00:00
|
|
|
pret = PrlVmCfg_GetEnvId(sdkdom, &envId);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2015-05-21 13:49:34 +00:00
|
|
|
pret = PrlVmCfg_GetAutoStart(sdkdom, &autostart);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
2016-02-10 09:39:14 +00:00
|
|
|
if (autostart != PAO_VM_START_ON_LOAD &&
|
|
|
|
autostart != PAO_VM_START_MANUAL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown autostart mode: %X"), autostart);
|
|
|
|
goto error;
|
|
|
|
}
|
2015-05-21 13:49:34 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkGetDomainState(dom, sdkdom, &domainState) < 0)
|
2015-05-21 13:49:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2019-09-23 10:44:35 +00:00
|
|
|
if (!IS_CT(def) && virDomainDefAddImplicitDevices(def, driver->xmlopt) < 0)
|
2015-04-07 20:35:04 +00:00
|
|
|
goto error;
|
|
|
|
|
2015-04-07 20:35:10 +00:00
|
|
|
if (def->ngraphics > 0) {
|
2015-06-25 07:56:56 +00:00
|
|
|
int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS :
|
|
|
|
VIR_DOMAIN_INPUT_BUS_PS2;
|
2015-04-07 20:35:10 +00:00
|
|
|
|
|
|
|
if (virDomainDefMaybeAddInput(def,
|
|
|
|
VIR_DOMAIN_INPUT_TYPE_MOUSE,
|
|
|
|
bus) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virDomainDefMaybeAddInput(def,
|
|
|
|
VIR_DOMAIN_INPUT_TYPE_KBD,
|
|
|
|
bus) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
if (!dom) {
|
|
|
|
virDomainObjPtr olddom = NULL;
|
|
|
|
|
2016-06-03 07:11:44 +00:00
|
|
|
job = PrlVm_SubscribeToPerfStats(sdkdom, NULL);
|
|
|
|
if (PRL_FAILED(waitJob(job)))
|
|
|
|
goto error;
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
virObjectLock(driver);
|
2018-03-09 15:47:46 +00:00
|
|
|
if (!(olddom = virDomainObjListFindByUUID(driver->domains, def->uuid)))
|
2016-06-14 08:45:57 +00:00
|
|
|
dom = virDomainObjListAdd(driver->domains, def, driver->xmlopt, 0, NULL);
|
|
|
|
virObjectUnlock(driver);
|
|
|
|
|
|
|
|
if (olddom) {
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return olddom;
|
|
|
|
} else if (!dom) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdom = dom->privateData;
|
2016-06-03 07:11:44 +00:00
|
|
|
pdom->sdkdom = sdkdom;
|
2016-06-14 08:45:57 +00:00
|
|
|
PrlHandle_AddRef(sdkdom);
|
|
|
|
dom->persistent = 1;
|
|
|
|
} else {
|
|
|
|
/* assign new virDomainDef without any checks
|
|
|
|
* we can't use virDomainObjAssignDef, because it checks
|
|
|
|
* for state and domain name */
|
|
|
|
virDomainDefFree(dom->def);
|
|
|
|
dom->def = def;
|
2016-06-03 07:11:44 +00:00
|
|
|
}
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
pdom = dom->privateData;
|
2016-02-10 09:39:14 +00:00
|
|
|
pdom->id = envId;
|
|
|
|
|
2016-03-11 08:36:17 +00:00
|
|
|
prlsdkConvertDomainState(domainState, envId, dom);
|
|
|
|
|
2016-02-10 09:39:14 +00:00
|
|
|
if (autostart == PAO_VM_START_ON_LOAD)
|
|
|
|
dom->autostart = 1;
|
|
|
|
else
|
|
|
|
dom->autostart = 0;
|
2015-05-21 13:49:35 +00:00
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
return dom;
|
|
|
|
|
2016-02-10 09:39:14 +00:00
|
|
|
error:
|
|
|
|
virDomainDefFree(def);
|
2016-06-14 08:45:57 +00:00
|
|
|
return NULL;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkLoadDomains(vzDriverPtr driver)
|
2014-12-01 15:38:48 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE result;
|
2016-02-10 09:39:14 +00:00
|
|
|
PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
|
2014-12-01 15:38:48 +00:00
|
|
|
PRL_UINT32 paramsCount;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
size_t i = 0;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_GetVmListEx(driver->server, PVTF_VM | PVTF_CT);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(getJobResult(job, &result)))
|
2014-12-01 15:38:48 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
pret = PrlResult_GetParamsCount(result, ¶msCount);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
for (i = 0; i < paramsCount; i++) {
|
|
|
|
pret = PrlResult_GetParamByIndex(result, i, &sdkdom);
|
2016-02-10 09:39:14 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
dom = prlsdkLoadDomain(driver, sdkdom, NULL);
|
|
|
|
virDomainObjEndAPI(&dom);
|
2014-12-01 15:38:48 +00:00
|
|
|
|
|
|
|
PrlHandle_Free(sdkdom);
|
2016-02-10 09:39:14 +00:00
|
|
|
sdkdom = PRL_INVALID_HANDLE;
|
2014-12-01 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2016-02-10 09:39:14 +00:00
|
|
|
PrlHandle_Free(sdkdom);
|
2014-12-01 15:38:48 +00:00
|
|
|
PrlHandle_Free(result);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
virDomainObjPtr
|
|
|
|
prlsdkAddDomainByUUID(vzDriverPtr driver, const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
PRL_HANDLE sdkdom;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
|
|
|
sdkdom = prlsdkSdkDomainLookupByUUID(driver, uuid);
|
|
|
|
if (sdkdom == PRL_INVALID_HANDLE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
dom = prlsdkLoadDomain(driver, sdkdom, NULL);
|
|
|
|
|
|
|
|
PrlHandle_Free(sdkdom);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainObjPtr
|
|
|
|
prlsdkAddDomainByName(vzDriverPtr driver, const char *name)
|
|
|
|
{
|
|
|
|
PRL_HANDLE sdkdom;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
|
|
|
sdkdom = prlsdkSdkDomainLookupByName(driver, name);
|
|
|
|
if (sdkdom == PRL_INVALID_HANDLE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
dom = prlsdkLoadDomain(driver, sdkdom, NULL);
|
|
|
|
|
|
|
|
PrlHandle_Free(sdkdom);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:54 +00:00
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkUpdateDomain(vzDriverPtr driver, virDomainObjPtr dom)
|
2014-12-01 15:38:50 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job;
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr pdom = dom->privateData;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
|
|
|
job = PrlVm_RefreshConfig(pdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (waitDomainJob(job, dom))
|
2014-12-01 15:38:50 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-06-14 08:45:57 +00:00
|
|
|
return prlsdkLoadDomain(driver, pdom->sdkdom, dom) ? 0 : -1;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-14 08:46:00 +00:00
|
|
|
static void
|
|
|
|
prlsdkSendEvent(vzDriverPtr driver,
|
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainEventType lvEventType,
|
|
|
|
int lvEventTypeDetails)
|
2014-12-01 15:38:50 +00:00
|
|
|
{
|
2016-06-14 08:46:00 +00:00
|
|
|
virObjectEventPtr event;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
|
|
|
event = virDomainEventLifecycleNewFromObj(dom,
|
|
|
|
lvEventType,
|
|
|
|
lvEventTypeDetails);
|
2018-06-11 19:38:17 +00:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
prlsdkNewStateToEvent(VIRTUAL_MACHINE_STATE domainState,
|
|
|
|
virDomainEventType *lvEventType,
|
|
|
|
int *lvEventTypeDetails)
|
|
|
|
{
|
|
|
|
/* We skip all intermediate states here, because
|
2020-07-09 04:42:21 +00:00
|
|
|
* libvirt doesn't have corresponding event types for
|
2014-12-01 15:38:50 +00:00
|
|
|
* them */
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)domainState) {
|
2014-12-01 15:38:50 +00:00
|
|
|
case VMS_STOPPED:
|
|
|
|
case VMS_MOUNTED:
|
|
|
|
*lvEventType = VIR_DOMAIN_EVENT_STOPPED;
|
|
|
|
*lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
|
|
|
|
break;
|
|
|
|
case VMS_RUNNING:
|
|
|
|
*lvEventType = VIR_DOMAIN_EVENT_STARTED;
|
|
|
|
*lvEventTypeDetails = VIR_DOMAIN_EVENT_STARTED_BOOTED;
|
|
|
|
break;
|
|
|
|
case VMS_PAUSED:
|
|
|
|
*lvEventType = VIR_DOMAIN_EVENT_SUSPENDED;
|
|
|
|
*lvEventTypeDetails = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
|
|
|
|
break;
|
|
|
|
case VMS_SUSPENDED:
|
|
|
|
*lvEventType = VIR_DOMAIN_EVENT_STOPPED;
|
|
|
|
*lvEventTypeDetails = VIR_DOMAIN_EVENT_STOPPED_SAVED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIR_DEBUG("Skip sending event about changing state to %X",
|
|
|
|
domainState);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-05 13:47:58 +00:00
|
|
|
static void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmStateEvent(vzDriverPtr driver,
|
2014-12-01 15:38:50 +00:00
|
|
|
PRL_HANDLE prlEvent,
|
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret = PRL_ERR_FAILURE;
|
|
|
|
PRL_HANDLE eventParam = PRL_INVALID_HANDLE;
|
|
|
|
PRL_INT32 domainState;
|
|
|
|
virDomainObjPtr dom = NULL;
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr pdom;
|
2014-12-01 15:38:50 +00:00
|
|
|
virDomainEventType lvEventType = 0;
|
|
|
|
int lvEventTypeDetails = 0;
|
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
dom = virDomainObjListFindByUUID(driver->domains, uuid);
|
2015-06-05 13:47:58 +00:00
|
|
|
if (dom == NULL)
|
|
|
|
return;
|
|
|
|
|
2014-12-01 15:38:50 +00:00
|
|
|
pret = PrlEvent_GetParamByName(prlEvent, "vminfo_vm_state", &eventParam);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlEvtPrm_ToInt32(eventParam, &domainState);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pdom = dom->privateData;
|
2016-03-11 08:36:17 +00:00
|
|
|
|
|
|
|
prlsdkConvertDomainState(domainState, pdom->id, dom);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
|
|
|
prlsdkNewStateToEvent(domainState,
|
|
|
|
&lvEventType,
|
|
|
|
&lvEventTypeDetails);
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSendEvent(driver, dom, lvEventType, lvEventTypeDetails);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
|
|
|
cleanup:
|
2017-02-08 14:09:57 +00:00
|
|
|
PrlHandle_Free(eventParam);
|
2018-03-09 15:30:47 +00:00
|
|
|
virDomainObjEndAPI(&dom);
|
2015-06-05 13:47:58 +00:00
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 13:47:58 +00:00
|
|
|
static void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmConfigEvent(vzDriverPtr driver,
|
2014-12-01 15:38:50 +00:00
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
bool job = false;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
dom = virDomainObjListFindByUUID(driver->domains, uuid);
|
2015-06-05 13:47:58 +00:00
|
|
|
if (dom == NULL)
|
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (vzDomainObjBeginJob(dom) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
job = true;
|
|
|
|
|
2016-07-20 15:00:34 +00:00
|
|
|
if (dom->removing)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (prlsdkUpdateDomain(driver, dom) < 0)
|
2014-12-01 15:38:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_DEFINED,
|
2015-06-25 07:56:56 +00:00
|
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
|
|
|
cleanup:
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (job)
|
|
|
|
vzDomainObjEndJob(dom);
|
|
|
|
virDomainObjEndAPI(&dom);
|
2015-06-05 13:47:58 +00:00
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 13:47:58 +00:00
|
|
|
static void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmAddedEvent(vzDriverPtr driver,
|
2015-06-25 07:56:56 +00:00
|
|
|
unsigned char *uuid)
|
2014-12-01 15:38:50 +00:00
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid)) &&
|
2016-06-14 08:45:57 +00:00
|
|
|
!(dom = prlsdkAddDomainByUUID(driver, uuid)))
|
|
|
|
goto cleanup;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_DEFINED,
|
2015-06-25 07:56:56 +00:00
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2016-02-10 09:39:14 +00:00
|
|
|
cleanup:
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
virDomainObjEndAPI(&dom);
|
2015-06-05 13:47:58 +00:00
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 13:47:58 +00:00
|
|
|
static void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmRemovedEvent(vzDriverPtr driver,
|
2014-12-01 15:38:50 +00:00
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
dom = virDomainObjListFindByUUID(driver->domains, uuid);
|
2015-06-05 13:47:58 +00:00
|
|
|
/* domain was removed from the list from the libvirt
|
|
|
|
* API function in current connection */
|
|
|
|
if (dom == NULL)
|
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_UNDEFINED,
|
2015-06-25 07:56:56 +00:00
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
virDomainObjListRemove(driver->domains, dom);
|
2018-03-09 15:30:47 +00:00
|
|
|
virDomainObjEndAPI(&dom);
|
2015-06-05 13:47:58 +00:00
|
|
|
return;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-03 07:11:44 +00:00
|
|
|
static void
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandlePerfEvent(vzDriverPtr driver,
|
2015-06-25 07:56:56 +00:00
|
|
|
PRL_HANDLE event,
|
|
|
|
unsigned char *uuid)
|
2015-06-09 07:35:53 +00:00
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr privdom = NULL;
|
2015-06-09 07:35:53 +00:00
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid))) {
|
2017-02-08 14:14:12 +00:00
|
|
|
PrlHandle_Free(event);
|
2016-06-03 07:11:44 +00:00
|
|
|
return;
|
2017-02-08 14:14:12 +00:00
|
|
|
}
|
2015-06-09 07:35:53 +00:00
|
|
|
|
2016-06-03 07:11:44 +00:00
|
|
|
privdom = dom->privateData;
|
|
|
|
PrlHandle_Free(privdom->stats);
|
|
|
|
privdom->stats = event;
|
2015-06-09 07:35:53 +00:00
|
|
|
|
2018-03-09 15:30:47 +00:00
|
|
|
virDomainObjEndAPI(&dom);
|
2015-06-09 07:35:53 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 10:08:14 +00:00
|
|
|
static void
|
|
|
|
prlsdkHandleMigrationProgress(vzDriverPtr driver,
|
|
|
|
PRL_HANDLE event,
|
|
|
|
unsigned char *uuid)
|
|
|
|
{
|
|
|
|
virDomainObjPtr dom = NULL;
|
|
|
|
vzDomObjPtr privdom = NULL;
|
|
|
|
PRL_UINT32 progress;
|
|
|
|
PRL_HANDLE param = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
2018-03-09 15:47:46 +00:00
|
|
|
if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid)))
|
2016-06-20 10:08:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
pret = PrlEvent_GetParam(event, 0, ¶m);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlEvtPrm_ToUint32(param, &progress);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
privdom = dom->privateData;
|
|
|
|
privdom->job.progress = progress;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(param);
|
2018-03-09 15:30:47 +00:00
|
|
|
virDomainObjEndAPI(&dom);
|
2016-06-20 10:08:14 +00:00
|
|
|
}
|
|
|
|
|
2015-06-25 08:56:00 +00:00
|
|
|
static PRL_RESULT
|
|
|
|
prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
|
2014-12-01 15:38:50 +00:00
|
|
|
{
|
2016-03-28 19:11:30 +00:00
|
|
|
vzDriverPtr driver = opaque;
|
2015-06-05 13:47:58 +00:00
|
|
|
PRL_RESULT pret = PRL_ERR_FAILURE;
|
2015-06-25 08:56:00 +00:00
|
|
|
PRL_HANDLE_TYPE handleType;
|
2016-05-18 08:11:08 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
|
2014-12-01 15:38:50 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
PRL_EVENT_TYPE prlEventType;
|
|
|
|
|
2015-06-25 08:56:00 +00:00
|
|
|
pret = PrlHandle_GetType(prlEvent, &handleType);
|
2015-06-09 07:35:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2015-06-25 08:56:00 +00:00
|
|
|
/* Currently, there is no need to handle anything but events */
|
|
|
|
if (handleType != PHT_EVENT)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
if (driver == NULL)
|
2015-06-25 08:56:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
pret = prlsdkGetStringParamBuf(PrlEvent_GetIssuerId,
|
|
|
|
prlEvent, uuidstr, sizeof(uuidstr));
|
2015-06-09 07:35:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2015-06-25 08:56:00 +00:00
|
|
|
pret = PrlEvent_GetType(prlEvent, &prlEventType);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2015-09-21 11:08:41 +00:00
|
|
|
if (prlsdkUUIDParse(uuidstr, uuid) < 0) {
|
|
|
|
VIR_DEBUG("Skipping event type %d", prlEventType);
|
2015-06-09 07:35:53 +00:00
|
|
|
goto cleanup;
|
2015-09-21 11:08:41 +00:00
|
|
|
}
|
2014-12-01 15:38:50 +00:00
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)prlEventType) {
|
2015-06-25 07:56:56 +00:00
|
|
|
case PET_DSP_EVT_VM_STATE_CHANGED:
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmStateEvent(driver, prlEvent, uuid);
|
2015-06-25 07:56:56 +00:00
|
|
|
break;
|
|
|
|
case PET_DSP_EVT_VM_CONFIG_CHANGED:
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmConfigEvent(driver, uuid);
|
2015-06-25 07:56:56 +00:00
|
|
|
break;
|
|
|
|
case PET_DSP_EVT_VM_CREATED:
|
|
|
|
case PET_DSP_EVT_VM_ADDED:
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmAddedEvent(driver, uuid);
|
2015-06-25 07:56:56 +00:00
|
|
|
break;
|
|
|
|
case PET_DSP_EVT_VM_DELETED:
|
|
|
|
case PET_DSP_EVT_VM_UNREGISTERED:
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandleVmRemovedEvent(driver, uuid);
|
2015-06-25 07:56:56 +00:00
|
|
|
break;
|
|
|
|
case PET_DSP_EVT_VM_PERFSTATS:
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkHandlePerfEvent(driver, prlEvent, uuid);
|
2015-06-25 07:56:56 +00:00
|
|
|
/* above function takes own of event */
|
|
|
|
prlEvent = PRL_INVALID_HANDLE;
|
|
|
|
break;
|
2016-02-17 12:15:03 +00:00
|
|
|
case PET_DSP_EVT_DISP_CONNECTION_CLOSED:
|
2016-03-28 19:11:30 +00:00
|
|
|
vzDestroyDriverConnection();
|
2016-02-17 12:15:03 +00:00
|
|
|
break;
|
2016-06-20 10:08:14 +00:00
|
|
|
case PET_DSP_EVT_VM_MIGRATE_PROGRESS_CHANGED:
|
|
|
|
prlsdkHandleMigrationProgress(driver, prlEvent, uuid);
|
|
|
|
break;
|
2015-06-25 07:56:56 +00:00
|
|
|
default:
|
2015-06-25 08:56:00 +00:00
|
|
|
VIR_DEBUG("Skipping event of type %d", prlEventType);
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(prlEvent);
|
2015-06-05 13:47:58 +00:00
|
|
|
return PRL_ERR_SUCCESS;
|
2014-12-01 15:38:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkStart(virDomainObjPtr dom)
|
2014-12-01 15:38:51 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-06-24 14:32:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_StartEx(privdom->sdkdom, PSM_VM_START, 0);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkKill(virDomainObjPtr dom)
|
2014-12-01 15:38:51 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-06-24 14:32:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
job = PrlVm_StopEx(privdom->sdkdom, PSM_KILL, 0);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkStop(virDomainObjPtr dom)
|
2014-12-01 15:38:51 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-06-24 14:32:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
job = PrlVm_StopEx(privdom->sdkdom, PSM_SHUTDOWN, 0);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkPause(virDomainObjPtr dom)
|
2015-04-07 20:35:02 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-06-24 14:32:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_Pause(privdom->sdkdom, false);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-04-07 20:35:02 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2015-04-07 20:35:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkResume(virDomainObjPtr dom)
|
2015-11-19 12:16:48 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-06-24 14:32:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_Resume(privdom->sdkdom);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-11-19 12:16:48 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2015-11-19 12:16:48 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkSuspend(virDomainObjPtr dom)
|
2014-12-01 15:38:51 +00:00
|
|
|
{
|
2016-06-24 14:32:30 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2014-12-01 15:39:01 +00:00
|
|
|
PRL_RESULT pret;
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
job = PrlVm_Suspend(privdom->sdkdom);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
2015-04-07 20:35:01 +00:00
|
|
|
return -1;
|
2014-12-01 15:39:01 +00:00
|
|
|
}
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
2015-04-07 20:35:01 +00:00
|
|
|
}
|
2014-12-01 15:38:51 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
int prlsdkRestart(virDomainObjPtr dom)
|
2015-04-07 20:35:01 +00:00
|
|
|
{
|
2016-06-24 14:32:30 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
2015-04-07 20:35:01 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
job = PrlVm_Restart(privdom->sdkdom);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
2015-04-07 20:35:01 +00:00
|
|
|
return -1;
|
2016-06-24 14:32:30 +00:00
|
|
|
}
|
2015-04-07 20:35:01 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
|
2017-01-31 07:44:13 +00:00
|
|
|
int prlsdkReset(virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_Reset(privdom->sdkdom);
|
|
|
|
if (PRL_FAILED(pret = waitDomainJob(job, dom))) {
|
|
|
|
prlsdkConvertError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
static void
|
|
|
|
prlsdkConvertError(PRL_RESULT pret)
|
|
|
|
{
|
|
|
|
virErrorNumber virerr;
|
2016-07-20 15:00:34 +00:00
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
switch (pret) {
|
|
|
|
case PRL_ERR_DISP_VM_IS_NOT_STARTED:
|
|
|
|
case PRL_ERR_DISP_VM_IS_NOT_STOPPED:
|
|
|
|
case PRL_ERR_INVALID_ACTION_REQUESTED:
|
|
|
|
case PRL_ERR_UNIMPLEMENTED:
|
|
|
|
virerr = VIR_ERR_OPERATION_INVALID;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virerr = VIR_ERR_OPERATION_FAILED;
|
2016-07-20 15:00:34 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:32:30 +00:00
|
|
|
virResetLastError();
|
|
|
|
virReportError(virerr, "%s", _("Can't change domain state."));
|
2014-12-01 15:38:51 +00:00
|
|
|
}
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
PRL_VM_TYPE vmType;
|
|
|
|
PRL_RESULT pret;
|
2015-05-19 09:55:26 +00:00
|
|
|
virDomainNumatuneMemMode memMode;
|
2016-04-20 08:58:21 +00:00
|
|
|
int bus = IS_CT(def) ? VIR_DOMAIN_INPUT_BUS_PARALLELS :
|
|
|
|
VIR_DOMAIN_INPUT_BUS_PS2;
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
if (def->title) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("titles are not supported by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->blkio.ndevices > 0) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("blkio parameters are not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-15 13:34:04 +00:00
|
|
|
if (virDomainDefGetMemoryTotal(def) != def->mem.cur_balloon) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-25 07:56:56 +00:00
|
|
|
_("changing balloon parameters is not supported "
|
|
|
|
"by vz driver"));
|
|
|
|
return -1;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
2016-06-15 13:34:04 +00:00
|
|
|
if (virDomainDefGetMemoryTotal(def) % (1 << 10) != 0) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-25 07:56:56 +00:00
|
|
|
_("Memory size should be multiple of 1Mb."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->mem.nhugepages ||
|
2015-03-12 15:43:29 +00:00
|
|
|
virMemoryLimitIsSet(def->mem.hard_limit) ||
|
|
|
|
virMemoryLimitIsSet(def->mem.soft_limit) ||
|
2014-12-01 15:38:52 +00:00
|
|
|
def->mem.min_guarantee ||
|
2015-03-12 15:43:29 +00:00
|
|
|
virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Memory parameter is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-10-19 16:23:23 +00:00
|
|
|
if (virDomainDefHasVcpusOffline(def)) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-25 07:56:56 +00:00
|
|
|
_("current vcpus must be equal to maxvcpus"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->placement_mode) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing cpu placement mode is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->cputune.shares ||
|
|
|
|
def->cputune.sharesSpecified ||
|
|
|
|
def->cputune.period ||
|
2015-03-10 20:12:22 +00:00
|
|
|
def->cputune.quota) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("cputune is not supported by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-01-29 09:20:44 +00:00
|
|
|
for (i = 0; i < virDomainDefGetVcpusMax(def); i++) {
|
2016-06-29 11:16:22 +00:00
|
|
|
virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(def, i);
|
2016-01-29 09:20:44 +00:00
|
|
|
|
|
|
|
if (vcpu->cpumask &&
|
|
|
|
!virBitmapEqual(def->cpumask, vcpu->cpumask)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("vcpupin cpumask differs from default cpumask"));
|
|
|
|
return -1;
|
2015-03-10 20:12:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 20:12:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Though we don't support NUMA configuration at the moment
|
|
|
|
* virDomainDefPtr always contain non zero NUMA configuration
|
2020-07-09 04:42:21 +00:00
|
|
|
* So, just make sure this configuration doesn't differ from auto generated.
|
2015-03-10 20:12:21 +00:00
|
|
|
*/
|
2015-05-19 09:55:26 +00:00
|
|
|
if ((virDomainNumatuneGetMode(def->numa, -1, &memMode) == 0 &&
|
|
|
|
memMode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) ||
|
2015-06-25 07:56:56 +00:00
|
|
|
virDomainNumatuneHasPerNodeBinding(def->numa)) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-25 07:56:56 +00:00
|
|
|
_("numa parameters are not supported "
|
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-10-10 12:32:11 +00:00
|
|
|
if (def->onReboot != VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
|
|
|
|
def->onPoweroff != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
|
2017-10-10 12:51:38 +00:00
|
|
|
def->onCrash != VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("on_reboot, on_poweroff and on_crash parameters "
|
2015-06-10 07:50:00 +00:00
|
|
|
"are not supported by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-06-10 07:50:00 +00:00
|
|
|
/* we fill only type and arch fields in vzLoadDomain for
|
2014-12-01 15:38:52 +00:00
|
|
|
* hvm type and also init for containers, so we can check that all
|
2018-12-04 17:08:14 +00:00
|
|
|
* other parameters are null and boot devices config is default */
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
if (def->os.machine != NULL || def->os.bootmenu != 0 ||
|
|
|
|
def->os.kernel != NULL || def->os.initrd != NULL ||
|
|
|
|
def->os.cmdline != NULL || def->os.root != NULL ||
|
|
|
|
def->os.loader != NULL || def->os.bootloader != NULL ||
|
|
|
|
def->os.bootloaderArgs != NULL || def->os.smbios_mode != 0 ||
|
|
|
|
def->os.bios.useserial != 0) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing OS parameters is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetVmType(sdkdom, &vmType);
|
|
|
|
if (PRL_FAILED(pret)) {
|
|
|
|
logPrlError(pret);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-02-17 11:52:32 +00:00
|
|
|
if (!(vmType == PVT_VM && !IS_CT(def)) &&
|
|
|
|
!(vmType == PVT_CT && IS_CT(def))) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing OS type is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-02-17 11:52:32 +00:00
|
|
|
if (!IS_CT(def)) {
|
2016-03-22 13:56:36 +00:00
|
|
|
if (def->os.init != NULL || def->os.initargv != NULL) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2016-03-22 13:56:36 +00:00
|
|
|
_("unsupported OS parameters"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->os.nBootDevs != 0 ||
|
2015-10-20 16:15:12 +00:00
|
|
|
STRNEQ_NULLABLE(def->os.init, "/sbin/init") ||
|
2014-12-01 15:38:52 +00:00
|
|
|
(def->os.initargv != NULL && def->os.initargv[0] != NULL)) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2016-03-22 13:56:36 +00:00
|
|
|
_("unsupported OS parameters"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->emulator) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing emulator is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
|
|
|
|
if (def->features[i]) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing features is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC ||
|
|
|
|
def->clock.ntimers != 0) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing clock parameters is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-01-13 11:27:39 +00:00
|
|
|
if (!IS_CT(def) && def->nfss != 0) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Filesystems in VMs are not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->nsounds != 0 || def->nhostdevs != 0 ||
|
2014-12-01 15:38:52 +00:00
|
|
|
def->nredirdevs != 0 || def->nsmartcards != 0 ||
|
|
|
|
def->nparallels || def->nchannels != 0 ||
|
|
|
|
def->nleases != 0 || def->nhubs != 0) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("changing devices parameters is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-04-20 08:58:21 +00:00
|
|
|
/* check we have only default input devices */
|
|
|
|
if (def->ngraphics > 0) {
|
|
|
|
if (def->ninputs != 2 ||
|
|
|
|
def->inputs[0]->bus != bus ||
|
|
|
|
def->inputs[1]->bus != bus ||
|
|
|
|
!((def->inputs[0]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE &&
|
|
|
|
def->inputs[1]->type == VIR_DOMAIN_INPUT_TYPE_KBD) ||
|
|
|
|
(def->inputs[0]->type == VIR_DOMAIN_INPUT_TYPE_KBD &&
|
2016-06-15 07:43:29 +00:00
|
|
|
def->inputs[1]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE))) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
2016-04-20 08:58:21 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("unsupported input device configuration"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else if (def->ninputs != 0) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2016-04-20 08:58:21 +00:00
|
|
|
_("input devices without vnc are not supported"));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int prlsdkClearDevices(PRL_HANDLE sdkdom)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 n, i;
|
|
|
|
PRL_HANDLE devList;
|
|
|
|
PRL_HANDLE dev;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetAllDevices(sdkdom, &devList);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlHndlList_GetItemsCount(devList, &n);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
pret = PrlHndlList_GetItem(devList, i, &dev);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_Remove(dev);
|
|
|
|
PrlHandle_Free(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(devList);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-02-17 11:52:33 +00:00
|
|
|
static int
|
|
|
|
prlsdkRemoveBootDevices(PRL_HANDLE sdkdom)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 i, devCount;
|
|
|
|
PRL_HANDLE dev = PRL_INVALID_HANDLE;
|
|
|
|
PRL_DEVICE_TYPE devType;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetBootDevCount(sdkdom, &devCount);
|
2020-01-08 08:46:27 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-02-17 11:52:33 +00:00
|
|
|
|
|
|
|
for (i = 0; i < devCount; i++) {
|
|
|
|
|
|
|
|
/* always get device by index 0, because device list resort after delete */
|
|
|
|
pret = PrlVmCfg_GetBootDev(sdkdom, 0, &dev);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-02-17 11:52:33 +00:00
|
|
|
|
|
|
|
pret = PrlBootDev_GetType(dev, &devType);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-02-17 11:52:33 +00:00
|
|
|
|
|
|
|
pret = PrlBootDev_Remove(dev);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2015-02-17 11:52:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom,
|
|
|
|
PRL_UINT32 devIndex,
|
|
|
|
PRL_DEVICE_TYPE devType,
|
|
|
|
PRL_UINT32 bootSequence)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_CreateBootDev(sdkdom, &bootDev);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
pret = PrlBootDev_SetIndex(bootDev, devIndex);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
pret = PrlBootDev_SetType(bootDev, devType);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
pret = PrlBootDev_SetSequenceIndex(bootDev, bootSequence);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
pret = PrlBootDev_SetInUse(bootDev, PRL_TRUE);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (bootDev != PRL_INVALID_HANDLE)
|
|
|
|
PrlBootDev_Remove(bootDev);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
static int prlsdkCheckVideoUnsupportedParams(virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
virDomainVideoDefPtr v;
|
|
|
|
|
2015-02-17 11:52:32 +00:00
|
|
|
if (IS_CT(def)) {
|
2014-12-01 15:38:52 +00:00
|
|
|
if (def->nvideos == 0) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Video adapters are not supported "
|
|
|
|
"int containers."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->nvideos != 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("vz driver supports "
|
2014-12-01 15:38:52 +00:00
|
|
|
"only one video adapter."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v = def->videos[0];
|
|
|
|
|
|
|
|
if (v->type != VIR_DOMAIN_VIDEO_TYPE_VGA) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("vz driver supports "
|
2014-12-01 15:38:52 +00:00
|
|
|
"only VGA video adapters."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v->heads != 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("vz driver doesn't support "
|
2014-12-01 15:38:52 +00:00
|
|
|
"multihead video adapters."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-11-25 08:42:30 +00:00
|
|
|
if (v->accel != NULL && (v->accel->accel2d || v->accel->accel3d)) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("vz driver doesn't support "
|
2014-12-01 15:38:52 +00:00
|
|
|
"setting video acceleration parameters."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int prlsdkCheckSerialUnsupportedParams(virDomainChrDefPtr chr)
|
|
|
|
{
|
|
|
|
if (chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Specified character device type is not supported "
|
2015-06-10 07:50:00 +00:00
|
|
|
"by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-11-10 13:54:19 +00:00
|
|
|
if (chr->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Specified character device target type is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
if (chr->source->type != VIR_DOMAIN_CHR_TYPE_DEV &&
|
|
|
|
chr->source->type != VIR_DOMAIN_CHR_TYPE_FILE &&
|
|
|
|
chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX &&
|
|
|
|
chr->source->type != VIR_DOMAIN_CHR_TYPE_TCP &&
|
|
|
|
chr->source->type != VIR_DOMAIN_CHR_TYPE_UDP) {
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Specified character device source type is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting device info for character devices is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-06-29 10:17:36 +00:00
|
|
|
if (chr->source->nseclabels > 0) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting security labels is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
if (chr->source->type == VIR_DOMAIN_CHR_TYPE_TCP &&
|
|
|
|
chr->source->data.tcp.protocol != VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW) {
|
2016-05-31 09:38:33 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Protocol '%s' is not supported for "
|
|
|
|
"tcp character device."),
|
2016-10-21 11:45:54 +00:00
|
|
|
virDomainChrTcpProtocolTypeToString(chr->source->data.tcp.protocol));
|
2016-05-31 09:38:33 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
if (chr->source->type == VIR_DOMAIN_CHR_TYPE_UDP &&
|
|
|
|
(STRNEQ(chr->source->data.udp.bindHost,
|
|
|
|
chr->source->data.udp.connectHost) ||
|
|
|
|
STRNEQ(chr->source->data.udp.bindService,
|
|
|
|
chr->source->data.udp.connectService))) {
|
2016-05-31 09:38:33 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Different bind and connect parameters for "
|
|
|
|
"udp character device is not supported."));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int prlsdkCheckNetUnsupportedParams(virDomainNetDefPtr net)
|
|
|
|
{
|
2015-03-18 08:33:57 +00:00
|
|
|
if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
|
|
|
|
net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Specified network adapter type is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->backend.tap || net->backend.vhost) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Interface backend parameters are not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->data.network.portgroup) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Virtual network portgroups are not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->tune.sndbuf_specified) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting interface sndbuf is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->script) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting interface script is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (net->ifname_guest) {
|
2014-12-01 15:38:52 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting guest interface name is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting device info for network devices is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->filter) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting network filter is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->bandwidth) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting network bandwidth is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->vlan.trunk) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting up vlans is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-13 11:27:39 +00:00
|
|
|
static int prlsdkCheckFSUnsupportedParams(virDomainFSDefPtr fs)
|
|
|
|
{
|
2016-07-14 13:52:41 +00:00
|
|
|
if (fs->type != VIR_DOMAIN_FS_TYPE_FILE &&
|
|
|
|
fs->type != VIR_DOMAIN_FS_TYPE_VOLUME) {
|
2015-01-13 11:27:39 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2016-07-14 13:52:41 +00:00
|
|
|
_("Only file based or volume based filesystems "
|
|
|
|
"are supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Only ploop fs driver is "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Changing fs access mode is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Changing fs write policy is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->format != VIR_STORAGE_FILE_PLOOP) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Only ploop disk images are "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->readonly) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting readonly for filesystems is "
|
2016-04-08 07:41:34 +00:00
|
|
|
"not supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs->space_hard_limit || fs->space_soft_limit) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Setting fs quotas is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2015-01-13 11:27:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom,
|
|
|
|
virDomainGraphicsDefPtr gr)
|
2014-12-01 15:38:52 +00:00
|
|
|
{
|
2016-05-17 12:55:55 +00:00
|
|
|
virDomainGraphicsListenDefPtr glisten;
|
2014-12-01 15:38:52 +00:00
|
|
|
PRL_RESULT pret;
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
if (!gr) {
|
|
|
|
pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2016-06-29 17:23:18 +00:00
|
|
|
return 0;
|
2016-04-20 14:05:42 +00:00
|
|
|
}
|
2014-12-01 15:38:52 +00:00
|
|
|
|
2016-04-20 14:05:44 +00:00
|
|
|
pret = PrlVmCfg_SetVNCPassword(sdkdom, gr->data.vnc.auth.passwd ? : "");
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
if (gr->data.vnc.autoport) {
|
|
|
|
pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_AUTO);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:52 +00:00
|
|
|
} else {
|
|
|
|
pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_MANUAL);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_SetVNCPort(sdkdom, gr->data.vnc.port);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:45 +00:00
|
|
|
glisten = virDomainGraphicsGetListen(gr, 0);
|
|
|
|
pret = PrlVmCfg_SetVNCHostName(sdkdom, glisten && glisten->address ?
|
2017-05-19 21:31:48 +00:00
|
|
|
glisten->address : VIR_LOOPBACK_IPV4_ADDR);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-19 13:41:03 +00:00
|
|
|
|
2020-01-06 21:57:42 +00:00
|
|
|
return 0;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int prlsdkApplyVideoParams(PRL_HANDLE sdkdom G_GNUC_UNUSED, virDomainDefPtr def)
|
2014-12-01 15:38:52 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
if (def->nvideos == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (IS_CT(def)) {
|
|
|
|
/* ignore video parameters */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prlsdkCheckVideoUnsupportedParams(def))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_SetVideoRamSize(sdkdom, def->videos[0]->vram >> 10);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int prlsdkAddSerial(PRL_HANDLE sdkdom, virDomainChrDefPtr chr)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE sdkchr = PRL_INVALID_HANDLE;
|
|
|
|
PRL_VM_DEV_EMULATION_TYPE emutype;
|
2015-06-25 07:56:56 +00:00
|
|
|
PRL_SERIAL_PORT_SOCKET_OPERATION_MODE socket_mode = PSP_SERIAL_SOCKET_SERVER;
|
2014-12-01 15:38:52 +00:00
|
|
|
char *path;
|
2016-05-31 09:38:33 +00:00
|
|
|
char *url = NULL;
|
2014-12-01 15:38:52 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (prlsdkCheckSerialUnsupportedParams(chr) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_SERIAL_PORT, &sdkchr);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-10-21 11:45:54 +00:00
|
|
|
switch (chr->source->type) {
|
2014-12-01 15:38:52 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
emutype = PDT_USE_REAL_DEVICE;
|
2016-10-21 11:45:54 +00:00
|
|
|
path = chr->source->data.file.path;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
emutype = PDT_USE_OUTPUT_FILE;
|
2016-10-21 11:45:54 +00:00
|
|
|
path = chr->source->data.file.path;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
emutype = PDT_USE_SERIAL_PORT_SOCKET_MODE;
|
2016-10-21 11:45:54 +00:00
|
|
|
path = chr->source->data.nix.path;
|
|
|
|
if (!chr->source->data.nix.listen)
|
2016-05-31 09:38:33 +00:00
|
|
|
socket_mode = PSP_SERIAL_SOCKET_CLIENT;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_TCP:
|
|
|
|
emutype = PDT_USE_TCP;
|
2019-10-22 13:26:14 +00:00
|
|
|
url = g_strdup_printf("%s:%s", chr->source->data.tcp.host,
|
|
|
|
chr->source->data.tcp.service);
|
2016-10-21 11:45:54 +00:00
|
|
|
if (!chr->source->data.tcp.listen)
|
2014-12-01 15:38:52 +00:00
|
|
|
socket_mode = PSP_SERIAL_SOCKET_CLIENT;
|
2016-05-31 09:38:33 +00:00
|
|
|
path = url;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UDP:
|
|
|
|
emutype = PDT_USE_UDP;
|
2019-10-22 13:26:14 +00:00
|
|
|
url = g_strdup_printf("%s:%s", chr->source->data.udp.bindHost,
|
|
|
|
chr->source->data.udp.bindService);
|
2016-05-31 09:38:33 +00:00
|
|
|
path = url;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-10 07:50:00 +00:00
|
|
|
_("vz driver doesn't support "
|
2014-12-01 15:38:52 +00:00
|
|
|
"specified serial source type."));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetEmulatedType(sdkchr, emutype);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetSysName(sdkchr, path);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetFriendlyName(sdkchr, path);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-05-31 09:38:33 +00:00
|
|
|
pret = PrlVmDevSerial_SetSocketMode(sdkchr, socket_mode);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmDev_SetEnabled(sdkchr, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetIndex(sdkchr, chr->target.port);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(sdkchr);
|
2016-05-31 09:38:33 +00:00
|
|
|
VIR_FREE(url);
|
2014-12-01 15:38:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PRL_MAC_STRING_BUFNAME 13
|
|
|
|
|
|
|
|
static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
|
|
|
|
{
|
2019-11-13 13:53:42 +00:00
|
|
|
g_snprintf(macstr, PRL_MAC_STRING_BUFNAME,
|
|
|
|
"%02X%02X%02X%02X%02X%02X",
|
|
|
|
mac->addr[0], mac->addr[1], mac->addr[2],
|
|
|
|
mac->addr[3], mac->addr[4], mac->addr[5]);
|
2014-12-01 15:38:52 +00:00
|
|
|
macstr[PRL_MAC_STRING_BUFNAME - 1] = '\0';
|
|
|
|
return macstr;
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:38 +00:00
|
|
|
static int prlsdkConfigureGateways(PRL_HANDLE sdknet, virDomainNetDefPtr net)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
2016-06-27 18:23:11 +00:00
|
|
|
virNetDevIPRoutePtr route4 = NULL, route6 = NULL;
|
2016-04-20 14:05:38 +00:00
|
|
|
char *gw4 = NULL, *gw6 = NULL;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
for (i = 0; i < net->guestIP.nroutes; i++) {
|
2016-04-20 14:05:38 +00:00
|
|
|
virSocketAddrPtr addrdst, gateway;
|
|
|
|
virSocketAddr zero;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
addrdst = virNetDevIPRouteGetAddress(net->guestIP.routes[i]);
|
|
|
|
gateway = virNetDevIPRouteGetGateway(net->guestIP.routes[i]);
|
2016-04-20 14:05:38 +00:00
|
|
|
|
|
|
|
ignore_value(virSocketAddrParse(&zero,
|
|
|
|
(VIR_SOCKET_ADDR_IS_FAMILY(addrdst, AF_INET)
|
|
|
|
? VIR_SOCKET_ADDR_IPV4_ALL
|
|
|
|
: VIR_SOCKET_ADDR_IPV6_ALL),
|
|
|
|
VIR_SOCKET_ADDR_FAMILY(addrdst)));
|
2016-08-03 09:41:53 +00:00
|
|
|
/* virSocketAddrParse raises an error
|
2020-01-24 20:32:03 +00:00
|
|
|
* and we are not going to report it, reset it explicitly */
|
2016-08-03 09:41:53 +00:00
|
|
|
virResetLastError();
|
2016-04-20 14:05:38 +00:00
|
|
|
|
|
|
|
if (!virSocketAddrEqual(addrdst, &zero)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Support only default gateway"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (VIR_SOCKET_ADDR_FAMILY(gateway)) {
|
|
|
|
case AF_INET:
|
|
|
|
if (route4) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Support only one IPv4 default gateway"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
route4 = net->guestIP.routes[i];
|
2016-04-20 14:05:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (route6) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Support only one IPv6 default gateway"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
route6 = net->guestIP.routes[i];
|
2016-04-20 14:05:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unsupported address family %d "
|
|
|
|
"Only IPv4 or IPv6 default gateway"),
|
|
|
|
VIR_SOCKET_ADDR_FAMILY(gateway));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (route4 &&
|
2016-06-27 18:23:11 +00:00
|
|
|
!(gw4 = virSocketAddrFormat(virNetDevIPRouteGetGateway(route4))))
|
2016-04-20 14:05:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetDefaultGateway(sdknet, gw4 ? : "");
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (route6 &&
|
2016-06-27 18:23:11 +00:00
|
|
|
!(gw6 = virSocketAddrFormat(virNetDevIPRouteGetGateway(route6))))
|
2016-04-20 14:05:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetDefaultGatewayIPv6(sdknet, gw6 ? : "");
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(gw4);
|
|
|
|
VIR_FREE(gw6);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int prlsdkConfigureNet(vzDriverPtr driver G_GNUC_UNUSED,
|
|
|
|
virDomainObjPtr dom G_GNUC_UNUSED,
|
2016-04-20 14:05:31 +00:00
|
|
|
PRL_HANDLE sdkdom,
|
|
|
|
virDomainNetDefPtr net,
|
|
|
|
bool isCt, bool create)
|
2014-12-01 15:38:52 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
|
2015-07-07 13:38:00 +00:00
|
|
|
PRL_HANDLE addrlist = PRL_INVALID_HANDLE;
|
|
|
|
size_t i;
|
2014-12-01 15:38:52 +00:00
|
|
|
int ret = -1;
|
|
|
|
char macstr[PRL_MAC_STRING_BUFNAME];
|
2015-07-07 13:38:00 +00:00
|
|
|
char *addrstr = NULL;
|
|
|
|
bool ipv6present = false;
|
|
|
|
bool ipv4present = false;
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
if (prlsdkCheckNetUnsupportedParams(net) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
if (create) {
|
|
|
|
pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_GENERIC_NETWORK_ADAPTER, &sdknet);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
} else {
|
|
|
|
sdknet = prlsdkFindNetByMAC(sdkdom, &net->mac);
|
|
|
|
if (sdknet == PRL_INVALID_HANDLE)
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmDev_SetEnabled(sdknet, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2015-03-18 08:33:54 +00:00
|
|
|
pret = PrlVmDev_SetConnected(sdknet, net->linkstate !=
|
|
|
|
VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN);
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (net->ifname) {
|
|
|
|
pret = PrlVmDevNet_SetHostInterfaceName(sdknet, net->ifname);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
|
|
|
prlsdkFormatMac(&net->mac, macstr);
|
|
|
|
pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2015-07-07 13:38:00 +00:00
|
|
|
pret = PrlApi_CreateStringsList(&addrlist);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
for (i = 0; i < net->guestIP.nips; i++) {
|
2015-07-07 13:38:00 +00:00
|
|
|
char *tmpstr;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (AF_INET == VIR_SOCKET_ADDR_FAMILY(&net->guestIP.ips[i]->address))
|
2015-07-07 13:38:00 +00:00
|
|
|
ipv4present = true;
|
2016-06-27 18:23:11 +00:00
|
|
|
else if (AF_INET6 == VIR_SOCKET_ADDR_FAMILY(&net->guestIP.ips[i]->address))
|
2015-07-07 13:38:00 +00:00
|
|
|
ipv6present = true;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
|
2016-06-27 18:23:11 +00:00
|
|
|
if (!(tmpstr = virSocketAddrFormat(&net->guestIP.ips[i]->address)))
|
2015-07-07 13:38:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
addrstr = g_strdup_printf("%s/%d", tmpstr, net->guestIP.ips[i]->prefix);
|
2015-07-07 13:38:00 +00:00
|
|
|
|
|
|
|
VIR_FREE(tmpstr);
|
|
|
|
pret = PrlStrList_AddItem(addrlist, addrstr);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
VIR_FREE(addrstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ipv4present || ipv6present) {
|
|
|
|
pret = PrlVmDevNet_SetNetAddresses(sdknet, addrlist);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetConfigureWithDhcp(sdknet, !ipv4present);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetConfigureWithDhcpIPv6(sdknet, !ipv6present);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetAutoApply(sdknet, true);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-04-20 14:05:38 +00:00
|
|
|
if (prlsdkConfigureGateways(sdknet, net))
|
|
|
|
goto cleanup;
|
2015-07-07 13:38:00 +00:00
|
|
|
|
2015-04-23 17:35:00 +00:00
|
|
|
if (isCt) {
|
2019-01-18 00:53:14 +00:00
|
|
|
if (net->model != VIR_DOMAIN_NET_MODEL_UNKNOWN)
|
2015-06-25 07:56:56 +00:00
|
|
|
VIR_WARN("Setting network adapter for containers is not "
|
|
|
|
"supported by vz driver.");
|
2015-03-18 08:33:55 +00:00
|
|
|
} else {
|
2019-01-18 00:53:14 +00:00
|
|
|
if (net->model == VIR_DOMAIN_NET_MODEL_RTL8139) {
|
2015-04-23 17:35:00 +00:00
|
|
|
pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_RTL);
|
2019-01-18 00:53:14 +00:00
|
|
|
} else if (net->model == VIR_DOMAIN_NET_MODEL_E1000) {
|
2015-04-23 17:35:00 +00:00
|
|
|
pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000);
|
2019-01-18 00:53:14 +00:00
|
|
|
} else if (net->model == VIR_DOMAIN_NET_MODEL_VIRTIO) {
|
2015-04-23 17:35:00 +00:00
|
|
|
pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_VIRTIO);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2015-06-25 07:56:56 +00:00
|
|
|
_("Specified network adapter model is not "
|
|
|
|
"supported by vz driver."));
|
2015-04-23 17:35:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2015-03-18 08:33:55 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 08:33:53 +00:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) {
|
|
|
|
pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2016-09-05 16:39:31 +00:00
|
|
|
} else {
|
|
|
|
pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_NETWORK);
|
2015-03-18 08:33:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
2016-09-05 16:39:31 +00:00
|
|
|
} else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
2015-03-18 08:33:53 +00:00
|
|
|
|
2016-09-05 16:39:31 +00:00
|
|
|
pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGE);
|
2015-03-18 08:33:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-04-20 14:05:39 +00:00
|
|
|
pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.bridge.brname);
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:40 +00:00
|
|
|
pret = PrlVmDevNet_SetPktFilterPreventMacSpoof(sdknet,
|
|
|
|
net->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES);
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2015-07-07 13:38:00 +00:00
|
|
|
VIR_FREE(addrstr);
|
|
|
|
PrlHandle_Free(addrlist);
|
2014-12-01 15:38:52 +00:00
|
|
|
PrlHandle_Free(sdknet);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-26 11:24:00 +00:00
|
|
|
static PRL_HANDLE
|
|
|
|
prlsdkFindNetByMAC(PRL_HANDLE sdkdom, virMacAddrPtr mac)
|
2015-06-22 16:57:00 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 adaptersCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
PRL_HANDLE adapter = PRL_INVALID_HANDLE;
|
|
|
|
char adapterMac[PRL_MAC_STRING_BUFNAME];
|
|
|
|
char expectedMac[PRL_MAC_STRING_BUFNAME];
|
2016-04-20 14:05:35 +00:00
|
|
|
char virMac[VIR_MAC_STRING_BUFLEN];
|
2015-06-22 16:57:00 +00:00
|
|
|
|
2015-06-26 11:24:00 +00:00
|
|
|
prlsdkFormatMac(mac, expectedMac);
|
|
|
|
|
2015-06-22 16:57:00 +00:00
|
|
|
pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &adaptersCount);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
for (i = 0; i < adaptersCount; ++i) {
|
|
|
|
pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &adapter);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
pret = prlsdkGetStringParamBuf(PrlVmDevNet_GetMacAddress,
|
|
|
|
adapter, adapterMac, sizeof(adapterMac));
|
2015-06-22 16:57:00 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (STREQ(adapterMac, expectedMac))
|
2015-06-26 11:24:00 +00:00
|
|
|
return adapter;
|
2015-06-22 16:57:00 +00:00
|
|
|
|
2015-06-26 11:24:00 +00:00
|
|
|
PrlHandle_Free(adapter);
|
|
|
|
adapter = PRL_INVALID_HANDLE;
|
2015-06-22 16:57:00 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:35 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No net with mac '%s'"), virMacAddrFormat(mac, virMac));
|
|
|
|
|
2015-06-22 16:57:00 +00:00
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(adapter);
|
2015-06-26 11:24:00 +00:00
|
|
|
return adapter;
|
2015-06-22 16:57:00 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
static int prlsdkConfigureDisk(vzDriverPtr driver,
|
|
|
|
PRL_HANDLE sdkdom,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
bool create)
|
2014-12-01 15:38:52 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
|
|
|
|
int ret = -1;
|
|
|
|
PRL_VM_DEV_EMULATION_TYPE emutype;
|
|
|
|
PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus;
|
2014-12-15 12:47:25 +00:00
|
|
|
int idx;
|
|
|
|
virDomainDeviceDriveAddressPtr drive;
|
2015-02-17 11:52:33 +00:00
|
|
|
PRL_DEVICE_TYPE devType;
|
2016-03-15 07:47:51 +00:00
|
|
|
PRL_CLUSTERED_DEVICE_SUBTYPE scsiModel;
|
2016-04-14 15:00:09 +00:00
|
|
|
const char *path = disk->src->path ? : "";
|
2014-12-01 15:38:52 +00:00
|
|
|
|
2014-12-01 15:38:57 +00:00
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
|
2015-02-17 11:52:33 +00:00
|
|
|
devType = PDE_HARD_DISK;
|
2014-12-01 15:38:57 +00:00
|
|
|
else
|
2015-02-17 11:52:33 +00:00
|
|
|
devType = PDE_OPTICAL_DISK;
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
if (create) {
|
|
|
|
pret = PrlVmCfg_CreateVmDev(sdkdom, devType, &sdkdisk);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
} else {
|
2016-08-15 16:02:49 +00:00
|
|
|
sdkdisk = prlsdkGetDisk(sdkdom, disk);
|
2016-04-20 14:05:31 +00:00
|
|
|
if (sdkdisk == PRL_INVALID_HANDLE)
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmDev_SetEnabled(sdkdisk, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetConnected(sdkdisk, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-03-15 07:47:48 +00:00
|
|
|
if (disk->src->type == VIR_STORAGE_TYPE_FILE)
|
2014-12-01 15:38:52 +00:00
|
|
|
emutype = PDT_USE_IMAGE_FILE;
|
2016-03-15 07:47:48 +00:00
|
|
|
else
|
2014-12-01 15:38:52 +00:00
|
|
|
emutype = PDT_USE_REAL_DEVICE;
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-05-17 12:11:35 +00:00
|
|
|
pret = PrlVmDev_SetSysName(sdkdisk, path);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
2016-05-17 12:11:35 +00:00
|
|
|
pret = PrlVmDev_SetFriendlyName(sdkdisk, path);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
2014-12-15 12:47:25 +00:00
|
|
|
drive = &disk->info.addr.drive;
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
switch (disk->bus) {
|
|
|
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
|
|
|
sdkbus = PMS_IDE_DEVICE;
|
2014-12-15 12:47:25 +00:00
|
|
|
idx = 2 * drive->bus + drive->unit;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
|
|
|
sdkbus = PMS_SCSI_DEVICE;
|
2014-12-15 12:47:25 +00:00
|
|
|
idx = drive->unit;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
|
|
sdkbus = PMS_SATA_DEVICE;
|
2014-12-15 12:47:25 +00:00
|
|
|
idx = drive->unit;
|
2014-12-01 15:38:52 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Specified disk bus is not "
|
2015-06-10 07:50:00 +00:00
|
|
|
"supported by vz driver."));
|
2014-12-01 15:38:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-03-15 07:47:51 +00:00
|
|
|
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
|
2016-03-28 19:11:30 +00:00
|
|
|
if (vzGetDefaultSCSIModel(driver, &scsiModel) < 0)
|
2016-03-15 07:47:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
pret = PrlVmDev_SetSubType(sdkdisk, scsiModel);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
pret = PrlVmDev_SetIfaceType(sdkdisk, sdkbus);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2014-12-15 12:47:25 +00:00
|
|
|
pret = PrlVmDev_SetStackIndex(sdkdisk, idx);
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-09-22 14:55:41 +00:00
|
|
|
if (devType == PDE_HARD_DISK) {
|
|
|
|
pret = PrlVmDevHd_SetSerialNumber(sdkdisk, disk->serial);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
return 0;
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(sdkdisk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-04-14 10:45:04 +00:00
|
|
|
static PRL_HANDLE
|
2016-08-15 16:02:49 +00:00
|
|
|
prlsdkGetDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
|
2016-04-14 10:45:04 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
2016-04-20 14:05:29 +00:00
|
|
|
PRL_UINT32 num;
|
2016-04-14 10:45:04 +00:00
|
|
|
size_t i;
|
2016-04-20 14:05:29 +00:00
|
|
|
PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
|
2016-04-14 10:45:04 +00:00
|
|
|
int bus;
|
|
|
|
char *dst = NULL;
|
2016-04-20 14:05:29 +00:00
|
|
|
PRL_DEVICE_TYPE devType;
|
2016-04-14 10:45:04 +00:00
|
|
|
|
2016-04-20 14:05:29 +00:00
|
|
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
|
|
|
|
devType = PDE_HARD_DISK;
|
|
|
|
else
|
|
|
|
devType = PDE_OPTICAL_DISK;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetDevsCountByType(sdkdom, devType, &num);
|
2016-04-14 10:45:04 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2016-04-20 14:05:29 +00:00
|
|
|
for (i = 0; i < num; ++i) {
|
|
|
|
pret = PrlVmCfg_GetDevByType(sdkdom, devType, i, &sdkdisk);
|
2016-04-14 10:45:04 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2016-08-15 16:02:49 +00:00
|
|
|
if (prlsdkGetDiskId(sdkdisk, &bus, &dst) < 0)
|
2016-04-14 10:45:04 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (disk->bus == bus && STREQ(disk->dst, dst)) {
|
|
|
|
VIR_FREE(dst);
|
2016-04-20 14:05:29 +00:00
|
|
|
return sdkdisk;
|
2016-04-14 10:45:04 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:29 +00:00
|
|
|
PrlHandle_Free(sdkdisk);
|
|
|
|
sdkdisk = PRL_INVALID_HANDLE;
|
2016-04-14 10:45:04 +00:00
|
|
|
VIR_FREE(dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No disk with bus '%s' and target '%s'"),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus), disk->dst);
|
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(dst);
|
2016-04-20 14:05:29 +00:00
|
|
|
PrlHandle_Free(sdkdisk);
|
2016-04-14 10:45:04 +00:00
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
2015-04-13 14:55:27 +00:00
|
|
|
int
|
2016-04-20 14:05:30 +00:00
|
|
|
prlsdkAttachDevice(vzDriverPtr driver,
|
2016-03-15 07:47:51 +00:00
|
|
|
virDomainObjPtr dom,
|
2016-04-20 14:05:30 +00:00
|
|
|
virDomainDeviceDefPtr dev)
|
2015-04-13 14:55:27 +00:00
|
|
|
{
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2015-04-13 14:55:27 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-20 14:05:30 +00:00
|
|
|
return -1;
|
2015-04-13 14:55:27 +00:00
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
2016-04-20 14:05:31 +00:00
|
|
|
if (prlsdkConfigureDisk(driver, privdom->sdkdom,
|
2016-08-15 16:02:49 +00:00
|
|
|
dev->data.disk, true) < 0)
|
2016-04-20 14:05:30 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
|
|
|
if (!IS_CT(dom->def)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("attaching network device to VM is unsupported"));
|
|
|
|
return -1;
|
2015-04-13 14:55:27 +00:00
|
|
|
}
|
2016-04-20 14:05:30 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkConfigureNet(driver, dom, privdom->sdkdom, dev->data.net,
|
2016-04-20 14:05:31 +00:00
|
|
|
IS_CT(dom->def), true) < 0)
|
2016-04-20 14:05:30 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
if (dom->def->ngraphics > 0) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("domain already has VNC graphics"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prlsdkApplyGraphicsParams(privdom->sdkdom, dev->data.graphics) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("attaching device type '%s' is unsupported"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
|
|
|
return -1;
|
2015-04-13 14:55:27 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-20 14:05:30 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
2015-04-13 14:55:27 +00:00
|
|
|
}
|
|
|
|
|
2015-05-13 14:23:00 +00:00
|
|
|
int
|
2019-10-14 12:45:33 +00:00
|
|
|
prlsdkDetachDevice(vzDriverPtr driver G_GNUC_UNUSED,
|
2016-04-20 14:05:30 +00:00
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainDeviceDefPtr dev)
|
2015-04-23 18:37:00 +00:00
|
|
|
{
|
2016-04-14 10:45:04 +00:00
|
|
|
int ret = -1;
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2015-04-23 18:37:00 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-04-20 14:05:30 +00:00
|
|
|
PRL_HANDLE sdkdev = PRL_INVALID_HANDLE;
|
2016-04-14 10:45:04 +00:00
|
|
|
PRL_RESULT pret;
|
2015-04-23 18:37:00 +00:00
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2015-04-23 18:37:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
2016-08-15 16:02:49 +00:00
|
|
|
sdkdev = prlsdkGetDisk(privdom->sdkdom, dev->data.disk);
|
2016-04-20 14:05:30 +00:00
|
|
|
if (sdkdev == PRL_INVALID_HANDLE)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDev_Remove(sdkdev);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
|
|
|
if (!IS_CT(dom->def)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("detaching network device from VM is unsupported"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
sdkdev = prlsdkFindNetByMAC(privdom->sdkdom, &dev->data.net->mac);
|
|
|
|
if (sdkdev == PRL_INVALID_HANDLE)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDev_Remove(sdkdev);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
if (dom->def->ngraphics < 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("cannot find VNC graphics device"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prlsdkApplyGraphicsParams(privdom->sdkdom, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("detaching device type '%s' is unsupported"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-04-14 10:45:04 +00:00
|
|
|
|
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-14 10:45:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2015-04-23 18:37:00 +00:00
|
|
|
|
|
|
|
cleanup:
|
2016-04-14 10:45:04 +00:00
|
|
|
|
2016-04-20 14:05:30 +00:00
|
|
|
PrlHandle_Free(sdkdev);
|
2015-04-23 18:37:00 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
int
|
|
|
|
prlsdkUpdateDevice(vzDriverPtr driver,
|
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-20 14:05:31 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
if (prlsdkConfigureDisk(driver, privdom->sdkdom, dev->data.disk,
|
2016-08-15 16:02:49 +00:00
|
|
|
false) < 0)
|
2016-04-20 14:05:31 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkConfigureNet(driver, dom, privdom->sdkdom, dev->data.net,
|
2016-04-20 14:05:31 +00:00
|
|
|
IS_CT(dom->def), false) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
|
|
|
if (dom->def->ngraphics < 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("cannot find VNC graphics device"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prlsdkApplyGraphicsParams(privdom->sdkdom, dev->data.graphics) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-04-20 14:05:31 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("updating device type '%s' is unsupported"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-20 14:05:31 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-13 11:27:39 +00:00
|
|
|
static int
|
|
|
|
prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs)
|
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
|
|
|
|
int ret = -1;
|
2016-07-14 13:52:41 +00:00
|
|
|
char *storage = NULL;
|
2015-01-13 11:27:39 +00:00
|
|
|
|
2016-04-08 07:41:35 +00:00
|
|
|
if (fs->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-13 11:27:39 +00:00
|
|
|
if (prlsdkCheckFSUnsupportedParams(fs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-07-14 13:52:41 +00:00
|
|
|
if (fs->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
|
2019-10-22 13:26:14 +00:00
|
|
|
storage = g_strdup_printf("libvirt://localhost/%s/%s",
|
|
|
|
fs->src->srcpool->pool, fs->src->srcpool->volume);
|
2016-07-14 13:52:41 +00:00
|
|
|
pret = PrlVmDevHd_SetStorageURL(sdkdisk, storage);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
|
|
|
|
2015-01-13 11:27:39 +00:00
|
|
|
pret = PrlVmDev_SetEnabled(sdkdisk, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetConnected(sdkdisk, 1);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-07-14 13:52:38 +00:00
|
|
|
pret = PrlVmDev_SetSysName(sdkdisk, fs->src->path);
|
2015-01-13 11:27:39 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-07-14 13:52:38 +00:00
|
|
|
pret = PrlVmDev_SetImagePath(sdkdisk, fs->src->path);
|
2015-01-13 11:27:39 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-07-14 13:52:38 +00:00
|
|
|
pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src->path);
|
2015-01-13 11:27:39 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-07-14 13:52:41 +00:00
|
|
|
VIR_FREE(storage);
|
2015-01-13 11:27:39 +00:00
|
|
|
PrlHandle_Free(sdkdisk);
|
|
|
|
return ret;
|
|
|
|
}
|
2016-03-22 13:56:36 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkSetBootOrderCt(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
PRL_HANDLE hdd = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
2016-12-05 13:34:52 +00:00
|
|
|
bool rootfs = false;
|
2016-03-22 13:56:36 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nfss; i++) {
|
2016-12-05 13:34:52 +00:00
|
|
|
|
|
|
|
pret = prlsdkAddDeviceToBootList(sdkdom, i, PDE_HARD_DISK, i + 1);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
|
2016-03-22 13:56:36 +00:00
|
|
|
if (STREQ(def->fss[i]->dst, "/"))
|
2016-12-05 13:34:52 +00:00
|
|
|
rootfs = true;
|
2016-03-22 13:56:36 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
if (!rootfs) {
|
|
|
|
/* if we have root mounted we don't need to explicitly set boot order */
|
|
|
|
pret = PrlVmCfg_GetHardDisk(sdkdom, def->nfss, &hdd);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2016-03-22 13:56:36 +00:00
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
PrlVmDevHd_SetMountPoint(hdd, "/");
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
}
|
2016-03-22 13:56:36 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(hdd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkSetBootOrderVm(PRL_HANDLE sdkdom, virDomainDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
int idx[VIR_DOMAIN_BOOT_LAST] = { 0 };
|
|
|
|
int bootIndex = 0;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 num;
|
|
|
|
int sdkType;
|
|
|
|
virDomainBootOrder virType;
|
|
|
|
|
|
|
|
for (i = 0; i < def->os.nBootDevs; ++i) {
|
|
|
|
virType = def->os.bootDevs[i];
|
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)virType) {
|
2016-03-22 13:56:36 +00:00
|
|
|
case VIR_DOMAIN_BOOT_CDROM:
|
|
|
|
sdkType = PDE_OPTICAL_DISK;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_DISK:
|
|
|
|
sdkType = PDE_HARD_DISK;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_NET:
|
|
|
|
sdkType = PDE_GENERIC_NETWORK_ADAPTER;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unsupported boot device type: '%s'"),
|
|
|
|
virDomainBootTypeToString(virType));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetDevsCountByType(sdkdom, sdkType, &num);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
|
|
|
|
pret = prlsdkAddDeviceToBootList(sdkdom, idx[virType]++, sdkType, bootIndex++);
|
|
|
|
prlsdkCheckRetExit(pret, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-05-27 15:16:34 +00:00
|
|
|
int
|
|
|
|
prlsdkDomainSetUserPassword(virDomainObjPtr dom,
|
|
|
|
const char *user,
|
|
|
|
const char *password)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
job = PrlVm_SetUserPasswd(privdom->sdkdom,
|
|
|
|
user,
|
|
|
|
password,
|
|
|
|
0);
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2017-05-03 10:44:52 +00:00
|
|
|
return -1;
|
2016-05-27 15:16:34 +00:00
|
|
|
|
2017-05-03 10:44:52 +00:00
|
|
|
return 0;
|
2016-05-27 15:16:34 +00:00
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
static int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkDoApplyConfig(vzDriverPtr driver,
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
virDomainObjPtr dom,
|
2015-03-18 08:33:53 +00:00
|
|
|
PRL_HANDLE sdkdom,
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
virDomainDefPtr def)
|
2014-12-01 15:38:52 +00:00
|
|
|
{
|
|
|
|
PRL_RESULT pret;
|
|
|
|
size_t i;
|
2016-05-18 08:11:08 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
|
2015-03-10 20:12:19 +00:00
|
|
|
char *mask = NULL;
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (def->description) {
|
|
|
|
pret = PrlVmCfg_SetDescription(sdkdom, def->description);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->name) {
|
|
|
|
pret = PrlVmCfg_SetName(sdkdom, def->name);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->uuid) {
|
|
|
|
prlsdkUUIDFormat(def->uuid, uuidstr);
|
|
|
|
|
|
|
|
pret = PrlVmCfg_SetUuid(sdkdom, uuidstr);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
}
|
|
|
|
|
2016-06-15 13:34:04 +00:00
|
|
|
pret = PrlVmCfg_SetRamSize(sdkdom, virDomainDefGetMemoryTotal(def) >> 10);
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2015-10-22 12:59:03 +00:00
|
|
|
pret = PrlVmCfg_SetCpuCount(sdkdom, virDomainDefGetVcpus(def));
|
2014-12-01 15:38:52 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2015-03-10 20:12:19 +00:00
|
|
|
if (!(mask = virBitmapFormat(def->cpumask)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_SetCpuMask(sdkdom, mask);
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
VIR_FREE(mask);
|
|
|
|
|
2018-02-26 09:25:51 +00:00
|
|
|
switch ((int)def->os.arch) {
|
2015-06-25 07:56:56 +00:00
|
|
|
case VIR_ARCH_X86_64:
|
|
|
|
pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_64);
|
|
|
|
break;
|
|
|
|
case VIR_ARCH_I686:
|
|
|
|
pret = PrlVmCfg_SetCpuMode(sdkdom, PCM_CPU_MODE_32);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown CPU mode: %s"),
|
|
|
|
virArchToString(def->os.arch));
|
|
|
|
goto error;
|
2015-03-13 15:40:40 +00:00
|
|
|
}
|
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2014-12-01 15:38:52 +00:00
|
|
|
if (prlsdkClearDevices(sdkdom) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2015-02-17 11:52:33 +00:00
|
|
|
if (prlsdkRemoveBootDevices(sdkdom) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2015-04-06 15:53:47 +00:00
|
|
|
for (i = 0; i < def->nnets; i++) {
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkConfigureNet(driver, dom, sdkdom, def->nets[i],
|
2016-04-20 14:05:31 +00:00
|
|
|
IS_CT(def), true) < 0)
|
2015-06-25 07:56:56 +00:00
|
|
|
goto error;
|
2015-04-06 15:53:47 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 14:05:42 +00:00
|
|
|
if (def->ngraphics > 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("vz driver supports only VNC graphics"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prlsdkApplyGraphicsParams(sdkdom,
|
|
|
|
def->ngraphics == 1 ? def->graphics[0] : NULL) < 0)
|
2014-12-01 15:38:52 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (prlsdkApplyVideoParams(sdkdom, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nserials; i++) {
|
2015-02-17 11:52:31 +00:00
|
|
|
if (prlsdkAddSerial(sdkdom, def->serials[i]) < 0)
|
|
|
|
goto error;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
/* It is important that we add filesystems first and then disks as we rely
|
|
|
|
* on this information in prlsdkSetBootOrderCt */
|
2015-06-03 21:10:00 +00:00
|
|
|
for (i = 0; i < def->nfss; i++) {
|
|
|
|
if (prlsdkAddFS(sdkdom, def->fss[i]) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2016-12-05 13:34:52 +00:00
|
|
|
/* filesystems first, disks go after them as we rely on this order in
|
|
|
|
* prlsdkSetBootOrderCt */
|
2014-12-01 15:38:52 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2016-04-20 14:05:31 +00:00
|
|
|
if (prlsdkConfigureDisk(driver, sdkdom, def->disks[i],
|
2016-08-15 16:02:49 +00:00
|
|
|
true) < 0)
|
2016-03-22 13:56:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2015-02-17 11:52:33 +00:00
|
|
|
|
2016-03-22 13:56:36 +00:00
|
|
|
if (IS_CT(def)) {
|
|
|
|
if (prlsdkSetBootOrderCt(sdkdom, def) < 0)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
if (prlsdkSetBootOrderVm(sdkdom, def) < 0)
|
2015-02-17 11:52:31 +00:00
|
|
|
goto error;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2015-03-10 20:12:19 +00:00
|
|
|
VIR_FREE(mask);
|
|
|
|
|
2015-06-25 07:56:56 +00:00
|
|
|
return -1;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkApplyConfig(vzDriverPtr driver,
|
2014-12-01 15:38:52 +00:00
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainDefPtr new)
|
|
|
|
{
|
2016-07-20 15:00:30 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2014-12-01 15:38:52 +00:00
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
int ret;
|
|
|
|
|
2016-07-20 15:00:30 +00:00
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2014-12-01 15:38:52 +00:00
|
|
|
return -1;
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
ret = prlsdkDoApplyConfig(driver, dom, privdom->sdkdom, new);
|
2014-12-01 15:38:52 +00:00
|
|
|
|
|
|
|
if (ret == 0) {
|
2016-07-20 15:00:30 +00:00
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2014-12-01 15:38:59 +00:00
|
|
|
ret = -1;
|
2014-12-01 15:38:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-12-01 15:38:53 +00:00
|
|
|
|
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkCreateVm(vzDriverPtr driver, virDomainDefPtr def)
|
2014-12-01 15:38:53 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE srvconf = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
int ret = -1;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
pret = PrlSrv_CreateVm(driver->server, &sdkdom);
|
2014-12-01 15:38:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_GetSrvConfig(driver->server);
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(getJobResult(job, &result)))
|
2014-12-01 15:38:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlResult_GetParamByIndex(result, 0, &srvconf);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2015-03-18 08:33:56 +00:00
|
|
|
pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkDoApplyConfig(driver, NULL, sdkdom, def) < 0)
|
2014-12-01 15:38:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
job = PrlVm_Reg(sdkdom, "", 1);
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(waitJob(job)))
|
2016-06-14 08:45:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-12-01 15:38:53 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(sdkdom);
|
2016-06-14 08:45:54 +00:00
|
|
|
PrlHandle_Free(srvconf);
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
|
2014-12-01 15:38:53 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-07-14 13:52:41 +00:00
|
|
|
static int
|
|
|
|
virStorageTranslatePoolLocal(virConnectPtr conn, virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool = NULL;
|
|
|
|
virStorageVolPtr vol = NULL;
|
|
|
|
virStorageVolInfo info;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(pool = virStoragePoolLookupByName(conn, src->srcpool->pool)))
|
|
|
|
return -1;
|
|
|
|
if (virStoragePoolIsActive(pool) != 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("storage pool '%s' containing volume '%s' "
|
|
|
|
"is not active"), src->srcpool->pool,
|
|
|
|
src->srcpool->volume);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(vol = virStorageVolLookupByName(pool, src->srcpool->volume)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStorageVolGetInfo(vol, &info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (info.type != VIR_STORAGE_VOL_PLOOP) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unsupported volume format '%s'"),
|
|
|
|
virStorageVolTypeToString(info.type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(src->path = virStorageVolGetPath(vol)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(pool);
|
|
|
|
virObjectUnref(vol);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-01 15:38:53 +00:00
|
|
|
int
|
2016-07-14 13:52:41 +00:00
|
|
|
prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def)
|
2014-12-01 15:38:53 +00:00
|
|
|
{
|
|
|
|
PRL_HANDLE sdkdom = PRL_INVALID_HANDLE;
|
|
|
|
PRL_GET_VM_CONFIG_PARAM_DATA confParam;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
2016-04-08 07:41:35 +00:00
|
|
|
PRL_UINT32 flags;
|
2016-07-14 13:52:41 +00:00
|
|
|
vzConnPtr privconn = conn->privateData;
|
|
|
|
vzDriverPtr driver = privconn->driver;
|
2014-12-01 15:38:53 +00:00
|
|
|
int ret = -1;
|
2015-01-13 11:27:40 +00:00
|
|
|
int useTemplate = 0;
|
|
|
|
size_t i;
|
2014-12-01 15:38:53 +00:00
|
|
|
|
2016-07-14 13:52:40 +00:00
|
|
|
for (i = 0; i < def->nfss; i++) {
|
|
|
|
if (useTemplate) {
|
2015-01-13 11:27:40 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2016-07-14 13:52:40 +00:00
|
|
|
_("Unsupported configuration"));
|
2015-01-13 11:27:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2016-07-14 13:52:40 +00:00
|
|
|
if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
|
|
|
|
useTemplate = 1;
|
2016-07-14 13:52:41 +00:00
|
|
|
if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
|
|
|
|
if (virStorageTranslatePoolLocal(conn, def->fss[i]->src) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-07-14 13:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (useTemplate && def->nfss > 1) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Unsupported configuration"));
|
|
|
|
return -1;
|
2014-12-01 15:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
confParam.nVmType = PVT_CT;
|
|
|
|
confParam.sConfigSample = "vswap.1024MB";
|
|
|
|
confParam.nOsVersion = 0;
|
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
job = PrlSrv_GetDefaultVmConfig(driver->server, &confParam, 0);
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(getJobResult(job, &result)))
|
2014-12-01 15:38:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlResult_GetParamByIndex(result, 0, &sdkdom);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2015-01-13 11:27:40 +00:00
|
|
|
if (useTemplate) {
|
2016-07-14 13:52:38 +00:00
|
|
|
pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src->path);
|
2014-12-01 15:38:53 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
2015-01-13 11:27:40 +00:00
|
|
|
|
2014-12-01 15:38:53 +00:00
|
|
|
}
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkDoApplyConfig(driver, NULL, sdkdom, def) < 0)
|
2014-12-01 15:38:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-04-08 07:41:35 +00:00
|
|
|
flags = PACF_NON_INTERACTIVE_MODE;
|
|
|
|
if (!useTemplate)
|
|
|
|
flags |= PRNVM_PRESERVE_DISK;
|
|
|
|
job = PrlVm_RegEx(sdkdom, "", flags);
|
2015-05-13 14:23:00 +00:00
|
|
|
if (PRL_FAILED(waitJob(job)))
|
2016-04-08 07:41:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2014-12-01 15:38:53 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(sdkdom);
|
2016-06-14 08:45:54 +00:00
|
|
|
PrlHandle_Free(result);
|
2015-01-13 11:27:40 +00:00
|
|
|
return ret;
|
2014-12-01 15:38:53 +00:00
|
|
|
}
|
2014-12-01 15:38:58 +00:00
|
|
|
|
2015-12-22 15:29:38 +00:00
|
|
|
/**
|
|
|
|
* prlsdkDetachDomainHardDisks:
|
|
|
|
*
|
|
|
|
* @sdkdom: domain handle
|
|
|
|
*
|
|
|
|
* Returns 0 if hard disks were successfully detached or not detected.
|
|
|
|
*/
|
|
|
|
static int
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
prlsdkDetachDomainHardDisks(virDomainObjPtr dom)
|
2015-12-22 15:29:38 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_UINT32 hddCount;
|
|
|
|
PRL_UINT32 i;
|
|
|
|
PRL_HANDLE job;
|
2016-04-14 10:45:06 +00:00
|
|
|
PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE;
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
vzDomObjPtr pdom = dom->privateData;
|
|
|
|
PRL_HANDLE sdkdom = pdom->sdkdom;
|
2015-12-22 15:29:38 +00:00
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2015-12-22 15:29:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
for (i = 0; i < hddCount; ++i) {
|
2016-04-27 15:37:27 +00:00
|
|
|
pret = PrlVmCfg_GetHardDisk(sdkdom, 0, &sdkdisk);
|
2016-04-14 10:45:06 +00:00
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
pret = PrlVmDev_Remove(sdkdisk);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
PrlHandle_Free(sdkdisk);
|
|
|
|
sdkdisk = PRL_INVALID_HANDLE;
|
2015-12-22 15:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-04-14 10:45:06 +00:00
|
|
|
goto cleanup;
|
2015-12-22 15:29:38 +00:00
|
|
|
|
2016-04-14 10:45:06 +00:00
|
|
|
ret = 0;
|
2015-12-22 15:29:38 +00:00
|
|
|
|
2016-04-14 10:45:06 +00:00
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(sdkdisk);
|
2015-12-22 15:29:38 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-12-01 15:38:58 +00:00
|
|
|
int
|
2016-03-28 19:11:30 +00:00
|
|
|
prlsdkUnregisterDomain(vzDriverPtr driver, virDomainObjPtr dom, unsigned int flags)
|
2014-12-01 15:38:58 +00:00
|
|
|
{
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2014-12-01 15:38:58 +00:00
|
|
|
PRL_HANDLE job;
|
2016-05-02 09:33:08 +00:00
|
|
|
virDomainSnapshotObjListPtr snapshots = NULL;
|
2015-12-22 15:29:40 +00:00
|
|
|
VIRTUAL_MACHINE_STATE domainState;
|
2016-05-02 09:33:08 +00:00
|
|
|
int ret = -1;
|
|
|
|
int num;
|
2015-12-22 15:29:40 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkGetDomainState(dom, privdom->sdkdom, &domainState) < 0)
|
2015-12-22 15:29:40 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VMS_SUSPENDED == domainState &&
|
|
|
|
!(flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE)) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Refusing to undefine while domain managed "
|
|
|
|
"save image exists"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-05-02 09:33:08 +00:00
|
|
|
if (!(snapshots = prlsdkLoadSnapshots(dom)))
|
2015-12-22 15:29:40 +00:00
|
|
|
return -1;
|
2015-03-18 08:33:53 +00:00
|
|
|
|
2016-05-02 09:33:08 +00:00
|
|
|
if ((num = virDomainSnapshotObjListNum(snapshots, NULL, 0)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (num > 0 && !(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
|
2015-12-22 15:29:40 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Refusing to undefine while snapshots exist"));
|
2016-05-02 09:33:08 +00:00
|
|
|
goto cleanup;
|
2015-12-22 15:29:40 +00:00
|
|
|
}
|
2014-12-01 15:38:58 +00:00
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (prlsdkDetachDomainHardDisks(dom))
|
2016-05-02 09:33:08 +00:00
|
|
|
goto cleanup;
|
2015-12-22 15:29:38 +00:00
|
|
|
|
|
|
|
job = PrlVm_Delete(privdom->sdkdom, PRL_INVALID_HANDLE);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-05-02 09:33:08 +00:00
|
|
|
goto cleanup;
|
2014-12-01 15:38:58 +00:00
|
|
|
|
2016-06-14 08:46:00 +00:00
|
|
|
prlsdkSendEvent(driver, dom, VIR_DOMAIN_EVENT_UNDEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
2014-12-01 15:38:58 +00:00
|
|
|
|
2016-03-28 19:11:30 +00:00
|
|
|
virDomainObjListRemove(driver->domains, dom);
|
2016-05-02 09:33:08 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
virDomainSnapshotObjListFree(snapshots);
|
|
|
|
return ret;
|
2014-12-01 15:38:58 +00:00
|
|
|
}
|
2015-04-07 20:35:02 +00:00
|
|
|
|
|
|
|
int
|
2015-05-13 14:23:00 +00:00
|
|
|
prlsdkDomainManagedSaveRemove(virDomainObjPtr dom)
|
2015-04-07 20:35:02 +00:00
|
|
|
{
|
2015-06-10 07:50:00 +00:00
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
2015-04-07 20:35:02 +00:00
|
|
|
PRL_HANDLE job;
|
|
|
|
|
|
|
|
job = PrlVm_DropSuspendedState(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2015-04-07 20:35:02 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-06-09 07:35:53 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
|
|
|
|
{
|
|
|
|
PRL_HANDLE param = PRL_INVALID_HANDLE;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_INT64 pval = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
pret = PrlEvent_GetParamByName(sdkstats, name, ¶m);
|
|
|
|
if (pret == PRL_ERR_NO_DATA) {
|
|
|
|
*val = -1;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
} else if (PRL_FAILED(pret)) {
|
|
|
|
logPrlError(pret);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
pret = PrlEvtPrm_ToInt64(param, &pval);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
*val = pval;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
PrlHandle_Free(param);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PARALLELS_STATISTICS_TIMEOUT (60 * 1000)
|
|
|
|
|
|
|
|
int
|
2016-06-03 07:11:44 +00:00
|
|
|
prlsdkGetBlockStats(PRL_HANDLE sdkstats,
|
|
|
|
virDomainDiskDefPtr disk,
|
2016-12-05 13:52:56 +00:00
|
|
|
virDomainBlockStatsPtr stats,
|
|
|
|
bool isCt)
|
2015-06-09 07:35:53 +00:00
|
|
|
{
|
|
|
|
virDomainDeviceDriveAddressPtr address;
|
|
|
|
int idx;
|
|
|
|
const char *prefix;
|
|
|
|
int ret = -1;
|
|
|
|
char *name = NULL;
|
|
|
|
|
|
|
|
address = &disk->info.addr.drive;
|
2016-12-05 13:52:56 +00:00
|
|
|
|
|
|
|
if (isCt) {
|
|
|
|
prefix = "hdd";
|
2015-06-09 07:35:53 +00:00
|
|
|
idx = address->unit;
|
2016-12-05 13:52:56 +00:00
|
|
|
} else {
|
|
|
|
switch (disk->bus) {
|
|
|
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
|
|
|
prefix = "ide";
|
|
|
|
idx = address->bus * 2 + address->unit;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
|
|
prefix = "sata";
|
|
|
|
idx = address->unit;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
|
|
|
prefix = "scsi";
|
|
|
|
idx = address->unit;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown disk bus: %X"), disk->bus);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2015-06-09 07:35:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME) \
|
2019-10-22 13:26:14 +00:00
|
|
|
name = g_strdup_printf("devices.%s%d.%s", prefix, idx, NAME); \
|
2017-11-03 12:09:47 +00:00
|
|
|
if (prlsdkExtractStatsParam(sdkstats, name, &stats->VAL) < 0) \
|
|
|
|
goto cleanup; \
|
2015-06-09 07:35:53 +00:00
|
|
|
VIR_FREE(name);
|
|
|
|
|
|
|
|
PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
|
|
|
|
|
|
|
|
#undef PRLSDK_GET_STAT_PARAM
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
VIR_FREE(name);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-06-26 11:24:00 +00:00
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
|
2015-06-26 11:24:00 +00:00
|
|
|
static PRL_HANDLE
|
2016-06-03 07:11:44 +00:00
|
|
|
prlsdkFindNetByPath(PRL_HANDLE sdkdom, const char *path)
|
2015-06-26 11:24:00 +00:00
|
|
|
{
|
|
|
|
PRL_UINT32 count = 0;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
size_t i;
|
|
|
|
char *name = NULL;
|
|
|
|
PRL_HANDLE net = PRL_INVALID_HANDLE;
|
|
|
|
|
2016-06-03 07:11:44 +00:00
|
|
|
pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &count);
|
2015-06-26 11:24:00 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i) {
|
2016-06-03 07:11:44 +00:00
|
|
|
pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &net);
|
2015-06-26 11:24:00 +00:00
|
|
|
prlsdkCheckRetGoto(pret, error);
|
|
|
|
|
2016-04-13 16:05:43 +00:00
|
|
|
if (!(name = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName,
|
|
|
|
net)))
|
2015-06-26 11:24:00 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (STREQ(name, path))
|
|
|
|
break;
|
|
|
|
|
|
|
|
VIR_FREE(name);
|
|
|
|
PrlHandle_Free(net);
|
|
|
|
net = PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net == PRL_INVALID_HANDLE)
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid path, '%s' is not a known interface"), path);
|
|
|
|
return net;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(name);
|
|
|
|
PrlHandle_Free(net);
|
|
|
|
return PRL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-10-13 20:25:42 +00:00
|
|
|
prlsdkGetNetStats(PRL_HANDLE sdkstats, PRL_HANDLE sdkdom, const char *device,
|
2015-06-26 11:24:00 +00:00
|
|
|
virDomainInterfaceStatsPtr stats)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
PRL_UINT32 net_index = -1;
|
|
|
|
char *name = NULL;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
PRL_HANDLE net = PRL_INVALID_HANDLE;
|
2017-10-13 20:25:42 +00:00
|
|
|
virMacAddr mac;
|
|
|
|
|
|
|
|
if (virMacAddrParse(device, &mac) == 0)
|
2017-10-17 13:55:15 +00:00
|
|
|
net = prlsdkFindNetByMAC(sdkdom, &mac);
|
2017-10-13 20:25:42 +00:00
|
|
|
else
|
|
|
|
net = prlsdkFindNetByPath(sdkdom, device);
|
2015-06-26 11:24:00 +00:00
|
|
|
|
|
|
|
if (net == PRL_INVALID_HANDLE)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetIndex(net, &net_index);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define PRLSDK_GET_NET_COUNTER(VAL, NAME) \
|
2019-10-22 13:26:14 +00:00
|
|
|
name = g_strdup_printf("net.nic%u.%s", net_index, NAME); \
|
2017-11-03 12:09:47 +00:00
|
|
|
if (prlsdkExtractStatsParam(sdkstats, name, &stats->VAL) < 0) \
|
|
|
|
goto cleanup; \
|
2015-06-26 11:24:00 +00:00
|
|
|
VIR_FREE(name);
|
|
|
|
|
|
|
|
PRLSDK_GET_NET_COUNTER(rx_bytes, "bytes_in")
|
|
|
|
PRLSDK_GET_NET_COUNTER(rx_packets, "pkts_in")
|
|
|
|
PRLSDK_GET_NET_COUNTER(tx_bytes, "bytes_out")
|
|
|
|
PRLSDK_GET_NET_COUNTER(tx_packets, "pkts_out")
|
|
|
|
stats->rx_errs = -1;
|
|
|
|
stats->rx_drop = -1;
|
|
|
|
stats->tx_errs = -1;
|
|
|
|
stats->tx_drop = -1;
|
|
|
|
|
|
|
|
#undef PRLSDK_GET_NET_COUNTER
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(name);
|
|
|
|
PrlHandle_Free(net);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2015-06-26 11:24:00 +00:00
|
|
|
|
|
|
|
int
|
2016-06-03 07:11:44 +00:00
|
|
|
prlsdkGetVcpuStats(PRL_HANDLE sdkstats, int idx, unsigned long long *vtime)
|
2015-06-26 11:24:00 +00:00
|
|
|
{
|
|
|
|
char *name = NULL;
|
|
|
|
long long ptime = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
name = g_strdup_printf("guest.vcpu%u.time", (unsigned int)idx);
|
2016-06-03 07:11:44 +00:00
|
|
|
if (prlsdkExtractStatsParam(sdkstats, name, &ptime) < 0)
|
2015-06-26 11:24:00 +00:00
|
|
|
goto cleanup;
|
|
|
|
*vtime = ptime == -1 ? 0 : ptime;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(name);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-06-26 11:24:00 +00:00
|
|
|
|
|
|
|
int
|
2016-06-03 07:11:44 +00:00
|
|
|
prlsdkGetMemoryStats(PRL_HANDLE sdkstats,
|
2015-06-26 11:24:00 +00:00
|
|
|
virDomainMemoryStatPtr stats,
|
|
|
|
unsigned int nr_stats)
|
|
|
|
{
|
|
|
|
long long v = 0, t = 0, u = 0;
|
|
|
|
size_t i = 0;
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define PRLSDK_GET_COUNTER(NAME, VALUE) \
|
|
|
|
if (prlsdkExtractStatsParam(sdkstats, NAME, &VALUE) < 0) \
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1; \
|
2015-06-26 11:24:00 +00:00
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
#define PRLSDK_MEMORY_STAT_SET(TAG, VALUE) \
|
|
|
|
if (i < nr_stats) { \
|
|
|
|
stats[i].tag = (TAG); \
|
|
|
|
stats[i].val = (VALUE); \
|
|
|
|
i++; \
|
2015-06-26 11:24:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
// count to kb
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.swap_in", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_SWAP_IN, v << 12)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.swap_out", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, v << 12)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.minor_fault", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, v)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.major_fault", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, v)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.total", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_AVAILABLE, v << 10)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.balloon_actual", v)
|
|
|
|
if (v != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON, v << 10)
|
|
|
|
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.usage", u)
|
|
|
|
PRLSDK_GET_COUNTER("guest.ram.total", t)
|
|
|
|
if (u != -1 && t != -1)
|
|
|
|
PRLSDK_MEMORY_STAT_SET(VIR_DOMAIN_MEMORY_STAT_UNUSED, (t - u) << 10)
|
|
|
|
|
|
|
|
#undef PRLSDK_GET_COUNTER
|
|
|
|
#undef PRLSDK_MEMORY_STAT_SET
|
|
|
|
|
2020-01-06 21:57:42 +00:00
|
|
|
return i;
|
2015-06-26 11:24:00 +00:00
|
|
|
}
|
2016-04-08 09:36:45 +00:00
|
|
|
|
|
|
|
/* memsize is in MiB */
|
|
|
|
int prlsdkSetMemsize(virDomainObjPtr dom, unsigned int memsize)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-08 09:36:45 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_SetRamSize(privdom->sdkdom, memsize);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2016-04-08 09:36:45 +00:00
|
|
|
|
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, 0);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2016-04-08 09:36:45 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-05-02 09:33:07 +00:00
|
|
|
|
|
|
|
static long long
|
|
|
|
prlsdkParseDateTime(const char *str)
|
|
|
|
{
|
2019-12-23 15:37:26 +00:00
|
|
|
g_autoptr(GDateTime) then = NULL;
|
2020-01-06 14:20:09 +00:00
|
|
|
g_autoptr(GTimeZone) tz = g_time_zone_new_utc();
|
|
|
|
char *tmp;
|
|
|
|
int year, mon, mday, hour, min, sec;
|
|
|
|
|
|
|
|
/* Expect: YYYY-MM-DD HH:MM:SS (%d-%d-%dT%d:%d:%d) eg 2010-11-28 14:29:01 */
|
|
|
|
if (/* year */
|
|
|
|
virStrToLong_i(str, &tmp, 10, &year) < 0 || *tmp != '-' ||
|
|
|
|
/* month */
|
|
|
|
virStrToLong_i(tmp+1, &tmp, 10, &mon) < 0 || *tmp != '-' ||
|
|
|
|
/* day */
|
|
|
|
virStrToLong_i(tmp+1, &tmp, 10, &mday) < 0 || *tmp != ' ' ||
|
|
|
|
/* hour */
|
|
|
|
virStrToLong_i(tmp+1, &tmp, 10, &hour) < 0 || *tmp != ':' ||
|
|
|
|
/* minute */
|
|
|
|
virStrToLong_i(tmp+1, &tmp, 10, &min) < 0 || *tmp != ':' ||
|
|
|
|
/* second */
|
|
|
|
virStrToLong_i(tmp+1, &tmp, 10, &sec) < 0 || *tmp != '\0') {
|
2016-05-02 09:33:07 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected DateTime format: '%s'"), str);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-01-06 14:20:09 +00:00
|
|
|
then = g_date_time_new(tz, year, mon, mday, hour, min, sec);
|
|
|
|
return (long long)g_date_time_to_unix(then);
|
2016-05-02 09:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainSnapshotObjListPtr
|
|
|
|
prlsdkParseSnapshotTree(const char *treexml)
|
|
|
|
{
|
|
|
|
virDomainSnapshotObjListPtr ret = NULL;
|
|
|
|
xmlDocPtr xml = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
xmlNodePtr root;
|
|
|
|
xmlNodePtr *nodes = NULL;
|
|
|
|
virDomainSnapshotDefPtr def = NULL;
|
2019-03-22 04:45:25 +00:00
|
|
|
virDomainMomentObjPtr snapshot;
|
2016-05-02 09:33:07 +00:00
|
|
|
virDomainSnapshotObjListPtr snapshots = NULL;
|
|
|
|
char *xmlstr = NULL;
|
|
|
|
int n;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!(snapshots = virDomainSnapshotObjListNew()))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (*treexml == '\0')
|
|
|
|
return snapshots;
|
|
|
|
|
|
|
|
if (!(xml = virXMLParse(NULL, treexml, _("(snapshot_tree)"))))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
root = xmlDocGetRootElement(xml);
|
2017-08-14 12:31:52 +00:00
|
|
|
if (!virXMLNodeNameEqual(root, "ParallelsSavedStates")) {
|
2016-05-02 09:33:07 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected root element: '%s'"), root->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-09-09 06:33:58 +00:00
|
|
|
if (!(ctxt = virXMLXPathContextNew(xml)))
|
2016-05-02 09:33:07 +00:00
|
|
|
goto cleanup;
|
2019-09-09 06:33:58 +00:00
|
|
|
|
2016-05-02 09:33:07 +00:00
|
|
|
ctxt->node = root;
|
|
|
|
|
|
|
|
if ((n = virXPathNodeSet("//SavedStateItem", ctxt, &nodes)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot extract snapshot nodes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
if (nodes[i]->parent == root)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ctxt->node = nodes[i];
|
|
|
|
|
2019-05-08 22:10:58 +00:00
|
|
|
def->parent.name = virXPathString("string(./@guid)", ctxt);
|
|
|
|
if (!def->parent.name) {
|
2016-05-02 09:33:07 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("missing 'guid' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-05-08 22:10:58 +00:00
|
|
|
def->parent.parent_name = virXPathString("string(../@guid)", ctxt);
|
2016-05-02 09:33:07 +00:00
|
|
|
|
|
|
|
xmlstr = virXPathString("string(./DateTime)", ctxt);
|
|
|
|
if (!xmlstr) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("missing 'DateTime' element"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2019-05-08 22:10:58 +00:00
|
|
|
if ((def->parent.creationTime = prlsdkParseDateTime(xmlstr)) < 0)
|
2016-05-02 09:33:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
VIR_FREE(xmlstr);
|
|
|
|
|
2019-05-08 22:10:58 +00:00
|
|
|
def->parent.description = virXPathString("string(./Description)", ctxt);
|
2016-05-02 09:33:07 +00:00
|
|
|
|
|
|
|
def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
|
|
|
|
xmlstr = virXPathString("string(./@state)", ctxt);
|
|
|
|
if (!xmlstr) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("missing 'state' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
} else if (STREQ(xmlstr, "poweron")) {
|
|
|
|
def->state = VIR_DOMAIN_RUNNING;
|
|
|
|
def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
|
|
|
|
} else if (STREQ(xmlstr, "pause")) {
|
|
|
|
def->state = VIR_DOMAIN_PAUSED;
|
|
|
|
def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
|
|
|
|
} else if (STREQ(xmlstr, "suspend")) {
|
|
|
|
def->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
} else if (STREQ(xmlstr, "poweroff")) {
|
|
|
|
def->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected snapshot state: %s"), xmlstr);
|
|
|
|
}
|
|
|
|
VIR_FREE(xmlstr);
|
|
|
|
|
|
|
|
if (!(snapshot = virDomainSnapshotAssignDef(snapshots, def)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
|
|
|
|
2019-04-05 14:33:49 +00:00
|
|
|
xmlstr = virXPathString("string(./@current)", ctxt);
|
|
|
|
if (xmlstr && STREQ("yes", xmlstr)) {
|
|
|
|
if (virDomainSnapshotGetCurrent(snapshots)) {
|
2016-05-02 09:33:07 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("too many current snapshots"));
|
2019-04-05 14:33:49 +00:00
|
|
|
VIR_FREE(xmlstr);
|
2016-05-02 09:33:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2019-04-05 14:33:49 +00:00
|
|
|
virDomainSnapshotSetCurrent(snapshots, snapshot);
|
2016-05-02 09:33:07 +00:00
|
|
|
}
|
2019-04-05 14:33:49 +00:00
|
|
|
VIR_FREE(xmlstr);
|
2016-05-02 09:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSnapshotUpdateRelations(snapshots) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("snapshots have inconsistent relations"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-16 11:45:15 +00:00
|
|
|
ret = g_steal_pointer(&snapshots);
|
2016-05-02 09:33:07 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainSnapshotObjListFree(snapshots);
|
|
|
|
VIR_FREE(nodes);
|
|
|
|
VIR_FREE(xmlstr);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
VIR_FREE(def);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainSnapshotObjListPtr
|
|
|
|
prlsdkLoadSnapshots(virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
virDomainSnapshotObjListPtr ret = NULL;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
PRL_HANDLE result = PRL_INVALID_HANDLE;
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
char *treexml = NULL;
|
|
|
|
|
|
|
|
job = PrlVm_GetSnapshotsTreeEx(privdom->sdkdom, PGST_WITHOUT_SCREENSHOTS);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(getDomainJobResult(job, dom, &result)))
|
2016-05-02 09:33:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(treexml = prlsdkGetStringParamVar(PrlResult_GetParamAsString, result)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = prlsdkParseSnapshotTree(treexml);
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
PrlHandle_Free(result);
|
|
|
|
VIR_FREE(treexml);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int prlsdkCreateSnapshot(virDomainObjPtr dom, const char *description)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
|
|
|
|
job = PrlVm_CreateSnapshot(privdom->sdkdom, "",
|
|
|
|
description ? : "");
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-05-02 09:33:07 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int prlsdkDeleteSnapshot(virDomainObjPtr dom, const char *uuid, bool children)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
|
|
|
|
job = PrlVm_DeleteSnapshot(privdom->sdkdom, uuid, children);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-05-02 09:33:07 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
PRL_UINT32 flags = 0;
|
|
|
|
|
|
|
|
if (paused)
|
|
|
|
flags |= PSSF_SKIP_RESUME;
|
|
|
|
|
|
|
|
job = PrlVm_SwitchToSnapshotEx(privdom->sdkdom, uuid, flags);
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2016-05-02 09:33:07 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-05-18 08:11:06 +00:00
|
|
|
|
|
|
|
/* high security is default choice for 2 reasons:
|
|
|
|
* 1. as this is the highest set security we can't get
|
|
|
|
* reject from server with high security settings
|
|
|
|
* 2. this is on par with security level of driver
|
|
|
|
* connection to dispatcher
|
|
|
|
*/
|
|
|
|
|
2016-12-08 08:49:15 +00:00
|
|
|
#define PRLSDK_MIGRATION_FLAGS (PSL_HIGH_SECURITY | PVMT_DONT_CREATE_DISK)
|
2016-05-18 08:11:06 +00:00
|
|
|
|
|
|
|
int prlsdkMigrate(virDomainObjPtr dom, virURIPtr uri,
|
|
|
|
const unsigned char *session_uuid,
|
|
|
|
const char *dname,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
2016-05-18 08:11:08 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BRACED_BUFLEN];
|
2016-05-18 08:11:06 +00:00
|
|
|
PRL_UINT32 vzflags = PRLSDK_MIGRATION_FLAGS;
|
|
|
|
|
|
|
|
if (flags & VIR_MIGRATE_PAUSED)
|
|
|
|
vzflags |= PVMT_DONT_RESUME_VM;
|
|
|
|
|
|
|
|
prlsdkUUIDFormat(session_uuid, uuidstr);
|
|
|
|
job = PrlVm_MigrateWithRenameEx(privdom->sdkdom, uri->server,
|
|
|
|
uri->port, uuidstr,
|
|
|
|
dname == NULL ? "" : dname,
|
|
|
|
"",
|
|
|
|
vzflags,
|
|
|
|
0,
|
|
|
|
PRL_TRUE
|
|
|
|
);
|
|
|
|
|
vz: make vz driver more responsive
Current vz driver implementation is not usable when it comes to
long runnig operations. Migration or saving a domain blocks all
other operations even query ones which are expecteted to be available.
This patch addresses this problem.
All vz driver API calls fall into next 3 groups:
1. only query domain cache (virDomainObj, vz cache statistic)
examples are vzDomainGetState, vzDomainGetXMLDesc etc.
2. use thread shared sdkdom object
examples are vzDomainSetMemoryFlags, vzDomainAttachDevice etc.
3. use no thread shared sdkdom object nor domain cache
examples are vzDomainSnapshotListNames, vzDomainSnapshotGetXMLDesc etc
API calls from group 1 don't need to be changed as they hold domain lock only
for short period of time. These calls [1] are easily distinguished. They query
domain object thru libvirt common code or query vz sdk statistics handle thru
vz sdk sync operations.
vzDomainInterfaceStats is the only exception. It uses sdkdom object to
convert interface name to its vz sdk stack index which could not be saved in
domain cache. Interface statistics is available thru this stack index as a key
rather than name. As a result we can have accidental 'not known interface'
errors on quering intrerface stats. The reason is that in the process of
updating domain configuration we drop all devices and then recreate them again
in sdkdom object and domain lock can be dropped meanwhile (to remove networks
for existing bridged interfaces and(or) (re)create new ones). We can fix this
by changing the way we support bridged interfaces or by reordering operations
and changing bridged networks beforehand. Anyway this is better than moving
this API call into 2 group and making it an exclusive job.
As to API calls from group 2, first thread shared sdkdom object needs to be
explained. vz sdk has only one handle for a given domain, thus threads need
exclusive access to operate on it. These calls are fixed to drop and reacquire
domain lock on any lengthy operations - namely waiting the result of async vz
sdk operation. As lock is dropped we need to take extra reference to domain
object if it is not taken already as domain object can be deleted from list
while lock is dropped. As this operations use thread shared sdkdom object, the
simplest way to make calls from group 2 be consistent to each other is to make
them mutually exclusive. This is done by taking/releasing job condition thru
calling correspondent job routine. This approach makes group 1 and group
2 calls consistent to each other too. Not all calls of group 2 change the
domain cache but those that do update it thru prlsdkUpdateDomain which holds
the lock thoughout the update.
API calls from group [2] are easily distinguished too. They use
beginEdit/commit to change domain configuration (vzDomainSetMemoryFlags) or/and
update domain cache from sdkdom at the end of operation (vzDomainSuspend).
There is a known issue however. Frankly speaking it was introduced by ealier
patch '[PATCH 6/9] vz: cleanup loading domain code' from a different series.
The patch significantly reduced amount of time when the driver lock is held when
creating domain from API call or as a result of domain added event from vz sdk.
The problem is these two paths race on using thread shared sdkdom as we don't
have libvirt domain object and can not lock on it. However this don't
invalidates the patch as we can't use the former approach of preadding domain
into the list as we need name at least and name is not given by event. Anyway
i'm against adding half baked object into the list. Eventually this race can be
fixed by extra measures. As to current situation races with different
configurations are unlikely and race when adding domain thru vz driver and
simultaneous event from vz sdk is not dangerous as configuration is the same.
The last group [3] is API calls that need only sdkdom object to make vz sdk
call and don't change thread shared sdkdom object or domain cache in any way.
For now these are mostly domain snapshot API calls. The changes are similar to
those of group 2 - they add extra reference and drop/reacquire the lock on waiting
vz async call result. One can simply take the immutable sdkdom object from the
cache and drop the lock for the rest of operations but the chosen approach
makes implementation of these API calls somewhat similar to those of from group
2 and thus a bit futureproof. As calls of group 3 don't need vz driver
domain/vz sdk cache in any way, they are consistent with respect to API calls from
groups 1 and 3.
There is another exception. Calls to make-snapshot/revert-to-snapshot/migrate
are moved to group 2. That is they are made mutually exclusive. The reason
is that libvirt API supports control/query only for one job per domain and
these are jobs that are likely to be queried/aborted.
Appendix.
[1] API calls that only query domain cache.
(marked [*] are included for a different reason)
.domainLookupByID = vzDomainLookupByID, /* 0.10.0 */
.domainLookupByUUID = vzDomainLookupByUUID, /* 0.10.0 */
.domainLookupByName = vzDomainLookupByName, /* 0.10.0 */
.domainGetOSType = vzDomainGetOSType, /* 0.10.0 */
.domainGetInfo = vzDomainGetInfo, /* 0.10.0 */
.domainGetState = vzDomainGetState, /* 0.10.0 */
.domainGetXMLDesc = vzDomainGetXMLDesc, /* 0.10.0 */
.domainIsPersistent = vzDomainIsPersistent, /* 0.10.0 */
.domainGetAutostart = vzDomainGetAutostart, /* 0.10.0 */
.domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
.domainIsActive = vzDomainIsActive, /* 1.2.10 */
.domainIsUpdated = vzDomainIsUpdated, /* 1.2.21 */
.domainGetVcpusFlags = vzDomainGetVcpusFlags, /* 1.2.21 */
.domainGetMaxVcpus = vzDomainGetMaxVcpus, /* 1.2.21 */
.domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
.domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
.domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
.domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
.domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */ [*]
.domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
[2] API calls that use thread shared sdkdom object
(marked [*] are included for a different reason)
.domainSuspend = vzDomainSuspend, /* 0.10.0 */
.domainResume = vzDomainResume, /* 0.10.0 */
.domainDestroy = vzDomainDestroy, /* 0.10.0 */
.domainShutdown = vzDomainShutdown, /* 0.10.0 */
.domainCreate = vzDomainCreate, /* 0.10.0 */
.domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
.domainReboot = vzDomainReboot, /* 1.3.0 */
.domainDefineXML = vzDomainDefineXML, /* 0.10.0 */
.domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */ (update part)
.domainUndefine = vzDomainUndefine, /* 1.2.10 */
.domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
.domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
.domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
.domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
.domainSetUserPassword = vzDomainSetUserPassword, /* 1.3.6 */
.domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
.domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
.domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */ [*]
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */ [*]
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */ [*]
.domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */
prlsdkHandleVmConfigEvent
[3] API calls that do not use thread shared sdkdom object
.domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
.domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
.domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
.domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
.domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
.domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
.domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
.domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
.domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
.domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
.domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
.domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
.domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
.domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
[4] Known issues.
1. accidental errors on getting network statistics
2. race with simultaneous use of thread shared domain object on paths
of adding domain thru API and adding domain on vz sdk domain added event.
2016-07-20 15:00:33 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2019-10-21 18:19:02 +00:00
|
|
|
return -1;
|
2016-05-18 08:11:06 +00:00
|
|
|
|
2019-10-21 18:19:02 +00:00
|
|
|
return 0;
|
2016-05-18 08:11:06 +00:00
|
|
|
}
|
2017-04-14 14:53:52 +00:00
|
|
|
|
|
|
|
int prlsdkSetCpuCount(virDomainObjPtr dom, unsigned int count)
|
|
|
|
{
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_HANDLE job;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
|
|
|
|
job = PrlVm_BeginEdit(privdom->sdkdom);
|
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2017-04-14 14:53:52 +00:00
|
|
|
|
|
|
|
pret = PrlVmCfg_SetCpuCount(privdom->sdkdom, count);
|
2020-01-06 21:57:42 +00:00
|
|
|
prlsdkCheckRetExit(pret, -1);
|
2017-04-14 14:53:52 +00:00
|
|
|
|
|
|
|
job = PrlVm_CommitEx(privdom->sdkdom, 0);
|
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2020-01-06 21:57:42 +00:00
|
|
|
return -1;
|
2017-04-14 14:53:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-04-14 14:53:53 +00:00
|
|
|
|
|
|
|
int prlsdkResizeImage(virDomainObjPtr dom, virDomainDiskDefPtr disk,
|
|
|
|
unsigned long long newsize)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
PRL_RESULT pret;
|
|
|
|
vzDomObjPtr privdom = dom->privateData;
|
|
|
|
PRL_UINT32 emulatedType;
|
|
|
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
|
|
|
PRL_HANDLE prldisk = PRL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
prldisk = prlsdkGetDisk(privdom->sdkdom, disk);
|
|
|
|
if (prldisk == PRL_INVALID_HANDLE)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pret = PrlVmDev_GetEmulatedType(prldisk, &emulatedType);
|
|
|
|
prlsdkCheckRetGoto(pret, cleanup);
|
|
|
|
|
|
|
|
if (emulatedType != PDT_USE_IMAGE_FILE &&
|
|
|
|
emulatedType != PDT_USE_FILE_SYSTEM) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Only disk image supported for resize"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
job = PrlVmDev_ResizeImage(prldisk, newsize,
|
|
|
|
PRIF_RESIZE_LAST_PARTITION);
|
2017-05-03 11:23:35 +00:00
|
|
|
if (PRL_FAILED(waitDomainJob(job, dom)))
|
2017-04-14 14:53:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
PrlHandle_Free(prldisk);
|
|
|
|
return ret;
|
|
|
|
}
|