libvirt/src/hypervisor/domain_job.c

229 lines
5.3 KiB
C
Raw Normal View History

/*
* domain_job.c: job functions shared between hypervisor drivers
*
* Copyright (C) 2022 Red Hat, Inc.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
#include <string.h>
#include "domain_job.h"
#include "viralloc.h"
VIR_ENUM_IMPL(virDomainJob,
VIR_JOB_LAST,
"none",
"query",
"destroy",
"suspend",
"modify",
"abort",
"migration operation",
"modify migration safe",
"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",
);
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:
case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
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;
}
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;
}
void
virDomainObjResetJob(virDomainJobObj *job)
{
job->active = VIR_JOB_NONE;
job->owner = 0;
g_clear_pointer(&job->ownerAPI, g_free);
job->started = 0;
}
void
virDomainObjResetAgentJob(virDomainJobObj *job)
{
job->agentActive = VIR_AGENT_JOB_NONE;
job->agentOwner = 0;
g_clear_pointer(&job->agentOwnerAPI, g_free);
job->agentStarted = 0;
}
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);
}
/**
* 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;
}
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);
}
bool
virDomainTrackJob(virDomainJob job)
{
return (VIR_DOMAIN_TRACK_JOBS & JOB_MASK(job)) != 0;
}