virt-sysprep: Use Augeas for config file manipulation.
[libguestfs.git] / clone / virt-sysprep.in
index b73acfb..cf4ad96 100644 (file)
@@ -167,6 +167,11 @@ fi
 # Create a temporary directory for general purpose use during operations.
 tmpdir="$(mktemp -d)"
 
+# Increase the amount of memory allocated to the appliance because
+# we're using augeas.  The user can override this by setting
+# $LIBGUESTFS_MEMSIZE before running the script.
+export LIBGUESTFS_MEMSIZE=${LIBGUESTFS_MEMSIZE:-2048}
+
 # Call guestfish.
 GUESTFISH_PID=
 eval $("${guestfish[@]}")
@@ -175,16 +180,19 @@ if [ -z "$GUESTFISH_PID" ]; then
     exit 1
 fi
 
+# Helper.
+gf="guestfish --remote --"
+
 cleanup ()
 {
-    kill $GUESTFISH_PID >/dev/null 2>&1 ||:
+    $gf exit >/dev/null 2>&1 ||:
     rm -rf "$tmpdir" ||:
 }
-trap cleanup EXIT
+trap cleanup EXIT ERR
 
 # Launch back-end, inspect for operating systems, and get the guest
 # root disk.
-root=$(guestfish --remote inspect-get-roots)
+root=$($gf inspect-get-roots)
 
 if [ "$root" = "" ]; then
     echo "$program: no operating system was found on this disk"
@@ -196,14 +204,20 @@ if [ "$verbose" = "yes" ]; then
 fi
 
 # Get the guest type.
-type="$(guestfish --remote -- -inspect-get-type $root)"
+type="$($gf -inspect-get-type $root)"
 
 if [ "$type" = "linux" ]; then
-    distro="$(guestfish --remote -- -inspect-get-distro $root)"
+    distro="$($gf -inspect-get-distro $root)"
 fi
 
 if [ "$type" = "windows" ]; then
-    systemroot="$(guestfish --remote -- -inspect-get-windows-systemroot $root)"
+    systemroot="$($gf -inspect-get-windows-systemroot $root)"
+fi
+
+# Start Augeas if it's a Linux guest.
+if [ "$type" = "linux" ]; then
+    $gf aug-init / 0
+    using_augeas=yes
 fi
 
 #----------------------------------------------------------------------
@@ -214,9 +228,21 @@ fi
 # Erase line(s) in a file that match the given regex.
 erase_line ()
 {
-    guestfish --remote -- download "$1" "$tmpdir/file"
+    $gf download "$1" "$tmpdir/file"
     sed "/$2/d" < "$tmpdir/file" > "$tmpdir/file.1"
-    guestfish --remote -- upload "$tmpdir/file.1" "$1"
+    $gf upload "$tmpdir/file.1" "$1"
+}
+
+# prepend_line filename line
+#
+# Prepend a line to a file (this is better than appending, because it
+# works even when the original file isn't terminated with a newline).
+prepend_line ()
+{
+    $gf download "$1" "$tmpdir/file"
+    echo "$2" > "$tmpdir/file.1"
+    cat "$tmpdir/file.1" "$tmpdir/file" >> "$tmpdir/file.2"
+    $gf upload "$tmpdir/file.2" "$1"
 }
 
 # rm_files wildcard
@@ -226,9 +252,9 @@ erase_line ()
 # quoting.
 rm_files ()
 {
-    files=$(guestfish --remote -- glob-expand "$1")
+    files=$($gf glob-expand "$1")
     for f in $files; do
-        guestfish --remote -- rm "$f"
+        $gf rm "$f"
     done
 }
 
@@ -238,9 +264,9 @@ rm_files ()
 # a file.
 rm_file ()
 {
-    t=$(guestfish --remote -- is-file "$1")
+    t=$($gf is-file "$1")
     if [ "$t" = "true" ]; then
-        guestfish --remote -- rm "$1"
+        $gf rm "$1"
     fi
 }
 
@@ -250,14 +276,12 @@ rm_file ()
 if [ "$hostname" = "yes" ]; then
     case "$type/$distro" in
         linux/fedora)
-            guestfish --remote -- \
-                download /etc/sysconfig/network "$tmpdir/network"
-            echo "HOSTNAME=$hostname_param" > "$tmpdir/network.1"
-            sed '/^HOSTNAME=/d' < "$tmpdir/network" >> "$tmpdir/network.1"
-            guestfish --remote -- \
-                upload "$tmpdir/network.1" /etc/sysconfig/network ;;
+            $gf aug-set /files/etc/sysconfig/network/HOSTNAME "$hostname_param"
+            augeas_save_needed=yes
+            ;;
         linux/debian|linux/ubuntu)
-            guestfish --remote -- write /etc/hostname "$hostname_param"
+            $gf write /etc/hostname "$hostname_param"
+            ;;
     esac
 fi
 
@@ -265,10 +289,13 @@ if [ "$net_hwaddr" = "yes" ]; then
     case "$type/$distro" in
         linux/fedora)
             # XXX these filenames can have spaces and untrusted chars in them!
-            files=$(guestfish --remote -- glob-expand '/etc/sysconfig/network-scripts/ifcfg-*')
-            for f in $files; do
-                erase_line "$f" "^HWADDR="
+            nodes=$( $gf aug-ls /files/etc/sysconfig/network-scripts |
+                     grep /files/etc/sysconfig/network-scripts/ifcfg- )
+            for node in $nodes; do
+                $gf -aug-rm "$node/HWADDR" >/dev/null
+                augeas_save_needed=yes
             done
+            ;;
     esac
 fi
 
@@ -280,10 +307,16 @@ if [ "$udev_persistent_net" = "yes" -a "$type" = "linux" ]; then
     rm_file /etc/udev/rules.d/70-persistent-net.rules
 fi
 
+#----------------------------------------------------------------------
 # Clean up and close down.
 
-guestfish --remote umount-all
-guestfish --remote sync
-guestfish --remote exit
+if [ "$using_augeas" = "yes" -a "$augeas_save_needed" = "yes" ]; then
+    $gf aug-save
+    $gf aug-close
+fi
+
+$gf umount-all
+$gf sync
+$gf exit
 
 exit 0