Example #1
0
def configure_unified_logger(args):
    ''' If we want to run a single unified logger for the entire test,
    set that up here. Note that these logs will be in addition to those
    created naturally during hypergolix operation (which will live
    within each app's respective hgx_root)
    '''
    from hypergolix import logutils

    if args.logdir:
        logutils.autoconfig(tofile=True,
                            logdirname=args.logdir,
                            loglevel=args.verbosity)
    else:
        logutils.autoconfig(tofile=False, loglevel=args.verbosity)
Example #2
0
def configure_unified_logger(args):
    ''' If we want to run a single unified logger for the entire test,
    set that up here. Note that these logs will be in addition to those
    created naturally during hypergolix operation (which will live
    within each app's respective hgx_root)
    '''
    from hypergolix import logutils
    
    if args.logdir:
        logutils.autoconfig(
            tofile = True,
            logdirname = args.logdir,
            loglevel = args.verbosity
        )
    else:
        logutils.autoconfig(
            tofile = False,
            loglevel = args.verbosity
        )
Example #3
0
        # Test object discarding
        # -----------
        joint2.hgx_discard_threadsafe()
        self.assertFalse(joint2._isalive_3141592)
        self.assertEqual(
            len(self.ipccore._update_listeners.get_any(dispatchable2.ghid)), 
            1
        )
        self.assertFalse(dispatchable2.deleted)
        
        # Test object discarding
        # -----------
        dispatchable1 = self.oracle.objs[obj1.hgx_ghid]
        obj1.hgx_delete_threadsafe()
        self.assertTrue(dispatchable1.deleted)
        self.assertFalse(obj1._isalive_3141592)
        
        # --------------------------------------------------------------------
        # Comment this out if no interactivity desired
            
        # # Start an interactive IPython interpreter with local namespace, but
        # # suppress all IPython-related warnings.
        # with warnings.catch_warnings():
        #     warnings.simplefilter('ignore')
        #     IPython.embed()

if __name__ == "__main__":
    from hypergolix import logutils
    logutils.autoconfig('debug')
    
    unittest.main()
Example #4
0
            )
        )
        # With an unknown author
        with self.assertRaises(InvalidIdentity):
            await_coroutine_threadsafe(
                coro = self.lawyer.validate_garq(req3),
                loop = self.nooploop._loop
            )


class LawyerCoreTest(GenericLawyerTest, unittest.TestCase):
    ''' Test the core lawyer-ness.
    '''
        
    def setUp(self):
        self.librarian = LibrarianCore.__fixture__()
        
        self.lawyer = LawyerCore()
        self.lawyer.assemble(self.librarian)


if __name__ == "__main__":

    from hypergolix import logutils
    logutils.autoconfig(loglevel='debug')
    
    # from hypergolix.utils import TraceLogger
    # with TraceLogger(interval=10):
    #     unittest.main()
    unittest.main()
Example #5
0
                'port': 5358,
                'tls': False,
            },
            debug = True,
            aengel = cls.aengel,
        )
        cls.remote2 = Autocomms(
            autoresponder_class = PersisterBridgeClient,
            connector_class = WSBasicClient,
            connector_kwargs = {
                'host': 'localhost',
                'port': 5358,
                'tls': False,
            },
            debug = True,
            aengel = cls.aengel,
        )
        
    @classmethod
    def tearDownClass(cls):
        cls.aengel.stop()
        

if __name__ == "__main__":
    from hypergolix import logutils
    logutils.autoconfig()
    
    # from hypergolix.utils import TraceLogger
    # with TraceLogger(interval=10):
    #     unittest.main()
    unittest.main()
Example #6
0
                    
                    argv = cmd_str.split()
                    argv.append('--root')
                    argv.append(str(cfg_path))
                    
                    with _NoSTDOUT(), self.assertWarns(DeprecationWarning):
                        ingest_args(argv)
                    
                    config = Config.load(cfg_path)
                    # THE PROBLEM HERE IS NOT JUST COERCE DEFAULTS! config.py,
                    # in its handle_args section, is passing in default values
                    # that are interfering with everything else.
                    self.assertEqual(config, cmd_result)
                
        # Don't need the temp dir for this; un-context to escape permissions
        for cmd_str in failing_commands:
            with self.subTest(cmd_str):
                argv = cmd_str.split()
                argv.append('--root')
                argv.append(str(root))
                # Note that argparse will always push usage to stderr in a
                # suuuuuuper annoying way if we don't suppress it.
                with self.assertRaises(SystemExit), _NoSTDERR(), _NoSTDOUT():
                        ingest_args(argv)


if __name__ == "__main__":
    from hypergolix import logutils
    logutils.autoconfig()
    unittest.main()
Example #7
0
def app_core(user_id, password, startup_logger, aengel=None,
             _scrypt_hardness=None, hgx_root=None, enable_logs=True):
    ''' This is where all of the UX goes for the service itself. From
    here, we build a credential, then a bootstrap, and then persisters,
    IPC, etc.
    
    Expected defaults:
    host:       'localhost'
    port:       7770
    tls:        True
    ipc_port:   7772
    debug:      False
    logfile:    None
    verbosity:  'warning'
    traceur:    False
    '''
    if startup_logger is not None:
        # At some point, this will need to restore the module logger, but for
        # now it really doesn't make any difference whatsoever
        effective_logger = startup_logger
    else:
        effective_logger = logger
    
    with Config(hgx_root) as config:
        # Convert paths to strs
        cache_dir = str(config.cache_dir)
        log_dir = str(config.log_dir)
            
        if user_id is None:
            user_id = config.user_id
        
        debug = config.debug_mode
        verbosity = config.log_verbosity
        ipc_port = config.ipc_port
        remotes = config.remotes
        
    if enable_logs:
        logutils.autoconfig(
            tofile = True,
            logdirname = log_dir,
            loglevel = verbosity,
            logname = 'hgxapp'
        )
    
    if not aengel:
        aengel = Aengel()
    
    core = AgentBootstrap(aengel=aengel, debug=debug, cache_dir=cache_dir)
    core.assemble()
    
    # In this case, we have no existing user_id.
    if user_id is None:
        user_id = core.bootstrap_zero(
            password = password,
            _scrypt_hardness = _scrypt_hardness
        )
        effective_logger.critical(
            'Identity created. Your user ID is ' + str(user_id) + '. You ' +
            'will need your user ID to log in to Hypergolix from another ' +
            'machine, or if your Hypergolix configuration file is corrupted ' +
            'or lost.'
        )
        with Config(hgx_root) as config:
            config.fingerprint = core.whoami
            config.user_id = user_id
        
    # Hey look, we have an existing user.
    else:
        core.bootstrap(
            user_id = user_id,
            password = password,
            _scrypt_hardness = _scrypt_hardness,
        )
        effective_logger.info('Login successful.')
        
    # Add all of the remotes to a namespace preserver
    persisters = []
    for remote in remotes:
        try:
            persister = Autocomms(
                autoresponder_name = 'remrecli',
                autoresponder_class = PersisterBridgeClient,
                connector_name = 'remwscli',
                connector_class = WSBasicClient,
                connector_kwargs = {
                    'host': remote.host,
                    'port': remote.port,
                    'tls': remote.tls,
                },
                debug = debug,
                aengel = aengel,
            )
            
        except CancelledError:
            effective_logger.error(
                'Error while connecting to upstream remote at ' +
                remote.host + ':' + str(remote.port) + '. Connection will ' +
                'only be reattempted after restarting Hypergolix.'
            )
            
        else:
            core.salmonator.add_upstream_remote(persister)
            persisters.append(persister)
        
    # Finally, add the ipc system
    core.ipccore.add_ipc_server(
        'wslocal',
        WSBasicServer,
        host = 'localhost',
        port = ipc_port,
        tls = False,
        debug = debug,
        aengel = aengel,
        threaded = True,
        thread_name = _generate_threadnames('ipc-ws')[0],
    )
        
    return persisters, core, aengel
Example #8
0
def start(namespace=None):
    ''' Starts a Hypergolix daemon.
    '''
    # Command args coming in.
    if namespace is not None:
        host = namespace.host
        port = namespace.port
        debug = namespace.debug
        traceur = namespace.traceur
        chdir = namespace.chdir
        # Convert log dir to absolute if defined
        if namespace.logdir is not None:
            log_dir = str(pathlib.Path(namespace.logdir).absolute())
        else:
            log_dir = namespace.log_dir
        # Convert cache dir to absolute if defined
        if namespace.cachedir is not None:
            cache_dir = str(pathlib.Path(namespace.cachedir).absolute())
        else:
            cache_dir = namespace.cache_dir
        verbosity = namespace.verbosity
        # Convert pid path to absolute (must be defined)
        pid_path = str(pathlib.Path(namespace.pidfile).absolute())

    # Daemonizing, we still need these to be defined to avoid NameErrors
    else:
        host = None
        port = None
        debug = None
        traceur = None
        chdir = None
        log_dir = None
        cache_dir = None
        verbosity = None
        pid_path = None

    with Daemonizer() as (is_setup, daemonizer):
        # Daemonize. Don't strip cmd-line arguments, or we won't know to
        # continue with startup
        (
            is_parent, host, port, debug, traceur, log_dir, cache_dir,
            verbosity, pid_path
        ) = daemonizer(
            pid_path,
            host,
            port,
            debug,
            traceur,
            log_dir,
            cache_dir,
            verbosity,
            pid_path,
            chdir=chdir,
            # Don't strip these, because otherwise we won't know to resume
            # daemonization
            strip_cmd_args=False)

        if not is_parent:
            # Do signal handling within the Daemonizer so that the parent knows
            # it was correctly init'd
            sighandler = SignalHandler1(pid_path)
            sighandler.start()

        #####################
        # PARENT EXITS HERE #
        #####################

    verbosity = _cast_verbosity(verbosity, debug, traceur)

    if log_dir is not None:
        logutils.autoconfig(tofile=True,
                            logdirname=log_dir,
                            logname='hgxremote',
                            loglevel=verbosity)

    logger.debug('Starting remote persistence server...')
    host = _cast_host(host)
    remote, server = _hgx_server(host, port, cache_dir, debug, traceur)
    logger.info('Remote persistence server successfully started.')

    # Wait indefinitely until signal caught.
    # TODO: literally anything smarter than this.
    try:
        while True:
            time.sleep(.5)
    except SIGTERM:
        logger.info('Caught SIGTERM. Exiting.')

    del remote
    del server
Example #9
0
               '"debug" -> most verbose, '
               '"info" -> somewhat verbose, '
               '"warning" -> default python verbosity, '
               '"error" -> quiet.',
    )
    parser.add_argument('unittest_args', nargs='*')

    args, unittest_args = parser.parse_known_args()
    
    # Do logging config and stuff
    from hypergolix import logutils
    
    if args.logdir:
        logutils.autoconfig(
            tofile = True,
            logdirname = args.logdir,
            loglevel = args.verbosity
        )
    else:
        logutils.autoconfig(
            tofile = False,
            loglevel = args.verbosity
        )
    
    # Dammit unittest using argparse
    # sys.argv[1:] = args.unittest_args
    from trashtest import *
    
    if args.traceur:
        # This diagnoses deadlocks
        from hypergolix.utils import TraceLogger
