1 /*
2  * qemu_domainjob.h: helper functions for QEMU domain jobs
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library.  If not, see
16  * <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <glib-object.h>
22 #include "qemu_monitor.h"
23 
24 #define JOB_MASK(job)                  (job == 0 ? 0 : 1 << (job - 1))
25 #define QEMU_JOB_DEFAULT_MASK \
26     (JOB_MASK(QEMU_JOB_QUERY) | \
27      JOB_MASK(QEMU_JOB_DESTROY) | \
28      JOB_MASK(QEMU_JOB_ABORT))
29 
30 /* Jobs which have to be tracked in domain state XML. */
31 #define QEMU_DOMAIN_TRACK_JOBS \
32     (JOB_MASK(QEMU_JOB_DESTROY) | \
33      JOB_MASK(QEMU_JOB_ASYNC))
34 
35 /* Only 1 job is allowed at any time
36  * A job includes *all* monitor commands, even those just querying
37  * information, not merely actions */
38 typedef enum {
39     QEMU_JOB_NONE = 0,  /* Always set to 0 for easy if (jobActive) conditions */
40     QEMU_JOB_QUERY,         /* Doesn't change any state */
41     QEMU_JOB_DESTROY,       /* Destroys the domain (cannot be masked out) */
42     QEMU_JOB_SUSPEND,       /* Suspends (stops vCPUs) the domain */
43     QEMU_JOB_MODIFY,        /* May change state */
44     QEMU_JOB_ABORT,         /* Abort current async job */
45     QEMU_JOB_MIGRATION_OP,  /* Operation influencing outgoing migration */
46 
47     /* The following two items must always be the last items before JOB_LAST */
48     QEMU_JOB_ASYNC,         /* Asynchronous job */
49     QEMU_JOB_ASYNC_NESTED,  /* Normal job within an async job */
50 
51     QEMU_JOB_LAST
52 } qemuDomainJob;
53 VIR_ENUM_DECL(qemuDomainJob);
54 
55 typedef enum {
56     QEMU_AGENT_JOB_NONE = 0,    /* No agent job. */
57     QEMU_AGENT_JOB_QUERY,       /* Does not change state of domain */
58     QEMU_AGENT_JOB_MODIFY,      /* May change state of domain */
59 
60     QEMU_AGENT_JOB_LAST
61 } qemuDomainAgentJob;
62 VIR_ENUM_DECL(qemuDomainAgentJob);
63 
64 /* Async job consists of a series of jobs that may change state. Independent
65  * jobs that do not change state (and possibly others if explicitly allowed by
66  * current async job) are allowed to be run even if async job is active.
67  */
68 typedef enum {
69     QEMU_ASYNC_JOB_NONE = 0,
70     QEMU_ASYNC_JOB_MIGRATION_OUT,
71     QEMU_ASYNC_JOB_MIGRATION_IN,
72     QEMU_ASYNC_JOB_SAVE,
73     QEMU_ASYNC_JOB_DUMP,
74     QEMU_ASYNC_JOB_SNAPSHOT,
75     QEMU_ASYNC_JOB_START,
76     QEMU_ASYNC_JOB_BACKUP,
77 
78     QEMU_ASYNC_JOB_LAST
79 } qemuDomainAsyncJob;
80 VIR_ENUM_DECL(qemuDomainAsyncJob);
81 
82 typedef enum {
83     QEMU_DOMAIN_JOB_STATUS_NONE = 0,
84     QEMU_DOMAIN_JOB_STATUS_ACTIVE,
85     QEMU_DOMAIN_JOB_STATUS_MIGRATING,
86     QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED,
87     QEMU_DOMAIN_JOB_STATUS_PAUSED,
88     QEMU_DOMAIN_JOB_STATUS_POSTCOPY,
89     QEMU_DOMAIN_JOB_STATUS_COMPLETED,
90     QEMU_DOMAIN_JOB_STATUS_FAILED,
91     QEMU_DOMAIN_JOB_STATUS_CANCELED,
92 } qemuDomainJobStatus;
93 
94 typedef enum {
95     QEMU_DOMAIN_JOB_STATS_TYPE_NONE = 0,
96     QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION,
97     QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP,
98     QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP,
99     QEMU_DOMAIN_JOB_STATS_TYPE_BACKUP,
100 } qemuDomainJobStatsType;
101 
102 
103 typedef struct _qemuDomainMirrorStats qemuDomainMirrorStats;
104 struct _qemuDomainMirrorStats {
105     unsigned long long transferred;
106     unsigned long long total;
107 };
108 
109 typedef struct _qemuDomainBackupStats qemuDomainBackupStats;
110 struct _qemuDomainBackupStats {
111     unsigned long long transferred;
112     unsigned long long total;
113     unsigned long long tmp_used;
114     unsigned long long tmp_total;
115 };
116 
117 typedef struct _qemuDomainJobInfo qemuDomainJobInfo;
118 struct _qemuDomainJobInfo {
119     qemuDomainJobStatus status;
120     virDomainJobOperation operation;
121     unsigned long long started; /* When the async job started */
122     unsigned long long stopped; /* When the domain's CPUs were stopped */
123     unsigned long long sent; /* When the source sent status info to the
124                                 destination (only for migrations). */
125     unsigned long long received; /* When the destination host received status
126                                     info from the source (migrations only). */
127     /* Computed values */
128     unsigned long long timeElapsed;
129     long long timeDelta; /* delta = received - sent, i.e., the difference
130                             between the source and the destination time plus
131                             the time between the end of Perform phase on the
132                             source and the beginning of Finish phase on the
133                             destination. */
134     bool timeDeltaSet;
135     /* Raw values from QEMU */
136     qemuDomainJobStatsType statsType;
137     union {
138         qemuMonitorMigrationStats mig;
139         qemuMonitorDumpStats dump;
140         qemuDomainBackupStats backup;
141     } stats;
142     qemuDomainMirrorStats mirrorStats;
143 
144     char *errmsg; /* optional error message for failed completed jobs */
145 };
146 
147 void
148 qemuDomainJobInfoFree(qemuDomainJobInfo *info);
149 
150 G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuDomainJobInfo, qemuDomainJobInfoFree);
151 
152 qemuDomainJobInfo *
153 qemuDomainJobInfoCopy(qemuDomainJobInfo *info);
154 
155 typedef struct _qemuDomainJobObj qemuDomainJobObj;
156 
157 typedef void *(*qemuDomainObjPrivateJobAlloc)(void);
158 typedef void (*qemuDomainObjPrivateJobFree)(void *);
159 typedef void (*qemuDomainObjPrivateJobReset)(void *);
160 typedef int (*qemuDomainObjPrivateJobFormat)(virBuffer *,
161                                              qemuDomainJobObj *,
162                                              virDomainObj *);
163 typedef int (*qemuDomainObjPrivateJobParse)(xmlXPathContextPtr,
164                                             qemuDomainJobObj *,
165                                             virDomainObj *);
166 
167 typedef struct _qemuDomainObjPrivateJobCallbacks qemuDomainObjPrivateJobCallbacks;
168 struct _qemuDomainObjPrivateJobCallbacks {
169    qemuDomainObjPrivateJobAlloc allocJobPrivate;
170    qemuDomainObjPrivateJobFree freeJobPrivate;
171    qemuDomainObjPrivateJobReset resetJobPrivate;
172    qemuDomainObjPrivateJobFormat formatJob;
173    qemuDomainObjPrivateJobParse parseJob;
174 };
175 
176 struct _qemuDomainJobObj {
177     virCond cond;                       /* Use to coordinate jobs */
178 
179     /* The following members are for QEMU_JOB_* */
180     qemuDomainJob active;               /* Currently running job */
181     unsigned long long owner;           /* Thread id which set current job */
182     char *ownerAPI;                     /* The API which owns the job */
183     unsigned long long started;         /* When the current job started */
184 
185     /* The following members are for QEMU_AGENT_JOB_* */
186     qemuDomainAgentJob agentActive;     /* Currently running agent job */
187     unsigned long long agentOwner;      /* Thread id which set current agent job */
188     char *agentOwnerAPI;                /* The API which owns the agent job */
189     unsigned long long agentStarted;    /* When the current agent job started */
190 
191     /* The following members are for QEMU_ASYNC_JOB_* */
192     virCond asyncCond;                  /* Use to coordinate with async jobs */
193     qemuDomainAsyncJob asyncJob;        /* Currently active async job */
194     unsigned long long asyncOwner;      /* Thread which set current async job */
195     char *asyncOwnerAPI;                /* The API which owns the async job */
196     unsigned long long asyncStarted;    /* When the current async job started */
197     int phase;                          /* Job phase (mainly for migrations) */
198     unsigned long long mask;            /* Jobs allowed during async job */
199     qemuDomainJobInfo *current;       /* async job progress data */
200     qemuDomainJobInfo *completed;     /* statistics data of a recently completed job */
201     bool abortJob;                      /* abort of the job requested */
202     char *error;                        /* job event completion error */
203     unsigned long apiFlags; /* flags passed to the API which started the async job */
204 
205     void *privateData;                  /* job specific collection of data */
206     qemuDomainObjPrivateJobCallbacks *cb;
207 };
208 
209 const char *qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job,
210                                             int phase);
211 int qemuDomainAsyncJobPhaseFromString(qemuDomainAsyncJob job,
212                                       const char *phase);
213 
214 void qemuDomainEventEmitJobCompleted(virQEMUDriver *driver,
215                                      virDomainObj *vm);
216 
217 int qemuDomainObjBeginJob(virQEMUDriver *driver,
218                           virDomainObj *obj,
219                           qemuDomainJob job)
220     G_GNUC_WARN_UNUSED_RESULT;
221 int qemuDomainObjBeginAgentJob(virQEMUDriver *driver,
222                                virDomainObj *obj,
223                                qemuDomainAgentJob agentJob)
224     G_GNUC_WARN_UNUSED_RESULT;
225 int qemuDomainObjBeginAsyncJob(virQEMUDriver *driver,
226                                virDomainObj *obj,
227                                qemuDomainAsyncJob asyncJob,
228                                virDomainJobOperation operation,
229                                unsigned long apiFlags)
230     G_GNUC_WARN_UNUSED_RESULT;
231 int qemuDomainObjBeginNestedJob(virQEMUDriver *driver,
232                                 virDomainObj *obj,
233                                 qemuDomainAsyncJob asyncJob)
234     G_GNUC_WARN_UNUSED_RESULT;
235 int qemuDomainObjBeginJobNowait(virQEMUDriver *driver,
236                                 virDomainObj *obj,
237                                 qemuDomainJob job)
238     G_GNUC_WARN_UNUSED_RESULT;
239 
240 void qemuDomainObjEndJob(virQEMUDriver *driver,
241                          virDomainObj *obj);
242 void qemuDomainObjEndAgentJob(virDomainObj *obj);
243 void qemuDomainObjEndAsyncJob(virQEMUDriver *driver,
244                               virDomainObj *obj);
245 void qemuDomainObjAbortAsyncJob(virDomainObj *obj);
246 void qemuDomainObjSetJobPhase(virQEMUDriver *driver,
247                               virDomainObj *obj,
248                               int phase);
249 void qemuDomainObjSetAsyncJobMask(virDomainObj *obj,
250                                   unsigned long long allowedJobs);
251 int qemuDomainObjRestoreJob(virDomainObj *obj,
252                             qemuDomainJobObj *job);
253 void qemuDomainObjDiscardAsyncJob(virQEMUDriver *driver,
254                                   virDomainObj *obj);
255 void qemuDomainObjReleaseAsyncJob(virDomainObj *obj);
256 
257 int qemuDomainJobInfoUpdateTime(qemuDomainJobInfo *jobInfo)
258     ATTRIBUTE_NONNULL(1);
259 int qemuDomainJobInfoUpdateDowntime(qemuDomainJobInfo *jobInfo)
260     ATTRIBUTE_NONNULL(1);
261 int qemuDomainJobInfoToInfo(qemuDomainJobInfo *jobInfo,
262                             virDomainJobInfoPtr info)
263     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
264 int qemuDomainJobInfoToParams(qemuDomainJobInfo *jobInfo,
265                               int *type,
266                               virTypedParameterPtr *params,
267                               int *nparams)
268     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
269     ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
270 
271 bool qemuDomainTrackJob(qemuDomainJob job);
272 
273 void qemuDomainObjClearJob(qemuDomainJobObj *job);
274 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(qemuDomainJobObj, qemuDomainObjClearJob);
275 
276 int
277 qemuDomainObjInitJob(qemuDomainJobObj *job,
278                      qemuDomainObjPrivateJobCallbacks *cb);
279 
280 bool qemuDomainJobAllowed(qemuDomainJobObj *jobs, qemuDomainJob newJob);
281 
282 int
283 qemuDomainObjPrivateXMLFormatJob(virBuffer *buf,
284                                  virDomainObj *vm);
285 
286 int
287 qemuDomainObjPrivateXMLParseJob(virDomainObj *vm,
288                                 xmlXPathContextPtr ctxt);
289