Multiple fixes:
authorRichard W.M. Jones <rjones@redhat.com>
Sat, 2 Feb 2008 14:20:15 +0000 (14:20 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Sat, 2 Feb 2008 14:20:15 +0000 (14:20 +0000)
 - fix interactive shell
 - copy more of /etc from the root for automatic networking
 - fix RHEL/CentOS 5.0 redhat-release parsing.

virt-p2v.ml

index 4b590af..f2db828 100755 (executable)
@@ -325,9 +325,21 @@ let shget cmd =
   | WSIGNALED i -> failwith (sprintf "shget: command killed by signal %d" i)
   | WSTOPPED i -> failwith (sprintf "shget: command stopped by signal %d" i)
 
-(* Start an interactive shell. *)
+(* Start an interactive shell.  Need to juggle file descriptors a bit
+ * because bash write PS1 to stderr (currently directed to the logfile).
+ *)
 let shell () =
-  shfailok "PS1='\\u@\\h:\\w\\$ ' bash"
+  match fork () with
+  | 0 ->                               (* child, runs bash *)
+      close stderr;
+      dup2 stdout stderr;
+      (* Sys.command runs 'sh -c' which blows away PS1, so set it late. *)
+      ignore (
+       Sys.command "PS1='\\u@\\h:\\w\\$ ' /bin/bash --norc --noprofile -i"
+      )
+  | _ ->                               (* parent, waits *)
+      eprintf "waiting for subshell to exit\n%!";
+      ignore (wait ())
 
 (* Some true if is dir/file, Some false if not, None if not found. *)
 let is_dir path =
@@ -441,33 +453,51 @@ let snapshot =
     sh (sprintf "dmsetup create %s --table='0 %Ld snapshot /dev/mapper/%s_org %s n 64'"
          snapshot_dev sectors snapshot_dev ramdisk)
 
-(* Try to perform automatic network configuration, assuming a Fedora or RHEL-
- * like root filesystem mounted on /mnt/root.
+(* Try to perform automatic network configuration, assuming a Fedora or
+ * RHEL-like root filesystem mounted on /mnt/root.
  *)
 let auto_network state =
   (* Fedora gives an error if this file doesn't exist. *)
   sh "touch /etc/resolv.conf";
 
+  (* It's tempting to do a 'chroot ...' and run the original
+   * '/etc/init.d/network start' script.  However this will not
+   * always work, in particular in the case where the root is
+   * a 64 bit machine and the live CD kernel is 32 bit, and so
+   * cannot run binaries such as /sbin/ifconfig from the root.
+   * Do it the hard way instead ...
+   *)
   chdir "/etc/sysconfig";
-
   sh "mv network network.saved";
   sh "mv networking networking.saved";
   sh "mv network-scripts network-scripts.saved";
+  chdir "/etc/init.d";
+  sh "mv network network.saved";
+  sh "mv functions functions.saved";
 
   (* Originally I symlinked these, but that causes dhclient to
    * keep open /mnt/root (as its cwd is in network-scripts subdir).
    * So now we will copy them recursively instead.
    *)
-  sh "cp -r /mnt/root/etc/sysconfig/network .";
-  sh "cp -r /mnt/root/etc/sysconfig/networking .";
-  sh "cp -r /mnt/root/etc/sysconfig/network-scripts .";
+  chdir "/etc/sysconfig";
+  sh "cp -a /mnt/root/etc/sysconfig/network .";
+  sh "cp -a /mnt/root/etc/sysconfig/networking .";
+  sh "cp -a /mnt/root/etc/sysconfig/network-scripts .";
+  chdir "/etc/init.d";
+  sh "cp /mnt/root/etc/init.d/network .";
+  sh "cp /mnt/root/etc/init.d/functions .";
 
   let status = shwithstatus "/etc/init.d/network start" in
 
+  chdir "/etc/sysconfig";
   sh "rm -rf network networking network-scripts";
   sh "mv network.saved network";
   sh "mv networking.saved networking";
   sh "mv network-scripts.saved network-scripts";
+  chdir "/etc/init.d";
+  sh "rm -f network functions";
+  sh "mv network.saved network";
+  sh "mv functions.saved functions";
 
   chdir "/tmp";
 
@@ -643,8 +673,8 @@ let rec main ttyname =
     (* Output of 'file' command for Linux swap file. *)
     let swap = Pcre.regexp "Linux.*swap.*file" in
     (* Contents of /etc/redhat-release. *)
-    let rhel = Pcre.regexp "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)\\.(\\d+)" in
-    let fedora = Pcre.regexp "Fedora.*release (\\d+)\\.(\\d+)" in
+    let rhel = Pcre.regexp "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)(?:\\.(\\d+))?" in
+    let fedora = Pcre.regexp "Fedora.*release (\\d+)" in
     (* Contents of /etc/debian_version. *)
     let debian = Pcre.regexp "^(\\d+)\\.(\\d+)" in
     (* Output of 'file' on certain executables. *)
@@ -670,11 +700,13 @@ let rec main ttyname =
            match lines with
            | [] -> (* empty /etc/redhat-release ...? *)
                LinuxRoot (UnknownArch, OtherLinux)
-           | line::_ ->
+           | line::_ -> (* try to detect OS from /etc/redhat-release *)
                try
                  let subs = Pcre.exec ~rex:rhel line in
                  let major = int_of_string (Pcre.get_substring subs 1) in
-                 let minor = int_of_string (Pcre.get_substring subs 2) in
+                 let minor =
+                   try int_of_string (Pcre.get_substring subs 2)
+                   with Not_found -> 0 in
                  LinuxRoot (UnknownArch, RHEL (major, minor))
                with
                  Not_found | Failure "int_of_string" ->
@@ -694,7 +726,7 @@ let rec main ttyname =
            match lines with
            | [] -> (* empty /etc/debian_version ...? *)
                LinuxRoot (UnknownArch, OtherLinux)
-           | line::_ ->
+           | line::_ -> (* try to detect version from /etc/debian_version *)
                try
                  let subs = Pcre.exec ~rex:debian line in
                  let major = int_of_string (Pcre.get_substring subs 1) in