Example #10
0
def start(namespace=None):
    ''' Starts a Hypergolix daemon.
    '''
    # Command arg support is deprecated.
    if namespace is not None:
        # Gigantic error trap
        if ((namespace.host is not None) | (namespace.port is not None) |
            (namespace.debug is not None) | (namespace.traceur is not None) |
            (namespace.pidfile is not None) | (namespace.logdir is not None) |
            (namespace.cachedir is not None) | (namespace.chdir is not None) |
            (namespace.verbosity is not None)):
                raise RuntimeError('Server configuration through CLI is no ' +
                                   'longer supported. Edit hypergolix.yml ' +
                                   'configuration file instead.')
    
    with Daemonizer() as (is_setup, daemonizer):
        # Get our config path in setup, so that we error out before attempting
        # to daemonize (if anything is wrong).
        if is_setup:
            config = Config.find()
            config_path = config.path
            chdir = config_path.parent
            pid_file = config.server.pid_file
            
        else:
            config_path = None
            pid_file = None
            chdir = None
        
        # Daemonize.
        is_parent, config_path = daemonizer(
            str(pid_file),
            config_path,
            chdir = str(chdir),
            explicit_rescript = '-m hypergolix.service'
        )
        
        #####################
        # PARENT EXITS HERE #
        #####################
        
    config = Config.load(config_path)
    _ensure_dir_exists(config.server.ghidcache)
    _ensure_dir_exists(config.server.logdir)
    
    debug = _default_to(config.server.debug, False)
    verbosity = _default_to(config.server.verbosity, 'info')
    
    logutils.autoconfig(
        tofile = True,
        logdirname = config.server.logdir,
        logname = 'hgxserver',
        loglevel = verbosity
    )
        
    logger.debug('Parsing config...')
    host = _cast_host(config.server.host)
    rps = RemotePersistenceServer(
        config.server.ghidcache,
        host,
        config.server.port,
        reusable_loop = False,
        threaded = False,
        debug = debug
    )
    
    logger.debug('Starting health check...')
    # Start a health check
    healthcheck_server, healthcheck_thread = _serve_healthcheck()
    healthcheck_thread.start()
        
    logger.debug('Starting signal handler...')
    
    def signal_handler(signum):
        logger.info('Caught signal. Exiting.')
        healthcheck_server.shutdown()
        rps.stop_threadsafe_nowait()
        
    # Normally I'd do this within daemonization, but in this case, we need to
    # wait to have access to the handler.
    sighandler = SignalHandler1(
        str(config.server.pid_file),
        sigint = signal_handler,
        sigterm = signal_handler,
        sigabrt = signal_handler
    )
    sighandler.start()
    
    logger.info('Starting remote persistence server...')
    rps.start()
Example #11
0
def run_daemon(cfg_path, pid_file, parent_port, account_entity,
               root_secret):
    ''' Start the actual Hypergolix daemon.
    '''
    # Start reporting to our parent about how stuff is going.
    parent_signaller = _StartupReporter(parent_port)
    startup_logger = parent_signaller.start()
    
    try:
        config = Config.load(cfg_path)
        # Convert paths to strs and make sure the dirs exist
        cache_dir = str(config.process.ghidcache)
        log_dir = str(config.process.logdir)
        _ensure_dir_exists(config.process.ghidcache)
        _ensure_dir_exists(config.process.logdir)
        
        debug = _default_to(config.instrumentation.debug, False)
        verbosity = _default_to(config.instrumentation.verbosity, 'info')
        
        logutils.autoconfig(
            tofile = True,
            logdirname = log_dir,
            loglevel = verbosity,
            logname = 'hgxapp'
        )
        
        ipc_port = config.process.ipc_port
        remotes = config.remotes
        # Look to see if we have an existing user_id to determine behavior
        save_cfg = not bool(config.user.user_id)
        
        hgxcore = _DaemonCore(
            cache_dir = cache_dir,
            ipc_port = ipc_port,
            reusable_loop = False,
            threaded = False,
            debug = debug,
            cfg_path = cfg_path,
            save_cfg = save_cfg,
            boot_logger = parent_signaller
        )
        
        for remote in remotes:
            hgxcore.add_remote(
                connection_cls = WSBeatingConn,
                host = remote.host,
                port = remote.port,
                tls = remote.tls
            )
        
        account = Account(
            user_id = account_entity,
            root_secret = root_secret,
            hgxcore = hgxcore
        )
        hgxcore.account = account
        
        # We need a signal handler for that.
        def signal_handler(signum):
            logger.info('Caught signal. Exiting.')
            hgxcore.stop_threadsafe_nowait()
            
        # Normally I'd do this within daemonization, but in this case, we need
        # to wait to have access to the handler.
        sighandler = SignalHandler1(
            pid_file,
            sigint = signal_handler,
            sigterm = signal_handler,
            sigabrt = signal_handler
        )
        sighandler.start()
        
        startup_logger.info('Booting Hypergolix...')
        hgxcore.start()
        
    except Exception:
        startup_logger.error('Failed to start Hypergolix:\n' +
                             ''.join(traceback.format_exc()))
        raise
        
    finally:
        # This is idempotent, so no worries if we already called it
        parent_signaller.stop()