summaryrefslogtreecommitdiff
path: root/pxeboot.write
diff options
context:
space:
mode:
Diffstat (limited to 'pxeboot.write')
-rwxr-xr-xpxeboot.write102
1 files changed, 77 insertions, 25 deletions
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)