diff options
-rw-r--r-- | clusters/moonshot-pxe-armv8l64.morph | 22 | ||||
-rw-r--r-- | moonshot-kernel.configure | 33 | ||||
-rw-r--r-- | moonshot/boot/m400-1003.dtb | bin | 0 -> 18063 bytes | |||
-rw-r--r-- | moonshot/manifest | 2 | ||||
-rwxr-xr-x | pxeboot.write | 102 | ||||
-rw-r--r-- | pxeboot.write.help | 31 | ||||
-rw-r--r-- | strata/bsp-armv8l64-generic.morph | 2 | ||||
-rw-r--r-- | strata/bsp-armv8l64-generic/linux-armv8l64-generic.morph (renamed from strata/bsp-armv8l64-generic/bsp-armv8l64-generic.morph) | 1 | ||||
-rw-r--r-- | systems/build-system-armv8l64.morph | 3 | ||||
-rw-r--r-- | systems/devel-system-armv8l64.morph | 3 |
10 files changed, 173 insertions, 26 deletions
diff --git a/clusters/moonshot-pxe-armv8l64.morph b/clusters/moonshot-pxe-armv8l64.morph new file mode 100644 index 00000000..3286c72e --- /dev/null +++ b/clusters/moonshot-pxe-armv8l64.morph @@ -0,0 +1,22 @@ +name: moonshot-m400-armv8l64-netboot +kind: cluster +description: | + Deploy an armv8l64 devel system into a HP Moonshot node + + The system will be configured to boot through PXE from existing DHCP, + TFTP and NFS servers. +systems: +- morph: systems/devel-system-armv8l64.morph + deploy: + netboot: + type: pxeboot + location: 14:58:d0:57:7f:42 + PXEBOOT_MODE: existing-server + PXEBOOT_CONFIG_TFTP_ADDRESS: sftp://192.168.0.1/srv/nfsboot/tftp/ + PXEBOOT_ROOTFS_RSYNC_ADDRESS: rsync://192.168.0.1/srv/nfsboot/ + KERNEL_ARGS: console=ttyS0,9600n8r rw + DTB_PATH: boot/m400-1003.dtb + HOSTNAME: baserock-m400-node31 + MOONSHOT_KERNEL: yes + INSTALL_FILES: moonshot/manifest + PXE_INSTALLER: no diff --git a/moonshot-kernel.configure b/moonshot-kernel.configure new file mode 100644 index 00000000..11d01751 --- /dev/null +++ b/moonshot-kernel.configure @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (C) 2014 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# This is a "morph deploy" configuration extension to convert a plain +# kernel Image to uImage, for an HP Moonshot m400 cartridge + +set -eu + +case "$MOONSHOT_KERNEL" in + True|yes) + echo "Converting kernel image for Moonshot" + mkimage -A arm -O linux -C none -T kernel -a 0x00080000 \ + -e 0x00080000 -n Linux -d "$1/boot/vmlinux" "$1/boot/uImage" + ;; + *) + echo Unrecognised option "$MOONSHOT_KERNEL" to MOONSHOT_KERNEL + exit 1 + ;; +esac diff --git a/moonshot/boot/m400-1003.dtb b/moonshot/boot/m400-1003.dtb Binary files differnew file mode 100644 index 00000000..d6fd83ee --- /dev/null +++ b/moonshot/boot/m400-1003.dtb diff --git a/moonshot/manifest b/moonshot/manifest new file mode 100644 index 00000000..dd80fe49 --- /dev/null +++ b/moonshot/manifest @@ -0,0 +1,2 @@ +0040755 0 0 /boot +0100744 0 0 /boot/m400-1003.dtb diff --git a/pxeboot.write b/pxeboot.write index e33da527..399914f5 100755 --- a/pxeboot.write +++ b/pxeboot.write @@ -223,11 +223,13 @@ class PXEBoot(morphlib.writeexts.WriteExtension): @contextlib.contextmanager def _remote_tempdir(self, hostname, template): + persist = os.environ.get('PXE_INSTALLER') in ('no', 'False') td = cliapp.ssh_runcmd(hostname, ['mktemp', '-d', template]).strip() try: yield td finally: - cliapp.ssh_runcmd(hostname, ['find', td, '-delete']) + if not persist: + cliapp.ssh_runcmd(hostname, ['find', td, '-delete']) def _serve_tftpd(self, sock, host, port, interface, tftproot): self.settings.progname = 'tftp server' @@ -321,6 +323,7 @@ class PXEBoot(morphlib.writeexts.WriteExtension): @contextlib.contextmanager def _remote_copy(self, hostname, src, dst): + persist = os.environ.get('PXE_INSTALLER') in ('no', 'False') with open(src, 'r') as f: cliapp.ssh_runcmd(hostname, ['install', '-D', '-m644', '/proc/self/fd/0', @@ -328,7 +331,20 @@ class PXEBoot(morphlib.writeexts.WriteExtension): try: yield finally: - cliapp.ssh_runcmd(hostname, ['rm', dst]) + if not persist: + cliapp.ssh_runcmd(hostname, ['rm', dst]) + + @contextlib.contextmanager + def _remote_symlink(self, hostname, src, dst): + persist = os.environ.get('PXE_INSTALLER') in ('no', 'False') + cliapp.ssh_runcmd(hostname, + ['ln', '-s', '-f', src, dst], + stdin=None, stdout=None, stderr=None) + try: + yield + finally: + if not persist: + cliapp.ssh_runcmd(hostname, ['rm', '-f', dst]) @contextlib.contextmanager def remote_kernel(self, rootfs, tftp_url, macaddr): @@ -346,6 +362,21 @@ class PXEBoot(morphlib.writeexts.WriteExtension): yield basename @contextlib.contextmanager + def remote_fdt(self, rootfs, tftp_url, macaddr): + fdt_rel_path = os.environ.get('DTB_PATH', '') + if fdt_rel_path == '': + yield + fdt_abs_path = os.path.join(rootfs, fdt_rel_path) + if not fdt_abs_path: + raise cliapp.AppException('Failed to locate Flattened Device Tree') + url = urlparse.urlsplit(tftp_url) + basename = '{}-fdt'.format(_normalise_macaddr(macaddr)) + target_path = os.path.join(url.path, basename) + with self._remote_copy(hostname=url.hostname, src=fdt_abs_path, + dst=target_path): + yield basename + + @contextlib.contextmanager def local_nfsroot(self, rootfs, target_ip): nfsroot = target_ip + ':' + rootfs self.status(msg='Exporting %(nfsroot)s as local nfsroot', @@ -362,17 +393,21 @@ class PXEBoot(morphlib.writeexts.WriteExtension): @contextlib.contextmanager def remote_nfsroot(self, rootfs, rsync_url, macaddr): url = urlparse.urlsplit(rsync_url) - template = os.path.join(url.path, 'nfsroot.XXXXXXXXXX') + template = os.path.join(url.path, + _normalise_macaddr(macaddr) + '.XXXXXXXXXX') with self._remote_tempdir(hostname=url.hostname, template=template) \ as tempdir: - nfsroot = urlparse.urlunsplit(url.scheme, url.netloc, tempdir, - url.query, url.fragment) - cliapp.runcmd(['rsync', '-asXSPH', '--delete', rootfs, nfsroot], - stdin=None, stdout=None, stderr=None) - yield basename + nfsroot = urlparse.urlunsplit((url.scheme, url.netloc, tempdir, + url.query, url.fragment)) + cliapp.runcmd(['rsync', '-asSPH', '--delete', rootfs, nfsroot], + stdin=None, stdout=open(os.devnull, 'w'), + stderr=None) + yield os.path.join(os.path.basename(tempdir), + os.path.basename(rootfs)) @staticmethod - def _write_pxe_config(fh, kernel_tftp_url, rootfs_nfs_url, extra_args=''): + def _write_pxe_config(fh, kernel_tftp_url, rootfs_nfs_url, + fdt_subpath=None, extra_args=''): fh.write(textwrap.dedent('''\ DEFAULT default LABEL default @@ -380,6 +415,8 @@ class PXEBoot(morphlib.writeexts.WriteExtension): APPEND root=/dev/nfs ip=dhcp nfsroot={rootfs_nfs_url} {extra_args} ''').format(kernel_url=kernel_tftp_url, rootfs_nfs_url=rootfs_nfs_url, extra_args=extra_args)) + if fdt_subpath is not None: + fh.write("FDT {}\n".format(fdt_subpath)) fh.flush() @contextlib.contextmanager @@ -401,19 +438,29 @@ class PXEBoot(morphlib.writeexts.WriteExtension): @contextlib.contextmanager def remote_pxeboot_config(self, tftproot, kernel_tftproot, kernel_subpath, - rootfs_nfsroot, rootfs_subpath, macaddr): - rootfs_nfs_url = '{}:{}/{}'.format(ip, rootfs_nfsroot, rootfs_subpath) - kernel_tftp_url = '{}/{}'.format(kernel_tftproot, kernel_subpath) + fdt_subpath, rootfs_nfsroot, rootfs_subpath, + macaddr): + rootfs_nfs_url = '{}/{}'.format(rootfs_nfsroot, rootfs_subpath) + url = urlparse.urlsplit(kernel_tftproot) + kernel_tftp_url = '{}:{}'.format(url.netloc, kernel_subpath) pxe_cfg_filename = _normalise_macaddr(macaddr) url = urlparse.urlsplit(tftproot) - inst_cfg_path = os.path.join(url.path, 'pxelinux.cfg', - pxe_cfg_filename) + inst_cfg_path = os.path.join(url.path, 'pxelinux.cfg') with tempfile.NamedTemporaryFile() as f: - self._write_pxe_config(fh=f, kernel_tftp_url=kernel_tftp_url, - rootfs_nfs_url=rootfs_nfs_url, - extra_args=os.environ.get('KERNEL_ARGS','')) - with self._remote_copy(hostname=url.hostname, src=f.name, - dst=inst_cfg_path): + self._write_pxe_config( + fh=f, kernel_tftp_url=kernel_tftp_url, + fdt_subpath=fdt_subpath, + rootfs_nfs_url=rootfs_nfs_url, + extra_args=os.environ.get('KERNEL_ARGS','')) + with self._remote_copy( + hostname=url.hostname, src=f.name, + dst=os.path.join(inst_cfg_path, + pxe_cfg_filename)), \ + self._remote_symlink( + hostname=url.hostname, + src=pxe_cfg_filename, + dst=os.path.join(inst_cfg_path, + '01-' + pxe_cfg_filename)): yield @contextlib.contextmanager @@ -660,19 +707,24 @@ class PXEBoot(morphlib.writeexts.WriteExtension): url = urlparse.urlsplit(rootfs_rsync) nfsroot = os.environ.get('PXEBOOT_ROOTFS_NFSROOT', '%s:%s' % (url.hostname, url.path)) - with self.remote_kernel(rootfs=temp_root, url=kernel_tftpaddr, + with self.remote_kernel(rootfs=temp_root, tftp_url=kernel_tftpaddr, macaddr=macaddr) as kernel_subpath, \ - self.remote_nfsroot(rootfs=temp_root, rsync_url=rootfs_rsync)\ - as rootfs_subpath, \ + self.remote_fdt(rootfs=temp_root, tftp_url=kernel_tftpaddr, + macaddr=macaddr) as fdt_subpath, \ + self.remote_nfsroot(rootfs=temp_root, rsync_url=rootfs_rsync, \ + macaddr=macaddr) as rootfs_subpath, \ self.remote_pxeboot_config(tftproot=config_tftpaddr, kernel_tftproot=kernel_tftproot, kernel_subpath=kernel_subpath, + fdt_subpath=fdt_subpath, rootfs_nfsroot=nfsroot, rootfs_subpath=rootfs_subpath, macaddr=macaddr): - self.ipmi_pxe_reboot_target() - self.wait_for_target_to_install() - self.ipmi_reboot_target() + persist = os.environ.get('PXE_INSTALLER') in ('no', 'False') + if not persist: + self.ipmi_pxe_reboot_target() + self.wait_for_target_to_install() + self.ipmi_reboot_target() else: cliapp.AppException('Invalid PXEBOOT_MODE: %s' % mode) diff --git a/pxeboot.write.help b/pxeboot.write.help index 58a86957..3aefe75e 100644 --- a/pxeboot.write.help +++ b/pxeboot.write.help @@ -121,3 +121,34 @@ help: > If it is possible for the target to notify you that it has finished installing, you can put a command in here to wait for the event. + + + # Misc + + + ## KERNEL_ARGS + + + Additional kernel command line options. Note that the following + options + + root=/dev/nfs ip=dhcp nfsroot=$NFSROOT` + + are implicitly added by the extension. + + + ## DTB_PATH + + + Location in the deployed root filesystem of the Flattened Device + Tree blob (FDT) to use. + + + ## PXE_INSTALLER + + + If set to `no`, `False` or any other YAML value for false, the + remotely installed rootfs, kernel, bootloader config file and + device tree blob if specified, will not be removed after the + deployment finishes. This variable is only meanful on the + `existing-server` mode. diff --git a/strata/bsp-armv8l64-generic.morph b/strata/bsp-armv8l64-generic.morph index 702858de..63c4ff5b 100644 --- a/strata/bsp-armv8l64-generic.morph +++ b/strata/bsp-armv8l64-generic.morph @@ -9,7 +9,7 @@ build-depends: - morph: strata/core.morph chunks: - name: linux-armv8l64-generic - morph: strata/bsp-armv8l64-generic/bsp-armv8l64-generic.morph + morph: strata/bsp-armv8l64-generic/linux-armv8l64-generic.morph repo: upstream:linux ref: 5f06398ae6a04f414932243de38b5cf3d264ff84 unpetrify-ref: baserock/apm-xgene-m400-moonshot-cartridge diff --git a/strata/bsp-armv8l64-generic/bsp-armv8l64-generic.morph b/strata/bsp-armv8l64-generic/linux-armv8l64-generic.morph index 120239b9..4eb92de4 100644 --- a/strata/bsp-armv8l64-generic/bsp-armv8l64-generic.morph +++ b/strata/bsp-armv8l64-generic/linux-armv8l64-generic.morph @@ -102,3 +102,4 @@ build-commands: install-commands: - mkdir -p "$DESTDIR"/boot - make install dtbs_install INSTALL_PATH="$DESTDIR/boot" +- cp arch/arm64/boot/Image "$DESTDIR/boot/vmlinux" diff --git a/systems/build-system-armv8l64.morph b/systems/build-system-armv8l64.morph index 7715ecb7..2fcb1e8c 100644 --- a/systems/build-system-armv8l64.morph +++ b/systems/build-system-armv8l64.morph @@ -12,6 +12,8 @@ strata: morph: strata/core.morph - name: foundation morph: strata/foundation.morph +- name: python-core + morph: strata/python-core.morph - name: bsp-armv8l64-generic morph: strata/bsp-armv8l64-generic.morph - name: tools @@ -39,3 +41,4 @@ configuration-extensions: - fstab - mason - cloud-init +- moonshot-kernel diff --git a/systems/devel-system-armv8l64.morph b/systems/devel-system-armv8l64.morph index 27080535..88495e48 100644 --- a/systems/devel-system-armv8l64.morph +++ b/systems/devel-system-armv8l64.morph @@ -30,6 +30,8 @@ strata: morph: strata/baserock-import.morph - name: nfs morph: strata/nfs.morph +- name: python-core + morph: strata/python-core.morph - name: python-tools morph: strata/python-tools.morph - name: devtools @@ -41,3 +43,4 @@ configuration-extensions: - nfsboot - install-files - cloud-init +- moonshot-kernel |