Fetch boot files via http instead of TFTP » History » Version 23
Lukas Zapletal, 07/20/2018 02:54 PM
Added option architecture code 93 = unsigned integer 16;
1 | 22 | Lukas Zapletal | h1. Using iPXE in Foreman |
---|---|---|---|
2 | 1 | Alexander Chuzhoy | |
3 | 14 | Lukas Zapletal | {{toc}} |
4 | |||
5 | 10 | Lukas Zapletal | TFTP is a slow protocol on high-latency networks, but if your hardware is supported by iPXE (http://ipxe.org/appnote/hardware_drivers) or if UNDI driver of the NIC is compatible with iPXE, it is possible to configure PXELinux to chainboot iPXE and continue booting via HTTP protocol which is fast and reliable. |
6 | 1 | Alexander Chuzhoy | |
7 | 10 | Lukas Zapletal | In this scenario, a system is PXE-booted into PXELinux which chainloads iPXE which continue booting via HTTP. The scenario is: |
8 | |||
9 | * hardware is turned on |
||
10 | * PXE driver gets network credentials from DHCP |
||
11 | * PXE driver gets PXELinux firmware from TFTP (pxelinux.0) |
||
12 | * PXELinux searches for configuration file on TFTP |
||
13 | * PXELinux chainloads iPXE (undionly-ipxe.0 or ipxe.lkrn) |
||
14 | * iPXE gets network credentials from DHCP again |
||
15 | * iPXE gets HTTP address from DHCP |
||
16 | * iPXE chainloads the iPXE template from Foreman |
||
17 | * iPXE loads kernel and init RAM disk of the installer |
||
18 | |||
19 | Requirements: |
||
20 | |||
21 | 21 | Lukas Zapletal | * hardware or VM is BIOS only (no UEFI) |
22 | * hardware is capable of PXE booting |
||
23 | * iPXE project has hardware driver for network card or hypervisor already uses iPXE as NIC firmware |
||
24 | 1 | Alexander Chuzhoy | * a host entry is created in Foreman |
25 | 21 | Lukas Zapletal | * MAC and IP addresses of the provisioning interface matches with Foreman inventory |
26 | * smart-proxy templates plugin is used when there is NAT between Foreman and client |
||
27 | 1 | Alexander Chuzhoy | * provisioning interface of the host has a valid DHCP reservation |
28 | |||
29 | 21 | Lukas Zapletal | These workflows won't work with discovery. |
30 | 1 | Alexander Chuzhoy | |
31 | 21 | Lukas Zapletal | h2. Chainbooting virtual machines |
32 | 1 | Alexander Chuzhoy | |
33 | Since most virtualization hypervisors use iPXE as the primary firmware for PXE booting, the above configuration will directly work without TFTP and PXELinux involved. This is known to work with libvirt, oVirt and RHEV. If the hypervisor is capable of replacing PXE firmware, it will work too (e.g. VMWare is documented at http://ipxe.org/howto/vmware). |
||
34 | |||
35 | This workflow will only work if *tokens are disabled*, to do that go to Administer - Settings and set "Token duration" to 0. There are two options. |
||
36 | |||
37 | 21 | Lukas Zapletal | h3. Foreman setup - iPXE templates |
38 | 1 | Alexander Chuzhoy | |
39 | 21 | Lukas Zapletal | * Associate iPXE template 'Kickstart default iPXE' or 'Preseed default iPXE' depending on OS family with your Host or Hostgroup. |
40 | * Select the 'Kickstart/Preseed default iPXE' as the default template for an Operating System |
||
41 | * Set PXE Loader of the Host/Hostgroup must be set to "None" |
||
42 | 1 | Alexander Chuzhoy | |
43 | h3. DHCP setup - managed server |
||
44 | |||
45 | In this case, Foreman manages DHCP and reservation (IP address) is known in advance, therefore iPXE script can be found in Foreman DB and returned to a client: |
||
46 | |||
47 | 21 | Lukas Zapletal | * VM (BIOS) is turned on |
48 | 1 | Alexander Chuzhoy | * iPXE gets network credentials from DHCP |
49 | * iPXE gets filename option from DHCP (URL) |
||
50 | * iPXE chainloads the iPXE template from Foreman |
||
51 | * Foreman renders iPXE template for given host found by remote IP |
||
52 | * iPXE executed the script, loads kernel and init RAM disk of the installer |
||
53 | |||
54 | In the /etc/dhcp/dhcpd.conf file change the "filename" global or subnet configuration as follows: |
||
55 | |||
56 | <pre><code> |
||
57 | 23 | Lukas Zapletal | option architecture code 93 = unsigned integer 16; |
58 | 1 | Alexander Chuzhoy | if exists user-class and option user-class = "iPXE" { |
59 | 21 | Lukas Zapletal | filename "http://FOREMAN_OR_PROXY/unattended/iPXE"; |
60 | } elsif option architecture = 00:06 { |
||
61 | filename "grub2/shim.efi"; |
||
62 | } elsif option architecture = 00:07 { |
||
63 | filename "grub2/shim.efi"; |
||
64 | } elsif option architecture = 00:09 { |
||
65 | filename "grub2/shim.efi"; |
||
66 | 10 | Lukas Zapletal | } else { |
67 | 12 | Lukas Zapletal | filename "pxelinux.0"; |
68 | } |
||
69 | </code></pre> |
||
70 | |||
71 | h3. DHCP setup - unmanaged server |
||
72 | |||
73 | In this case, Foreman cannot create DHCP reservation in advance. But an intermediate iPXE script can be deployed to report MAC address to find proper host: |
||
74 | |||
75 | 21 | Lukas Zapletal | * VM (BIOS) is turned on |
76 | 9 | Lukas Zapletal | * iPXE gets network credentials from DHCP |
77 | 1 | Alexander Chuzhoy | * iPXE gets filename option from DHCP (URL) |
78 | * iPXE loads the intermediate iPXE template from a HTTP server |
||
79 | * iPXE executes the intermediate script |
||
80 | * iPXE chainloads the iPXE template from Foreman with MAC address provided as a parameter |
||
81 | 10 | Lukas Zapletal | * Foreman renders iPXE template for given host found by remote IP |
82 | 9 | Lukas Zapletal | * iPXE executed the script, loads kernel and init RAM disk of the installer |
83 | 1 | Alexander Chuzhoy | |
84 | 19 | Lukas Zapletal | Create the following script and put it somewhere on the network via HTTP so iPXE clients can access it. |
85 | 1 | Alexander Chuzhoy | |
86 | 12 | Lukas Zapletal | <pre><code> |
87 | 1 | Alexander Chuzhoy | #!ipxe |
88 | 12 | Lukas Zapletal | # Intermediate iPXE script to report MAC address to Foreman |
89 | 1 | Alexander Chuzhoy | isset ${net0/mac} || goto no_nic |
90 | dhcp net0 || goto net1 |
||
91 | 21 | Lukas Zapletal | chain http://FOREMAN_OR_PROXY/unattended/iPXE?mac=${net0/mac} || goto net1 |
92 | 1 | Alexander Chuzhoy | exit 0 |
93 | |||
94 | :net1 |
||
95 | isset ${net1/mac} || goto no_nic |
||
96 | 12 | Lukas Zapletal | dhcp net1 || goto net2 |
97 | 21 | Lukas Zapletal | chain http://FOREMAN_OR_PROXY/unattended/iPXE?mac=${net1/mac} || goto net2 |
98 | 1 | Alexander Chuzhoy | exit 0 |
99 | |||
100 | 9 | Lukas Zapletal | :net1 |
101 | 21 | Lukas Zapletal | # Create as many copies as necessary (the example will work up to 2 NICs) |
102 | 1 | Alexander Chuzhoy | |
103 | :no_nic |
||
104 | echo Failed to chainload from any network interface |
||
105 | sleep 30 |
||
106 | 12 | Lukas Zapletal | exit 1 |
107 | 1 | Alexander Chuzhoy | </code></pre> |
108 | 10 | Lukas Zapletal | |
109 | 1 | Alexander Chuzhoy | Let's use httpd on Foreman server for this purpose: |
110 | 10 | Lukas Zapletal | |
111 | <pre><code> |
||
112 | 11 | Lukas Zapletal | # scp intermediate.ipxe root@foreman:/var/www/htdocs/pub/ |
113 | 13 | Lukas Zapletal | </code></pre> |
114 | 10 | Lukas Zapletal | |
115 | 21 | Lukas Zapletal | On an *unmanaged DHCP server* change filename option to be "http://FOREMAN_OR_PROXY/pub/intermediate.ipxe". Instructions are different for various DHCP servers (like MS DHCP, Infoblox, Bluecoat) but if this was ISC DHCP, then simply change /etc/dhcp/dhcpd.conf file as follows: |
116 | 1 | Alexander Chuzhoy | |
117 | 18 | Lukas Zapletal | <pre><code> |
118 | if exists user-class and option user-class = "iPXE" { |
||
119 | 21 | Lukas Zapletal | filename "http://FOREMAN_OR_PROXY/pub/intermediate.ipxe"; |
120 | 16 | Lukas Zapletal | } else { |
121 | filename "pxelinux.0"; |
||
122 | } |
||
123 | </code></pre> |
||
124 | |||
125 | 21 | Lukas Zapletal | h3. Remarks |
126 | 16 | Lukas Zapletal | |
127 | 21 | Lukas Zapletal | * Configuration file dhcpd.conf is under puppet control, it can be overwritten. |
128 | * Use Foreman server IP address or smart-proxy IP address with port 8000 instead FOREMAN_OR_PROXY. |
||
129 | * Software iPXE shipped with Red Hat does not have HTTPS support compiled in, use HTTP instead. |
||
130 | * On isolated networks, a Smart Proxy Templates feature must be enabled must be enabled to work around NAT. |
||
131 | * Foreman 1.17 and older will not accept "mac" HTTP option, unless bootdisk plugin is installed, so make sure it is present. Foreman 1.18+ already accepts the "mac" option even if bootdisk plugin is not installed. |
||
132 | * Both managed and unmanaged setups are for BIOS VMs, it is possible to use UEFI VMs but iPXE EFI build must be downloaded separately as it's not part of RHEL package: |
||
133 | |||
134 | <pre><code> |
||
135 | $ wget http://boot.ipxe.org/ipxe.efi -O /var/lib/tftpboot/ipxe.efi |
||
136 | |||
137 | 23 | Lukas Zapletal | option architecture code 93 = unsigned integer 16; |
138 | 21 | Lukas Zapletal | if exists user-class and option user-class = "iPXE" { |
139 | filename "http://FOREMAN_OR_PROXY/unattended/iPXE"; |
||
140 | } elsif option architecture = 00:06 { |
||
141 | filename "ipxe.efi"; |
||
142 | } elsif option architecture = 00:07 { |
||
143 | filename "ipxe.efi"; |
||
144 | } elsif option architecture = 00:09 { |
||
145 | filename "ipxe.efi"; |
||
146 | } else { |
||
147 | filename "pxelinux.0"; |
||
148 | } |
||
149 | </code></pre> |
||
150 | |||
151 | h2. PXELinux chainboots iPXE |
||
152 | |||
153 | In this setup, iPXE uses build-in driver for network communication or UNDI interface. Therefore this will only work on supported cards. This setup will only work on BIOS systems. |
||
154 | |||
155 | h3. TFTP setup |
||
156 | |||
157 | Copy the iPXE firmware to the TFTP root directory: |
||
158 | |||
159 | cp /usr/share/ipxe/ipxe.lkrn /var/lib/tftpboot/ |
||
160 | cp /usr/share/ipxe/undionly.kpxe /var/lib/tftpboot/undionly-ipxe.0 |
||
161 | |||
162 | The source directory can be different on linux distributions, this is for Red Hats. The file is shipped in ipxe-bootimgs package. |
||
163 | |||
164 | Not all hardware is supported by iPXE drivers. In case of troubles, use latest development version build of iPXE: |
||
165 | |||
166 | wget -O /var/lib/tftpboot/ http://boot.ipxe.org/ipxe.lkrn |
||
167 | |||
168 | Do not use symbolic links as TFTP runs in chroot. When using SELinux, remember to correct file contexts: |
||
169 | |||
170 | restorecon -RvF /var/lib/tftpboot/ |
||
171 | |||
172 | h3. Foreman setup - PXELinux template |
||
173 | |||
174 | * Associate iPXE template "Kickstart default iPXE" or "Preseed default iPXE" depending on OS family with an Operating System. |
||
175 | * Associate templates named "PXELinux chain iPXE" and "PXELinux chain iPXE UNDI" with the same Operating System. |
||
176 | * Select the "Kickstart/Preseed default iPXE" as default for the Operating System. |
||
177 | * Select the "PXELinux chain iPXE" as default for the Operating System. |
||
178 | * Set PXE Loader of the Host/Hostgroup must be set to "PXELinux BIOS" |
||
179 | |||
180 | h3. DHCP setup |
||
181 | |||
182 | The above configuration will lead to an endless loop of chainbooting iPXE firmware. To break this loop, configure DHCP server to hand over correct URL to iPXE to continue booting. In the /etc/dhcp/dhcpd.conf file change the "filename" global or subnet configuration as follows: |
||
183 | |||
184 | <pre><code> |
||
185 | 23 | Lukas Zapletal | option architecture code 93 = unsigned integer 16; |
186 | 21 | Lukas Zapletal | if exists user-class and option user-class = "iPXE" { |
187 | filename "http://FOREMAN_OR_PROXY/unattended/iPXE"; |
||
188 | } elsif option architecture = 00:06 { |
||
189 | filename "grub2/shim.efi"; |
||
190 | } elsif option architecture = 00:07 { |
||
191 | filename "grub2/shim.efi"; |
||
192 | } elsif option architecture = 00:09 { |
||
193 | filename "grub2/shim.efi"; |
||
194 | } else { |
||
195 | filename "pxelinux.0"; |
||
196 | } |
||
197 | </code></pre> |
||
198 | |||
199 | h3. Remarks |
||
200 | |||
201 | * Configuration file dhcpd.conf is under puppet control, it can be overwritten. |
||
202 | * Use Foreman server IP address or smart-proxy IP address with port 8000 instead FOREMAN_OR_PROXY. |
||
203 | * Software iPXE shipped with Red Hat does not have HTTPS support compiled in, use HTTP instead. |
||
204 | * This works only for BIOS, for UEFI hosts use UEFI HTTP booting instead. |