2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-02-28 16:21:40 +00:00

Extend a proxydhcpack

This is one stage of actually
providing download over
PXE.
This commit is contained in:
Jarrod Johnson 2020-04-01 16:40:47 -04:00
parent b573ffa897
commit 0fe136d4ee
2 changed files with 56 additions and 4 deletions

View File

@ -27,6 +27,7 @@ import confluent.log as log
import confluent.netutil as netutil
import ctypes
import ctypes.util
import eventlet
import eventlet.green.socket as socket
import eventlet.green.select as select
import struct
@ -162,7 +163,7 @@ def _decode_ocp_vivso(rq, idx, size):
idx += rq[idx + 1] + 2
return '', None, vivso
def opts_to_dict(rq, optidx):
def opts_to_dict(rq, optidx, expectype=1):
reqdict = {}
disco = {'uuid':None, 'arch': None, 'vivso': None}
try:
@ -173,7 +174,7 @@ def opts_to_dict(rq, optidx):
optidx += optlen + 2
except IndexError:
pass
if reqdict.get(53, [0])[0] != 1:
if reqdict.get(53, [0])[0] != expectype:
return reqdict, disco
# It is a discover packet..
iscumulus = False
@ -207,6 +208,54 @@ def opts_to_dict(rq, optidx):
def ipfromint(numb):
return socket.inet_ntoa(struct.pack('I', numb))
def proxydhcp():
net4011 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
net4011.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
net4011.setsockopt(socket.IPPROTO_IP, IP_PKTINFO, 1)
net4011.bind(('', 4011))
cfg = cfm.ConfigManager(None)
while True:
ready = select.select([net4011], [], [], None)
if not ready or not ready[0]:
continue
rq = bytearray(1024)
rqv = memoryview(rq)
nb, client = net4011.recvfrom_into(rq)
if nb < 240:
continue
rp = bytearray(1024)
rpv = memoryview(rp)
try:
optidx = rq.index(b'\x63\x82\x53\x63') + 4
except ValueError:
continue
opts, disco = opts_to_dict(rq, optidx, 3)
disco['uuid']
node = None
if disco.get('hwaddr', None) in macmap:
node = macmap[disco['hwaddr']]
elif disco.get('uuid', None) in uuidmap:
node = uuidmap[disco['uuid']]
if not node:
continue
myipn = myipbypeer.get(bytes(rq[28:44]), None)
if not myipn:
continue
rpv[:240] = bytes(rqv[:240])
rpv[0:1] = b'\x02'
bootfile = b'confluent/x86_64/ipxe.efi'
rpv[108:108 + len(bootfile)] = bootfile
rpv[240:243] = b'\x35\x01\x05'
rpv[243:249] = b'\x36\x04' + myipn
rpv[249:268] = b'\x61\x11' + bytes(opts[97])
rpv[268:280] = b'\x3c\x09PXEClient\xff'
net4011.sendto(rpv[:281], client)
def start_proxydhcp():
eventlet.spawn_n(proxydhcp)
def snoop(handler, protocol=None):
#TODO(jjohnson2): ipv6 socket and multicast for DHCPv6, should that be
#prominent
@ -290,7 +339,7 @@ def snoop(handler, protocol=None):
'netinfo': {'ifidx': idx, 'recvip': recv, 'txid': txid},
'attributes': {'enclosure-machinetype-model': [vivso.get('machine', '')]}}
handler(info)
consider_discover(info, rqinfo, net4, cfg, rqv)
#consider_discover(info, rqinfo, net4, cfg, rqv)
continue
# We will fill out service to have something to byte into,
# but the nature of the beast is that we do not have peers,
@ -341,6 +390,7 @@ def remap_nodes(nodeattribs, configmanager):
staticassigns = {}
myipbypeer = {}
def check_reply(node, info, packet, sock, cfg, reqview):
httpboot = info['architecture'] == 'uefi-httpboot'
replen = 275 # default is going to be 286
@ -412,6 +462,7 @@ def check_reply(node, info, packet, sock, cfg, reqview):
repview[replen - 1:replen + 11] = b'\x3c\x0aHTTPClient'
replen += 12
else:
myipbypeer[bytes(repview[28:44])] = myipn
repview[replen - 1:replen + 10] = b'\x3c\x09PXEClient'
replen += 11
if netmask:
@ -460,7 +511,6 @@ def check_reply(node, info, packet, sock, cfg, reqview):
repview[:replen + 28].tobytes()))
sendto(tsock.fileno(), pkt, replen + 28, 0, ctypes.byref(targ),
ctypes.sizeof(targ))
print('Thinking about reply to {0}'.format(node))
def consider_discover(info, packet, sock, cfg, reqview):

View File

@ -34,6 +34,7 @@ import confluent.core as confluentcore
import confluent.httpapi as httpapi
import confluent.log as log
import confluent.collective.manager as collective
import confluent.discovery.protocols.pxe as pxe
try:
import confluent.sockapi as sockapi
except ImportError:
@ -262,6 +263,7 @@ def run(args):
webservice = httpapi.HttpApi(http_bind_host, http_bind_port)
webservice.start()
disco.start_detection()
pxe.start_proxydhcp()
try:
sockservice = sockapi.SockApi(sock_bind_host, sock_bind_port)
sockservice.start()