def __init__(self, mainsock, parent): self.default_retries = parent.default_retries self.timeout = parent.timeout self.ip = parent.ip self.message, self.address = mainsock.recvfrom(1024) self.logger = helpers.get_child_logger(parent.logger, 'Client.{0}'.format(self.address)) self.netboot_directory = parent.netboot_directory self.logger.debug('Receiving request...') self.retries = self.default_retries self.block = 1 self.blksize = 512 self.sent_time = float('inf') self.dead = False self.fh = None self.filename = '' self.wrap = 0 self.arm_wrap = False self.handle() # message from the main socket
def __init__(self, mainsock, parent): self.default_retries = parent.default_retries self.timeout = parent.timeout self.ip = parent.ip self.message, self.address = mainsock.recvfrom(1024) self.logger = helpers.get_child_logger(parent.logger, 'Client.{0}'.format(self.address)) self.netboot_directory = parent.netboot_directory self.logger.debug('Recieving request...') self.retries = self.default_retries self.block = 1 self.blksize = 512 self.sent_time = float('inf') self.dead = False self.fh = None self.filename = '' self.wrap = 0 self.arm_wrap = False self.handle() # message from the main socket
def main(): global SETTINGS, args try: # configure args = parse_cli_arguments() if args.DUMP_CONFIG or args.DUMP_CONFIG_MERGED: if args.DUMP_CONFIG: settings = SETTINGS else: # some arguments don't make sense to print settings = args.__dict__ del settings['DUMP_CONFIG'] del settings['DUMP_CONFIG_MERGED'] del settings['JSON_CONFIG'] print(json.dumps(settings, sort_keys=True, indent=4)) sys.exit() if args.JSON_CONFIG: # load from configuration file if specified try: config_file = io.open(args.JSON_CONFIG, 'r') except IOError: sys.exit('Failed to open {0}'.format(args.JSON_CONFIG)) try: loaded_config = json.load(config_file) config_file.close() except ValueError: sys.exit('{0} does not contain valid JSON'.format(args.JSON_CONFIG)) for setting in loaded_config: if type(loaded_config[setting]) is unicode: loaded_config[setting] = loaded_config[setting].encode('ascii') SETTINGS.update(loaded_config) # update settings with JSON config args = parse_cli_arguments() # re-parse, CLI options take precedence # warn the user that they are starting PyPXE as non-root user if os.getuid() != 0: print(sys.stderr, '\nWARNING: Not root. Servers will probably fail to bind.\n') # ideally this would be in dhcp itself, but the chroot below *probably* # breaks the ability to open the config file. if args.STATIC_CONFIG: try: static_config = io.open(args.STATIC_CONFIG, 'r') except IOError: sys.exit("Failed to open {0}".format(args.STATIC_CONFIG)) try: loaded_statics = json.load(static_config) static_config.close() except ValueError: sys.exit("{0} does not contain valid json".format(args.STATIC_CONFIG)) else: loaded_statics = dict() # setup main logger sys_logger = logging.getLogger('PyPXE') if args.SYSLOG_SERVER: handler = logging.handlers.SysLogHandler(address = (args.SYSLOG_SERVER, int(args.SYSLOG_PORT))) else: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s %(message)s') handler.setFormatter(formatter) sys_logger.addHandler(handler) sys_logger.setLevel(logging.INFO) # pass warning to user regarding starting HTTP server without iPXE if args.USE_HTTP and not args.USE_IPXE and not args.USE_DHCP: sys_logger.warning('HTTP selected but iPXE disabled. PXE ROM must support HTTP requests.') # if the argument was pased to enabled ProxyDHCP then enable the DHCP server if args.DHCP_MODE_PROXY: args.USE_DHCP = True # if the network boot file name was not specified in the argument, # set it based on what services were enabled/disabled if args.NETBOOT_FILE == '': if not args.USE_IPXE: args.NETBOOT_FILE = 'pxelinux.0' elif not args.USE_HTTP: args.NETBOOT_FILE = 'boot.ipxe' else: args.NETBOOT_FILE = 'boot.http.ipxe' if args.NBD_WRITE and not args.NBD_COW: sys_logger.warning('NBD Write enabled but copy-on-write is not. Multiple clients may cause corruption') if args.NBD_COW_IN_MEM or args.NBD_COPY_TO_RAM: sys_logger.warning('NBD cowinmem and copytoram can cause high RAM usage') if args.NBD_COW and not args.NBD_WRITE: # cow implies write args.NBD_WRITE = True # make a list of running threads for each service running_services = [] # configure/start TFTP server if args.USE_TFTP: # setup TFTP logger tftp_logger = helpers.get_child_logger(sys_logger, 'TFTP') sys_logger.info('Starting TFTP server...') # setup the thread tftp_server = tftp.TFTPD( mode_debug = do_debug('tftp'), mode_verbose = do_verbose('tftp'), logger = tftp_logger, netboot_directory = args.NETBOOT_DIR, ip = args.TFTP_SERVER_IP) tftpd = threading.Thread(target = tftp_server.listen) tftpd.daemon = True tftpd.start() running_services.append(tftpd) # configure/start DHCP server if args.USE_DHCP: # setup DHCP logger dhcp_logger = helpers.get_child_logger(sys_logger, 'DHCP') if args.DHCP_MODE_PROXY: sys_logger.info('Starting DHCP server in ProxyDHCP mode...') else: sys_logger.info('Starting DHCP server...') # setup the thread dhcp_server = dhcp.DHCPD( ip = args.DHCP_SERVER_IP, port = args.DHCP_SERVER_PORT, offer_from = args.DHCP_OFFER_BEGIN, offer_to = args.DHCP_OFFER_END, subnet_mask = args.DHCP_SUBNET, router = args.DHCP_ROUTER, dns_server = args.DHCP_DNS, broadcast = args.DHCP_BROADCAST, file_server = args.DHCP_FILESERVER, file_name = args.NETBOOT_FILE, use_ipxe = args.USE_IPXE, use_http = args.USE_HTTP, mode_proxy = args.DHCP_MODE_PROXY, mode_debug = do_debug('dhcp'), mode_verbose = do_verbose('dhcp'), whitelist = args.DHCP_WHITELIST, static_config = loaded_statics, logger = dhcp_logger, saveleases = args.LEASES_FILE) dhcpd = threading.Thread(target = dhcp_server.listen) dhcpd.daemon = True dhcpd.start() running_services.append(dhcpd) # configure/start HTTP server if args.USE_HTTP: # setup HTTP logger http_logger = helpers.get_child_logger(sys_logger, 'HTTP') sys_logger.info('Starting HTTP server...') # setup the thread http_server = http.HTTPD( mode_debug = do_debug('http'), mode_verbose = do_debug('http'), logger = http_logger, port = args.HTTP_PORT, netboot_directory = args.NETBOOT_DIR) httpd = threading.Thread(target = http_server.listen) httpd.daemon = True httpd.start() running_services.append(httpd) # configure/start NBD server if args.NBD_BLOCK_DEVICE: # setup NBD logger nbd_logger = helpers.get_child_logger(sys_logger, 'NBD') sys_logger.info('Starting NBD server...') nbd_server = nbd.NBD( block_device = args.NBD_BLOCK_DEVICE, write = args.NBD_WRITE, cow = args.NBD_COW, in_mem = args.NBD_COW_IN_MEM, copy_to_ram = args.NBD_COPY_TO_RAM, ip = args.NBD_SERVER_IP, port = args.NBD_PORT, mode_debug = do_debug('nbd'), mode_verbose = do_verbose('nbd'), logger = nbd_logger, netboot_directory = args.NETBOOT_DIR) nbdd = threading.Thread(target = nbd_server.listen) nbdd.daemon = True nbdd.start() running_services.append(nbdd) sys_logger.info('PyPXE successfully initialized and running!') while all(map(lambda x: x.isAlive(), running_services)): sleep(1) except KeyboardInterrupt: sys.exit('\nShutting down PyPXE...\n')