scope startVMLister. static new TreeMap startVMLister_vms; static Lock startVMLister_lock = lock(); static O startVMLister_onChange; sclass #Data { long started; int port; S vmID; bool hidden; } static bool startVMLister() { S bot = "VM Lister."; if (!hasBot(bot)) { makeBot(bot, f startVMLister_answer); thread { startVMLister_scan(); } true; } false; } static S startVMLister_answer(S s) { lock startVMLister_lock; new Matches m; if "started vm * *" { int port = parseInt($1); startVMLister_vms.put(port, nu(startVMLister_Data, started := now(), +port, vmID := $2)); pcallF(startVMLister_onChange); ret "OK"; } if "hiding vm *" { startVMLister_Data vm = startVMLister_vms.get(parseInt($1)); if (vm != null) vm.hidden = true; pcallF(startVMLister_onChange); ret "OK"; } if "unhiding vm *" { startVMLister_Data vm = startVMLister_vms.get(parseInt($1)); if (vm != null) vm.hidden = false; pcallF(startVMLister_onChange); ret "OK"; } if "killing vm *" { startVMLister_vms.remove(parseInt($1)); pcallF(startVMLister_onChange); ret "OK"; } if "number of vms" ret lstr(startVMLister_vms); if "number of hidden vms" ret str(startVMLister_numHiddenVMs()); if "all vms struct" ret struct(values(startVMLister_vms)); if "scan vms" { startVMLister_scan(); ret "OK, found " + n(startVMLister_vms, "VM"); } null; } svoid startVMLister_scan ctex { lock startVMLister_lock; new TreeMap vms; for (DialogIO io : talkToAllVMs()) try { new startVMLister_Data vm; vm.port = io.getPort(); vm.vmID = io.ask("get vm id"); vm.hidden = isYes(io.ask("is hidden vm")); vm.started = parseLongOpt(io.ask("vm start date")); vms.put(vm.port, vm); } finally { io.close(); } copyMap(vms, startVMLister_vms); pcallF(startVMLister_onChange); } static int startVMLister_numVMs() { lock startVMLister_lock; ret l(startVMLister_vms); } static L #hiddenVMs() { lock startVMLister_lock; ret objectsWhere(values(startVMLister_vms), hidden := true); } static int #numHiddenVMs() { ret l(hiddenVMs()); } end scope