[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Libguestfs] Rethinking appliance building



Ok, here is where I am so far, but my ocaml is VERY weak, so it is slow going, I also added the right stuff to config.ml.in and Makefile.ml to make it work.

it seems to work, but when I run febootstrap --names bash coreutils dcron dhcpcd e2fsprogs file filesystem findutils gawk grep grub gzip initscripts iputils kernel26 less libusb logrotate net-tools pacman sed shadow sysvinit tar tcp_wrappers udev util-linux-ng
it only processes bash.

I am sure I am missing something obvious, but if you have any suggestions that would be great, learning ocaml is taking some time :)

-Tom Hatch

On Sun, Dec 5, 2010 at 4:28 PM, Thomas S Hatch <thatch45 gmail com> wrote:


On Sun, Dec 5, 2010 at 10:56 AM, Richard W.M. Jones <rjones redhat com> wrote:
To make this even more explicit:

> (1) There has to be a way to detect that the package manager should
> be used, eg. by looking for /etc/arch-release

RPM: check for existence of /etc/redhat-release
Debian: check for existence of /etc/debian_version
Arch: check for existence of /etc/arch-release
Arch: Or check the kernel version for "ARCH" with a uname -r
 
> (2) There must be a way to take a list of package names, and fully
> resolve all dependencies (recursively as necessary) to get a complete
> list of packages that must be installed to bootstrap.

RPM: [lots of Yum API magic]
Debian: apt-cache depends --recurse -i <list of package names>
Arch: pactree -l <list of package names> | sort -u 
pactree is part of the pacman-contrib package

> (3) Must be a way to download a package.

RPM: yumdownloader <name of package>
Debian: aptitude download <name of package>
Arch: pacman -Sw --cachedir=<Where to download> <name of package(s)>
This will download the package to the cachedir: /var/cache/pacman/pkg

> (4) Must be able to list out the files in a downloaded package.

RPM: rpm -qlp foo.rpm
Debian: dpkg-deb -c foo.deb
pacman -Qlp  foo.pkg.tar.xz

> (5) Must be able to extract a single file from a downloaded package.

RPM: rpm2cpio foo.rpm | cpio -id
Debian: dpkg-deb --fsys-tarfile foo.deb | tar xf -
Arch: tar xf foo.pkg.tar.xz
Arch packages are just tarballs with a PKGINFO file in the root directory which has package metadata

So it's almost enough for you to tell me the equivalent of those
commands for pacman, although of course I'd prefer a patch to
febootstrap!

Rich.

--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v

Here are the answers, and all commands work as non-root, before running any commands the package database would need to be updated by running "pacman -Sy"

I will grab a git checkout of febootstrap and start looking into prepping a patch, but if this is enough info for you to whip up support then let me know and I will test it and fix any arch specific things.

Thanks!

-Tom Hatch

(* febootstrap 3
 * Copyright (C) 2009-2010 Red Hat Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *)

(* ArchLinux support. *)

open Unix
open Printf

open Febootstrap_package_handlers
open Febootstrap_utils
open Febootstrap_cmdline

(* Create a temporary directory for use by all the functions in this file. *)
let tmpdir = tmpdir ()

let pacman_detect () =
  file_exists "/etc/arch-release" &&
    Config.pacman <> "no"

let pacman_resolve_dependencies_and_download names =
  let cmd =
    sprintf "pactree -u %s | sort -u"
      (String.concat " " (List.map Filename.quote names)) in
  let pkgs = run_command_get_lines cmd in

  (* Exclude packages matching [--exclude] regexps on the command line. *)
  let pkgs =
    List.filter (
      fun name ->
        not (List.exists (fun re -> Str.string_match re name 0) excludes)
    ) pkgs in

  (* Download the packages. I could use wget `pacman -Sp`, but this narrows the
   * pacman -Sy window*)
  let cmd =
    sprintf "cd %s && mkdir -p var/lib/pacman && fakeroot pacman -Syw --noconfirm --cachedir=$(pwd) --root=$(pwd) %s"
      (Filename.quote tmpdir)
      (String.concat " " (List.map Filename.quote pkgs)) in
  run_command cmd;

  (* Find out what pacman downloaded. *)
  (*let files = Sys.readdir tmpdir in

  let pkgs = List.map (
    fun pkg ->
      (* Look for 'pkg*.pkg.tar.xz' in the list of files. *)
      let pre = pkg in
      let r = ref "" in
      try
	for i = 0 to Array.length files - 1 do
	  if string_prefix pre files.(i) then (
	    r := files.(i);
	    files.(i) <- "";
	    raise Exit
	  )
	done;
	eprintf "febootstrap: pacman: error: no file was downloaded corresponding to package %s\n" pkg;
	exit 1
      with
	  Exit -> !r
  ) pkgs in *)

  List.sort compare pkgs

let pacman_list_files pkg =
  debug "unpacking %s ..." pkg;
  printf "unpacking %s \n" pkg;

  (* We actually need to extract the file in order to get the
   * information about modes etc.
   *)
  let pkgdir = tmpdir // pkg ^ ".d" in
  mkdir pkgdir 0o755;
  let cmd =
    sprintf "tar -xf %s-* -C %s"
      (tmpdir // pkg ) pkgdir in
  run_command cmd;

  let cmd = sprintf "cd %s && find ." pkgdir in
  let lines = run_command_get_lines cmd in

  let files = List.map (
    fun path ->
      assert (path.[0] = '.');
      (* No leading '.' *)
      let path =
	if path = "." then "/"
	else String.sub path 1 (String.length path - 1) in

      (* Find out what it is and get the canonical filename. *)
      let statbuf = lstat (pkgdir // path) in
      let is_dir = statbuf.st_kind = S_DIR in

      (* No per-file metadata like in RPM, but we can synthesize it
       * from the path.
       *)
      let config = statbuf.st_kind = S_REG && string_prefix path "/etc/" in

      let mode = statbuf.st_perm in

      (path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
	       ft_ghost = false })
  ) lines in

  files

(* Easy because we already unpacked the archive above. *)
let pacman_get_file_from_package pkg file =
  tmpdir // pkg ^ ".d" // file

let () =
  let ph = {
    ph_detect = pacman_detect;
    ph_resolve_dependencies_and_download =
      pacman_resolve_dependencies_and_download;
    ph_list_files = pacman_list_files;
    ph_get_file_from_package = pacman_get_file_from_package;
  } in
  register_package_handler "pacman" ph

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]