def main(): global options # bail out if we are not running Linux if platform.system() != 'Linux': print( 'Non Linux database hosts are not supported at the moment. Can not continue' ) sys.exit(243) options, args = parse_args() consts.TICK_LENGTH = options.tick output_method = options.output_method if not output_method_is_valid(output_method): print('Unsupported output method: {0}'.format(output_method)) print('Valid output methods are: {0}'.format(','.join( get_valid_output_methods()))) sys.exit(1) if output_method == OUTPUT_METHOD.curses and not curses_available: print( 'Curses output is selected, but curses are unavailable, falling back to console output' ) output_method = OUTPUT_METHOD.console log_stderr = setup_loggers(options) user_dbname = options.instance user_dbver = options.version clusters = [] # now try to read the configuration file config = (read_configuration(options.config_file) if options.config_file else None) if config: for instance in config: if user_dbname and instance != user_dbname: continue # pass already aquired connections to make sure we only list unique clusters. db_client = DBClient.from_config(config[instance]) try: cluster = db_client.establish_user_defined_connection( instance, clusters) except (NotConnectedError, NoPidConnectionError): msg = 'failed to acquire details about the database cluster {0}, the server will be skipped' loggers.logger.error(msg.format(instance)) except DuplicatedConnectionError: pass else: clusters.append(cluster) elif options.host: # try to connect to the database specified by command-line options instance = options.instance or "default" db_client = DBClient.from_options(options) try: cluster = db_client.establish_user_defined_connection( instance, clusters) except (NotConnectedError, NoPidConnectionError): loggers.logger.error( "unable to continue with cluster {0}".format(instance)) except DuplicatedConnectionError: pass else: clusters.append(cluster) else: # do autodetection postmasters = ProcWorker().get_postmasters_directories() # get all PostgreSQL instances for result_work_dir, connection_params in postmasters.items(): # if user requested a specific database name and version - don't try to connect to others try: validate_autodetected_conn_param(user_dbname, user_dbver, result_work_dir, connection_params) except InvalidConnectionParamError: continue db_client = DBClient.from_postmasters(result_work_dir, connection_params.pid, connection_params.version, options) if db_client is None: continue conn = db_client.connection_builder.build_connection() try: pgcon = psycopg2.connect(**conn) except Exception as e: loggers.logger.error('PostgreSQL exception {0}'.format(e)) pgcon = None if pgcon: desc = make_cluster_desc(name=connection_params.dbname, version=connection_params.version, workdir=result_work_dir, pid=connection_params.pid, pgcon=pgcon, conn=conn) clusters.append(desc) collectors = [] groups = {} try: if not clusters: loggers.logger.error( 'No suitable PostgreSQL instances detected, exiting...') loggers.logger.error( 'hint: use -v for details, or specify connection parameters ' 'manually in the configuration file (-c)') sys.exit(1) # initialize the disks stat collector process and create an exchange queue q = JoinableQueue(1) work_directories = [cl['wd'] for cl in clusters if 'wd' in cl] collector = DetachedDiskStatCollector(q, work_directories) collector.start() consumer = DiskCollectorConsumer(q) collectors.append(HostStatCollector()) collectors.append(SystemStatCollector()) collectors.append(MemoryStatCollector()) for cluster in clusters: partition_collector = PartitionStatCollector.from_cluster( cluster, consumer) pg_collector = PgStatCollector.from_cluster(cluster, options.pid) groups[cluster['wd']] = { 'pg': pg_collector, 'partitions': partition_collector } collectors.append(partition_collector) collectors.append(pg_collector) # we don't want to mix diagnostics messages with useful output, so we log the former into a file. loggers.logger.removeHandler(log_stderr) loop(collectors, consumer, groups, output_method) loggers.logger.addHandler(log_stderr) except KeyboardInterrupt: pass except curses.error: print(traceback.format_exc()) if 'SSH_CLIENT' in os.environ and 'SSH_TTY' not in os.environ: print( 'Unable to initialize curses. Make sure you supply -t option (force psedo-tty allocation) to ssh' ) except: print(traceback.format_exc()) finally: sys.exit(0)
def test_validate_autodetected_conn_param_should_raise_invalid_param_when_no_result_work_dir(self): conn_parameters = connection_params(pid=1049, version=9.3, dbname='/var/lib/postgresql/9.3/main') with self.assertRaises(InvalidConnectionParamError): validate_autodetected_conn_param('/var/lib/postgresql/9.3/main', 9.3, '', conn_parameters)
def test_validate_autodetected_conn_param_should_raise_invalid_param_when_different_versions(self): conn_parameters = connection_params(pid=2, version=9.3, dbname='/var/lib/postgresql/9.3/main') with self.assertRaises(InvalidConnectionParamError): validate_autodetected_conn_param( '/var/lib/postgresql/9.3/main', 9.5, '/var/run/postgresql', conn_parameters)
def test_validate_autodetected_conn_param_should_return_none_when_no_user_dbname(self): self.assertIsNone(validate_autodetected_conn_param(None, '9.3', '/var/run/postgresql', {}))