Maros Zatko
2015-Mar-18 16:20 UTC
[Libguestfs] [PATCH 0/2] [RFE] virt-builder should support download resume
This patchset adds support for resuming downloads in virt-builder. Partially downloaded file is not deleted on exit anymore. There is a check for partially downloaded image in cache directory based on its name. When found, download_to crafts appropriate options to continue its download. Maros Zatko (2): mllib: allow external_command to return [] on nonzero return value builder: support for download resume builder/downloader.ml | 16 ++++++++++++---- mllib/common_utils.ml | 15 ++++++++++----- mllib/common_utils.mli | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) -- 1.9.3
Maros Zatko
2015-Mar-18 16:20 UTC
[Libguestfs] [PATCH 1/2] mllib: allow external_command to return [] on nonzero return value
This is useful for probing probing for cache files such as: external_command ?ignore_error:(Some true) ~prog "ls .cache/something.*" will return command output (matched files) on its success or empty list whenits exit code is other than 0 (there are no such files). --- mllib/common_utils.ml | 15 ++++++++++----- mllib/common_utils.mli | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 76d8b79..9719b16 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -528,23 +528,28 @@ let compare_lvm2_uuids uuid1 uuid2 loop 0 0 (* Run an external command, slurp up the output as a list of lines. *) -let external_command ~prog cmd +let external_command ~prog ?(ignore_error = false) cmd let chan = Unix.open_process_in cmd in let lines = ref [] in (try while true do lines := input_line chan :: !lines done with End_of_file -> ()); let lines = List.rev !lines in let stat = Unix.close_process_in chan in - (match stat with - | Unix.WEXITED 0 -> () + match stat with + | Unix.WEXITED 0 -> + (* Command exited correctly, return its output *) + lines + | Unix.WEXITED i when ignore_error -> + (* Command failed. in case such as 'ls something*' when path doesn't exist + * and desired behavior is to get empty list instead of error. + * This is useful for probing partial downloads *) + [] | Unix.WEXITED i -> error ~prog (f_"external command '%s' exited with error %d") cmd i | Unix.WSIGNALED i -> error ~prog (f_"external command '%s' killed by signal %d") cmd i | Unix.WSTOPPED i -> error ~prog (f_"external command '%s' stopped by signal %d") cmd i - ); - lines (* Run uuidgen to return a random UUID. *) let uuidgen ~prog () diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli index 28ba648..ce2242a 100644 --- a/mllib/common_utils.mli +++ b/mllib/common_utils.mli @@ -109,7 +109,7 @@ val compare_version : string -> string -> int val compare_lvm2_uuids : string -> string -> int (** Compare two LVM2 UUIDs, ignoring '-' characters. *) -val external_command : prog:string -> string -> string list +val external_command : prog:string -> ?ignore_error:bool -> string -> string list (** Run an external command, slurp up the output as a list of lines. *) val uuidgen : prog:string -> unit -> string -- 1.9.3
Maros Zatko
2015-Mar-18 16:20 UTC
[Libguestfs] [PATCH 2/2] builder: support for download resume
Partially downloaded file is not deleted on exit anymore. There is a check for partially downloaded image in cache directory based on its name. When found, download_to crafts appropriate options to continue its download. --- builder/downloader.ml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/builder/downloader.ml b/builder/downloader.ml index 8a23bdc..6e19ee4 100644 --- a/builder/downloader.ml +++ b/builder/downloader.ml @@ -65,11 +65,11 @@ let rec download ~prog t ?template ?progress_bar ?(proxy = SystemProxy) uri * If not, download it. *) if not (Sys.file_exists filename) then - download_to ~prog t ?progress_bar ~proxy uri filename; + download_to ~prog t ?progress_bar ?continue:(Some true) ~proxy uri filename; (filename, false) -and download_to ~prog t ?(progress_bar = false) ~proxy uri filename +and download_to ~prog t ?(progress_bar = false) ?(continue = false) ~proxy uri filename let parseduri try URI.parse_uri uri with Invalid_argument "URI.parse_uri" -> @@ -82,7 +82,6 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename * atomically rename it to the final filename. *) let filename_new = filename ^ "." ^ string_random8 () in - unlink_on_exit filename_new; (match parseduri.URI.protocol with | "file" -> @@ -115,11 +114,20 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename if bad_status_code status_code then error (f_"failed to download %s: HTTP status code %s") uri status_code; + let cmd = sprintf "ls %s.* 2>/dev/null" filename in + let lines = if continue + then external_command ~prog ?ignore_error:(Some true) cmd + else [] in + let filename_new, continue_download = match List.length lines with + | 0 -> filename_new, "" + | _ -> List.hd lines, " -C -" in + (* Now download the file. *) - let cmd = sprintf "%s%s%s -g -o %s %s" + let cmd = sprintf "%s%s%s%s -g -o %s %s" outenv t.curl (if t.verbose then "" else if progress_bar then " -#" else " -s -S") + continue_download (quote filename_new) (quote uri) in if t.verbose then printf "%s\n%!" cmd; let r = Sys.command cmd in -- 1.9.3
Pino Toscano
2015-Mar-19 13:40 UTC
Re: [Libguestfs] [PATCH 2/2] builder: support for download resume
On Wednesday 18 March 2015 17:20:07 Maros Zatko wrote:> Partially downloaded file is not deleted on exit anymore. > There is a check for partially downloaded image in cache directory > based on its name. When found, download_to crafts appropriate > options to continue its download. > --- > builder/downloader.ml | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/builder/downloader.ml b/builder/downloader.ml > index 8a23bdc..6e19ee4 100644 > --- a/builder/downloader.ml > +++ b/builder/downloader.ml > @@ -65,11 +65,11 @@ let rec download ~prog t ?template ?progress_bar ?(proxy = SystemProxy) uri > * If not, download it. > *) > if not (Sys.file_exists filename) then > - download_to ~prog t ?progress_bar ~proxy uri filename; > + download_to ~prog t ?progress_bar ?continue:(Some true) ~proxy uri filename;~continue:true should work too.> > (filename, false) > > -and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > +and download_to ~prog t ?(progress_bar = false) ?(continue = false) ~proxy uri filename > let parseduri > try URI.parse_uri uri > with Invalid_argument "URI.parse_uri" -> > @@ -82,7 +82,6 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > * atomically rename it to the final filename. > *) > let filename_new = filename ^ "." ^ string_random8 () in > - unlink_on_exit filename_new; > > (match parseduri.URI.protocol with > | "file" -> > @@ -115,11 +114,20 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > if bad_status_code status_code then > error (f_"failed to download %s: HTTP status code %s") uri status_code; > > + let cmd = sprintf "ls %s.* 2>/dev/null" filename inThis should rather use Sys.readdir + List.filter.> + let lines = if continue > + then external_command ~prog ?ignore_error:(Some true) cmd > + else [] in > + let filename_new, continue_download = match List.length lines with > + | 0 -> filename_new, "" > + | _ -> List.hd lines, " -C -" in > + > (* Now download the file. *) > - let cmd = sprintf "%s%s%s -g -o %s %s" > + let cmd = sprintf "%s%s%s%s -g -o %s %s" > outenv > t.curl > (if t.verbose then "" else if progress_bar then " -#" else " -s -S") > + continue_download > (quote filename_new) (quote uri) in > if t.verbose then printf "%s\n%!" cmd; > let r = Sys.command cmd in >-- Pino Toscano
Richard W.M. Jones
2015-Mar-23 13:44 UTC
Re: [Libguestfs] [PATCH 1/2] mllib: allow external_command to return [] on nonzero return value
On Wed, Mar 18, 2015 at 05:20:06PM +0100, Maros Zatko wrote:> This is useful for probing probing for cache files such as: > external_command ?ignore_error:(Some true) ~prog "ls .cache/something.*" > will return command output (matched files) on its success or empty list > whenits exit code is other than 0 (there are no such files).I would write this as: let files = Sys.readdir ".cache" inm let files = Array.to_list files in let files = List.filter (fun s -> string_prefix s "something.") in (* or if you just want to check existence of any something.* file: let file_exists = List.exists (fun s -> string_prefix s "something.") in *) Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Richard W.M. Jones
2015-Mar-23 13:48 UTC
Re: [Libguestfs] [PATCH 2/2] builder: support for download resume
On Wed, Mar 18, 2015 at 05:20:07PM +0100, Maros Zatko wrote:> Partially downloaded file is not deleted on exit anymore. > There is a check for partially downloaded image in cache directory > based on its name. When found, download_to crafts appropriate > options to continue its download. > --- > builder/downloader.ml | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/builder/downloader.ml b/builder/downloader.ml > index 8a23bdc..6e19ee4 100644 > --- a/builder/downloader.ml > +++ b/builder/downloader.ml > @@ -65,11 +65,11 @@ let rec download ~prog t ?template ?progress_bar ?(proxy = SystemProxy) uri > * If not, download it. > *) > if not (Sys.file_exists filename) then > - download_to ~prog t ?progress_bar ~proxy uri filename; > + download_to ~prog t ?progress_bar ?continue:(Some true) ~proxy uri filename;To expand on what Pino said: ?foo arguments are passed as options, ie. None or Some .. The function has (hidden, generated by the compiler) code which does effectively: let foo = match ?foo with None -> (* default value *) | Some x -> x in When calling if you write the argument as ~foo:true then the compiler automatically translates that to 'Some true'.> (filename, false) > > -and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > +and download_to ~prog t ?(progress_bar = false) ?(continue = false) ~proxy uri filename > let parseduri > try URI.parse_uri uri > with Invalid_argument "URI.parse_uri" -> > @@ -82,7 +82,6 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > * atomically rename it to the final filename. > *) > let filename_new = filename ^ "." ^ string_random8 () in > - unlink_on_exit filename_new; > > (match parseduri.URI.protocol with > | "file" -> > @@ -115,11 +114,20 @@ and download_to ~prog t ?(progress_bar = false) ~proxy uri filename > if bad_status_code status_code then > error (f_"failed to download %s: HTTP status code %s") uri status_code; > > + let cmd = sprintf "ls %s.* 2>/dev/null" filename in > + let lines = if continue > + then external_command ~prog ?ignore_error:(Some true) cmd > + else [] in > + let filename_new, continue_download = match List.length lines with > + | 0 -> filename_new, "" > + | _ -> List.hd lines, " -C -" in > + > (* Now download the file. *) > - let cmd = sprintf "%s%s%s -g -o %s %s" > + let cmd = sprintf "%s%s%s%s -g -o %s %s" > outenv > t.curl > (if t.verbose then "" else if progress_bar then " -#" else " -s -S") > + continue_download > (quote filename_new) (quote uri) in > if t.verbose then printf "%s\n%!" cmd; > let r = Sys.command cmd inI can't say I'm very happy to have partial downloads lying around in the cache directory. Let's see what Pino thinks of the updated patch however. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Possibly Parallel Threads
- [PATCH 2/2] builder: support for download resume
- [PATCH v4] [RFE] virt-builder should support download resume
- [PATCH v3] [RFE] virt-builder should support download resume
- [PATCH] [RFE] virt-builder should support download resume
- [PATCH 0/3] virt-builder: copy local files instead of using curl