From 8727e74eab0c6072d8bb537fcf48519cb8044bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Sun, 28 Jan 2024 22:20:56 +0100 Subject: [PATCH 1/2] Fix port reuse during provisionning. Before this, provisionning might use twice the same port (second app install for example). Indeed, _port_is_used only checks processes and already installed apps. Not the current app being installed. --- src/utils/resources.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/utils/resources.py b/src/utils/resources.py index 0d3f584da..931bb057d 100644 --- a/src/utils/resources.py +++ b/src/utils/resources.py @@ -1216,17 +1216,24 @@ class PortsResource(AppResource): if properties[port]["default"] is None: properties[port]["default"] = random.randint(10000, 60000) + # This is to prevent using twice the same port during provisionning. + self.used_ports: list[int] = [] + super().__init__({"ports": properties}, *args, **kwargs) def _port_is_used(self, port): # FIXME : this could be less brutal than two os.system... - cmd1 = ( + used_by_process = os.system( "ss --numeric --listening --tcp --udp | awk '{print$5}' | grep --quiet --extended-regexp ':%s$'" % port - ) + ) == 0 # This second command is mean to cover (most) case where an app is using a port yet ain't currently using it for some reason (typically service ain't up) - cmd2 = f"grep --quiet --extended-regexp \"port: '?{port}'?\" /etc/yunohost/apps/*/settings.yml" - return os.system(cmd1) == 0 or os.system(cmd2) == 0 + used_by_app = os.system( + f"grep --quiet --extended-regexp \"port: '?{port}'?\" /etc/yunohost/apps/*/settings.yml" + ) == 0 + used_by_self_provisioning = port in self.used_ports + + return used_by_process or used_by_app or used_by_self_provisioning def provision_or_update(self, context: Dict = {}): from yunohost.firewall import firewall_allow, firewall_disallow @@ -1256,6 +1263,7 @@ class PortsResource(AppResource): while self._port_is_used(port_value): port_value += 1 + self.used_ports.append(port_value) self.set_setting(setting_name, port_value) if infos["exposed"]: From 820a79c238ca9f9167d7cc130982b4936ef4700e Mon Sep 17 00:00:00 2001 From: Alexandre Aubin <4533074+alexAubin@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:28:45 +0100 Subject: [PATCH 2/2] Update resources.py: used_ports -> ports_used_by_self --- src/utils/resources.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/resources.py b/src/utils/resources.py index 931bb057d..5ce76cabe 100644 --- a/src/utils/resources.py +++ b/src/utils/resources.py @@ -1217,7 +1217,7 @@ class PortsResource(AppResource): properties[port]["default"] = random.randint(10000, 60000) # This is to prevent using twice the same port during provisionning. - self.used_ports: list[int] = [] + self.ports_used_by_self: list[int] = [] super().__init__({"ports": properties}, *args, **kwargs) @@ -1231,7 +1231,7 @@ class PortsResource(AppResource): used_by_app = os.system( f"grep --quiet --extended-regexp \"port: '?{port}'?\" /etc/yunohost/apps/*/settings.yml" ) == 0 - used_by_self_provisioning = port in self.used_ports + used_by_self_provisioning = port in self.ports_used_by_self return used_by_process or used_by_app or used_by_self_provisioning @@ -1263,7 +1263,7 @@ class PortsResource(AppResource): while self._port_is_used(port_value): port_value += 1 - self.used_ports.append(port_value) + self.ports_used_by_self.append(port_value) self.set_setting(setting_name, port_value) if infos["exposed"]: