Re: [Libguestfs] virt-builder problem
by Richard W.M. Jones
On Tue, Jun 23, 2020 at 06:14:06PM +0800, 雁渡寒潭 wrote:
> hello: I yum install libguestfs-tools,when I run virt-builder -l
> error:
> curl: (56) Recv failure: Connection reset by peer
> virt-builder: error: external command ‘'curl' -q --config
> '/tmp/virt-builder.sVjrSV/guestfscurl53f9ac.conf'’ exited with error 56
Possibly a problem reaching http://builder.libguestfs.org/ ?
It might be blocked in some countries.
> this is detailed:
> /usr/bin/gpg2 --homedir /tmp/virt-builder.sVjrSV/vb.gpghome.1AUiGm --verify --status-file '/tmp/virt-builder.sVjrSV/vbstatc04e44.txt' '/tmp/virt-builder.sVjrSV/vbcache1f47e5.txt'
> gpg: Signature made Tue 16 Jun 2020 07:48:27 PM CST using RSA key ID E1B768A0
> gpg: Good signature from "Richard W.M. Jones <rjones(a)redhat.com>"
> gpg: aka "Richard W.M. Jones <rich(a)annexia.org>"
> /usr/bin/gpg2 --homedir /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd --list-keys
> gpg: keyring `/tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd/pubring.gpg' created
> gpg: /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd/trustdb.gpg: trustdb created
> /usr/bin/gpg2 --homedir /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd --status-file '/tmp/virt-builder.sVjrSV/vbstatf02a5b.txt' --import '/etc/xdg/virt-builder/repos.d/libguestfs.gpg'
> gpg: keyring `/tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd/secring.gpg' created
> gpg: key E1B768A0: public key "Richard W.M. Jones <rjones(a)redhat.com>" imported
> gpg: Total number processed: 1
> gpg: imported: 1 (RSA: 1)
> /usr/bin/gpg2 --homedir /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd --trusted-key '91738F73E1B768A0' --list-keys
> gpg: key E1B768A0 marked as ultimately trusted
> gpg: checking the trustdb
> gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
> gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
> /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd/pubring.gpg
> ------------------------------------------------------
> pub 4096R/E1B768A0 2011-10-11
> uid Richard W.M. Jones <rjones(a)redhat.com>
> uid Richard W.M. Jones <rich(a)annexia.org>
> sub 4096R/2D07308A 2011-10-11
>
>
> /usr/bin/gpg2 --homedir /tmp/virt-builder.sVjrSV/vb.gpghome.YDYcXd --with-colons --with-fingerprint --with-fingerprint --list-keys F7774FB1AD074A7E8C8767EA91738F73E1B768A0
> % Total % Received % Xferd Average Speed Time Time Time Current
> Dload Upload Total Spent Left Speed
> 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
> curl: (56) Recv failure: Connection reset by peer
> virt-builder: error: external command ‘'curl' -q --config
> '/tmp/virt-builder.sVjrSV/guestfscurl53f9ac.conf'’ exited with error 56
> rm -rf '/tmp/virt-builder.sVjrSV'
> index file (http://download.opensuse.org/repositories/Virtualization:/virt-builder-im...) after parsing (C parser):
> [opensuse-13.1]
> name=openSUSE 13.1
> osinfo=opensuse13.1
> file=http://download.opensuse.org/repositories/Virtualization:/virt-build...
> arch=x86_64
> checksum[sha512]=feca65e4801e93c63ed6361f03c8577fc23e1e83f2f23404483ab1980d5c1da2520ba55542df8097832d9d3fbc4be231648c206d7089d5aec5efb369fb88f41a
> revision=232
> format=qcow2
> size=6441402368
> compressed_size=337112892
> expand=/dev/sda1
> notes=This openSUSE image only contains the base pattern. It is
> designed to run as either KVM or Xen HVM guest.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages. http://libguestfs.org
4 years, 4 months
virt-customize --selinux-relabel
by Nicholas Hardiman
I'm setting up a test VM network for myself.
Is this a good forum for questions?
For instance, I've just stumbled over SElinux type of /etc/machine-info.
Type was unlabeled_t, not hostname_etc_t.
I probably broke it by running virt-customize --hostname
myhost.example.com without
adding the option --selinux-relabel.
Is this the kind of thing I can ping this mailing list about?
Many thanks, Nick
--
Nick Hardiman, RHCE
Senior Consultant
Red Hat <https://www.redhat.com/>
nhardima(a)redhat.com
M: 07585-206195
<https://www.redhat.com/>
4 years, 4 months
[PATCH nbdkit 1/2] server: Add .after_fork callback, mainly for plugins to create threads.
by Richard W.M. Jones
If you have a plugin which either creates background threads itself or
uses a library that creates background threads, it turns out you
cannot create these in .get_ready (or earlier). The reason is that
nbdkit forks when either daemonizing itself or using the --run option,
and fork cancels all the background threads in the child process (the
daemonized or captive nbdkit).
The only good solution here is to add a new callback which I've called
.after_fork which runs after either daemonization or the --run
function.
It should be used sparingly because it's not possible to report errors
nicely from this callback. In particular when daemonizing we have
lost the controlling terminal and errors go to syslog - it looks to
the user as if nbdkit “died”.
This adds the callback to the C and OCaml APIs, and also sh and eval
(to make the tests work), but I didn't update the other language APIs
yet.
---
docs/nbdkit-filter.pod | 39 ++++++++++++++---------
docs/nbdkit-plugin.pod | 49 ++++++++++++++++++++++++++---
plugins/eval/nbdkit-eval-plugin.pod | 2 ++
plugins/sh/nbdkit-sh-plugin.pod | 4 +++
include/nbdkit-filter.h | 2 ++
include/nbdkit-plugin.h | 1 +
server/internal.h | 1 +
server/filters.c | 23 ++++++++++++++
server/main.c | 3 ++
server/plugins.c | 16 ++++++++++
plugins/ocaml/NBDKit.mli | 1 +
plugins/sh/methods.h | 1 +
plugins/ocaml/NBDKit.ml | 4 +++
plugins/eval/eval.c | 2 ++
plugins/ocaml/ocaml.c | 22 +++++++++++++
plugins/sh/methods.c | 25 +++++++++++++++
plugins/sh/sh.c | 1 +
tests/test-eval.sh | 1 +
tests/test-layers-filter.c | 9 ++++++
tests/test-layers-plugin.c | 8 +++++
tests/test-layers.c | 12 +++++++
21 files changed, 207 insertions(+), 19 deletions(-)
diff --git a/docs/nbdkit-filter.pod b/docs/nbdkit-filter.pod
index 00f8e70d..510781e1 100644
--- a/docs/nbdkit-filter.pod
+++ b/docs/nbdkit-filter.pod
@@ -128,23 +128,23 @@ which is required.
F<nbdkit-filter.h> defines some function types (C<nbdkit_next_config>,
C<nbdkit_next_config_complete>, C<nbdkit_next_get_ready>,
-C<nbdkit_next_preconnect>, C<nbdkit_next_open>) and a structure called
-C<struct nbdkit_next_ops>. These abstract the next plugin or filter
-in the chain. There is also an opaque pointer C<nxdata> which must be
-passed along when calling these functions. The value of C<nxdata>
-passed to C<.open> has a stable lifetime that lasts to the
-corresponding C<.close>, with all intermediate functions (such as
-C<.pread>) receiving the same value for convenience; the only
-exceptions where C<nxdata> is not reused are C<.config>,
-C<.config_complete>, C<.get_ready>, and C<.preconnect>, which are
-called outside the lifetime of a connection.
+C<nbdkit_next_after_fork>, C<nbdkit_next_preconnect>,
+C<nbdkit_next_open>) and a structure called C<struct nbdkit_next_ops>.
+These abstract the next plugin or filter in the chain. There is also
+an opaque pointer C<nxdata> which must be passed along when calling
+these functions. The value of C<nxdata> passed to C<.open> has a
+stable lifetime that lasts to the corresponding C<.close>, with all
+intermediate functions (such as C<.pread>) receiving the same value
+for convenience; the only exceptions where C<nxdata> is not reused are
+C<.config>, C<.config_complete>, C<.get_ready>, C<.after_fork> and
+C<.preconnect>, which are called outside the lifetime of a connection.
=head2 Next config, open and close
-The filter’s C<.config>, C<.config_complete>, C<.get_ready> and
-C<.open> methods may only call the next C<.config>,
-C<.config_complete>, C<.get_ready> and C<.open> method in the chain
-(optionally for C<.config>).
+The filter’s C<.config>, C<.config_complete>, C<.get_ready>,
+C<.after_fork> and C<.open> methods may only call the next C<.config>,
+C<.config_complete>, C<.get_ready>, C<.after_fork> and C<.open> method
+in the chain (optionally for C<.config>).
The filter’s C<.close> method is called when an old connection closed,
and this has no C<next> parameter because it cannot be
@@ -304,6 +304,17 @@ filter to get ready to serve requests.
If there is an error, C<.get_ready> should call C<nbdkit_error> with
an error message and return C<-1>.
+=head2 C<.after_fork>
+
+ int (*after_fork) (nbdkit_next_after_fork *next, void *nxdata);
+
+This intercepts the plugin C<.after_fork> method and can be used by
+the filter to start background threads (although these have limited
+usefulness since they will not be able to access the plugin).
+
+If there is an error, C<.after_fork> should call C<nbdkit_error> with
+an error message and return C<-1>.
+
=head2 C<.preconnect>
int (*preconnect) (nbdkit_next_preconnect *next, void *nxdata,
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 7b8a5393..b2f6197b 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -143,6 +143,9 @@ the plugin:
└─────────┬────────┘
│ nbdkit forks into the background
│ and starts serving clients
+ ┌─────────┴────────┐
+ │ after_fork │
+ └─────────┬────────┘
│
┌──────────┴─────────────┬─ ─ ─ ─ ─ ─ ─ ─ ─
┌──────┴─────┐ client #1 │
@@ -201,8 +204,29 @@ script must be prepared for a missing script).
In normal operation, C<.get_ready> is called before the server starts
serving. It is called before the server forks or changes directory.
-It is the last chance to do any global preparation that is needed to
-serve connections.
+It is normally the last chance to do any global preparation that is
+needed to serve connections.
+
+=item C<.after_fork>
+
+In normal operation, C<.after_fork> is called after the server has
+forked into the background and changed UID and directory. If a plugin
+needs to create background threads (or uses an external library that
+creates threads) it should do so here, because background threads are
+killed by fork.
+
+Because the server may have forked into the background, error messages
+and failures from C<.after_fork> cannot be seen by the user unless
+they look through syslog. An error in C<.after_fork> can appear to
+the user as if nbdkit “just died”. So in almost all cases it is
+better to use C<.get_ready> instead of this callback, or to do as much
+preparation work as possible in C<.get_ready> and only start
+background threads here.
+
+The server doesn't always fork (eg. if the I<-f> flag is used), but
+even so this callback will be called. If you want to find out if the
+server forked between C<.get_ready> and C<.after_fork> use
+L<getpid(2)>.
=item C<.preconnect>
@@ -579,13 +603,28 @@ with an error message and return C<-1>.
int get_ready (void);
This optional callback is called before the server starts serving. It
-is called before the server forks or changes directory. It is the
-last chance to do any global preparation that is needed to serve
-connections.
+is called before the server forks or changes directory. It is
+ordinarily the last chance to do any global preparation that is needed
+to serve connections.
If there is an error, C<.get_ready> should call C<nbdkit_error> with
an error message and return C<-1>.
+=head2 C<.after_fork>
+
+ int after_ready (void);
+
+This optional callback is called before the server starts serving. It
+is called after the server forks and changes directory. If a plugin
+needs to create background threads (or uses an external library that
+creates threads) it should do so here, because background threads are
+killed by fork. However you should try to do as little as possible
+here because error reporting is difficult. See L</Callback lifecycle>
+above.
+
+If there is an error, C<.after_fork> should call C<nbdkit_error> with
+an error message and return C<-1>.
+
=head2 C<.preconnect>
int preconnect (int readonly);
diff --git a/plugins/eval/nbdkit-eval-plugin.pod b/plugins/eval/nbdkit-eval-plugin.pod
index c5bebb15..7e25a01f 100644
--- a/plugins/eval/nbdkit-eval-plugin.pod
+++ b/plugins/eval/nbdkit-eval-plugin.pod
@@ -68,6 +68,8 @@ features):
=over 4
+=item B<after_fork=>SCRIPT
+
=item B<cache=>SCRIPT
=item B<can_cache=>SCRIPT
diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index 4d885a53..771c6bc0 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -258,6 +258,10 @@ with status C<1>; unrecognized output is ignored.
/path/to/script get_ready
+=item C<after_fork>
+
+ /path/to/script after_fork
+
=item C<preconnect>
/path/to/script preconnect <readonly> <exportname>
diff --git a/include/nbdkit-filter.h b/include/nbdkit-filter.h
index ca58e496..d81186f5 100644
--- a/include/nbdkit-filter.h
+++ b/include/nbdkit-filter.h
@@ -63,6 +63,7 @@ typedef int nbdkit_next_config (nbdkit_backend *nxdata,
const char *key, const char *value);
typedef int nbdkit_next_config_complete (nbdkit_backend *nxdata);
typedef int nbdkit_next_get_ready (nbdkit_backend *nxdata);
+typedef int nbdkit_next_after_fork (nbdkit_backend *nxdata);
typedef int nbdkit_next_preconnect (nbdkit_backend *nxdata, int readonly);
typedef int nbdkit_next_open (nbdkit_backend *nxdata, int readonly);
@@ -145,6 +146,7 @@ struct nbdkit_filter {
const char *config_help;
int (*thread_model) (void);
int (*get_ready) (nbdkit_next_get_ready *next, nbdkit_backend *nxdata);
+ int (*after_fork) (nbdkit_next_after_fork *next, nbdkit_backend *nxdata);
int (*preconnect) (nbdkit_next_preconnect *next, nbdkit_backend *nxdata,
int readonly);
diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h
index 7ff7bcee..cc261635 100644
--- a/include/nbdkit-plugin.h
+++ b/include/nbdkit-plugin.h
@@ -138,6 +138,7 @@ struct nbdkit_plugin {
int (*preconnect) (int readonly);
int (*get_ready) (void);
+ int (*after_fork) (void);
};
extern void nbdkit_set_error (int err);
diff --git a/server/internal.h b/server/internal.h
index f2b87439..f5653a72 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -362,6 +362,7 @@ struct backend {
void (*config_complete) (struct backend *);
const char *(*magic_config_key) (struct backend *);
void (*get_ready) (struct backend *);
+ void (*after_fork) (struct backend *);
int (*preconnect) (struct backend *, int readonly);
void *(*open) (struct backend *, int readonly);
int (*prepare) (struct backend *, void *handle, int readonly);
diff --git a/server/filters.c b/server/filters.c
index b4f05236..2d705e1e 100644
--- a/server/filters.c
+++ b/server/filters.c
@@ -193,6 +193,28 @@ filter_get_ready (struct backend *b)
b->next->get_ready (b->next);
}
+static int
+next_after_fork (struct backend *b)
+{
+ b->after_fork (b);
+ return 0;
+}
+
+static void
+filter_after_fork (struct backend *b)
+{
+ struct backend_filter *f = container_of (b, struct backend_filter, backend);
+
+ debug ("%s: after_fork", b->name);
+
+ if (f->filter.after_fork) {
+ if (f->filter.after_fork (next_after_fork, b->next) == -1)
+ exit (EXIT_FAILURE);
+ }
+ else
+ b->next->after_fork (b->next);
+}
+
static int
filter_preconnect (struct backend *b, int readonly)
{
@@ -516,6 +538,7 @@ static struct backend filter_functions = {
.config_complete = filter_config_complete,
.magic_config_key = plugin_magic_config_key,
.get_ready = filter_get_ready,
+ .after_fork = filter_after_fork,
.preconnect = filter_preconnect,
.open = filter_open,
.prepare = filter_prepare,
diff --git a/server/main.c b/server/main.c
index e9f95380..c432f5bd 100644
--- a/server/main.c
+++ b/server/main.c
@@ -959,6 +959,7 @@ start_serving (void)
debug ("using socket activation, nr_socks = %zu", socks.size);
change_user ();
write_pidfile ();
+ top->after_fork (top);
accept_incoming_connections (&socks);
return;
}
@@ -967,6 +968,7 @@ start_serving (void)
if (listen_stdin) {
change_user ();
write_pidfile ();
+ top->after_fork (top);
threadlocal_new_server_thread ();
handle_single_connection (saved_stdin, saved_stdout);
return;
@@ -986,6 +988,7 @@ start_serving (void)
change_user ();
fork_into_background ();
write_pidfile ();
+ top->after_fork (top);
accept_incoming_connections (&socks);
}
diff --git a/server/plugins.c b/server/plugins.c
index fa572a6a..285569bb 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -159,6 +159,7 @@ plugin_dump_fields (struct backend *b)
HAS (config_complete);
HAS (config_help);
HAS (get_ready);
+ HAS (after_fork);
HAS (preconnect);
HAS (open);
HAS (close);
@@ -249,6 +250,20 @@ plugin_get_ready (struct backend *b)
exit (EXIT_FAILURE);
}
+static void
+plugin_after_fork (struct backend *b)
+{
+ struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
+
+ debug ("%s: after_fork", b->name);
+
+ if (!p->plugin.after_fork)
+ return;
+
+ if (p->plugin.after_fork () == -1)
+ exit (EXIT_FAILURE);
+}
+
static int
plugin_preconnect (struct backend *b, int readonly)
{
@@ -695,6 +710,7 @@ static struct backend plugin_functions = {
.config_complete = plugin_config_complete,
.magic_config_key = plugin_magic_config_key,
.get_ready = plugin_get_ready,
+ .after_fork = plugin_after_fork,
.preconnect = plugin_preconnect,
.open = plugin_open,
.prepare = plugin_prepare,
diff --git a/plugins/ocaml/NBDKit.mli b/plugins/ocaml/NBDKit.mli
index 1f7a7e4b..3ebbf18f 100644
--- a/plugins/ocaml/NBDKit.mli
+++ b/plugins/ocaml/NBDKit.mli
@@ -75,6 +75,7 @@ type 'a plugin = {
thread_model : (unit -> thread_model) option;
get_ready : (unit -> unit) option;
+ after_fork : (unit -> unit) option;
preconnect : (bool -> unit) option;
open_connection : (bool -> 'a) option; (* required *)
diff --git a/plugins/sh/methods.h b/plugins/sh/methods.h
index f11e67e7..08a5ed17 100644
--- a/plugins/sh/methods.h
+++ b/plugins/sh/methods.h
@@ -42,6 +42,7 @@ extern const char *get_script (const char *method);
extern void sh_dump_plugin (void);
extern int sh_thread_model (void);
extern int sh_get_ready (void);
+extern int sh_after_fork (void);
extern int sh_preconnect (int readonly);
extern void *sh_open (int readonly);
extern void sh_close (void *handle);
diff --git a/plugins/ocaml/NBDKit.ml b/plugins/ocaml/NBDKit.ml
index ae3d8fb6..9ce3bf3e 100644
--- a/plugins/ocaml/NBDKit.ml
+++ b/plugins/ocaml/NBDKit.ml
@@ -70,6 +70,7 @@ type 'a plugin = {
thread_model : (unit -> thread_model) option;
get_ready : (unit -> unit) option;
+ after_fork : (unit -> unit) option;
preconnect : (bool -> unit) option;
open_connection : (bool -> 'a) option;
@@ -114,6 +115,7 @@ let default_callbacks = {
thread_model = None;
get_ready = None;
+ after_fork = None;
preconnect = None;
open_connection = None;
@@ -157,6 +159,7 @@ external set_config_help : string -> unit = "ocaml_nbdkit_set_config_help" "noal
external set_thread_model : (unit -> thread_model) -> unit = "ocaml_nbdkit_set_thread_model"
external set_get_ready : (unit -> unit) -> unit = "ocaml_nbdkit_set_get_ready"
+external set_after_fork : (unit -> unit) -> unit = "ocaml_nbdkit_set_after_fork"
external set_preconnect : (bool -> unit) -> unit = "ocaml_nbdkit_set_preconnect"
external set_open : (bool -> 'a) -> unit = "ocaml_nbdkit_set_open"
@@ -219,6 +222,7 @@ let register_plugin plugin =
may set_thread_model plugin.thread_model;
may set_get_ready plugin.get_ready;
+ may set_after_fork plugin.after_fork;
may set_preconnect plugin.preconnect;
may set_open plugin.open_connection;
diff --git a/plugins/eval/eval.c b/plugins/eval/eval.c
index df701f8f..51b57d09 100644
--- a/plugins/eval/eval.c
+++ b/plugins/eval/eval.c
@@ -54,6 +54,7 @@
static char *missing;
static const char *known_methods[] = {
+ "after_fork",
"cache",
"can_cache",
"can_extents",
@@ -389,6 +390,7 @@ static struct nbdkit_plugin plugin = {
.config_help = eval_config_help,
.thread_model = sh_thread_model,
.get_ready = sh_get_ready,
+ .after_fork = sh_after_fork,
.preconnect = sh_preconnect,
.open = sh_open,
diff --git a/plugins/ocaml/ocaml.c b/plugins/ocaml/ocaml.c
index 8e0e88f6..d8b61108 100644
--- a/plugins/ocaml/ocaml.c
+++ b/plugins/ocaml/ocaml.c
@@ -120,6 +120,7 @@ static value config_complete_fn;
static value thread_model_fn;
static value get_ready_fn;
+static value after_fork_fn;
static value preconnect_fn;
static value open_fn;
@@ -272,6 +273,25 @@ get_ready_wrapper (void)
CAMLreturnT (int, 0);
}
+static int
+after_fork_wrapper (void)
+{
+ CAMLparam0 ();
+ CAMLlocal1 (rv);
+
+ caml_leave_blocking_section ();
+
+ rv = caml_callback_exn (after_fork_fn, Val_unit);
+ if (Is_exception_result (rv)) {
+ nbdkit_error ("%s", caml_format_exception (Extract_exception (rv)));
+ caml_enter_blocking_section ();
+ CAMLreturnT (int, -1);
+ }
+
+ caml_enter_blocking_section ();
+ CAMLreturnT (int, 0);
+}
+
static int
preconnect_wrapper (int readonly)
{
@@ -833,6 +853,7 @@ SET(config_complete)
SET(thread_model)
SET(get_ready)
+SET(after_fork)
SET(preconnect)
SET(open)
@@ -876,6 +897,7 @@ remove_roots (void)
REMOVE (thread_model);
REMOVE (get_ready);
+ REMOVE (after_fork);
REMOVE (preconnect);
REMOVE (open);
diff --git a/plugins/sh/methods.c b/plugins/sh/methods.c
index 10cd4100..8257103e 100644
--- a/plugins/sh/methods.c
+++ b/plugins/sh/methods.c
@@ -165,6 +165,31 @@ sh_get_ready (void)
}
}
+int
+sh_after_fork (void)
+{
+ const char *method = "after_fork";
+ const char *script = get_script (method);
+ const char *args[] = { script, method, NULL };
+
+ switch (call (args)) {
+ case OK:
+ case MISSING:
+ return 0;
+
+ case ERROR:
+ return -1;
+
+ case RET_FALSE:
+ nbdkit_error ("%s: %s method returned unexpected code (3/false)",
+ script, method);
+ errno = EIO;
+ return -1;
+
+ default: abort ();
+ }
+}
+
int
sh_preconnect (int readonly)
{
diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c
index eb677d5b..9e484823 100644
--- a/plugins/sh/sh.c
+++ b/plugins/sh/sh.c
@@ -297,6 +297,7 @@ static struct nbdkit_plugin plugin = {
.magic_config_key = "script",
.thread_model = sh_thread_model,
.get_ready = sh_get_ready,
+ .after_fork = sh_after_fork,
.preconnect = sh_preconnect,
.open = sh_open,
diff --git a/tests/test-eval.sh b/tests/test-eval.sh
index cf88fcf7..07a9ea1e 100755
--- a/tests/test-eval.sh
+++ b/tests/test-eval.sh
@@ -65,6 +65,7 @@ grep 'in missing: thread_model' eval.missing
grep 'in missing: can_write' eval.missing
grep 'in missing: is_rotational' eval.missing
grep 'in missing: get_ready' eval.missing
+grep 'in missing: after_fork' eval.missing
grep 'in missing: preconnect' eval.missing
grep 'in missing: open' eval.missing
grep 'in missing: close' eval.missing
diff --git a/tests/test-layers-filter.c b/tests/test-layers-filter.c
index 53427d2a..66d80835 100644
--- a/tests/test-layers-filter.c
+++ b/tests/test-layers-filter.c
@@ -89,6 +89,14 @@ test_layers_filter_get_ready (nbdkit_next_get_ready *next,
return next (nxdata);
}
+static int
+test_layers_filter_after_fork (nbdkit_next_after_fork *next,
+ void *nxdata)
+{
+ DEBUG_FUNCTION;
+ return next (nxdata);
+}
+
static int
test_layers_filter_preconnect (nbdkit_next_preconnect *next,
void *nxdata, int readonly)
@@ -358,6 +366,7 @@ static struct nbdkit_filter filter = {
.config_complete = test_layers_filter_config_complete,
.config_help = test_layers_filter_config_help,
.get_ready = test_layers_filter_get_ready,
+ .after_fork = test_layers_filter_after_fork,
.preconnect = test_layers_filter_preconnect,
.open = test_layers_filter_open,
.close = test_layers_filter_close,
diff --git a/tests/test-layers-plugin.c b/tests/test-layers-plugin.c
index 72ed03f5..ccb67fe4 100644
--- a/tests/test-layers-plugin.c
+++ b/tests/test-layers-plugin.c
@@ -79,6 +79,13 @@ test_layers_plugin_get_ready (void)
return 0;
}
+static int
+test_layers_plugin_after_fork (void)
+{
+ DEBUG_FUNCTION;
+ return 0;
+}
+
static int
test_layers_plugin_preconnect (int readonly)
{
@@ -239,6 +246,7 @@ static struct nbdkit_plugin plugin = {
.config_complete = test_layers_plugin_config_complete,
.config_help = test_layers_plugin_config_help,
.get_ready = test_layers_plugin_get_ready,
+ .after_fork = test_layers_plugin_after_fork,
.preconnect = test_layers_plugin_preconnect,
.open = test_layers_plugin_open,
.close = test_layers_plugin_close,
diff --git a/tests/test-layers.c b/tests/test-layers.c
index aa61d03b..9a0279f1 100644
--- a/tests/test-layers.c
+++ b/tests/test-layers.c
@@ -300,6 +300,18 @@ main (int argc, char *argv[])
"test_layers_plugin_get_ready",
NULL);
+ /* after_fork methods called in order. */
+ log_verify_seen_in_order
+ ("testlayersfilter3: after_fork",
+ "filter3: test_layers_filter_after_fork",
+ "testlayersfilter2: after_fork",
+ "filter2: test_layers_filter_after_fork",
+ "testlayersfilter1: after_fork",
+ "filter1: test_layers_filter_after_fork",
+ "testlayersplugin: after_fork",
+ "test_layers_plugin_after_fork",
+ NULL);
+
/* preconnect methods called in outer-to-inner order, complete
* in inner-to-outer order.
*/
--
2.25.0
4 years, 4 months
[v2v PATCH] libosinfo: declare autocleanup funcs with libosinfo < 1.8.0
by Pino Toscano
libosinfo 1.8.0 declares them automatically for all of its classes, so
there is no need to declare ours. This requires fixing the definition of
the IS_LIBOSINFO_VERSION macro to wrap its body in brackets.
While in the process, simplify the workaround for a related bug by
removing a now-useless check.
---
v2v/libosinfo-c.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/v2v/libosinfo-c.c b/v2v/libosinfo-c.c
index e5327dff..322e7d3d 100644
--- a/v2v/libosinfo-c.c
+++ b/v2v/libosinfo-c.c
@@ -40,8 +40,13 @@
#define V2V_LIBOSINFO_VERSION_HEX \
MAKE_VERSION_HEX(OSINFO_MAJOR_VERSION, OSINFO_MINOR_VERSION, OSINFO_MICRO_VERSION)
#define IS_LIBOSINFO_VERSION(maj, min, mic) \
- V2V_LIBOSINFO_VERSION_HEX >= MAKE_VERSION_HEX(maj, min, mic)
+ (V2V_LIBOSINFO_VERSION_HEX >= MAKE_VERSION_HEX(maj, min, mic))
+/*
+ * libosinfo 1.8.0 provides auto-cleanup functions for all its classes,
+ * so avoid declaring our own.
+ */
+#if !IS_LIBOSINFO_VERSION(1, 8, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoFilter, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoLoader, g_object_unref)
/*
@@ -50,11 +55,13 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoLoader, g_object_unref)
* avoid declaring this when:
* - libosinfo is >= 1.7.0 and < 1.8.0
* - glib is >= 2.63.3
+ * (the 1.8.0 check is not done, as already covered by the check above)
*/
-#if !IS_LIBOSINFO_VERSION(1, 7, 0) || IS_LIBOSINFO_VERSION(1, 8, 0) || !GLIB_CHECK_VERSION(2, 63, 3)
+#if !IS_LIBOSINFO_VERSION(1, 7, 0) || !GLIB_CHECK_VERSION(2, 63, 3)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoList, g_object_unref)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoOsList, g_object_unref)
+#endif
typedef OsinfoDb *OsinfoDb_t;
typedef OsinfoOs *OsinfoOs_t;
--
2.25.4
4 years, 4 months
[PATCH nbdkit] build: Rename configure --without-linuxdisk -> --disable-linuxdisk
by Richard W.M. Jones
When I was reviewing this I forgot the slightly ridiculous rules that
autoconf uses for --enable/disable vs --with/without:
https://www.gnu.org/software/autoconf/manual/autoconf-2.66/html_node/Pack...
https://www.gnu.org/software/autoconf/manual/autoconf-2.66/html_node/Exte...
Since this is disabling an intrinsic feature of the software (a
plugin) it should use --disable.
Updates: commit 2a3efc5836df3d55d304cc4b3ea2800b5e93831a
---
configure.ac | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index e6ca09de..376b1538 100644
--- a/configure.ac
+++ b/configure.ac
@@ -483,17 +483,17 @@ AS_IF([test "$GNUTLS_LIBS" != ""],[
LIBS="$old_LIBS"
])
-AC_ARG_WITH([linuxdisk],
- [AS_HELP_STRING([--without-linuxdisk],
+AC_ARG_ENABLE([linuxdisk],
+ [AS_HELP_STRING([--disable-linuxdisk],
[disable linuxdisk plugin @<:@default=check@:>@])],
[],
- [with_linuxdisk=check])
+ [enable_linuxdisk=check])
dnl Check for mke2fs -d (used by linuxdisk plugin). There are two
dnl possible outcomes that we care about: (1) We have mke2fs and
dnl it supports the -d option. (2) We either don't have mke2fs
dnl or it's too old to support the -d option (eg. on RHEL 7).
mke2fs_with_d=no
-AS_IF([test "$with_linuxdisk" != "no"], [
+AS_IF([test "enable_linuxdisk" != "no"], [
AC_MSG_CHECKING([for mke2fs supporting the -d option])
AS_IF([mke2fs -V >/dev/null 2>&1], [
AS_IF([LANG=C mke2fs -d 2>&1 | grep -sq "option requires an argument"], [
--
2.25.0
4 years, 4 months
[PATCH 1/3] nbdkit: fix build of the SSH plugin on FreeBSD
by asomers@gmail.com
From: Alan Somers <asomers(a)gmail.com>
There was a missing #include. It only worked on Linux due to header
pollution.
---
plugins/ssh/ssh.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/plugins/ssh/ssh.c b/plugins/ssh/ssh.c
index ea199a93..a4007c40 100644
--- a/plugins/ssh/ssh.c
+++ b/plugins/ssh/ssh.c
@@ -30,6 +30,8 @@
* SUCH DAMAGE.
*/
+#include <sys/stat.h>
+
#include <config.h>
#include <stdio.h>
--
2.26.2
4 years, 4 months
[PATCH nbdkit] v2v: Disable readahead for VMware curl sources too (RHBZ#1848862).
by Richard W.M. Jones
I'm still testing this fix, so let's hold off the review for the
moment.
Also it may be better to specifically identify problematic servers
rather than disabling this for every curl source. eg. I suspect that
the problem is the Java server used by VCenter, so we might think
about only disabling readahead for that single case.
Rich.
4 years, 4 months
Deduplication and block size
by Richard W.M. Jones
Nothing too interesting here, I was just playing around with the idea
of a deduplication allocator for nbdkit (“allocator=dedup”, see
https://rwmj.wordpress.com/2020/06/15/compressed-ram-disks/).
Before implementing such a thing I wanted to know if there's much
duplicated structure in a disk image. It seems to depend very
critically on the block size, but also there are no significant
savings to be had by deduplicating.
A test script I wrote is attached. It takes any disk image that you
give it plus a block size, and produces a report on the potential
number of duplicated blocks at the given block size. For example:
$ guestfish -N fs:vfat -m /dev/sda1 tgz-in /tmp/nbdkit-1.21.10.tar.gz /
$ ./dedup.pl test1.img 4096
disk size = 1073741824
blocks of zeros: 259699 / 262144 99.1%
blocks that could not be deduplicated: 2336 / 262144 0.9%
number of duplicates: 22 count: 1 0.0%
number of duplicates: 11 count: 2 0.0%
number of duplicates: 9 count: 1 0.0%
number of duplicates: 8 count: 1 0.0%
number of duplicates: 6 count: 1 0.0%
number of duplicates: 3 count: 2 0.0%
number of duplicates: 2 count: 18 0.0%
This means that > 99% of the disk is zeroes. 0.9% of the disk (2336 x
4k blocks) is unique and cannot be deduplicated.
For the remaining 4k blocks: 1 block was replicated 22 times. 2
blocks were replicated 11 times each. 1 block was replicated 9 times.
etc down to 18 blocks which had 2 copies each.
** But almost no savings could be made by deduplicating **
99.1% - 0.9% ≈ 0
Adjusting the block size (and of course different disk images,
especially filesystem type and data stored) showed that we'd need to
use the smallest possible block size (ie. 512 bytes) in order to get
the best deduplication. Same as above with 512 byte block size:
$ ./dedup.pl test1.img 512
disk size = 1073741824
blocks of zeros: 2080973 / 2097152 99.2%
blocks that could not be deduplicated: 12952 / 2097152 0.6%
number of duplicates: 160 count: 1 0.0%
number of duplicates: 115 count: 1 0.0%
number of duplicates: 89 count: 1 0.0%
number of duplicates: 84 count: 1 0.0%
number of duplicates: 74 count: 1 0.0%
number of duplicates: 73 count: 1 0.0%
...
number of duplicates: 5 count: 7 0.0%
number of duplicates: 4 count: 37 0.0%
number of duplicates: 3 count: 73 0.0%
number of duplicates: 2 count: 332 0.0%
Note that even with the smaller block size, almost nothing would be
saved by deduplicating (only ≈0.2% of the disk). Smaller block sizes
have quite a lot more overhead too, so there's a trade-off between
block size and metadata.
Changing the filesystem type makes some difference (but not enough to
be important). Here's the same data as the first table above, but
using ext4 instead of vfat:
$ guestfish -N fs:ext4 -m /dev/sda1 tgz-in /tmp/nbdkit-1.21.10.tar.gz /
$ /var/tmp/dedup.pl test1.img 4096
disk size = 1073741824
blocks of zeros: 259317 / 262144 98.9%
blocks that could not be deduplicated: 2359 / 262144 0.9%
number of duplicates: 22 count: 1 0.0%
number of duplicates: 11 count: 2 0.0%
number of duplicates: 9 count: 1 0.0%
number of duplicates: 8 count: 1 0.0%
number of duplicates: 6 count: 1 0.0%
number of duplicates: 4 count: 1 0.0%
number of duplicates: 3 count: 3 0.0%
number of duplicates: 2 count: 194 0.1%
Here's another one where I take a video file which about 11% of the
virtual size of the disk (and of course compressed, so random and
pretty much the worst case for deduplication):
$ guestfish -N fs:ext4 -m /dev/sda1 upload /tmp/2020-02-rjones-goals-tech-talk.mp4 /video.mp4
$ /var/tmp/dedup.pl test1.img 4096
disk size = 1073741824
blocks of zeros: 236161 / 262144 90.1%
blocks that could not be deduplicated: 25966 / 262144 9.9%
number of duplicates: 4 count: 1 0.0%
number of duplicates: 3 count: 1 0.0%
number of duplicates: 2 count: 5 0.0%
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v
4 years, 4 months
[PATCH virt-v2v] v2v: Allow temporary directory to be set on a global basis.
by Richard W.M. Jones
Previously we placed large files in g#get_cachedir () (usually
/var/tmp). However the problem is this ties the libguestfs appliance
and the virt-v2v overlay files to the same location.
When virt-v2v is run in a container, or any other situation where
local storage is limited, it's helpful to be able to put the overlay
files on an externally mounted PVC, which might be using NFS and
shared between containers. But putting the libguestfs appliance on
NFS in a shared location is certainly not recommended.
This allows the two locations to be set separately:
VIRT_V2V_TMPDIR - location of large temporary files, can use NFS
and may be shared
LIBGUESTFS_CACHEDIR - location of libguestfs appliance
Another motivation for this patch is to allow more reliable cleanup of
temporary files by an external process, as described in the updated
documentation.
---
docs/virt-v2v.pod | 21 +++++++++++++++++----
v2v/input_ova.ml | 4 ++--
v2v/input_vmx.ml | 3 +--
v2v/nbdkit.ml | 3 +--
v2v/output_glance.ml | 3 +--
v2v/output_null.ml | 5 ++---
v2v/output_rhv_upload.ml | 3 +--
v2v/parse_ova.ml | 5 ++---
v2v/python_script.ml | 3 +--
v2v/utils.ml | 8 ++++++--
v2v/utils.mli | 4 ++++
v2v/v2v.ml | 15 ++++++---------
12 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
index ed95fdc8e..dbfd10cad 100644
--- a/docs/virt-v2v.pod
+++ b/docs/virt-v2v.pod
@@ -1206,8 +1206,9 @@ possible.
=head3 Disk space
-Virt-v2v places potentially large temporary files in C<$TMPDIR> (which
-is F</var/tmp> if you don't set it). Using tmpfs is a bad idea.
+Virt-v2v places potentially large temporary files in
+C<$VIRT_V2V_TMPDIR> (or F</var/tmp>, see also L</ENVIRONMENT VARIBLES>
+below). Using tmpfs is a bad idea.
For each guest disk, an overlay is stored temporarily. This stores
the changes made during conversion, and is used as a cache. The
@@ -1554,10 +1555,22 @@ conversion.
=over 4
+=item C<VIRT_V2V_TMPDIR>
+
+=item C<LIBGUESTFS_CACHEDIR>
+
=item C<TMPDIR>
-Location of the temporary directory used for the potentially large
-temporary overlay file.
+Location of the temporary directory. This is used for the potentially
+large temporary overlay files. Also for miscellaneous temporary
+files. These environment variables are checked in order:
+C<VIRT_V2V_TMPDIR>, C<LIBGUESTFS_CACHEDIR>, C<TMPDIR>. If none are
+set then F</var/tmp> is used.
+
+To reliably ensure temporary files are cleaned up (for example in case
+virt-v2v crashes) you should create a randomly named directory under
+F</var/tmp>, set C<VIRT_V2V_TMPDIR> to point to this directory, then
+when virt-v2v exits remove the directory.
See the L</Disk space> section above.
diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
index 5d3bece18..86f81e1f9 100644
--- a/v2v/input_ova.ml
+++ b/v2v/input_ova.ml
@@ -132,8 +132,8 @@ class input_ova ova = object
(* The spec allows the file to be gzip-compressed, in
* which case we must uncompress it into a temporary.
*)
- let temp_dir = (open_guestfs ())#get_cachedir () in
- let new_filename = Filename.temp_file ~temp_dir "ova" ".vmdk" in
+ let new_filename =
+ Filename.temp_file ~temp_dir:Utils.tmpdir "ova" ".vmdk" in
unlink_on_exit new_filename;
let cmd =
sprintf "zcat %s > %s" (quote filename) (quote new_filename) in
diff --git a/v2v/input_vmx.ml b/v2v/input_vmx.ml
index f1d143e97..5a1804182 100644
--- a/v2v/input_vmx.ml
+++ b/v2v/input_vmx.ml
@@ -389,8 +389,7 @@ and find_nics vmx =
class input_vmx input_password input_transport arg =
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "vmx." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "vmx." in
rmdir_on_exit t;
t in
object
diff --git a/v2v/nbdkit.ml b/v2v/nbdkit.ml
index 65317f9b9..188647f65 100644
--- a/v2v/nbdkit.ml
+++ b/v2v/nbdkit.ml
@@ -105,8 +105,7 @@ let add_filter_if_available cmd filter =
let run_unix cmd =
(* Create a temporary directory where we place the socket and PID file. *)
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "v2vnbdkit." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "v2vnbdkit." in
(* tmpdir must be readable (but not writable) by "other" so that
* qemu can open the sockets.
*)
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
index 0a9e91818..fce223333 100644
--- a/v2v/output_glance.ml
+++ b/v2v/output_glance.ml
@@ -33,8 +33,7 @@ class output_glance () =
* to write to a temporary file. XXX
*)
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "glance." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "glance." in
rmdir_on_exit t;
t in
object
diff --git a/v2v/output_null.ml b/v2v/output_null.ml
index 3528da50a..5ce30d557 100644
--- a/v2v/output_null.ml
+++ b/v2v/output_null.ml
@@ -50,7 +50,7 @@ let can_use_qemu_null_co_device () =
(* We actually attempt to convert a raw file to the null-co device
* using a JSON URL.
*)
- let tmp = Filename.temp_file "v2vqemunullcotst" ".img" in
+ let tmp = Filename.temp_file ~temp_dir:tmpdir "v2vqemunullcotst" ".img" in
Unix.truncate tmp 1024;
let json = [
@@ -75,8 +75,7 @@ class output_null =
* the null-co device w/ a JSON URL.
*)
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "null." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "null." in
rmdir_on_exit t;
t in
object
diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml
index 5c6c26110..4922a2040 100644
--- a/v2v/output_rhv_upload.ml
+++ b/v2v/output_rhv_upload.ml
@@ -155,8 +155,7 @@ class output_rhv_upload output_alloc output_conn
rhv_options =
(* Create a temporary directory which will be deleted on exit. *)
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "rhvupload." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "rhvupload." in
rmdir_on_exit t;
t in
diff --git a/v2v/parse_ova.ml b/v2v/parse_ova.ml
index 0b939ac43..1f332a82c 100644
--- a/v2v/parse_ova.ml
+++ b/v2v/parse_ova.ml
@@ -71,8 +71,7 @@ let rec parse_ova ova =
if is_directory ova then ova, Directory
else (
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "ova." in
+ let t = Mkdtemp.temp_dir ~base_dir:tmpdir "ova." in
rmdir_on_exit t;
t in
@@ -222,7 +221,7 @@ and uncompress_head format file =
and uncompressed_type format file =
let head, headlen = uncompress_head format file in
let tmpfile, chan =
- Filename.open_temp_file "ova.file." "" in
+ Filename.open_temp_file ~temp_dir:tmpdir "ova.file." "" in
output chan head 0 headlen;
close_out chan;
let ret = detect_file_type tmpfile in
diff --git a/v2v/python_script.ml b/v2v/python_script.ml
index 33c5e9a21..2d95f4bd5 100644
--- a/v2v/python_script.ml
+++ b/v2v/python_script.ml
@@ -35,8 +35,7 @@ let create ?(name = "script.py") ?tmpdir code =
let tmpdir =
match tmpdir with
| None ->
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "v2v." in
+ let t = Mkdtemp.temp_dir ~base_dir:Utils.tmpdir "v2v." in
rmdir_on_exit t;
t
| Some dir -> dir in
diff --git a/v2v/utils.ml b/v2v/utils.ml
index ccbb9d68a..8cc24d6a2 100644
--- a/v2v/utils.ml
+++ b/v2v/utils.ml
@@ -24,6 +24,10 @@ open Std_utils
open Tools_utils
open Common_gettext.Gettext
+let tmpdir =
+ try Sys.getenv "VIRT_V2V_TMPDIR"
+ with Not_found -> (open_guestfs ())#get_cachedir ()
+
(* Is SELinux enabled and enforcing on the host? *)
let have_selinux =
0 = Sys.command "getenforce 2>/dev/null | grep -isq Enforcing"
@@ -112,7 +116,8 @@ let qemu_img_supports_offset_and_size () =
(* We actually attempt to create a qcow2 file with a raw backing
* file that has an offset and size.
*)
- let tmp = Filename.temp_file "v2vqemuimgtst" ".img" in
+ let tmp = Filename.temp_file ~temp_dir:tmpdir "v2vqemuimgtst" ".img" in
+ unlink_on_exit tmp;
Unix.truncate tmp 1024;
let json = [
@@ -132,7 +137,6 @@ let qemu_img_supports_offset_and_size () =
(if verbose () then "" else " 2>&1") in
debug "%s" cmd;
let r = 0 = Sys.command cmd in
- Unix.unlink tmp;
debug "qemu-img supports \"offset\" and \"size\" in json URLs: %b" r;
r
diff --git a/v2v/utils.mli b/v2v/utils.mli
index 937e2b9b8..5afe2954f 100644
--- a/v2v/utils.mli
+++ b/v2v/utils.mli
@@ -18,6 +18,10 @@
(** Utilities used in virt-v2v only. *)
+val tmpdir : string
+(** [VIRT_V2V_TMPDIR] or [/var/tmp]. Create all temporary files
+ under this directory. *)
+
val have_selinux : bool
(** True if SELinux is enabled and enforcing on the host. *)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 73edff2c4..6dd5fc693 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -264,8 +264,6 @@ and set_source_networks_and_bridges cmdline source =
let nics = List.map (Networks.map cmdline.network_map) source.s_nics in
{ source with s_nics = nics }
-and overlay_dir = (open_guestfs ())#get_cachedir ()
-
(* Conversion can fail or hang if there is insufficient free space in
* the temporary directory used to store overlays on the host
* (RHBZ#1316479). Although only a few hundred MB is actually
@@ -273,12 +271,12 @@ and overlay_dir = (open_guestfs ())#get_cachedir ()
* guestfs appliance which is also stored here.
*)
and check_host_free_space () =
- let free_space = StatVFS.free_space (StatVFS.statvfs overlay_dir) in
- debug "check_host_free_space: overlay_dir=%s free_space=%Ld"
- overlay_dir free_space;
+ let free_space = StatVFS.free_space (StatVFS.statvfs tmpdir) in
+ debug "check_host_free_space: tmpdir=%s free_space=%Ld"
+ tmpdir free_space;
if free_space < 1_073_741_824L then
error (f_"insufficient free space in the conversion server temporary directory %s (%s).\n\nEither free up space in that directory, or set the LIBGUESTFS_CACHEDIR environment variable to point to another directory with more than 1GB of free space.\n\nSee also the virt-v2v(1) manual, section \"Minimum free space check in the host\".")
- overlay_dir (human_size free_space)
+ tmpdir (human_size free_space)
(* Create a qcow2 v3 overlay to protect the source image(s). *)
and create_overlays source_disks =
@@ -286,7 +284,7 @@ and create_overlays source_disks =
List.mapi (
fun i ({ s_qemu_uri = qemu_uri; s_format = format } as source) ->
let overlay_file =
- Filename.temp_file ~temp_dir:overlay_dir "v2vovl" ".qcow2" in
+ Filename.temp_file ~temp_dir:tmpdir "v2vovl" ".qcow2" in
unlink_on_exit overlay_file;
(* There is a specific reason to use the newer qcow2 variant:
@@ -822,8 +820,7 @@ and actual_target_size target_file disk_stats =
and preserve_overlays overlays src_name =
List.iter (
fun ov ->
- let saved_filename =
- sprintf "%s/%s-%s.qcow2" overlay_dir src_name ov.ov_sd in
+ let saved_filename = sprintf "%s/%s-%s.qcow2" tmpdir src_name ov.ov_sd in
rename ov.ov_overlay_file saved_filename;
info (f_"Overlay saved as %s [--debug-overlays]") saved_filename
) overlays
--
2.25.0
4 years, 4 months