/usr/lib/python3/dist-packages/provisioningserver/boot/powernv.py is in python3-maas-provisioningserver 2.0.0~beta3+bzr4941-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | # Copyright 2014-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""PowerNV Boot Method"""
__all__ = [
'PowerNVBootMethod',
]
import re
from provisioningserver.boot import (
BootMethod,
BytesReader,
get_parameters,
get_remote_mac,
)
from provisioningserver.boot.pxe import (
ARP_HTYPE,
re_mac_address,
)
from provisioningserver.kernel_opts import compose_kernel_command_line
from provisioningserver.utils import typed
from tftp.backend import FilesystemReader
# The pxelinux.cfg path is prefixed with the architecture for the
# PowerNV nodes. This prefix is set by the path-prefix dhcpd option.
# We assume that the ARP HTYPE (hardware type) that PXELINUX sends is
# always Ethernet.
re_config_file = r'''
# Optional leading slash(es).
^/*
ppc64el # PowerNV pxe prefix, set by dhcpd
/
pxelinux[.]cfg # PXELINUX expects this.
/
(?: # either a MAC
{htype:02x} # ARP HTYPE.
-
(?P<mac>{re_mac_address.pattern}) # Capture MAC.
| # or "default"
default
)
$
'''
re_config_file = re_config_file.format(
htype=ARP_HTYPE.ETHERNET, re_mac_address=re_mac_address)
re_config_file = re_config_file.encode("ascii")
re_config_file = re.compile(re_config_file, re.VERBOSE)
def format_bootif(mac):
"""Formats a mac address into the BOOTIF format, expected by
the linux kernel."""
mac = mac.replace(':', '-')
mac = mac.lower()
return '%02x-%s' % (ARP_HTYPE.ETHERNET, mac)
class PowerNVBootMethod(BootMethod):
name = "powernv"
bios_boot_method = "powernv"
template_subdir = "pxe"
bootloader_path = "pxelinux.0"
arch_octet = "00:0E"
path_prefix = b"ppc64el/"
def get_params(self, backend, path):
"""Gets the matching parameters from the requested path."""
match = re_config_file.match(path)
if match is not None:
return get_parameters(match)
if path.lstrip(b'/').startswith(self.path_prefix):
return {'path': path}
return None
def match_path(self, backend, path):
"""Checks path for the configuration file that needs to be
generated.
:param backend: requesting backend
:param path: requested path
:return: dict of match params from path, None if no match
"""
params = self.get_params(backend, path)
if params is None:
return None
params['arch'] = "ppc64el"
if 'mac' not in params:
mac = get_remote_mac()
if mac is not None:
params['mac'] = mac
return params
def get_reader(self, backend, kernel_params, **extra):
"""Render a configuration file as a unicode string.
:param backend: requesting backend
:param kernel_params: An instance of `KernelParameters`.
:param extra: Allow for other arguments. This is a safety valve;
parameters generated in another component (for example, see
`TFTPBackend.get_config_reader`) won't cause this to break.
"""
# Due to the path prefix, all requested files from the client will
# contain that prefix. Removing the prefix from the path will return
# the correct path in the tftp root.
if 'path' in extra:
path = extra['path']
if path.startswith(self.path_prefix):
path = path[len(self.path_prefix):]
target_path = backend.base.descendant(path.split(b'/'))
return FilesystemReader(target_path)
# Return empty config for PowerNV local. PowerNV fails to
# support the LOCALBOOT flag. Empty config will allow it
# to select the first device.
if kernel_params.purpose == 'local':
return BytesReader("".encode("utf-8"))
template = self.get_template(
kernel_params.purpose, kernel_params.arch,
kernel_params.subarch)
namespace = self.compose_template_namespace(kernel_params)
# Modify the kernel_command to inject the BOOTIF. PowerNV fails to
# support the IPAPPEND pxelinux flag.
def kernel_command(params):
cmd_line = compose_kernel_command_line(params)
if 'mac' in extra:
mac = extra['mac']
mac = format_bootif(mac)
return '%s BOOTIF=%s' % (cmd_line, mac)
return cmd_line
namespace['kernel_command'] = kernel_command
return BytesReader(template.substitute(namespace).encode("utf-8"))
@typed
def install_bootloader(self, destination: str):
"""Does nothing. No extra boot files are required. All of the boot
files from PXEBootMethod will suffice."""
|