Add support for FreeBSD
authorNikos Skalkotos <skalkoto@grnet.gr>
Thu, 18 Apr 2013 13:03:04 +0000 (16:03 +0300)
committerNikos Skalkotos <skalkoto@grnet.gr>
Thu, 18 Apr 2013 14:36:06 +0000 (17:36 +0300)
File injection isn't implemented yet

snf-image-helper/common.sh
snf-image-helper/snf-image-helper.in
snf-image-helper/tasks/20FilesystemResizeUnmounted.in
snf-image-helper/tasks/30MountImage.in
snf-image-helper/tasks/40DeleteSSHKeys.in
snf-image-helper/tasks/50AssignHostname.in
snf-image-helper/tasks/50ChangePassword.in
snf-image-host/multistrap.conf
snf-image-host/version_pinning.pref

index 5db1119..827d954 100644 (file)
@@ -32,6 +32,7 @@ BLOCKDEV=blockdev
 REGLOOKUP=reglookup
 CHNTPW=chntpw
 SGDISK=sgdisk
+GROWFS_UFS=growfs.ufs
 DATE="date -u" # Time in UTC
 EATMYDATA=eatmydata
 MOUNT="mount -n"
@@ -190,6 +191,8 @@ get_base_distro() {
         echo "gentoo"
     elif [ -e "$root_dir/etc/arch-release" ]; then
         echo "arch"
+    elif [ -e "$root_dir/etc/freebsd-update.conf" ]; then
+        echo "freebsd"
     else
         warn "Unknown base distro."
     fi
@@ -222,6 +225,8 @@ get_distro() {
         echo "gentoo"
     elif [ -e "$root_dir/etc/arch-release" ]; then
         echo "arch"
+    elif [ -e "$root_dir/etc/freebsd-update.conf" ]; then
+        echo "freebsd"
     else
         warn "Unknown distro."
     fi
index 21bfe91..2ac51e2 100644 (file)
@@ -111,8 +111,8 @@ if [ -z "$SNF_IMAGE_PROPERTY_EXCLUDE_ALL_TASKS" ]; then
 
     export SNF_IMAGE_RESIZE_PART="$(get_partition_to_resize "$SNF_IMAGE_DEV")"
 
-    if [[ ! "$SNF_IMAGE_PROPERTY_OSFAMILY" =~ ^(linux|windows)$ ]]; then
-        log_error "Supported values for OSFAMILY property are: linux|windows"
+    if [[ ! "$SNF_IMAGE_PROPERTY_OSFAMILY" =~ ^(linux|windows|freebsd)$ ]]; then
+        log_error "Supported values for OSFAMILY property are: linux|windows|freebsd"
     fi
 
     # If something goes wrong with the tasks, try to umount the disk file
index 71cc284..44b77dd 100644 (file)
@@ -50,9 +50,9 @@ partition=$(get_partition_by_num "$table" "$SNF_IMAGE_RESIZE_PART")
 id=$(cut -d: -f1 <<< "$partition")
 ptype=$(cut -d: -f5 <<< "$partition")
 
-if [[ "$ptype" == ext[234] ]]; then
-    device="${SNF_IMAGE_DEV}${id}"
+device="${SNF_IMAGE_DEV}${id}"
 
+if [[ "$ptype" == ext[234] ]]; then
     state=$($TUNE2FS -l "$device" | grep ^Filesystem\ state: | cut -d: -f2);
     state=$(echo $state) #trim the value
 
@@ -66,7 +66,8 @@ if [[ "$ptype" == ext[234] ]]; then
         log_error "The file system state of partition: \`$device' " \
             " is not clean (state = $state)"
     fi
-
+elif [[ "$ptype" == "freebsd-ufs" ]]; then
+    $GROWFS_UFS -y "$device"
 else
     warn "Don't know how to resize partition \`$id' with file system \`$ptype'."
 fi
index b0c41ab..1d7946a 100644 (file)
@@ -45,7 +45,11 @@ if [ ! -b "$rootdev" ]; then
         "(=$SNF_IMAGE_PROPERTY_ROOT_PARTITION) is valid."
 fi
 
-$MOUNT "$rootdev" "$SNF_IMAGE_TARGET" -o rw
+if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" ]; then
+    $MOUNT -t ufs -o ufstype=ufs2,rw "$rootdev" "$SNF_IMAGE_TARGET"
+else
+    $MOUNT -o rw "$rootdev" "$SNF_IMAGE_TARGET"
+fi
 
 if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "linux" ]; then
     exit 0
index 1f4ffed..ed738d5 100644 (file)
@@ -37,7 +37,7 @@ if [ ! -d "$SNF_IMAGE_TARGET" ]; then
     log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing."
 fi
 
-if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "linux" ]; then
+if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" != "linux" -a "$SNF_IMAGE_PROPERTY_OSFAMILY" != "freebsd" ]; then
     exit 0
 fi
 
