diff --git a/_modules/win_agent.py b/_modules/win_agent.py index 7a11e9e5..3c3b301b 100644 --- a/_modules/win_agent.py +++ b/_modules/win_agent.py @@ -75,7 +75,22 @@ def install_updates(): def agent_update(version, url): - sleep(random.randint(1, 90)) + # make sure another instance of the update is not running + # this function spawns 2 instances of itself so if more than 2 running, + # don't continue as an update is already running + count = 0 + for p in psutil.process_iter(): + try: + with p.oneshot(): + if "win_agent.agent_update" in p.cmdline(): + count += 1 + except Exception: + continue + + if count > 2: + return "already running" + + sleep(random.randint(1, 60)) # don't flood the rmm try: r = requests.get(url, stream=True, timeout=600) except Exception: @@ -99,7 +114,7 @@ def agent_update(version, url): sleep(10) r = subprocess.run([exe, "/VERYSILENT", "/SUPPRESSMSGBOXES"], timeout=300) - sleep(20) + sleep(30) for svc in services: subprocess.run([NSSM, "start", svc], timeout=120) diff --git a/api/tacticalrmm/core/management/commands/post_update_tasks.py b/api/tacticalrmm/core/management/commands/post_update_tasks.py new file mode 100644 index 00000000..a058c403 --- /dev/null +++ b/api/tacticalrmm/core/management/commands/post_update_tasks.py @@ -0,0 +1,21 @@ +from time import sleep + +from django.core.management.base import BaseCommand + +from agents.models import Agent + + +class Command(BaseCommand): + help = "Collection of tasks to run after updating the rmm, after migrations" + + def handle(self, *args, **kwargs): + # sync modules. split into chunks of 30 agents to not overload the salt master + agents = Agent.objects.all() + online = [i.salt_id for i in agents if i.status == "online"] + + chunks = (online[i : i + 30] for i in range(0, len(online), 30)) + + self.stdout.write(self.style.SUCCESS("Syncing agent modules...")) + for chunk in chunks: + r = Agent.salt_batch_async(minions=chunk, func="saltutil.sync_modules") + sleep(5) diff --git a/api/tacticalrmm/core/management/commands/pre_update_tasks.py b/api/tacticalrmm/core/management/commands/pre_update_tasks.py new file mode 100644 index 00000000..0ab06acf --- /dev/null +++ b/api/tacticalrmm/core/management/commands/pre_update_tasks.py @@ -0,0 +1,13 @@ +from time import sleep + +from django.core.management.base import BaseCommand + +from agents.models import Agent + + +class Command(BaseCommand): + help = "Collection of tasks to run after updating the rmm, before migrations" + + def handle(self, *args, **kwargs): + # adding this now for future updates + pass diff --git a/update.sh b/update.sh index 813f5b8c..e691e41f 100644 --- a/update.sh +++ b/update.sh @@ -1,6 +1,6 @@ #!/bin/bash -SCRIPT_VERSION="1" +SCRIPT_VERSION="2" SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/develop/update.sh' YELLOW='\033[1;33m' GREEN='\033[0;32m' @@ -38,10 +38,12 @@ cd /rmm/api/tacticalrmm pip install --no-cache-dir --upgrade pip pip install --no-cache-dir setuptools==47.3.2 wheel==0.34.2 pip install --no-cache-dir -r requirements.txt +python manage.py pre_update_tasks python manage.py migrate python manage.py delete_tokens python manage.py fix_salt_key python manage.py collectstatic --no-input +python manage.py post_update_tasks deactivate