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

[Xen-devel] [PATCH 4/7] osstest: add a FreeBSD host install recipe



The installation is performed using the bsdinstall tool, which is part of the
FreeBSD base system. The installer image is setup with the osstest ssh keys and
sshd enabled by default, which allows the test harness to just ssh into the
box, create the install config file and launch the scripted install.

Currently the installation is done with ZFS only, in stripe mode, and a single
disk.

In order to support the FreeBSD installer a new method is added, that allows
setting the pxe boot of a host using a memdisk. Also, a new tftp path is added
in order to point to the place where the FreeBSD installed images should be
stored.

The install script either picks the binary images from the output of a previous
FreeBSD buildjob (yet to be introduced), or from the freebsd_image and
freebsd_sets runvars, that should point to a FreeBSD installer image and to the
folder that contain the install sets respectively.

When relying on the output from a previous FreeBSD buildjob (freebsd_buildjob
runvar is set), the install image is picked from the path_freebsd-image runvar,
and the sets from path_freebsd-{base,kernel,manifest} of the previous job.

Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
 Osstest.pm              |   1 +
 Osstest/TestSupport.pm  |  18 +++-
 ts-freebsd-host-install | 259 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 276 insertions(+), 2 deletions(-)
 create mode 100755 ts-freebsd-host-install