index 1b2d1a6..afb9687 100644 (file)
@@ -67,7 +67,7 @@ linux_hostname() {
         distro=$(get_base_distro "$target")
         case "$distro" in
             redhat)
-                sed -ie "s/HOSTNAME=.*$/HOSTNAME=$hostname/g" "$target/etc/sysconfig/network";;
+                sed -i -e "s/HOSTNAME=.*$/HOSTNAME=$hostname/g" "$target/etc/sysconfig/network";;
             slackware|suse)
                 #local domain=$(sed -e 's/^[^\.]*//g' < /etc/HOSTNAME)
 
@@ -75,17 +75,17 @@ linux_hostname() {
                 # I will not retain the domain name.
                 echo "$hostname" > "${target}/etc/HOSTNAME";;
             gentoo)
-                sed -ie "s/\(\(HOSTNAME\)\|\(hostname\)\)=.*$/\1=\"$hostname\"/" "$target/etc/conf.d/hostname";;
+                sed -i -e "s/\(\(HOSTNAME\)\|\(hostname\)\)=.*$/\1=\"$hostname\"/" "$target/etc/conf.d/hostname";;
             arch)
                 if [ -f "$target/etc/rc.conf" ]; then
-                    sed -ie "s/^HOSTNAME=.*$/HOSTNAME=\"$hostname\"/" "$target/etc/rc.conf"
+                    sed -i -e "s/^HOSTNAME=.*$/HOSTNAME=\"$hostname\"/" "$target/etc/rc.conf"
                 else
                     # In new versions of arch, /etc/rc.conf is missing
                     echo "$hostname" > "$target/etc/hostname"
                 fi
 
                 if grep "^127\.0\.0\.1[ \t]*" "$target/etc/hosts" > /dev/null; then
-                   sed -ie "s/127\.0\.0\.1[ \t]*.*$/127.0.0.1\t$hostname/" "$target/etc/hosts"
+                   sed -i -e "s/127\.0\.0\.1[ \t]*.*$/127.0.0.1\t$hostname/" "$target/etc/hosts"
                 else
                    echo -e "127.0.0.1\t$hostname" >> "$target/etc/hosts"
                 fi;;
@@ -95,11 +95,23 @@ linux_hostname() {
 
     # Some Linux distributions assign the hostname to 127.0.1.1 in order to be
     # resolvable to an IP address. Lets replace this if found in /etc/hosts
-    sed -ie "s/^[[:blank:]]*127\.0\.1\.1[[:blank:]].\+$/127.0.1.1\t$hostname/" "$target/etc/hosts"
+    sed -i -e "s/^[[:blank:]]*127\.0\.1\.1[[:blank:]].\+$/127.0.1.1\t$hostname/" "$target/etc/hosts"
+}
+
+freebsd_hostname() {
+    local target hostname
+    target="$1"
+    hostname="$2"
+
+    if grep ^hostname= "$target/etc/rc.conf"; then
+        sed -i -e "s/^hostname=.*$/hostname=\"$(printf "%q" "$hostname")\"/" "$target/etc/rc.conf"
+    else
+        echo "hostname=\"$(printf "%q" "$hostname")\"" >> "$target/etc/rc.conf"
+    fi
 }
 
 if [ ! -d "$SNF_IMAGE_TARGET" ]; then
-    log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"    
+    log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"
 fi
 
 if [ -z "$SNF_IMAGE_HOSTNAME" ]; then
@@ -110,6 +122,8 @@ if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "windows" ]; then
     windows_hostname "$SNF_IMAGE_TARGET" "$SNF_IMAGE_HOSTNAME"
 elif [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "linux" ]; then
     linux_hostname "$SNF_IMAGE_TARGET" "$SNF_IMAGE_HOSTNAME"
+elif [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" ]; then
+    freebsd_hostname "$SNF_IMAGE_TARGET" "$SNF_IMAGE_HOSTNAME"
 fi
 
 exit 0
index 375eeec..39f4961 100644 (file)
@@ -33,6 +33,29 @@ report_task_start
 # Check if the task should be prevented from running.
 check_if_excluded
 
+linux_shadow="/etc/shadow"
+freebsd_shadow="/etc/master.passwd"
+
+linux_change_shadow_entry() {
+    local line encrypted
+    line="$1"
+    encrypted="$2"
+
+    IFS=":" read -a entry <<< "$line"
+
+    echo "${entry[0]}:$encrypted:15103:0:99999:7:::"
+}
+
+freebsd_change_shadow_entry() {
+    local line encrypted
+    line="$1"
+    encrypted="$2"
+
+    IFS=":" read -a entry <<< "$line"
+
+    echo "${entry[0]}:$encrypted:${entry[2]}:${entry[3]}:${entry[4]}:${entry[5]}:0:${entry[7]}:${entry[8]}:${entry[9]}"
+}
+
 windows_password() {
     local target password
     target="$1"
@@ -55,15 +78,18 @@ windows_password() {
     done
 }
 
-linux_password() {
-    local target password hash users tmp_shadow
-    target="$1"
-    password="$2"
+unix_password() {
+    local flavor target password hash users tmp_shadow
+    flavor="$1"
+    target="$2"
+    password="$3"
 
-    hash=$("@scriptsdir@/snf-passtohash.py" "$password")
-    if [ ! -e "$target/etc/shadow" ]; then
-       log_error "No /etc/shadow found!" 
+    shadow="${flavor}_shadow"
+    if [ ! -e "$target${!shadow}" ]; then
+       log_error "No ${!shadow} found!"
     fi
+
+    hash=$("@scriptsdir@/snf-passtohash.py" "$password")
     
     users=()
     
@@ -82,17 +108,34 @@ linux_password() {
         add_cleanup rm "$tmp_shadow"
 
         echo -n "Setting ${users[$i]} password..."
-        if ! grep "^${users[$i]}:" "$target/etc/shadow" > /dev/null; then
+        entry=$(grep "^${users[$i]}:" "$target${!shadow}")
+        if [ -z "$entry" ]; then
             log_error "User: \`${users[$i]}' does not exist."
         fi
-    
-        echo "${users[$i]}:$hash:15103:0:99999:7:::" > "$tmp_shadow"
-        grep -v "${users[$i]}" "$target/etc/shadow" >> "$tmp_shadow"
-        cat "$tmp_shadow" > "$target/etc/shadow"
+
+        new_entry="$(${flavor}_change_shadow_entry "$entry" "$hash")"
+        grep -v "${users[$i]}" "$target${!shadow}" > "$tmp_shadow"
+        echo "$new_entry" >> "$tmp_shadow"
+        cat "$tmp_shadow" > "$target${!shadow}"
         echo "done"
     done
 }
 
+freebsd_password() {
+    local target password hash
+    target="$1"
+    password="$2"
+
+    if [ ! -e "$target/etc/master.passwd" ]; then
+        log_error "No /etc/master.passwd found!"
+    fi
+
+    hash=$("@scriptsdir@/snf-passtohash.py" "$password")
+    for i in $(seq 0 1 $((${#users[@]}-1))); do
+        tmp_master="$(mktemp)"
+    done
+}
+
 if [ ! -d "$SNF_IMAGE_TARGET" ]; then
     log_error "Target dir: \`$SNF_IMAGE_TARGET' is missing"
 fi
@@ -107,7 +150,35 @@ SNF_IMAGE_PROPERTY_USERS=$(echo $SNF_IMAGE_PROPERTY_USERS)
 if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "windows" ]; then
     windows_password "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
 elif [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "linux" ]; then
-    linux_password "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
+    unix_password linux "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
+elif [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" ]; then
+    unix_password freebsd "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWORD"
+
+    rm -f "$SNF_IMAGE_TARGET/etc/spwd.db"
+
+    # Make sure /etc/spwd.db is recreated on first boot
+    rc_local=$(cat <<EOF
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
+export PATH
+
+pwd_mkdb -p /etc/master.passwd
+EOF
+)
+    if [ -e "$SNF_IMAGE_TARGET/etc/rc.local" ]; then
+        orig_local="/etc/rc.local.snf_image_$RANDOM"
+        mv "$SNF_IMAGE_TARGET/etc/rc.local" "$SNF_IMAGE_TARGET$orig_local"
+        cat > "$SNF_IMAGE_TARGET/etc/rc.local" <<EOF
+$rc_local
+mv $orig_local /etc/rc.local
+. /etc/rc.local
+EOF
+    else
+        cat > "$SNF_IMAGE_TARGET/etc/rc.local" <<EOF
+$rc_local
+rm -f /etc/rc.local
+exit 0
+EOF
+    fi
 fi
 
 exit 0
index e7b313b..bc5b35a 100644 (file)
@@ -31,7 +31,7 @@ source=http://backports.debian.org/debian-backports
 suite=squeeze-backports
 
 [GRNet]
-packages=snf-image-helper ntfs-3g
+packages=snf-image-helper ntfs-3g ufsutils
 # Don't change the parameters below unless you really know what you are doing.
 # The /'s and the empty `componets' variable are needed when working with apt2.
 source=http://apt2.dev.grnet.gr/
index 45e24da..c9e20c2 100644 (file)
@@ -5,3 +5,15 @@ Pin-Priority: 1001
 Package: ntfs-3g
 Pin: version 1:2010.3.6+no-mtab-fix-1
 Pin-Priority: 1001
+
+Package: ufsutils
+Pin: version 7.3-1+b1+grnet.growfs.fix
+Pin-Priority: 1001
+
+Package: linux-image-2.6.32-5-amd64
+Pin: version 2.6.32-48squeeze1+ufs.rw
+Pin-Priority: 1001
+
+Package: linux-image-2.6.32-5-xen-amd64
+Pin: version 2.6.32-48squeeze1+ufs.rw
+Pin-Priority: 1001