diff --git a/bdisk/host.py b/bdisk/host.py index 54812ad..ff32dc9 100755 --- a/bdisk/host.py +++ b/bdisk/host.py @@ -3,6 +3,7 @@ import sys import platform import re import configparser +import validators from socket import getaddrinfo def getOS(): @@ -45,15 +46,10 @@ def getConfig(conf_file='/etc/bdisk/build.ini'): return(conf) def parseConfig(conf): - # The following are paths; c means create, e means must exist, ? means depends on other opts: - # build:basedir(e),build:archboot(c),build:isodir(c),build:mountpt(c), - # build:srcdir(c),build:tempdir(c),http:path(c?),tftp:path(c?),rsync:path (remote, no op) - # The following are files: ipxe:ssl_ca(e?),ipxe:ssl_cakey(e?),ipxe:ssl_crt(e?),ipxe:key(c) - # The following are URIs: ipxe:uri - # The rest are strings. config = configparser.ConfigParser() config._interpolation = configparser.ExtendedInterpolation() config.read(conf) + # a dict makes this so much easier. config_dict = {s:dict(config.items(s)) for s in config.sections()} # Convert the booleans to pythonic booleans in the dict... config_dict['bdisk']['user'] = config['bdisk'].getboolean('user') @@ -63,13 +59,52 @@ def parseConfig(conf): config_dict['sync'][i] = config['sync'].getboolean(i) config_dict['ipxe']['iso'] = config['ipxe'].getboolean('iso') config_dict['ipxe']['usb'] = config['ipxe'].getboolean('usb') - # Validate the rsync host. Works for IP address too. It does NOT - # check to see if we can actually *rsync* to it; that'll come later. - try: - getaddrinfo(config_dict['rsync']['host'], None) - except: - exit(('ERROR: {0} is not a valid host that can be used for rsyncing.' + - 'Check your configuration.').format(config_dict['rsync']['host'])) + ## VALIDATORS ## + # Are we rsyncing? If so, validate the rsync host. + # Works for IP address too. It does NOT check to see if we can + # actually *rsync* to it; that'll come later. + if config_dict['sync']['rsync']: + if (validators.domain(config_dict['rsync']['host']) or validators.ipv4( + config_dict['rsync']['host']) or validators.ipv6( + config_dict['rsync']['host'])): + try: + getaddrinfo(config_dict['rsync']['host'], None) + except: + exit(('ERROR: {0} does not resolve and cannot be used for rsyncing.' + + 'Check your configuration.').format(config_dict['rsync']['host'])) + else: + exit(('ERROR: {0} is not a valid host and cannot be used for rsyncing.' + + 'Check your configuration.').format(config_dict['rsync']['host'])) # Validate the URI. + if config_dict['sync']['ipxe']: + # so this won't validate e.g. custom LAN domains (https://pxeserver/bdisk.php). TODO. + if not validators.url(config_dict['ipxe']['uri']): + if not re.match('^https?://localhost(/.*)?$'): + exit('ERROR: {0} is not a valid URL/URI. Check your configuration.'.format( + config_dict['ipxe']['uri'])) + # Validate required paths + if not os.path.exists(config_dict['build']['basedir'] + '/extra'): + exit(("ERROR: {0} does not contain BDisk's core files!" + + "Check your configuration.").format(config_dict['build']['basedir'])) + # Make dirs if they don't exist + for d in ('archboot', 'isodir', 'mountpt', 'srcdir', 'tempdir'): + os.makedirs(config_dict['build'][d], exists_ok = True) + # Make dirs for sync staging if we need to + for x in ('http', 'tftp'): + if config_dict['sync'][x]: + os.makedirs(config_dict[x]['path'], exist_ok = True) + # Hoo boy. Now we test paths for SSL in iPXE... + if config_dict['build']['ipxe']: + if config_dict['ipxe']['ssl_crt']: + for x in ('ssl_key', 'ssl_cakey'): + if config_dict['ipxe'][x]: + if not os.path.isfile(config_dict['ipxe'][x]): + exit(('ERROR: {0} is not an existing file. Check your' + + 'configuration.').format(config_dict['ipxe'][x])) + if config_dict['ipxe']['ssl_ca']: + if not os.path.isfile(config_dict['ipxe']['ssl_ca']): + exit(('ERROR: {0} is not an existing file. Check your' + + 'configuration.').format(config_dict['ipxe']['ssl_ca'])) + return(config, config_dict)