POC state of core_daemon. With to example modules.
This commit is contained in:
parent
ff00e4a2bc
commit
30ec739e8a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
109
core_daemon.py
Normal file
109
core_daemon.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import importlib
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
|
||||||
|
# Add the modules folder to the Python path
|
||||||
|
modules_path = os.path.join(os.path.dirname(__file__), 'modules')
|
||||||
|
sys.path.append(modules_path)
|
||||||
|
|
||||||
|
class ModuleManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.loaded_modules = {}
|
||||||
|
self.extra_commands = {}
|
||||||
|
|
||||||
|
def load_module(self, module_name):
|
||||||
|
try:
|
||||||
|
# Try to import from the modules folder
|
||||||
|
module = importlib.import_module(f'modules.{module_name}')
|
||||||
|
self.loaded_modules[module_name] = module
|
||||||
|
if hasattr(module, 'initialize'):
|
||||||
|
module.initialize()
|
||||||
|
if hasattr(module, 'get_commands'):
|
||||||
|
new_commands = module.get_commands()
|
||||||
|
self.extra_commands.update(new_commands)
|
||||||
|
return True, f"Module '{module_name}' loaded and initialized successfully."
|
||||||
|
except ImportError as e:
|
||||||
|
return False, f"Error: Unable to load module '{module_name}'. {str(e)}"
|
||||||
|
|
||||||
|
def unload_module(self, module_name):
|
||||||
|
if module_name in self.loaded_modules:
|
||||||
|
module = self.loaded_modules[module_name]
|
||||||
|
if hasattr(module, 'shutdown'):
|
||||||
|
module.shutdown()
|
||||||
|
if hasattr(module, 'get_commands'):
|
||||||
|
commands_to_remove = module.get_commands().keys()
|
||||||
|
for cmd in commands_to_remove:
|
||||||
|
self.extra_commands.pop(cmd, None)
|
||||||
|
del self.loaded_modules[module_name]
|
||||||
|
return True, f"Module '{module_name}' unloaded and shut down."
|
||||||
|
return False, f"Module '{module_name}' is not loaded."
|
||||||
|
|
||||||
|
def list_modules(self):
|
||||||
|
return list(self.loaded_modules.keys())
|
||||||
|
|
||||||
|
def list_commands(self):
|
||||||
|
return list(self.extra_commands.keys())
|
||||||
|
|
||||||
|
def execute_command(self, command, args):
|
||||||
|
if command in self.extra_commands:
|
||||||
|
return True, self.extra_commands[command](args)
|
||||||
|
return False, "Command not found"
|
||||||
|
|
||||||
|
class CoreDaemon:
|
||||||
|
def __init__(self, host='localhost', port=9999):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.module_manager = ModuleManager()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind((self.host, self.port))
|
||||||
|
s.listen()
|
||||||
|
print(f"Core daemon listening on {self.host}:{self.port}")
|
||||||
|
while True:
|
||||||
|
conn, addr = s.accept()
|
||||||
|
threading.Thread(target=self.handle_client, args=(conn,)).start()
|
||||||
|
|
||||||
|
def handle_client(self, conn):
|
||||||
|
with conn:
|
||||||
|
while True:
|
||||||
|
data = conn.recv(1024)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
command = json.loads(data.decode())
|
||||||
|
response = self.process_command(command)
|
||||||
|
conn.sendall(json.dumps(response).encode())
|
||||||
|
|
||||||
|
def upgrade(self):
|
||||||
|
print("Upgrading core daemon...")
|
||||||
|
# Here you would typically download or copy the new version
|
||||||
|
# For this example, we'll just restart the script
|
||||||
|
os.execv(sys.executable, ['python'] + sys.argv)
|
||||||
|
|
||||||
|
def process_command(self, command):
|
||||||
|
action = command.get('action')
|
||||||
|
if action == 'load':
|
||||||
|
success, message = self.module_manager.load_module(command.get('module'))
|
||||||
|
elif action == 'unload':
|
||||||
|
success, message = self.module_manager.unload_module(command.get('module'))
|
||||||
|
elif action == 'list':
|
||||||
|
modules = self.module_manager.list_modules()
|
||||||
|
success, message = True, modules
|
||||||
|
elif action == 'execute':
|
||||||
|
success, message = self.module_manager.execute_command(command.get('command'), command.get('args'))
|
||||||
|
elif action == 'upgrade':
|
||||||
|
self.upgrade()
|
||||||
|
success, message = True, "Upgrade initiated"
|
||||||
|
elif action == 'list_commands':
|
||||||
|
commands = self.module_manager.list_commands()
|
||||||
|
success, message = True, commands
|
||||||
|
else:
|
||||||
|
success, message = False, "Unknown command"
|
||||||
|
return {'success': success, 'message': message}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
daemon = CoreDaemon()
|
||||||
|
daemon.start()
|
95
daemon_cli.py
Normal file
95
daemon_cli.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import cmd
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
class ModuleShell(cmd.Cmd):
|
||||||
|
intro = "Welcome to the Module Shell. Type 'help' for commands."
|
||||||
|
prompt = "(module_shell) "
|
||||||
|
|
||||||
|
def __init__(self, host='localhost', port=9999):
|
||||||
|
super().__init__()
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.update_commands()
|
||||||
|
|
||||||
|
def send_command(self, command):
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect((self.host, self.port))
|
||||||
|
s.sendall(json.dumps(command).encode())
|
||||||
|
return json.loads(s.recv(1024).decode())
|
||||||
|
|
||||||
|
def update_commands(self):
|
||||||
|
response = self.send_command({'action': 'list_commands'})
|
||||||
|
if response['success']:
|
||||||
|
self.dynamic_commands = response['message']
|
||||||
|
else:
|
||||||
|
self.dynamic_commands = []
|
||||||
|
|
||||||
|
def default(self, line):
|
||||||
|
parts = line.split()
|
||||||
|
command = parts[0]
|
||||||
|
args = ' '.join(parts[1:])
|
||||||
|
response = self.send_command({'action': 'execute', 'command': command, 'args': args})
|
||||||
|
if response['success']:
|
||||||
|
print(response['message'])
|
||||||
|
else:
|
||||||
|
print(f"Error: {response['message']}")
|
||||||
|
|
||||||
|
def completenames(self, text, *ignored):
|
||||||
|
dotext = 'do_'+text
|
||||||
|
return [a[3:] for a in self.get_names() if a.startswith(dotext)] + \
|
||||||
|
[cmd for cmd in self.dynamic_commands if cmd.startswith(text)]
|
||||||
|
|
||||||
|
def do_load(self, arg):
|
||||||
|
"""Load a module: load <module_name>"""
|
||||||
|
response = self.send_command({'action': 'load', 'module': arg})
|
||||||
|
print(response['message'])
|
||||||
|
self.update_commands() # Update commands after loading a new module
|
||||||
|
|
||||||
|
def do_unload(self, arg):
|
||||||
|
"""Unload a module: unload <module_name>"""
|
||||||
|
response = self.send_command({'action': 'unload', 'module': arg})
|
||||||
|
print(response['message'])
|
||||||
|
self.update_commands() # Update commands after unloading a module
|
||||||
|
|
||||||
|
def do_list(self, arg):
|
||||||
|
"""List all loaded modules"""
|
||||||
|
response = self.send_command({'action': 'list'})
|
||||||
|
modules = response['message']
|
||||||
|
if modules:
|
||||||
|
print("Loaded modules:")
|
||||||
|
for module in modules:
|
||||||
|
print(f"- {module}")
|
||||||
|
else:
|
||||||
|
print("No modules are currently loaded.")
|
||||||
|
|
||||||
|
def do_list_available(self, arg):
|
||||||
|
"""List available modules in the modules folder"""
|
||||||
|
modules_path = os.path.join(os.path.dirname(__file__), 'modules')
|
||||||
|
available_modules = [f[:-3] for f in os.listdir(modules_path) if f.endswith('.py') and not f.startswith('__')]
|
||||||
|
print("Available modules:")
|
||||||
|
for module in available_modules:
|
||||||
|
print(f"- {module}")
|
||||||
|
|
||||||
|
def complete_load(self, text, line, begidx, endidx):
|
||||||
|
modules_path = os.path.join(os.path.dirname(__file__), 'modules')
|
||||||
|
available_modules = [f[:-3] for f in os.listdir(modules_path) if f.endswith('.py') and not f.startswith('__')]
|
||||||
|
return [m for m in available_modules if m.startswith(text)]
|
||||||
|
|
||||||
|
|
||||||
|
def do_upgrade(self, arg):
|
||||||
|
"""Upgrade the core daemon"""
|
||||||
|
response = self.send_command({'action': 'upgrade'})
|
||||||
|
print(response['message'])
|
||||||
|
|
||||||
|
def do_exit(self, arg):
|
||||||
|
"""Exit the shell"""
|
||||||
|
print("Exiting...")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ModuleShell().cmdloop()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
25
modules/extra_commands.py
Normal file
25
modules/extra_commands.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
class ExtraCommands:
|
||||||
|
@staticmethod
|
||||||
|
def do_greet(args):
|
||||||
|
"""Greet someone: greet <name>"""
|
||||||
|
name = args if args else "World"
|
||||||
|
return f"Hello, {name}!"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def do_reverse(args):
|
||||||
|
"""Reverse a string: reverse <string>"""
|
||||||
|
return args[::-1]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def do_count(args):
|
||||||
|
"""Count words in a string: count <string>"""
|
||||||
|
return str(len(args.split()))
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
'greet': ExtraCommands.do_greet,
|
||||||
|
'reverse': ExtraCommands.do_reverse,
|
||||||
|
'count': ExtraCommands.do_count,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_commands():
|
||||||
|
return commands
|
37
modules/http_service.py
Normal file
37
modules/http_service.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
def do_GET(self):
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b'Hello, World!')
|
||||||
|
|
||||||
|
class HTTPService:
|
||||||
|
def __init__(self, host='localhost', port=8000):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.server = None
|
||||||
|
self.thread = None
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.server = HTTPServer((self.host, self.port), SimpleHTTPRequestHandler)
|
||||||
|
self.thread = threading.Thread(target=self.server.serve_forever)
|
||||||
|
self.thread.start()
|
||||||
|
print(f"HTTP service started on http://{self.host}:{self.port}")
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.server:
|
||||||
|
self.server.shutdown()
|
||||||
|
self.server.server_close()
|
||||||
|
self.thread.join()
|
||||||
|
print("HTTP service stopped")
|
||||||
|
|
||||||
|
http_service = HTTPService()
|
||||||
|
|
||||||
|
def initialize():
|
||||||
|
http_service.start()
|
||||||
|
|
||||||
|
def shutdown():
|
||||||
|
http_service.stop()
|
Loading…
Reference in New Issue
Block a user