From a9157e3a9f65e3dfb706ae19ea655756f1e6c4a8 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 26 Apr 2020 11:21:56 +0200 Subject: [PATCH] Fix possible Ingress port collisions (#1682) * Fix possible Ingress port collisions * Cleanup dynamic port assignment on uninstall * Check port against gateway address * gateway address is already of type IPv4Address * Update supervisor/ingress.py Co-Authored-By: Pascal Vizeli Co-authored-by: Pascal Vizeli --- supervisor/addons/__init__.py | 3 +++ supervisor/ingress.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/supervisor/addons/__init__.py b/supervisor/addons/__init__.py index 3d33a7c7c..93d0d25ba 100644 --- a/supervisor/addons/__init__.py +++ b/supervisor/addons/__init__.py @@ -166,6 +166,9 @@ class AddonManager(CoreSysAttributes): with suppress(HomeAssistantAPIError): await self.sys_ingress.update_hass_panel(addon) + # Cleanup Ingress dynamic port assignment + self.sys_ingress.del_dynamic_port(slug) + # Cleanup discovery data for message in self.sys_discovery.list_messages: if message.addon != addon.slug: diff --git a/supervisor/ingress.py b/supervisor/ingress.py index 1c7ef85e1..5ff17eadb 100644 --- a/supervisor/ingress.py +++ b/supervisor/ingress.py @@ -8,6 +8,7 @@ from typing import Dict, List, Optional from .addons.addon import Addon from .const import ATTR_PORTS, ATTR_SESSION, FILE_HASSIO_INGRESS from .coresys import CoreSys, CoreSysAttributes +from .utils import check_port from .utils.dt import utc_from_timestamp, utcnow from .utils.json import JsonConfig from .validate import SCHEMA_INGRESS_CONFIG @@ -118,13 +119,28 @@ class Ingress(JsonConfig, CoreSysAttributes): """Get/Create a dynamic port from range.""" if addon_slug in self.ports: return self.ports[addon_slug] - port = random.randint(62000, 65500) + + port = None + while ( + port is None + or port in self.ports.values() + or check_port(self.sys_docker.network.gateway, port) + ): + port = random.randint(62000, 65500) # Save port for next time self.ports[addon_slug] = port self.save_data() return port + def del_dynamic_port(self, addon_slug: str) -> None: + """Remove a previously assigned dynamic port.""" + if addon_slug not in self.ports: + return + + del self.ports[addon_slug] + self.save_data() + async def update_hass_panel(self, addon: Addon): """Return True if Home Assistant up and running.""" if not await self.sys_homeassistant.is_running():