X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=virt-p2v.ml;h=23b59f0ad1e0d8c457354c28f1b137ca6e4695ef;hb=e3ee0ffbe935690a7caf6d2972d23af58650ae24;hp=4b590afa6c436c778c1bd0eee41bc85e960dccfc;hpb=006c856bcddca31693d9b5b8916ef87135a230f8;p=virt-p2v.git diff --git a/virt-p2v.ml b/virt-p2v.ml index 4b590af..23b59f0 100755 --- a/virt-p2v.ml +++ b/virt-p2v.ml @@ -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,35 +453,46 @@ 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"; - chdir "/etc/sysconfig"; - - sh "mv network network.saved"; - sh "mv networking networking.saved"; - sh "mv network-scripts network-scripts.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. +(* + (* We can run /mnt/root/etc/init.d/network in a chroot environment, + * however this won't work directly because the architecture of the + * binaries under /mnt/root (eg. /mnt/root/sbin/ip) might not match + * the architecture of the live CD kernel. In particular, a 32 bit + * live CD cannot run 64 bit binaries. So we also have to bind-mount + * the live CD's /bin, /sbin, /lib etc. over the equivalents in + * /mnt/root. *) - 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 ."; - + let bind dir = + if is_dir dir = Some true then + sh ("mount -o bind " ^ quote dir ^ " " ^ quote ("/mnt/root" ^ dir)) + in + let unbind dir = + if is_dir dir = Some true then sh ("umount -l " ^ quote ("/mnt/root" ^ dir)) + in + let dirs = [ + "/bin"; "/sbin"; "/lib"; "/lib64"; + "/usr/bin"; "/usr/sbin"; "/usr/lib"; "/usr/lib64"; + "/proc"; "/sys" + ] in + List.iter bind dirs; + let status = shwithstatus "chroot /mnt/root /etc/init.d/network start" in + List.iter unbind dirs; +*) + + (* Simpler way to do the above. + * NB. Lazy unmount is required because dhclient keeps its current + * directory open on /etc/sysconfig/network-scripts/ + *) + sh "mount -o bind /mnt/root/etc /etc"; let status = shwithstatus "/etc/init.d/network start" in - - 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 "/tmp"; + sh "umount -l /etc"; (* Try to ping the remote host to see if this worked. *) shfailok ("ping -c 3 " ^ Option.map_default quote "" state.remote_host); @@ -643,8 +666,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 +693,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 +719,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