Olaf Hering
2013-Apr-11 17:07 UTC
[Libguestfs] [PATCH] handle --use-installed in zypp driver
An attempt to use installed files in zypp driver. Add also a comment about the theory of operation. Enable set -x in shell only in verbose mode. This adds a dependency to xmlstarlet, which is required to parse zypper output. Signed-off-by: Olaf Hering <olaf at aepfle.de> --- src/supermin_zypp_rpm.ml | 93 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/src/supermin_zypp_rpm.ml b/src/supermin_zypp_rpm.ml index 2089837..720f50a 100644 --- a/src/supermin_zypp_rpm.ml +++ b/src/supermin_zypp_rpm.ml @@ -18,6 +18,31 @@ (* Zypper and RPM support. *) +(* + * Theory of operation: + * called as root: + * - without --use-installed: + * ->ph_resolve_dependencies_and_download() returns a list of filenames + * Need to download all packages into an empty --root directory so that + * zypper places all dependencies into --pkg-cache-dir + * - with --use-installed: + * ->ph_resolve_dependencies_and_download() returns a list of package names + * Need to work with an empty --root directory so that zypper can list + * all dependencies of "names". This mode assumes that all required packages + * are installed and the system is consistent. Downloading just the missing + * packages is not implemented. + * called as non-root: + * (Due to the usage of --root zypper does not require root permissions.) + * - without --use-installed: + * Same as above. + * - with --use-installed: + * Same as above. + * + * The usage of --packager-config is tricky: If --root is used zypper assumes + * that every config file is below <rootdir>. So the config has to be parsed + * and relevant files/dirs should be copied into <rootdir> so that zypper can + * use the specified config. + *) open Unix open Printf @@ -34,15 +59,15 @@ let zypp_rpm_detect () Config.zypper <> "no" && Config.rpm <> "no" let zypp_rpm_init () - if use_installed && Unix.getuid() > 0 then - failwith "zypp_rpm driver doesn't support --use-installed when called as non-root user" + if use_installed then + eprintf "supermin: zypp_rpm driver assumes all packages are already installed when called with option --use-installed.\n%!" -let zypp_rpm_resolve_dependencies_and_download names +let zypp_rpm_resolve_dependencies_and_download_no_installed names (* Liberate this data from shell. *) let tmp_pkg_cache_dir = tmpdir // "pkg_cache_dir" in let tmp_root = tmpdir // "root" in let sh = sprintf " -set -ex +%s unset LANG ${!LC_*} tmpdir=%S cache_dir=\"${tmpdir}/cache-dir\" @@ -60,6 +85,7 @@ time zypper \ --download-only \ $@ " + (if verbose then "set -x" else "") tmpdir tmp_pkg_cache_dir (if verbose then "--verbose --verbose" else "--quiet") @@ -96,10 +122,47 @@ time zypper \ (* Return list of package filenames. *) pkgs +let zypp_rpm_resolve_dependencies_and_download_use_installed names + let cmd = sprintf " +%s +unset LANG ${!LC_*} +zypper \ + %s \ + %s \ + --root %S --reposd-dir /dev/shm/supermin/zypp/repos.d \ + --cache-dir %S \ + --gpg-auto-import-keys \ + --non-interactive \ + --xml \ + install \ + --auto-agree-with-licenses \ + --dry-run \ + %s | \ + xml sel -t \ + -m \"stream/install-summary/to-install/solvable[%@type='package']\" \ + -c \"string(%@name)\" -n +" + (if verbose then "set -x" else "") + (if verbose then "--verbose --verbose" else "--quiet") + (match packager_config with None -> "" + | Some filename -> sprintf "--config %s" filename) + tmpdir tmpdir (String.concat " " (List.map Filename.quote names)) in + let pkg_names = run_command_get_lines cmd in + + (* Return list of package names, remove empty lines. *) + List.filter (fun s -> s <> "") pkg_names + +let zypp_rpm_resolve_dependencies_and_download names + if use_installed then + zypp_rpm_resolve_dependencies_and_download_use_installed names + else + zypp_rpm_resolve_dependencies_and_download_no_installed names + let rec zypp_rpm_list_files pkg (* Run rpm -qlp with some extra magic. *) let cmd - sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' -p %S" + sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' %s %S" + (if use_installed then "" else "-p") pkg in let lines = run_command_get_lines cmd in @@ -153,14 +216,18 @@ let rec zypp_rpm_list_files pkg files let zypp_rpm_get_file_from_package pkg file - debug "extracting %s from %s ..." file (Filename.basename pkg); - - let outfile = tmpdir // file in - let cmd - sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)" - (Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in - run_command cmd; - outfile + if use_installed then + file + else ( + debug "extracting %s from %s ..." file (Filename.basename pkg); + + let outfile = tmpdir // file in + let cmd + sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)" + (Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in + run_command cmd; + outfile + ) let () let ph = {
Richard W.M. Jones
2013-Apr-11 17:21 UTC
[Libguestfs] [PATCH] handle --use-installed in zypp driver
On Thu, Apr 11, 2013 at 07:07:11PM +0200, Olaf Hering wrote:> An attempt to use installed files in zypp driver. > Add also a comment about the theory of operation. > Enable set -x in shell only in verbose mode. > This adds a dependency to xmlstarlet, which is required to parse zypper output. > > Signed-off-by: Olaf Hering <olaf at aepfle.de>Thanks - pushed. Git also complained about a line with trailing whitespace, so I fixed that. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
Olaf Hering
2013-Apr-29 13:22 UTC
[Libguestfs] [PATCH] handle --use-installed in zypp driver
On Thu, Apr 11, Olaf Hering wrote:> + -m \"stream/install-summary/to-install/solvable[%@type='package']\" \ > + -c \"string(%@name)\" -nThis is supposed to be "[@type='package']" and "string(@name)". Some of the ocaml printf docs made me believe that "%@" is the way to print a single "@". Now I see this part was changed to "%%@", which puts an extra % into the output string. Is the @ sign a special char in ocaml printf? Olaf