2022-02-11 13:49:05 +00:00
|
|
|
/*
|
2022-07-19 12:52:01 +00:00
|
|
|
* domain_job.c: job functions shared between hypervisor drivers
|
|
|
|
*
|
2022-02-11 13:49:05 +00:00
|
|
|
* Copyright (C) 2022 Red Hat, Inc.
|
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "domain_job.h"
|
2022-08-03 12:43:13 +00:00
|
|
|
#include "viralloc.h"
|
2022-02-11 13:49:05 +00:00
|
|
|
|
|
|
|
|
2022-03-24 15:32:42 +00:00
|
|
|
VIR_ENUM_IMPL(virDomainJob,
|
|
|
|
VIR_JOB_LAST,
|
|
|
|
"none",
|
|
|
|
"query",
|
|
|
|
"destroy",
|
|
|
|
"suspend",
|
|
|
|
"modify",
|
|
|
|
"abort",
|
|
|
|
"migration operation",
|
2022-05-24 14:17:23 +00:00
|
|
|
"modify migration safe",
|
2022-03-24 15:32:42 +00:00
|
|
|
"none", /* async job is never stored in job.active */
|
|
|
|
"async nested",
|
|
|
|
);
|
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virDomainAgentJob,
|
|
|
|
VIR_AGENT_JOB_LAST,
|
|
|
|
"none",
|
|
|
|
"query",
|
|
|
|
"modify",
|
|
|
|
);
|
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virDomainAsyncJob,
|
|
|
|
VIR_ASYNC_JOB_LAST,
|
|
|
|
"none",
|
|
|
|
"migration out",
|
|
|
|
"migration in",
|
|
|
|
"save",
|
|
|
|
"dump",
|
|
|
|
"snapshot",
|
|
|
|
"start",
|
|
|
|
"backup",
|
|
|
|
);
|
|
|
|
|
2022-02-11 13:49:05 +00:00
|
|
|
virDomainJobData *
|
|
|
|
virDomainJobDataInit(virDomainJobDataPrivateDataCallbacks *cb)
|
|
|
|
{
|
|
|
|
virDomainJobData *ret = g_new0(virDomainJobData, 1);
|
|
|
|
|
|
|
|
ret->privateDataCb = cb;
|
|
|
|
|
|
|
|
if (ret->privateDataCb)
|
|
|
|
ret->privateData = ret->privateDataCb->allocPrivateData();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainJobData *
|
|
|
|
virDomainJobDataCopy(virDomainJobData *data)
|
|
|
|
{
|
|
|
|
virDomainJobData *ret = g_new0(virDomainJobData, 1);
|
|
|
|
|
|
|
|
memcpy(ret, data, sizeof(*data));
|
|
|
|
|
|
|
|
if (ret->privateDataCb)
|
|
|
|
ret->privateData = data->privateDataCb->copyPrivateData(data->privateData);
|
|
|
|
|
|
|
|
ret->errmsg = g_strdup(data->errmsg);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
virDomainJobDataFree(virDomainJobData *data)
|
|
|
|
{
|
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (data->privateDataCb)
|
|
|
|
data->privateDataCb->freePrivateData(data->privateData);
|
|
|
|
|
|
|
|
g_free(data->errmsg);
|
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainJobType
|
|
|
|
virDomainJobStatusToType(virDomainJobStatus status)
|
|
|
|
{
|
|
|
|
switch (status) {
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_NONE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_ACTIVE:
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_MIGRATING:
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED:
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_POSTCOPY:
|
2022-05-10 13:20:25 +00:00
|
|
|
case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
|
2022-02-11 13:49:05 +00:00
|
|
|
case VIR_DOMAIN_JOB_STATUS_PAUSED:
|
|
|
|
return VIR_DOMAIN_JOB_UNBOUNDED;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_COMPLETED:
|
|
|
|
return VIR_DOMAIN_JOB_COMPLETED;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_FAILED:
|
|
|
|
return VIR_DOMAIN_JOB_FAILED;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_JOB_STATUS_CANCELED:
|
|
|
|
return VIR_DOMAIN_JOB_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VIR_DOMAIN_JOB_NONE;
|
|
|
|
}
|
2022-07-21 11:54:46 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
virDomainObjInitJob(virDomainJobObj *job,
|
|
|
|
virDomainObjPrivateJobCallbacks *cb)
|
|
|
|
{
|
|
|
|
memset(job, 0, sizeof(*job));
|
|
|
|
job->cb = cb;
|
|
|
|
|
|
|
|
if (virCondInit(&job->cond) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virCondInit(&job->asyncCond) < 0) {
|
|
|
|
virCondDestroy(&job->cond);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (job->cb &&
|
|
|
|
!(job->privateData = job->cb->allocJobPrivate())) {
|
|
|
|
virCondDestroy(&job->cond);
|
|
|
|
virCondDestroy(&job->asyncCond);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-07-22 14:25:31 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
virDomainObjResetJob(virDomainJobObj *job)
|
|
|
|
{
|
|
|
|
job->active = VIR_JOB_NONE;
|
|
|
|
job->owner = 0;
|
|
|
|
g_clear_pointer(&job->ownerAPI, g_free);
|
|
|
|
job->started = 0;
|
|
|
|
}
|
2022-08-03 12:43:12 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
virDomainObjResetAgentJob(virDomainJobObj *job)
|
|
|
|
{
|
|
|
|
job->agentActive = VIR_AGENT_JOB_NONE;
|
|
|
|
job->agentOwner = 0;
|
|
|
|
g_clear_pointer(&job->agentOwnerAPI, g_free);
|
|
|
|
job->agentStarted = 0;
|
|
|
|
}
|
2022-08-03 12:43:13 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
virDomainObjResetAsyncJob(virDomainJobObj *job)
|
|
|
|
{
|
|
|
|
job->asyncJob = VIR_ASYNC_JOB_NONE;
|
|
|
|
job->asyncOwner = 0;
|
|
|
|
g_clear_pointer(&job->asyncOwnerAPI, g_free);
|
|
|
|
job->asyncStarted = 0;
|
|
|
|
job->phase = 0;
|
|
|
|
job->mask = VIR_JOB_DEFAULT_MASK;
|
|
|
|
job->abortJob = false;
|
|
|
|
VIR_FREE(job->error);
|
|
|
|
g_clear_pointer(&job->current, virDomainJobDataFree);
|
|
|
|
job->apiFlags = 0;
|
|
|
|
|
|
|
|
if (job->cb)
|
|
|
|
job->cb->resetJobPrivate(job->privateData);
|
|
|
|
}
|
2022-08-03 12:43:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainObjPreserveJob
|
|
|
|
* @param currJob structure is a job that needs to be preserved
|
|
|
|
* @param job structure where to store job details from @currJob
|
|
|
|
*
|
|
|
|
* Saves the current job details from @currJob to @job and resets the job in @currJob.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virDomainObjPreserveJob(virDomainJobObj *currJob,
|
|
|
|
virDomainJobObj *job)
|
|
|
|
{
|
|
|
|
memset(job, 0, sizeof(*job));
|
|
|
|
job->active = currJob->active;
|
|
|
|
job->owner = currJob->owner;
|
|
|
|
job->asyncJob = currJob->asyncJob;
|
|
|
|
job->asyncOwner = currJob->asyncOwner;
|
|
|
|
job->phase = currJob->phase;
|
|
|
|
job->privateData = g_steal_pointer(&currJob->privateData);
|
|
|
|
job->apiFlags = currJob->apiFlags;
|
|
|
|
|
|
|
|
if (currJob->cb &&
|
|
|
|
!(currJob->privateData = currJob->cb->allocJobPrivate()))
|
|
|
|
return -1;
|
|
|
|
job->cb = currJob->cb;
|
|
|
|
|
|
|
|
virDomainObjResetJob(currJob);
|
|
|
|
virDomainObjResetAsyncJob(currJob);
|
|
|
|
return 0;
|
|
|
|
}
|
2022-08-03 12:43:16 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
virDomainObjClearJob(virDomainJobObj *job)
|
|
|
|
{
|
|
|
|
virDomainObjResetJob(job);
|
|
|
|
virDomainObjResetAsyncJob(job);
|
|
|
|
g_clear_pointer(&job->current, virDomainJobDataFree);
|
|
|
|
g_clear_pointer(&job->completed, virDomainJobDataFree);
|
|
|
|
virCondDestroy(&job->cond);
|
|
|
|
virCondDestroy(&job->asyncCond);
|
|
|
|
|
|
|
|
if (job->cb)
|
|
|
|
g_clear_pointer(&job->privateData, job->cb->freeJobPrivate);
|
|
|
|
}
|
2022-08-03 12:43:20 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
virDomainTrackJob(virDomainJob job)
|
|
|
|
{
|
|
|
|
return (VIR_DOMAIN_TRACK_JOBS & JOB_MASK(job)) != 0;
|
|
|
|
}
|