Esempio n. 1
0
 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
Esempio n. 2
0
File: tftp.py Progetto: icb-/PyPXE
 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
Esempio n. 3
0
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')