Merge lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages into lp:ubuntu/raring/libvirt
- Raring (13.04)
- libvirt-hugepages
- Merge into raring
Status: | Needs review |
---|---|
Proposed branch: | lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages |
Merge into: | lp:ubuntu/raring/libvirt |
Diff against target: |
11034 lines (+10828/-0) 24 files modified
.pc/apparmor-allow-hugepages/src/libvirt_private.syms (+1840/-0) .pc/apparmor-allow-hugepages/src/qemu/qemu_process.c (+4474/-0) .pc/apparmor-allow-hugepages/src/security/security_apparmor.c (+911/-0) .pc/apparmor-allow-hugepages/src/security/security_driver.h (+148/-0) .pc/apparmor-allow-hugepages/src/security/security_manager.c (+513/-0) .pc/apparmor-allow-hugepages/src/security/security_manager.h (+116/-0) .pc/apparmor-allow-hugepages/src/security/security_stack.c (+532/-0) .pc/apparmor-allow-hugepages/tests/virt-aa-helper-test (+326/-0) .pc/applied-patches (+2/-0) .pc/vnc-socket.patch/src/security/virt-aa-helper.c (+1314/-0) .pc/vnc-socket.patch/tests/virt-aa-helper-test (+329/-0) debian/changelog (+9/-0) debian/patches/apparmor-allow-hugepages (+189/-0) debian/patches/series (+2/-0) debian/patches/vnc-socket.patch (+37/-0) src/libvirt_private.syms (+1/-0) src/qemu/qemu_process.c (+9/-0) src/security/security_apparmor.c (+27/-0) src/security/security_driver.h (+4/-0) src/security/security_manager.c (+10/-0) src/security/security_manager.h (+3/-0) src/security/security_stack.c (+19/-0) src/security/virt-aa-helper.c (+7/-0) tests/virt-aa-helper-test (+6/-0) |
To merge this branch: | bzr merge lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jamie Strandboge | Pending | ||
Review via email: mp+138341@code.launchpad.net |
Commit message
Description of the change
This has proposed changes for vnc socket files and hugepages backing stores. Both have been tested and appear to work, but given my un-familiarity with the relevant code before I started, I'd appreciate a review to make sure I didn't mis-interpret any of the code.
- 228. By Serge Hallyn
-
Switch to using virBuffer
- 229. By Serge Hallyn
-
add tests for vnc and hugepages apparmor extensions
- 230. By Serge Hallyn
-
fix bad cut-pastes
Unmerged revisions
- 230. By Serge Hallyn
-
fix bad cut-pastes
- 229. By Serge Hallyn
-
add tests for vnc and hugepages apparmor extensions
- 228. By Serge Hallyn
-
Switch to using virBuffer
- 227. By Serge Hallyn
-
debian/
patches/ vnc-socket. patch: If a vnc socket is in use, add it's
path to the apparmor policy. (LP: #1069534)Note - I'm not sure whether there are non-unix-socket cases which are
mis-handled by this. - 226. By Serge Hallyn
-
debian/
patches/ apparmor- allow-hugepages : update apparmor policies to
allow use of hugepages. (LP: #646468)
Preview Diff
1 | === added directory '.pc/apparmor-allow-hugepages' |
2 | === added file '.pc/apparmor-allow-hugepages/.timestamp' |
3 | === added directory '.pc/apparmor-allow-hugepages/src' |
4 | === added file '.pc/apparmor-allow-hugepages/src/libvirt_private.syms' |
5 | --- .pc/apparmor-allow-hugepages/src/libvirt_private.syms 1970-01-01 00:00:00 +0000 |
6 | +++ .pc/apparmor-allow-hugepages/src/libvirt_private.syms 2012-12-11 20:02:29 +0000 |
7 | @@ -0,0 +1,1840 @@ |
8 | +# |
9 | +# General private symbols. Add symbols here, and see Makefile.am for |
10 | +# more details. |
11 | +# |
12 | +# Keep this file sorted by header name, then by symbols with each header. |
13 | +# |
14 | + |
15 | +# bitmap.h |
16 | +virBitmapClearAll; |
17 | +virBitmapClearBit; |
18 | +virBitmapCopy; |
19 | +virBitmapCountBits; |
20 | +virBitmapEqual; |
21 | +virBitmapFormat; |
22 | +virBitmapFree; |
23 | +virBitmapGetBit; |
24 | +virBitmapIsAllSet; |
25 | +virBitmapNew; |
26 | +virBitmapNewCopy; |
27 | +virBitmapNewData; |
28 | +virBitmapNextSetBit; |
29 | +virBitmapParse; |
30 | +virBitmapSetAll; |
31 | +virBitmapSetBit; |
32 | +virBitmapSize; |
33 | +virBitmapString; |
34 | +virBitmapToData; |
35 | + |
36 | + |
37 | +# buf.h |
38 | +virBufferAdd; |
39 | +virBufferAddChar; |
40 | +virBufferAdjustIndent; |
41 | +virBufferAsprintf; |
42 | +virBufferContentAndReset; |
43 | +virBufferCurrentContent; |
44 | +virBufferError; |
45 | +virBufferEscape; |
46 | +virBufferEscapeSexpr; |
47 | +virBufferEscapeShell; |
48 | +virBufferEscapeString; |
49 | +virBufferFreeAndReset; |
50 | +virBufferGetIndent; |
51 | +virBufferStrcat; |
52 | +virBufferTrim; |
53 | +virBufferURIEncodeString; |
54 | +virBufferUse; |
55 | +virBufferVasprintf; |
56 | + |
57 | + |
58 | +# caps.h |
59 | +virCapabilitiesAddGuest; |
60 | +virCapabilitiesAddGuestDomain; |
61 | +virCapabilitiesAddGuestFeature; |
62 | +virCapabilitiesAddHostFeature; |
63 | +virCapabilitiesAddHostMigrateTransport; |
64 | +virCapabilitiesAddHostNUMACell; |
65 | +virCapabilitiesAllocMachines; |
66 | +virCapabilitiesDefaultGuestArch; |
67 | +virCapabilitiesDefaultGuestEmulator; |
68 | +virCapabilitiesDefaultGuestMachine; |
69 | +virCapabilitiesFormatXML; |
70 | +virCapabilitiesFree; |
71 | +virCapabilitiesFreeMachines; |
72 | +virCapabilitiesFreeNUMAInfo; |
73 | +virCapabilitiesGenerateMac; |
74 | +virCapabilitiesIsEmulatorRequired; |
75 | +virCapabilitiesNew; |
76 | +virCapabilitiesSetEmulatorRequired; |
77 | +virCapabilitiesSetHostCPU; |
78 | +virCapabilitiesSetMacPrefix; |
79 | + |
80 | + |
81 | +# cgroup.h |
82 | +virCgroupAddTask; |
83 | +virCgroupAddTaskController; |
84 | +virCgroupAllowDevice; |
85 | +virCgroupAllowDeviceMajor; |
86 | +virCgroupAllowDevicePath; |
87 | +virCgroupControllerTypeFromString; |
88 | +virCgroupControllerTypeToString; |
89 | +virCgroupDenyAllDevices; |
90 | +virCgroupDenyDevice; |
91 | +virCgroupDenyDeviceMajor; |
92 | +virCgroupDenyDevicePath; |
93 | +virCgroupForDomain; |
94 | +virCgroupForDriver; |
95 | +virCgroupForEmulator; |
96 | +virCgroupForVcpu; |
97 | +virCgroupFree; |
98 | +virCgroupGetBlkioWeight; |
99 | +virCgroupGetCpuCfsPeriod; |
100 | +virCgroupGetCpuCfsQuota; |
101 | +virCgroupGetCpuShares; |
102 | +virCgroupGetCpuacctPercpuUsage; |
103 | +virCgroupGetCpuacctStat; |
104 | +virCgroupGetCpuacctUsage; |
105 | +virCgroupGetCpusetCpus; |
106 | +virCgroupGetCpusetMems; |
107 | +virCgroupGetFreezerState; |
108 | +virCgroupGetMemSwapHardLimit; |
109 | +virCgroupGetMemoryHardLimit; |
110 | +virCgroupGetMemorySoftLimit; |
111 | +virCgroupGetMemoryUsage; |
112 | +virCgroupKill; |
113 | +virCgroupKillPainfully; |
114 | +virCgroupKillRecursive; |
115 | +virCgroupMounted; |
116 | +virCgroupMoveTask; |
117 | +virCgroupPathOfController; |
118 | +virCgroupRemove; |
119 | +virCgroupSetBlkioDeviceWeight; |
120 | +virCgroupSetBlkioWeight; |
121 | +virCgroupSetCpuCfsPeriod; |
122 | +virCgroupSetCpuCfsQuota; |
123 | +virCgroupSetCpuShares; |
124 | +virCgroupSetCpusetCpus; |
125 | +virCgroupSetCpusetMems; |
126 | +virCgroupSetFreezerState; |
127 | +virCgroupSetMemSwapHardLimit; |
128 | +virCgroupSetMemory; |
129 | +virCgroupSetMemoryHardLimit; |
130 | +virCgroupSetMemorySoftLimit; |
131 | + |
132 | + |
133 | +# command.h |
134 | +virCommandAbort; |
135 | +virCommandAddArg; |
136 | +virCommandAddArgBuffer; |
137 | +virCommandAddArgFormat; |
138 | +virCommandAddArgList; |
139 | +virCommandAddArgPair; |
140 | +virCommandAddArgSet; |
141 | +virCommandAddEnvBuffer; |
142 | +virCommandAddEnvFormat; |
143 | +virCommandAddEnvPair; |
144 | +virCommandAddEnvPass; |
145 | +virCommandAddEnvPassCommon; |
146 | +virCommandAddEnvString; |
147 | +virCommandAllowCap; |
148 | +virCommandClearCaps; |
149 | +virCommandDaemonize; |
150 | +virCommandExec; |
151 | +virCommandFree; |
152 | +virCommandHandshakeNotify; |
153 | +virCommandHandshakeWait; |
154 | +virCommandNew; |
155 | +virCommandNewArgList; |
156 | +virCommandNewArgs; |
157 | +virCommandNonblockingFDs; |
158 | +virCommandPreserveFD; |
159 | +virCommandRequireHandshake; |
160 | +virCommandRun; |
161 | +virCommandRunAsync; |
162 | +virCommandSetErrorBuffer; |
163 | +virCommandSetErrorFD; |
164 | +virCommandSetInputBuffer; |
165 | +virCommandSetInputFD; |
166 | +virCommandSetOutputBuffer; |
167 | +virCommandSetOutputFD; |
168 | +virCommandSetPidFile; |
169 | +virCommandSetPreExecHook; |
170 | +virCommandSetWorkingDirectory; |
171 | +virCommandToString; |
172 | +virCommandTransferFD; |
173 | +virCommandWait; |
174 | +virCommandWriteArgLog; |
175 | +virFork; |
176 | +virRun; |
177 | + |
178 | + |
179 | +# conf.h |
180 | +virConfFree; |
181 | +virConfFreeValue; |
182 | +virConfGetValue; |
183 | +virConfNew; |
184 | +virConfReadFile; |
185 | +virConfReadMem; |
186 | +virConfSetValue; |
187 | +virConfWriteFile; |
188 | +virConfWriteMem; |
189 | + |
190 | + |
191 | +# cpu.h |
192 | +cpuBaseline; |
193 | +cpuBaselineXML; |
194 | +cpuCompare; |
195 | +cpuCompareXML; |
196 | +cpuDataFree; |
197 | +cpuDecode; |
198 | +cpuEncode; |
199 | +cpuGuestData; |
200 | +cpuHasFeature; |
201 | +cpuMapOverride; |
202 | +cpuNodeData; |
203 | +cpuUpdate; |
204 | + |
205 | + |
206 | +# cpu_conf.h |
207 | +virCPUDefAddFeature; |
208 | +virCPUDefCopy; |
209 | +virCPUDefCopyModel; |
210 | +virCPUDefFormat; |
211 | +virCPUDefFormatBuf; |
212 | +virCPUDefFree; |
213 | +virCPUDefFreeModel; |
214 | +virCPUDefParseXML; |
215 | +virCPUModeTypeToString; |
216 | + |
217 | + |
218 | +# datatypes.h |
219 | +virConnectClass; |
220 | +virDomainClass; |
221 | +virDomainSnapshotClass; |
222 | +virGetConnect; |
223 | +virGetDomain; |
224 | +virGetDomainSnapshot; |
225 | +virGetInterface; |
226 | +virGetNWFilter; |
227 | +virGetNetwork; |
228 | +virGetNodeDevice; |
229 | +virGetSecret; |
230 | +virGetStoragePool; |
231 | +virGetStorageVol; |
232 | +virGetStream; |
233 | +virInterfaceClass; |
234 | +virNetworkClass; |
235 | +virNodeDeviceClass; |
236 | +virNWFilterClass; |
237 | +virSecretClass; |
238 | +virStoragePoolClass; |
239 | +virStorageVolClass; |
240 | +virStreamClass; |
241 | + |
242 | + |
243 | +# device_conf.h |
244 | +virDeviceAddressPciMultiTypeFromString; |
245 | +virDeviceAddressPciMultiTypeToString; |
246 | +virDevicePCIAddressEqual; |
247 | +virDevicePCIAddressFormat; |
248 | +virDevicePCIAddressIsValid; |
249 | +virDevicePCIAddressParseXML; |
250 | + |
251 | +# dnsmasq.h |
252 | +dnsmasqAddDhcpHost; |
253 | +dnsmasqAddHost; |
254 | +dnsmasqContextFree; |
255 | +dnsmasqContextNew; |
256 | +dnsmasqDelete; |
257 | +dnsmasqReload; |
258 | +dnsmasqSave; |
259 | + |
260 | + |
261 | +# domain_audit.h |
262 | +virDomainAuditCgroup; |
263 | +virDomainAuditCgroupMajor; |
264 | +virDomainAuditCgroupPath; |
265 | +virDomainAuditDisk; |
266 | +virDomainAuditFS; |
267 | +virDomainAuditHostdev; |
268 | +virDomainAuditMemory; |
269 | +virDomainAuditNet; |
270 | +virDomainAuditNetDevice; |
271 | +virDomainAuditRedirdev; |
272 | +virDomainAuditSecurityLabel; |
273 | +virDomainAuditStart; |
274 | +virDomainAuditStop; |
275 | +virDomainAuditVcpu; |
276 | + |
277 | + |
278 | +# domain_conf.h |
279 | +virBlkioDeviceWeightArrayClear; |
280 | +virDiskNameToBusDeviceIndex; |
281 | +virDiskNameToIndex; |
282 | +virDomainActualNetDefFree; |
283 | +virDomainAssignDef; |
284 | +virDomainBlockedReasonTypeFromString; |
285 | +virDomainBlockedReasonTypeToString; |
286 | +virDomainBootMenuTypeFromString; |
287 | +virDomainBootMenuTypeToString; |
288 | +virDomainChrConsoleTargetTypeFromString; |
289 | +virDomainChrConsoleTargetTypeToString; |
290 | +virDomainChrDefForeach; |
291 | +virDomainChrDefFree; |
292 | +virDomainChrDefNew; |
293 | +virDomainChrSourceDefCopy; |
294 | +virDomainChrSourceDefFree; |
295 | +virDomainChrSpicevmcTypeFromString; |
296 | +virDomainChrSpicevmcTypeToString; |
297 | +virDomainChrTcpProtocolTypeFromString; |
298 | +virDomainChrTcpProtocolTypeToString; |
299 | +virDomainChrTypeFromString; |
300 | +virDomainChrTypeToString; |
301 | +virDomainClockBasisTypeToString; |
302 | +virDomainClockOffsetTypeFromString; |
303 | +virDomainClockOffsetTypeToString; |
304 | +virDomainConfigFile; |
305 | +virDomainControllerDefFree; |
306 | +virDomainControllerFind; |
307 | +virDomainControllerInsert; |
308 | +virDomainControllerInsertPreAlloced; |
309 | +virDomainControllerModelSCSITypeFromString; |
310 | +virDomainControllerModelSCSITypeToString; |
311 | +virDomainControllerModelUSBTypeFromString; |
312 | +virDomainControllerModelUSBTypeToString; |
313 | +virDomainControllerRemove; |
314 | +virDomainControllerTypeToString; |
315 | +virDomainCpuPlacementModeTypeFromString; |
316 | +virDomainCpuPlacementModeTypeToString; |
317 | +virDomainDefAddImplicitControllers; |
318 | +virDomainDefCheckABIStability; |
319 | +virDomainDefClearDeviceAliases; |
320 | +virDomainDefClearPCIAddresses; |
321 | +virDomainDefCompatibleDevice; |
322 | +virDomainDefFormat; |
323 | +virDomainDefFormatInternal; |
324 | +virDomainDefFree; |
325 | +virDomainDefGetSecurityLabelDef; |
326 | +virDomainDiskDefGetSecurityLabelDef; |
327 | +virDomainDefAddSecurityLabelDef; |
328 | +virDomainDefParseFile; |
329 | +virDomainDefParseNode; |
330 | +virDomainDefParseString; |
331 | +virDomainDeleteConfig; |
332 | +virDomainDeviceAddressIsValid; |
333 | +virDomainDeviceAddressTypeToString; |
334 | +virDomainDeviceDefCopy; |
335 | +virDomainDeviceDefFree; |
336 | +virDomainDeviceDefParse; |
337 | +virDomainDeviceInfoCopy; |
338 | +virDomainDeviceInfoIterate; |
339 | +virDomainDeviceTypeToString; |
340 | +virDomainDiskBusTypeToString; |
341 | +virDomainDiskCacheTypeFromString; |
342 | +virDomainDiskCacheTypeToString; |
343 | +virDomainDiskCopyOnReadTypeFromString; |
344 | +virDomainDiskCopyOnReadTypeToString; |
345 | +virDomainDiskDefAssignAddress; |
346 | +virDomainDiskDefForeachPath; |
347 | +virDomainDiskDefFree; |
348 | +virDomainDiskDeviceTypeToString; |
349 | +virDomainDiskErrorPolicyTypeFromString; |
350 | +virDomainDiskErrorPolicyTypeToString; |
351 | +virDomainDiskFindControllerModel; |
352 | +virDomainDiskGeometryTransTypeFromString; |
353 | +virDomainDiskGeometryTransTypeToString; |
354 | +virDomainDiskIndexByName; |
355 | +virDomainDiskInsert; |
356 | +virDomainDiskInsertPreAlloced; |
357 | +virDomainDiskIoTypeFromString; |
358 | +virDomainDiskIoTypeToString; |
359 | +virDomainDiskPathByName; |
360 | +virDomainDiskRemove; |
361 | +virDomainDiskRemoveByName; |
362 | +virDomainDiskTypeFromString; |
363 | +virDomainDiskTypeToString; |
364 | +virDomainEmulatorPinAdd; |
365 | +virDomainEmulatorPinDel; |
366 | +virDomainFSDefFree; |
367 | +virDomainFSIndexByName; |
368 | +virDomainFSTypeFromString; |
369 | +virDomainFSTypeToString; |
370 | +virDomainFSWrpolicyTypeFromString; |
371 | +virDomainFSWrpolicyTypeToString; |
372 | +virDomainFeatureStateTypeFromString; |
373 | +virDomainFeatureStateTypeToString; |
374 | +virDomainFindByID; |
375 | +virDomainFindByName; |
376 | +virDomainFindByUUID; |
377 | +virDomainGetRootFilesystem; |
378 | +virDomainGraphicsAuthConnectedTypeFromString; |
379 | +virDomainGraphicsAuthConnectedTypeToString; |
380 | +virDomainGraphicsDefFree; |
381 | +virDomainGraphicsListenGetAddress; |
382 | +virDomainGraphicsListenGetNetwork; |
383 | +virDomainGraphicsListenGetType; |
384 | +virDomainGraphicsListenSetAddress; |
385 | +virDomainGraphicsListenSetNetwork; |
386 | +virDomainGraphicsListenSetType; |
387 | +virDomainGraphicsSpiceChannelModeTypeFromString; |
388 | +virDomainGraphicsSpiceChannelModeTypeToString; |
389 | +virDomainGraphicsSpiceChannelNameTypeFromString; |
390 | +virDomainGraphicsSpiceChannelNameTypeToString; |
391 | +virDomainGraphicsSpiceClipboardCopypasteTypeFromString; |
392 | +virDomainGraphicsSpiceClipboardCopypasteTypeToString; |
393 | +virDomainGraphicsSpiceImageCompressionTypeFromString; |
394 | +virDomainGraphicsSpiceImageCompressionTypeToString; |
395 | +virDomainGraphicsSpiceJpegCompressionTypeFromString; |
396 | +virDomainGraphicsSpiceJpegCompressionTypeToString; |
397 | +virDomainGraphicsSpiceMouseModeTypeFromString; |
398 | +virDomainGraphicsSpiceMouseModeTypeToString; |
399 | +virDomainGraphicsSpicePlaybackCompressionTypeFromString; |
400 | +virDomainGraphicsSpicePlaybackCompressionTypeToString; |
401 | +virDomainGraphicsSpiceStreamingModeTypeFromString; |
402 | +virDomainGraphicsSpiceStreamingModeTypeToString; |
403 | +virDomainGraphicsSpiceZlibCompressionTypeFromString; |
404 | +virDomainGraphicsSpiceZlibCompressionTypeToString; |
405 | +virDomainGraphicsTypeFromString; |
406 | +virDomainGraphicsTypeToString; |
407 | +virDomainHasDiskMirror; |
408 | +virDomainHostdevDefAlloc; |
409 | +virDomainHostdevDefClear; |
410 | +virDomainHostdevDefFree; |
411 | +virDomainHostdevFind; |
412 | +virDomainHostdevInsert; |
413 | +virDomainHostdevModeTypeToString; |
414 | +virDomainHostdevRemove; |
415 | +virDomainHostdevSubsysTypeToString; |
416 | +virDomainHubTypeFromString; |
417 | +virDomainHubTypeToString; |
418 | +virDomainHypervTypeFromString; |
419 | +virDomainHypervTypeToString; |
420 | +virDomainInputDefFree; |
421 | +virDomainIoEventFdTypeFromString; |
422 | +virDomainIoEventFdTypeToString; |
423 | +virDomainLeaseDefFree; |
424 | +virDomainLeaseIndex; |
425 | +virDomainLeaseInsert; |
426 | +virDomainLeaseInsertPreAlloc; |
427 | +virDomainLeaseInsertPreAlloced; |
428 | +virDomainLeaseRemove; |
429 | +virDomainLeaseRemoveAt; |
430 | +virDomainLifecycleCrashTypeFromString; |
431 | +virDomainLifecycleCrashTypeToString; |
432 | +virDomainLifecycleTypeFromString; |
433 | +virDomainLifecycleTypeToString; |
434 | +virDomainList; |
435 | +virDomainLiveConfigHelperMethod; |
436 | +virDomainLoadAllConfigs; |
437 | +virDomainLockFailureTypeFromString; |
438 | +virDomainLockFailureTypeToString; |
439 | +virDomainLookupVcpuPin; |
440 | +virDomainMemballoonModelTypeFromString; |
441 | +virDomainMemballoonModelTypeToString; |
442 | +virDomainMemDumpTypeFromString; |
443 | +virDomainMemDumpTypeToString; |
444 | +virDomainNetDefFree; |
445 | +virDomainNetFind; |
446 | +virDomainNetFindIdx; |
447 | +virDomainNetGetActualBandwidth; |
448 | +virDomainNetGetActualBridgeName; |
449 | +virDomainNetGetActualDirectDev; |
450 | +virDomainNetGetActualDirectMode; |
451 | +virDomainNetGetActualHostdev; |
452 | +virDomainNetGetActualType; |
453 | +virDomainNetGetActualVirtPortProfile; |
454 | +virDomainNetGetActualVlan; |
455 | +virDomainNetInsert; |
456 | +virDomainNetRemove; |
457 | +virDomainNetTypeToString; |
458 | +virDomainNostateReasonTypeFromString; |
459 | +virDomainNostateReasonTypeToString; |
460 | +virDomainNumatuneMemModeTypeFromString; |
461 | +virDomainNumatuneMemModeTypeToString; |
462 | +virDomainNumatuneMemPlacementModeTypeFromString; |
463 | +virDomainNumatuneMemPlacementModeTypeToString; |
464 | +virDomainObjAssignDef; |
465 | +virDomainObjCopyPersistentDef; |
466 | +virDomainObjGetPersistentDef; |
467 | +virDomainObjGetState; |
468 | +virDomainObjIsDuplicate; |
469 | +virDomainObjListDeinit; |
470 | +virDomainObjListGetActiveIDs; |
471 | +virDomainObjListGetInactiveNames; |
472 | +virDomainObjListInit; |
473 | +virDomainObjListNumOfDomains; |
474 | +virDomainObjLock; |
475 | +virDomainObjNew; |
476 | +virDomainObjSetDefTransient; |
477 | +virDomainObjSetState; |
478 | +virDomainObjTaint; |
479 | +virDomainObjUnlock; |
480 | +virDomainPausedReasonTypeFromString; |
481 | +virDomainPausedReasonTypeToString; |
482 | +virDomainPciRombarModeTypeFromString; |
483 | +virDomainPciRombarModeTypeToString; |
484 | +virDomainPMStateTypeFromString; |
485 | +virDomainPMStateTypeToString; |
486 | +virDomainRedirdevBusTypeFromString; |
487 | +virDomainRedirdevBusTypeToString; |
488 | +virDomainRemoveInactive; |
489 | +virDomainRunningReasonTypeFromString; |
490 | +virDomainRunningReasonTypeToString; |
491 | +virDomainSaveConfig; |
492 | +virDomainSaveStatus; |
493 | +virDomainSaveXML; |
494 | +virDomainSeclabelTypeFromString; |
495 | +virDomainSeclabelTypeToString; |
496 | +virDomainShutdownReasonTypeFromString; |
497 | +virDomainShutdownReasonTypeToString; |
498 | +virDomainShutoffReasonTypeFromString; |
499 | +virDomainShutoffReasonTypeToString; |
500 | +virDomainSmartcardDefForeach; |
501 | +virDomainSmartcardDefFree; |
502 | +virDomainSmartcardTypeFromString; |
503 | +virDomainSmartcardTypeToString; |
504 | +virDomainSmbiosModeTypeFromString; |
505 | +virDomainSmbiosModeTypeToString; |
506 | +virDomainSoundDefFree; |
507 | +virDomainSoundModelTypeFromString; |
508 | +virDomainSoundModelTypeToString; |
509 | +virDomainStartupPolicyTypeFromString; |
510 | +virDomainStartupPolicyTypeToString; |
511 | +virDomainStateReasonFromString; |
512 | +virDomainStateReasonToString; |
513 | +virDomainStateTypeFromString; |
514 | +virDomainStateTypeToString; |
515 | +virDomainTaintTypeFromString; |
516 | +virDomainTaintTypeToString; |
517 | +virDomainTimerModeTypeFromString; |
518 | +virDomainTimerModeTypeToString; |
519 | +virDomainTimerNameTypeFromString; |
520 | +virDomainTimerNameTypeToString; |
521 | +virDomainTimerTickpolicyTypeFromString; |
522 | +virDomainTimerTickpolicyTypeToString; |
523 | +virDomainTimerTrackTypeFromString; |
524 | +virDomainTimerTrackTypeToString; |
525 | +virDomainVcpuPinAdd; |
526 | +virDomainVcpuPinDefArrayFree; |
527 | +virDomainVcpuPinDefCopy; |
528 | +virDomainVcpuPinDefFree; |
529 | +virDomainVcpuPinDel; |
530 | +virDomainVcpuPinFindByVcpu; |
531 | +virDomainVcpuPinIsDuplicate; |
532 | +virDomainVideoDefFree; |
533 | +virDomainVideoDefaultRAM; |
534 | +virDomainVideoDefaultType; |
535 | +virDomainVideoTypeFromString; |
536 | +virDomainVideoTypeToString; |
537 | +virDomainVirtTypeToString; |
538 | +virDomainVirtioEventIdxTypeFromString; |
539 | +virDomainVirtioEventIdxTypeToString; |
540 | +virDomainWatchdogActionTypeFromString; |
541 | +virDomainWatchdogActionTypeToString; |
542 | +virDomainWatchdogModelTypeFromString; |
543 | +virDomainWatchdogModelTypeToString; |
544 | + |
545 | + |
546 | +# domain_event.h |
547 | +virDomainEventBalloonChangeNewFromDom; |
548 | +virDomainEventBalloonChangeNewFromObj; |
549 | +virDomainEventBlockJobNewFromObj; |
550 | +virDomainEventBlockJobNewFromDom; |
551 | +virDomainEventControlErrorNewFromDom; |
552 | +virDomainEventControlErrorNewFromObj; |
553 | +virDomainEventDiskChangeNewFromDom; |
554 | +virDomainEventDiskChangeNewFromObj; |
555 | +virDomainEventFree; |
556 | +virDomainEventGraphicsNewFromDom; |
557 | +virDomainEventGraphicsNewFromObj; |
558 | +virDomainEventIOErrorNewFromDom; |
559 | +virDomainEventIOErrorNewFromObj; |
560 | +virDomainEventIOErrorReasonNewFromDom; |
561 | +virDomainEventIOErrorReasonNewFromObj; |
562 | +virDomainEventNew; |
563 | +virDomainEventNewFromDef; |
564 | +virDomainEventNewFromDom; |
565 | +virDomainEventNewFromObj; |
566 | +virDomainEventPMSuspendNewFromDom; |
567 | +virDomainEventPMSuspendNewFromObj; |
568 | +virDomainEventPMWakeupNewFromDom; |
569 | +virDomainEventPMWakeupNewFromObj; |
570 | +virDomainEventRTCChangeNewFromDom; |
571 | +virDomainEventRTCChangeNewFromObj; |
572 | +virDomainEventRebootNew; |
573 | +virDomainEventRebootNewFromDom; |
574 | +virDomainEventRebootNewFromObj; |
575 | +virDomainEventStateDeregister; |
576 | +virDomainEventStateDeregisterID; |
577 | +virDomainEventStateEventID; |
578 | +virDomainEventStateRegister; |
579 | +virDomainEventStateRegisterID; |
580 | +virDomainEventStateFree; |
581 | +virDomainEventStateNew; |
582 | +virDomainEventStateQueue; |
583 | +virDomainEventPMSuspendDiskNewFromDom; |
584 | +virDomainEventPMSuspendDiskNewFromObj; |
585 | +virDomainEventTrayChangeNewFromDom; |
586 | +virDomainEventTrayChangeNewFromObj; |
587 | +virDomainEventWatchdogNewFromDom; |
588 | +virDomainEventWatchdogNewFromObj; |
589 | + |
590 | + |
591 | +# domain_lock.h |
592 | +virDomainLockProcessStart; |
593 | +virDomainLockProcessInquire; |
594 | +virDomainLockProcessPause; |
595 | +virDomainLockProcessResume; |
596 | +virDomainLockDiskAttach; |
597 | +virDomainLockDiskDetach; |
598 | +virDomainLockLeaseAttach; |
599 | +virDomainLockLeaseDetach; |
600 | + |
601 | + |
602 | +# domain_nwfilter.h |
603 | +virDomainConfNWFilterInstantiate; |
604 | +virDomainConfNWFilterRegister; |
605 | +virDomainConfNWFilterTeardown; |
606 | +virDomainConfVMNWFilterTeardown; |
607 | + |
608 | + |
609 | +# ebtables.h |
610 | +ebtablesAddForwardAllowIn; |
611 | +ebtablesAddForwardPolicyReject; |
612 | +ebtablesContextFree; |
613 | +ebtablesContextNew; |
614 | +ebtablesRemoveForwardAllowIn; |
615 | + |
616 | + |
617 | +# event_poll.h |
618 | +virEventPollAddHandle; |
619 | +virEventPollAddTimeout; |
620 | +virEventPollFromNativeEvents; |
621 | +virEventPollInit; |
622 | +virEventPollRemoveHandle; |
623 | +virEventPollRemoveTimeout; |
624 | +virEventPollRunOnce; |
625 | +virEventPollToNativeEvents; |
626 | +virEventPollUpdateHandle; |
627 | +virEventPollUpdateTimeout; |
628 | + |
629 | + |
630 | +# fdstream.h |
631 | +virFDStreamOpen; |
632 | +virFDStreamConnectUNIX; |
633 | +virFDStreamOpenFile; |
634 | +virFDStreamCreateFile; |
635 | + |
636 | + |
637 | +# hash.h |
638 | +virHashAddEntry; |
639 | +virHashCreate; |
640 | +virHashEqual; |
641 | +virHashForEach; |
642 | +virHashFree; |
643 | +virHashGetItems; |
644 | +virHashLookup; |
645 | +virHashRemoveAll; |
646 | +virHashRemoveEntry; |
647 | +virHashRemoveSet; |
648 | +virHashSearch; |
649 | +virHashSize; |
650 | +virHashSteal; |
651 | +virHashTableSize; |
652 | +virHashUpdateEntry; |
653 | + |
654 | + |
655 | +# hooks.h |
656 | +virHookCall; |
657 | +virHookInitialize; |
658 | +virHookPresent; |
659 | + |
660 | + |
661 | +# interface_conf.h |
662 | +virInterfaceAssignDef; |
663 | +virInterfaceDefFormat; |
664 | +virInterfaceDefFree; |
665 | +virInterfaceDefParseFile; |
666 | +virInterfaceDefParseNode; |
667 | +virInterfaceDefParseString; |
668 | +virInterfaceFindByMACString; |
669 | +virInterfaceFindByName; |
670 | +virInterfaceObjListClone; |
671 | +virInterfaceObjListFree; |
672 | +virInterfaceObjLock; |
673 | +virInterfaceObjUnlock; |
674 | +virInterfaceRemove; |
675 | + |
676 | + |
677 | +# iptables.h |
678 | +iptablesAddForwardAllowCross; |
679 | +iptablesAddForwardAllowIn; |
680 | +iptablesAddForwardAllowOut; |
681 | +iptablesAddForwardAllowRelatedIn; |
682 | +iptablesAddForwardMasquerade; |
683 | +iptablesAddForwardRejectIn; |
684 | +iptablesAddForwardRejectOut; |
685 | +iptablesAddOutputFixUdpChecksum; |
686 | +iptablesAddTcpInput; |
687 | +iptablesAddUdpInput; |
688 | +iptablesContextFree; |
689 | +iptablesContextNew; |
690 | +iptablesRemoveForwardAllowCross; |
691 | +iptablesRemoveForwardAllowIn; |
692 | +iptablesRemoveForwardAllowOut; |
693 | +iptablesRemoveForwardAllowRelatedIn; |
694 | +iptablesRemoveForwardMasquerade; |
695 | +iptablesRemoveForwardRejectIn; |
696 | +iptablesRemoveForwardRejectOut; |
697 | +iptablesRemoveOutputFixUdpChecksum; |
698 | +iptablesRemoveTcpInput; |
699 | +iptablesRemoveUdpInput; |
700 | + |
701 | + |
702 | +# json.h |
703 | +virJSONValueArrayAppend; |
704 | +virJSONValueArrayGet; |
705 | +virJSONValueArraySize; |
706 | +virJSONValueFree; |
707 | +virJSONValueFromString; |
708 | +virJSONValueGetBoolean; |
709 | +virJSONValueGetNumberDouble; |
710 | +virJSONValueGetNumberInt; |
711 | +virJSONValueGetNumberLong; |
712 | +virJSONValueGetNumberUint; |
713 | +virJSONValueGetNumberUlong; |
714 | +virJSONValueGetString; |
715 | +virJSONValueIsNull; |
716 | +virJSONValueNewArray; |
717 | +virJSONValueNewBoolean; |
718 | +virJSONValueNewNull; |
719 | +virJSONValueNewNumberDouble; |
720 | +virJSONValueNewNumberInt; |
721 | +virJSONValueNewNumberLong; |
722 | +virJSONValueNewNumberUint; |
723 | +virJSONValueNewNumberUlong; |
724 | +virJSONValueNewObject; |
725 | +virJSONValueNewString; |
726 | +virJSONValueNewStringLen; |
727 | +virJSONValueObjectAppend; |
728 | +virJSONValueObjectAppendBoolean; |
729 | +virJSONValueObjectAppendNull; |
730 | +virJSONValueObjectAppendNumberDouble; |
731 | +virJSONValueObjectAppendNumberInt; |
732 | +virJSONValueObjectAppendNumberLong; |
733 | +virJSONValueObjectAppendNumberUint; |
734 | +virJSONValueObjectAppendNumberUlong; |
735 | +virJSONValueObjectAppendString; |
736 | +virJSONValueObjectGet; |
737 | +virJSONValueObjectGetBoolean; |
738 | +virJSONValueObjectGetKey; |
739 | +virJSONValueObjectGetNumberDouble; |
740 | +virJSONValueObjectGetNumberInt; |
741 | +virJSONValueObjectGetNumberLong; |
742 | +virJSONValueObjectGetNumberUint; |
743 | +virJSONValueObjectGetNumberUlong; |
744 | +virJSONValueObjectGetString; |
745 | +virJSONValueObjectGetValue; |
746 | +virJSONValueObjectHasKey; |
747 | +virJSONValueObjectIsNull; |
748 | +virJSONValueObjectKeysNumber; |
749 | +virJSONValueToString; |
750 | + |
751 | + |
752 | +# libvirt_internal.h |
753 | +virDomainMigrateFinish2; |
754 | +virDomainMigrateFinish; |
755 | +virDomainMigratePerform; |
756 | +virDomainMigratePrepare2; |
757 | +virDomainMigratePrepare; |
758 | +virDomainMigratePrepareTunnel; |
759 | +virDomainMigrateBegin3; |
760 | +virDomainMigratePrepare3; |
761 | +virDomainMigratePrepareTunnel3; |
762 | +virDomainMigratePerform3; |
763 | +virDomainMigrateFinish3; |
764 | +virDomainMigrateConfirm3; |
765 | +virDrvSupportsFeature; |
766 | +virRegisterDeviceMonitor; |
767 | +virRegisterDriver; |
768 | +virRegisterInterfaceDriver; |
769 | +virRegisterNWFilterDriver; |
770 | +virRegisterNetworkDriver; |
771 | +virRegisterSecretDriver; |
772 | +virRegisterStorageDriver; |
773 | + |
774 | + |
775 | +# locking.h |
776 | +virLockManagerAcquire; |
777 | +virLockManagerAddResource; |
778 | +virLockManagerFree; |
779 | +virLockManagerInquire; |
780 | +virLockManagerNew; |
781 | +virLockManagerPluginNew; |
782 | +virLockManagerPluginRef; |
783 | +virLockManagerPluginUnref; |
784 | +virLockManagerPluginUsesState; |
785 | +virLockManagerPluginGetName; |
786 | +virLockManagerRelease; |
787 | +virLockManagerSetPluginDir; |
788 | + |
789 | + |
790 | +# logging.h |
791 | +virLogDefineFilter; |
792 | +virLogDefineOutput; |
793 | +virLogEmergencyDumpAll; |
794 | +virLogGetDefaultPriority; |
795 | +virLogGetFilters; |
796 | +virLogGetNbFilters; |
797 | +virLogGetNbOutputs; |
798 | +virLogGetOutputs; |
799 | +virLogLock; |
800 | +virLogMessage; |
801 | +virLogParseDefaultPriority; |
802 | +virLogParseFilters; |
803 | +virLogParseOutputs; |
804 | +virLogReset; |
805 | +virLogSetBufferSize; |
806 | +virLogSetDefaultPriority; |
807 | +virLogSetFromEnv; |
808 | +virLogUnlock; |
809 | + |
810 | + |
811 | +# memory.h |
812 | +virAlloc; |
813 | +virAllocN; |
814 | +virAllocVar; |
815 | +virExpandN; |
816 | +virFree; |
817 | +virReallocN; |
818 | +virResizeN; |
819 | +virShrinkN; |
820 | + |
821 | + |
822 | +# netdev_bandwidth_conf.h |
823 | +virNetDevBandwidthFormat; |
824 | +virNetDevBandwidthParse; |
825 | + |
826 | + |
827 | +#netdev_vlan_conf.h |
828 | +virNetDevVlanFormat; |
829 | +virNetDevVlanParse; |
830 | + |
831 | + |
832 | +# netdev_vportprofile_conf.h |
833 | +virNetDevVPortProfileFormat; |
834 | +virNetDevVPortProfileParse; |
835 | +virNetDevVPortTypeFromString; |
836 | +virNetDevVPortTypeToString; |
837 | + |
838 | + |
839 | +# network_conf.h |
840 | +virNetworkAssignDef; |
841 | +virNetworkConfigFile; |
842 | +virNetworkConfigChangeSetup; |
843 | +virNetworkDefCopy; |
844 | +virNetworkDefFormat; |
845 | +virNetworkDefFree; |
846 | +virNetworkDefGetIpByIndex; |
847 | +virNetworkDefParseFile; |
848 | +virNetworkDefParseNode; |
849 | +virNetworkDefParseString; |
850 | +virNetworkDeleteConfig; |
851 | +virNetworkFindByName; |
852 | +virNetworkFindByUUID; |
853 | +virNetworkIpDefNetmask; |
854 | +virNetworkIpDefPrefix; |
855 | +virNetworkList; |
856 | +virNetworkLoadAllConfigs; |
857 | +virNetworkObjAssignDef; |
858 | +virNetworkObjFree; |
859 | +virNetworkObjGetPersistentDef; |
860 | +virNetworkObjIsDuplicate; |
861 | +virNetworkObjListFree; |
862 | +virNetworkObjLock; |
863 | +virNetworkObjReplacePersistentDef; |
864 | +virNetworkObjSetDefTransient; |
865 | +virNetworkObjUnlock; |
866 | +virNetworkObjUnsetDefTransient; |
867 | +virNetworkObjUpdate; |
868 | +virNetworkRemoveInactive; |
869 | +virNetworkSaveConfig; |
870 | +virNetworkSaveStatus; |
871 | +virNetworkSetBridgeMacAddr; |
872 | +virNetworkSetBridgeName; |
873 | +virPortGroupFindByName; |
874 | + |
875 | + |
876 | +# node_device_conf.h |
877 | +virNodeDevCapTypeFromString; |
878 | +virNodeDevCapTypeToString; |
879 | +virNodeDevCapsDefFree; |
880 | +virNodeDeviceAssignDef; |
881 | +virNodeDeviceDefFormat; |
882 | +virNodeDeviceDefFree; |
883 | +virNodeDeviceDefParseFile; |
884 | +virNodeDeviceDefParseNode; |
885 | +virNodeDeviceDefParseString; |
886 | +virNodeDeviceFindByName; |
887 | +virNodeDeviceFindBySysfsPath; |
888 | +virNodeDeviceGetParentHost; |
889 | +virNodeDeviceGetWWNs; |
890 | +virNodeDeviceHasCap; |
891 | +virNodeDeviceList; |
892 | +virNodeDeviceObjListFree; |
893 | +virNodeDeviceObjLock; |
894 | +virNodeDeviceObjRemove; |
895 | +virNodeDeviceObjUnlock; |
896 | + |
897 | + |
898 | +# nodeinfo.h |
899 | +nodeCapsInitNUMA; |
900 | +nodeGetCPUBitmap; |
901 | +nodeGetCPUCount; |
902 | +nodeGetCPUMap; |
903 | +nodeGetCPUStats; |
904 | +nodeGetCellsFreeMemory; |
905 | +nodeGetFreeMemory; |
906 | +nodeGetInfo; |
907 | +nodeGetMemoryParameters; |
908 | +nodeGetMemoryStats; |
909 | +nodeSetMemoryParameters; |
910 | + |
911 | + |
912 | +# nwfilter_conf.h |
913 | +virNWFilterCallbackDriversLock; |
914 | +virNWFilterCallbackDriversUnlock; |
915 | +virNWFilterChainSuffixTypeToString; |
916 | +virNWFilterConfLayerInit; |
917 | +virNWFilterConfLayerShutdown; |
918 | +virNWFilterDefFormat; |
919 | +virNWFilterDefFree; |
920 | +virNWFilterDefParseString; |
921 | +virNWFilterInstFiltersOnAllVMs; |
922 | +virNWFilterJumpTargetTypeToString; |
923 | +virNWFilterLoadAllConfigs; |
924 | +virNWFilterLockFilterUpdates; |
925 | +virNWFilterObjAssignDef; |
926 | +virNWFilterObjDeleteDef; |
927 | +virNWFilterObjFindByName; |
928 | +virNWFilterObjFindByUUID; |
929 | +virNWFilterObjListFree; |
930 | +virNWFilterObjLock; |
931 | +virNWFilterObjRemove; |
932 | +virNWFilterObjSaveDef; |
933 | +virNWFilterObjUnlock; |
934 | +virNWFilterPrintStateMatchFlags; |
935 | +virNWFilterPrintTCPFlags; |
936 | +virNWFilterRegisterCallbackDriver; |
937 | +virNWFilterRuleActionTypeToString; |
938 | +virNWFilterRuleDirectionTypeToString; |
939 | +virNWFilterRuleProtocolTypeToString; |
940 | +virNWFilterTestUnassignDef; |
941 | +virNWFilterUnRegisterCallbackDriver; |
942 | +virNWFilterUnlockFilterUpdates; |
943 | + |
944 | + |
945 | +# nwfilter_ipaddrmap |
946 | +virNWFilterIPAddrMapAddIPAddr; |
947 | +virNWFilterIPAddrMapDelIPAddr; |
948 | +virNWFilterIPAddrMapGetIPAddr; |
949 | +virNWFilterIPAddrMapInit; |
950 | +virNWFilterIPAddrMapShutdown; |
951 | + |
952 | + |
953 | +# nwfilter_params.h |
954 | +virNWFilterHashTableCreate; |
955 | +virNWFilterHashTableFree; |
956 | +virNWFilterHashTablePut; |
957 | +virNWFilterHashTablePutAll; |
958 | +virNWFilterHashTableRemoveEntry; |
959 | +virNWFilterVarAccessGetVarName; |
960 | +virNWFilterVarAccessIsAvailable; |
961 | +virNWFilterVarAccessPrint; |
962 | +virNWFilterVarCombIterCreate; |
963 | +virNWFilterVarCombIterFree; |
964 | +virNWFilterVarCombIterGetVarValue; |
965 | +virNWFilterVarCombIterNext; |
966 | +virNWFilterVarValueAddValue; |
967 | +virNWFilterVarValueCopy; |
968 | +virNWFilterVarValueCreateSimple; |
969 | +virNWFilterVarValueCreateSimpleCopyValue; |
970 | +virNWFilterVarValueDelValue; |
971 | +virNWFilterVarValueFree; |
972 | +virNWFilterVarValueGetCardinality; |
973 | +virNWFilterVarValueGetNthValue; |
974 | +virNWFilterVarValueGetSimple; |
975 | + |
976 | + |
977 | +# pci.h |
978 | +pciConfigAddressToSysfsFile; |
979 | +pciDettachDevice; |
980 | +pciDeviceFileIterate; |
981 | +pciDeviceGetManaged; |
982 | +pciDeviceGetName; |
983 | +pciDeviceGetRemoveSlot; |
984 | +pciDeviceGetReprobe; |
985 | +pciDeviceGetUnbindFromStub; |
986 | +pciDeviceGetUsedBy; |
987 | +pciDeviceGetVirtualFunctionInfo; |
988 | +pciDeviceIsAssignable; |
989 | +pciDeviceIsVirtualFunction; |
990 | +pciDeviceListAdd; |
991 | +pciDeviceListCount; |
992 | +pciDeviceListDel; |
993 | +pciDeviceListFind; |
994 | +pciDeviceListFree; |
995 | +pciDeviceListGet; |
996 | +pciDeviceListNew; |
997 | +pciDeviceListSteal; |
998 | +pciDeviceNetName; |
999 | +pciDeviceReAttachInit; |
1000 | +pciDeviceSetManaged; |
1001 | +pciDeviceSetRemoveSlot; |
1002 | +pciDeviceSetReprobe; |
1003 | +pciDeviceSetUnbindFromStub; |
1004 | +pciDeviceSetUsedBy; |
1005 | +pciFreeDevice; |
1006 | +pciGetDevice; |
1007 | +pciGetPhysicalFunction; |
1008 | +pciGetVirtualFunctionIndex; |
1009 | +pciGetVirtualFunctions; |
1010 | +pciReAttachDevice; |
1011 | +pciResetDevice; |
1012 | +pciWaitForDeviceCleanup; |
1013 | + |
1014 | + |
1015 | +# processinfo.h |
1016 | +virProcessInfoGetAffinity; |
1017 | +virProcessInfoSetAffinity; |
1018 | + |
1019 | + |
1020 | +# secret_conf.h |
1021 | +virSecretDefFormat; |
1022 | +virSecretDefFree; |
1023 | +virSecretDefParseFile; |
1024 | +virSecretDefParseString; |
1025 | +virSecretUsageTypeTypeFromString; |
1026 | +virSecretUsageTypeTypeToString; |
1027 | + |
1028 | + |
1029 | +# security_driver.h |
1030 | +virSecurityDriverLookup; |
1031 | + |
1032 | + |
1033 | +# security_manager.h |
1034 | +virSecurityManagerClearSocketLabel; |
1035 | +virSecurityManagerFree; |
1036 | +virSecurityManagerGenLabel; |
1037 | +virSecurityManagerGetDOI; |
1038 | +virSecurityManagerGetModel; |
1039 | +virSecurityManagerGetNested; |
1040 | +virSecurityManagerGetProcessLabel; |
1041 | +virSecurityManagerNew; |
1042 | +virSecurityManagerNewStack; |
1043 | +virSecurityManagerNewDAC; |
1044 | +virSecurityManagerReleaseLabel; |
1045 | +virSecurityManagerReserveLabel; |
1046 | +virSecurityManagerRestoreImageLabel; |
1047 | +virSecurityManagerRestoreAllLabel; |
1048 | +virSecurityManagerRestoreHostdevLabel; |
1049 | +virSecurityManagerRestoreSavedStateLabel; |
1050 | +virSecurityManagerSetAllLabel; |
1051 | +virSecurityManagerSetDaemonSocketLabel; |
1052 | +virSecurityManagerSetImageFDLabel; |
1053 | +virSecurityManagerSetImageLabel; |
1054 | +virSecurityManagerSetHostdevLabel; |
1055 | +virSecurityManagerSetProcessLabel; |
1056 | +virSecurityManagerSetSavedStateLabel; |
1057 | +virSecurityManagerSetSocketLabel; |
1058 | +virSecurityManagerSetTapFDLabel; |
1059 | +virSecurityManagerStackAddNested; |
1060 | +virSecurityManagerVerify; |
1061 | +virSecurityManagerGetMountOptions; |
1062 | + |
1063 | +# sexpr.h |
1064 | +sexpr_append; |
1065 | +sexpr_cons; |
1066 | +sexpr_float; |
1067 | +sexpr_fmt_node; |
1068 | +sexpr_free; |
1069 | +sexpr_has; |
1070 | +sexpr_int; |
1071 | +sexpr_lookup; |
1072 | +sexpr_nil; |
1073 | +sexpr_node; |
1074 | +sexpr_node_copy; |
1075 | +sexpr_string; |
1076 | +sexpr_u64; |
1077 | +sexpr2string; |
1078 | +string2sexpr; |
1079 | + |
1080 | + |
1081 | +# snapshot_conf.h |
1082 | +virDomainListSnapshots; |
1083 | +virDomainSnapshotAlignDisks; |
1084 | +virDomainSnapshotAssignDef; |
1085 | +virDomainSnapshotDefFormat; |
1086 | +virDomainSnapshotDefFree; |
1087 | +virDomainSnapshotDefParseString; |
1088 | +virDomainSnapshotDropParent; |
1089 | +virDomainSnapshotFindByName; |
1090 | +virDomainSnapshotForEach; |
1091 | +virDomainSnapshotForEachChild; |
1092 | +virDomainSnapshotForEachDescendant; |
1093 | +virDomainSnapshotLocationTypeFromString; |
1094 | +virDomainSnapshotLocationTypeToString; |
1095 | +virDomainSnapshotObjListGetNames; |
1096 | +virDomainSnapshotObjListNum; |
1097 | +virDomainSnapshotObjListRemove; |
1098 | +virDomainSnapshotStateTypeFromString; |
1099 | +virDomainSnapshotStateTypeToString; |
1100 | +virDomainSnapshotUpdateRelations; |
1101 | + |
1102 | + |
1103 | +# storage_conf.h |
1104 | +virStoragePartedFsTypeTypeToString; |
1105 | +virStoragePoolDefFormat; |
1106 | +virStoragePoolDefFree; |
1107 | +virStoragePoolDefParseFile; |
1108 | +virStoragePoolDefParseNode; |
1109 | +virStoragePoolDefParseSourceString; |
1110 | +virStoragePoolDefParseString; |
1111 | +virStoragePoolFormatDiskTypeToString; |
1112 | +virStoragePoolFormatFileSystemNetTypeToString; |
1113 | +virStoragePoolFormatFileSystemTypeToString; |
1114 | +virStoragePoolList; |
1115 | +virStoragePoolLoadAllConfigs; |
1116 | +virStoragePoolObjAssignDef; |
1117 | +virStoragePoolObjClearVols; |
1118 | +virStoragePoolObjDeleteDef; |
1119 | +virStoragePoolObjFindByName; |
1120 | +virStoragePoolObjFindByUUID; |
1121 | +virStoragePoolObjIsDuplicate; |
1122 | +virStoragePoolObjListFree; |
1123 | +virStoragePoolObjLock; |
1124 | +virStoragePoolObjRemove; |
1125 | +virStoragePoolObjSaveDef; |
1126 | +virStoragePoolObjUnlock; |
1127 | +virStoragePoolSourceClear; |
1128 | +virStoragePoolSourceFindDuplicate; |
1129 | +virStoragePoolSourceFindDuplicateDevices; |
1130 | +virStoragePoolSourceFree; |
1131 | +virStoragePoolSourceListFormat; |
1132 | +virStoragePoolSourceListNewSource; |
1133 | +virStoragePoolTypeFromString; |
1134 | +virStorageVolDefFindByKey; |
1135 | +virStorageVolDefFindByName; |
1136 | +virStorageVolDefFindByPath; |
1137 | +virStorageVolDefFormat; |
1138 | +virStorageVolDefFree; |
1139 | +virStorageVolDefParseFile; |
1140 | +virStorageVolDefParseNode; |
1141 | +virStorageVolDefParseString; |
1142 | + |
1143 | + |
1144 | +# storage_encryption_conf.h |
1145 | +virStorageEncryptionFormat; |
1146 | +virStorageEncryptionFree; |
1147 | +virStorageEncryptionParseNode; |
1148 | +virStorageGenerateQcowPassphrase; |
1149 | + |
1150 | + |
1151 | +# storage_file.h |
1152 | +virStorageFileChainLookup; |
1153 | +virStorageFileFormatTypeFromString; |
1154 | +virStorageFileFormatTypeToString; |
1155 | +virStorageFileFreeMetadata; |
1156 | +virStorageFileGetMetadata; |
1157 | +virStorageFileGetMetadataFromFD; |
1158 | +virStorageFileIsClusterFS; |
1159 | +virStorageFileIsSharedFS; |
1160 | +virStorageFileIsSharedFSType; |
1161 | +virStorageFileProbeFormat; |
1162 | +virStorageFileProbeFormatFromFD; |
1163 | +virStorageFileResize; |
1164 | + |
1165 | +# sysinfo.h |
1166 | +virSysinfoDefFree; |
1167 | +virSysinfoFormat; |
1168 | +virSysinfoRead; |
1169 | + |
1170 | + |
1171 | +# threadpool.h |
1172 | +virThreadPoolFree; |
1173 | +virThreadPoolNew; |
1174 | +virThreadPoolSendJob; |
1175 | +virThreadPoolGetMinWorkers; |
1176 | +virThreadPoolGetMaxWorkers; |
1177 | +virThreadPoolGetPriorityWorkers; |
1178 | + |
1179 | + |
1180 | +# threads.h |
1181 | +virCondBroadcast; |
1182 | +virCondDestroy; |
1183 | +virCondInit; |
1184 | +virCondSignal; |
1185 | +virCondWait; |
1186 | +virCondWaitUntil; |
1187 | +virMutexDestroy; |
1188 | +virMutexInit; |
1189 | +virMutexInitRecursive; |
1190 | +virMutexLock; |
1191 | +virMutexUnlock; |
1192 | +virOnce; |
1193 | +virThreadCreate; |
1194 | +virThreadID; |
1195 | +virThreadInitialize; |
1196 | +virThreadIsSelf; |
1197 | +virThreadJoin; |
1198 | +virThreadSelf; |
1199 | +virThreadSelfID; |
1200 | + |
1201 | + |
1202 | +# usb.h |
1203 | +usbDeviceFileIterate; |
1204 | +usbDeviceGetBus; |
1205 | +usbDeviceGetDevno; |
1206 | +usbDeviceGetName; |
1207 | +usbDeviceGetUsedBy; |
1208 | +usbDeviceListAdd; |
1209 | +usbDeviceListCount; |
1210 | +usbDeviceListDel; |
1211 | +usbDeviceListFind; |
1212 | +usbDeviceListFree; |
1213 | +usbDeviceListGet; |
1214 | +usbDeviceListNew; |
1215 | +usbDeviceListSteal; |
1216 | +usbDeviceSetUsedBy; |
1217 | +usbFindDevice; |
1218 | +usbFindDeviceByBus; |
1219 | +usbFindDeviceByVendor; |
1220 | +usbFreeDevice; |
1221 | +usbGetDevice; |
1222 | + |
1223 | + |
1224 | +# util.h |
1225 | +saferead; |
1226 | +safewrite; |
1227 | +safezero; |
1228 | +virArgvToString; |
1229 | +virAsprintf; |
1230 | +virBuildPathInternal; |
1231 | +virDirCreate; |
1232 | +virDoubleToStr; |
1233 | +virEnumFromString; |
1234 | +virEnumToString; |
1235 | +virFileAbsPath; |
1236 | +virFileAccessibleAs; |
1237 | +virFileBuildPath; |
1238 | +virFileExists; |
1239 | +virFileFindMountPoint; |
1240 | +virFileHasSuffix; |
1241 | +virFileIsAbsPath; |
1242 | +virFileIsExecutable; |
1243 | +virFileIsLink; |
1244 | +virFileIsDir; |
1245 | +virFileLinkPointsTo; |
1246 | +virFileLock; |
1247 | +virFileMakePath; |
1248 | +virFileMakePathWithMode; |
1249 | +virFileMatchesNameSuffix; |
1250 | +virFileOpenAs; |
1251 | +virFileOpenTty; |
1252 | +virFileReadAll; |
1253 | +virFileReadLimFD; |
1254 | +virFileResolveAllLinks; |
1255 | +virFileResolveLink; |
1256 | +virFileSanitizePath; |
1257 | +virFileSkipRoot; |
1258 | +virFileStripSuffix; |
1259 | +virFileUnlock; |
1260 | +virFileWaitForDevices; |
1261 | +virFileWriteStr; |
1262 | +virFindFileInPath; |
1263 | +virFormatIntDecimal; |
1264 | +virGetGroupID; |
1265 | +virGetGroupName; |
1266 | +virGetHostname; |
1267 | +virGetUserDirectory; |
1268 | +virGetUserConfigDirectory; |
1269 | +virGetUserCacheDirectory; |
1270 | +virGetUserRuntimeDirectory; |
1271 | +virGetUserID; |
1272 | +virGetUserName; |
1273 | +virHexToBin; |
1274 | +virIndexToDiskName; |
1275 | +virIsDevMapperDevice; |
1276 | +virParseNumber; |
1277 | +virParseVersionString; |
1278 | +virPipeReadUntilEOF; |
1279 | +virScaleInteger; |
1280 | +virSetBlocking; |
1281 | +virSetCloseExec; |
1282 | +virSetInherit; |
1283 | +virSetNonBlock; |
1284 | +virSetUIDGID; |
1285 | +virSkipSpaces; |
1286 | +virSkipSpacesAndBackslash; |
1287 | +virSkipSpacesBackwards; |
1288 | +virStrToDouble; |
1289 | +virStrToLong_i; |
1290 | +virStrToLong_l; |
1291 | +virStrToLong_ll; |
1292 | +virStrToLong_ui; |
1293 | +virStrToLong_ul; |
1294 | +virStrToLong_ull; |
1295 | +virStrcpy; |
1296 | +virStrncpy; |
1297 | +virTrimSpaces; |
1298 | +virValidateWWN; |
1299 | +virVasprintf; |
1300 | + |
1301 | + |
1302 | +# uuid.h |
1303 | +virGetHostUUID; |
1304 | +virSetHostUUIDStr; |
1305 | +virUUIDFormat; |
1306 | +virUUIDGenerate; |
1307 | +virUUIDIsValid; |
1308 | +virUUIDParse; |
1309 | + |
1310 | + |
1311 | +# virauth.h |
1312 | +virAuthGetConfigFilePath; |
1313 | +virAuthGetPassword; |
1314 | +virAuthGetUsername; |
1315 | + |
1316 | + |
1317 | +# virauthconfig.h |
1318 | +virAuthConfigFree; |
1319 | +virAuthConfigLookup; |
1320 | +virAuthConfigNew; |
1321 | +virAuthConfigNewData; |
1322 | + |
1323 | + |
1324 | +# viraudit.h |
1325 | +virAuditClose; |
1326 | +virAuditEncode; |
1327 | +virAuditLog; |
1328 | +virAuditOpen; |
1329 | +virAuditSend; |
1330 | + |
1331 | + |
1332 | +# virconsole.h |
1333 | +virConsoleAlloc; |
1334 | +virConsoleFree; |
1335 | +virConsoleOpen; |
1336 | + |
1337 | + |
1338 | +# virdbus.h |
1339 | +virDBusGetSystemBus; |
1340 | + |
1341 | + |
1342 | +# virfile.h |
1343 | +virFileLoopDeviceAssociate; |
1344 | +virFileClose; |
1345 | +virFileDirectFdFlag; |
1346 | +virFileWrapperFdCatchError; |
1347 | +virFileWrapperFdClose; |
1348 | +virFileWrapperFdFree; |
1349 | +virFileWrapperFdNew; |
1350 | +virFileFclose; |
1351 | +virFileFdopen; |
1352 | +virFileRewrite; |
1353 | +virFileTouch; |
1354 | +virFileUpdatePerm; |
1355 | + |
1356 | + |
1357 | +# virkeycode.h |
1358 | +virKeycodeSetTypeFromString; |
1359 | +virKeycodeSetTypeToString; |
1360 | +virKeycodeValueFromString; |
1361 | +virKeycodeValueTranslate; |
1362 | + |
1363 | + |
1364 | +# virkeyfile.h |
1365 | +virKeyFileNew; |
1366 | +virKeyFileLoadFile; |
1367 | +virKeyFileLoadData; |
1368 | +virKeyFileFree; |
1369 | +virKeyFileHasValue; |
1370 | +virKeyFileHasGroup; |
1371 | +virKeyFileGetValueString; |
1372 | + |
1373 | + |
1374 | +# virlockspace.h |
1375 | +virLockSpaceAcquireResource; |
1376 | +virLockSpaceCreateResource; |
1377 | +virLockSpaceDeleteResource; |
1378 | +virLockSpaceFree; |
1379 | +virLockSpaceGetDirectory; |
1380 | +virLockSpaceNew; |
1381 | +virLockSpaceNewPostExecRestart; |
1382 | +virLockSpacePreExecRestart; |
1383 | +virLockSpaceReleaseResource; |
1384 | +virLockSpaceReleaseResourcesForOwner; |
1385 | + |
1386 | + |
1387 | +# virmacaddr.h |
1388 | +virMacAddrCmp; |
1389 | +virMacAddrCmpRaw; |
1390 | +virMacAddrCompare; |
1391 | +virMacAddrFormat; |
1392 | +virMacAddrGenerate; |
1393 | +virMacAddrGetRaw; |
1394 | +virMacAddrIsBroadcastRaw; |
1395 | +virMacAddrIsMulticast; |
1396 | +virMacAddrIsUnicast; |
1397 | +virMacAddrParse; |
1398 | +virMacAddrSet; |
1399 | +virMacAddrSetRaw; |
1400 | + |
1401 | + |
1402 | +# virnetclient.h |
1403 | +virNetClientAddProgram; |
1404 | +virNetClientAddStream; |
1405 | +virNetClientClose; |
1406 | +virNetClientDupFD; |
1407 | +virNetClientGetFD; |
1408 | +virNetClientGetTLSKeySize; |
1409 | +virNetClientHasPassFD; |
1410 | +virNetClientIsEncrypted; |
1411 | +virNetClientIsOpen; |
1412 | +virNetClientKeepAliveIsSupported; |
1413 | +virNetClientKeepAliveStart; |
1414 | +virNetClientKeepAliveStop; |
1415 | +virNetClientLocalAddrString; |
1416 | +virNetClientNewExternal; |
1417 | +virNetClientNewLibSSH2; |
1418 | +virNetClientNewSSH; |
1419 | +virNetClientNewTCP; |
1420 | +virNetClientNewUNIX; |
1421 | +virNetClientRegisterAsyncIO; |
1422 | +virNetClientRegisterKeepAlive; |
1423 | +virNetClientRemoteAddrString; |
1424 | +virNetClientRemoveStream; |
1425 | +virNetClientSendNoReply; |
1426 | +virNetClientSendNonBlock; |
1427 | +virNetClientSendWithReply; |
1428 | +virNetClientSendWithReplyStream; |
1429 | +virNetClientSetCloseCallback; |
1430 | +virNetClientSetTLSSession; |
1431 | + |
1432 | + |
1433 | +# virnetclientprogram.h |
1434 | +virNetClientProgramCall; |
1435 | +virNetClientProgramDispatch; |
1436 | +virNetClientProgramGetProgram; |
1437 | +virNetClientProgramGetVersion; |
1438 | +virNetClientProgramMatches; |
1439 | +virNetClientProgramNew; |
1440 | + |
1441 | + |
1442 | +# virnetclientstream.h |
1443 | +virNetClientStreamEOF; |
1444 | +virNetClientStreamEventAddCallback; |
1445 | +virNetClientStreamEventRemoveCallback; |
1446 | +virNetClientStreamEventUpdateCallback; |
1447 | +virNetClientStreamMatches; |
1448 | +virNetClientStreamNew; |
1449 | +virNetClientStreamQueuePacket; |
1450 | +virNetClientStreamRaiseError; |
1451 | +virNetClientStreamRecvPacket; |
1452 | +virNetClientStreamSendPacket; |
1453 | +virNetClientStreamSetError; |
1454 | + |
1455 | + |
1456 | +# virnetdev.h |
1457 | +virNetDevClearIPv4Address; |
1458 | +virNetDevExists; |
1459 | +virNetDevGetIPv4Address; |
1460 | +virNetDevGetIndex; |
1461 | +virNetDevGetMAC; |
1462 | +virNetDevGetMTU; |
1463 | +virNetDevGetPhysicalFunction; |
1464 | +virNetDevGetVLanID; |
1465 | +virNetDevGetVirtualFunctionIndex; |
1466 | +virNetDevGetVirtualFunctionInfo; |
1467 | +virNetDevGetVirtualFunctions; |
1468 | +virNetDevIsOnline; |
1469 | +virNetDevIsVirtualFunction; |
1470 | +virNetDevLinkDump; |
1471 | +virNetDevReplaceMacAddress; |
1472 | +virNetDevReplaceNetConfig; |
1473 | +virNetDevRestoreMacAddress; |
1474 | +virNetDevRestoreNetConfig; |
1475 | +virNetDevSetIPv4Address; |
1476 | +virNetDevSetMAC; |
1477 | +virNetDevSetMTU; |
1478 | +virNetDevSetMTUFromDevice; |
1479 | +virNetDevSetName; |
1480 | +virNetDevSetNamespace; |
1481 | +virNetDevSetOnline; |
1482 | +virNetDevValidateConfig; |
1483 | + |
1484 | + |
1485 | +# virnetdevbandwidth.h |
1486 | +virNetDevBandwidthClear; |
1487 | +virNetDevBandwidthCopy; |
1488 | +virNetDevBandwidthEqual; |
1489 | +virNetDevBandwidthFree; |
1490 | +virNetDevBandwidthSet; |
1491 | + |
1492 | + |
1493 | +# virnetdevbridge.h |
1494 | +virNetDevBridgeAddPort; |
1495 | +virNetDevBridgeCreate; |
1496 | +virNetDevBridgeDelete; |
1497 | +virNetDevBridgeGetSTP; |
1498 | +virNetDevBridgeGetSTPDelay; |
1499 | +virNetDevBridgeRemovePort; |
1500 | +virNetDevBridgeSetSTP; |
1501 | +virNetDevBridgeSetSTPDelay; |
1502 | + |
1503 | + |
1504 | +# virnetdevmacvlan.h |
1505 | +virNetDevMacVLanCreate; |
1506 | +virNetDevMacVLanDelete; |
1507 | +virNetDevMacVLanCreateWithVPortProfile; |
1508 | +virNetDevMacVLanDeleteWithVPortProfile; |
1509 | +virNetDevMacVLanRestartWithVPortProfile; |
1510 | +virNetDevMacVLanVPortProfileRegisterCallback; |
1511 | + |
1512 | + |
1513 | +# virnetdevopenvswitch.h |
1514 | +virNetDevOpenvswitchAddPort; |
1515 | +virNetDevOpenvswitchGetMigrateData; |
1516 | +virNetDevOpenvswitchRemovePort; |
1517 | +virNetDevOpenvswitchSetMigrateData; |
1518 | + |
1519 | + |
1520 | +# virnetdevtap.h |
1521 | +virNetDevTapCreate; |
1522 | +virNetDevTapCreateInBridgePort; |
1523 | +virNetDevTapDelete; |
1524 | + |
1525 | + |
1526 | +# virnetdevveth.h |
1527 | +virNetDevVethCreate; |
1528 | +virNetDevVethDelete; |
1529 | + |
1530 | + |
1531 | +# virnetdevvlan.h |
1532 | +virNetDevVlanClear; |
1533 | +virNetDevVlanCopy; |
1534 | +virNetDevVlanEqual; |
1535 | +virNetDevVlanFree; |
1536 | + |
1537 | +# virnetdevvportprofile.h |
1538 | +virNetDevVPortProfileAssociate; |
1539 | +virNetDevVPortProfileCheckComplete; |
1540 | +virNetDevVPortProfileCheckNoExtras; |
1541 | +virNetDevVPortProfileDisassociate; |
1542 | +virNetDevVPortProfileEqual; |
1543 | +virNetDevVPortProfileMerge3; |
1544 | +virNetDevVPortProfileOpTypeFromString; |
1545 | +virNetDevVPortProfileOpTypeToString; |
1546 | + |
1547 | + |
1548 | +#virnetlink.h |
1549 | +virNetlinkCommand; |
1550 | +virNetlinkEventAddClient; |
1551 | +virNetlinkEventRemoveClient; |
1552 | +virNetlinkEventServiceIsRunning; |
1553 | +virNetlinkEventServiceLocalPid; |
1554 | +virNetlinkEventServiceStop; |
1555 | +virNetlinkEventServiceStopAll; |
1556 | +virNetlinkEventServiceStart; |
1557 | +virNetlinkShutdown; |
1558 | +virNetlinkStartup; |
1559 | + |
1560 | + |
1561 | +# virnetmessage.h |
1562 | +virNetMessageClear; |
1563 | +virNetMessageDecodeHeader; |
1564 | +virNetMessageDecodeNumFDs; |
1565 | +virNetMessageDecodeLength; |
1566 | +virNetMessageDecodePayload; |
1567 | +virNetMessageDupFD; |
1568 | +virNetMessageEncodeHeader; |
1569 | +virNetMessageEncodePayload; |
1570 | +virNetMessageEncodePayloadRaw; |
1571 | +virNetMessageEncodeNumFDs; |
1572 | +virNetMessageFree; |
1573 | +virNetMessageNew; |
1574 | +virNetMessageQueuePush; |
1575 | +virNetMessageQueueServe; |
1576 | +virNetMessageSaveError; |
1577 | +xdr_virNetMessageError; |
1578 | + |
1579 | + |
1580 | +# virnetserver.h |
1581 | +virNetServerAddProgram; |
1582 | +virNetServerAddService; |
1583 | +virNetServerAddSignalHandler; |
1584 | +virNetServerAutoShutdown; |
1585 | +virNetServerClose; |
1586 | +virNetServerIsPrivileged; |
1587 | +virNetServerKeepAliveRequired; |
1588 | +virNetServerNew; |
1589 | +virNetServerNewPostExecRestart; |
1590 | +virNetServerPreExecRestart; |
1591 | +virNetServerQuit; |
1592 | +virNetServerRun; |
1593 | +virNetServerSetTLSContext; |
1594 | +virNetServerUpdateServices; |
1595 | + |
1596 | + |
1597 | +# virnetserverclient.h |
1598 | +virNetServerClientAddFilter; |
1599 | +virNetServerClientClose; |
1600 | +virNetServerClientDelayedClose; |
1601 | +virNetServerClientGetAuth; |
1602 | +virNetServerClientGetFD; |
1603 | +virNetServerClientGetIdentity; |
1604 | +virNetServerClientGetPrivateData; |
1605 | +virNetServerClientGetReadonly; |
1606 | +virNetServerClientGetTLSKeySize; |
1607 | +virNetServerClientGetUNIXIdentity; |
1608 | +virNetServerClientHasTLSSession; |
1609 | +virNetServerClientImmediateClose; |
1610 | +virNetServerClientInit; |
1611 | +virNetServerClientInitKeepAlive; |
1612 | +virNetServerClientIsClosed; |
1613 | +virNetServerClientIsSecure; |
1614 | +virNetServerClientLocalAddrString; |
1615 | +virNetServerClientNeedAuth; |
1616 | +virNetServerClientNew; |
1617 | +virNetServerClientNewPostExecRestart; |
1618 | +virNetServerClientPreExecRestart; |
1619 | +virNetServerClientRemoteAddrString; |
1620 | +virNetServerClientRemoveFilter; |
1621 | +virNetServerClientSendMessage; |
1622 | +virNetServerClientSetCloseHook; |
1623 | +virNetServerClientSetDispatcher; |
1624 | +virNetServerClientSetIdentity; |
1625 | +virNetServerClientStartKeepAlive; |
1626 | +virNetServerClientWantClose; |
1627 | + |
1628 | + |
1629 | +# virnetservermdns.h |
1630 | +virNetServerMDNSAddEntry; |
1631 | +virNetServerMDNSAddGroup; |
1632 | +virNetServerMDNSEntryFree; |
1633 | +virNetServerMDNSFree; |
1634 | +virNetServerMDNSGroupFree; |
1635 | +virNetServerMDNSNew; |
1636 | +virNetServerMDNSRemoveEntry; |
1637 | +virNetServerMDNSRemoveGroup; |
1638 | +virNetServerMDNSStart; |
1639 | +virNetServerMDNSStop; |
1640 | + |
1641 | + |
1642 | +# virnetserverprogram.h |
1643 | +virNetServerProgramDispatch; |
1644 | +virNetServerProgramGetID; |
1645 | +virNetServerProgramGetPriority; |
1646 | +virNetServerProgramGetVersion; |
1647 | +virNetServerProgramMatches; |
1648 | +virNetServerProgramNew; |
1649 | +virNetServerProgramSendReplyError; |
1650 | +virNetServerProgramSendStreamData; |
1651 | +virNetServerProgramSendStreamError; |
1652 | +virNetServerProgramUnknownError; |
1653 | + |
1654 | + |
1655 | +# virnetserverservice.h |
1656 | +virNetServerServiceClose; |
1657 | +virNetServerServiceGetAuth; |
1658 | +virNetServerServiceGetMaxRequests; |
1659 | +virNetServerServiceGetPort; |
1660 | +virNetServerServiceGetTLSContext; |
1661 | +virNetServerServiceIsReadonly; |
1662 | +virNetServerServiceNewFD; |
1663 | +virNetServerServiceNewPostExecRestart; |
1664 | +virNetServerServiceNewTCP; |
1665 | +virNetServerServiceNewUNIX; |
1666 | +virNetServerServicePreExecRestart; |
1667 | +virNetServerServiceSetDispatcher; |
1668 | +virNetServerServiceToggle; |
1669 | + |
1670 | + |
1671 | +# virnetsocket.h |
1672 | +virNetSocketAccept; |
1673 | +virNetSocketAddIOCallback; |
1674 | +virNetSocketClose; |
1675 | +virNetSocketDupFD; |
1676 | +virNetSocketGetFD; |
1677 | +virNetSocketGetPort; |
1678 | +virNetSocketGetUNIXIdentity; |
1679 | +virNetSocketHasCachedData; |
1680 | +virNetSocketHasPassFD; |
1681 | +virNetSocketHasPendingData; |
1682 | +virNetSocketIsLocal; |
1683 | +virNetSocketListen; |
1684 | +virNetSocketLocalAddrString; |
1685 | +virNetSocketNewConnectCommand; |
1686 | +virNetSocketNewConnectExternal; |
1687 | +virNetSocketNewConnectLibSSH2; |
1688 | +virNetSocketNewConnectSSH; |
1689 | +virNetSocketNewConnectTCP; |
1690 | +virNetSocketNewConnectUNIX; |
1691 | +virNetSocketNewListenFD; |
1692 | +virNetSocketNewListenTCP; |
1693 | +virNetSocketNewListenUNIX; |
1694 | +virNetSocketNewPostExecRestart; |
1695 | +virNetSocketPreExecRestart; |
1696 | +virNetSocketRead; |
1697 | +virNetSocketRecvFD; |
1698 | +virNetSocketRemoteAddrString; |
1699 | +virNetSocketRemoveIOCallback; |
1700 | +virNetSocketSendFD; |
1701 | +virNetSocketSetBlocking; |
1702 | +virNetSocketSetTLSSession; |
1703 | +virNetSocketUpdateIOCallback; |
1704 | +virNetSocketWrite; |
1705 | + |
1706 | + |
1707 | +# virnettlscontext.h |
1708 | +virNetTLSContextCheckCertificate; |
1709 | +virNetTLSContextNewClient; |
1710 | +virNetTLSContextNewClientPath; |
1711 | +virNetTLSContextNewServer; |
1712 | +virNetTLSContextNewServerPath; |
1713 | +virNetTLSInit; |
1714 | +virNetTLSSessionGetHandshakeStatus; |
1715 | +virNetTLSSessionGetKeySize; |
1716 | +virNetTLSSessionHandshake; |
1717 | +virNetTLSSessionNew; |
1718 | +virNetTLSSessionRead; |
1719 | +virNetTLSSessionSetIOCallbacks; |
1720 | +virNetTLSSessionWrite; |
1721 | + |
1722 | + |
1723 | +# virnodesuspend.h |
1724 | +nodeSuspendForDuration; |
1725 | +virNodeSuspendGetTargetMask; |
1726 | + |
1727 | + |
1728 | +# virobject.h |
1729 | +virClassName; |
1730 | +virClassNew; |
1731 | +virObjectFreeCallback; |
1732 | +virObjectIsClass; |
1733 | +virObjectNew; |
1734 | +virObjectRef; |
1735 | +virObjectUnref; |
1736 | + |
1737 | + |
1738 | +# virpidfile.h |
1739 | +virPidFileAcquire; |
1740 | +virPidFileAcquirePath; |
1741 | +virPidFileBuildPath; |
1742 | +virPidFileRead; |
1743 | +virPidFileReadIfAlive; |
1744 | +virPidFileReadPath; |
1745 | +virPidFileReadPathIfAlive; |
1746 | +virPidFileRelease; |
1747 | +virPidFileReleasePath; |
1748 | +virPidFileWrite; |
1749 | +virPidFileWritePath; |
1750 | +virPidFileDelete; |
1751 | +virPidFileDeletePath; |
1752 | + |
1753 | + |
1754 | +# virprocess.h |
1755 | +virProcessAbort; |
1756 | +virProcessKill; |
1757 | +virProcessKillPainfully; |
1758 | +virProcessTranslateStatus; |
1759 | +virProcessWait; |
1760 | + |
1761 | + |
1762 | +# virrandom.h |
1763 | +virRandom; |
1764 | +virRandomBits; |
1765 | +virRandomGenerateWWN; |
1766 | +virRandomInt; |
1767 | + |
1768 | + |
1769 | +# virsocketaddr.h |
1770 | +virSocketAddrBroadcast; |
1771 | +virSocketAddrBroadcastByPrefix; |
1772 | +virSocketAddrCheckNetmask; |
1773 | +virSocketAddrEqual; |
1774 | +virSocketAddrFormat; |
1775 | +virSocketAddrFormatFull; |
1776 | +virSocketAddrGetPort; |
1777 | +virSocketAddrGetRange; |
1778 | +virSocketAddrIsNetmask; |
1779 | +virSocketAddrMask; |
1780 | +virSocketAddrMaskByPrefix; |
1781 | +virSocketAddrParse; |
1782 | +virSocketAddrParseIPv4; |
1783 | +virSocketAddrParseIPv6; |
1784 | +virSocketAddrPrefixToNetmask; |
1785 | +virSocketAddrSetIPv4Addr; |
1786 | +virSocketAddrSetPort; |
1787 | + |
1788 | + |
1789 | +# virterror_internal.h |
1790 | +virDispatchError; |
1791 | +virErrorInitialize; |
1792 | +virRaiseErrorFull; |
1793 | +virReportErrorHelper; |
1794 | +virReportOOMErrorFull; |
1795 | +virReportSystemErrorFull; |
1796 | +virSetError; |
1797 | +virSetErrorLogPriorityFunc; |
1798 | +virStrerror; |
1799 | + |
1800 | + |
1801 | +# virtime.h |
1802 | +virTimeFieldsNow; |
1803 | +virTimeFieldsNowRaw; |
1804 | +virTimeFieldsThen; |
1805 | +virTimeFieldsThenRaw; |
1806 | +virTimeMillisNow; |
1807 | +virTimeMillisNowRaw; |
1808 | +virTimeStringNow; |
1809 | +virTimeStringNowRaw; |
1810 | +virTimeStringThen; |
1811 | +virTimeStringThenRaw; |
1812 | + |
1813 | + |
1814 | +# virtypedparam.h |
1815 | +virTypedParameterArrayClear; |
1816 | +virTypedParameterArrayValidate; |
1817 | +virTypedParameterAssign; |
1818 | +virTypedParameterAssignFromStr; |
1819 | + |
1820 | + |
1821 | +# viruri.h |
1822 | +virURIFormat; |
1823 | +virURIFormatParams; |
1824 | +virURIFree; |
1825 | +virURIParse; |
1826 | + |
1827 | + |
1828 | +# xml.h |
1829 | +virXMLChildElementCount; |
1830 | +virXMLParseHelper; |
1831 | +virXMLPickShellSafeComment; |
1832 | +virXMLPropString; |
1833 | +virXMLSaveFile; |
1834 | +virXPathBoolean; |
1835 | +virXPathInt; |
1836 | +virXPathLong; |
1837 | +virXPathLongHex; |
1838 | +virXPathLongLong; |
1839 | +virXPathNode; |
1840 | +virXPathNodeSet; |
1841 | +virXPathNumber; |
1842 | +virXPathString; |
1843 | +virXPathStringLimit; |
1844 | +virXPathUInt; |
1845 | +virXPathULong; |
1846 | +virXPathULongHex; |
1847 | +virXPathULongLong; |
1848 | |
1849 | === added directory '.pc/apparmor-allow-hugepages/src/qemu' |
1850 | === added file '.pc/apparmor-allow-hugepages/src/qemu/qemu_process.c' |
1851 | --- .pc/apparmor-allow-hugepages/src/qemu/qemu_process.c 1970-01-01 00:00:00 +0000 |
1852 | +++ .pc/apparmor-allow-hugepages/src/qemu/qemu_process.c 2012-12-11 20:02:29 +0000 |
1853 | @@ -0,0 +1,4474 @@ |
1854 | +/* |
1855 | + * qemu_process.h: QEMU process management |
1856 | + * |
1857 | + * Copyright (C) 2006-2012 Red Hat, Inc. |
1858 | + * |
1859 | + * This library is free software; you can redistribute it and/or |
1860 | + * modify it under the terms of the GNU Lesser General Public |
1861 | + * License as published by the Free Software Foundation; either |
1862 | + * version 2.1 of the License, or (at your option) any later version. |
1863 | + * |
1864 | + * This library is distributed in the hope that it will be useful, |
1865 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1866 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1867 | + * Lesser General Public License for more details. |
1868 | + * |
1869 | + * You should have received a copy of the GNU Lesser General Public |
1870 | + * License along with this library. If not, see |
1871 | + * <http://www.gnu.org/licenses/>. |
1872 | + * |
1873 | + */ |
1874 | + |
1875 | +#include <config.h> |
1876 | + |
1877 | +#include <fcntl.h> |
1878 | +#include <unistd.h> |
1879 | +#include <signal.h> |
1880 | +#include <sys/stat.h> |
1881 | +#include <sys/time.h> |
1882 | +#include <sys/resource.h> |
1883 | +#include <linux/capability.h> |
1884 | + |
1885 | +#include "qemu_process.h" |
1886 | +#include "qemu_domain.h" |
1887 | +#include "qemu_cgroup.h" |
1888 | +#include "qemu_capabilities.h" |
1889 | +#include "qemu_monitor.h" |
1890 | +#include "qemu_command.h" |
1891 | +#include "qemu_hostdev.h" |
1892 | +#include "qemu_hotplug.h" |
1893 | +#include "qemu_bridge_filter.h" |
1894 | +#include "qemu_migration.h" |
1895 | + |
1896 | +#if HAVE_NUMACTL |
1897 | +# define NUMA_VERSION1_COMPATIBILITY 1 |
1898 | +# include <numa.h> |
1899 | +#endif |
1900 | + |
1901 | +#include "datatypes.h" |
1902 | +#include "logging.h" |
1903 | +#include "virterror_internal.h" |
1904 | +#include "memory.h" |
1905 | +#include "hooks.h" |
1906 | +#include "virfile.h" |
1907 | +#include "virpidfile.h" |
1908 | +#include "util.h" |
1909 | +#include "c-ctype.h" |
1910 | +#include "nodeinfo.h" |
1911 | +#include "processinfo.h" |
1912 | +#include "domain_audit.h" |
1913 | +#include "domain_nwfilter.h" |
1914 | +#include "locking/domain_lock.h" |
1915 | +#include "network/bridge_driver.h" |
1916 | +#include "uuid.h" |
1917 | +#include "virprocess.h" |
1918 | +#include "virtime.h" |
1919 | +#include "virnetdevtap.h" |
1920 | +#include "bitmap.h" |
1921 | + |
1922 | +#define VIR_FROM_THIS VIR_FROM_QEMU |
1923 | + |
1924 | +#define START_POSTFIX ": starting up\n" |
1925 | +#define ATTACH_POSTFIX ": attaching\n" |
1926 | +#define SHUTDOWN_POSTFIX ": shutting down\n" |
1927 | + |
1928 | +/** |
1929 | + * qemudRemoveDomainStatus |
1930 | + * |
1931 | + * remove all state files of a domain from statedir |
1932 | + * |
1933 | + * Returns 0 on success |
1934 | + */ |
1935 | +static int |
1936 | +qemuProcessRemoveDomainStatus(struct qemud_driver *driver, |
1937 | + virDomainObjPtr vm) |
1938 | +{ |
1939 | + char ebuf[1024]; |
1940 | + char *file = NULL; |
1941 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
1942 | + |
1943 | + if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) < 0) { |
1944 | + virReportOOMError(); |
1945 | + return -1; |
1946 | + } |
1947 | + |
1948 | + if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) |
1949 | + VIR_WARN("Failed to remove domain XML for %s: %s", |
1950 | + vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf))); |
1951 | + VIR_FREE(file); |
1952 | + |
1953 | + if (priv->pidfile && |
1954 | + unlink(priv->pidfile) < 0 && |
1955 | + errno != ENOENT) |
1956 | + VIR_WARN("Failed to remove PID file for %s: %s", |
1957 | + vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf))); |
1958 | + |
1959 | + return 0; |
1960 | +} |
1961 | + |
1962 | + |
1963 | +/* XXX figure out how to remove this */ |
1964 | +extern struct qemud_driver *qemu_driver; |
1965 | + |
1966 | +/* |
1967 | + * This is a callback registered with a qemuAgentPtr instance, |
1968 | + * and to be invoked when the agent console hits an end of file |
1969 | + * condition, or error, thus indicating VM shutdown should be |
1970 | + * performed |
1971 | + */ |
1972 | +static void |
1973 | +qemuProcessHandleAgentEOF(qemuAgentPtr agent, |
1974 | + virDomainObjPtr vm) |
1975 | +{ |
1976 | + struct qemud_driver *driver = qemu_driver; |
1977 | + qemuDomainObjPrivatePtr priv; |
1978 | + |
1979 | + VIR_DEBUG("Received EOF from agent on %p '%s'", vm, vm->def->name); |
1980 | + |
1981 | + qemuDriverLock(driver); |
1982 | + virDomainObjLock(vm); |
1983 | + |
1984 | + priv = vm->privateData; |
1985 | + if (priv->agent == agent) |
1986 | + priv->agent = NULL; |
1987 | + |
1988 | + virDomainObjUnlock(vm); |
1989 | + qemuDriverUnlock(driver); |
1990 | + |
1991 | + qemuAgentClose(agent); |
1992 | +} |
1993 | + |
1994 | + |
1995 | +/* |
1996 | + * This is invoked when there is some kind of error |
1997 | + * parsing data to/from the agent. The VM can continue |
1998 | + * to run, but no further agent commands will be |
1999 | + * allowed |
2000 | + */ |
2001 | +static void |
2002 | +qemuProcessHandleAgentError(qemuAgentPtr agent ATTRIBUTE_UNUSED, |
2003 | + virDomainObjPtr vm) |
2004 | +{ |
2005 | + struct qemud_driver *driver = qemu_driver; |
2006 | + qemuDomainObjPrivatePtr priv; |
2007 | + |
2008 | + VIR_DEBUG("Received error from agent on %p '%s'", vm, vm->def->name); |
2009 | + |
2010 | + qemuDriverLock(driver); |
2011 | + virDomainObjLock(vm); |
2012 | + |
2013 | + priv = vm->privateData; |
2014 | + |
2015 | + priv->agentError = true; |
2016 | + |
2017 | + virDomainObjUnlock(vm); |
2018 | + qemuDriverUnlock(driver); |
2019 | +} |
2020 | + |
2021 | +static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent, |
2022 | + virDomainObjPtr vm) |
2023 | +{ |
2024 | + VIR_DEBUG("Received destroy agent=%p vm=%p", agent, vm); |
2025 | + |
2026 | + virObjectUnref(vm); |
2027 | +} |
2028 | + |
2029 | + |
2030 | +static qemuAgentCallbacks agentCallbacks = { |
2031 | + .destroy = qemuProcessHandleAgentDestroy, |
2032 | + .eofNotify = qemuProcessHandleAgentEOF, |
2033 | + .errorNotify = qemuProcessHandleAgentError, |
2034 | +}; |
2035 | + |
2036 | +static virDomainChrSourceDefPtr |
2037 | +qemuFindAgentConfig(virDomainDefPtr def) |
2038 | +{ |
2039 | + virDomainChrSourceDefPtr config = NULL; |
2040 | + int i; |
2041 | + |
2042 | + for (i = 0 ; i < def->nchannels ; i++) { |
2043 | + virDomainChrDefPtr channel = def->channels[i]; |
2044 | + |
2045 | + if (channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) |
2046 | + continue; |
2047 | + |
2048 | + if (STREQ_NULLABLE(channel->target.name, "org.qemu.guest_agent.0")) { |
2049 | + config = &channel->source; |
2050 | + break; |
2051 | + } |
2052 | + } |
2053 | + |
2054 | + return config; |
2055 | +} |
2056 | + |
2057 | +static int |
2058 | +qemuConnectAgent(struct qemud_driver *driver, virDomainObjPtr vm) |
2059 | +{ |
2060 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2061 | + int ret = -1; |
2062 | + qemuAgentPtr agent = NULL; |
2063 | + virDomainChrSourceDefPtr config = qemuFindAgentConfig(vm->def); |
2064 | + |
2065 | + if (!config) |
2066 | + return 0; |
2067 | + |
2068 | + if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager, |
2069 | + vm->def) < 0) { |
2070 | + VIR_ERROR(_("Failed to set security context for agent for %s"), |
2071 | + vm->def->name); |
2072 | + goto cleanup; |
2073 | + } |
2074 | + |
2075 | + /* Hold an extra reference because we can't allow 'vm' to be |
2076 | + * deleted while the agent is active */ |
2077 | + virObjectRef(vm); |
2078 | + |
2079 | + ignore_value(virTimeMillisNow(&priv->agentStart)); |
2080 | + virDomainObjUnlock(vm); |
2081 | + qemuDriverUnlock(driver); |
2082 | + |
2083 | + agent = qemuAgentOpen(vm, |
2084 | + config, |
2085 | + &agentCallbacks); |
2086 | + |
2087 | + qemuDriverLock(driver); |
2088 | + virDomainObjLock(vm); |
2089 | + priv->agentStart = 0; |
2090 | + |
2091 | + if (virSecurityManagerClearSocketLabel(driver->securityManager, |
2092 | + vm->def) < 0) { |
2093 | + VIR_ERROR(_("Failed to clear security context for agent for %s"), |
2094 | + vm->def->name); |
2095 | + goto cleanup; |
2096 | + } |
2097 | + |
2098 | + if (agent == NULL) |
2099 | + virObjectUnref(vm); |
2100 | + |
2101 | + if (!virDomainObjIsActive(vm)) { |
2102 | + qemuAgentClose(agent); |
2103 | + goto cleanup; |
2104 | + } |
2105 | + priv->agent = agent; |
2106 | + |
2107 | + if (priv->agent == NULL) { |
2108 | + VIR_INFO("Failed to connect agent for %s", vm->def->name); |
2109 | + goto cleanup; |
2110 | + } |
2111 | + |
2112 | + ret = 0; |
2113 | + |
2114 | +cleanup: |
2115 | + return ret; |
2116 | +} |
2117 | + |
2118 | + |
2119 | +/* |
2120 | + * This is a callback registered with a qemuMonitorPtr instance, |
2121 | + * and to be invoked when the monitor console hits an end of file |
2122 | + * condition, or error, thus indicating VM shutdown should be |
2123 | + * performed |
2124 | + */ |
2125 | +static void |
2126 | +qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2127 | + virDomainObjPtr vm) |
2128 | +{ |
2129 | + struct qemud_driver *driver = qemu_driver; |
2130 | + virDomainEventPtr event = NULL; |
2131 | + qemuDomainObjPrivatePtr priv; |
2132 | + int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN; |
2133 | + int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; |
2134 | + const char *auditReason = "shutdown"; |
2135 | + |
2136 | + VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name); |
2137 | + |
2138 | + qemuDriverLock(driver); |
2139 | + virDomainObjLock(vm); |
2140 | + |
2141 | + priv = vm->privateData; |
2142 | + |
2143 | + if (priv->beingDestroyed) { |
2144 | + VIR_DEBUG("Domain is being destroyed, EOF is expected"); |
2145 | + goto unlock; |
2146 | + } |
2147 | + |
2148 | + if (!virDomainObjIsActive(vm)) { |
2149 | + VIR_DEBUG("Domain %p is not active, ignoring EOF", vm); |
2150 | + goto unlock; |
2151 | + } |
2152 | + |
2153 | + if (priv->monJSON && !priv->gotShutdown) { |
2154 | + VIR_DEBUG("Monitor connection to '%s' closed without SHUTDOWN event; " |
2155 | + "assuming the domain crashed", vm->def->name); |
2156 | + eventReason = VIR_DOMAIN_EVENT_STOPPED_FAILED; |
2157 | + stopReason = VIR_DOMAIN_SHUTOFF_CRASHED; |
2158 | + auditReason = "failed"; |
2159 | + } |
2160 | + |
2161 | + event = virDomainEventNewFromObj(vm, |
2162 | + VIR_DOMAIN_EVENT_STOPPED, |
2163 | + eventReason); |
2164 | + qemuProcessStop(driver, vm, stopReason, 0); |
2165 | + virDomainAuditStop(vm, auditReason); |
2166 | + |
2167 | + if (!vm->persistent) { |
2168 | + qemuDomainRemoveInactive(driver, vm); |
2169 | + goto cleanup; |
2170 | + } |
2171 | + |
2172 | +unlock: |
2173 | + virDomainObjUnlock(vm); |
2174 | + |
2175 | +cleanup: |
2176 | + if (event) |
2177 | + qemuDomainEventQueue(driver, event); |
2178 | + qemuDriverUnlock(driver); |
2179 | +} |
2180 | + |
2181 | + |
2182 | +/* |
2183 | + * This is invoked when there is some kind of error |
2184 | + * parsing data to/from the monitor. The VM can continue |
2185 | + * to run, but no further monitor commands will be |
2186 | + * allowed |
2187 | + */ |
2188 | +static void |
2189 | +qemuProcessHandleMonitorError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2190 | + virDomainObjPtr vm) |
2191 | +{ |
2192 | + struct qemud_driver *driver = qemu_driver; |
2193 | + virDomainEventPtr event = NULL; |
2194 | + |
2195 | + VIR_DEBUG("Received error on %p '%s'", vm, vm->def->name); |
2196 | + |
2197 | + qemuDriverLock(driver); |
2198 | + virDomainObjLock(vm); |
2199 | + |
2200 | + ((qemuDomainObjPrivatePtr) vm->privateData)->monError = true; |
2201 | + event = virDomainEventControlErrorNewFromObj(vm); |
2202 | + if (event) |
2203 | + qemuDomainEventQueue(driver, event); |
2204 | + |
2205 | + virDomainObjUnlock(vm); |
2206 | + qemuDriverUnlock(driver); |
2207 | +} |
2208 | + |
2209 | + |
2210 | +static virDomainDiskDefPtr |
2211 | +qemuProcessFindDomainDiskByPath(virDomainObjPtr vm, |
2212 | + const char *path) |
2213 | +{ |
2214 | + int i = virDomainDiskIndexByName(vm->def, path, true); |
2215 | + |
2216 | + if (i >= 0) |
2217 | + return vm->def->disks[i]; |
2218 | + |
2219 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
2220 | + _("no disk found with path %s"), |
2221 | + path); |
2222 | + return NULL; |
2223 | +} |
2224 | + |
2225 | +static virDomainDiskDefPtr |
2226 | +qemuProcessFindDomainDiskByAlias(virDomainObjPtr vm, |
2227 | + const char *alias) |
2228 | +{ |
2229 | + int i; |
2230 | + |
2231 | + if (STRPREFIX(alias, QEMU_DRIVE_HOST_PREFIX)) |
2232 | + alias += strlen(QEMU_DRIVE_HOST_PREFIX); |
2233 | + |
2234 | + for (i = 0; i < vm->def->ndisks; i++) { |
2235 | + virDomainDiskDefPtr disk; |
2236 | + |
2237 | + disk = vm->def->disks[i]; |
2238 | + if (disk->info.alias != NULL && STREQ(disk->info.alias, alias)) |
2239 | + return disk; |
2240 | + } |
2241 | + |
2242 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
2243 | + _("no disk found with alias %s"), |
2244 | + alias); |
2245 | + return NULL; |
2246 | +} |
2247 | + |
2248 | +static int |
2249 | +qemuProcessGetVolumeQcowPassphrase(virConnectPtr conn, |
2250 | + virDomainDiskDefPtr disk, |
2251 | + char **secretRet, |
2252 | + size_t *secretLen) |
2253 | +{ |
2254 | + virSecretPtr secret; |
2255 | + char *passphrase; |
2256 | + unsigned char *data; |
2257 | + size_t size; |
2258 | + int ret = -1; |
2259 | + virStorageEncryptionPtr enc; |
2260 | + |
2261 | + if (!disk->encryption) { |
2262 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
2263 | + _("disk %s does not have any encryption information"), |
2264 | + disk->src); |
2265 | + return -1; |
2266 | + } |
2267 | + enc = disk->encryption; |
2268 | + |
2269 | + if (!conn) { |
2270 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
2271 | + "%s", _("cannot find secrets without a connection")); |
2272 | + goto cleanup; |
2273 | + } |
2274 | + |
2275 | + if (conn->secretDriver == NULL || |
2276 | + conn->secretDriver->lookupByUUID == NULL || |
2277 | + conn->secretDriver->getValue == NULL) { |
2278 | + virReportError(VIR_ERR_OPERATION_INVALID, "%s", |
2279 | + _("secret storage not supported")); |
2280 | + goto cleanup; |
2281 | + } |
2282 | + |
2283 | + if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW || |
2284 | + enc->nsecrets != 1 || |
2285 | + enc->secrets[0]->type != |
2286 | + VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) { |
2287 | + virReportError(VIR_ERR_XML_ERROR, |
2288 | + _("invalid <encryption> for volume %s"), disk->src); |
2289 | + goto cleanup; |
2290 | + } |
2291 | + |
2292 | + secret = conn->secretDriver->lookupByUUID(conn, |
2293 | + enc->secrets[0]->uuid); |
2294 | + if (secret == NULL) |
2295 | + goto cleanup; |
2296 | + data = conn->secretDriver->getValue(secret, &size, 0, |
2297 | + VIR_SECRET_GET_VALUE_INTERNAL_CALL); |
2298 | + virObjectUnref(secret); |
2299 | + if (data == NULL) |
2300 | + goto cleanup; |
2301 | + |
2302 | + if (memchr(data, '\0', size) != NULL) { |
2303 | + memset(data, 0, size); |
2304 | + VIR_FREE(data); |
2305 | + virReportError(VIR_ERR_XML_ERROR, |
2306 | + _("format='qcow' passphrase for %s must not contain a " |
2307 | + "'\\0'"), disk->src); |
2308 | + goto cleanup; |
2309 | + } |
2310 | + |
2311 | + if (VIR_ALLOC_N(passphrase, size + 1) < 0) { |
2312 | + memset(data, 0, size); |
2313 | + VIR_FREE(data); |
2314 | + virReportOOMError(); |
2315 | + goto cleanup; |
2316 | + } |
2317 | + memcpy(passphrase, data, size); |
2318 | + passphrase[size] = '\0'; |
2319 | + |
2320 | + memset(data, 0, size); |
2321 | + VIR_FREE(data); |
2322 | + |
2323 | + *secretRet = passphrase; |
2324 | + *secretLen = size; |
2325 | + |
2326 | + ret = 0; |
2327 | + |
2328 | +cleanup: |
2329 | + return ret; |
2330 | +} |
2331 | + |
2332 | +static int |
2333 | +qemuProcessFindVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2334 | + virConnectPtr conn, |
2335 | + virDomainObjPtr vm, |
2336 | + const char *path, |
2337 | + char **secretRet, |
2338 | + size_t *secretLen) |
2339 | +{ |
2340 | + virDomainDiskDefPtr disk; |
2341 | + int ret = -1; |
2342 | + |
2343 | + virDomainObjLock(vm); |
2344 | + disk = qemuProcessFindDomainDiskByPath(vm, path); |
2345 | + |
2346 | + if (!disk) |
2347 | + goto cleanup; |
2348 | + |
2349 | + ret = qemuProcessGetVolumeQcowPassphrase(conn, disk, secretRet, secretLen); |
2350 | + |
2351 | +cleanup: |
2352 | + virDomainObjUnlock(vm); |
2353 | + return ret; |
2354 | +} |
2355 | + |
2356 | + |
2357 | +static int |
2358 | +qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2359 | + virDomainObjPtr vm) |
2360 | +{ |
2361 | + struct qemud_driver *driver = qemu_driver; |
2362 | + virDomainEventPtr event; |
2363 | + qemuDomainObjPrivatePtr priv; |
2364 | + |
2365 | + virDomainObjLock(vm); |
2366 | + |
2367 | + event = virDomainEventRebootNewFromObj(vm); |
2368 | + priv = vm->privateData; |
2369 | + if (priv->agent) |
2370 | + qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_RESET); |
2371 | + |
2372 | + virDomainObjUnlock(vm); |
2373 | + |
2374 | + if (event) { |
2375 | + qemuDriverLock(driver); |
2376 | + qemuDomainEventQueue(driver, event); |
2377 | + qemuDriverUnlock(driver); |
2378 | + } |
2379 | + |
2380 | + return 0; |
2381 | +} |
2382 | + |
2383 | + |
2384 | +/* |
2385 | + * Since we have the '-no-shutdown' flag set, the |
2386 | + * QEMU process will currently have guest OS shutdown |
2387 | + * and the CPUS stopped. To fake the reboot, we thus |
2388 | + * want todo a reset of the virtual hardware, followed |
2389 | + * by restart of the CPUs. This should result in the |
2390 | + * guest OS booting up again |
2391 | + */ |
2392 | +static void |
2393 | +qemuProcessFakeReboot(void *opaque) |
2394 | +{ |
2395 | + struct qemud_driver *driver = qemu_driver; |
2396 | + virDomainObjPtr vm = opaque; |
2397 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2398 | + virDomainEventPtr event = NULL; |
2399 | + int ret = -1; |
2400 | + VIR_DEBUG("vm=%p", vm); |
2401 | + qemuDriverLock(driver); |
2402 | + virDomainObjLock(vm); |
2403 | + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) |
2404 | + goto cleanup; |
2405 | + |
2406 | + if (!virDomainObjIsActive(vm)) { |
2407 | + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
2408 | + _("guest unexpectedly quit")); |
2409 | + goto endjob; |
2410 | + } |
2411 | + |
2412 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
2413 | + if (qemuMonitorSystemReset(priv->mon) < 0) { |
2414 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
2415 | + goto endjob; |
2416 | + } |
2417 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
2418 | + |
2419 | + if (!virDomainObjIsActive(vm)) { |
2420 | + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
2421 | + _("guest unexpectedly quit")); |
2422 | + goto endjob; |
2423 | + } |
2424 | + |
2425 | + if (qemuProcessStartCPUs(driver, vm, NULL, |
2426 | + VIR_DOMAIN_RUNNING_BOOTED, |
2427 | + QEMU_ASYNC_JOB_NONE) < 0) { |
2428 | + if (virGetLastError() == NULL) |
2429 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
2430 | + "%s", _("resume operation failed")); |
2431 | + goto endjob; |
2432 | + } |
2433 | + priv->gotShutdown = false; |
2434 | + event = virDomainEventNewFromObj(vm, |
2435 | + VIR_DOMAIN_EVENT_RESUMED, |
2436 | + VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); |
2437 | + |
2438 | + ret = 0; |
2439 | + |
2440 | +endjob: |
2441 | + if (!qemuDomainObjEndJob(driver, vm)) |
2442 | + vm = NULL; |
2443 | + |
2444 | +cleanup: |
2445 | + if (vm) { |
2446 | + if (ret == -1) { |
2447 | + ignore_value(qemuProcessKill(driver, vm, |
2448 | + VIR_QEMU_PROCESS_KILL_FORCE)); |
2449 | + } |
2450 | + if (virObjectUnref(vm)) |
2451 | + virDomainObjUnlock(vm); |
2452 | + } |
2453 | + if (event) |
2454 | + qemuDomainEventQueue(driver, event); |
2455 | + qemuDriverUnlock(driver); |
2456 | +} |
2457 | + |
2458 | + |
2459 | +static void |
2460 | +qemuProcessShutdownOrReboot(struct qemud_driver *driver, |
2461 | + virDomainObjPtr vm) |
2462 | +{ |
2463 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2464 | + |
2465 | + if (priv->fakeReboot) { |
2466 | + qemuDomainSetFakeReboot(driver, vm, false); |
2467 | + virObjectRef(vm); |
2468 | + virThread th; |
2469 | + if (virThreadCreate(&th, |
2470 | + false, |
2471 | + qemuProcessFakeReboot, |
2472 | + vm) < 0) { |
2473 | + VIR_ERROR(_("Failed to create reboot thread, killing domain")); |
2474 | + ignore_value(qemuProcessKill(driver, vm, |
2475 | + VIR_QEMU_PROCESS_KILL_NOWAIT)); |
2476 | + virObjectUnref(vm); |
2477 | + } |
2478 | + } else { |
2479 | + ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_NOWAIT)); |
2480 | + } |
2481 | +} |
2482 | + |
2483 | +static int |
2484 | +qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2485 | + virDomainObjPtr vm) |
2486 | +{ |
2487 | + struct qemud_driver *driver = qemu_driver; |
2488 | + qemuDomainObjPrivatePtr priv; |
2489 | + virDomainEventPtr event = NULL; |
2490 | + |
2491 | + VIR_DEBUG("vm=%p", vm); |
2492 | + |
2493 | + virDomainObjLock(vm); |
2494 | + |
2495 | + priv = vm->privateData; |
2496 | + if (priv->gotShutdown) { |
2497 | + VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s", |
2498 | + vm->def->name); |
2499 | + goto unlock; |
2500 | + } else if (!virDomainObjIsActive(vm)) { |
2501 | + VIR_DEBUG("Ignoring SHUTDOWN event from inactive domain %s", |
2502 | + vm->def->name); |
2503 | + goto unlock; |
2504 | + } |
2505 | + priv->gotShutdown = true; |
2506 | + |
2507 | + VIR_DEBUG("Transitioned guest %s to shutdown state", |
2508 | + vm->def->name); |
2509 | + virDomainObjSetState(vm, |
2510 | + VIR_DOMAIN_SHUTDOWN, |
2511 | + VIR_DOMAIN_SHUTDOWN_UNKNOWN); |
2512 | + event = virDomainEventNewFromObj(vm, |
2513 | + VIR_DOMAIN_EVENT_SHUTDOWN, |
2514 | + VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED); |
2515 | + |
2516 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2517 | + VIR_WARN("Unable to save status on vm %s after state change", |
2518 | + vm->def->name); |
2519 | + } |
2520 | + |
2521 | + if (priv->agent) |
2522 | + qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SHUTDOWN); |
2523 | + |
2524 | + qemuProcessShutdownOrReboot(driver, vm); |
2525 | + |
2526 | +unlock: |
2527 | + virDomainObjUnlock(vm); |
2528 | + |
2529 | + if (event) { |
2530 | + qemuDriverLock(driver); |
2531 | + qemuDomainEventQueue(driver, event); |
2532 | + qemuDriverUnlock(driver); |
2533 | + } |
2534 | + |
2535 | + return 0; |
2536 | +} |
2537 | + |
2538 | + |
2539 | +static int |
2540 | +qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2541 | + virDomainObjPtr vm) |
2542 | +{ |
2543 | + struct qemud_driver *driver = qemu_driver; |
2544 | + virDomainEventPtr event = NULL; |
2545 | + |
2546 | + virDomainObjLock(vm); |
2547 | + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { |
2548 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2549 | + |
2550 | + if (priv->gotShutdown) { |
2551 | + VIR_DEBUG("Ignoring STOP event after SHUTDOWN"); |
2552 | + goto unlock; |
2553 | + } |
2554 | + |
2555 | + VIR_DEBUG("Transitioned guest %s to paused state", |
2556 | + vm->def->name); |
2557 | + |
2558 | + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN); |
2559 | + event = virDomainEventNewFromObj(vm, |
2560 | + VIR_DOMAIN_EVENT_SUSPENDED, |
2561 | + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); |
2562 | + |
2563 | + VIR_FREE(priv->lockState); |
2564 | + if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) |
2565 | + VIR_WARN("Unable to release lease on %s", vm->def->name); |
2566 | + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); |
2567 | + |
2568 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2569 | + VIR_WARN("Unable to save status on vm %s after state change", |
2570 | + vm->def->name); |
2571 | + } |
2572 | + } |
2573 | + |
2574 | +unlock: |
2575 | + virDomainObjUnlock(vm); |
2576 | + |
2577 | + if (event) { |
2578 | + qemuDriverLock(driver); |
2579 | + qemuDomainEventQueue(driver, event); |
2580 | + qemuDriverUnlock(driver); |
2581 | + } |
2582 | + |
2583 | + return 0; |
2584 | +} |
2585 | + |
2586 | + |
2587 | +static int |
2588 | +qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2589 | + virDomainObjPtr vm, |
2590 | + long long offset) |
2591 | +{ |
2592 | + struct qemud_driver *driver = qemu_driver; |
2593 | + virDomainEventPtr event; |
2594 | + |
2595 | + virDomainObjLock(vm); |
2596 | + event = virDomainEventRTCChangeNewFromObj(vm, offset); |
2597 | + |
2598 | + if (vm->def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE) |
2599 | + vm->def->clock.data.variable.adjustment = offset; |
2600 | + |
2601 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) |
2602 | + VIR_WARN("unable to save domain status with RTC change"); |
2603 | + |
2604 | + virDomainObjUnlock(vm); |
2605 | + |
2606 | + if (event) { |
2607 | + qemuDriverLock(driver); |
2608 | + qemuDomainEventQueue(driver, event); |
2609 | + qemuDriverUnlock(driver); |
2610 | + } |
2611 | + |
2612 | + return 0; |
2613 | +} |
2614 | + |
2615 | + |
2616 | +static int |
2617 | +qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2618 | + virDomainObjPtr vm, |
2619 | + int action) |
2620 | +{ |
2621 | + struct qemud_driver *driver = qemu_driver; |
2622 | + virDomainEventPtr watchdogEvent = NULL; |
2623 | + virDomainEventPtr lifecycleEvent = NULL; |
2624 | + |
2625 | + virDomainObjLock(vm); |
2626 | + watchdogEvent = virDomainEventWatchdogNewFromObj(vm, action); |
2627 | + |
2628 | + if (action == VIR_DOMAIN_EVENT_WATCHDOG_PAUSE && |
2629 | + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { |
2630 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2631 | + VIR_DEBUG("Transitioned guest %s to paused state due to watchdog", vm->def->name); |
2632 | + |
2633 | + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_WATCHDOG); |
2634 | + lifecycleEvent = virDomainEventNewFromObj(vm, |
2635 | + VIR_DOMAIN_EVENT_SUSPENDED, |
2636 | + VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG); |
2637 | + |
2638 | + VIR_FREE(priv->lockState); |
2639 | + if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) |
2640 | + VIR_WARN("Unable to release lease on %s", vm->def->name); |
2641 | + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); |
2642 | + |
2643 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2644 | + VIR_WARN("Unable to save status on vm %s after watchdog event", |
2645 | + vm->def->name); |
2646 | + } |
2647 | + } |
2648 | + |
2649 | + if (vm->def->watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) { |
2650 | + struct qemuDomainWatchdogEvent *wdEvent; |
2651 | + if (VIR_ALLOC(wdEvent) == 0) { |
2652 | + wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; |
2653 | + wdEvent->vm = vm; |
2654 | + /* Hold an extra reference because we can't allow 'vm' to be |
2655 | + * deleted before handling watchdog event is finished. |
2656 | + */ |
2657 | + virObjectRef(vm); |
2658 | + if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) { |
2659 | + if (!virObjectUnref(vm)) |
2660 | + vm = NULL; |
2661 | + VIR_FREE(wdEvent); |
2662 | + } |
2663 | + } else { |
2664 | + virReportOOMError(); |
2665 | + } |
2666 | + } |
2667 | + |
2668 | + if (vm) |
2669 | + virDomainObjUnlock(vm); |
2670 | + |
2671 | + if (watchdogEvent || lifecycleEvent) { |
2672 | + qemuDriverLock(driver); |
2673 | + if (watchdogEvent) |
2674 | + qemuDomainEventQueue(driver, watchdogEvent); |
2675 | + if (lifecycleEvent) |
2676 | + qemuDomainEventQueue(driver, lifecycleEvent); |
2677 | + qemuDriverUnlock(driver); |
2678 | + } |
2679 | + |
2680 | + return 0; |
2681 | +} |
2682 | + |
2683 | + |
2684 | +static int |
2685 | +qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2686 | + virDomainObjPtr vm, |
2687 | + const char *diskAlias, |
2688 | + int action, |
2689 | + const char *reason) |
2690 | +{ |
2691 | + struct qemud_driver *driver = qemu_driver; |
2692 | + virDomainEventPtr ioErrorEvent = NULL; |
2693 | + virDomainEventPtr ioErrorEvent2 = NULL; |
2694 | + virDomainEventPtr lifecycleEvent = NULL; |
2695 | + const char *srcPath; |
2696 | + const char *devAlias; |
2697 | + virDomainDiskDefPtr disk; |
2698 | + |
2699 | + virDomainObjLock(vm); |
2700 | + disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias); |
2701 | + |
2702 | + if (disk) { |
2703 | + srcPath = disk->src; |
2704 | + devAlias = disk->info.alias; |
2705 | + } else { |
2706 | + srcPath = ""; |
2707 | + devAlias = ""; |
2708 | + } |
2709 | + |
2710 | + ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action); |
2711 | + ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason); |
2712 | + |
2713 | + if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE && |
2714 | + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { |
2715 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2716 | + VIR_DEBUG("Transitioned guest %s to paused state due to IO error", vm->def->name); |
2717 | + |
2718 | + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR); |
2719 | + lifecycleEvent = virDomainEventNewFromObj(vm, |
2720 | + VIR_DOMAIN_EVENT_SUSPENDED, |
2721 | + VIR_DOMAIN_EVENT_SUSPENDED_IOERROR); |
2722 | + |
2723 | + VIR_FREE(priv->lockState); |
2724 | + if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) |
2725 | + VIR_WARN("Unable to release lease on %s", vm->def->name); |
2726 | + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); |
2727 | + |
2728 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) |
2729 | + VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name); |
2730 | + } |
2731 | + virDomainObjUnlock(vm); |
2732 | + |
2733 | + if (ioErrorEvent || ioErrorEvent2 || lifecycleEvent) { |
2734 | + qemuDriverLock(driver); |
2735 | + if (ioErrorEvent) |
2736 | + qemuDomainEventQueue(driver, ioErrorEvent); |
2737 | + if (ioErrorEvent2) |
2738 | + qemuDomainEventQueue(driver, ioErrorEvent2); |
2739 | + if (lifecycleEvent) |
2740 | + qemuDomainEventQueue(driver, lifecycleEvent); |
2741 | + qemuDriverUnlock(driver); |
2742 | + } |
2743 | + |
2744 | + return 0; |
2745 | +} |
2746 | + |
2747 | +static int |
2748 | +qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2749 | + virDomainObjPtr vm, |
2750 | + const char *diskAlias, |
2751 | + int type, |
2752 | + int status) |
2753 | +{ |
2754 | + struct qemud_driver *driver = qemu_driver; |
2755 | + virDomainEventPtr event = NULL; |
2756 | + const char *path; |
2757 | + virDomainDiskDefPtr disk; |
2758 | + |
2759 | + virDomainObjLock(vm); |
2760 | + disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias); |
2761 | + |
2762 | + if (disk) { |
2763 | + path = disk->src; |
2764 | + event = virDomainEventBlockJobNewFromObj(vm, path, type, status); |
2765 | + /* XXX If we completed a block pull or commit, then recompute |
2766 | + * the cached backing chain to match. Better would be storing |
2767 | + * the chain ourselves rather than reprobing, but this |
2768 | + * requires modifying domain_conf and our XML to fully track |
2769 | + * the chain across libvirtd restarts. For that matter, if |
2770 | + * qemu gains support for committing the active layer, we have |
2771 | + * to update disk->src. */ |
2772 | + if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL || |
2773 | + type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) && |
2774 | + status == VIR_DOMAIN_BLOCK_JOB_COMPLETED) |
2775 | + qemuDomainDetermineDiskChain(driver, disk, true); |
2776 | + if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY && |
2777 | + status == VIR_DOMAIN_BLOCK_JOB_READY) |
2778 | + disk->mirroring = true; |
2779 | + } |
2780 | + |
2781 | + virDomainObjUnlock(vm); |
2782 | + |
2783 | + if (event) { |
2784 | + qemuDriverLock(driver); |
2785 | + qemuDomainEventQueue(driver, event); |
2786 | + qemuDriverUnlock(driver); |
2787 | + } |
2788 | + |
2789 | + return 0; |
2790 | +} |
2791 | + |
2792 | +static int |
2793 | +qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2794 | + virDomainObjPtr vm, |
2795 | + int phase, |
2796 | + int localFamily, |
2797 | + const char *localNode, |
2798 | + const char *localService, |
2799 | + int remoteFamily, |
2800 | + const char *remoteNode, |
2801 | + const char *remoteService, |
2802 | + const char *authScheme, |
2803 | + const char *x509dname, |
2804 | + const char *saslUsername) |
2805 | +{ |
2806 | + struct qemud_driver *driver = qemu_driver; |
2807 | + virDomainEventPtr event; |
2808 | + virDomainEventGraphicsAddressPtr localAddr = NULL; |
2809 | + virDomainEventGraphicsAddressPtr remoteAddr = NULL; |
2810 | + virDomainEventGraphicsSubjectPtr subject = NULL; |
2811 | + int i; |
2812 | + |
2813 | + if (VIR_ALLOC(localAddr) < 0) |
2814 | + goto no_memory; |
2815 | + localAddr->family = localFamily; |
2816 | + if (!(localAddr->service = strdup(localService)) || |
2817 | + !(localAddr->node = strdup(localNode))) |
2818 | + goto no_memory; |
2819 | + |
2820 | + if (VIR_ALLOC(remoteAddr) < 0) |
2821 | + goto no_memory; |
2822 | + remoteAddr->family = remoteFamily; |
2823 | + if (!(remoteAddr->service = strdup(remoteService)) || |
2824 | + !(remoteAddr->node = strdup(remoteNode))) |
2825 | + goto no_memory; |
2826 | + |
2827 | + if (VIR_ALLOC(subject) < 0) |
2828 | + goto no_memory; |
2829 | + if (x509dname) { |
2830 | + if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0) |
2831 | + goto no_memory; |
2832 | + subject->nidentity++; |
2833 | + if (!(subject->identities[subject->nidentity-1].type = strdup("x509dname")) || |
2834 | + !(subject->identities[subject->nidentity-1].name = strdup(x509dname))) |
2835 | + goto no_memory; |
2836 | + } |
2837 | + if (saslUsername) { |
2838 | + if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0) |
2839 | + goto no_memory; |
2840 | + subject->nidentity++; |
2841 | + if (!(subject->identities[subject->nidentity-1].type = strdup("saslUsername")) || |
2842 | + !(subject->identities[subject->nidentity-1].name = strdup(saslUsername))) |
2843 | + goto no_memory; |
2844 | + } |
2845 | + |
2846 | + virDomainObjLock(vm); |
2847 | + event = virDomainEventGraphicsNewFromObj(vm, phase, localAddr, remoteAddr, authScheme, subject); |
2848 | + virDomainObjUnlock(vm); |
2849 | + |
2850 | + if (event) { |
2851 | + qemuDriverLock(driver); |
2852 | + qemuDomainEventQueue(driver, event); |
2853 | + qemuDriverUnlock(driver); |
2854 | + } |
2855 | + |
2856 | + return 0; |
2857 | + |
2858 | +no_memory: |
2859 | + virReportOOMError(); |
2860 | + if (localAddr) { |
2861 | + VIR_FREE(localAddr->service); |
2862 | + VIR_FREE(localAddr->node); |
2863 | + VIR_FREE(localAddr); |
2864 | + } |
2865 | + if (remoteAddr) { |
2866 | + VIR_FREE(remoteAddr->service); |
2867 | + VIR_FREE(remoteAddr->node); |
2868 | + VIR_FREE(remoteAddr); |
2869 | + } |
2870 | + if (subject) { |
2871 | + for (i = 0 ; i < subject->nidentity ; i++) { |
2872 | + VIR_FREE(subject->identities[i].type); |
2873 | + VIR_FREE(subject->identities[i].name); |
2874 | + } |
2875 | + VIR_FREE(subject->identities); |
2876 | + VIR_FREE(subject); |
2877 | + } |
2878 | + |
2879 | + return -1; |
2880 | +} |
2881 | + |
2882 | + |
2883 | +static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2884 | + virDomainObjPtr vm) |
2885 | +{ |
2886 | + virObjectUnref(vm); |
2887 | +} |
2888 | + |
2889 | +static int |
2890 | +qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2891 | + virDomainObjPtr vm, |
2892 | + const char *devAlias, |
2893 | + int reason) |
2894 | +{ |
2895 | + struct qemud_driver *driver = qemu_driver; |
2896 | + virDomainEventPtr event = NULL; |
2897 | + virDomainDiskDefPtr disk; |
2898 | + |
2899 | + virDomainObjLock(vm); |
2900 | + disk = qemuProcessFindDomainDiskByAlias(vm, devAlias); |
2901 | + |
2902 | + if (disk) { |
2903 | + event = virDomainEventTrayChangeNewFromObj(vm, |
2904 | + devAlias, |
2905 | + reason); |
2906 | + /* Update disk tray status */ |
2907 | + if (reason == VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN) |
2908 | + disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; |
2909 | + else if (reason == VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE) |
2910 | + disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; |
2911 | + |
2912 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2913 | + VIR_WARN("Unable to save status on vm %s after tray moved event", |
2914 | + vm->def->name); |
2915 | + } |
2916 | + } |
2917 | + |
2918 | + virDomainObjUnlock(vm); |
2919 | + |
2920 | + if (event) { |
2921 | + qemuDriverLock(driver); |
2922 | + qemuDomainEventQueue(driver, event); |
2923 | + qemuDriverUnlock(driver); |
2924 | + } |
2925 | + |
2926 | + return 0; |
2927 | +} |
2928 | + |
2929 | +static int |
2930 | +qemuProcessHandlePMWakeup(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2931 | + virDomainObjPtr vm) |
2932 | +{ |
2933 | + struct qemud_driver *driver = qemu_driver; |
2934 | + virDomainEventPtr event = NULL; |
2935 | + virDomainEventPtr lifecycleEvent = NULL; |
2936 | + |
2937 | + virDomainObjLock(vm); |
2938 | + event = virDomainEventPMWakeupNewFromObj(vm); |
2939 | + |
2940 | + /* Don't set domain status back to running if it wasn't paused |
2941 | + * from guest side, otherwise it can just cause confusion. |
2942 | + */ |
2943 | + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PMSUSPENDED) { |
2944 | + VIR_DEBUG("Transitioned guest %s from pmsuspended to running " |
2945 | + "state due to QMP wakeup event", vm->def->name); |
2946 | + |
2947 | + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, |
2948 | + VIR_DOMAIN_RUNNING_WAKEUP); |
2949 | + lifecycleEvent = virDomainEventNewFromObj(vm, |
2950 | + VIR_DOMAIN_EVENT_STARTED, |
2951 | + VIR_DOMAIN_EVENT_STARTED_WAKEUP); |
2952 | + |
2953 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2954 | + VIR_WARN("Unable to save status on vm %s after wakeup event", |
2955 | + vm->def->name); |
2956 | + } |
2957 | + } |
2958 | + |
2959 | + virDomainObjUnlock(vm); |
2960 | + |
2961 | + if (event || lifecycleEvent) { |
2962 | + qemuDriverLock(driver); |
2963 | + if (event) |
2964 | + qemuDomainEventQueue(driver, event); |
2965 | + if (lifecycleEvent) |
2966 | + qemuDomainEventQueue(driver, lifecycleEvent); |
2967 | + qemuDriverUnlock(driver); |
2968 | + } |
2969 | + |
2970 | + return 0; |
2971 | +} |
2972 | + |
2973 | +static int |
2974 | +qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
2975 | + virDomainObjPtr vm) |
2976 | +{ |
2977 | + struct qemud_driver *driver = qemu_driver; |
2978 | + virDomainEventPtr event = NULL; |
2979 | + virDomainEventPtr lifecycleEvent = NULL; |
2980 | + |
2981 | + virDomainObjLock(vm); |
2982 | + event = virDomainEventPMSuspendNewFromObj(vm); |
2983 | + |
2984 | + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { |
2985 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
2986 | + VIR_DEBUG("Transitioned guest %s to pmsuspended state due to " |
2987 | + "QMP suspend event", vm->def->name); |
2988 | + |
2989 | + virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED, |
2990 | + VIR_DOMAIN_PMSUSPENDED_UNKNOWN); |
2991 | + lifecycleEvent = |
2992 | + virDomainEventNewFromObj(vm, |
2993 | + VIR_DOMAIN_EVENT_PMSUSPENDED, |
2994 | + VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY); |
2995 | + |
2996 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
2997 | + VIR_WARN("Unable to save status on vm %s after suspend event", |
2998 | + vm->def->name); |
2999 | + } |
3000 | + |
3001 | + if (priv->agent) |
3002 | + qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND); |
3003 | + } |
3004 | + |
3005 | + virDomainObjUnlock(vm); |
3006 | + |
3007 | + if (event || lifecycleEvent) { |
3008 | + qemuDriverLock(driver); |
3009 | + if (event) |
3010 | + qemuDomainEventQueue(driver, event); |
3011 | + if (lifecycleEvent) |
3012 | + qemuDomainEventQueue(driver, lifecycleEvent); |
3013 | + qemuDriverUnlock(driver); |
3014 | + } |
3015 | + |
3016 | + return 0; |
3017 | +} |
3018 | + |
3019 | +static int |
3020 | +qemuProcessHandleBalloonChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
3021 | + virDomainObjPtr vm, |
3022 | + unsigned long long actual) |
3023 | +{ |
3024 | + struct qemud_driver *driver = qemu_driver; |
3025 | + virDomainEventPtr event; |
3026 | + |
3027 | + virDomainObjLock(vm); |
3028 | + event = virDomainEventBalloonChangeNewFromObj(vm, actual); |
3029 | + |
3030 | + VIR_DEBUG("Updating balloon from %lld to %lld kb", |
3031 | + vm->def->mem.cur_balloon, actual); |
3032 | + vm->def->mem.cur_balloon = actual; |
3033 | + |
3034 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) |
3035 | + VIR_WARN("unable to save domain status with balloon change"); |
3036 | + |
3037 | + virDomainObjUnlock(vm); |
3038 | + |
3039 | + if (event) { |
3040 | + qemuDriverLock(driver); |
3041 | + qemuDomainEventQueue(driver, event); |
3042 | + qemuDriverUnlock(driver); |
3043 | + } |
3044 | + |
3045 | + return 0; |
3046 | +} |
3047 | + |
3048 | +static int |
3049 | +qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, |
3050 | + virDomainObjPtr vm) |
3051 | +{ |
3052 | + struct qemud_driver *driver = qemu_driver; |
3053 | + virDomainEventPtr event = NULL; |
3054 | + virDomainEventPtr lifecycleEvent = NULL; |
3055 | + |
3056 | + virDomainObjLock(vm); |
3057 | + event = virDomainEventPMSuspendDiskNewFromObj(vm); |
3058 | + |
3059 | + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { |
3060 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3061 | + VIR_DEBUG("Transitioned guest %s to pmsuspended state due to " |
3062 | + "QMP suspend_disk event", vm->def->name); |
3063 | + |
3064 | + virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED, |
3065 | + VIR_DOMAIN_PMSUSPENDED_UNKNOWN); |
3066 | + lifecycleEvent = |
3067 | + virDomainEventNewFromObj(vm, |
3068 | + VIR_DOMAIN_EVENT_PMSUSPENDED, |
3069 | + VIR_DOMAIN_EVENT_PMSUSPENDED_DISK); |
3070 | + |
3071 | + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { |
3072 | + VIR_WARN("Unable to save status on vm %s after suspend event", |
3073 | + vm->def->name); |
3074 | + } |
3075 | + |
3076 | + if (priv->agent) |
3077 | + qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND); |
3078 | + } |
3079 | + |
3080 | + virDomainObjUnlock(vm); |
3081 | + |
3082 | + if (event || lifecycleEvent) { |
3083 | + qemuDriverLock(driver); |
3084 | + if (event) |
3085 | + qemuDomainEventQueue(driver, event); |
3086 | + if (lifecycleEvent) |
3087 | + qemuDomainEventQueue(driver, lifecycleEvent); |
3088 | + qemuDriverUnlock(driver); |
3089 | + } |
3090 | + |
3091 | + return 0; |
3092 | +} |
3093 | + |
3094 | + |
3095 | +static qemuMonitorCallbacks monitorCallbacks = { |
3096 | + .destroy = qemuProcessHandleMonitorDestroy, |
3097 | + .eofNotify = qemuProcessHandleMonitorEOF, |
3098 | + .errorNotify = qemuProcessHandleMonitorError, |
3099 | + .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase, |
3100 | + .domainShutdown = qemuProcessHandleShutdown, |
3101 | + .domainStop = qemuProcessHandleStop, |
3102 | + .domainReset = qemuProcessHandleReset, |
3103 | + .domainRTCChange = qemuProcessHandleRTCChange, |
3104 | + .domainWatchdog = qemuProcessHandleWatchdog, |
3105 | + .domainIOError = qemuProcessHandleIOError, |
3106 | + .domainGraphics = qemuProcessHandleGraphics, |
3107 | + .domainBlockJob = qemuProcessHandleBlockJob, |
3108 | + .domainTrayChange = qemuProcessHandleTrayChange, |
3109 | + .domainPMWakeup = qemuProcessHandlePMWakeup, |
3110 | + .domainPMSuspend = qemuProcessHandlePMSuspend, |
3111 | + .domainBalloonChange = qemuProcessHandleBalloonChange, |
3112 | + .domainPMSuspendDisk = qemuProcessHandlePMSuspendDisk, |
3113 | +}; |
3114 | + |
3115 | +static int |
3116 | +qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) |
3117 | +{ |
3118 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3119 | + int ret = -1; |
3120 | + qemuMonitorPtr mon = NULL; |
3121 | + |
3122 | + if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager, |
3123 | + vm->def) < 0) { |
3124 | + VIR_ERROR(_("Failed to set security context for monitor for %s"), |
3125 | + vm->def->name); |
3126 | + goto error; |
3127 | + } |
3128 | + |
3129 | + /* Hold an extra reference because we can't allow 'vm' to be |
3130 | + * deleted while the monitor is active */ |
3131 | + virObjectRef(vm); |
3132 | + |
3133 | + ignore_value(virTimeMillisNow(&priv->monStart)); |
3134 | + virDomainObjUnlock(vm); |
3135 | + qemuDriverUnlock(driver); |
3136 | + |
3137 | + mon = qemuMonitorOpen(vm, |
3138 | + priv->monConfig, |
3139 | + priv->monJSON, |
3140 | + &monitorCallbacks); |
3141 | + |
3142 | + qemuDriverLock(driver); |
3143 | + virDomainObjLock(vm); |
3144 | + priv->monStart = 0; |
3145 | + |
3146 | + if (mon == NULL) { |
3147 | + virObjectUnref(vm); |
3148 | + } else if (!virDomainObjIsActive(vm)) { |
3149 | + qemuMonitorClose(mon); |
3150 | + mon = NULL; |
3151 | + } |
3152 | + priv->mon = mon; |
3153 | + |
3154 | + if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { |
3155 | + VIR_ERROR(_("Failed to clear security context for monitor for %s"), |
3156 | + vm->def->name); |
3157 | + goto error; |
3158 | + } |
3159 | + |
3160 | + if (priv->mon == NULL) { |
3161 | + VIR_INFO("Failed to connect monitor for %s", vm->def->name); |
3162 | + goto error; |
3163 | + } |
3164 | + |
3165 | + |
3166 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
3167 | + ret = qemuMonitorSetCapabilities(priv->mon); |
3168 | + if (ret == 0 && |
3169 | + qemuCapsGet(priv->caps, QEMU_CAPS_MONITOR_JSON)) |
3170 | + ret = qemuCapsProbeQMP(priv->caps, priv->mon); |
3171 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
3172 | + |
3173 | +error: |
3174 | + |
3175 | + return ret; |
3176 | +} |
3177 | + |
3178 | +typedef int qemuProcessLogHandleOutput(virDomainObjPtr vm, |
3179 | + const char *output, |
3180 | + int fd); |
3181 | + |
3182 | +/* |
3183 | + * Returns -1 for error, 0 on success |
3184 | + */ |
3185 | +static int |
3186 | +qemuProcessReadLogOutput(virDomainObjPtr vm, |
3187 | + int fd, |
3188 | + char *buf, |
3189 | + size_t buflen, |
3190 | + qemuProcessLogHandleOutput func, |
3191 | + const char *what, |
3192 | + int timeout) |
3193 | +{ |
3194 | + int retries = (timeout*10); |
3195 | + int got = 0; |
3196 | + char *debug = NULL; |
3197 | + int ret = -1; |
3198 | + char *filter_next = buf; |
3199 | + |
3200 | + buf[0] = '\0'; |
3201 | + |
3202 | + /* This relies on log message format generated by virLogFormatString() and |
3203 | + * might need to be modified when message format changes. */ |
3204 | + if (virAsprintf(&debug, ": %d: debug : ", vm->pid) < 0) { |
3205 | + virReportOOMError(); |
3206 | + return -1; |
3207 | + } |
3208 | + |
3209 | + while (retries) { |
3210 | + ssize_t func_ret, bytes; |
3211 | + int isdead = 0; |
3212 | + char *eol; |
3213 | + |
3214 | + func_ret = func(vm, buf, fd); |
3215 | + |
3216 | + if (kill(vm->pid, 0) == -1 && errno == ESRCH) |
3217 | + isdead = 1; |
3218 | + |
3219 | + /* Any failures should be detected before we read the log, so we |
3220 | + * always have something useful to report on failure. */ |
3221 | + bytes = saferead(fd, buf+got, buflen-got-1); |
3222 | + if (bytes < 0) { |
3223 | + virReportSystemError(errno, |
3224 | + _("Failure while reading %s log output"), |
3225 | + what); |
3226 | + goto cleanup; |
3227 | + } |
3228 | + |
3229 | + got += bytes; |
3230 | + buf[got] = '\0'; |
3231 | + |
3232 | + /* Filter out debug messages from intermediate libvirt process */ |
3233 | + while ((eol = strchr(filter_next, '\n'))) { |
3234 | + *eol = '\0'; |
3235 | + if (strstr(filter_next, debug)) { |
3236 | + memmove(filter_next, eol + 1, got - (eol - buf)); |
3237 | + got -= eol + 1 - filter_next; |
3238 | + } else { |
3239 | + filter_next = eol + 1; |
3240 | + *eol = '\n'; |
3241 | + } |
3242 | + } |
3243 | + |
3244 | + if (got == buflen-1) { |
3245 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3246 | + _("Out of space while reading %s log output: %s"), |
3247 | + what, buf); |
3248 | + goto cleanup; |
3249 | + } |
3250 | + |
3251 | + if (isdead) { |
3252 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3253 | + _("Process exited while reading %s log output: %s"), |
3254 | + what, buf); |
3255 | + goto cleanup; |
3256 | + } |
3257 | + |
3258 | + if (func_ret <= 0) { |
3259 | + ret = func_ret; |
3260 | + goto cleanup; |
3261 | + } |
3262 | + |
3263 | + usleep(100*1000); |
3264 | + retries--; |
3265 | + } |
3266 | + |
3267 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3268 | + _("Timed out while reading %s log output: %s"), |
3269 | + what, buf); |
3270 | + |
3271 | +cleanup: |
3272 | + VIR_FREE(debug); |
3273 | + return ret; |
3274 | +} |
3275 | + |
3276 | + |
3277 | +/* |
3278 | + * Look at a chunk of data from the QEMU stdout logs and try to |
3279 | + * find a TTY device, as indicated by a line like |
3280 | + * |
3281 | + * char device redirected to /dev/pts/3 |
3282 | + * |
3283 | + * Returns -1 for error, 0 success, 1 continue reading |
3284 | + */ |
3285 | +static int |
3286 | +qemuProcessExtractTTYPath(const char *haystack, |
3287 | + size_t *offset, |
3288 | + char **path) |
3289 | +{ |
3290 | + static const char needle[] = "char device redirected to"; |
3291 | + char *tmp, *dev; |
3292 | + |
3293 | + VIR_FREE(*path); |
3294 | + /* First look for our magic string */ |
3295 | + if (!(tmp = strstr(haystack + *offset, needle))) { |
3296 | + return 1; |
3297 | + } |
3298 | + tmp += sizeof(needle); |
3299 | + dev = tmp; |
3300 | + |
3301 | + /* |
3302 | + * And look for first whitespace character and nul terminate |
3303 | + * to mark end of the pty path |
3304 | + */ |
3305 | + while (*tmp) { |
3306 | + if (c_isspace(*tmp)) { |
3307 | + *path = strndup(dev, tmp-dev); |
3308 | + if (*path == NULL) { |
3309 | + virReportOOMError(); |
3310 | + return -1; |
3311 | + } |
3312 | + |
3313 | + /* ... now further update offset till we get EOL */ |
3314 | + *offset = tmp - haystack; |
3315 | + return 0; |
3316 | + } |
3317 | + tmp++; |
3318 | + } |
3319 | + |
3320 | + /* |
3321 | + * We found a path, but didn't find any whitespace, |
3322 | + * so it must be still incomplete - we should at |
3323 | + * least see a \n - indicate that we want to carry |
3324 | + * on trying again |
3325 | + */ |
3326 | + return 1; |
3327 | +} |
3328 | + |
3329 | +static int |
3330 | +qemuProcessLookupPTYs(virDomainChrDefPtr *devices, |
3331 | + int count, |
3332 | + virHashTablePtr paths, |
3333 | + bool chardevfmt) |
3334 | +{ |
3335 | + int i; |
3336 | + const char *prefix = chardevfmt ? "char" : ""; |
3337 | + |
3338 | + for (i = 0 ; i < count ; i++) { |
3339 | + virDomainChrDefPtr chr = devices[i]; |
3340 | + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { |
3341 | + char id[32]; |
3342 | + const char *path; |
3343 | + |
3344 | + if (snprintf(id, sizeof(id), "%s%s", |
3345 | + prefix, chr->info.alias) >= sizeof(id)) |
3346 | + return -1; |
3347 | + |
3348 | + path = (const char *) virHashLookup(paths, id); |
3349 | + if (path == NULL) { |
3350 | + if (chr->source.data.file.path == NULL) { |
3351 | + /* neither the log output nor 'info chardev' had a |
3352 | + * pty path for this chardev, report an error |
3353 | + */ |
3354 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3355 | + _("no assigned pty for device %s"), id); |
3356 | + return -1; |
3357 | + } else { |
3358 | + /* 'info chardev' had no pty path for this chardev, |
3359 | + * but the log output had, so we're fine |
3360 | + */ |
3361 | + continue; |
3362 | + } |
3363 | + } |
3364 | + |
3365 | + VIR_FREE(chr->source.data.file.path); |
3366 | + chr->source.data.file.path = strdup(path); |
3367 | + |
3368 | + if (chr->source.data.file.path == NULL) { |
3369 | + virReportOOMError(); |
3370 | + return -1; |
3371 | + } |
3372 | + } |
3373 | + } |
3374 | + |
3375 | + return 0; |
3376 | +} |
3377 | + |
3378 | +static int |
3379 | +qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm, |
3380 | + qemuCapsPtr caps, |
3381 | + virHashTablePtr paths) |
3382 | +{ |
3383 | + bool chardevfmt = qemuCapsGet(caps, QEMU_CAPS_CHARDEV); |
3384 | + |
3385 | + if (qemuProcessLookupPTYs(vm->def->serials, vm->def->nserials, |
3386 | + paths, chardevfmt) < 0) |
3387 | + return -1; |
3388 | + |
3389 | + if (qemuProcessLookupPTYs(vm->def->parallels, vm->def->nparallels, |
3390 | + paths, chardevfmt) < 0) |
3391 | + return -1; |
3392 | + |
3393 | + if (qemuProcessLookupPTYs(vm->def->channels, vm->def->nchannels, |
3394 | + paths, chardevfmt) < 0) |
3395 | + return -1; |
3396 | + |
3397 | + if (qemuProcessLookupPTYs(vm->def->consoles, vm->def->nconsoles, |
3398 | + paths, chardevfmt) < 0) |
3399 | + return -1; |
3400 | + |
3401 | + return 0; |
3402 | +} |
3403 | + |
3404 | +static int |
3405 | +qemuProcessFindCharDevicePTYs(virDomainObjPtr vm, |
3406 | + const char *output, |
3407 | + int fd ATTRIBUTE_UNUSED) |
3408 | +{ |
3409 | + size_t offset = 0; |
3410 | + int ret, i; |
3411 | + |
3412 | + /* The order in which QEMU prints out the PTY paths is |
3413 | + the order in which it procsses its serial and parallel |
3414 | + device args. This code must match that ordering.... */ |
3415 | + |
3416 | + /* first comes the serial devices */ |
3417 | + for (i = 0 ; i < vm->def->nserials ; i++) { |
3418 | + virDomainChrDefPtr chr = vm->def->serials[i]; |
3419 | + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { |
3420 | + if ((ret = qemuProcessExtractTTYPath(output, &offset, |
3421 | + &chr->source.data.file.path)) != 0) |
3422 | + return ret; |
3423 | + } |
3424 | + } |
3425 | + |
3426 | + /* then the parallel devices */ |
3427 | + for (i = 0 ; i < vm->def->nparallels ; i++) { |
3428 | + virDomainChrDefPtr chr = vm->def->parallels[i]; |
3429 | + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { |
3430 | + if ((ret = qemuProcessExtractTTYPath(output, &offset, |
3431 | + &chr->source.data.file.path)) != 0) |
3432 | + return ret; |
3433 | + } |
3434 | + } |
3435 | + |
3436 | + /* then the channel devices */ |
3437 | + for (i = 0 ; i < vm->def->nchannels ; i++) { |
3438 | + virDomainChrDefPtr chr = vm->def->channels[i]; |
3439 | + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { |
3440 | + if ((ret = qemuProcessExtractTTYPath(output, &offset, |
3441 | + &chr->source.data.file.path)) != 0) |
3442 | + return ret; |
3443 | + } |
3444 | + } |
3445 | + |
3446 | + for (i = 0 ; i < vm->def->nconsoles ; i++) { |
3447 | + virDomainChrDefPtr chr = vm->def->consoles[i]; |
3448 | + /* For historical reasons, console[0] can be just an alias |
3449 | + * for serial[0]; That's why we need to update it as well */ |
3450 | + if (i == 0 && vm->def->nserials && |
3451 | + chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && |
3452 | + chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) { |
3453 | + if ((ret = virDomainChrSourceDefCopy(&chr->source, |
3454 | + &((vm->def->serials[0])->source))) != 0) |
3455 | + return ret; |
3456 | + } else { |
3457 | + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY && |
3458 | + chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) { |
3459 | + if ((ret = qemuProcessExtractTTYPath(output, &offset, |
3460 | + &chr->source.data.file.path)) != 0) |
3461 | + return ret; |
3462 | + } |
3463 | + } |
3464 | + } |
3465 | + |
3466 | + return 0; |
3467 | +} |
3468 | + |
3469 | +static void qemuProcessFreePtyPath(void *payload, const void *name ATTRIBUTE_UNUSED) |
3470 | +{ |
3471 | + VIR_FREE(payload); |
3472 | +} |
3473 | + |
3474 | +static void |
3475 | +qemuProcessReadLogFD(int logfd, char *buf, int maxlen, int off) |
3476 | +{ |
3477 | + int ret; |
3478 | + char *tmpbuf = buf + off; |
3479 | + |
3480 | + ret = saferead(logfd, tmpbuf, maxlen - off - 1); |
3481 | + if (ret < 0) { |
3482 | + ret = 0; |
3483 | + } |
3484 | + |
3485 | + tmpbuf[ret] = '\0'; |
3486 | +} |
3487 | + |
3488 | + |
3489 | +static int |
3490 | +qemuProcessWaitForMonitor(struct qemud_driver* driver, |
3491 | + virDomainObjPtr vm, |
3492 | + qemuCapsPtr caps, |
3493 | + off_t pos) |
3494 | +{ |
3495 | + char *buf = NULL; |
3496 | + size_t buf_size = 4096; /* Plenty of space to get startup greeting */ |
3497 | + int logfd = -1; |
3498 | + int ret = -1; |
3499 | + virHashTablePtr paths = NULL; |
3500 | + qemuDomainObjPrivatePtr priv; |
3501 | + |
3502 | + if (pos != -1) { |
3503 | + if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0) |
3504 | + return -1; |
3505 | + |
3506 | + if (VIR_ALLOC_N(buf, buf_size) < 0) { |
3507 | + virReportOOMError(); |
3508 | + goto closelog; |
3509 | + } |
3510 | + |
3511 | + if (qemuProcessReadLogOutput(vm, logfd, buf, buf_size, |
3512 | + qemuProcessFindCharDevicePTYs, |
3513 | + "console", 30) < 0) |
3514 | + goto closelog; |
3515 | + } |
3516 | + |
3517 | + VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name); |
3518 | + if (qemuConnectMonitor(driver, vm) < 0) { |
3519 | + goto cleanup; |
3520 | + } |
3521 | + |
3522 | + /* Try to get the pty path mappings again via the monitor. This is much more |
3523 | + * reliable if it's available. |
3524 | + * Note that the monitor itself can be on a pty, so we still need to try the |
3525 | + * log output method. */ |
3526 | + paths = virHashCreate(0, qemuProcessFreePtyPath); |
3527 | + if (paths == NULL) |
3528 | + goto cleanup; |
3529 | + |
3530 | + priv = vm->privateData; |
3531 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
3532 | + ret = qemuMonitorGetPtyPaths(priv->mon, paths); |
3533 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
3534 | + |
3535 | + VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); |
3536 | + if (ret == 0) |
3537 | + ret = qemuProcessFindCharDevicePTYsMonitor(vm, caps, paths); |
3538 | + |
3539 | +cleanup: |
3540 | + virHashFree(paths); |
3541 | + |
3542 | + if (pos != -1 && kill(vm->pid, 0) == -1 && errno == ESRCH) { |
3543 | + /* VM is dead, any other error raised in the interim is probably |
3544 | + * not as important as the qemu cmdline output */ |
3545 | + qemuProcessReadLogFD(logfd, buf, buf_size, strlen(buf)); |
3546 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3547 | + _("process exited while connecting to monitor: %s"), |
3548 | + buf); |
3549 | + ret = -1; |
3550 | + } |
3551 | + |
3552 | +closelog: |
3553 | + if (VIR_CLOSE(logfd) < 0) { |
3554 | + char ebuf[1024]; |
3555 | + VIR_WARN("Unable to close logfile: %s", |
3556 | + virStrerror(errno, ebuf, sizeof(ebuf))); |
3557 | + } |
3558 | + |
3559 | + VIR_FREE(buf); |
3560 | + |
3561 | + return ret; |
3562 | +} |
3563 | + |
3564 | +static int |
3565 | +qemuProcessDetectVcpuPIDs(struct qemud_driver *driver, |
3566 | + virDomainObjPtr vm) |
3567 | +{ |
3568 | + pid_t *cpupids = NULL; |
3569 | + int ncpupids; |
3570 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3571 | + |
3572 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
3573 | + /* failure to get the VCPU<-> PID mapping or to execute the query |
3574 | + * command will not be treated fatal as some versions of qemu don't |
3575 | + * support this command */ |
3576 | + if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) <= 0) { |
3577 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
3578 | + virResetLastError(); |
3579 | + |
3580 | + priv->nvcpupids = 1; |
3581 | + if (VIR_ALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) { |
3582 | + virReportOOMError(); |
3583 | + return -1; |
3584 | + } |
3585 | + priv->vcpupids[0] = vm->pid; |
3586 | + return 0; |
3587 | + } |
3588 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
3589 | + |
3590 | + if (ncpupids != vm->def->vcpus) { |
3591 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3592 | + _("got wrong number of vCPU pids from QEMU monitor. " |
3593 | + "got %d, wanted %d"), |
3594 | + ncpupids, vm->def->vcpus); |
3595 | + VIR_FREE(cpupids); |
3596 | + return -1; |
3597 | + } |
3598 | + |
3599 | + priv->nvcpupids = ncpupids; |
3600 | + priv->vcpupids = cpupids; |
3601 | + return 0; |
3602 | +} |
3603 | + |
3604 | + |
3605 | +/* |
3606 | + * Set NUMA memory policy for qemu process, to be run between |
3607 | + * fork/exec of QEMU only. |
3608 | + */ |
3609 | +#if HAVE_NUMACTL |
3610 | +static int |
3611 | +qemuProcessInitNumaMemoryPolicy(virDomainObjPtr vm, |
3612 | + virBitmapPtr nodemask) |
3613 | +{ |
3614 | + nodemask_t mask; |
3615 | + int mode = -1; |
3616 | + int node = -1; |
3617 | + int ret = -1; |
3618 | + int i = 0; |
3619 | + int maxnode = 0; |
3620 | + bool warned = false; |
3621 | + virDomainNumatuneDef numatune = vm->def->numatune; |
3622 | + virBitmapPtr tmp_nodemask = NULL; |
3623 | + |
3624 | + if (numatune.memory.placement_mode == |
3625 | + VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_STATIC) { |
3626 | + if (!numatune.memory.nodemask) |
3627 | + return 0; |
3628 | + VIR_DEBUG("Set NUMA memory policy with specified nodeset"); |
3629 | + tmp_nodemask = numatune.memory.nodemask; |
3630 | + } else if (numatune.memory.placement_mode == |
3631 | + VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_AUTO) { |
3632 | + VIR_DEBUG("Set NUMA memory policy with advisory nodeset from numad"); |
3633 | + tmp_nodemask = nodemask; |
3634 | + } else { |
3635 | + return 0; |
3636 | + } |
3637 | + |
3638 | + if (numa_available() < 0) { |
3639 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3640 | + "%s", _("Host kernel is not aware of NUMA.")); |
3641 | + return -1; |
3642 | + } |
3643 | + |
3644 | + maxnode = numa_max_node() + 1; |
3645 | + /* Convert nodemask to NUMA bitmask. */ |
3646 | + nodemask_zero(&mask); |
3647 | + i = -1; |
3648 | + while ((i = virBitmapNextSetBit(tmp_nodemask, i)) >= 0) { |
3649 | + if (i > NUMA_NUM_NODES) { |
3650 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3651 | + _("Host cannot support NUMA node %d"), i); |
3652 | + return -1; |
3653 | + } |
3654 | + if (i > maxnode && !warned) { |
3655 | + VIR_WARN("nodeset is out of range, there is only %d NUMA " |
3656 | + "nodes on host", maxnode); |
3657 | + warned = true; |
3658 | + } |
3659 | + nodemask_set(&mask, i); |
3660 | + } |
3661 | + |
3662 | + mode = numatune.memory.mode; |
3663 | + |
3664 | + if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { |
3665 | + numa_set_bind_policy(1); |
3666 | + numa_set_membind(&mask); |
3667 | + numa_set_bind_policy(0); |
3668 | + } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) { |
3669 | + int nnodes = 0; |
3670 | + for (i = 0; i < NUMA_NUM_NODES; i++) { |
3671 | + if (nodemask_isset(&mask, i)) { |
3672 | + node = i; |
3673 | + nnodes++; |
3674 | + } |
3675 | + } |
3676 | + |
3677 | + if (nnodes != 1) { |
3678 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
3679 | + "%s", _("NUMA memory tuning in 'preferred' mode " |
3680 | + "only supports single node")); |
3681 | + goto cleanup; |
3682 | + } |
3683 | + |
3684 | + numa_set_bind_policy(0); |
3685 | + numa_set_preferred(node); |
3686 | + } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) { |
3687 | + numa_set_interleave_mask(&mask); |
3688 | + } else { |
3689 | + /* XXX: Shouldn't go here, as we already do checking when |
3690 | + * parsing domain XML. |
3691 | + */ |
3692 | + virReportError(VIR_ERR_XML_ERROR, |
3693 | + "%s", _("Invalid mode for memory NUMA tuning.")); |
3694 | + goto cleanup; |
3695 | + } |
3696 | + |
3697 | + ret = 0; |
3698 | + |
3699 | +cleanup: |
3700 | + return ret; |
3701 | +} |
3702 | +#else |
3703 | +static int |
3704 | +qemuProcessInitNumaMemoryPolicy(virDomainObjPtr vm, |
3705 | + virBitmapPtr nodemask ATTRIBUTE_UNUSED) |
3706 | +{ |
3707 | + if (vm->def->numatune.memory.nodemask) { |
3708 | + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
3709 | + _("libvirt is compiled without NUMA tuning support")); |
3710 | + |
3711 | + return -1; |
3712 | + } |
3713 | + |
3714 | + return 0; |
3715 | +} |
3716 | +#endif |
3717 | + |
3718 | +#if HAVE_NUMAD |
3719 | +static char * |
3720 | +qemuGetNumadAdvice(virDomainDefPtr def) |
3721 | +{ |
3722 | + virCommandPtr cmd = NULL; |
3723 | + char *output = NULL; |
3724 | + |
3725 | + cmd = virCommandNewArgList(NUMAD, "-w", NULL); |
3726 | + virCommandAddArgFormat(cmd, "%d:%llu", def->vcpus, |
3727 | + VIR_DIV_UP(def->mem.cur_balloon, 1024)); |
3728 | + |
3729 | + virCommandSetOutputBuffer(cmd, &output); |
3730 | + |
3731 | + if (virCommandRun(cmd, NULL) < 0) |
3732 | + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
3733 | + _("Failed to query numad for the " |
3734 | + "advisory nodeset")); |
3735 | + |
3736 | + virCommandFree(cmd); |
3737 | + return output; |
3738 | +} |
3739 | +#else |
3740 | +static char * |
3741 | +qemuGetNumadAdvice(virDomainDefPtr def ATTRIBUTE_UNUSED) |
3742 | +{ |
3743 | + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", |
3744 | + _("numad is not available on this host")); |
3745 | + return NULL; |
3746 | +} |
3747 | +#endif |
3748 | + |
3749 | +/* Helper to prepare cpumap for affinity setting, convert |
3750 | + * NUMA nodeset into cpuset if @nodemask is not NULL, otherwise |
3751 | + * just return a new allocated bitmap. |
3752 | + */ |
3753 | +virBitmapPtr |
3754 | +qemuPrepareCpumap(struct qemud_driver *driver, |
3755 | + virBitmapPtr nodemask) |
3756 | +{ |
3757 | + int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN; |
3758 | + virNodeInfo nodeinfo; |
3759 | + virBitmapPtr cpumap = NULL; |
3760 | + |
3761 | + if (nodeGetInfo(NULL, &nodeinfo) < 0) |
3762 | + return NULL; |
3763 | + |
3764 | + /* setaffinity fails if you set bits for CPUs which |
3765 | + * aren't present, so we have to limit ourselves */ |
3766 | + hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); |
3767 | + if (maxcpu > hostcpus) |
3768 | + maxcpu = hostcpus; |
3769 | + |
3770 | + if (!(cpumap = virBitmapNew(maxcpu))) { |
3771 | + virReportOOMError(); |
3772 | + return NULL; |
3773 | + } |
3774 | + |
3775 | + if (nodemask) { |
3776 | + for (i = 0; i < driver->caps->host.nnumaCell; i++) { |
3777 | + int j; |
3778 | + int cur_ncpus = driver->caps->host.numaCell[i]->ncpus; |
3779 | + bool result; |
3780 | + if (virBitmapGetBit(nodemask, i, &result) < 0) { |
3781 | + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
3782 | + _("Failed to convert nodeset to cpuset")); |
3783 | + virBitmapFree(cpumap); |
3784 | + return NULL; |
3785 | + } |
3786 | + if (result) { |
3787 | + for (j = 0; j < cur_ncpus; j++) |
3788 | + ignore_value(virBitmapSetBit(cpumap, |
3789 | + driver->caps->host.numaCell[i]->cpus[j])); |
3790 | + } |
3791 | + } |
3792 | + } |
3793 | + |
3794 | + return cpumap; |
3795 | +} |
3796 | + |
3797 | +/* |
3798 | + * To be run between fork/exec of QEMU only |
3799 | + */ |
3800 | +static int |
3801 | +qemuProcessInitCpuAffinity(struct qemud_driver *driver, |
3802 | + virDomainObjPtr vm, |
3803 | + virBitmapPtr nodemask) |
3804 | +{ |
3805 | + int ret = -1; |
3806 | + virBitmapPtr cpumap = NULL; |
3807 | + virBitmapPtr cpumapToSet = NULL; |
3808 | + |
3809 | + if (!(cpumap = qemuPrepareCpumap(driver, nodemask))) |
3810 | + return -1; |
3811 | + |
3812 | + if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) { |
3813 | + VIR_DEBUG("Set CPU affinity with advisory nodeset from numad"); |
3814 | + cpumapToSet = cpumap; |
3815 | + } else { |
3816 | + VIR_DEBUG("Set CPU affinity with specified cpuset"); |
3817 | + if (vm->def->cpumask) { |
3818 | + cpumapToSet = vm->def->cpumask; |
3819 | + } else { |
3820 | + cpumapToSet = cpumap; |
3821 | + /* You may think this is redundant, but we can't assume libvirtd |
3822 | + * itself is running on all pCPUs, so we need to explicitly set |
3823 | + * the spawned QEMU instance to all pCPUs if no map is given in |
3824 | + * its config file */ |
3825 | + virBitmapSetAll(cpumap); |
3826 | + } |
3827 | + } |
3828 | + |
3829 | + /* We are pressuming we are running between fork/exec of QEMU |
3830 | + * so use '0' to indicate our own process ID. No threads are |
3831 | + * running at this point |
3832 | + */ |
3833 | + if (virProcessInfoSetAffinity(0 /* Self */, cpumapToSet) < 0) |
3834 | + goto cleanup; |
3835 | + |
3836 | + ret = 0; |
3837 | + |
3838 | +cleanup: |
3839 | + virBitmapFree(cpumap); |
3840 | + return ret; |
3841 | +} |
3842 | + |
3843 | +/* set link states to down on interfaces at qemu start */ |
3844 | +static int |
3845 | +qemuProcessSetLinkStates(virDomainObjPtr vm) |
3846 | +{ |
3847 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3848 | + virDomainDefPtr def = vm->def; |
3849 | + int i; |
3850 | + int ret = 0; |
3851 | + |
3852 | + for (i = 0; i < def->nnets; i++) { |
3853 | + if (def->nets[i]->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) { |
3854 | + VIR_DEBUG("Setting link state: %s", def->nets[i]->info.alias); |
3855 | + |
3856 | + if (!qemuCapsGet(priv->caps, QEMU_CAPS_NETDEV)) { |
3857 | + virReportError(VIR_ERR_NO_SUPPORT, "%s", |
3858 | + _("Setting of link state is not supported by this qemu")); |
3859 | + return -1; |
3860 | + } |
3861 | + |
3862 | + ret = qemuMonitorSetLink(priv->mon, |
3863 | + def->nets[i]->info.alias, |
3864 | + VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN); |
3865 | + if (ret != 0) { |
3866 | + virReportError(VIR_ERR_OPERATION_FAILED, |
3867 | + _("Couldn't set link state on interface: %s"), def->nets[i]->info.alias); |
3868 | + break; |
3869 | + } |
3870 | + } |
3871 | + } |
3872 | + |
3873 | + return ret; |
3874 | +} |
3875 | + |
3876 | +/* Set CPU affinities for vcpus if vcpupin xml provided. */ |
3877 | +static int |
3878 | +qemuProcessSetVcpuAffinites(virConnectPtr conn ATTRIBUTE_UNUSED, |
3879 | + virDomainObjPtr vm) |
3880 | +{ |
3881 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3882 | + virDomainDefPtr def = vm->def; |
3883 | + int vcpu, n; |
3884 | + int ret = -1; |
3885 | + |
3886 | + if (!def->cputune.nvcpupin) |
3887 | + return 0; |
3888 | + |
3889 | + if (priv->vcpupids == NULL) { |
3890 | + virReportError(VIR_ERR_OPERATION_INVALID, |
3891 | + "%s", _("cpu affinity is not supported")); |
3892 | + return -1; |
3893 | + } |
3894 | + |
3895 | + for (n = 0; n < def->cputune.nvcpupin; n++) { |
3896 | + vcpu = def->cputune.vcpupin[n]->vcpuid; |
3897 | + |
3898 | + if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], |
3899 | + def->cputune.vcpupin[n]->cpumask) < 0) { |
3900 | + goto cleanup; |
3901 | + } |
3902 | + } |
3903 | + |
3904 | + ret = 0; |
3905 | +cleanup: |
3906 | + return ret; |
3907 | +} |
3908 | + |
3909 | +/* Set CPU affinities for emulator threads. */ |
3910 | +static int |
3911 | +qemuProcessSetEmulatorAffinites(virConnectPtr conn ATTRIBUTE_UNUSED, |
3912 | + virDomainObjPtr vm) |
3913 | +{ |
3914 | + virBitmapPtr cpumask; |
3915 | + virDomainDefPtr def = vm->def; |
3916 | + int ret = -1; |
3917 | + |
3918 | + if (def->cputune.emulatorpin) |
3919 | + cpumask = def->cputune.emulatorpin->cpumask; |
3920 | + else if (def->cpumask) |
3921 | + cpumask = def->cpumask; |
3922 | + else |
3923 | + return 0; |
3924 | + |
3925 | + ret = virProcessInfoSetAffinity(vm->pid, cpumask); |
3926 | + return ret; |
3927 | +} |
3928 | + |
3929 | +static int |
3930 | +qemuProcessInitPasswords(virConnectPtr conn, |
3931 | + struct qemud_driver *driver, |
3932 | + virDomainObjPtr vm) |
3933 | +{ |
3934 | + int ret = 0; |
3935 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
3936 | + |
3937 | + if (vm->def->ngraphics == 1) { |
3938 | + if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { |
3939 | + ret = qemuDomainChangeGraphicsPasswords(driver, vm, |
3940 | + VIR_DOMAIN_GRAPHICS_TYPE_VNC, |
3941 | + &vm->def->graphics[0]->data.vnc.auth, |
3942 | + driver->vncPassword); |
3943 | + } else if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { |
3944 | + ret = qemuDomainChangeGraphicsPasswords(driver, vm, |
3945 | + VIR_DOMAIN_GRAPHICS_TYPE_SPICE, |
3946 | + &vm->def->graphics[0]->data.spice.auth, |
3947 | + driver->spicePassword); |
3948 | + } |
3949 | + } |
3950 | + |
3951 | + if (ret < 0) |
3952 | + goto cleanup; |
3953 | + |
3954 | + if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE)) { |
3955 | + int i; |
3956 | + |
3957 | + for (i = 0 ; i < vm->def->ndisks ; i++) { |
3958 | + char *secret; |
3959 | + size_t secretLen; |
3960 | + const char *alias; |
3961 | + |
3962 | + if (!vm->def->disks[i]->encryption || |
3963 | + !vm->def->disks[i]->src) |
3964 | + continue; |
3965 | + |
3966 | + if (qemuProcessGetVolumeQcowPassphrase(conn, |
3967 | + vm->def->disks[i], |
3968 | + &secret, &secretLen) < 0) |
3969 | + goto cleanup; |
3970 | + |
3971 | + alias = vm->def->disks[i]->info.alias; |
3972 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
3973 | + ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret); |
3974 | + VIR_FREE(secret); |
3975 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
3976 | + if (ret < 0) |
3977 | + goto cleanup; |
3978 | + } |
3979 | + } |
3980 | + |
3981 | +cleanup: |
3982 | + return ret; |
3983 | +} |
3984 | + |
3985 | + |
3986 | +#define QEMU_PCI_VENDOR_INTEL 0x8086 |
3987 | +#define QEMU_PCI_VENDOR_LSI_LOGIC 0x1000 |
3988 | +#define QEMU_PCI_VENDOR_REDHAT 0x1af4 |
3989 | +#define QEMU_PCI_VENDOR_CIRRUS 0x1013 |
3990 | +#define QEMU_PCI_VENDOR_REALTEK 0x10ec |
3991 | +#define QEMU_PCI_VENDOR_AMD 0x1022 |
3992 | +#define QEMU_PCI_VENDOR_ENSONIQ 0x1274 |
3993 | +#define QEMU_PCI_VENDOR_VMWARE 0x15ad |
3994 | +#define QEMU_PCI_VENDOR_QEMU 0x1234 |
3995 | + |
3996 | +#define QEMU_PCI_PRODUCT_DISK_VIRTIO 0x1001 |
3997 | + |
3998 | +#define QEMU_PCI_PRODUCT_BALLOON_VIRTIO 0x1002 |
3999 | + |
4000 | +#define QEMU_PCI_PRODUCT_NIC_NE2K 0x8029 |
4001 | +#define QEMU_PCI_PRODUCT_NIC_PCNET 0x2000 |
4002 | +#define QEMU_PCI_PRODUCT_NIC_RTL8139 0x8139 |
4003 | +#define QEMU_PCI_PRODUCT_NIC_E1000 0x100E |
4004 | +#define QEMU_PCI_PRODUCT_NIC_VIRTIO 0x1000 |
4005 | + |
4006 | +#define QEMU_PCI_PRODUCT_VGA_CIRRUS 0x00b8 |
4007 | +#define QEMU_PCI_PRODUCT_VGA_VMWARE 0x0405 |
4008 | +#define QEMU_PCI_PRODUCT_VGA_STDVGA 0x1111 |
4009 | + |
4010 | +#define QEMU_PCI_PRODUCT_AUDIO_AC97 0x2415 |
4011 | +#define QEMU_PCI_PRODUCT_AUDIO_ES1370 0x5000 |
4012 | + |
4013 | +#define QEMU_PCI_PRODUCT_CONTROLLER_PIIX 0x7010 |
4014 | +#define QEMU_PCI_PRODUCT_CONTROLLER_LSI 0x0012 |
4015 | + |
4016 | +#define QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB 0x25ab |
4017 | + |
4018 | +static int |
4019 | +qemuProcessAssignNextPCIAddress(virDomainDeviceInfo *info, |
4020 | + int vendor, |
4021 | + int product, |
4022 | + qemuMonitorPCIAddress *addrs, |
4023 | + int naddrs) |
4024 | +{ |
4025 | + int found = 0; |
4026 | + int i; |
4027 | + |
4028 | + VIR_DEBUG("Look for %x:%x out of %d", vendor, product, naddrs); |
4029 | + |
4030 | + for (i = 0 ; (i < naddrs) && !found; i++) { |
4031 | + VIR_DEBUG("Maybe %x:%x", addrs[i].vendor, addrs[i].product); |
4032 | + if (addrs[i].vendor == vendor && |
4033 | + addrs[i].product == product) { |
4034 | + VIR_DEBUG("Match %d", i); |
4035 | + found = 1; |
4036 | + break; |
4037 | + } |
4038 | + } |
4039 | + if (!found) { |
4040 | + return -1; |
4041 | + } |
4042 | + |
4043 | + /* Blank it out so this device isn't matched again */ |
4044 | + addrs[i].vendor = 0; |
4045 | + addrs[i].product = 0; |
4046 | + |
4047 | + if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) |
4048 | + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; |
4049 | + |
4050 | + if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { |
4051 | + info->addr.pci.domain = addrs[i].addr.domain; |
4052 | + info->addr.pci.bus = addrs[i].addr.bus; |
4053 | + info->addr.pci.slot = addrs[i].addr.slot; |
4054 | + info->addr.pci.function = addrs[i].addr.function; |
4055 | + } |
4056 | + |
4057 | + return 0; |
4058 | +} |
4059 | + |
4060 | +static int |
4061 | +qemuProcessGetPCIDiskVendorProduct(virDomainDiskDefPtr def, |
4062 | + unsigned *vendor, |
4063 | + unsigned *product) |
4064 | +{ |
4065 | + switch (def->bus) { |
4066 | + case VIR_DOMAIN_DISK_BUS_VIRTIO: |
4067 | + *vendor = QEMU_PCI_VENDOR_REDHAT; |
4068 | + *product = QEMU_PCI_PRODUCT_DISK_VIRTIO; |
4069 | + break; |
4070 | + |
4071 | + default: |
4072 | + return -1; |
4073 | + } |
4074 | + |
4075 | + return 0; |
4076 | +} |
4077 | + |
4078 | +static int |
4079 | +qemuProcessGetPCINetVendorProduct(virDomainNetDefPtr def, |
4080 | + unsigned *vendor, |
4081 | + unsigned *product) |
4082 | +{ |
4083 | + if (!def->model) |
4084 | + return -1; |
4085 | + |
4086 | + if (STREQ(def->model, "ne2k_pci")) { |
4087 | + *vendor = QEMU_PCI_VENDOR_REALTEK; |
4088 | + *product = QEMU_PCI_PRODUCT_NIC_NE2K; |
4089 | + } else if (STREQ(def->model, "pcnet")) { |
4090 | + *vendor = QEMU_PCI_VENDOR_AMD; |
4091 | + *product = QEMU_PCI_PRODUCT_NIC_PCNET; |
4092 | + } else if (STREQ(def->model, "rtl8139")) { |
4093 | + *vendor = QEMU_PCI_VENDOR_REALTEK; |
4094 | + *product = QEMU_PCI_PRODUCT_NIC_RTL8139; |
4095 | + } else if (STREQ(def->model, "e1000")) { |
4096 | + *vendor = QEMU_PCI_VENDOR_INTEL; |
4097 | + *product = QEMU_PCI_PRODUCT_NIC_E1000; |
4098 | + } else if (STREQ(def->model, "virtio")) { |
4099 | + *vendor = QEMU_PCI_VENDOR_REDHAT; |
4100 | + *product = QEMU_PCI_PRODUCT_NIC_VIRTIO; |
4101 | + } else { |
4102 | + VIR_INFO("Unexpected NIC model %s, cannot get PCI address", |
4103 | + def->model); |
4104 | + return -1; |
4105 | + } |
4106 | + return 0; |
4107 | +} |
4108 | + |
4109 | +static int |
4110 | +qemuProcessGetPCIControllerVendorProduct(virDomainControllerDefPtr def, |
4111 | + unsigned *vendor, |
4112 | + unsigned *product) |
4113 | +{ |
4114 | + switch (def->type) { |
4115 | + case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: |
4116 | + *vendor = QEMU_PCI_VENDOR_LSI_LOGIC; |
4117 | + *product = QEMU_PCI_PRODUCT_CONTROLLER_LSI; |
4118 | + break; |
4119 | + |
4120 | + case VIR_DOMAIN_CONTROLLER_TYPE_FDC: |
4121 | + /* XXX we could put in the ISA bridge address, but |
4122 | + that's not technically the FDC's address */ |
4123 | + return -1; |
4124 | + |
4125 | + case VIR_DOMAIN_CONTROLLER_TYPE_IDE: |
4126 | + *vendor = QEMU_PCI_VENDOR_INTEL; |
4127 | + *product = QEMU_PCI_PRODUCT_CONTROLLER_PIIX; |
4128 | + break; |
4129 | + |
4130 | + default: |
4131 | + VIR_INFO("Unexpected controller type %s, cannot get PCI address", |
4132 | + virDomainControllerTypeToString(def->type)); |
4133 | + return -1; |
4134 | + } |
4135 | + |
4136 | + return 0; |
4137 | +} |
4138 | + |
4139 | +static int |
4140 | +qemuProcessGetPCIVideoVendorProduct(virDomainVideoDefPtr def, |
4141 | + unsigned *vendor, |
4142 | + unsigned *product) |
4143 | +{ |
4144 | + switch (def->type) { |
4145 | + case VIR_DOMAIN_VIDEO_TYPE_CIRRUS: |
4146 | + *vendor = QEMU_PCI_VENDOR_CIRRUS; |
4147 | + *product = QEMU_PCI_PRODUCT_VGA_CIRRUS; |
4148 | + break; |
4149 | + |
4150 | + case VIR_DOMAIN_VIDEO_TYPE_VGA: |
4151 | + *vendor = QEMU_PCI_VENDOR_QEMU; |
4152 | + *product = QEMU_PCI_PRODUCT_VGA_STDVGA; |
4153 | + break; |
4154 | + |
4155 | + case VIR_DOMAIN_VIDEO_TYPE_VMVGA: |
4156 | + *vendor = QEMU_PCI_VENDOR_VMWARE; |
4157 | + *product = QEMU_PCI_PRODUCT_VGA_VMWARE; |
4158 | + break; |
4159 | + |
4160 | + default: |
4161 | + return -1; |
4162 | + } |
4163 | + return 0; |
4164 | +} |
4165 | + |
4166 | +static int |
4167 | +qemuProcessGetPCISoundVendorProduct(virDomainSoundDefPtr def, |
4168 | + unsigned *vendor, |
4169 | + unsigned *product) |
4170 | +{ |
4171 | + switch (def->model) { |
4172 | + case VIR_DOMAIN_SOUND_MODEL_ES1370: |
4173 | + *vendor = QEMU_PCI_VENDOR_ENSONIQ; |
4174 | + *product = QEMU_PCI_PRODUCT_AUDIO_ES1370; |
4175 | + break; |
4176 | + |
4177 | + case VIR_DOMAIN_SOUND_MODEL_AC97: |
4178 | + *vendor = QEMU_PCI_VENDOR_INTEL; |
4179 | + *product = QEMU_PCI_PRODUCT_AUDIO_AC97; |
4180 | + break; |
4181 | + |
4182 | + default: |
4183 | + return -1; |
4184 | + } |
4185 | + |
4186 | + return 0; |
4187 | +} |
4188 | + |
4189 | +static int |
4190 | +qemuProcessGetPCIWatchdogVendorProduct(virDomainWatchdogDefPtr def, |
4191 | + unsigned *vendor, |
4192 | + unsigned *product) |
4193 | +{ |
4194 | + switch (def->model) { |
4195 | + case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB: |
4196 | + *vendor = QEMU_PCI_VENDOR_INTEL; |
4197 | + *product = QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB; |
4198 | + break; |
4199 | + |
4200 | + default: |
4201 | + return -1; |
4202 | + } |
4203 | + |
4204 | + return 0; |
4205 | +} |
4206 | + |
4207 | + |
4208 | +static int |
4209 | +qemuProcessGetPCIMemballoonVendorProduct(virDomainMemballoonDefPtr def, |
4210 | + unsigned *vendor, |
4211 | + unsigned *product) |
4212 | +{ |
4213 | + switch (def->model) { |
4214 | + case VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO: |
4215 | + *vendor = QEMU_PCI_VENDOR_REDHAT; |
4216 | + *product = QEMU_PCI_PRODUCT_BALLOON_VIRTIO; |
4217 | + break; |
4218 | + |
4219 | + default: |
4220 | + return -1; |
4221 | + } |
4222 | + |
4223 | + return 0; |
4224 | +} |
4225 | + |
4226 | + |
4227 | +/* |
4228 | + * This entire method assumes that PCI devices in 'info pci' |
4229 | + * match ordering of devices specified on the command line |
4230 | + * wrt to devices of matching vendor+product |
4231 | + * |
4232 | + * XXXX this might not be a valid assumption if we assign |
4233 | + * some static addrs on CLI. Have to check that... |
4234 | + */ |
4235 | +static int |
4236 | +qemuProcessDetectPCIAddresses(virDomainObjPtr vm, |
4237 | + qemuMonitorPCIAddress *addrs, |
4238 | + int naddrs) |
4239 | +{ |
4240 | + unsigned int vendor = 0, product = 0; |
4241 | + int i; |
4242 | + |
4243 | + /* XXX should all these vendor/product IDs be kept in the |
4244 | + * actual device data structure instead ? |
4245 | + */ |
4246 | + |
4247 | + for (i = 0 ; i < vm->def->ndisks ; i++) { |
4248 | + if (qemuProcessGetPCIDiskVendorProduct(vm->def->disks[i], &vendor, &product) < 0) |
4249 | + continue; |
4250 | + |
4251 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->disks[i]->info), |
4252 | + vendor, product, |
4253 | + addrs, naddrs) < 0) { |
4254 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4255 | + _("cannot find PCI address for VirtIO disk %s"), |
4256 | + vm->def->disks[i]->dst); |
4257 | + return -1; |
4258 | + } |
4259 | + } |
4260 | + |
4261 | + for (i = 0 ; i < vm->def->nnets ; i++) { |
4262 | + if (qemuProcessGetPCINetVendorProduct(vm->def->nets[i], &vendor, &product) < 0) |
4263 | + continue; |
4264 | + |
4265 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->nets[i]->info), |
4266 | + vendor, product, |
4267 | + addrs, naddrs) < 0) { |
4268 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4269 | + _("cannot find PCI address for %s NIC"), |
4270 | + vm->def->nets[i]->model); |
4271 | + return -1; |
4272 | + } |
4273 | + } |
4274 | + |
4275 | + for (i = 0 ; i < vm->def->ncontrollers ; i++) { |
4276 | + if (qemuProcessGetPCIControllerVendorProduct(vm->def->controllers[i], &vendor, &product) < 0) |
4277 | + continue; |
4278 | + |
4279 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->controllers[i]->info), |
4280 | + vendor, product, |
4281 | + addrs, naddrs) < 0) { |
4282 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4283 | + _("cannot find PCI address for controller %s"), |
4284 | + virDomainControllerTypeToString(vm->def->controllers[i]->type)); |
4285 | + return -1; |
4286 | + } |
4287 | + } |
4288 | + |
4289 | + for (i = 0 ; i < vm->def->nvideos ; i++) { |
4290 | + if (qemuProcessGetPCIVideoVendorProduct(vm->def->videos[i], &vendor, &product) < 0) |
4291 | + continue; |
4292 | + |
4293 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->videos[i]->info), |
4294 | + vendor, product, |
4295 | + addrs, naddrs) < 0) { |
4296 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4297 | + _("cannot find PCI address for video adapter %s"), |
4298 | + virDomainVideoTypeToString(vm->def->videos[i]->type)); |
4299 | + return -1; |
4300 | + } |
4301 | + } |
4302 | + |
4303 | + for (i = 0 ; i < vm->def->nsounds ; i++) { |
4304 | + if (qemuProcessGetPCISoundVendorProduct(vm->def->sounds[i], &vendor, &product) < 0) |
4305 | + continue; |
4306 | + |
4307 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->sounds[i]->info), |
4308 | + vendor, product, |
4309 | + addrs, naddrs) < 0) { |
4310 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4311 | + _("cannot find PCI address for sound adapter %s"), |
4312 | + virDomainSoundModelTypeToString(vm->def->sounds[i]->model)); |
4313 | + return -1; |
4314 | + } |
4315 | + } |
4316 | + |
4317 | + |
4318 | + if (vm->def->watchdog && |
4319 | + qemuProcessGetPCIWatchdogVendorProduct(vm->def->watchdog, &vendor, &product) == 0) { |
4320 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->watchdog->info), |
4321 | + vendor, product, |
4322 | + addrs, naddrs) < 0) { |
4323 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4324 | + _("cannot find PCI address for watchdog %s"), |
4325 | + virDomainWatchdogModelTypeToString(vm->def->watchdog->model)); |
4326 | + return -1; |
4327 | + } |
4328 | + } |
4329 | + |
4330 | + if (vm->def->memballoon && |
4331 | + qemuProcessGetPCIMemballoonVendorProduct(vm->def->memballoon, &vendor, &product) == 0) { |
4332 | + if (qemuProcessAssignNextPCIAddress(&(vm->def->memballoon->info), |
4333 | + vendor, product, |
4334 | + addrs, naddrs) < 0) { |
4335 | + virReportError(VIR_ERR_INTERNAL_ERROR, |
4336 | + _("cannot find PCI address for balloon %s"), |
4337 | + virDomainMemballoonModelTypeToString(vm->def->memballoon->model)); |
4338 | + return -1; |
4339 | + } |
4340 | + } |
4341 | + |
4342 | + /* XXX console (virtio) */ |
4343 | + |
4344 | + |
4345 | + /* ... and now things we don't have in our xml */ |
4346 | + |
4347 | + /* XXX USB controller ? */ |
4348 | + |
4349 | + /* XXX what about other PCI devices (ie bridges) */ |
4350 | + |
4351 | + return 0; |
4352 | +} |
4353 | + |
4354 | +static int |
4355 | +qemuProcessInitPCIAddresses(struct qemud_driver *driver, |
4356 | + virDomainObjPtr vm) |
4357 | +{ |
4358 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4359 | + int naddrs; |
4360 | + int ret; |
4361 | + qemuMonitorPCIAddress *addrs = NULL; |
4362 | + |
4363 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
4364 | + naddrs = qemuMonitorGetAllPCIAddresses(priv->mon, |
4365 | + &addrs); |
4366 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
4367 | + |
4368 | + ret = qemuProcessDetectPCIAddresses(vm, addrs, naddrs); |
4369 | + |
4370 | + VIR_FREE(addrs); |
4371 | + |
4372 | + return ret; |
4373 | +} |
4374 | + |
4375 | + |
4376 | +static int qemuProcessNextFreePort(struct qemud_driver *driver, |
4377 | + int startPort) |
4378 | +{ |
4379 | + int i; |
4380 | + |
4381 | + for (i = startPort ; i < driver->remotePortMax; i++) { |
4382 | + int fd; |
4383 | + int reuse = 1; |
4384 | + struct sockaddr_in addr; |
4385 | + bool used = false; |
4386 | + |
4387 | + if (virBitmapGetBit(driver->reservedRemotePorts, |
4388 | + i - driver->remotePortMin, &used) < 0) |
4389 | + VIR_DEBUG("virBitmapGetBit failed on bit %d", i - driver->remotePortMin); |
4390 | + |
4391 | + if (used) |
4392 | + continue; |
4393 | + |
4394 | + addr.sin_family = AF_INET; |
4395 | + addr.sin_port = htons(i); |
4396 | + addr.sin_addr.s_addr = htonl(INADDR_ANY); |
4397 | + fd = socket(PF_INET, SOCK_STREAM, 0); |
4398 | + if (fd < 0) |
4399 | + return -1; |
4400 | + |
4401 | + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)) < 0) { |
4402 | + VIR_FORCE_CLOSE(fd); |
4403 | + break; |
4404 | + } |
4405 | + |
4406 | + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { |
4407 | + /* Not in use, lets grab it */ |
4408 | + VIR_FORCE_CLOSE(fd); |
4409 | + /* Add port to bitmap of reserved ports */ |
4410 | + if (virBitmapSetBit(driver->reservedRemotePorts, |
4411 | + i - driver->remotePortMin) < 0) { |
4412 | + VIR_DEBUG("virBitmapSetBit failed on bit %d", |
4413 | + i - driver->remotePortMin); |
4414 | + } |
4415 | + return i; |
4416 | + } |
4417 | + VIR_FORCE_CLOSE(fd); |
4418 | + |
4419 | + if (errno == EADDRINUSE) { |
4420 | + /* In use, try next */ |
4421 | + continue; |
4422 | + } |
4423 | + /* Some other bad failure, get out.. */ |
4424 | + break; |
4425 | + } |
4426 | + return -1; |
4427 | +} |
4428 | + |
4429 | + |
4430 | +static void |
4431 | +qemuProcessReturnPort(struct qemud_driver *driver, |
4432 | + int port) |
4433 | +{ |
4434 | + if (port < driver->remotePortMin) |
4435 | + return; |
4436 | + |
4437 | + if (virBitmapClearBit(driver->reservedRemotePorts, |
4438 | + port - driver->remotePortMin) < 0) |
4439 | + VIR_DEBUG("Could not mark port %d as unused", port); |
4440 | +} |
4441 | + |
4442 | + |
4443 | +static int |
4444 | +qemuProcessPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED, |
4445 | + virDomainChrDefPtr dev, |
4446 | + void *opaque ATTRIBUTE_UNUSED) |
4447 | +{ |
4448 | + int fd; |
4449 | + if (dev->source.type != VIR_DOMAIN_CHR_TYPE_FILE) |
4450 | + return 0; |
4451 | + |
4452 | + if ((fd = open(dev->source.data.file.path, |
4453 | + O_CREAT | O_APPEND, S_IRUSR|S_IWUSR)) < 0) { |
4454 | + virReportSystemError(errno, |
4455 | + _("Unable to pre-create chardev file '%s'"), |
4456 | + dev->source.data.file.path); |
4457 | + return -1; |
4458 | + } |
4459 | + |
4460 | + VIR_FORCE_CLOSE(fd); |
4461 | + |
4462 | + return 0; |
4463 | +} |
4464 | + |
4465 | + |
4466 | +static int |
4467 | +qemuProcessLimits(struct qemud_driver *driver) |
4468 | +{ |
4469 | + struct rlimit rlim; |
4470 | + |
4471 | + if (driver->maxProcesses > 0) { |
4472 | + rlim.rlim_cur = rlim.rlim_max = driver->maxProcesses; |
4473 | + if (setrlimit(RLIMIT_NPROC, &rlim) < 0) { |
4474 | + virReportSystemError(errno, |
4475 | + _("cannot limit number of processes to %d"), |
4476 | + driver->maxProcesses); |
4477 | + return -1; |
4478 | + } |
4479 | + } |
4480 | + |
4481 | + if (driver->maxFiles > 0) { |
4482 | + /* Max number of opened files is one greater than |
4483 | + * actual limit. See man setrlimit */ |
4484 | + rlim.rlim_cur = rlim.rlim_max = driver->maxFiles + 1; |
4485 | + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { |
4486 | + virReportSystemError(errno, |
4487 | + _("cannot set max opened files to %d"), |
4488 | + driver->maxFiles); |
4489 | + return -1; |
4490 | + } |
4491 | + } |
4492 | + |
4493 | + return 0; |
4494 | +} |
4495 | + |
4496 | + |
4497 | +struct qemuProcessHookData { |
4498 | + virConnectPtr conn; |
4499 | + virDomainObjPtr vm; |
4500 | + struct qemud_driver *driver; |
4501 | + virBitmapPtr nodemask; |
4502 | +}; |
4503 | + |
4504 | +static int qemuProcessHook(void *data) |
4505 | +{ |
4506 | + struct qemuProcessHookData *h = data; |
4507 | + int ret = -1; |
4508 | + int fd; |
4509 | + |
4510 | + /* Some later calls want pid present */ |
4511 | + h->vm->pid = getpid(); |
4512 | + |
4513 | + VIR_DEBUG("Obtaining domain lock"); |
4514 | + /* |
4515 | + * Since we're going to leak the returned FD to QEMU, |
4516 | + * we need to make sure it gets a sensible label. |
4517 | + * This mildly sucks, because there could be other |
4518 | + * sockets the lock driver opens that we don't want |
4519 | + * labelled. So far we're ok though. |
4520 | + */ |
4521 | + if (virSecurityManagerSetSocketLabel(h->driver->securityManager, h->vm->def) < 0) |
4522 | + goto cleanup; |
4523 | + if (virDomainLockProcessStart(h->driver->lockManager, |
4524 | + h->driver->uri, |
4525 | + h->vm, |
4526 | + /* QEMU is always paused initially */ |
4527 | + true, |
4528 | + &fd) < 0) |
4529 | + goto cleanup; |
4530 | + if (virSecurityManagerClearSocketLabel(h->driver->securityManager, h->vm->def) < 0) |
4531 | + goto cleanup; |
4532 | + |
4533 | + if (qemuProcessLimits(h->driver) < 0) |
4534 | + goto cleanup; |
4535 | + |
4536 | + /* This must take place before exec(), so that all QEMU |
4537 | + * memory allocation is on the correct NUMA node |
4538 | + */ |
4539 | + VIR_DEBUG("Moving process to cgroup"); |
4540 | + if (qemuAddToCgroup(h->driver, h->vm->def) < 0) |
4541 | + goto cleanup; |
4542 | + |
4543 | + /* This must be done after cgroup placement to avoid resetting CPU |
4544 | + * affinity */ |
4545 | + if (!h->vm->def->cputune.emulatorpin && |
4546 | + qemuProcessInitCpuAffinity(h->driver, h->vm, h->nodemask) < 0) |
4547 | + goto cleanup; |
4548 | + |
4549 | + if (qemuProcessInitNumaMemoryPolicy(h->vm, h->nodemask) < 0) |
4550 | + goto cleanup; |
4551 | + |
4552 | + VIR_DEBUG("Setting up security labelling"); |
4553 | + if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm->def) < 0) |
4554 | + goto cleanup; |
4555 | + |
4556 | + ret = 0; |
4557 | + |
4558 | +cleanup: |
4559 | + VIR_DEBUG("Hook complete ret=%d", ret); |
4560 | + return ret; |
4561 | +} |
4562 | + |
4563 | +int |
4564 | +qemuProcessPrepareMonitorChr(struct qemud_driver *driver, |
4565 | + virDomainChrSourceDefPtr monConfig, |
4566 | + const char *vm) |
4567 | +{ |
4568 | + monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX; |
4569 | + monConfig->data.nix.listen = true; |
4570 | + |
4571 | + if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor", |
4572 | + driver->libDir, vm) < 0) { |
4573 | + virReportOOMError(); |
4574 | + return -1; |
4575 | + } |
4576 | + |
4577 | + return 0; |
4578 | +} |
4579 | + |
4580 | + |
4581 | +/* |
4582 | + * Precondition: Both driver and vm must be locked, |
4583 | + * and a job must be active. This method will call |
4584 | + * {Enter,Exit}MonitorWithDriver |
4585 | + */ |
4586 | +int |
4587 | +qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, |
4588 | + virConnectPtr conn, virDomainRunningReason reason, |
4589 | + enum qemuDomainAsyncJob asyncJob) |
4590 | +{ |
4591 | + int ret; |
4592 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4593 | + |
4594 | + VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState)); |
4595 | + if (virDomainLockProcessResume(driver->lockManager, driver->uri, |
4596 | + vm, priv->lockState) < 0) { |
4597 | + /* Don't free priv->lockState on error, because we need |
4598 | + * to make sure we have state still present if the user |
4599 | + * tries to resume again |
4600 | + */ |
4601 | + return -1; |
4602 | + } |
4603 | + VIR_FREE(priv->lockState); |
4604 | + |
4605 | + ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob); |
4606 | + if (ret == 0) { |
4607 | + ret = qemuMonitorStartCPUs(priv->mon, conn); |
4608 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
4609 | + } |
4610 | + |
4611 | + if (ret == 0) { |
4612 | + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); |
4613 | + } else { |
4614 | + if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) |
4615 | + VIR_WARN("Unable to release lease on %s", vm->def->name); |
4616 | + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); |
4617 | + } |
4618 | + |
4619 | + return ret; |
4620 | +} |
4621 | + |
4622 | + |
4623 | +int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm, |
4624 | + virDomainPausedReason reason, |
4625 | + enum qemuDomainAsyncJob asyncJob) |
4626 | +{ |
4627 | + int ret; |
4628 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4629 | + |
4630 | + VIR_FREE(priv->lockState); |
4631 | + |
4632 | + ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob); |
4633 | + if (ret == 0) { |
4634 | + ret = qemuMonitorStopCPUs(priv->mon); |
4635 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
4636 | + } |
4637 | + |
4638 | + if (ret == 0) { |
4639 | + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason); |
4640 | + if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) |
4641 | + VIR_WARN("Unable to release lease on %s", vm->def->name); |
4642 | + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); |
4643 | + } |
4644 | + |
4645 | + return ret; |
4646 | +} |
4647 | + |
4648 | + |
4649 | + |
4650 | +static int |
4651 | +qemuProcessNotifyNets(virDomainDefPtr def) |
4652 | +{ |
4653 | + int ii; |
4654 | + |
4655 | + for (ii = 0 ; ii < def->nnets ; ii++) { |
4656 | + virDomainNetDefPtr net = def->nets[ii]; |
4657 | + if (networkNotifyActualDevice(net) < 0) |
4658 | + return -1; |
4659 | + } |
4660 | + return 0; |
4661 | +} |
4662 | + |
4663 | +static int |
4664 | +qemuProcessFiltersInstantiate(virConnectPtr conn, |
4665 | + virDomainDefPtr def) |
4666 | +{ |
4667 | + int err = 0; |
4668 | + int i; |
4669 | + |
4670 | + if (!conn) |
4671 | + return 1; |
4672 | + |
4673 | + for (i = 0 ; i < def->nnets ; i++) { |
4674 | + virDomainNetDefPtr net = def->nets[i]; |
4675 | + if ((net->filter) && (net->ifname)) { |
4676 | + if (virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) { |
4677 | + err = 1; |
4678 | + break; |
4679 | + } |
4680 | + } |
4681 | + } |
4682 | + |
4683 | + return err; |
4684 | +} |
4685 | + |
4686 | +static int |
4687 | +qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm) |
4688 | +{ |
4689 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4690 | + virDomainState state; |
4691 | + virDomainPausedReason reason; |
4692 | + virDomainState newState = VIR_DOMAIN_NOSTATE; |
4693 | + int newReason; |
4694 | + bool running; |
4695 | + char *msg = NULL; |
4696 | + int ret; |
4697 | + |
4698 | + qemuDomainObjEnterMonitorWithDriver(driver, vm); |
4699 | + ret = qemuMonitorGetStatus(priv->mon, &running, &reason); |
4700 | + qemuDomainObjExitMonitorWithDriver(driver, vm); |
4701 | + |
4702 | + if (ret < 0 || !virDomainObjIsActive(vm)) |
4703 | + return -1; |
4704 | + |
4705 | + state = virDomainObjGetState(vm, NULL); |
4706 | + |
4707 | + if (state == VIR_DOMAIN_PAUSED && running) { |
4708 | + newState = VIR_DOMAIN_RUNNING; |
4709 | + newReason = VIR_DOMAIN_RUNNING_UNPAUSED; |
4710 | + msg = strdup("was unpaused"); |
4711 | + } else if (state == VIR_DOMAIN_RUNNING && !running) { |
4712 | + if (reason == VIR_DOMAIN_PAUSED_SHUTTING_DOWN) { |
4713 | + newState = VIR_DOMAIN_SHUTDOWN; |
4714 | + newReason = VIR_DOMAIN_SHUTDOWN_UNKNOWN; |
4715 | + msg = strdup("shutdown"); |
4716 | + } else { |
4717 | + newState = VIR_DOMAIN_PAUSED; |
4718 | + newReason = reason; |
4719 | + ignore_value(virAsprintf(&msg, "was paused (%s)", |
4720 | + virDomainPausedReasonTypeToString(reason))); |
4721 | + } |
4722 | + } else if (state == VIR_DOMAIN_SHUTOFF && running) { |
4723 | + newState = VIR_DOMAIN_RUNNING; |
4724 | + newReason = VIR_DOMAIN_RUNNING_BOOTED; |
4725 | + msg = strdup("finished booting"); |
4726 | + } |
4727 | + |
4728 | + if (newState != VIR_DOMAIN_NOSTATE) { |
4729 | + if (!msg) { |
4730 | + virReportOOMError(); |
4731 | + return -1; |
4732 | + } |
4733 | + |
4734 | + VIR_DEBUG("Domain %s %s while its monitor was disconnected;" |
4735 | + " changing state to %s (%s)", |
4736 | + vm->def->name, |
4737 | + msg, |
4738 | + virDomainStateTypeToString(newState), |
4739 | + virDomainStateReasonToString(newState, newReason)); |
4740 | + VIR_FREE(msg); |
4741 | + virDomainObjSetState(vm, newState, newReason); |
4742 | + } |
4743 | + |
4744 | + return 0; |
4745 | +} |
4746 | + |
4747 | +static int |
4748 | +qemuProcessRecoverMigration(struct qemud_driver *driver, |
4749 | + virDomainObjPtr vm, |
4750 | + virConnectPtr conn, |
4751 | + enum qemuDomainAsyncJob job, |
4752 | + enum qemuMigrationJobPhase phase, |
4753 | + virDomainState state, |
4754 | + int reason) |
4755 | +{ |
4756 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4757 | + |
4758 | + if (job == QEMU_ASYNC_JOB_MIGRATION_IN) { |
4759 | + switch (phase) { |
4760 | + case QEMU_MIGRATION_PHASE_NONE: |
4761 | + case QEMU_MIGRATION_PHASE_PERFORM2: |
4762 | + case QEMU_MIGRATION_PHASE_BEGIN3: |
4763 | + case QEMU_MIGRATION_PHASE_PERFORM3: |
4764 | + case QEMU_MIGRATION_PHASE_PERFORM3_DONE: |
4765 | + case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED: |
4766 | + case QEMU_MIGRATION_PHASE_CONFIRM3: |
4767 | + case QEMU_MIGRATION_PHASE_LAST: |
4768 | + break; |
4769 | + |
4770 | + case QEMU_MIGRATION_PHASE_PREPARE: |
4771 | + VIR_DEBUG("Killing unfinished incoming migration for domain %s", |
4772 | + vm->def->name); |
4773 | + return -1; |
4774 | + |
4775 | + case QEMU_MIGRATION_PHASE_FINISH2: |
4776 | + /* source domain is already killed so let's just resume the domain |
4777 | + * and hope we are all set */ |
4778 | + VIR_DEBUG("Incoming migration finished, resuming domain %s", |
4779 | + vm->def->name); |
4780 | + if (qemuProcessStartCPUs(driver, vm, conn, |
4781 | + VIR_DOMAIN_RUNNING_UNPAUSED, |
4782 | + QEMU_ASYNC_JOB_NONE) < 0) { |
4783 | + VIR_WARN("Could not resume domain %s", vm->def->name); |
4784 | + } |
4785 | + break; |
4786 | + |
4787 | + case QEMU_MIGRATION_PHASE_FINISH3: |
4788 | + /* migration finished, we started resuming the domain but didn't |
4789 | + * confirm success or failure yet; killing it seems safest */ |
4790 | + VIR_DEBUG("Killing migrated domain %s", vm->def->name); |
4791 | + return -1; |
4792 | + } |
4793 | + } else if (job == QEMU_ASYNC_JOB_MIGRATION_OUT) { |
4794 | + switch (phase) { |
4795 | + case QEMU_MIGRATION_PHASE_NONE: |
4796 | + case QEMU_MIGRATION_PHASE_PREPARE: |
4797 | + case QEMU_MIGRATION_PHASE_FINISH2: |
4798 | + case QEMU_MIGRATION_PHASE_FINISH3: |
4799 | + case QEMU_MIGRATION_PHASE_LAST: |
4800 | + break; |
4801 | + |
4802 | + case QEMU_MIGRATION_PHASE_BEGIN3: |
4803 | + /* nothing happen so far, just forget we were about to migrate the |
4804 | + * domain */ |
4805 | + break; |
4806 | + |
4807 | + case QEMU_MIGRATION_PHASE_PERFORM2: |
4808 | + case QEMU_MIGRATION_PHASE_PERFORM3: |
4809 | + /* migration is still in progress, let's cancel it and resume the |
4810 | + * domain */ |
4811 | + VIR_DEBUG("Canceling unfinished outgoing migration of domain %s", |
4812 | + vm->def->name); |
4813 | + qemuDomainObjEnterMonitor(driver, vm); |
4814 | + ignore_value(qemuMonitorMigrateCancel(priv->mon)); |
4815 | + qemuDomainObjExitMonitor(driver, vm); |
4816 | + /* resume the domain but only if it was paused as a result of |
4817 | + * migration */ |
4818 | + if (state == VIR_DOMAIN_PAUSED && |
4819 | + (reason == VIR_DOMAIN_PAUSED_MIGRATION || |
4820 | + reason == VIR_DOMAIN_PAUSED_UNKNOWN)) { |
4821 | + if (qemuProcessStartCPUs(driver, vm, conn, |
4822 | + VIR_DOMAIN_RUNNING_UNPAUSED, |
4823 | + QEMU_ASYNC_JOB_NONE) < 0) { |
4824 | + VIR_WARN("Could not resume domain %s", vm->def->name); |
4825 | + } |
4826 | + } |
4827 | + break; |
4828 | + |
4829 | + case QEMU_MIGRATION_PHASE_PERFORM3_DONE: |
4830 | + /* migration finished but we didn't have a chance to get the result |
4831 | + * of Finish3 step; third party needs to check what to do next |
4832 | + */ |
4833 | + break; |
4834 | + |
4835 | + case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED: |
4836 | + /* Finish3 failed, we need to resume the domain */ |
4837 | + VIR_DEBUG("Resuming domain %s after failed migration", |
4838 | + vm->def->name); |
4839 | + if (state == VIR_DOMAIN_PAUSED && |
4840 | + (reason == VIR_DOMAIN_PAUSED_MIGRATION || |
4841 | + reason == VIR_DOMAIN_PAUSED_UNKNOWN)) { |
4842 | + if (qemuProcessStartCPUs(driver, vm, conn, |
4843 | + VIR_DOMAIN_RUNNING_UNPAUSED, |
4844 | + QEMU_ASYNC_JOB_NONE) < 0) { |
4845 | + VIR_WARN("Could not resume domain %s", vm->def->name); |
4846 | + } |
4847 | + } |
4848 | + break; |
4849 | + |
4850 | + case QEMU_MIGRATION_PHASE_CONFIRM3: |
4851 | + /* migration completed, we need to kill the domain here */ |
4852 | + return -1; |
4853 | + } |
4854 | + } |
4855 | + |
4856 | + return 0; |
4857 | +} |
4858 | + |
4859 | +static int |
4860 | +qemuProcessRecoverJob(struct qemud_driver *driver, |
4861 | + virDomainObjPtr vm, |
4862 | + virConnectPtr conn, |
4863 | + const struct qemuDomainJobObj *job) |
4864 | +{ |
4865 | + qemuDomainObjPrivatePtr priv = vm->privateData; |
4866 | + virDomainState state; |
4867 | + int reason; |
4868 | + |
4869 | + state = virDomainObjGetState(vm, &reason); |
4870 | + |
4871 | + switch (job->asyncJob) { |
4872 | + case QEMU_ASYNC_JOB_MIGRATION_OUT: |
4873 | + case QEMU_ASYNC_JOB_MIGRATION_IN: |
4874 | + if (qemuProcessRecoverMigration(driver, vm, conn, job->asyncJob, |
4875 | + job->phase, state, reason) < 0) |
4876 | + return -1; |
4877 | + break; |
4878 | + |
4879 | + case QEMU_ASYNC_JOB_SAVE: |
4880 | + case QEMU_ASYNC_JOB_DUMP: |
4881 | + qemuDomainObjEnterMonitor(driver, vm); |
4882 | + ignore_value(qemuMonitorMigrateCancel(priv->mon)); |
4883 | + qemuDomainObjExitMonitor(driver, vm); |
4884 | + /* resume the domain but only if it was paused as a result of |
4885 | + * running save/dump operation. Although we are recovering an |
4886 | + * async job, this function is run at startup and must resume |
4887 | + * things using sync monitor connections. */ |
4888 | + if (state == VIR_DOMAIN_PAUSED && |
4889 | + ((job->asyncJob == QEMU_ASYNC_JOB_DUMP && |
4890 | + reason == VIR_DOMAIN_PAUSED_DUMP) || |
4891 | + (job->asyncJob == QEMU_ASYNC_JOB_SAVE && |
4892 | + reason == VIR_DOMAIN_PAUSED_SAVE) || |
4893 | + reason == VIR_DOMAIN_PAUSED_UNKNOWN)) { |
4894 | + if (qemuProcessStartCPUs(driver, vm, conn, |
4895 | + VIR_DOMAIN_RUNNING_UNPAUSED, |
4896 | + QEMU_ASYNC_JOB_NONE) < 0) { |
4897 | + VIR_WARN("Could not resume domain %s after", vm->def->name); |
4898 | + } |
4899 | + } |
4900 | + break; |
4901 | + |
4902 | + case QEMU_ASYNC_JOB_NONE: |
4903 | + case QEMU_ASYNC_JOB_LAST: |
4904 | + break; |
4905 | + } |
4906 | + |
4907 | + if (!virDomainObjIsActive(vm)) |
4908 | + return -1; |
4909 | + |
4910 | + /* In case any special handling is added for job type that has been ignored |
4911 | + * before, QEMU_DOMAIN_TRACK_JOBS (from qemu_domain.h) needs to be updated |
4912 | + * for the job to be properly tracked in domain state XML. |
4913 | + */ |
4914 | + switch (job->active) { |
4915 | + case QEMU_JOB_QUERY: |
4916 | + /* harmless */ |
4917 | + break; |
4918 | + |
4919 | + case QEMU_JOB_DESTROY: |
4920 | + VIR_DEBUG("Domain %s should have already been destroyed", |
4921 | + vm->def->name); |
4922 | + return -1; |
4923 | + |
4924 | + case QEMU_JOB_SUSPEND: |
4925 | + /* mostly harmless */ |
4926 | + break; |
4927 | + |
4928 | + case QEMU_JOB_MODIFY: |
4929 | + /* XXX depending on the command we may be in an inconsistent state and |
4930 | + * we should probably fall back to "monitor error" state and refuse to |
4931 | + */ |
4932 | + break; |
4933 | + |
4934 | + case QEMU_JOB_MIGRATION_OP: |
4935 | + case QEMU_JOB_ABORT: |
4936 | + case QEMU_JOB_ASYNC: |
4937 | + case QEMU_JOB_ASYNC_NESTED: |
4938 | + /* async job was already handled above */ |
4939 | + case QEMU_JOB_NONE: |
4940 | + case QEMU_JOB_LAST: |
4941 | + break; |
4942 | + } |
4943 | + |
4944 | + return 0; |
4945 | +} |
4946 | + |
4947 | +struct qemuProcessReconnectData { |
4948 | + virConnectPtr conn; |
4949 | + struct qemud_driver *driver; |
4950 | + void *payload; |
4951 | + struct qemuDomainJobObj oldjob; |
4952 | +}; |
4953 | +/* |
4954 | + * Open an existing VM's monitor, re-detect VCPU threads |
4955 | + * and re-reserve the security labels in use |
4956 | + * |
4957 | + * We own the virConnectPtr we are passed here - whoever started |
4958 | + * this thread function has increased the reference counter to it |
4959 | + * so that we now have to close it. |
4960 | + */ |
4961 | +static void |
4962 | +qemuProcessReconnect(void *opaque) |
4963 | +{ |
4964 | + struct qemuProcessReconnectData *data = opaque; |
4965 | + struct qemud_driver *driver = data->driver; |
4966 | + virDomainObjPtr obj = data->payload; |
4967 | + qemuDomainObjPrivatePtr priv; |
4968 | + virConnectPtr conn = data->conn; |
4969 | + struct qemuDomainJobObj oldjob; |
4970 | + int state; |
4971 | + int reason; |
4972 | + |
4973 | + memcpy(&oldjob, &data->oldjob, sizeof(oldjob)); |
4974 | + |
4975 | + VIR_FREE(data); |
4976 | + |
4977 | + qemuDriverLock(driver); |
4978 | + virDomainObjLock(obj); |
4979 | + |
4980 | + |
4981 | + VIR_DEBUG("Reconnect monitor to %p '%s'", obj, obj->def->name); |
4982 | + |
4983 | + priv = obj->privateData; |
4984 | + |
4985 | + /* Job was started by the caller for us */ |
4986 | + qemuDomainObjTransferJob(obj); |
4987 | + |
4988 | + /* Hold an extra reference because we can't allow 'vm' to be |
4989 | + * deleted if qemuConnectMonitor() failed */ |
4990 | + virObjectRef(obj); |
4991 | + |
4992 | + /* XXX check PID liveliness & EXE path */ |
4993 | + if (qemuConnectMonitor(driver, obj) < 0) |
4994 | + goto error; |
4995 | + |
4996 | + /* Failure to connect to agent shouldn't be fatal */ |
4997 | + if (qemuConnectAgent(driver, obj) < 0) { |
4998 | + VIR_WARN("Cannot connect to QEMU guest agent for %s", |
4999 | + obj->def->name); |
5000 | + virResetLastError(); |