def run(self, connection, max_end_time): """ Read data from the download action and replace in context Use common data for all values passed into the substitutions so that multiple actions can use the same code. """ # Multiple deployments would overwrite the value if parsed in the validate step. # FIXME: implement isolation for repeated steps. connection = super().run(connection, max_end_time) ip_addr = dispatcher_ip(self.job.parameters["dispatcher"]) self.ram_disk = self.get_namespace_data(action="compress-ramdisk", label="file", key="ramdisk") # most jobs substitute RAMDISK, so also use this for the initrd if self.get_namespace_data(action="nbd-deploy", label="nbd", key="initrd"): self.ram_disk = self.get_namespace_data(action="download-action", label="file", key="initrd") substitutions = { "{SERVER_IP}": ip_addr, "{PRESEED_CONFIG}": self.get_namespace_data(action="download-action", label="file", key="preseed"), "{PRESEED_LOCAL}": self.get_namespace_data(action="compress-ramdisk", label="file", key="preseed_local"), "{DTB}": self.get_namespace_data(action="download-action", label="file", key="dtb"), "{RAMDISK}": self.ram_disk, "{INITRD}": self.ram_disk, "{KERNEL}": self.get_namespace_data(action="download-action", label="file", key="kernel"), "{LAVA_MAC}": self.lava_mac, "{TEE}": self.get_namespace_data(action="download-action", label="file", key="tee"), } self.bootcommand = self.get_namespace_data( action="uboot-prepare-kernel", label="bootcommand", key="bootcommand") if not self.bootcommand and "type" in self.parameters: raise JobError("Kernel image type can't be determined") prepared_kernel = self.get_namespace_data(action="prepare-kernel", label="file", key="kernel") if prepared_kernel: self.logger.info("Using kernel file from prepare-kernel: %s", prepared_kernel) substitutions["{KERNEL}"] = prepared_kernel if self.bootcommand: kernel_addr = self.job.device["parameters"][ self.bootcommand]["kernel"] dtb_addr = self.job.device["parameters"][self.bootcommand]["dtb"] ramdisk_addr = self.job.device["parameters"][ self.bootcommand]["ramdisk"] tee_addr = self.job.device["parameters"][self.bootcommand].get( "tee") if (not self.get_namespace_data( action="tftp-deploy", label="tftp", key="ramdisk") and not self.get_namespace_data( action="download-action", label="file", key="ramdisk") and not self.get_namespace_data( action="download-action", label="file", key="initrd")): ramdisk_addr = "-" add_header = self.job.device["actions"]["deploy"][ "parameters"].get("add_header") if self.method == "u-boot" and not add_header == "u-boot": self.logger.debug( "No u-boot header, not passing ramdisk to bootX cmd") ramdisk_addr = "-" if self.get_namespace_data(action="download-action", label="file", key="initrd"): # no u-boot header, thus no embedded size, so we have to add it to the # boot cmd with colon after the ramdisk if self.get_namespace_data(action="download-action", label="file", key="tee"): substitutions["{BOOTX}"] = "%s %s %s:%s %s" % ( self.bootcommand, tee_addr, ramdisk_addr, "${initrd_size}", dtb_addr, ) else: substitutions["{BOOTX}"] = "%s %s %s:%s %s" % ( self.bootcommand, kernel_addr, ramdisk_addr, "${initrd_size}", dtb_addr, ) else: if self.get_namespace_data(action="download-action", label="file", key="tee"): substitutions["{BOOTX}"] = "%s %s %s %s" % ( self.bootcommand, tee_addr, ramdisk_addr, dtb_addr, ) else: substitutions["{BOOTX}"] = "%s %s %s %s" % ( self.bootcommand, kernel_addr, ramdisk_addr, dtb_addr, ) substitutions["{KERNEL_ADDR}"] = kernel_addr substitutions["{DTB_ADDR}"] = dtb_addr substitutions["{RAMDISK_ADDR}"] = ramdisk_addr substitutions["{TEE_ADDR}"] = tee_addr self.results = { "kernel_addr": kernel_addr, "dtb_addr": dtb_addr, "ramdisk_addr": ramdisk_addr, "tee_addr": tee_addr, } nfs_address = self.get_namespace_data(action="persistent-nfs-overlay", label="nfs_address", key="nfsroot") nfs_root = self.get_namespace_data(action="download-action", label="file", key="nfsrootfs") if nfs_root: substitutions["{NFSROOTFS}"] = self.get_namespace_data( action="extract-rootfs", label="file", key="nfsroot") substitutions["{NFS_SERVER_IP}"] = ip_addr elif nfs_address: substitutions["{NFSROOTFS}"] = nfs_address substitutions["{NFS_SERVER_IP}"] = self.get_namespace_data( action="persistent-nfs-overlay", label="nfs_address", key="serverip") if "lava-xnbd" in self.parameters: substitutions["{NBDSERVERIP}"] = str( self.get_namespace_data(action="nbd-deploy", label="nbd", key="nbd_server_ip")) substitutions["{NBDSERVERPORT}"] = str( self.get_namespace_data(action="nbd-deploy", label="nbd", key="nbd_server_port")) substitutions["{ROOT}"] = self.get_namespace_data( action="bootloader-from-media", label="uuid", key="root") # UUID label, not a file substitutions["{ROOT_PART}"] = self.get_namespace_data( action="bootloader-from-media", label="uuid", key="boot_part") # Save the substitutions self.set_namespace_data( action=self.name, label=self.method, key="substitutions", value=substitutions, ) if self.use_bootscript: script = "/script.ipxe" bootscript = (self.get_namespace_data( action="tftp-deploy", label="tftp", key="tftp_dir") + script) bootscripturi = "tftp://%s/%s" % ( ip_addr, os.path.dirname(substitutions["{KERNEL}"]) + script, ) write_bootscript(substitute(self.commands, substitutions), bootscript) bootscript_commands = ["dhcp net0", "chain %s" % bootscripturi] self.set_namespace_data( action=self.name, label=self.method, key="commands", value=bootscript_commands, ) self.logger.info("Parsed boot commands: %s", "; ".join(bootscript_commands)) return connection subs = substitute(self.commands, substitutions, drop=True) self.set_namespace_data(action="bootloader-overlay", label=self.method, key="commands", value=subs) self.logger.debug("substitutions:") for k in sorted(substitutions.keys()): self.logger.debug("- %s: %s", k, substitutions[k]) self.logger.info("Parsed boot commands:") for sub in subs: self.logger.info("- %s", sub) return connection
def run(self, connection, max_end_time, args=None): """ Read data from the download action and replace in context Use common data for all values passed into the substitutions so that multiple actions can use the same code. """ # Multiple deployments would overwrite the value if parsed in the validate step. # FIXME: implement isolation for repeated steps. connection = super(BootloaderCommandOverlay, self).run(connection, max_end_time, args) ip_addr = dispatcher_ip(self.job.parameters['dispatcher']) self.ram_disk = self.get_namespace_data(action='compress-ramdisk', label='file', key='ramdisk') # most jobs substitute RAMDISK, so also use this for the initrd if self.get_namespace_data(action='nbd-deploy', label='nbd', key='initrd'): self.ram_disk = self.get_namespace_data(action='download-action', label='file', key='initrd') substitutions = { '{SERVER_IP}': ip_addr, '{PRESEED_CONFIG}': self.get_namespace_data(action='download-action', label='file', key='preseed'), '{PRESEED_LOCAL}': self.get_namespace_data(action='compress-ramdisk', label='file', key='preseed_local'), '{DTB}': self.get_namespace_data(action='download-action', label='file', key='dtb'), '{RAMDISK}': self.ram_disk, '{INITRD}': self.ram_disk, '{KERNEL}': self.get_namespace_data(action='download-action', label='file', key='kernel'), '{LAVA_MAC}': self.lava_mac } self.bootcommand = self.get_namespace_data(action='uboot-prepare-kernel', label='bootcommand', key='bootcommand') if not self.bootcommand: if 'type' in self.parameters: self.logger.warning("Using type from the boot action as the boot-command. " "Declaring a kernel type in the deploy is preferred.") self.bootcommand = self.parameters['type'] prepared_kernel = self.get_namespace_data(action='prepare-kernel', label='file', key='kernel') if prepared_kernel: self.logger.info("Using kernel file from prepare-kernel: %s", prepared_kernel) substitutions['{KERNEL}'] = prepared_kernel if self.bootcommand: self.logger.debug("%s", self.job.device['parameters']) kernel_addr = self.job.device['parameters'][self.bootcommand]['kernel'] dtb_addr = self.job.device['parameters'][self.bootcommand]['dtb'] ramdisk_addr = self.job.device['parameters'][self.bootcommand]['ramdisk'] if not self.get_namespace_data(action='tftp-deploy', label='tftp', key='ramdisk') \ and not self.get_namespace_data(action='download-action', label='file', key='ramdisk') \ and not self.get_namespace_data(action='download-action', label='file', key='initrd'): ramdisk_addr = '-' add_header = self.job.device['actions']['deploy']['parameters'].get('add_header', None) if self.method == 'u-boot' and not add_header == "u-boot": self.logger.debug("No u-boot header, not passing ramdisk to bootX cmd") ramdisk_addr = '-' if self.get_namespace_data(action='download-action', label='file', key='initrd'): # no u-boot header, thus no embedded size, so we have to add it to the # boot cmd with colon after the ramdisk substitutions['{BOOTX}'] = "%s %s %s:%s %s" % ( self.bootcommand, kernel_addr, ramdisk_addr, '${initrd_size}', dtb_addr) else: substitutions['{BOOTX}'] = "%s %s %s %s" % ( self.bootcommand, kernel_addr, ramdisk_addr, dtb_addr) substitutions['{KERNEL_ADDR}'] = kernel_addr substitutions['{DTB_ADDR}'] = dtb_addr substitutions['{RAMDISK_ADDR}'] = ramdisk_addr self.results = { 'kernel_addr': kernel_addr, 'dtb_addr': dtb_addr, 'ramdisk_addr': ramdisk_addr } nfs_address = self.get_namespace_data(action='persistent-nfs-overlay', label='nfs_address', key='nfsroot') nfs_root = self.get_namespace_data(action='download-action', label='file', key='nfsrootfs') if nfs_root: substitutions['{NFSROOTFS}'] = self.get_namespace_data(action='extract-rootfs', label='file', key='nfsroot') substitutions['{NFS_SERVER_IP}'] = ip_addr elif nfs_address: substitutions['{NFSROOTFS}'] = nfs_address substitutions['{NFS_SERVER_IP}'] = self.get_namespace_data( action='persistent-nfs-overlay', label='nfs_address', key='serverip') nbd_root = self.get_namespace_data(action='download-action', label='file', key='nbdroot') if nbd_root: substitutions['{NBDSERVERIP}'] = str(self.get_namespace_data(action='nbd-deploy', label='nbd', key='nbd_server_ip')) substitutions['{NBDSERVERPORT}'] = str(self.get_namespace_data(action='nbd-deploy', label='nbd', key='nbd_server_port')) substitutions['{ROOT}'] = self.get_namespace_data(action='bootloader-from-media', label='uuid', key='root') # UUID label, not a file substitutions['{ROOT_PART}'] = self.get_namespace_data(action='bootloader-from-media', label='uuid', key='boot_part') if self.use_bootscript: script = "/script.ipxe" bootscript = self.get_namespace_data(action='tftp-deploy', label='tftp', key='tftp_dir') + script bootscripturi = "tftp://%s/%s" % (ip_addr, os.path.dirname(substitutions['{KERNEL}']) + script) write_bootscript(substitute(self.commands, substitutions), bootscript) bootscript_commands = ['dhcp net0', "chain %s" % bootscripturi] self.set_namespace_data(action=self.name, label=self.method, key='commands', value=bootscript_commands) self.logger.info("Parsed boot commands: %s", '; '.join(bootscript_commands)) return connection subs = substitute(self.commands, substitutions) self.set_namespace_data(action='bootloader-overlay', label=self.method, key='commands', value=subs) self.logger.info("Parsed boot commands: %s", '; '.join(subs)) return connection