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

[Xen-devel] [PATCH v4 04/11] osstest: add support for installing bare metal FreeBSD



This is done using mfsBSD, which can be booted from pxelinux and
contains a script to automatically install FreeBSD using ZFS on root.
After the install the host is set to boot from the local disk.

Signed-off-by: Roger Pau Monnà <roger.pau@xxxxxxxxxx>
Cc: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
Changes since RFC:
 - Set the bridge to use the MAC from the first added interface
   instead of generating a random one.
 - Launch DHCP on the bridge instead of the nic.
 - Add a list of FreeBSD ftp mirrors and iterate over them in order to
   find a working one.
 - Add support for finding the primary disk and nic automatically.
 - Switch shell to sh (instead of the default csh), and use set -e in
   order to exit if a command fails.
 - Replace echo "-Dh" with printf "%s" "-Dh".
 - Copy installer keys into the installed system in order to prevent
   it from generating new keys on the first boot.
---
 production-config       |   2 +
 ts-freebsd-host-install | 283 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 285 insertions(+)
 create mode 100755 ts-freebsd-host-install

diff --git a/production-config b/production-config
index 515bd98..fefc467 100644
--- a/production-config
+++ b/production-config
@@ -86,6 +86,8 @@ HostProp_GenEtherPrefixBase 5a:36:0e:00
 #                                      :00:01 guest number in job appended
 #                                    ^^ xor'd with low 8 bits of flight
 
+FreeBSDVersion current
+
 AuthorizedKeysAppend= <<'END'
 ssh-rsa 
AAAAB3NzaC1yc2EAAAABIwAAAQEAq8eHHFJ+XHYgpHxfSdciq0b3tYPdMhHf9CgtwdKGSqCyDyocbn1jX6P0Z535K/JcVaxvaRQbGDl9FZ25neQw6lysE8pGf+G353mgLAE7Lw6xKqlTXDcR0GpKHiZUyY8Ck5AJlGF2MO0cDEzMBx+xkOahDBvAozikUcDHJsTNP+UUIGoRaPeQK0DfgprPkoaLzXFDiZvEoBtYcUUieuNygJt+QVM+ovyTXC68wg5Xb5Ou2PopmDaVMX6/A1HxziTWc3XdhOF5ocuRF/kfWpZL223Auuu/xvNQDly13DhuVlQiU3gRIP7BSCwCdsQC/K68Q6SgfBklKRiqHquYo/QyNQ==
 osstest@xxxxxxxxxxxxxxxxxxx
 ssh-rsa 
AAAAB3NzaC1yc2EAAAABIwAAAQEAs6FF9nfzWIlLPeYdqNteJBoYJAcgGxQgeNi7FHYDgWNFhoYPlMPXWOuXhgNxA2/vkX9tUMVZaAh+4WTL1iRBW5B/AS/Ek2O7uM2Uq8v68D2aU9/XalLVnIxssr84pewUmKW8hZfjNnRm99RTQ2Knr2BvtwcHqXtdGYdTYCJkel+FPYQ51yXGRU7dS0D59WapkDFU1tH1Y8s+dRZcRZNRJ5f1w/KO1zx1tOrZRkO3fPlEGNZHVUYfpZLPxz0VX8tOeoaOXhKZO8vSp1pD0L/uaD6FOmugMZxbtq9wEjhZciNCq61ynRf2yt2v9DMu4EAzbW/Ws7OBvWtYj/RHcSxKbw==
 iwj@xxxxxxxxxxxxxxxxxxx
diff --git a/ts-freebsd-host-install b/ts-freebsd-host-install
new file mode 100755
index 0000000..2097c66
--- /dev/null
+++ b/ts-freebsd-host-install
@@ -0,0 +1,283 @@
+#!/usr/bin/perl -w
+# This is part of "osstest", an automated testing framework for Xen.
+# Copyright (C) 2009-2014 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;
+
+use Osstest;
+use Osstest::TestSupport;
+use Osstest::Logtailer;
+
+use File::Basename;
+use File::Copy;
+use File::Path;
+use Cwd 'abs_path';
+
+tsreadconfig();
+
+our ($whhost) = grep /host=/, @ARGV;
+$whhost ||= 'host';
+our $ho= selecthost($whhost);
+exit 0 if $ho->{Flags}{'no-reinstall'};
+exit 0 if $ho->{SharedReady};
+
+our %timeout= qw(ReadPreseed  350
+                 Sshd        2400);
+
+our @disk_names = qw(ada0 da0 ad0);
+our @sets = qw(kernel.txz base.txz MANIFEST);
+
+defined($r{freebsd_buildjob}) or defined($c{FreeBSDVersion}) or
+    die "don't know which FreeBSD version to install";
+
+sub get_mfsbsd() {
+
+    # Figure out the path to the mfsBSD image we have to use.
+    # This can either come from a previous buildjob or from
+    # a pre-seeded image.
+
+    if ($r{freebsd_buildjob}) {
+        # We are going to use the build output from a previous job.
+        return get_stashed('path_mfsbsd.img', $r{freebsd_buildjob});
+    } else {
+        # We are going to use a pre-seeded version.
+        return "$c{Images}/freebsd/$c{FreeBSDVersion}/$r{arch}/mfsbsd.img";
+    }
+}
+
+sub get_set($) {
+    my ($set) = @_;
+
+    if ($r{freebsd_buildjob}) {
+        # We are going to use the build output from a previous job.
+        return get_stashed("path_$set", $r{freebsd_buildjob});
+    } else {
+        # We are going to use a pre-seeded version.
+        return "$c{Images}/freebsd/$c{FreeBSDVersion}/$r{arch}/$set";
+    }
+}
+
+sub setup_sets() {
+    my $webfolder = "$c{WebspaceFile}/$c{WebspaceCommon}/freebsd/$ho->{Name}";
+
+    # Link the sets to the public http folder
+    rmtree($webfolder);
+    mkpath($webfolder);
+    foreach my $set (@sets) {
+        my $set_src = abs_path(get_set($set));
+        logm("Using install set: $set_src");
+        symlink $set_src,"$webfolder/$set" or die "Unable to create symlink: 
$!";
+    }
+}
+
+sub setup_pxeboot_firstboot() {
+    # copy mfsBSD image from the images folder to the tftp folder.
+    my $mfs_src = get_mfsbsd();
+    my $mfs = "$ho->{Tftp}{TmpDir}/mfsbsd-$ho->{Name}.img";
+    unlink "$ho->{Tftp}{Path}/$mfs";
+
+    logm("Using mfsBSD image: $mfs_src");
+    copy($mfs_src, "$ho->{Tftp}{Path}/$mfs") or die "Unable to copy image 
file: $!";
+
+    setup_pxeboot($ho, <<END);
+serial 0 $c{Baud}
+timeout 5
+label overwrite
+    menu label ^Overwrite
+    menu default
+    kernel memdisk
+    append initrd=$mfs
+default overwrite
+END
+}
+
+sub set_host_keys ($;$) {
+    my ($restart, $prefix) = @_;
+    my $target_path;
+
+    if (defined $prefix) {
+        $target_path = "$prefix/etc/ssh/";
+    } else {
+        $target_path = "/etc/ssh/";
+    }
+
+    logm("Copying overlay keys to: $target_path");
+
+    my @ssh_keys = glob("$c{OverlayLocal}/etc/ssh/*");
+    foreach my $key (@ssh_keys) {
+        target_putfile_root($ho, 10, $key, $target_path, undef, 1);
+        # Force the usage of the keys that we have uploaded.
+        # If not mfsBSD/FreeBSD defaults to the automatically generated
+        # ECDSA key.
+        if ($key !~ /pub$/) {
+            $key = basename($key);
+            target_cmd_root($ho, <<END, 100, 1);
+                set -e
+                echo 'HostKey /etc/ssh/$key' >> $target_path/sshd_config
+END
+        }
+    }
+
+    if ($restart) {
+        logm("Restarting sshd");
+        target_cmd_root($ho, <<END, 100, 1);
+            set -e
+            /etc/rc.d/sshd restart
+END
+    }
+}
+
+sub install () {
+    my $authkeys= authorized_keys();
+    my $disk = "";
+    my $nic = "";
+    my $ftp = "";
+
+    power_state($ho, 0);
+
+    setup_pxeboot_firstboot();
+
+    logm('Booting into mfsBSD');
+
+    sleep(power_cycle_time($ho));
+
+    power_state($ho, 1);
+
+    # Prepare the sets while the host boots
+    setup_sets();
+
+    logm('Waiting for host to boot');
+    await_tcp(get_timeout($ho,'boot',$timeout{Sshd}), 22, $ho);
+
+    logm('Setting host to boot from local disk on next boot');
+    setup_pxeboot_local($ho);
+
+    logm('Switching root shell to /bin/sh');
+    target_cmd_root_with_password($ho, 'chsh -s /bin/sh', 100, "root", 1);
+
+    logm('Setting up ssh keys for remote access');
+    target_cmd_root_with_password($ho, <<END, 100, "root", 1);
+        set -e
+        mkdir -p ~/.ssh
+        cat <<ENDKEYS >~/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+END
+
+    set_host_keys(1);
+
+    foreach my $test_disk (@disk_names) {
+        logm("Probing for $test_disk existence");
+        my $output = target_cmd_output_root($ho,
+            'test -c /dev/'.$test_disk.' >/dev/null 2>&1 && echo "yes" || echo 
"no"',
+            200);
+        if ($output eq "yes") {
+            logm("Found a valid disk device: $test_disk");
+            $disk = $test_disk;
+            last;
+        }
+    }
+    length($disk) or die "Unable to find a valid disk, exiting";
+
+    my $sets_url = "$c{WebspaceUrl}/$c{WebspaceCommon}/freebsd/$ho->{Name}";
+    logm("Install of base system using ZFS on root, using sets from: 
$sets_url");
+    target_cmd_root($ho, <<END,2400);
+            set -e
+            gpart destroy -F $disk || true
+            zfsinstall -d $disk -u $sets_url -s 4g
+END
+
+    logm('Setting up ssh and keys for the installed system');
+    target_cmd_root($ho, <<END, 100);
+            set -e
+            echo 'sshd_enable="YES"' >> /mnt/etc/rc.conf
+            echo 'PermitRootLogin yes' >> /mnt/etc/ssh/sshd_config
+            mkdir -p /mnt/root/.ssh
+            cat <<ENDKEYS >/mnt/root/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+END
+
+    logm('Setting up serial console');
+    target_cmd_root($ho, <<END, 100);
+            set -e
+            printf "%s" "-Dh" >> /mnt/boot.config
+            cat <<ENDB >>/mnt/boot/loader.conf
+boot_multicons="YES"
+boot_serial="YES"
+comconsole_speed="$c{Baud}"
+console="comconsole,vidconsole"
+boot_verbose="YES"
+ENDB
+END
+
+    logm("Trying to figure out primary nic device name");
+    $nic = target_cmd_output_root($ho,
+            'ifconfig | grep -B3 '.$ho->{Ip}.' | head -n1 | awk \'{print 
$1}\'|sed s/://',
+            200);
+    length($nic) or die "Unable to find primary network interface";
+
+    logm("Using $nic as primary nic interface");
+
+    logm('Setting up network');
+    target_cmd_root($ho, <<END, 100);
+            set -e
+            echo "net.link.bridge.inherit_mac=1" >> /mnt/boot/loader.conf
+            echo 'cloned_interfaces="bridge0"' >> /mnt/etc/rc.conf
+            echo 'ifconfig_bridge0="addm $nic SYNCDHCP"' >> /mnt/etc/rc.conf
+            echo 'ifconfig_$nic="up"' >> /mnt/etc/rc.conf
+END
+
+    if ($c{HttpProxy}) {
+        logm("Setting pkg proxy to: $c{HttpProxy}");
+        target_cmd_root($ho, <<END, 100);
+            set -e
+            mkdir -p /mnt/usr/local/etc/
+            echo 'PKG_ENV: { http_proxy = $c{HttpProxy} }' >> 
/mnt/usr/local/etc/pkg.conf
+END
+    }
+
+    logm('Setting up miscellaneous settings');
+    target_cmd_root($ho, <<END, 100);
+            set -e
+            cp /mnt/usr/share/zoneinfo/Europe/London /mnt/etc/localtime
+            echo 'sendmail_enable="NONE"' >> /mnt/etc/rc.conf
+END
+
+    set_host_keys(0, "/mnt");
+
+    logm('Rebooting into the installed system');
+    target_reboot($ho);
+
+    logm('Setting root shell to /bin/sh');
+    target_cmd_root($ho, 'chsh -s /bin/sh', 100);
+    logm('Adding osstest user');
+    target_cmd_root($ho, 'pw useradd osstest -m', 100);
+    target_cmd_root($ho, <<END, 100);
+            set -e
+            chsh -s /bin/sh osstest
+            mkdir -p /home/osstest/.ssh
+            cat <<ENDKEYS >/home/osstest/.ssh/authorized_keys
+$authkeys
+ENDKEYS
+END
+
+    logm('OK: install completed');
+}
+
+install();
-- 
1.9.3 (Apple Git-50)


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

 


Rackspace

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