diff --git a/README.md b/README.md index 1c8a816..b969ac8 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ The following are arguments that can be passed to `pypxe.server` when running fr |__`--no-http`__|Disable built-in HTTP server|`True`| |__`--dhcp`__|Enable built-in DHCP server|`False`| |__`--dhcp-proxy`__|Enable built-in DHCP server in proxy mode (implies `--dhcp`)|`False`| -|__`--no-dhcp`__|Disable built-in DHCP server|`True`| |__`--tftp`__|Enable built-in TFTP server which is enabled by default|`True`| |__`--no-tftp`__|Disable built-in TFTP server which is enabled by default|`False`| |__`--debug`__|Enable selected services in DEBUG mode; services are selected by passing the name in a comma separated list. **Options are: http, tftp and dhcp**; one can also prefix an option with `-` to prevent debugging of that service; for example, the following will enable debugging for all services _except_ the DHCP service `--debug all,-dhcp`. _This mode adds a level of verbosity so that you can see what's happening in the background._|`''`| diff --git a/example_cfg.json b/example_cfg.json index f006c20..12c1451 100644 --- a/example_cfg.json +++ b/example_cfg.json @@ -1,27 +1,32 @@ -{ "NETBOOT_DIR" : "netboot", - "NETBOOT_FILE" : "", - "DHCP_SERVER_IP" : "192.168.2.2", - "DHCP_SERVER_PORT" : 67, - "DHCP_OFFER_BEGIN" : "192.168.2.100", - "DHCP_OFFER_END" : "192.168.2.150", - "DHCP_SUBNET" : "255.255.255.0", - "DHCP_ROUTER" : "192.168.2.1", - "DHCP_DNS" : "8.8.8.8", - "DHCP_BROADCAST" : "", - "DHCP_FILESERVER" : "192.168.2.2", - "SYSLOG_SERVER" : null, - "SYSLOG_PORT" : 514, - "USE_IPXE" : false, - "USE_HTTP" : false, - "USE_TFTP" : true, - "USE_DHCP" : true, - "DHCP_MODE_PROXY" : false, - "NBD_BLOCK_DEVICE" : "", - "NBD_WRITE" : false, - "NBD_COW" : true, - "NBD_COW_IN_MEM" : false, - "NBD_COPY_TO_RAM" : false, - "NBD_SERVER_IP" : "0.0.0.0", - "NBD_SERVER_PORT" : 10809, - "MODE_DEBUG" : "", - "MODE_VERBOSE" : "" } +{ + "DHCP_BROADCAST": "", + "DHCP_DNS": "8.8.8.8", + "DHCP_FILESERVER": "192.168.2.2", + "DHCP_MODE_PROXY": false, + "DHCP_OFFER_BEGIN": "192.168.2.100", + "DHCP_OFFER_END": "192.168.2.150", + "DHCP_ROUTER": "192.168.2.1", + "DHCP_SERVER_IP": "192.168.2.2", + "DHCP_SERVER_PORT": 67, + "DHCP_SUBNET": "255.255.255.0", + "DHCP_WHITELIST": false, + "LEASES_FILE": "", + "MODE_DEBUG": "", + "MODE_VERBOSE": "", + "NBD_BLOCK_DEVICE": "", + "NBD_COPY_TO_RAM": false, + "NBD_COW": true, + "NBD_COW_IN_MEM": false, + "NBD_PORT": 10809, + "NBD_SERVER_IP": "0.0.0.0", + "NBD_WRITE": false, + "NETBOOT_DIR": "netboot", + "NETBOOT_FILE": "", + "STATIC_CONFIG": "", + "SYSLOG_PORT": 514, + "SYSLOG_SERVER": null, + "USE_DHCP": true, + "USE_HTTP": false, + "USE_IPXE": false, + "USE_TFTP": true +} diff --git a/pypxe/server.py b/pypxe/server.py index 4c2b258..f72b4a3 100755 --- a/pypxe/server.py +++ b/pypxe/server.py @@ -30,12 +30,15 @@ 'DHCP_ROUTER':'192.168.2.1', 'DHCP_BROADCAST':'', 'DHCP_FILESERVER':'192.168.2.2', + 'DHCP_WHITELIST':False, + 'LEASES_FILE':'', + 'STATIC_CONFIG':'', 'SYSLOG_SERVER':None, 'SYSLOG_PORT':514, 'USE_IPXE':False, 'USE_HTTP':False, 'USE_TFTP':True, - 'USE_DHCP':True, + 'USE_DHCP':False, 'DHCP_MODE_PROXY':False, 'NBD_BLOCK_DEVICE':'', 'NBD_WRITE':False, @@ -66,8 +69,10 @@ def parse_cli_arguments(): parser.add_argument('--debug', action = 'store', dest = 'MODE_DEBUG', help = 'Comma Seperated (http,tftp,dhcp). Adds verbosity to the selected services while they run. Use \'all\' for enabling debug on all services. Precede an option with \'-\' to disable debugging for that service; as an example, one can pass in the following to enable debugging for all services except the DHCP service: \'--debug all,-dhcp\'', default = SETTINGS['MODE_DEBUG']) parser.add_argument('--verbose', action = 'store', dest = 'MODE_VERBOSE', help = 'Comma Seperated (http,tftp,dhcp). Adds verbosity to the selected services while they run. Less verbose than \'debug\'. Use \'all\' for enabling verbosity on all services. Precede an option with \'-\' to disable debugging for that service; as an example, one can pass in the following to enable debugging for all services except the DHCP service: \'--debug all,-dhcp\'', default = SETTINGS['MODE_VERBOSE']) parser.add_argument('--config', action = 'store', dest = 'JSON_CONFIG', help = 'Configure from a JSON file rather than the command line', default = '') - parser.add_argument('--static-config', action = 'store', dest = 'STATIC_CONFIG', help = 'Configure leases from a json file rather than the command line', default = '') - parser.add_argument('--save-leases', action = 'store', dest = 'LEASES_FILE', help = 'Save all DHCP leases on exit or SIGHUP. Will load from this file on start', default = '') + parser.add_argument('--dump-config', action = 'store_true', dest = 'DUMP_CONFIG', help = 'Dump the default configuration as a valid input file') + parser.add_argument('--dump-config-merged', action = 'store_true', dest = 'DUMP_CONFIG_MERGED', help = 'Like --dump-config, but also merge in CLI options') + parser.add_argument('--static-config', action = 'store', dest = 'STATIC_CONFIG', help = 'Configure leases from a json file rather than the command line', default = SETTINGS['STATIC_CONFIG']) + parser.add_argument('--save-leases', action = 'store', dest = 'LEASES_FILE', help = 'Save all DHCP leases on exit or SIGHUP. Will load from this file on start', default = SETTINGS['LEASES_FILE']) parser.add_argument('--syslog', action = 'store', dest = 'SYSLOG_SERVER', help = 'Syslog server', default = SETTINGS['SYSLOG_SERVER']) parser.add_argument('--syslog-port', action = 'store', dest = 'SYSLOG_PORT', help = 'Syslog server port', default = SETTINGS['SYSLOG_PORT']) @@ -75,7 +80,6 @@ def parse_cli_arguments(): # DHCP server arguments dhcp_group = parser.add_argument_group(title = 'DHCP', description = 'Arguments relevant to the DHCP server') exclusive = dhcp_group.add_mutually_exclusive_group(required = False) - exclusive.add_argument('--no-dhcp', action = 'store_false', dest = 'USE_DHCP', help = 'Disable built-in DHCP server', default = not SETTINGS['USE_DHCP']) exclusive.add_argument('--dhcp', action = 'store_true', dest = 'USE_DHCP', help = 'Enable built-in DHCP server', default = SETTINGS['USE_DHCP']) exclusive.add_argument('--dhcp-proxy', action = 'store_true', dest = 'DHCP_MODE_PROXY', help = 'Enable built-in DHCP server in proxy mode (implies --dhcp)', default = SETTINGS['DHCP_MODE_PROXY']) @@ -88,7 +92,7 @@ def parse_cli_arguments(): dhcp_group.add_argument('--dhcp-dns', action = 'store', dest = 'DHCP_DNS', help = 'DHCP lease DNS server', default = SETTINGS['DHCP_DNS']) dhcp_group.add_argument('--dhcp-broadcast', action = 'store', dest = 'DHCP_BROADCAST', help = 'DHCP broadcast address', default = SETTINGS['DHCP_BROADCAST']) dhcp_group.add_argument('--dhcp-fileserver', action = 'store', dest = 'DHCP_FILESERVER', help = 'DHCP fileserver IP', default = SETTINGS['DHCP_FILESERVER']) - dhcp_group.add_argument('--dhcp-whitelist', action = 'store_true', dest = 'DHCP_WHITELIST', help = 'Only respond to DHCP clients present in --static-config', default = False) + dhcp_group.add_argument('--dhcp-whitelist', action = 'store_true', dest = 'DHCP_WHITELIST', help = 'Only respond to DHCP clients present in --static-config', default = SETTINGS['DHCP_WHITELIST']) # network boot directory and file name arguments parser.add_argument('--netboot-dir', action = 'store', dest = 'NETBOOT_DIR', help = 'Local file serve directory', default = SETTINGS['NETBOOT_DIR']) @@ -119,12 +123,20 @@ def do_verbose(service): def main(): global SETTINGS, args try: - # warn the user that they are starting PyPXE as non-root user - if os.getuid() != 0: - print '\nWARNING: Not root. Servers will probably fail to bind.\n' - # 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'] + print json.dumps(SETTINGS, sort_keys=True, indent=4) + sys.exit() + if args.JSON_CONFIG: # load from configuration file if specified try: config_file = open(args.JSON_CONFIG, 'rb') @@ -141,6 +153,11 @@ def main(): 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: @@ -286,7 +303,7 @@ def main(): sys_logger.info('PyPXE successfully initialized and running!') - while map(lambda x: x.isAlive(), running_services): + while all(map(lambda x: x.isAlive(), running_services)): sleep(1) except KeyboardInterrupt: diff --git a/setup.py b/setup.py index 40a3775..0af3827 100755 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ deps.append('argparse') setup(name='PyPXE', - version='1.7', + version='1.7.1', description='Pure Python2 PXE (DHCP-(Proxy)/TFTP/HTTP/NBD) Server', url='https://github.com/psychomario/PyPXE', license='MIT',