PyPXE-一个牛逼的一站式PXE安装包

一般来说,我们要搭建一个正式的pxe自动装机系统,需要装 dnsmasq 做 dhcp + tftp ,需要编译 ipxe 来获得 undionly.kpxe ,需要 http 服务器来提供资源下载,repo 同步服务来提供 repo。组件非常多,也比较麻烦。

当然,这么多也是有必要的,因为可以持续提供一个稳定的装机系统。

场景一换,如果我们在本地机房里,什么都没有,想搭一套环境的步骤就比较繁复了。

PyPXE 就是非常简单的一个程序,居然自己实现了用于 PXE 的 dhcp、tftp 和 http 全部的功能,而且支持 iPXE。

太牛逼了,前提啊,PyPXE 是基于 Python 2.7 的,Python 3.x是运行不了的。

想让它跑起来还必须做一定的修改,步骤如下:

一、下载PyPXE

1git clone https://github.com/pypxe/PyPXE.git
2cd PyPXE

下载就行了,不用安装。

二、手动生成config.json配置文件

 1{
 2    "DHCP_SERVER_IP": "192.168.85.27",
 3    "DHCP_FILESERVER": "192.168.85.27",
 4
 5    "DHCP_OFFER_BEGIN": "192.168.85.200",
 6    "DHCP_OFFER_END": "192.168.85.250",
 7    "DHCP_SUBNET": "255.255.255.0",
 8    "DHCP_ROUTER": "192.168.85.1",
 9    "DHCP_DNS": "114.114.114.114",
10 
11    "DHCP_SERVER_PORT": 67,
12    "DHCP_BROADCAST": "",
13    "DHCP_MODE_PROXY": false,
14    "DHCP_WHITELIST": false,
15    "HTTP_PORT": 80,
16    "LEASES_FILE": "",
17    "MODE_DEBUG": "dhcp",
18    "MODE_VERBOSE": "",
19    "NBD_BLOCK_DEVICE": "",
20    "NBD_COPY_TO_RAM": false,
21    "NBD_COW": true,
22    "NBD_COW_IN_MEM": false,
23    "NBD_PORT": 10809,
24    "NBD_SERVER_IP": "0.0.0.0",
25    "NBD_WRITE": false,
26    "NETBOOT_DIR": "netboot",
27    "NETBOOT_FILE": "boot.http.ipxe",
28    "STATIC_CONFIG": "",
29    "SYSLOG_PORT": 514,
30    "SYSLOG_SERVER": null,
31    "USE_DHCP": true,
32    "USE_HTTP": true,
33    "USE_IPXE": true,
34    "USE_TFTP": true
35}

上面json文件无法加注解,我们把它分三部分

  • 本机配置,本机的地址都是 192.168.85.27

  • dhcp 的配置,开始192.168.85.200,结束192.68.85.250,掩码255.255.255.0,网关192.168.85.1,DNS114.114.114.114

  • 第三部分不用动

三、下载ISO并修改ipxe脚本

 1cd netboot
 2wget http://mirrors.163.com/rocky/8/isos/x86_64/Rocky-8.4-x86_64-dvd1.iso
 3mkdir rocky8.iso
 4mount -o loop Rocky-8.4-x86_64-dvd1.iso rocky8.iso
 5
 6cat << EOF >> boot.http.ipxe
 7#!ipxe
 8
 9:start
10menu PXE Boot Options
11item shell iPXE shell
12item Rocky8 Install rocky8
13item exit  Exit to BIOS
14
15choose --default rocky8 --timeout 5000 option && goto ${option}
16:shell
17shell
18
19
20:rocky8
21set root http://192.168.85.27/rocky8.iso
22initrd ${root}/images/pxeboot/initrd.img
23kernel ${root}/images/pxeboot/vmlinuz inst.repo=${root}/ initrd=initrd.img ip=dhcp
24boot
25
26
27:exit
28exit
29EOF

三、修改源代码

运行一下:

1python -m pypxe.server --config config.json --debug all --verbose all

如果我们起一台机器或者虚机,会报第一个错:

UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc0 in position 0: ordinal not in range(128)

Float Left

这个是代码报错,我们需要修改一下

 1vi pypxe/dhcp.py
 2
 3    def tlv_encode(self, tag, value):
 4        '''Encode a TLV option.'''
 5        
 6        # 注释掉下面的两行,我们不需要打印出我们一定能看懂的字符,都按bytes处理即可
 7        #if type(value) is str:
 8        #    value = value.encode('ascii')
 9        value = bytes(value)
10        return struct.pack('BB', tag, len(value)) + value

然后我们需要修改第二个地方,理由是这个 PyPXE 会判断 Client 发过来的 dhcp 请求,它只实现了针对PXE-Client的 Vendor-class:

所以我们也要屏蔽一下,否则按照正常过程

客户端dhcp –> PyPXE 后,PyPXE 送回客户 ipxe 脚本,然后客户安装,当加载了vmlinuzinitrd之后会进入anaconda-linux进行系统安装,过程中会再次向DHCP服务器申请IP地址, 这个时候他向DHCP Server发出的discover申请是得不到回复的,因此安装过程将被打断。

 1vi pypxe/dhcp.py
 2
 3    def validate_req(self, client_mac):
 4        # client request is valid only if contains Vendor-Class = PXEClient
 5        '''代码整个注释掉,直接返回 True
 6        if self.whitelist and self.get_mac(client_mac) not in self.get_namespaced_static('dhcp.binding'):
 7            self.logger.info('Non-whitelisted client request received from {0}'.format(self.get_mac(client_mac)))
 8            return False
 9        if 60 in self.options[client_mac] and 'PXEClient'.encode() in self.options[client_mac][60][0]:
10            self.logger.info('PXE client request received from {0}'.format(self.get_mac(client_mac)))
11            return True
12        self.logger.info('Non-PXE client request received from {0}'.format(self.get_mac(client_mac)))
13        return False
14        '''
15        return True

这样修改后,就可以正常安装了。

服务器启动:

Float Left

客户端启动pxe开始安装,看下面,系统的ipxe dhcp一次,然后chainload.kpxe 又一次,anaconda 又一次,最少会发三次或更多的dhcp请求。

Float Left

用 VNC 连进去可以看到安装画面,如果是 kickstart 就是全自动安装了。

Float Left


ETCD + CONFD + NGINX的配置
Vsftpd的日志设置