File: guestfs-internals.1

package info (click to toggle)
libguestfs 1%3A1.40.2-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 123,660 kB
  • sloc: ansic: 460,074; ml: 63,059; sh: 14,955; java: 9,512; makefile: 9,133; cs: 6,300; haskell: 5,652; python: 3,856; perl: 3,619; erlang: 2,435; xml: 1,683; ruby: 350; pascal: 255; lex: 135; yacc: 128; cpp: 10
file content (499 lines) | stat: -rw-r--r-- 21,874 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
.\" Automatically generated by Podwrapper::Man 1.40.2 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "guestfs-internals 1"
.TH guestfs-internals 1 "2019-02-07" "libguestfs-1.40.2" "Virtualization Support"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "名前"
.IX Header "名前"
guestfs-internals \- architecture and internals of libguestfs
.SH "説明"
.IX Header "説明"
This manual page is for hackers who want to understand how libguestfs works
internally.  This is just a description of how libguestfs works now, and it
may change at any time in the future.
.SH "アーキテクチャー"
.IX Header "アーキテクチャー"
内部的に、libguestfs は \fBqemu\fR\|(1)
を使用してアプライアンス(特別な形式の小さな仮想マシン)を実行することにより実装されます。QEMU はメインプログラムの子プロセスとして実行します。
.PP
.Vb 10
\& ┌───────────────────┐
\& │ main program      │
\& │                   │
\& │                   │           child process / appliance
\& │                   │          ┌──────────────────────────┐
\& │                   │          │ qemu                     │
\& ├───────────────────┤   RPC    │      ┌─────────────────┐ │
\& │ libguestfs  ◀╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ guestfsd        │ │
\& │                   │          │      ├─────────────────┤ │
\& └───────────────────┘          │      │ Linux kernel    │ │
\&                                │      └────────┬────────┘ │
\&                                └───────────────│──────────┘
\&                                                │
\&                                                │ virtio\-scsi
\&                                         ┌──────┴──────┐
\&                                         │  Device or  │
\&                                         │  disk image │
\&                                         └─────────────┘
.Ve
.PP
The library, linked to the main program, creates the child process and hence
the appliance in the \*(L"guestfs_launch\*(R" in \fBguestfs\fR\|(3) function.
.PP
Inside the appliance is a Linux kernel and a complete stack of userspace
tools (such as \s-1LVM\s0 and ext2 programs) and a small controlling daemon called
\&\*(L"guestfsd\*(R".  The library talks to \*(L"guestfsd\*(R" using remote procedure
calls (\s-1RPC\s0).  There is a mostly one-to-one correspondence between libguestfs
\&\s-1API\s0 calls and \s-1RPC\s0 calls to the daemon.  Lastly the disk image(s) are
attached to the qemu process which translates device access by the
appliance’s Linux kernel into accesses to the image.
.PP
A common misunderstanding is that the appliance \*(L"is\*(R" the virtual machine.
Although the disk image you are attached to might also be used by some
virtual machine, libguestfs doesn't know or care about this.  (But you will
care if both libguestfs’s qemu process and your virtual machine are trying
to update the disk image at the same time, since these usually results in
massive disk corruption).
.SH "状態マシン"
.IX Header "状態マシン"
libguestfs は子プロセスをモデル化するために状態マシンを使用します:
.PP
.Vb 10
\&                         |
\&          guestfs_create / guestfs_create_flags
\&                         |
\&                         |
\&                     _\|_\|_\|_V_\|_\|_\|_\|_
\&                    /          \e
\&                    |   設定   |
\&                    \e_\|_\|_\|_\|_\|_\|_\|_\|_\|_/
\&                       ^   ^  \e
\&                       |    \e  \e guestfs_launch
\&                       |    _\e_\|_V_\|_\|_\|_\|_\|_
\&                       |   /           \e
\&                       |   |  起動中   |
\&                       |   \e_\|_\|_\|_\|_\|_\|_\|_\|_\|_\|_/
\&                       |       /
\&                       |  guestfs_launch
\&                       |     /
\&                  _\|_\|_\|_\|_|_\|_\|_\|_V
\&                 /        \e
\&                 | 準備完了  |
\&                 \e_\|_\|_\|_\|_\|_\|_\|_\|_\|_\|_/
\&The normal transitions are (1) CONFIG (when the handle is created, but there
\&is no child process), (2) LAUNCHING (when the child process is booting up),
\&(3) READY meaning the appliance is up, actions can be issued to, and carried
\&out by, the child process.
.Ve
.PP
The guest may be killed by \*(L"guestfs_kill_subprocess\*(R" in \fBguestfs\fR\|(3), or may die
asynchronously at any time (eg. due to some internal error), and that causes
the state to transition back to \s-1CONFIG.\s0
.PP
Configuration commands for qemu such as \*(L"guestfs_set_path\*(R" in \fBguestfs\fR\|(3) can
only be issued when in the \s-1CONFIG\s0 state.
.PP
The \s-1API\s0 offers one call that goes from \s-1CONFIG\s0 through \s-1LAUNCHING\s0 to \s-1READY.\s0
\&\*(L"guestfs_launch\*(R" in \fBguestfs\fR\|(3) blocks until the child process is \s-1READY\s0 to
accept commands (or until some failure or timeout).
\&\*(L"guestfs_launch\*(R" in \fBguestfs\fR\|(3) internally moves the state from \s-1CONFIG\s0 to
\&\s-1LAUNCHING\s0 while it is running.
.PP
\&\s-1API\s0 actions such as \*(L"guestfs_mount\*(R" in \fBguestfs\fR\|(3) can only be issued when in
the \s-1READY\s0 state.  These \s-1API\s0 calls block waiting for the command to be
carried out.  There are no non-blocking versions, and no way to issue more
than one command per handle at the same time.
.PP
Finally, the child process sends asynchronous messages back to the main
program, such as kernel log messages.  You can register a callback to
receive these messages.
.SH "内部構造"
.IX Header "内部構造"
.SS "アプライアンスの起動プロセス"
.IX Subsection "アプライアンスの起動プロセス"
このプロセスは進化してきました。そして、進化し続けます。ここの記述は現在のバージョンの libguestfs
にのみ対応していて、参考情報としてのみ提供されます。
.PP
以下に関係する段階に従うには libguestfs デバッグを有効にします(環境変数 \f(CW\*(C`LIBGUESTFS_DEBUG=1\*(C'\fR を設定します)。
.IP "アプライアンスを作成します" 4
.IX Item "アプライアンスを作成します"
\&\f(CW\*(C`supermin \-\-build\*(C'\fR is invoked to create the kernel, a small initrd and the
appliance.
.Sp
The appliance is cached in \fI/var/tmp/.guestfs\-<\s-1UID\s0>\fR (or in another
directory if \f(CW\*(C`LIBGUESTFS_CACHEDIR\*(C'\fR or \f(CW\*(C`TMPDIR\*(C'\fR are set).
.Sp
For a complete description of how the appliance is created and cached, read
the \fBsupermin\fR\|(1) man page.
.IP "\s-1QEMU\s0 を開始してカーネルを起動します" 4
.IX Item "QEMU を開始してカーネルを起動します"
カーネルを起動するために \s-1QEMU\s0 が呼び出されます。
.IP "initrd を実行します" 4
.IX Item "initrd を実行します"
\&\f(CW\*(C`supermin \-\-build\*(C'\fR builds a small initrd.  The initrd is not the
appliance.  The purpose of the initrd is to load enough kernel modules in
order that the appliance itself can be mounted and started.
.Sp
The initrd is a cpio archive called
\&\fI/var/tmp/.guestfs\-<\s-1UID\s0>/appliance.d/initrd\fR.
.Sp
initrd が起動したとき、カーネルモジュールが読み込まれたことを示すこのようなメッセージが表示されます:
.Sp
.Vb 4
\& supermin: ext2 mini initrd starting up
\& supermin: mounting /sys
\& supermin: internal insmod libcrc32c.ko
\& supermin: internal insmod crc32c\-intel.ko
.Ve
.IP "アプライアンスデバイスを検索およびマウントします" 4
.IX Item "アプライアンスデバイスを検索およびマウントします"
The appliance is a sparse file containing an ext2 filesystem which contains
a familiar (although reduced in size) Linux operating system.  It would
normally be called \fI/var/tmp/.guestfs\-<\s-1UID\s0>/appliance.d/root\fR.
.Sp
The regular disks being inspected by libguestfs are the first devices
exposed by qemu (eg. as \fI/dev/vda\fR).
.Sp
The last disk added to qemu is the appliance itself (eg. \fI/dev/vdb\fR if
there was only one regular disk).
.Sp
Thus the final job of the initrd is to locate the appliance disk, mount it,
and switch root into the appliance, and run \fI/init\fR from the appliance.
.Sp
If this works successfully you will see messages such as:
.Sp
.Vb 5
\& supermin: picked /sys/block/vdb/dev as root device
\& supermin: creating /dev/root as block special 252:16
\& supermin: mounting new root on /root
\& supermin: chroot
\& Starting /init script ...
.Ve
.Sp
Note that \f(CW\*(C`Starting /init script ...\*(C'\fR indicates that the appliance's init
script is now running.
.IP "アプライアンスを初期化します" 4
.IX Item "アプライアンスを初期化します"
The appliance itself now initializes itself.  This involves starting certain
processes like \f(CW\*(C`udev\*(C'\fR, possibly printing some debug information, and
finally running the daemon (\f(CW\*(C`guestfsd\*(C'\fR).
.IP "デーモン" 4
.IX Item "デーモン"
Finally the daemon (\f(CW\*(C`guestfsd\*(C'\fR) runs inside the appliance.  If it runs you
should see:
.Sp
.Vb 1
\& verbose daemon enabled
.Ve
.Sp
The daemon expects to see a named virtio-serial port exposed by qemu and
connected on the other end to the library.
.Sp
The daemon connects to this port (and hence to the library) and sends a four
byte message \f(CW\*(C`GUESTFS_LAUNCH_FLAG\*(C'\fR, which initiates the communication
protocol (see below).
.SS "通信プロトコル"
.IX Subsection "通信プロトコル"
Don’t rely on using this protocol directly.  This section documents how it
currently works, but it may change at any time.
.PP
The protocol used to talk between the library and the daemon running inside
the qemu virtual machine is a simple \s-1RPC\s0 mechanism built on top of \s-1XDR\s0 (\s-1RFC
1014, RFC 1832, RFC 4506\s0).
.PP
The detailed format of structures is in
\&\fIcommon/protocol/guestfs_protocol.x\fR (note: this file is automatically
generated).
.PP
There are two broad cases, ordinary functions that don’t have any \f(CW\*(C`FileIn\*(C'\fR
and \f(CW\*(C`FileOut\*(C'\fR parameters, which are handled with very simple request/reply
messages.  Then there are functions that have any \f(CW\*(C`FileIn\*(C'\fR or \f(CW\*(C`FileOut\*(C'\fR
parameters, which use the same request and reply messages, but they may also
be followed by files sent using a chunked encoding.
.PP
\fI\s-1ORDINARY FUNCTIONS\s0 (\s-1NO FILEIN/FILEOUT PARAMS\s0)\fR
.IX Subsection "ORDINARY FUNCTIONS (NO FILEIN/FILEOUT PARAMS)"
.PP
For ordinary functions, the request message is:
.PP
.Vb 4
\& total length (header + arguments,
\&      but not including the length word itself)
\& struct guestfs_message_header (encoded as XDR)
\& struct guestfs_<foo>_args (encoded as XDR)
.Ve
.PP
The total length field allows the daemon to allocate a fixed size buffer
into which it slurps the rest of the message.  As a result, the total length
is limited to \f(CW\*(C`GUESTFS_MESSAGE_MAX\*(C'\fR bytes (currently 4MB), which means the
effective size of any request is limited to somewhere under this size.
.PP
Note also that many functions don’t take any arguments, in which case the
\&\f(CW\*(C`guestfs_\f(CIfoo\f(CW_args\*(C'\fR is completely omitted.
.PP
The header contains the procedure number (\f(CW\*(C`guestfs_proc\*(C'\fR) which is how the
receiver knows what type of args structure to expect, or none at all.
.PP
For functions that take optional arguments, the optional arguments are
encoded in the \f(CW\*(C`guestfs_\f(CIfoo\f(CW_args\*(C'\fR structure in the same way as ordinary
arguments.  A bitmask in the header indicates which optional arguments are
meaningful.  The bitmask is also checked to see if it contains bits set
which the daemon does not know about (eg. if more optional arguments were
added in a later version of the library), and this causes the call to be
rejected.
.PP
The reply message for ordinary functions is:
.PP
.Vb 4
\& total length (header + ret,
\&      but not including the length word itself)
\& struct guestfs_message_header (encoded as XDR)
\& struct guestfs_<foo>_ret (encoded as XDR)
.Ve
.PP
As above the \f(CW\*(C`guestfs_\f(CIfoo\f(CW_ret\*(C'\fR structure may be completely omitted for
functions that return no formal return values.
.PP
As above the total length of the reply is limited to \f(CW\*(C`GUESTFS_MESSAGE_MAX\*(C'\fR.
.PP
In the case of an error, a flag is set in the header, and the reply message
is slightly changed:
.PP
.Vb 4
\& total length (header + error,
\&      but not including the length word itself)
\& struct guestfs_message_header (encoded as XDR)
\& struct guestfs_message_error (encoded as XDR)
.Ve
.PP
\&\f(CW\*(C`guestfs_message_error\*(C'\fR の構造は、文字列としてエラーメッセージを含みます。
.PP
\fI\s-1FUNCTIONS THAT HAVE FILEIN PARAMETERS\s0\fR
.IX Subsection "FUNCTIONS THAT HAVE FILEIN PARAMETERS"
.PP
A \f(CW\*(C`FileIn\*(C'\fR parameter indicates that we transfer a file \fIinto\fR the guest.
The normal request message is sent (see above).  However this is followed by
a sequence of file chunks.
.PP
.Vb 7
\& total length (header + arguments,
\&      but not including the length word itself,
\&      and not including the chunks)
\& struct guestfs_message_header (encoded as XDR)
\& struct guestfs_<foo>_args (encoded as XDR)
\& sequence of chunks for FileIn param #0
\& sequence of chunks for FileIn param #1 etc.
.Ve
.PP
The \*(L"sequence of chunks\*(R" is:
.PP
.Vb 7
\& length of chunk (not including length word itself)
\& struct guestfs_chunk (encoded as XDR)
\& length of chunk
\& struct guestfs_chunk (encoded as XDR)
\&   ...
\& length of chunk
\& struct guestfs_chunk (with data.data_len == 0)
.Ve
.PP
The final chunk has the \f(CW\*(C`data_len\*(C'\fR field set to zero.  Additionally a flag
is set in the final chunk to indicate either successful completion or early
cancellation.
.PP
At time of writing there are no functions that have more than one FileIn
parameter.  However this is (theoretically) supported, by sending the
sequence of chunks for each FileIn parameter one after another (from left to
right).
.PP
Both the library (sender) \fIand\fR the daemon (receiver) may cancel the
transfer.  The library does this by sending a chunk with a special flag set
to indicate cancellation.  When the daemon sees this, it cancels the whole
\&\s-1RPC,\s0 does \fInot\fR send any reply, and goes back to reading the next request.
.PP
The daemon may also cancel.  It does this by writing a special word
\&\f(CW\*(C`GUESTFS_CANCEL_FLAG\*(C'\fR to the socket.  The library listens for this during
the transfer, and if it gets it, it will cancel the transfer (it sends a
cancel chunk).  The special word is chosen so that even if cancellation
happens right at the end of the transfer (after the library has finished
writing and has started listening for the reply), the \*(L"spurious\*(R" cancel flag
will not be confused with the reply message.
.PP
This protocol allows the transfer of arbitrary sized files (no 32 bit
limit), and also files where the size is not known in advance (eg. from
pipes or sockets).  However the chunks are rather small
(\f(CW\*(C`GUESTFS_MAX_CHUNK_SIZE\*(C'\fR), so that neither the library nor the daemon need
to keep much in memory.
.PP
\fI\s-1FUNCTIONS THAT HAVE FILEOUT PARAMETERS\s0\fR
.IX Subsection "FUNCTIONS THAT HAVE FILEOUT PARAMETERS"
.PP
The protocol for FileOut parameters is exactly the same as for FileIn
parameters, but with the roles of daemon and library reversed.
.PP
.Vb 7
\& total length (header + ret,
\&      but not including the length word itself,
\&      and not including the chunks)
\& struct guestfs_message_header (encoded as XDR)
\& struct guestfs_<foo>_ret (encoded as XDR)
\& sequence of chunks for FileOut param #0
\& sequence of chunks for FileOut param #1 etc.
.Ve
.PP
\fI初期メッセージ\fR
.IX Subsection "初期メッセージ"
.PP
When the daemon launches it sends an initial word (\f(CW\*(C`GUESTFS_LAUNCH_FLAG\*(C'\fR)
which indicates that the guest and daemon is alive.  This is what
\&\*(L"guestfs_launch\*(R" in \fBguestfs\fR\|(3) waits for.
.PP
\fI\s-1PROGRESS NOTIFICATION MESSAGES\s0\fR
.IX Subsection "PROGRESS NOTIFICATION MESSAGES"
.PP
The daemon may send progress notification messages at any time.  These are
distinguished by the normal length word being replaced by
\&\f(CW\*(C`GUESTFS_PROGRESS_FLAG\*(C'\fR, followed by a fixed size progress message.
.PP
The library turns them into progress callbacks (see
\&\*(L"\s-1GUESTFS_EVENT_PROGRESS\*(R"\s0 in \fBguestfs\fR\|(3)) if there is a callback registered, or
discards them if not.
.PP
The daemon self-limits the frequency of progress messages it sends (see
\&\f(CW\*(C`daemon/proto.c:notify_progress\*(C'\fR).  Not all calls generate progress
messages.
.SS "固定アプライアンス"
.IX Subsection "固定アプライアンス"
When libguestfs (or libguestfs tools) are run, they search a path looking
for an appliance.  The path is built into libguestfs, or can be set using
the \f(CW\*(C`LIBGUESTFS_PATH\*(C'\fR environment variable.
.PP
Normally a supermin appliance is located on this path (see
\&\*(L"\s-1SUPERMIN APPLIANCE\*(R"\s0 in \fBsupermin\fR\|(1)).  libguestfs reconstructs this into a
full appliance by running \f(CW\*(C`supermin \-\-build\*(C'\fR.
.PP
However, a simpler \*(L"fixed appliance\*(R" can also be used.  libguestfs detects
this by looking for a directory on the path containing all the following
files:
.IP "\(bu" 4
\&\fIkernel\fR
.IP "\(bu" 4
\&\fIinitrd\fR
.IP "\(bu" 4
\&\fIroot\fR
.IP "\(bu" 4
\&\fI\s-1README\s0.fixed\fR (note that it \fBmust\fR be present as well)
.PP
If the fixed appliance is found, libguestfs skips supermin entirely and just
runs the virtual machine (using qemu or the current backend, see
\&\*(L"\s-1BACKEND\*(R"\s0 in \fBguestfs\fR\|(3)) with the kernel, initrd and root disk from the fixed
appliance.
.PP
Thus the fixed appliance can be used when a platform or a Linux distribution
does not support supermin.  You build the fixed appliance on a platform that
does support supermin using \fBlibguestfs\-make\-fixed\-appliance\fR\|(1), copy it
over, and use that to run libguestfs.
.SH "関連項目"
.IX Header "関連項目"
\&\fBguestfs\fR\|(3), \fBguestfs\-hacking\fR\|(1), \fBguestfs\-examples\fR\|(3),
\&\fBlibguestfs\-test\-tool\fR\|(1), \fBlibguestfs\-make\-fixed\-appliance\fR\|(1),
http://libguestfs.org/.
.SH "著者"
.IX Header "著者"
Richard W.M. Jones (\f(CW\*(C`rjones at redhat dot com\*(C'\fR)
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright (C) 2009\-2019 Red Hat Inc.
.SH "LICENSE"
.IX Header "LICENSE"
.SH "BUGS"
.IX Header "BUGS"
To get a list of bugs against libguestfs, use this link:
https://bugzilla.redhat.com/buglist.cgi?component=libguestfs&product=Virtualization+Tools
.PP
To report a new bug against libguestfs, use this link:
https://bugzilla.redhat.com/enter_bug.cgi?component=libguestfs&product=Virtualization+Tools
.PP
When reporting a bug, please supply:
.IP "\(bu" 4
The version of libguestfs.
.IP "\(bu" 4
Where you got libguestfs (eg. which Linux distro, compiled from source, etc)
.IP "\(bu" 4
Describe the bug accurately and give a way to reproduce it.
.IP "\(bu" 4
Run \fBlibguestfs\-test\-tool\fR\|(1) and paste the \fBcomplete, unedited\fR
output into the bug report.