diff --git a/Osstest.pm b/Osstest.pm
index a78728cd..a0c0339c 100644
--- a/Osstest.pm
+++ b/Osstest.pm
@@ -227,6 +227,7 @@ sub readglobalconfig () {
     $c{TftpTmpDir} ||= "$c{TftpPlayDir}tmp/";
 
     $c{TftpDiBase} ||= "$c{TftpPlayDir}debian-installer";
+    $c{TftpFreeBSDBase} ||= "$c{TftpPlayDir}freebsd-installer";
     $c{TftpDiVersion} ||= $c{ "TftpDiVersion_$c{DebianSuite}" } // 'current';
 
     $c{TftpGrubBase} ||= "$c{TftpPlayDir}grub";
diff --git a/Osstest/TestSupport.pm b/Osstest/TestSupport.pm
index 8c7078c5..4418f024 100644
--- a/Osstest/TestSupport.pm
+++ b/Osstest/TestSupport.pm
@@ -118,7 +118,7 @@ BEGIN {
                       await_webspace_fetch_byleaf create_webfile
                       file_link_contents get_timeout
                       setup_netboot_di setup_netboot_local host_netboot_file
-                     subst_netboot_template
+                      subst_netboot_template setup_netboot_memdisk
 
                       ether_prefix
 
@@ -1032,7 +1032,7 @@ sub selecthost ($) {
     $ho->{Tftp} = { };
     $ho->{Tftp}{$_} = $c{"Tftp${_}_${tftpscope}"} || $c{"Tftp${_}"}
         foreach qw(Path TmpDir PxeDir NetbootGroup PxeTemplates 
PxeTemplatesReal
-                   DiBase GrubBase
+                   DiBase GrubBase FreeBSDBase
                    NetGrubDir NetGrubTemplates NetGrubTemplatesReal
                    PxeGroup);
     $ho->{TftpNetbootGroup} //= $ho->{TftpPxeGroup}; # compatibility
@@ -2553,6 +2553,20 @@ default local
 END
 }
 
+sub setup_netboot_memdisk ($$) {
+    my ($ho, $img) = @_;
+    setup_netboot_bootcfg($ho, <<END);
+serial 0 $c{Baud}
+timeout 5
+label overwrite
+       menu label ^Overwrite
+       menu default
+       kernel memdisk
+       append initrd=$img
+default overwrite
+END
+}
+
 # uboot emulates pxelinux, so reuse BIOS stuff
 sub setup_netboot_di_uboot ($$$$$;%) { return &setup_netboot_di_bios; }
 sub setup_netboot_local_uboot ($) { return &setup_netboot_local_bios; }
diff --git a/ts-freebsd-host-install b/ts-freebsd-host-install
new file mode 100755
index 00000000..d59b66a4
--- /dev/null
+++ b/ts-freebsd-host-install
@@ -0,0 +1,259 @@
+#!/usr/bin/perl -w
+# This is part of "osstest", an automated testing framework for Xen.
+# Copyright (C) 2017 Citrix Inc.
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+# 
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+use strict qw(vars);
+use DBI;
+use POSIX;
+
+unshift @INC, qw(.);
+use Osstest;
+use Osstest::TestSupport;
+
+tsreadconfig();
+
+our %xopts;
+
+our ($whhost) = @ARGV;
+$whhost ||= 'host';
+our $ho= selecthost($whhost);
+exit 0 if $ho->{Flags}{'no-reinstall'};
+exit 0 if $ho->{SharedReady};
+
+our %timeout= qw(Sshd 1000);
+
+our @sets = qw(base.txz kernel.txz);
+
+our $image = $r{"freebsd_image"} ||
+             get_stashed("path_freebsd-image", $r{"freebsd_buildjob"});
+
+sub get_sets_path () {
+    my @paths;
+
+    foreach (@sets, "MANIFEST") {
+        my $path;
+
+        if (!defined($r{"freebsd_sets"})) {
+            # Get everything before the "." (ie: get base from base.txz)
+            my $stash_name = lc((split /\./)[0]);
+            $path = get_stashed("path_freebsd-$stash_name",
+                                $r{"freebsd_buildjob"});
+        } else {
+            $path = $r{"freebsd_sets"} . "/$_";
+        }
+
+        push @paths, { name => "$_", path => "$path" };
+    }
+
+    return @paths;
+}
+
+sub create_ssh_overlay () {
+    my $url = create_webfile($ho, "ssh.tar", sub {
+        my ($fh) = @_;
+        contents_make_cpio($fh, 'ustar',  "$c{OverlayLocal}/etc/ssh/");
+    });
+
+    return $url;
+}
+
+sub setup_netboot_installer () {
+    my $pxeimg = "$ho->{Tftp}{FreeBSDBase}/install-$ho->{Name}.img";
+    my $script = <<END;
+set -ex
+basedir=$ho->{Tftp}{Path}/$ho->{Tftp}{FreeBSDBase}/
+hash=`sha256sum $image|head -c 64`
+localpath="$r{arch}/\$hash/install.img";
+mkdir -p \$basedir
+(
+flock -x -w 600 200
+cd \$basedir
+if [ ! -f \$localpath ]; then
+    mkdir -p `dirname \$localpath`
+    cp $image \$localpath
+fi
+rm -f install-$ho->{Name}.img
+ln \$localpath install-$ho->{Name}.img
+for hash in `ls $r{arch}/`; do
+    count=`stat -c %h $r{arch}/\$hash/install.img`
+    if [ \$count -eq 1 ]; then
+        rm -rf $r{arch}/\$hash
+    fi
+done
+) 200<\$basedir
+END
+
+    logm("Executing:\n$script");
+    my $ret = system("/bin/bash -c '$script'");
+    $ret == 0 or die "Unable to setup netboot";
+
+    # Setup the pxelinux config file
+    logm("Booting from installer image at $pxeimg");
+    setup_netboot_memdisk($ho, $pxeimg);
+}
+
+sub install () {
+    my $authkeys = authorized_keys();
+    my $knownhosts = known_hosts();
+    my $sshd_keys_url = create_ssh_overlay();
+    my $disk_names = "ada0 da0 ad0";
+    my $installer_sets = join(" ", @sets);
+    my $target_sets = "/tmp/osstest_sets";
+    my $disk;
+    my $nic;
+
+    target_cmd_root($ho, 'chsh -s /bin/sh', 10);
+
+    logm("Trying to find a disk to install to");
+    $disk = target_cmd_output_root($ho, <<END, 30);
+for disk in $disk_names; do
+    if [ -c "/dev/\$disk" ]; then
+        echo \$disk
+        exit 0
+    fi
+done
+exit 1
+END
+    defined($disk) or die "Unable to find a valid disk";
+    logm("Using $disk as destination disk device");
+
+    logm("Trying to figure out primary nic device name");
+    $nic = target_cmd_output_root($ho, <<END, 30);
+nics=`ifconfig -l`
+for nic in \$nics; do
+    addr=`ifconfig \$nic inet|grep inet|awk {'print \$2'}`
+    if [ "\$addr" = "$ho->{Ip}" ]; then
+        echo \$nic
+        exit 0
+    fi
+done
+exit 1
+END
+    defined($nic) or die "Unable to find primary network interface";
+    logm("Using $nic as primary network interface");
+
+    logm("Uploading the install sets to the system");
+    target_cmd_root($ho, <<END, 30);
+mkdir -p $target_sets
+mount -o size=1G -t tmpfs tmpfs $target_sets
+END
+
+    foreach (get_sets_path()) {
+        target_putfile_root($ho, 600, $_->{path}, "$target_sets/$_->{name}");
+    }
+
+    logm("Creating the installer script");
+    target_cmd_root($ho, <<END, 60);
+        set -e
+        cat << ENDSCRIPT > installscript
+set -a
+BSDINSTALL_DISTDIR="$target_sets"
+ZFSBOOT_DISKS="$disk"
+DISTRIBUTIONS="$installer_sets"
+nonInteractive=1
+
+#!/bin/sh
+set -ex
+
+# Setup nic and sshd
+echo "ifconfig_$nic=DHCP" >> /etc/rc.conf
+echo "sshd_enable=YES" >> /etc/rc.conf
+
+# Disable sendmail
+echo "sendmail_enable=NONE" >> /etc/rc.conf
+
+# Set proxy for the pkg manager
+mkdir -p /usr/local/etc/
+cat << ENDPKG >> /usr/local/etc/pkg.conf
+pkg_env: { http_proxy = $c{HttpProxy} }
+default_always_yes: true
+assume_always_yes: true
+ENDPKG
+
+# Bootstap the package manager
+export HTTP_PROXY=$c{HttpProxy}
+export ASSUME_ALWAYS_YES=yes
+pkg update
+
+# Allow root user login and setup ssh keys
+chsh -s /bin/sh root
+echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
+mkdir -p /root/.ssh
+cat << ENDKEYS > /root/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+cat << ENDHOSTS > /root/.ssh/known_hosts
+$knownhosts
+ENDHOSTS
+
+# Fetch host keys
+fetch $sshd_keys_url -o - | tar -xf - -C /etc/ssh/
+# Set correct permissions
+chown root:wheel /etc/ssh/ssh_host_*_key*
+chmod 0600 /etc/ssh/ssh_host_*_key
+chmod 0644 /etc/ssh/ssh_host_*_key.pub
+
+# Add a osstest user
+pw useradd osstest -m
+chsh -s /bin/sh osstest
+mkdir -p /home/osstest/.ssh
+cat << ENDKEYS > /home/osstest/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+cat << ENDHOSTS > /home/osstest/.ssh/known_hosts
+$knownhosts
+ENDHOSTS
+
+# Setup serial console
+printf "%s" "-h -S$c{Baud}" >> /boot.config
+cat << ENDBOOT >> /boot/loader.conf
+boot_serial="YES"
+comconsole_speed="$c{Baud}"
+console="comconsole"
+boot_verbose="YES"
+beastie_disable="YES"
+ENDBOOT
+
+ENDSCRIPT
+END
+
+    logm("Launch the installer");
+    target_cmd_root($ho, 'bsdinstall script installscript', 1200);
+
+    target_reboot($ho);
+
+    logm("Waiting for the host to boot");
+    await_tcp(get_timeout($ho,'reboot',$timeout{Sshd}), 14, $ho);
+
+    logm("FreeBSD installed succesfully");
+}
+
+# Switch off, setup PXE and switch on to the installer
+power_state($ho, 0);
+setup_netboot_installer();
+power_cycle_sleep($ho);
+power_state($ho, 1);
+
+# Wait for the host to finish booting
+logm("Waiting for the installer to boot");
+await_tcp(get_timeout($ho,'reboot',$timeout{Sshd}), 14, $ho);
+
+# Next boot will be from local disk
+setup_netboot_local($ho);
+
+# Proceed with the install
+install();
+
-- 
2.11.0 (Apple Git-81)


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.