mirror of
				https://github.com/xcat2/confluent.git
				synced 2025-10-31 03:12:31 +00:00 
			
		
		
		
	Fix ipv6 netboot support to get to request
A number of mistakes were in netutil and the advertise needed to be complete and transmitted.
This commit is contained in:
		| @@ -38,6 +38,7 @@ import netifaces | ||||
| import struct | ||||
| import time | ||||
| import traceback | ||||
| import uuid | ||||
|  | ||||
| libc = ctypes.CDLL(ctypes.util.find_library('c')) | ||||
|  | ||||
| @@ -529,19 +530,87 @@ def check_reply(node, info, packet, sock, cfg, reqview, addr): | ||||
|         if not httpboot: | ||||
|             log.log({'info': 'IPv6 PXE boot attempt by {0}, but IPv6 PXE is not supported, try IPv6 HTTP boot or IPv4 boot'.format(node)}) | ||||
|             return | ||||
|         return reply_dhcp6(node, addr, cfg) | ||||
|         return reply_dhcp6(node, addr, cfg, packet, cfd, profile, sock) | ||||
|     else: | ||||
|         return reply_dhcp4(node, info, packet, cfg, reqview, httpboot, cfd, profile) | ||||
|  | ||||
| def reply_dhcp6(node, addr, cfg): | ||||
| def reply_dhcp6(node, addr, cfg, packet, cfd, profile, sock): | ||||
|     myaddrs = netutil.get_my_addresses(addr[-1], socket.AF_INET6) | ||||
|     if not myaddrs: | ||||
|         log.log({'info': 'Unable to provide IPv6 boot services to {0} , no viable IPv6 configuration on interface index "{1}" to respond through.'.format(node, addr[-1])}) | ||||
|         log.log({'info': 'Unable to provide IPv6 boot services to {0}, no viable IPv6 configuration on interface index "{1}" to respond through.'.format(node, addr[-1])}) | ||||
|         return | ||||
|     niccfg = netutil.get_nic_config(cfg, node, ifidx=addr[-1]) | ||||
|     ipv6addr = niccfg.get('ipv6_address', None) | ||||
|     ipv6prefix = niccfg.get('ipv6_prefix', None) | ||||
|     ipv6method = niccfg.get('ipv6_method', 'static') | ||||
|     ipv6srvaddr = niccfg.get('deploy_server_v6', None) | ||||
|     if not ipv6srvaddr: | ||||
|         log.log({'info': 'Unable to determine an appropriate ipv6 server ip for {}'.format(node)}) | ||||
|         return | ||||
|     insecuremode = cfd.get(node, {}).get('deployment.useinsecureprotocols', | ||||
|         {}).get('value', 'never') | ||||
|     if not insecuremode: | ||||
|         insecuremode = 'never' | ||||
|     proto = 'https' if insecuremode == 'never' else 'http' | ||||
|     bootfile = '{0}://[{1}]/confluent-public/os/{2}/boot.img'.format( | ||||
|         proto, ipv6srvaddr, profile | ||||
|     ) | ||||
|     if not isinstance(bootfile, bytes): | ||||
|         bootfile = bootfile.encode('utf8') | ||||
|     ipass = [] | ||||
|     if ipv6method not in ('dhcp', 'firmwaredhcp') and ipv6addr: | ||||
|         if not ipv6prefix: | ||||
|             log.log({'info': 'Unable to determine prefix to serve to address {} for node {}'.format(ipv6addr, node)}) | ||||
|             return | ||||
|         ipass = bytearray(40) | ||||
|         ipass[:4] = packet[3][:4]  # pass iaid back | ||||
|         ipass[4:16] = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x18' | ||||
|         ipass[16:32] = socket.inet_pton(socket.AF_INET6, ipv6addr) | ||||
|         ipass[32:40] = b'\x00\x00\x00\x78\x00\x00\x01\x2c' | ||||
|     #1 msgtype | ||||
|     #3 txid | ||||
|     #22 - server ident | ||||
|     #len(packet[1]) + 4 - client ident | ||||
|     #len(ipass) + 4 or 0 | ||||
|     #len(url) + 4 | ||||
|     replylen = 50 + len(bootfile) + len(packet[1]) + 4 | ||||
|     if len(ipass): | ||||
|         replylen += len(ipass) | ||||
|     reply = bytearray(replylen) | ||||
|     reply[0] = 2 | ||||
|     reply[1:4] = packet['txid'] | ||||
|     offset = 4 | ||||
|     struct.pack_into('!HH', reply, offset, 1, len(packet[1])) | ||||
|     offset += 4 | ||||
|     reply[offset:offset+len(packet[1])] = packet[1] | ||||
|     offset += len(packet[1]) | ||||
|     struct.pack_into('!HHH', reply, offset, 2, 18, 4) | ||||
|     offset += 6 | ||||
|     reply[offset:offset+16] = get_my_duid() | ||||
|     offset += 16 | ||||
|     if ipass: | ||||
|         struct.pack_into('!HH', reply, offset, 3, len(ipass)) | ||||
|         offset += 4 | ||||
|         reply[offset:offset + len(ipass)] = ipass | ||||
|         offset += len(ipass) | ||||
|     struct.pack_into('!HH', reply, offset, 59, len(bootfile)) | ||||
|     offset += 4 | ||||
|     reply[offset:offset + len(bootfile)] = bootfile | ||||
|     offset += len(bootfile) | ||||
|     # Need the HTTPClient in the vendor class for reply | ||||
|     struct.pack_into('!HHIH', reply, offset, 16, 16, 0, 10) | ||||
|     offset += 10 | ||||
|     reply[offset:offset + 10] = b'HTTPClient' | ||||
|     sock.sendto(reply, addr) | ||||
|  | ||||
|  | ||||
| _myuuid = None | ||||
| def get_my_duid(): | ||||
|     global _myuuid | ||||
|     if not _myuuid: | ||||
|         _myuuid = uuid.uuid4().bytes | ||||
|     return _myuuid | ||||
|  | ||||
|     print(repr(addr)) | ||||
|     pass | ||||
|  | ||||
| def reply_dhcp4(node, info, packet, cfg, reqview, httpboot, cfd, profile): | ||||
|     replen = 275  # default is going to be 286 | ||||
|   | ||||
| @@ -226,10 +226,13 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, | ||||
|     ipbynodename = None | ||||
|     ip6bynodename = None | ||||
|     try: | ||||
|         for addr in socket.getaddrinfo(node, 0, 0, socket.SOCK_DGRAM): | ||||
|             if addr[0] == socket.AF_INET: | ||||
|                 ipbynodename = addr[-1][0] | ||||
|             elif addr[0] == socket.AF_INET6: | ||||
|         for addr in socket.getaddrinfo(node, 0, socket.AF_INET, socket.SOCK_DGRAM): | ||||
|             ipbynodename = addr[-1][0] | ||||
|          | ||||
|     except socket.gaierror: | ||||
|         pass | ||||
|     try: | ||||
|         for addr in socket.getaddrinfo(node, 0, socket.AF_INET6, socket.SOCK_DGRAM): | ||||
|                 ip6bynodename = addr[-1][0] | ||||
|     except socket.gaierror: | ||||
|         pass | ||||
| @@ -270,7 +273,7 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, | ||||
|                             if nver == '4': | ||||
|                                 cfgdata['prefix'] = prefix | ||||
|                             else: | ||||
|                                 cfgdata['prefix_v{}'.format(nver)] = prefix | ||||
|                                 cfgdata['ipv{}_prefix'.format(nver)] = prefix | ||||
|                             if candip in (ipbynodename, ip6bynodename): | ||||
|                                 cfgdata['matchesnodename'] = True | ||||
|                             return cfgdata | ||||
| @@ -297,6 +300,8 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, | ||||
|             else: | ||||
|                 bynodename = ip6bynodename | ||||
|                 nver = '6' | ||||
|             if not bynodename:  # node is missing either ipv6 or ipv4, ignore | ||||
|                 continue | ||||
|             ipbynodenamn = socket.inet_pton(fam, bynodename) | ||||
|             if ipn_on_same_subnet(fam, svrip, ipbynodenamn, prefix): | ||||
|                 cfgdata['matchesnodename'] = True | ||||
| @@ -305,13 +310,15 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, | ||||
|                 if nver == '4': | ||||
|                     cfgdata['prefix'] = prefix | ||||
|                 else: | ||||
|                     cfgdata['prefix_v6'] = prefix | ||||
|                     cfgdata['ipv{}_prefix'.format(nver)] = prefix | ||||
|         for svr in candsrvs: | ||||
|             fam, svr, prefix = svr | ||||
|             if fam == socket.AF_INET: | ||||
|                 bynodename = ipbynodename | ||||
|             elif fam == socket.AF_INET6: | ||||
|                 bynodename = ip6bynodename | ||||
|             if not bynodename: | ||||
|                 continue  # ignore undefined family | ||||
|             bynodenamn = socket.inet_pton(fam, bynodename) | ||||
|             if ipn_on_same_subnet(fam, svr, bynodenamn, prefix): | ||||
|                 svrname = socket.inet_ntop(fam, svr) | ||||
| @@ -338,8 +345,8 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, | ||||
|                 cfgdata['prefix'] = prefix | ||||
|                 nver = '4' | ||||
|             else: | ||||
|                 cfgdata['prefix_v6'] = prefix | ||||
|                 nver = '6' | ||||
|                 cfgdata['ipv{}_prefix'.format(nver)] = prefix | ||||
|             for setting in nodenetattribs: | ||||
|                 if 'ipv{}_gateway'.format(nver) not in setting: | ||||
|                     continue | ||||
|   | ||||
		Reference in New Issue
	
	Block a user