def install_agent(self, package_path): checksum = utils.get_checksum(package_path, self.get_checksum_dir()) if not utils.check_file(package_path, checksum): LOG.debug("check downloaded package failed, removing %s", package_path) os.remove(package_path) utils.remove_checksum(package_path, self.get_checksum_dir()) return None dirname = utils.get_file_name_without_extension(package_path) agent_dir = '%s\%s' % (self.get_install_dir(), dirname) tmp_dir = '%s\%s' % (self.get_tmp_dir(), dirname) try: if utils.unzip(package_path, tmp_dir): tmp_name = os.listdir(tmp_dir)[0] tmp_path = '%s\%s' % (tmp_dir, tmp_name) ren_path = '%s\%s' % (tmp_dir, dirname) if os.system('ren "%s" "%s"' % (tmp_path, dirname)) != 0: return None if os.system('move "%s" "%s"' % (ren_path, self.get_install_dir())) != 0: return None else: return None finally: if os.path.isdir(tmp_dir): os.system('rd /s /q "%s"' % tmp_dir) installer = Installer(agent_dir, self.recycle_queue) installer.install() return agent_dir
def install_agent(self, package_path): checksum = utils.get_checksum(package_path, self.get_checksum_dir()) if not utils.check_file(package_path, checksum): LOG.debug("check downloaded package failed, removing %s", package_path) os.remove(package_path) utils.remove_checksum(package_path, self.get_checksum_dir()) return None dirname = utils.get_file_name_without_extension(package_path) agent_dir = '%s/%s' % (self.get_install_dir(), dirname) r = os.system('mkdir -p %s && tar xzf %s -C %s --strip-components 1' % (agent_dir, package_path, agent_dir)) != 0 if r != 0: LOG.debug('decompress failed, %d', r) os.remove(package_path) os.rmdir(agent_dir) return None else: LOG.debug('decompress success') installer = Installer(agent_dir, self.recycle_queue) installer.install() return agent_dir
def create_db(self) -> None: """Create database, collect data and insert them.""" print("creating tables...") Base.metadata.create_all(self.engine) print("tables created") print("uploading data from api...") collector = Collector() data = collector.collect() cleaner = Cleaner() data_cleaned = cleaner.cleaner(data) print("upload successful") print("adding data to tables...") installer = Installer() installer.install(data_cleaned, self.engine) print("database install with success")
def runInstaller(options, config): try: sys.path.insert(0, options.installer_path) from installer import Installer from packageselector import PackageSelector except: raise ImportError('Installer path incorrect!') config["pkg_to_rpm_map_file"] = options.pkg_to_rpm_map_file # Check the installation type option_list_json = Utils.jsonread(options.package_list_file) options_sorted = option_list_json.items() packages = [] if 'type' in config: for install_option in options_sorted: if install_option[0] == config['type']: packages = PackageSelector.get_packages_to_install(install_option[1]['packagelist_file'], options.generated_data_path) break else: if 'packagelist_file' in config: packages = PackageSelector.get_packages_to_install(config['packagelist_file'], options.generated_data_path) if 'additional_packages' in config: packages = packages.extend(config['additional_packages']) config['packages'] = packages # Run the installer package_installer = Installer(config, rpm_path=options.rpm_path, log_path=options.log_path, log_level=options.log_level) return package_installer.install(None)
def install(self, params): installer = None installer = Installer(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path, self.log_level) return installer.install(params)
def install(opts, conf): dotfiles = conf.get_dotfiles(opts['profile']) if dotfiles == []: LOG.err('no dotfiles defined for this profile (\"%s\")' % (str(opts['profile']))) return False t = Templategen(base=opts['dotpath']) inst = Installer(create=opts['create'], backup=opts['backup'], dry=opts['dry'], safe=opts['safe'], base=opts['dotpath'], diff=opts['installdiff'], quiet=opts['quiet']) installed = [] for dotfile in dotfiles: if hasattr(dotfile, 'link') and dotfile.link: r = inst.link(dotfile.src, dotfile.dst) else: r = inst.install(t, opts['profile'], dotfile.src, dotfile.dst) if len(r) > 0 and len(dotfile.actions) > 0: # execute action for action in dotfile.actions: action.execute() installed.extend(r) LOG.log('\n%u dotfile(s) installed.' % (len(installed))) return True
def onOK(self, event): parent = self.GetParent() i = self.box.GetSelection() ext = "" if i == 0: ext = "zip" elif i == 1: ext = "dwa" elif i == 2: ext = "mova" elif i == 3: ext = "tmx" elif i == 4: ext == "dz" from installer import Installer installer = Installer(parent, parent.app.config) installer.install(self.filePath, ext) self.Destroy()
def OnApply(self, event): self.log.AppendText('please wait...\n') for i in range(len(db[0])): if self.list.IsChecked(i): if len(db[0][i]) == 6: pass else: if len(db[0][i]) == 5: pass else: self.log.AppendText('downloading ' + str(db[0][i]) + '...\n') try: Downloader.dl(db[0][i]) except: self.log.AppendText('failed\n') self.log.AppendText('installing ' + str(db[0][i]) + '...\n') try: Installer.install(db[0][i]) except: self.log.AppendText('failed\n') else: if len(db[0][i]) == 6: self.log.AppendText('uninstalling ' + str(db[0][i]) + '...\n') try: Installer.uninstall(db[0][i]) except: self.log.AppendText('failed\n') self.log.AppendText('refreshing database...\n') global db db = Database.build() self.log.AppendText('all done\n')
def main(): instr = '' while instr != 'exit': db = Database.build() instr = input("\ntype mod ID (e.g. '3') or 'exit'\n") try: if instr != 'exit': inp = int(instr) dbq = db[inp] print("choose instruction (e.g. '1')") if 'installed' in dbq: inp2 = int(input("'0' - uninstall\n'1' - cancel\n")) if inp2 == 0: Installer.uninstall(dbq) elif inp2 == 1: pass elif 'downloaded' in dbq: inp2 = int( input("'0' - install\n'1' - remove\n'2' - cancel\n")) if inp2 == 0: Installer.install(dbq) elif inp2 == 1: Downloader.rm(dbq) elif inp2 == 2: pass else: inp2 = int(input("'0' - download\n'1' - cancel\n")) if inp2 == 0: Downloader.dl(dbq) elif inp2 == 1: pass elif instr == 'exit': print('exiting...') break except ValueError: print('valid ID please') continue
def main(): instr = '' while instr != 'exit': db = Database.build() instr = input("\ntype mod ID (e.g. '3') or 'exit'\n") try: if instr != 'exit': inp = int(instr) dbq = db[inp] print ("choose instruction (e.g. '1')") if 'installed' in dbq: inp2 = int(input("'0' - uninstall\n'1' - cancel\n")) if inp2 == 0: Installer.uninstall(dbq) elif inp2 == 1: pass elif 'downloaded' in dbq: inp2 = int(input("'0' - install\n'1' - remove\n'2' - cancel\n")) if inp2 == 0: Installer.install(dbq) elif inp2 == 1: Downloader.rm(dbq) elif inp2 == 2: pass else: inp2 = int(input("'0' - download\n'1' - cancel\n")) if inp2 == 0: Downloader.dl(dbq) elif inp2 == 1: pass elif instr == 'exit': print ('exiting...') break except ValueError: print ('valid ID please') continue
def cli_install(): parser = argparse.ArgumentParser(description='Create a new Launchable Application') parser.add_argument('prefix', # metavar = 'prefix', type=str, nargs='?', help='Prefix name. used to identify the icon file and the launch script eg. pychron' ) parser.add_argument('name', # metavar = 'name', type=str, nargs='?', help='Name of the application bundle eg. Pychron') parser.add_argument('--icon', type=str, nargs='?', help='icon file name') args = parser.parse_args() i = Installer(args.prefix, args.name, args.icon) root = os.path.join(os.path.expanduser('~'), 'Programming', 'mercurial', 'pychron_beta' ) i.install(root)
def install(upgrade: bool = False, version: str = typer.Argument(None)): """安装Graia,--upgrade 升级Graia,可指定版本""" installer = Installer() if upgrade: if 0 != installer.upgrade(): logging.error(u'升级失败') sys.exit(1) logging.info(u'升级成功') else: if 0 != installer.install(version=version): logging.error(u'安装失败') sys.exit(1) logging.info(u'安装成功')
def OnApply(self, event): self.log.AppendText("please wait...\n") for i in range(len(db[0])): if self.list.IsChecked(i): if len(db[0][i]) == 6: pass else: if len(db[0][i]) == 5: pass else: self.log.AppendText("downloading " + str(db[0][i]) + "...\n") try: Downloader.dl(db[0][i]) except: self.log.AppendText("failed\n") self.log.AppendText("installing " + str(db[0][i]) + "...\n") try: Installer.install(db[0][i]) except: self.log.AppendText("failed\n") else: if len(db[0][i]) == 6: self.log.AppendText("uninstalling " + str(db[0][i]) + "...\n") try: Installer.uninstall(db[0][i]) except: self.log.AppendText("failed\n") self.log.AppendText("refreshing database...\n") global db db = Database.build() self.log.AppendText("all done\n")
packages = PackageSelector.get_packages_to_install(options_sorted, config['type'], options.output_data_path) config['packages'] = packages if (os.path.isdir(options.working_directory)): process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() process = subprocess.Popen(['mkdir', '-p', os.path.join(options.working_directory, "photon-chroot")]) retval = process.wait() config['working_directory'] = options.working_directory # Run the installer package_installer = Installer(config, rpm_path = options.rpm_path, log_path = options.log_path) package_installer.install(None) # Making the iso if needed if options.iso_path: rpm_list = " ".join(create_rpm_list_to_be_copied_to_iso(options.pkg_to_rpm_map_file, options.pkg_to_be_copied_conf_file, 1, options.output_data_path)) files_to_copy = " ".join(create_additional_file_list_to_copy_in_iso(os.path.abspath(options.stage_path), options.package_list_file)) live_cd = get_live_cd_status_string(options.package_list_file) process = subprocess.Popen(['./mk-install-iso.sh', '-w', options.working_directory, options.iso_path, options.rpm_path, options.package_list_file, rpm_list, options.stage_path, files_to_copy, live_cd, options.json_data_path]) retval = process.wait() if options.debug_iso_path: debug_rpm_list = create_rpm_list_to_be_copied_to_iso(options.pkg_to_rpm_map_file, options.pkg_to_be_copied_conf_file, 2, options.output_data_path) make_debug_iso(options.working_directory, options.debug_iso_path, debug_rpm_list) # Cleaning up for vmdk if 'vmdk_install' in config and config['vmdk_install']:
if not proceed: sys.exit(0) if (os.path.isdir(options.working_directory)): process = subprocess.Popen(['rm', '-rf', options.working_directory]) retval = process.wait() else: process = subprocess.Popen(['mkdir', '-p', options.working_directory]) retval = process.wait() config['working_directory'] = options.working_directory # Run the installer package_installer = Installer( config, local_install=not (options.iso_path or options.vmdk_path)) package_installer.install(None) # Making the iso if needed if config['iso_system']: process = subprocess.Popen([ './mk-install-iso.sh', '-w', options.working_directory, options.iso_path, options.tools_path ]) retval = process.wait() # Cleaning up for vmdk if 'vmdk_install' in config and config['vmdk_install']: process = subprocess.Popen( ['./mk-clean-vmdk.sh', config['disk']['disk']]) process.wait()
exit(1) # Initialize python confparser and read config config = configparser.ConfigParser() config.read(CONFPATH) config.sections() # Read sections from the configuration file interfaces = config["Interfaces"]["interfaces"].split(",") NetworkControllers = config["NetworkControllers"]["controllers"] ufwHandled = config["Ufw"]["handled"] if args.install: # Install scutum into system avalon.info('Start Installing SCUTUM...') installer.install() print('\n' + avalon.FM.BD, end='') avalon.info('Installation Complete!') avalon.info('SCUTUM service is now enabled on system startup') avalon.info('You can now control it with systemd') avalon.info("You can also control it manually with \"scutum\" command") exit(0) elif args.uninstall: # Removes scutum completely from the system # Note that the configuration file will be removed too if avalon.ask('Removal Confirm: ', False): installer.removeScutum() else: avalon.warning('Removal Canceled') exit(0) elif args.reset:
from installer import Installer install_dir = r'E:\Tutorial\Python\steam_workshop_downloader\test\testing' craft_id_file = r'E:\Tutorial\Python\steam_workshop_downloader\crafts.txt' installer = Installer(install_dir) with open(craft_id_file, 'r') as crafts: for craft_id in crafts: print(f'getting {craft_id}') installer.install(craft_id.strip()) print('Done')
cache = Cache() logger.info('Start data receiver') receiver = Receiver(cache) receiver.start() logger.info('Plant collectors') nodes = topo.list_nodes() installer = Installer(cfg['node']) for node in nodes : node_ipaddress = topo.get_node_ipaddress(node) #print 'node_ipaddress = ',node_ipaddress logger.info('Planting collector to ' + node_ipaddress) if node_ipaddress : installer.set_trust(node_ipaddress) installer.install(node_ipaddress) logger.info('Start auto-scaling checker') checker = Checker(cache, topo, installer, cfg['policy']) checker.start() logger.info('Start api server') http_server = HTTPServer(('', 8001), myHttpHandler) http_server.serve_forever()
class Controller: def __init__(self, configs): self.configs = configs self.installer = None self.agent_holder = None self.need_download = False self.download_path = None self.checksum = None self.need_update = False self.agent_abnormal = False self.main_loop_lock = False self.scheduler = None def start(self): LOG.debug('controller started') self.scheduler = BlockingScheduler() self.scheduler.add_job(self.update_check, trigger='interval', seconds=self.configs['update_check_period'], next_run_time=datetime.datetime.now()) self.scheduler.add_job(self.main_job, trigger='cron', minute='*/%d' % self.configs['main_loop_period_minute'], second='0') self.scheduler.start() LOG.debug('controller stopped') def stop(self): self.stop_agent() if self.scheduler: self.scheduler.shutdown() def main_job(self): if self.main_loop_lock: return self.main_loop_lock = True self.health_check() try: if self.need_update: LOG.info('********************* udpate') self.stop_agent() self.uninstall_agent() package_path = self.download_agent() if package_path: LOG.info('********************* udpate install') agent_dir = self.install_agent(package_path) LOG.info('********************* udpate start') self.start_agent(agent_dir) elif self.agent_abnormal: LOG.info('********************* restart') self.stop_agent() agent_dir = self.get_latest_install_folder() if not agent_dir: package_path = self.get_latest_install_package() if package_path: LOG.info('********************* restart install') agent_dir = self.install_agent(package_path) else: return LOG.info('********************* restart start') self.start_agent(agent_dir) except Exception as e: pass finally: self.main_loop_lock = False def install_agent(self, package_path): dirname = utils.get_file_name_without_extension(package_path) agent_dir = '%s/%s' % (self.get_install_dir(), dirname) r = os.system('mkdir -p %s && tar xzf %s -C %s --strip-components 1' % (agent_dir, package_path, agent_dir)) != 0 if r != 0: LOG.debug('decompress failed, %d', r) os.remove(package_path) os.rmdir(agent_dir) return None else: LOG.debug('decompress success') self.installer = Installer(agent_dir) self.installer.install() return agent_dir def uninstall_agent(self, agent_dir=None): if self.installer is None: if agent_dir and os.path.isdir(agent_dir): self.installer = Installer(agent_dir) else: return self.installer.uninstall() def start_agent(self, agent_dir): if agent_dir: self.agent_holder = AgentHolder(agent_dir) agent_process_name = self.agent_holder.start() self.save_process_name_to_disk(agent_process_name) self.agent_abnormal = False def stop_agent(self): if self.agent_holder is None: agent_process_name = self.get_process_name_from_disk() if agent_process_name: os.popen('killall -g %s' % agent_process_name) self.save_process_name_to_disk() else: self.agent_holder.stop() self.save_process_name_to_disk() def health_check(self): if self.agent_holder: LOG.info('.............. last check before: %d seconds' % (int(time.time()) - self.agent_holder.last_check_time)) if int(time.time()) - self.agent_holder.last_check_time > self.configs['health_check_threshold']: self.agent_abnormal = True else: LOG.info('.............. agent_holder is None') self.agent_abnormal = True def update_check(self): if self.check_new_version(): self.need_download = True self.need_update = True else: self.need_download = False download_version = int(utils.get_version_from_path(self.get_latest_install_package())) install_version = int(utils.get_version_from_path(self.get_latest_install_folder())) if download_version > install_version: self.need_update = True def check_new_version(self): try: url = '%s/linux/latest' % self.configs['update_server_url'] req = urllib2.Request(url) response = urllib2.urlopen(req, timeout=3) response_json = json.loads(response.read()) new_version = response_json['version'] new_path = response_json['path'] checksum = response_json['checksum'] # print new_version # print new_path version = int(utils.get_version_from_path(self.get_latest_install_package())) if new_version > version: self.download_path = new_path self.checksum = checksum return True else: return False except Exception as e: LOG.exception('check new version failed, err: %s', e) return False def download_agent(self): if self.need_download: if self.download_path and self.checksum: url = '%s/%s' % (self.configs['update_server_url'], self.download_path) f = urllib2.urlopen(url) package_name = utils.get_file_name(url) package_path = '%s/%s' % (self.get_download_dir(), package_name) with open(package_path, 'wb') as target: target.write(f.read()) if not utils.check_file(package_path, self.checksum): os.remove(package_path) LOG.debug('checksum failed, removing %s', package_name) return else: LOG.debug('download %s success', package_name) # src_url = '%s/agent_linux_2.tar.gz' % self.get_tmp_dir() # log = os.popen('mv %s %s/' % (src_url, self.get_download_dir())) # LOG.debug(log) self.need_download = False self.download_path = None self.checksum = None self.need_update = False else: self.need_update = False return self.get_latest_install_package() def get_install_dir(self): path = os.path.join(self.configs['home_dir'], 'install_folders') if not os.path.isdir(path): os.mkdir(path) return path def get_download_dir(self): path = os.path.join(self.configs['home_dir'], 'download') if not os.path.isdir(path): os.mkdir(path) return path def get_latest_install_folder(self): latest_version = 0 latest_folder_path = None if not os.path.isdir(self.get_install_dir()): return None for folder in os.listdir(self.get_install_dir()): version = utils.get_version(folder) if version.isdigit() and int(version) > latest_version: latest_version = int(version) latest_folder_path = folder if latest_folder_path: return '%s/%s' % (self.get_install_dir(), latest_folder_path) else: return None def get_latest_install_package(self): latest_version = 0 latest_package = None if not os.path.isdir(self.get_download_dir()): return None for package in os.listdir(self.get_download_dir()): version = utils.get_version(package) if version.isdigit() and int(version) > latest_version: latest_version = int(version) latest_package = package if latest_package: return '%s/%s' % (self.get_download_dir(), latest_package) else: return None # for debug def get_tmp_dir(self): return os.path.join(self.configs['home_dir'], 'tmp') def save_process_name_to_disk(self, process_name=''): with open('%s/process_name' % self.configs['home_dir'], 'w+') as f: f.truncate() f.write(process_name) def get_process_name_from_disk(self): with open('%s/process_name' % self.configs['home_dir'], 'a+') as f: return f.read()
def main(): parser = argparse.ArgumentParser(description="Tactical RMM Agent") parser.add_argument("-m", action="store", dest="mode", type=str) parser.add_argument("-p", action="store", dest="taskpk", type=int) parser.add_argument("--api", action="store", dest="api_url", type=str) parser.add_argument("--client-id", action="store", dest="client_id", type=int) parser.add_argument("--site-id", action="store", dest="site_id", type=int) parser.add_argument( "--desc", action="store", dest="agent_desc", type=str, default=socket.gethostname(), ) parser.add_argument( "--agent-type", action="store", dest="agent_type", type=str, default="server", choices=["server", "workstation"], ) parser.add_argument( "-l", "--log", action="store", dest="log_level", type=str, default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], ) parser.add_argument( "--logto", action="store", dest="log_to", type=str, default="file", choices=["file", "stdout"], ) parser.add_argument( "--power", action="store", dest="power", type=int, default=0, choices=[0, 1], ) parser.add_argument( "--rdp", action="store", dest="rdp", type=int, default=0, choices=[0, 1], ) parser.add_argument( "--ping", action="store", dest="ping", type=int, default=0, choices=[0, 1], ) parser.add_argument("--auth", action="store", dest="auth_token", type=str) parser.add_argument("--version", action="store_true") parser.add_argument( "--local-salt", action="store", dest="local_salt", type=str, help= r'The full path to the salt-minion executable e.g. "C:\\temp\\salt-minion-setup.exe"', ) parser.add_argument( "--local-mesh", action="store", dest="local_mesh", type=str, help= r'The full path to the Mesh Agent executable e.g. "C:\\temp\\meshagent.exe"', ) args = parser.parse_args() if args.version: try: with open( os.path.join("C:\\Program Files\\TacticalAgent", "VERSION")) as f: ver = f.read().strip() print(ver) except Exception as e: print(f"Error getting version: {e}") elif args.mode == "install": if (not args.api_url or not args.client_id or not args.site_id or not args.auth_token): parser.print_help() sys.exit(1) if args.local_salt: if not os.path.exists(args.local_salt): parser.print_help() sys.stdout.flush() print(f"\nError: {args.local_salt} does not exist\n", flush=True) sys.exit(1) if not os.path.isfile(args.local_salt): parser.print_help() sys.stdout.flush() print( f"\nError: {args.local_salt} must be a file, not a folder.", flush=True, ) print( r'Make sure to use double backslashes for file paths, and double quotes e.g. "C:\\temp\\salt-minion-setup.exe"', flush=True, ) print("", flush=True) sys.exit(1) if args.local_mesh: if not os.path.exists(args.local_mesh): parser.print_help() sys.stdout.flush() print(f"\nError: {args.local_mesh} does not exist\n", flush=True) sys.exit(1) if not os.path.isfile(args.local_mesh): parser.print_help() sys.stdout.flush() print( f"\nError: {args.local_mesh} must be a file, not a folder.", flush=True, ) print( r'Make sure to use double backslashes for file paths, and double quotes e.g. "C:\\temp\\meshagent.exe"', flush=True, ) print("", flush=True) sys.exit(1) from installer import Installer installer = Installer( api_url=args.api_url, client_id=args.client_id, site_id=args.site_id, agent_desc=args.agent_desc, agent_type=args.agent_type, power=args.power, rdp=args.rdp, ping=args.ping, auth_token=args.auth_token, log_level=args.log_level, local_salt=args.local_salt, local_mesh=args.local_mesh, ) installer.install() elif args.mode == "winagentsvc": from winagentsvc import WinAgentSvc agent = WinAgentSvc(log_level=args.log_level, log_to=args.log_to) agent.run() elif args.mode == "checkrunner": from checkrunner import CheckRunner agent = CheckRunner(log_level=args.log_level, log_to=args.log_to) agent.run_forever() elif args.mode == "runchecks": from checkrunner import CheckRunner agent = CheckRunner(log_level=args.log_level, log_to=args.log_to) agent.run() elif args.mode == "winupdater": from winupdater import WinUpdater agent = WinUpdater(log_level=args.log_level, log_to=args.log_to) agent.install_all() elif args.mode == "patchscan": from winupdater import WinUpdater agent = WinUpdater(log_level=args.log_level, log_to=args.log_to) agent.trigger_patch_scan() elif args.mode == "taskrunner": from taskrunner import TaskRunner agent = TaskRunner(task_pk=args.taskpk, log_level=args.log_level, log_to=args.log_to) agent.run() elif args.mode == "updatesalt": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.fix_salt(by_time=False) agent.update_salt() elif args.mode == "fixsalt": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.fix_salt() elif args.mode == "fixmesh": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.fix_mesh() elif args.mode == "cleanup": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.fix_salt(by_time=False) agent.cleanup() elif args.mode == "recoversalt": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.recover_salt() elif args.mode == "recovermesh": from agent import WindowsAgent agent = WindowsAgent(log_level=args.log_level, log_to=args.log_to) agent.recover_mesh() else: import win32gui from agent import show_agent_status window = win32gui.GetForegroundWindow() if window == 0: # called from cli with no interactive desktop show_agent_status(window=None, gui=False) else: show_agent_status(window=window, gui=True)