def manifest(request, manifest_name): if request.method == 'GET': # load base manifest from file system (either a specific one or site_default) manifest = Manifest.read(manifest_name) if not manifest: manifest = Manifest.read('site_default') # Only if the request matches an UDID (v4) the JSS will be queried if re.search( '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', manifest_name.lower()): jss_connection = jss.JSS(user=settings.JSS_READONLY_USER, password=settings.JSS_READONLY_PASS, url=settings.JSS_URL, ssl_verify=settings.JSS_VERIFY_CERT) jcomputer = jss_connection.Computer('udid=%s' % manifest_name.upper()) computer = etree.fromstring(jcomputer.__str__()) if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: _dump_computer_ea(manifest, computer.iter('extension_attribute')) attribute_types = JSSComputerAttributeType.objects.all() manifest['computer_matches'] = [] manifest_updates = [] for type in attribute_types: if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: type.dump_debug_xml(manifest) mappings = type.jsscomputerattributemapping_set.all() for mapping in mappings: if mapping.computer_match(computer): if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: manifest['computer_matches'].append('%s' % mapping) manifest_updates.append(mapping) manifest_updates.sort(key=attrgetter('priority')) for manifest_update in manifest_updates: manifest_update.apply_mapping(manifest) response = HttpResponse(content_type='application/xml') plistlib.writePlist(manifest, response) if settings.JSSMANIFESTS_DOWNLOAD_AS_ATTACHMENT: response['Content-Disposition'] = "attachment; filename=%s" % udid return response
def manifest(request, manifest_name): if request.method == 'GET': # load base manifest from file system (either a specific one or site_default) manifest = Manifest.read(manifest_name) if not manifest: manifest = Manifest.read('site_default') # Only if the request matches an UDID (v4) the JSS will be queried if re.search('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', manifest_name.lower()): jss_connection = jss.JSS(user=settings.JSS_READONLY_USER, password=settings.JSS_READONLY_PASS, url=settings.JSS_URL, ssl_verify=settings.JSS_VERIFY_CERT) jcomputer = jss_connection.Computer('udid=%s' % manifest_name.upper()) computer = etree.fromstring(jcomputer.__str__()) if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: _dump_computer_ea(manifest, computer.iter('extension_attribute') ) attribute_types = JSSComputerAttributeType.objects.all() manifest['computer_matches'] = [] manifest_updates = [] for type in attribute_types: if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: type.dump_debug_xml(manifest) mappings = type.jsscomputerattributemapping_set.all() for mapping in mappings: if mapping.computer_match(computer): if settings.JSSMANIFESTS_DEBUG_DUMPJSSEA: manifest['computer_matches'].append( '%s' % mapping) manifest_updates.append(mapping) manifest_updates.sort( key=attrgetter('priority') ) for manifest_update in manifest_updates: manifest_update.apply_mapping(manifest) response = HttpResponse(content_type='application/xml') plistlib.writePlist(manifest, response) if settings.JSSMANIFESTS_DOWNLOAD_AS_ATTACHMENT: response['Content-Disposition'] = "attachment; filename=%s" % udid return response
def detail(request, manifest_path): '''Returns data on a given manifest''' if request.method == 'GET': LOGGER.debug("Got read request for %s", manifest_path) manifest = Manifest.read(manifest_path) if manifest is None: raise Http404("%s does not exist" % manifest_path) context = {'plist_text': manifest, 'pathname': manifest_path} return render(request, 'manifests/detail.html', context=context) if request.method == 'POST': # could be PUT, POST, or DELETE if request.META.has_key('HTTP_X_METHODOVERRIDE'): http_method = request.META['HTTP_X_METHODOVERRIDE'] if http_method.lower() == 'delete': # DELETE LOGGER.debug("Got delete request for %s", manifest_path) if not request.user.has_perm('manifest.delete_manifestfile'): raise PermissionDenied try: Manifest.delete(manifest_path, request.user) except ManifestError, err: return HttpResponse( json.dumps({'result': 'failed', 'exception_type': str(type(err)), 'detail': str(err)}), content_type='application/json') else: return HttpResponse( json.dumps({'result': 'success'}), content_type='application/json') elif http_method.lower() == 'put': # regular POST (update/change) LOGGER.debug("Got write request for %s", manifest_path) if not request.user.has_perm('manifest.change_manifestfile'): raise PermissionDenied if request.is_ajax(): json_data = json.loads(request.body) if json_data and 'plist_data' in json_data: plist_data = json_data['plist_data'].encode('utf-8') try: Manifest.write( json_data['plist_data'], manifest_path, request.user) except ManifestError, err: return HttpResponse( json.dumps({'result': 'failed', 'exception_type': str(type(err)), 'detail': str(err)}), content_type='application/json') else: return HttpResponse( json.dumps({'result': 'success'}), content_type='application/json') else: LOGGER.warning( "Got unknown HTTP_X_METHODOVERRIDE for %s: %s", manifest_path, http_method)
def test_extension_attribute_mappings_ea(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=1) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=4) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['catalogs'] = [] assert_test['catalogs'].append('ea_match_catalog') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['catalogs'].append('ea_match_catalog') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest)
def test_extension_attribute_mappings_ea(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=1) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=4) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['catalogs'] = [] assert_test['catalogs'].append('ea_match_catalog') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test ) assert_test = Manifest.read('site_default') assert_test['catalogs'].append('ea_match_catalog') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest)
def test_groups_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=9) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=10) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['managed_uninstalls'] = [] assert_test['managed_uninstalls'].append('group_package') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['managed_uninstalls'].append('group_package') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test)
def test_building_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=7) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=8) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['optional_installs'] = [] assert_test['optional_installs'].append('building_two_package') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['optional_installs'].append('building_two_package') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test)
def test_site_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=2) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=5) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['included_manifests'] = [] assert_test['included_manifests'].append('site_match_manifest') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['included_manifests'].append('site_match_manifest') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test)
def test_groups_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=9) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=10) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['managed_uninstalls'] = [] assert_test['managed_uninstalls'].append('group_package') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['managed_uninstalls'].append('group_package') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test )
def test_building_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=7) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=8) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['optional_installs'] = [] assert_test['optional_installs'].append('building_two_package') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['optional_installs'].append('building_two_package') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test )
def test_site_mappings(self): mapping_match = JSSComputerAttributeMapping.objects.get(id=2) self.assertEqual(mapping_match.computer_match(self.computer), True) mapping_mismatch = JSSComputerAttributeMapping.objects.get(id=5) self.assertEqual(mapping_mismatch.computer_match(self.computer), False) assert_test = {} # empty manifest, so be lazy assert_test['included_manifests'] = [] assert_test['included_manifests'].append('site_match_manifest') test_manifest = {} mapping_mismatch.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test) assert_test = Manifest.read('site_default') assert_test['included_manifests'].append('site_match_manifest') test_manifest = Manifest.read('site_default') mapping_match.apply_mapping(test_manifest) self.assertEqual(test_manifest, assert_test )
def get_addition_manifests(manifest): detailManifest = Manifest.read(manifest) includetManifests.update({manifest: detailManifest}) if "included_manifests" in detailManifest: for includetManifest in detailManifest.included_manifests: get_addition_manifests(includetManifest)
def detail_pkg(request, serial, manifest_name): machine = None manifest = None install_items = None if serial: try: machine = Machine.objects.get(serial_number=serial) except Machine.DoesNotExist: raise Http404 else: raise Http404 report_plist = {} if machine: try: report = MunkiReport.objects.get(machine=machine) report_plist = report.get_report() except MunkiReport.DoesNotExist: pass # get autocomplete data install_items = Manifest.getInstallItemNames(manifest_name) valid_install_items = install_items["suggested"] + install_items["updates"] + install_items["with_version"] suggested_install_items = install_items["suggested"] valid_catalogs = Catalog.list() valid_manifest_names = Manifest.list() autocomplete_data = json.dumps( {"items": install_items["suggested"], "catalogs": valid_catalogs, "manifests": valid_manifest_names} ) # loop trought includet manifests as long as it have one includetManifests = dict() def get_addition_manifests(manifest): detailManifest = Manifest.read(manifest) includetManifests.update({manifest: detailManifest}) if "included_manifests" in detailManifest: for includetManifest in detailManifest.included_manifests: get_addition_manifests(includetManifest) manifest = Manifest.read(manifest_name) sorted_Manifests = SortedDict() sorted_Manifests[manifest_name] = manifest if "included_manifests" in manifest: for includetManifest in manifest.included_manifests: get_addition_manifests(includetManifest) sort_list = manifest.included_manifests for key in sort_list: sorted_Manifests[key] = includetManifests[key] key_list = includetManifests.keys() key_list.sort() for key in key_list: if key not in sorted_Manifests: sorted_Manifests[key] = includetManifests[key] # item_details -> list with software and details # true_items for check if a software is in catalog or not item_details = {} true_items = list() if "catalogs" in manifest: for catalog in manifest.catalogs: catalog_detail = Catalog.detail(catalog) if catalog_detail: for detail in reversed(catalog_detail): if not detail.name in item_details: item_details[detail.name] = detail true_items.append(detail.name) if "icon_name" in item_details[detail.name]: icon = Catalog.get_icon(item_details[detail.name].icon_name) else: icon = Catalog.get_icon(detail.name) item_details[detail.name].icon_name = icon ManagedInstallsDetail = SortedDict() if report_plist.has_key("ManagedInstalls"): for item in report_plist.ManagedInstalls: ManagedInstallsDetail[item.name] = item # installs installs = SortedDict() listed = list() installsTypes = ["managed_installs", "managed_uninstalls", "optional_installs"] for installsType in installsTypes: installs[installsType] = SortedDict() for number, manifests in enumerate(sorted_Manifests): installs[installsType][manifests] = SortedDict() if manifest: for index, item in enumerate(sorted_Manifests[manifests][installsType]): listed.append(item) if ManagedInstallsDetail.has_key(item): installs[installsType][manifests][item] = ManagedInstallsDetail[item] if item in true_items: if installs[installsType].get(manifests, {}).has_key(item): installs[installsType][manifests][item].update(item_details[item]) else: installs[installsType][manifests][item] = item_details[item] installs[installsType][manifests][item].update({"incatalog": "True"}) else: if installs[installsType].get(manifests, {}).has_key(item): installs[installsType][manifests][item].update({"incatalog": "False"}) else: installs[installsType][manifests][item] = {"name": item, "incatalog": "False"} required = SortedDict() for item in sorted(ManagedInstallsDetail.items(), key=lambda x: x[1]["display_name"]): if not item[0] in listed: if item_details.has_key(item[0]): ManagedInstallsDetail[item[0]].icon_name = item_details[item[0]].icon_name else: ManagedInstallsDetail[item[0]].icon_name = "/static/img/PackageIcon.png" required[item[0]] = ManagedInstallsDetail[item[0]] # handle items that were installed during the most recent run install_results = {} for result in report_plist.get("InstallResults", []): nameAndVers = result["name"] + "-" + result["version"] if result["status"] == 0: install_results[nameAndVers] = "installed" else: install_results[nameAndVers] = "error" if install_results: for item in report_plist.get("ItemsToInstall", []): name = item.get("display_name", item["name"]) nameAndVers = "%s-%s" % (name, item["version_to_install"]) item["install_result"] = install_results.get(nameAndVers, "pending") for item in report_plist.get("ManagedInstalls", []): if "version_to_install" in item: name = item.get("display_name", item["name"]) nameAndVers = "%s-%s" % (name, item["version_to_install"]) if install_results.get(nameAndVers) == "installed": item["installed"] = True # handle items that were removed during the most recent run # this is crappy. We should fix it in Munki. removal_results = {} # for result in report_plist.get('RemovalResults', []): # m = re.search('^Removal of (.+): (.+)$', result) # if m: # try: # if m.group(2) == 'SUCCESSFUL': # removal_results[m.group(1)] = 'removed' # else: # removal_results[m.group(1)] = m.group(2) # except IndexError: # pass if removal_results: for item in report_plist.get("ItemsToRemove", []): name = item.get("display_name", item["name"]) item["install_result"] = removal_results.get(name, "pending") if item["install_result"] == "removed": if not "RemovedItems" in report_plist: report_plist["RemovedItems"] = [item["name"]] elif not name in report_plist["RemovedItems"]: report_plist["RemovedItems"].append(item["name"]) c = RequestContext( request, { "manifest_name": manifest_name, "manifest": manifest, "report": report_plist, "installs": installs, "autocomplete_data": autocomplete_data, "required": required, "valid_manifest_names": valid_manifest_names, "valid_catalogs": valid_catalogs, }, ) c.update(csrf(request)) return render_to_response("reports/detail_pkg.html", c)
def detail_pkg(request, serial, manifest_name): machine = None manifest = None install_items = None if serial: try: machine = Machine.objects.get(serial_number=serial) except Machine.DoesNotExist: raise Http404 else: raise Http404 report_plist = {} if machine: try: report = MunkiReport.objects.get(machine=machine) report_plist = report.get_report() except MunkiReport.DoesNotExist: pass # get autocomplete data install_items = Manifest.getInstallItemNames(manifest_name) valid_install_items = (install_items['suggested'] + install_items['updates'] + install_items['with_version']) suggested_install_items = install_items['suggested'] valid_catalogs = Catalog.list() valid_manifest_names = Manifest.list() autocomplete_data = json.dumps({ 'items': install_items['suggested'], 'catalogs': valid_catalogs, 'manifests': valid_manifest_names }) # loop trought includet manifests as long as it have one includetManifests = dict() def get_addition_manifests(manifest): detailManifest = Manifest.read(manifest) includetManifests.update({manifest: detailManifest}) if "included_manifests" in detailManifest: for includetManifest in detailManifest.included_manifests: get_addition_manifests(includetManifest) manifest = Manifest.read(manifest_name) sorted_Manifests = SortedDict() sorted_Manifests[manifest_name] = manifest if "included_manifests" in manifest: for includetManifest in manifest.included_manifests: get_addition_manifests(includetManifest) sort_list = manifest.included_manifests for key in sort_list: sorted_Manifests[key] = includetManifests[key] key_list = includetManifests.keys() key_list.sort() for key in key_list: if key not in sorted_Manifests: sorted_Manifests[key] = includetManifests[key] # item_details -> list with software and details # true_items for check if a software is in catalog or not item_details = {} true_items = list() if "catalogs" in manifest: for catalog in manifest.catalogs: catalog_detail = Catalog.detail(catalog) if catalog_detail: for detail in reversed(catalog_detail): if not detail.name in item_details: item_details[detail.name] = detail true_items.append(detail.name) if "icon_name" in item_details[detail.name]: icon = Catalog.get_icon( item_details[detail.name].icon_name) else: icon = Catalog.get_icon(detail.name) item_details[detail.name].icon_name = icon ManagedInstallsDetail = SortedDict() if report_plist.has_key("ManagedInstalls"): for item in report_plist.ManagedInstalls: ManagedInstallsDetail[item.name] = item # installs installs = SortedDict() listed = list() installsTypes = [ "managed_installs", "managed_uninstalls", "optional_installs" ] for installsType in installsTypes: installs[installsType] = SortedDict() for number, manifests in enumerate(sorted_Manifests): installs[installsType][manifests] = SortedDict() if manifest: for index, item in enumerate( sorted_Manifests[manifests][installsType]): listed.append(item) if ManagedInstallsDetail.has_key(item): installs[installsType][manifests][ item] = ManagedInstallsDetail[item] if item in true_items: if installs[installsType].get(manifests, {}).has_key(item): installs[installsType][manifests][item].update( item_details[item]) else: installs[installsType][manifests][ item] = item_details[item] installs[installsType][manifests][item].update( {"incatalog": "True"}) else: if installs[installsType].get(manifests, {}).has_key(item): installs[installsType][manifests][item].update( {"incatalog": "False"}) else: installs[installsType][manifests][item] = { 'name': item, "incatalog": "False" } required = SortedDict() for item in sorted(ManagedInstallsDetail.items(), key=lambda x: x[1]['display_name']): if not item[0] in listed: if item_details.has_key(item[0]): ManagedInstallsDetail[item[0]].icon_name = item_details[ item[0]].icon_name else: ManagedInstallsDetail[ item[0]].icon_name = "/static/img/PackageIcon.png" required[item[0]] = ManagedInstallsDetail[item[0]] # handle items that were installed during the most recent run install_results = {} for result in report_plist.get('InstallResults', []): nameAndVers = result['name'] + '-' + result['version'] if result['status'] == 0: install_results[nameAndVers] = "installed" else: install_results[nameAndVers] = 'error' if install_results: for item in report_plist.get('ItemsToInstall', []): name = item.get('display_name', item['name']) nameAndVers = ('%s-%s' % (name, item['version_to_install'])) item['install_result'] = install_results.get( nameAndVers, 'pending') for item in report_plist.get('ManagedInstalls', []): if 'version_to_install' in item: name = item.get('display_name', item['name']) nameAndVers = ('%s-%s' % (name, item['version_to_install'])) if install_results.get(nameAndVers) == 'installed': item['installed'] = True # handle items that were removed during the most recent run # this is crappy. We should fix it in Munki. removal_results = {} # for result in report_plist.get('RemovalResults', []): # m = re.search('^Removal of (.+): (.+)$', result) # if m: # try: # if m.group(2) == 'SUCCESSFUL': # removal_results[m.group(1)] = 'removed' # else: # removal_results[m.group(1)] = m.group(2) # except IndexError: # pass if removal_results: for item in report_plist.get('ItemsToRemove', []): name = item.get('display_name', item['name']) item['install_result'] = removal_results.get(name, 'pending') if item['install_result'] == 'removed': if not 'RemovedItems' in report_plist: report_plist['RemovedItems'] = [item['name']] elif not name in report_plist['RemovedItems']: report_plist['RemovedItems'].append(item['name']) c = RequestContext( request, { 'manifest_name': manifest_name, 'manifest': manifest, 'report': report_plist, 'installs': installs, 'autocomplete_data': autocomplete_data, 'required': required, 'valid_manifest_names': valid_manifest_names, 'valid_catalogs': valid_catalogs, }) c.update(csrf(request)) return render_to_response('reports/detail_pkg.html', c)