def validate_host_port(host_port, listen=False, multiple_hosts=False): try: hosts, port = split_host_port(host_port, None) except (ValueError, TypeError): raise ConfigParseError("contains a wrong value") else: if multiple_hosts: hosts = hosts.split(",") else: hosts = [hosts] for host in hosts: proto = socket.getaddrinfo(host, "", 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) s = socket.socket(proto[0][0], socket.SOCK_STREAM) try: if s.connect_ex((host, port)) == 0: if listen: raise ConfigParseError( "Port {} is already in use.".format(port)) elif not listen: raise ConfigParseError( "{} is not reachable".format(host_port)) except socket.gaierror as e: raise ConfigParseError(e) finally: s.close() return True
def validate_connect_address(address): try: host, _ = split_host_port(address, 1) except (AttributeError, TypeError, ValueError): raise ConfigParseError("contains a wrong value") if host in ["127.0.0.1", "0.0.0.0", "*", "::1", "localhost"]: raise ConfigParseError( 'must not contain "127.0.0.1", "0.0.0.0", "*", "::1", "localhost"') return True
def __init__(self, configfile, validator=default_validator): self._modify_index = -1 self._dynamic_configuration = {} self.__environment_configuration = self._build_environment_configuration( ) # Patroni reads the configuration from the command-line argument if it exists, otherwise from the environment self._config_file = configfile and os.path.isfile( configfile) and configfile if self._config_file: self._local_configuration = self._load_config_file() else: config_env = os.environ.pop(self.PATRONI_CONFIG_VARIABLE, None) self._local_configuration = config_env and yaml.safe_load( config_env) or self.__environment_configuration if validator: error = validator(self._local_configuration) if error: raise ConfigParseError(error) self.__effective_configuration = self._build_effective_configuration( {}, self._local_configuration) self._data_dir = self.__effective_configuration.get('postgresql', {}).get( 'data_dir', "") self._cache_file = os.path.join(self._data_dir, self.__CACHE_FILENAME) self._load_cache() self._cache_needs_saving = False
def validate_data_dir(data_dir): if not data_dir: raise ConfigParseError("is an empty string") elif os.path.exists(data_dir) and not os.path.isdir(data_dir): raise ConfigParseError("is not a directory") elif not data_directory_empty(data_dir): if not os.path.exists(os.path.join(data_dir, "PG_VERSION")): raise ConfigParseError("doesn't look like a valid data directory") else: with open(os.path.join(data_dir, "PG_VERSION"), "r") as version: pgversion = version.read().strip() waldir = ("pg_wal" if float(pgversion) >= 10 else "pg_xlog") if not os.path.isdir(os.path.join(data_dir, waldir)): raise ConfigParseError( "data dir for the cluster is not empty, but doesn't contain" " \"{}\" directory".format(waldir)) bin_dir = schema.data.get("postgresql", {}).get("bin_dir", None) major_version = get_major_version(bin_dir) if pgversion != major_version: raise ConfigParseError( "data_dir directory postgresql version ({}) doesn't match" "with 'postgres --version' output ({})".format( pgversion, major_version)) return True
def _load_config_path(self, path): """ If path is a file, loads the yml file pointed to by path. If path is a directory, loads all yml files in that directory in alphabetical order """ if os.path.isfile(path): files = [path] elif os.path.isdir(path): files = [os.path.join(path, f) for f in sorted(os.listdir(path)) if (f.endswith('.yml') or f.endswith('.yaml')) and os.path.isfile(os.path.join(path, f))] else: logger.error('config path %s is neither directory nor file', path) raise ConfigParseError('invalid config path') overall_config = {} for fname in files: with open(fname) as f: config = yaml.safe_load(f) patch_config(overall_config, config) return overall_config
def is_ipv6_address(ip): try: socket.inet_pton(socket.AF_INET6, ip) except Exception: raise ConfigParseError("Is not a valid ipv6 address") return True
def is_ipv4_address(ip): try: socket.inet_aton(ip) except Exception: raise ConfigParseError("Is not a valid ipv4 address") return True