Example #1
0
	def _run(self) -> None:
		WSGIRequestHandler.protocol_version = "HTTP/1.1"

		# Run the http server. This runs forever.
		# The server can run single-threadedly since some of the underlying
		# components (e.g. TinyDB) may run into problems otherwise.
		if self.flaskApp is not None:
			# Disable the flask banner messages
			cli = sys.modules['flask.cli']
			cli.show_server_banner = lambda *x: None 	# type: ignore
			# Start the server
			try:
				context = None
				if self.useTLS:
					Logging.logDebug(f'Setup SSL context. Certfile: {self.caCertificateFile}, KeyFile:{self.caPrivateKeyFile}, TLS version: {self.tlsVersion}')
					context = ssl.SSLContext(
									{ 	'tls1.1' : ssl.PROTOCOL_TLSv1_1,
										'tls1.2' : ssl.PROTOCOL_TLSv1_2,
										'auto'   : ssl.PROTOCOL_TLS,			# since Python 3.6. Automatically choose the highest protocol version between client & server
									}[self.tlsVersion.lower()]
								)
					context.load_cert_chain(self.caCertificateFile, self.caPrivateKeyFile)
				self.flaskApp.run(host=self.listenIF, 
								  port=self.port,
								  threaded=Configuration.get('http.multiThread'),
								  request_handler=ACMERequestHandler,
								  ssl_context=context,
								  debug=False)
			except Exception as e:
				# No logging for headless, nevertheless print the reason what happened
				if CSE.isHeadless:
					Logging.console(str(e), isError=True)
					#print(str(e))
				Logging.logErr(str(e))
				CSE.shutdown() # exit the CSE. Cleanup happens in the CSE atexit() handler
Example #2
0
def _keyDeleteResource(key: str) -> None:
    """	Delete a resource from the CSE.
	"""
    Logging.console('**Delete Resource**', extranl=True)
    loggingOld = Logging.loggingEnabled
    Logging.loggingEnabled = False

    if (ri := readline('ri=')) is None:
        Logging.console()
Example #3
0
def _keyInspectResource(key: str) -> None:
    """	Inspect a resource.
	"""
    Logging.console('**Inspect Resource**', extranl=True)
    loggingOld = Logging.loggingEnabled
    Logging.loggingEnabled = False

    if (ri := readline('ri=')) is None:
        Logging.console()
Example #4
0
def _keyChildResourceTree(key: str) -> None:
    """	Render the CSE's resource tree, beginning with a child resource.
	"""
    Logging.console('**Child Resource Tree**', extranl=True)
    loggingOld = Logging.loggingEnabled
    Logging.loggingEnabled = False

    if (ri := readline('ri=')) is None:
        Logging.console()
Example #5
0
def shutdown() -> None:
    """	Gracefully shutdown the CSE programmatically. This will end the mail console loop
		to terminate.
		The actual shutdown happens in the _shutdown() method.
	"""
    global shuttingDown

    # indicating the shutting down status. When running in another environment the
    # atexit-handler might not be called. Therefore, we need to set it here
    shuttingDown = True
    stopLoop()  # This will end the main run loop.
    if isHeadless:
        Logging.console('CSE shutting down')
Example #6
0
def _keyWorkers(key: str) -> None:
    """	Print the worker and actor threads.
	"""
    from rich.table import Table

    Logging.console('**Worker & Actor Threads**', extranl=True)
    table = Table()
    table.add_column('Name', no_wrap=True)
    table.add_column('Type', no_wrap=True)
    table.add_column('Interval', no_wrap=True)
    table.add_column('Runs', no_wrap=True)
    for w in BackgroundWorkerPool.backgroundWorkers.values():
        a = 'Actor' if w.count == 1 else 'Worker'
        table.add_row(w.name, a, str(w.updateInterval), str(w.numberOfRuns))
    Logging.console(table, extranl=True)
Example #7
0
def _keyConfiguration(key: str) -> None:
    """	Print the configuration.
	"""
    from rich.table import Table

    Logging.console('**Configuration**', extranl=True)
    conf = Configuration.print().split('\n')
    conf.sort()
    table = Table()
    table.add_column('Key', no_wrap=True)
    table.add_column('Value', no_wrap=False)
    for c in conf:
        if c.startswith('Configuration:'):
            continue
        kv = c.split(' = ', 1)
        if len(kv) == 2:
            table.add_row(kv[0].strip(), kv[1])
    Logging.console(table, extranl=True)
Example #8
0
def _keyHelp(key: str) -> None:
    """	Print help for keyboard commands.
	"""
    Logging.console(
        f'\n[white][dim][[/dim][red][i]ACME[/i][/red][dim]] {C.version}',
        plain=True)
    Logging.console("""**Console Commands**  
- h, ?  - This help
- Q, ^C - Shutdown CSE
- c     - Show configuration
- C     - Clear the console screen
- D     - Delete resource
- i     - Inspect resource
- l     - Toggle logging on/off
- r     - Show CSE registrations
- s     - Show statistics
- t     - Show resource tree
- T     - Show child resource tree
- w     - Show worker threads status
""",
                    extranl=True)
Example #9
0
def startup(args: argparse.Namespace, **kwargs: Dict[str, Any]) -> None:
    global announce, dispatcher, group, httpServer, notification, validator
    global registration, remote, request, security, statistics, storage, event
    global rootDirectory
    global aeStatistics
    global supportedReleaseVersions, cseType, defaultSerialization, cseCsi, cseRi, cseRn
    global cseOriginator
    global isHeadless

    rootDirectory = os.getcwd()  # get the root directory
    os.environ[
        "FLASK_ENV"] = "development"  # get rid if the warning message from flask.
    # Hopefully it is clear at this point that this is not a production CSE

    # Handle command line arguments and load the configuration
    if args is None:
        args = argparse.Namespace(
        )  # In case args is None create a new args object and populate it
        args.configfile = None
        args.resetdb = False
        args.loglevel = None
        args.headless = False
        for key, value in kwargs.items():
            args.__setattr__(key, value)
    isHeadless = args.headless

    if not Configuration.init(args):
        return

    # Initialize configurable constants
    supportedReleaseVersions = Configuration.get(
        'cse.supportedReleaseVersions')
    cseType = Configuration.get('cse.type')
    cseCsi = Configuration.get('cse.csi')
    cseRi = Configuration.get('cse.ri')
    cseRn = Configuration.get('cse.rn')
    cseOriginator = Configuration.get('cse.originator')

    defaultSerialization = Configuration.get('cse.defaultSerialization')

    # init Logging
    Logging.init()
    if not args.headless:
        Logging.console('Press ? for help')
    Logging.log('============')
    Logging.log('Starting CSE')
    Logging.log(f'CSE-Type: {cseType.name}')
    Logging.log('Configuration:')
    Logging.log(Configuration.print())

    # Initiatlize the resource storage
    storage = Storage()

    # Initialize the event manager
    event = EventManager()

    # Initialize the statistics system
    statistics = Statistics()

    # Initialize the registration manager
    registration = RegistrationManager()

    # Initialize the resource validator
    validator = Validator()

    # Initialize the resource dispatcher
    dispatcher = Dispatcher()

    # Initialize the request manager
    request = RequestManager()

    # Initialize the security manager
    security = SecurityManager()

    # Initialize the HTTP server
    httpServer = HttpServer()

    # Initialize the notification manager
    notification = NotificationManager()

    # Initialize the group manager
    group = GroupManager()

    # Import a default set of resources, e.g. the CSE, first ACP or resource structure
    # Import extra attribute policies for specializations first
    importer = Importer()
    if not importer.importAttributePolicies() or not importer.importResources(
    ):
        return

    # Initialize the remote CSE manager
    remote = RemoteCSEManager()

    # Initialize the announcement manager
    announce = AnnouncementManager()

    # Start AEs
    startAppsDelayed(
    )  # the Apps are actually started after the CSE finished the startup

    # Start the HTTP server
    event.cseStartup()  # type: ignore
    httpServer.run()  # This does return (!)

    Logging.log('CSE started')
    if isHeadless:
        # when in headless mode give the CSE a moment (2s) to experience fatal errors before printing the start message
        BackgroundWorkerPool.newActor(
            delay=2,
            workerCallback=lambda: Logging.console('CSE started')
            if not shuttingDown else None).start()

    #
    #	Enter an endless loop.
    #	Execute keyboard commands in the keyboardHandler's loop() function.
    #
    commands = {
        '?': _keyHelp,
        'h': _keyHelp,
        '\n': lambda c: print(),  # 1 empty line
        '\x03': _keyShutdownCSE,  # See handler below
        'c': _keyConfiguration,
        'C': _keyClearScreen,
        'D': _keyDeleteResource,
        'i': _keyInspectResource,
        'l': _keyToggleLogging,
        'Q': _keyShutdownCSE,  # See handler below
        'r': _keyCSERegistrations,
        's': _keyStatistics,
        't': _keyResourceTree,
        'T': _keyChildResourceTree,
        'w': _keyWorkers,
    }

    #	Endless runtime loop. This handles key input & commands
    #	The CSE's shutdown happens in one of the key handlers below
    loop(commands, catchKeyboardInterrupt=True, headless=args.headless)
    shutdown()
Example #10
0
def _keyStatistics(key: str) -> None:
    """ Render various statistics & counts.
	"""
    Logging.console('**Statistics**', extranl=True)
    Logging.console(statistics.getStatisticsRich())
    Logging.console()
Example #11
0
def _keyCSERegistrations(key: str) -> None:
    """	Render CSE registrations.
	"""
    Logging.console('**CSE Registrations**', extranl=True)
    Logging.console(statistics.getCSERegistrationsRich())
    Logging.console()
Example #12
0
def _keyResourceTree(key: str) -> None:
    """	Render the CSE's resource tree.
	"""
    Logging.console('**Resource Tree**', extranl=True)
    Logging.console(statistics.getResourceTreeRich())
    Logging.console()
Example #13
0
def _keyToggleLogging(key: str) -> None:
    """	Toggle through the log levels.
	"""
    Logging.enableScreenLogging = not Logging.enableScreenLogging
    Logging.console(f'Logging enabled -> **{Logging.enableScreenLogging}**')
Example #14
0
def _keyShutdownCSE(key: str) -> None:
    """	Shutdown the CSE.
	"""
    if not isHeadless:
        Logging.console('Shutdown CSE')
    sys.exit()
Example #15
0
    Logging.console(statistics.getResourceTreeRich())
    Logging.console()


def _keyChildResourceTree(key: str) -> None:
    """	Render the CSE's resource tree, beginning with a child resource.
	"""
    Logging.console('**Child Resource Tree**', extranl=True)
    loggingOld = Logging.loggingEnabled
    Logging.loggingEnabled = False

    if (ri := readline('ri=')) is None:
        Logging.console()
    elif len(ri) > 0:
        if (tree := statistics.getResourceTreeRich(parent=ri)) is not None:
            Logging.console(tree)
        else:
            Logging.console('not found', isError=True)

    Logging.loggingEnabled = loggingOld


def _keyCSERegistrations(key: str) -> None:
    """	Render CSE registrations.
	"""
    Logging.console('**CSE Registrations**', extranl=True)
    Logging.console(statistics.getCSERegistrationsRich())
    Logging.console()


def _keyStatistics(key: str) -> None: