def bootstrap(command, conf, vars): """Import pickled database dump.""" appsupport_dir = tg.config.get("appsupport_dir") dump_path = os.path.join(appsupport_dir, "Dump") for item in glob.iglob("%s/*.pickle" % (dump_path)): print "Importing %s" % item with open(item, "rb") as f: pickled_client = pickle.load(f) client = Client() for prop in dir(Client): attr = getattr(Client, prop) if isinstance(attr, sqlalchemy.orm.attributes.InstrumentedAttribute): try: value = pickled_client[prop] except KeyError: print "Warning: no pickled '%s' attribute" % prop else: v = repr(value) if len(v) > (70 - len(prop)): v = v[:67] + "..." # print "client.%s = %s" % (prop, v) setattr(client, prop, value) client.update_report(pickled_client["report_plist"]) # print client DBSession.add(client) DBSession.flush() transaction.commit()
def get_manifest(self, serial): """Lookup Manifest.""" client = Client.by_serial(serial) if not client: return "none\n" manifest = client.manifest return "%s\n" % manifest
def report_plist(self, serial=None): """View a munki report.""" client=Client.by_serial(unicode(serial)) if not client: abort(404) # Work with a copy of the client report so we can modify it without # causing a database update. report = dict(client.report_plist) return plistlib.writePlistToString(report)
def preflight(self, runtype=None, mac=None, name=None): """Log preflight.""" client = Client.by_mac(mac) if not client: client = Client() client.mac = mac DBSession.add(client) client.runtype = runtype if name: client.name = name else: client.name = "<NO NAME>" client.runstate = u"in progress" client.timestamp = datetime.now() client.remote_ip = unicode(request.environ['REMOTE_ADDR']) client.activity = {"Updating": "preflight"} DBSession.flush() return "preflight logged for %s\n" % name
def client_info(self, mac): """Look up client information summary.""" client_info = dict() client = Client.by_mac(mac) if not client: return dict(client=None) return dict( client=client, report=dict(client.report_plist), )
def report_broken_client(self, runtype=None, mac=None, name=None): """Log report_broken_client.""" client = Client.by_serial(serial) if not client: client = Client() client.serial = serial DBSession.add(client) client.runtype = runtype client.name = name client.mac = mac client.runstate = u"broken client" client.timestamp = datetime.now() client.remote_ip = unicode(request.environ['REMOTE_ADDR']) client.report_plist = None client.errors = 1 client.warnings = 0 DBSession.flush() return "report_broken_client logged for %s\n" % (name, remote_ip)
def postflight(self, runtype=None, mac=None, name=None, serial=None, manifest=None, base64bz2report=None): """Log postflight.""" # Decode report # FIXME: there has to be a better way to submit a binary blob try: base64bz2report = base64bz2report.replace(" ", "+") bz2report = base64.b64decode(base64bz2report) report = bz2.decompress(bz2report) except BaseException as e: print "Can't decode report from %s (%s): %s" % (request.environ['REMOTE_ADDR'], mac, str(e)) abort(403) # Parse plist with plistlib, as Objective-C objects can't be pickled. try: plist = plistlib.readPlistFromString(report) except BaseException as e: print "Received invalid plist from %s (%s): %s" % (request.environ['REMOTE_ADDR'], mac, str(e)) abort(403) #plist, format, error = \ # NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_( # buffer(report), # NSPropertyListMutableContainers, # None, # None # ) #if error: # print "error:", error # abort(401) # Create client if needed. client = Client.by_serial(serial) if not client: print "postflight running without preflight for %s" % mac client = Client() client.serial = serial DBSession.add(client) # Update client attributes. client.runtype = runtype if name: client.name = name else: client.name = "<NO NAME>" # Get manifest id from plist client.mac = mac client.manifest = manifest client.runstate = u"done" client.timestamp = datetime.now() client.remote_ip = unicode(request.environ['REMOTE_ADDR']) # Save report, updating activity, errors, warnings, and console_user. client.update_report(plist) DBSession.flush() return "postflight logged for %s\n" % name
def report(self, serial=None): """View a munki report.""" client=Client.by_serial(unicode(serial)) if not client: abort(404) # Work with a copy of the client report so we can modify it without # causing a database update. report = dict(client.report_plist) # Move install results over to their install items. install_results = dict() if "InstallResults" in report: for result in report["InstallResults"]: if isinstance(result, basestring): # Older Munki clients return an array of strings m = re_result.search(result) if m: install_results["%s-%s" % (m.group("dname"), m.group("version"))] = { "result": "Installed" if m.group("result") == "SUCCESSFUL" else m.group("result") } else: # Newer Munki clients return an array of dicts install_results["%s-%s" % (result["name"], result["version"])] = { "result": "Installed" if result["status"] == 0 else "error %d" % result["status"] } if "ItemsToInstall" in report: for item in report["ItemsToInstall"]: item["install_result"] = "Pending" dversion = "%s-%s" % (item["display_name"], item["version_to_install"]) if dversion in install_results: res = install_results[dversion] item["install_result"] = res["result"] if "AppleUpdateList" in report: for item in report["AppleUpdateList"]: item["install_result"] = "Pending" dversion = "%s-%s" % (item["display_name"], item["version_to_install"]) if dversion in install_results: res = install_results[dversion] item["install_result"] = res["result"] # Move removal results over to their removal items. removal_results = dict() if "RemovalResults" in report: for result in report["RemovalResults"]: m = re_result.search(result) if m: removal_results[m.group("dname")] = { "result": "Removed" if m.group("result") == "SUCCESSFUL" else m.group("result") } if "ItemsToRemove" in report: for item in report["ItemsToRemove"]: item["removal_result"] = "Pending" dversion = item["display_name"] if dversion in removal_results: res = removal_results[dversion] item["removal_result"] = res["result"] return dict( page="reports", client=client, report=report, install_results=install_results, removal_results=removal_results )