def handle_bulk_script_task(scriptpk, agentpks, args, timeout): script = Script.objects.get(pk=scriptpk) agents = Agent.objects.filter(pk__in=agentpks) agents_nats = [agent for agent in agents if agent.has_nats] agents_salt = [agent for agent in agents if not agent.has_nats] minions = [agent.salt_id for agent in agents_salt] if minions: Agent.salt_batch_async( minions=minions, func="win_agent.run_script", kwargs={ "filepath": script.filepath, "filename": script.filename, "shell": script.shell, "timeout": timeout, "args": args, "bg": True if script.shell == "python" else False, # salt bg script bug }, ) nats_data = { "func": "runscript", "timeout": timeout, "script_args": args, "payload": { "code": script.code, "shell": script.shell, }, } for agent in agents_nats: asyncio.run(agent.nats_cmd(nats_data, wait=False))
def handle_bulk_command_task(agentpks, cmd, shell, timeout): agents = Agent.objects.filter(pk__in=agentpks) agents_nats = [agent for agent in agents if agent.has_nats] agents_salt = [agent for agent in agents if not agent.has_nats] minions = [agent.salt_id for agent in agents_salt] if minions: Agent.salt_batch_async( minions=minions, func="cmd.run_bg", kwargs={ "cmd": cmd, "shell": shell, "timeout": timeout, }, ) if agents_nats: nats_data = { "func": "rawcmd", "timeout": timeout, "payload": { "command": cmd, "shell": shell, }, } for agent in agents_nats: asyncio.run(agent.nats_cmd(nats_data, wait=False))
def add(request): data = request.data client = get_object_or_404(Client, pk=int(data["client"])) site = get_object_or_404(Site, pk=int(data["site"])) if not Agent.objects.filter(agent_id=data["agent_id"]).exists(): agent = Agent( agent_id=data["agent_id"], hostname=data["hostname"], client=client.client, site=site.site, monitoring_type=data["monitoring_type"], description=data["description"], mesh_node_id=data["mesh_node_id"], last_seen=djangotime.now(), ) agent.save() if agent.monitoring_type == "workstation": WinUpdatePolicy(agent=agent, run_time_days=[5, 6]).save() else: WinUpdatePolicy(agent=agent).save() return Response({"pk": agent.pk}) else: return Response("err", status=status.HTTP_400_BAD_REQUEST)
def get_all_agents_url(): existing = [agent.url for agent in Agent.objects.all()] agents = [] for c in string.ascii_uppercase: num = get_num_page(c) if num: page_num = (num - 1) / 50 + 1 for page in range(1, page_num + 1): url = AGENTS_FIRSTNAME_URL + "/%c/%d" % (c, page) + "?items_per_page=50" agent_url_list = get_agent_url_list_from_url(url) for agent_url in agent_url_list: if not (agent_url in existing): agent = Agent(url=agent_url) agent.save() # agent = get_agent_by_url(HOST + agent_url) # if agent is None: # some error happens, try to process again # time.sleep(1) # agent = get_agent_by_url(HOST + agent_url) # else: # agent.save() agents.append(agent) time.sleep(1) logger.info("Get all agents with first_letter = %c done!" % c) logger.info("Get agents: %d" % (len(agents))) return agents
def batch_sync_modules_task(): # sync modules, split into chunks of 50 agents to not overload salt agents = Agent.objects.all() online = [i.salt_id for i in agents] chunks = (online[i:i + 50] for i in range(0, len(online), 50)) for chunk in chunks: Agent.salt_batch_async(minions=chunk, func="saltutil.sync_modules") sleep(10)
def batch_sysinfo_task(): # update system info using WMI agents = Agent.objects.all() online = [ i.salt_id for i in agents if not i.not_supported("0.11.0") and i.status == "online" ] chunks = (online[i:i + 30] for i in range(0, len(online), 30)) for chunk in chunks: Agent.salt_batch_async(minions=chunk, func="win_agent.local_sys_info") sleep(10)
def add(request): data = request.data agent_id = data["agentid"] hostname = data["hostname"] client = data["client"] site = data["site"] monitoring_type = data["monitoring_type"] description = data["description"] mesh_node_id = data["mesh_node_id"] if not Agent.objects.filter(agent_id=agent_id).exists(): Agent( agent_id=agent_id, hostname=hostname, client=client, site=site, monitoring_type=monitoring_type, description=description, mesh_node_id=mesh_node_id, ).save() agent = get_object_or_404(Agent, agent_id=agent_id) MemoryHistory(agent=agent).save() CpuHistory(agent=agent).save() if agent.monitoring_type == "workstation": WinUpdatePolicy(agent=agent, run_time_days=[5, 6]).save() else: WinUpdatePolicy(agent=agent).save() return Response({"pk": agent.pk}) else: return Response("err", status=status.HTTP_400_BAD_REQUEST)
def save_model(self, request, obj, form, change): if not change: # Django's PasswordResetForm won't let us reset an unusable # password. We set it above super() so we don't have to save twice. obj.set_password(get_random_string()) reset_password = True import pdb pdb.set_trace() else: reset_password = False user = super(UserAdmin, self).save_model(request, obj, form, change) import pdb pdb.set_trace() # Create the Agent now facility = form.cleaned_data.get("facility") user = User.objects.get(email=form.cleaned_data.get("email")) Agent(user=user, facility=facility).save() import pdb pdb.set_trace() if reset_password: import pdb pdb.set_trace() reset_form = PasswordResetForm({'email': obj.email}) assert reset_form.is_valid() if reset_password: reset_form = PasswordResetForm({'email': obj.email}) assert reset_form.is_valid() reset_form.save( request=request, use_https=request.is_secure(), subject_template_name='account_creation_subject.txt', email_template_name='account_creation_email.html', )
def service_action(hostname, action, service): return Agent.salt_api_cmd( hostname=hostname, timeout=30, func="cmd.script", arg="C:\\Program Files\\TacticalAgent\\nssm.exe", kwargs={"args": f"{action} {service}"}, )
def read_agent_list(input_path='agents/SalesPersons.xlsx'): book = xlrd.open_workbook(input_path) sheet = book.sheet_by_index(0) for row in range(2, sheet.nrows): reg_number = sheet.cell(row, 0).value name = sheet.cell(row, 1).value estate_name = sheet.cell(row, 2).value lic_number = sheet.cell(row, 3).value agent = Agent(reg_number=reg_number, name=name, estate_name=estate_name, lic_number=lic_number) agent.save() print "done %d" % row print "done"
def post(self, request): from logs.models import AuditLog """ Creates the agent """ if Agent.objects.filter(agent_id=request.data["agent_id"]).exists(): return notify_error( "Agent already exists. Remove old agent first if trying to re-install" ) agent = Agent( agent_id=request.data["agent_id"], hostname=request.data["hostname"], site_id=int(request.data["site"]), monitoring_type=request.data["monitoring_type"], description=request.data["description"], mesh_node_id=request.data["mesh_node_id"], last_seen=djangotime.now(), ) agent.save() agent.salt_id = f"{agent.hostname}-{agent.pk}" agent.save(update_fields=["salt_id"]) user = User.objects.create_user( # type: ignore username=request.data["agent_id"], agent=agent, password=User.objects.make_random_password(60), # type: ignore ) token = Token.objects.create(user=user) if agent.monitoring_type == "workstation": WinUpdatePolicy(agent=agent, run_time_days=[5, 6]).save() else: WinUpdatePolicy(agent=agent).save() reload_nats() # create agent install audit record AuditLog.objects.create( username=request.user, agent=agent.hostname, object_type="agent", action="agent_install", message=f"{request.user} installed new agent {agent.hostname}", after_value=Agent.serialize(agent), ) return Response( { "pk": agent.pk, "saltid": f"{agent.hostname}-{agent.pk}", "token": token.key, } )
def get_agents_by_html(source_code): # care only about 1st page of results tree = html.fromstring(source_code) rows = tree.xpath('//tbody/tr') agents = [] for row in rows: agents.append( Agent(reg_number=row.xpath('td/a/text()'), name=row.xpath('td/span/text()'))) logger.info("get %d agents." % len(agents)) if len(agents) > 0: logger.info(agents[0]) return agents
def send_agent_update_task(pks, version): assert isinstance(pks, list) ver = version.split("winagent-v")[1] q = Agent.objects.only("pk").filter(pk__in=pks) agents = [ i for i in q if pyver.parse(i.version) < pyver.parse(ver) and i.status == "online" ] if agents: for agent in agents: agent.update_pending = True agent.save(update_fields=["update_pending"]) minions = [i.salt_id for i in agents] r = Agent.get_github_versions() git_versions = r["versions"] data = r["data"] # full response from github versions = {} for i, release in enumerate(data): versions[i] = release["name"] key = [k for k, v in versions.items() if v == version][0] download_url = data[key]["assets"][0]["browser_download_url"] # split into chunks to not overload salt chunks = (minions[i : i + 30] for i in range(0, len(minions), 30)) for chunk in chunks: r = Agent.salt_batch_async( minions=chunk, func="win_agent.do_agent_update", kwargs={"version": ver, "url": download_url}, ) sleep(5)
def uninstall_agent_task(salt_id): attempts = 0 error = False while 1: try: r = Agent.salt_api_cmd(hostname=salt_id, timeout=10, func="win_agent.uninstall_agent") ret = r.json()["return"][0][salt_id] except Exception: attempts += 1 else: if ret != "ok": attempts += 1 else: attempts = 0 if attempts >= 10: error = True break elif attempts == 0: break if error: logger.error(f"{salt_id} uninstall failed") else: logger.info(f"{salt_id} was successfully uninstalled") try: r = requests.post( f"http://{settings.SALT_HOST}:8123/run", json=[{ "client": "wheel", "fun": "key.delete", "match": salt_id, "username": settings.SALT_USERNAME, "password": settings.SALT_PASSWORD, "eauth": "pam", }], timeout=30, ) except Exception: logger.error(f"{salt_id} unable to remove salt-key") return "ok"
def get_agent_by_url(url): logger.info("get agent by url, url = %s" % url) try: source_code = get_page(url) tree = html.fromstring(source_code.text) # Get detail information about the agent summary1 = tostring(tree.cssselect('div.summary1')[0]) summary2 = tostring(tree.cssselect('div.summary2')[0]) name = html.fromstring(summary1).cssselect('h1.summarytitle a')[0].text.encode('ascii', 'ignore').decode('ascii').strip() try: estate_name = html.fromstring(summary1).cssselect('div.summary1 span.greytext')[0].text.strip() except IndexError: estate_name = None phone_number = html.fromstring(summary2).cssselect('span.orangebold')[0].text.strip() cea = html.fromstring(summary2).cssselect('div.top15 a') try: lic_number = cea[0].text.strip() except IndexError: lic_number = None try: reg_number = cea[1].text.strip() except IndexError: reg_number = None agent = Agent(name=name, estate_name=estate_name, phone_number=phone_number, lic_number=lic_number, reg_number=reg_number) logger.info(agent) return agent except requests.exceptions.HTTPError as e: logger.error("HTTPError: " + str(e)) return None except requests.exceptions.ConnectionError as e: logger.error(str(e)) return None except IndexError as e: logger.error(str(e)) with open("error_page.html", "w") as f: f.write(source_code.text.encode('utf-8')) return None except AttributeError as e: logger.error(str(e)) return None
def cancel_pending_action_task(data): if data["action_type"] == "schedreboot" and data["status"] == "pending": from agents.models import Agent task_name = data["details"]["taskname"] try: resp = Agent.salt_api_cmd( hostname=data["salt_id"], timeout=45, func="task.delete_task", arg=[f"name={task_name}"], ) except Exception as e: logger.error( f"Unable to contact {data['salt_id']}. Task {task_name} will need to cancelled manually." ) else: logger.info(f"Scheduled reboot cancellled: {resp.json()}") return "ok"
def signup_agent(request): if not request.user.is_authenticated(): if request.method == 'POST': form = SignUpAgentForm(request.POST) if form.is_valid(): user = form.save() user.save() password = form.cleaned_data.get('password1') user = authenticate(username=user.username, password=password) agent = Agent() agent.agent_id = user agent.total_transaction = 0 agent.save() auth_login(request, user) return HttpResponseRedirect(reverse('catalog:index')) else: return render(request, 'del3/signupagent.html', {'form': form}) else: form = SignUpAgentForm() return render(request, 'del3/signupagent.html', {'form': form}) else: return HttpResponseRedirect(reverse('index'))
def update_agent_task(pk, version): agent = Agent.objects.get(pk=pk) errors = [] file = f"/srv/salt/scripts/{version}.exe" ver = version.split("winagent-v")[1] # download the release from github if the file doesn't already exist in /srv if not os.path.exists(file): r = Agent.get_github_versions() git_versions = r["versions"] data = r["data"] # full response from github versions = {} for i, release in enumerate(data): versions[i] = release["name"] key = [k for k, v in versions.items() if v == version][0] download_url = data[key]["assets"][0]["browser_download_url"] p = subprocess.run(["wget", download_url, "-O", file], capture_output=True) app_dir = "C:\\Program Files\\TacticalAgent" temp_dir = "C:\\Windows\\Temp" logger.info( f"{agent.hostname} is attempting update from version {agent.version} to {ver}" ) # send the release to the agent r = agent.salt_api_cmd( hostname=agent.salt_id, timeout=300, func="cp.get_file", arg=[f"salt://scripts/{version}.exe", temp_dir], ) # success return example: {'return': [{'HOSTNAME': 'C:\\Windows\\Temp\\winagent-v0.1.12.exe'}]} # error return example: {'return': [{'HOSTNAME': ''}]} if not r.json()["return"][0][agent.salt_id]: agent.is_updating = False agent.save(update_fields=["is_updating"]) logger.error( f"{agent.hostname} update failed to version {ver} (unable to copy installer)" ) return f"{agent.hostname} update failed to version {ver} (unable to copy installer)" services = ( "tacticalagent", "checkrunner", ) for svc in services: r = service_action(agent.salt_id, "stop", svc) # returns non 0 if error if r.json()["return"][0][agent.salt_id]["retcode"]: errors.append(f"failed to stop {svc}") logger.error( f"{agent.hostname} was unable to stop service {svc}. Update cancelled" ) # start the services if some of them failed to stop, then don't continue if errors: agent.is_updating = False agent.save(update_fields=["is_updating"]) for svc in services: service_action(agent.salt_id, "start", svc) return "stopping services failed. started again" # install the update # success respose example: {'return': [{'HOSTNAME': {'retcode': 0, 'stderr': '', 'stdout': '', 'pid': 3452}}]} # error response example: {'return': [{'HOSTNAME': 'The minion function caused an exception: Traceback...'}]} try: r = agent.salt_api_cmd( hostname=agent.salt_id, timeout=200, func="cmd.script", arg=f"{temp_dir}\\{version}.exe", kwargs={"args": "/VERYSILENT /SUPPRESSMSGBOXES"}, ) except Exception: agent.is_updating = False agent.save(update_fields=["is_updating"]) return ( f"TIMEOUT: failed to run inno setup on {agent.hostname} for version {ver}" ) if "minion function caused an exception" in r.json()["return"][0][ agent.salt_id]: agent.is_updating = False agent.save(update_fields=["is_updating"]) return ( f"EXCEPTION: failed to run inno setup on {agent.hostname} for version {ver}" ) if r.json()["return"][0][agent.salt_id]["retcode"]: agent.is_updating = False agent.save(update_fields=["is_updating"]) logger.error( f"failed to run inno setup on {agent.hostname} for version {ver}") return f"failed to run inno setup on {agent.hostname} for version {ver}" # update the version in the agent's local database r = agent.salt_api_cmd( hostname=agent.salt_id, timeout=45, func="sqlite3.modify", arg=[ "C:\\Program Files\\TacticalAgent\\agentdb.db", f'UPDATE agentstorage SET version = "{ver}"', ], ) # success return example: {'return': [{'FSV': True}]} # error return example: {'return': [{'HOSTNAME': 'The minion function caused an exception: Traceback...'}]} sql_ret = r.json()["return"][0][agent.salt_id] if not isinstance(sql_ret, bool) and isinstance(sql_ret, str): if "minion function caused an exception" in sql_ret: logger.error(f"failed to update {agent.hostname} local database") if not sql_ret: logger.error( f"failed to update {agent.hostname} local database to version {ver}" ) # start the services for svc in services: service_action(agent.salt_id, "start", svc) agent.is_updating = False agent.save(update_fields=["is_updating"]) logger.info(f"{agent.hostname} was successfully updated to version {ver}") return f"{agent.hostname} was successfully updated to version {ver}"
def patch(self, request): """ Creates the agent """ if Agent.objects.filter(agent_id=request.data["agent_id"]).exists(): return notify_error( "Agent already exists. Remove old agent first if trying to re-install" ) client = get_object_or_404(Client, pk=int(request.data["client"])) site = get_object_or_404(Site, pk=int(request.data["site"])) agent = Agent( agent_id=request.data["agent_id"], hostname=request.data["hostname"], client=client.client, site=site.site, monitoring_type=request.data["monitoring_type"], description=request.data["description"], mesh_node_id=request.data["mesh_node_id"], last_seen=djangotime.now(), ) agent.save() agent.salt_id = f"{agent.hostname}-{agent.pk}" agent.save(update_fields=["salt_id"]) if agent.monitoring_type == "workstation": WinUpdatePolicy(agent=agent, run_time_days=[5, 6]).save() else: WinUpdatePolicy(agent=agent).save() # Generate policies for new agent agent.generate_checks_from_policies() agent.generate_tasks_from_policies() return Response({"pk": agent.pk, "saltid": f"{agent.hostname}-{agent.pk}"})
'name': 'CMIS Rest API', 'is_active': True, 'script': 'agents.lib.cmis_rest_agent.CmisRestAgent', 'description': ( 'Tests availability and performance of Alfresco ' 'CMIS Rest API endpoints.' ), }, { 'name': 'JMXDump', 'is_active': True, 'script': 'agents.lib.jmxdump_agent.JmxDumpAgent', 'description': ( 'Stores all settings of a running Alfresco system ' 'for archival purposes.' ), }, ] if __name__ == '__main__': for agent in agent_list: a = Agent() for k, v in agent.items(): setattr(a, k, v) try: a.save() except IntegrityError: print('Agent already exists.')
def new_method(handler, request, *args, **kwargs): if request.POST.get('crypto_v1', None): from agents.CryptoLib_v1 import crypto, CryptoLib, aggregatorKey, aes_decrypt else: from agents.CryptoLib import crypto, CryptoLib, aggregatorKey, aes_decrypt aes_key = None agent = None key = request.POST.get('key', None) message = request.POST.get('msg', None) agent_id = request.POST.get('agentID', None) # If key is not provided, then agent_id must be present. if key is None: assert agent_id agent = Agent.get_agent(agent_id) aes_key = agent.AESKey else: aes_key = crypto.decodeRSAPrivateKey(key, aggregatorKey) aes_key, msg_obj = aes_decrypt(message, self.message_type, aes_key=aes_key) # get software version information # TODO: CACHE the desktop and mobile latest versions so we don't need # to reach out to the datastore to get that upon every api request. software_version = None if agent is not None: if agent.agent_type == 'DESKTOP': software_version = DesktopAgentVersion.getLastVersionNo() elif agent.agent_type == 'MOBILE': software_version = MobileAgentVersion.getLastVersionNo() else: logging.error("Unknown agent type '%s' - Agent %s" % \ ( agent.agent_type, agent)) # get lastest test id # TODO: Cache the latest test version to avoid going to datastore on # every api request test_version = Test.get_test_version(agent) response = None if self.response_type is not None: response = self.response_type() if getattr(response, "header", False): response.header.currentVersionNo = software_version.version if software_version is not None else 0 response.header.currentTestVersionNo = test_version response = method(handler, request, msg_obj, aes_key, agent, software_version, test_version, response, *args, **kwargs) # Need to encrypt and return the response now return crypto.encodeAES(response, aes_key)
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) has_old_config = True rmm_conf = "/etc/nginx/sites-available/rmm.conf" if os.path.exists(rmm_conf): with open(rmm_conf) as f: for line in f: if "location" and "builtin" in line: has_old_config = False break if has_old_config: new_conf = """ location /builtin/ { internal; add_header "Access-Control-Allow-Origin" "https://rmm.yourwebsite.com"; alias /srv/salt/scripts/; } """ after_this = """ location /saltscripts/ { internal; add_header "Access-Control-Allow-Origin" "https://rmm.yourwebsite.com"; alias /srv/salt/scripts/userdefined/; } """ self.stdout.write(self.style.ERROR("*" * 100)) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "WARNING: A recent update requires you to manually edit your nginx config" )) self.stdout.write("\n") self.stdout.write( self.style.ERROR("Please add the following location block to ") + self.style.WARNING(rmm_conf)) self.stdout.write(self.style.SUCCESS(new_conf)) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "You can paste the above right after the following block that's already in your nginx config:" )) self.stdout.write(after_this) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "Make sure to replace rmm.yourwebsite.com with your domain" )) self.stdout.write( self.style.ERROR( "After editing, restart nginx with the command ") + self.style.WARNING("sudo systemctl restart nginx")) self.stdout.write("\n") self.stdout.write(self.style.ERROR("*" * 100)) input("Press Enter to continue...") # install go if not os.path.exists("/usr/local/rmmgo/"): self.stdout.write(self.style.SUCCESS("Installing golang")) subprocess.run("sudo mkdir -p /usr/local/rmmgo", shell=True) tmpdir = tempfile.mkdtemp() r = subprocess.run( f"wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P {tmpdir}", shell=True, ) gotar = os.path.join(tmpdir, "go1.15.linux-amd64.tar.gz") subprocess.run(f"tar -xzf {gotar} -C {tmpdir}", shell=True) gofolder = os.path.join(tmpdir, "go") subprocess.run(f"sudo mv {gofolder} /usr/local/rmmgo/", shell=True) shutil.rmtree(tmpdir)
def handle(self, *args, **kwargs): if not os.path.exists("/usr/local/bin/goversioninfo"): self.stdout.write(self.style.ERROR("*" * 100)) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "ERROR: New update script available. Delete this one and re-download." )) self.stdout.write("\n") sys.exit(1) # 10-16-2020 changed the type of the agent's 'disks' model field # from a dict of dicts, to a list of disks in the golang agent # the following will convert dicts to lists for agent's still on the python agent agents = Agent.objects.all() for agent in agents: if agent.disks is not None and isinstance(agent.disks, dict): new = [] for k, v in agent.disks.items(): new.append(v) agent.disks = new agent.save(update_fields=["disks"]) self.stdout.write( self.style.SUCCESS(f"Migrated disks on {agent.hostname}")) # sync modules. split into chunks of 60 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 + 60] for i in range(0, len(online), 60)) 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) has_old_config = True rmm_conf = "/etc/nginx/sites-available/rmm.conf" if os.path.exists(rmm_conf): with open(rmm_conf) as f: for line in f: if "location" and "builtin" in line: has_old_config = False break if has_old_config: new_conf = """ location /builtin/ { internal; add_header "Access-Control-Allow-Origin" "https://rmm.yourwebsite.com"; alias /srv/salt/scripts/; } """ after_this = """ location /saltscripts/ { internal; add_header "Access-Control-Allow-Origin" "https://rmm.yourwebsite.com"; alias /srv/salt/scripts/userdefined/; } """ self.stdout.write(self.style.ERROR("*" * 100)) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "WARNING: A recent update requires you to manually edit your nginx config" )) self.stdout.write("\n") self.stdout.write( self.style.ERROR("Please add the following location block to ") + self.style.WARNING(rmm_conf)) self.stdout.write(self.style.SUCCESS(new_conf)) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "You can paste the above right after the following block that's already in your nginx config:" )) self.stdout.write(after_this) self.stdout.write("\n") self.stdout.write( self.style.ERROR( "Make sure to replace rmm.yourwebsite.com with your domain" )) self.stdout.write( self.style.ERROR( "After editing, restart nginx with the command ") + self.style.WARNING("sudo systemctl restart nginx")) self.stdout.write("\n") self.stdout.write(self.style.ERROR("*" * 100)) input("Press Enter to continue...") # install go if not os.path.exists("/usr/local/rmmgo/"): self.stdout.write(self.style.SUCCESS("Installing golang")) subprocess.run("sudo mkdir -p /usr/local/rmmgo", shell=True) tmpdir = tempfile.mkdtemp() r = subprocess.run( f"wget https://golang.org/dl/go1.15.linux-amd64.tar.gz -P {tmpdir}", shell=True, ) gotar = os.path.join(tmpdir, "go1.15.linux-amd64.tar.gz") subprocess.run(f"tar -xzf {gotar} -C {tmpdir}", shell=True) gofolder = os.path.join(tmpdir, "go") subprocess.run(f"sudo mv {gofolder} /usr/local/rmmgo/", shell=True) shutil.rmtree(tmpdir) # load community scripts into the db Script.load_community_scripts()