import os import aiohttp import asyncio import socket import configparser cfg = configparser.ConfigParser() import asusrouter.modules.port_forwarding from asusrouter import AsusRouter, AsusData from api.pelican import PelicanApi from flask import Flask, request RULE_PREFIX = "[auto]::" def create_rule(label, address, port): return asusrouter.modules.port_forwarding.PortForwardingRule(RULE_PREFIX + label, address, None, "BOTH", None, port) def rule_to_string(rule: asusrouter.modules.port_forwarding.PortForwardingRule): return f"{rule.name}::{rule.port_external}->{rule.port if rule.port else rule.port_external}@{rule.ip_address}" def apply_port_changes(): loop = asyncio.get_event_loop() session = aiohttp.ClientSession(loop=loop) pelican_cfg = cfg["pelican"] router_cfg = cfg["router"] pelican = PelicanApi(pelican_cfg["baseurl"], pelican_cfg["auth"]) router = AsusRouter( hostname=router_cfg["hostname"], username=router_cfg["username"], password=router_cfg["password"], use_ssl=False, session=session ) run = loop.run_until_complete run(router.async_connect()) data = run(router.async_get_data(AsusData.PORT_FORWARDING)) rules = data["rules"] x: asusrouter.modules.port_forwarding.PortForwardingRule # Remove auto-generated rules rules = [x for x in rules if not x.name.startswith(RULE_PREFIX)] # Add new auto-generated rules allocation_server_lookup = {} for server in pelican.servers(): allocation_server_lookup[server["allocation"]] = server for node in pelican.nodes(): node_id = node["id"] allocs = pelican.allocations(node_id) node_internal_name = node["name"] + ".pve.local" node_internal_ip = socket.getaddrinfo(node_internal_name, 0)[0][4][0] for alloc in allocs: if not alloc["assigned"]: continue label = "Allocation " + str(alloc["id"]) + " for " + node_internal_name if alloc["id"] in allocation_server_lookup.keys(): svr = allocation_server_lookup[alloc["id"]] label = svr["name"] + "(" + svr["identifier"] + ") allocation" rules.append(create_rule(label, node_internal_ip, alloc["port"])) run(router.async_apply_port_forwarding_rules(rules)) print("Currently open ports: ") for rule in rules: print("\t" + rule_to_string(rule)) run(router.async_disconnect()) run(session.close()) app = Flask(__name__) @app.route("/pelican-wh", methods=["GET", "POST"]) def start(): apply_port_changes() return "Hello, world!" if __name__ == '__main__': if os.path.exists("/config/config.ini"): cfg.read("/config/config.ini") else: print("No config file detected, exiting...") exit(1) port = int(cfg["app"]["port"]) app.run(host="0.0.0.0", port=port)