def update_notify_date(request, length='never'): # Don't notify about a new version until there is a new one version_report = utils.check_version() if version_report['new_version_available']: if isinstance(length, int): next_notify_date = utils.get_setting('next_notify_date', time.time()) + length else: next_notify_date = length utils.set_setting('next_notify_date', next_notify_date)
def settings_historical_data(request): if request.method == 'POST': form = forms.SettingsHistoricalDataForm(request.POST) if form.is_valid(): utils.set_setting('historical_retention', form.cleaned_data['days']) messages.success(request, 'Data retention settings saved.') return redirect('settings_page') else: return redirect('settings_page')
def senddata_disable(request): utils.set_setting('send_data', False) return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
def checkin(request): if request.method != 'POST': print 'not post data' return HttpResponseNotFound('No POST data sent') data = request.POST key = data.get('key') uuid = data.get('uuid') serial = data.get('serial') serial = serial.upper() broken_client = data.get('broken_client', False) # Take out some of the weird junk VMware puts in. Keep an eye out in case # Apple actually uses these: serial = serial.replace('/', '') serial = serial.replace('+', '') # Are we using Sal for some sort of inventory (like, I don't know, Puppet?) try: add_new_machines = settings.ADD_NEW_MACHINES except Exception: add_new_machines = True if add_new_machines: # look for serial number - if it doesn't exist, create one if serial: try: machine = Machine.objects.get(serial=serial) except Machine.DoesNotExist: machine = Machine(serial=serial) else: machine = get_object_or_404(Machine, serial=serial) try: deployed_on_checkin = settings.DEPLOYED_ON_CHECKIN except Exception: deployed_on_checkin = True if key is None or key == 'None': try: key = settings.DEFAULT_MACHINE_GROUP_KEY except Exception: pass machine_group = get_object_or_404(MachineGroup, key=key) machine.machine_group = machine_group machine.last_checkin = django.utils.timezone.now() if bool(broken_client): machine.broken_client = True machine.save() return HttpResponse("Broken Client report submmitted for %s" % data.get('serial')) else: machine.broken_client = False historical_days = utils.get_setting('historical_retention') machine.hostname = data.get('name', '<NO NAME>') if 'username' in data: if data.get('username') != '_mbsetupuser': machine.console_user = data.get('username') if 'base64bz2report' in data: machine.update_report(data.get('base64bz2report')) if 'base64report' in data: machine.update_report(data.get('base64report'), 'base64') if 'sal_version' in data: machine.sal_version = data.get('sal_version') # extract machine data from the report report_data = machine.get_report() if 'Puppet_Version' in report_data: machine.puppet_version = report_data['Puppet_Version'] if 'ManifestName' in report_data: manifest = report_data['ManifestName'] machine.manifest = manifest if 'MachineInfo' in report_data: machine.operating_system = report_data['MachineInfo'].get( 'os_vers', 'UNKNOWN') # some machines are reporting 10.9, some 10.9.0 - make them the same if len(machine.operating_system) <= 4: machine.operating_system = machine.operating_system + '.0' # if gosal is the sender look for OSVers key if 'OSVers' in report_data['MachineInfo']: machine.operating_system = report_data['MachineInfo'].get('OSVers') machine.hd_space = report_data.get('AvailableDiskSpace') or 0 machine.hd_total = int(data.get('disk_size')) or 0 if machine.hd_total == 0: machine.hd_percent = 0 else: machine.hd_percent = int( round(((float(machine.hd_total) - float(machine.hd_space)) / float(machine.hd_total)) * 100)) machine.munki_version = report_data.get('ManagedInstallVersion') or 0 hwinfo = {} # macOS System Profiler if 'SystemProfile' in report_data.get('MachineInfo', []): for profile in report_data['MachineInfo']['SystemProfile']: if profile['_dataType'] == 'SPHardwareDataType': hwinfo = profile._items[0] break if 'HardwareInfo' in report_data.get('MachineInfo', []): hwinfo = report_data['MachineInfo']['HardwareInfo'] if 'Puppet' in report_data: puppet = report_data.get('Puppet') if 'time' in puppet: machine.last_puppet_run = datetime.fromtimestamp( float(puppet['time']['last_run'])) if 'events' in puppet: machine.puppet_errors = puppet['events']['failure'] if hwinfo: # setup vars for hash keys we might get sent if 'MachineModel' in hwinfo: var_machine_model = 'MachineModel' var_cpu_type = 'CPUType' var_cpu_speed = 'CurrentProcessorSpeed' var_memory = 'PhysicalMemory' else: var_machine_model = 'machine_model' var_cpu_type = 'cpu_type' var_cpu_speed = 'current_processor_speed' var_memory = 'physical_memory' machine.machine_model = hwinfo.get(var_machine_model) machine.cpu_type = hwinfo.get(var_cpu_type) machine.cpu_speed = hwinfo.get(var_cpu_speed) machine.memory = hwinfo.get(var_memory) if hwinfo.get(var_memory)[-2:] == 'KB': machine.memory_kb = int(hwinfo.get(var_memory)[:-3]) if hwinfo.get(var_memory)[-2:] == 'MB': memory_mb = float(hwinfo.get(var_memory)[:-3]) machine.memory_kb = int(memory_mb * 1024) if hwinfo.get(var_memory)[-2:] == 'GB': memory_gb = float(hwinfo.get(var_memory)[:-3]) machine.memory_kb = int(memory_gb * 1024 * 1024) if hwinfo.get(var_memory)[-2:] == 'TB': memory_tb = float(hwinfo.get(var_memory)[:-3]) machine.memory_kb = int(memory_tb * 1024 * 1024 * 1024) if 'os_family' in report_data: machine.os_family = report_data['os_family'] # support golang strict structure if 'OSFamily' in report_data: machine.os_family = report_data['OSFamily'] if not machine.machine_model_friendly: try: machine.machine_model_friendly = utils.friendly_machine_model( machine) except Exception: machine.machine_model_friendly = machine.machine_model if deployed_on_checkin is True: machine.deployed = True machine.save() # If Plugin_Results are in the report, handle them try: datelimit = django.utils.timezone.now() - timedelta( days=historical_days) PluginScriptSubmission.objects.filter(recorded__lt=datelimit).delete() except Exception: pass if 'Plugin_Results' in report_data: utils.process_plugin_script(report_data.get('Plugin_Results'), machine) # Remove existing PendingUpdates for the machine machine.pending_updates.all().delete() now = django.utils.timezone.now() if 'ItemsToInstall' in report_data: pending_update_to_save = [] update_history_item_to_save = [] for update in report_data.get('ItemsToInstall'): display_name = update.get('display_name', update['name']) update_name = update.get('name') version = str(update['version_to_install']) if version: pending_update = PendingUpdate(machine=machine, display_name=display_name, update_version=version, update=update_name) if IS_POSTGRES: pending_update_to_save.append(pending_update) else: pending_update.save() # Let's handle some of those lovely pending installs into the UpdateHistory Model try: update_history = UpdateHistory.objects.get( name=update_name, version=version, machine=machine, update_type='third_party') except UpdateHistory.DoesNotExist: update_history = UpdateHistory(name=update_name, version=version, machine=machine, update_type='third_party') update_history.save() if not update_history.pending_recorded: update_history_item = UpdateHistoryItem( update_history=update_history, status='pending', recorded=now, uuid=uuid) update_history.pending_recorded = True update_history.save() if IS_POSTGRES: update_history_item_to_save.append(update_history_item) else: update_history_item.save() if IS_POSTGRES: PendingUpdate.objects.bulk_create(pending_update_to_save) UpdateHistoryItem.objects.bulk_create(update_history_item_to_save) machine.installed_updates.all().delete() if 'ManagedInstalls' in report_data: # Due to a quirk in how Munki 3 processes updates with dependencies, # it's possible to have multiple entries in the ManagedInstalls list # that share an update_name and installed_version. This causes an # IntegrityError in Django since (machine_id, update, update_version) # must be unique.Until/(unless!) this is addressed in Munki, we need to # be careful to not add multiple items with the same name and version. # We'll store each (update_name, version) combo as we see them. seen_names_and_versions = [] installed_updates_to_save = [] for update in report_data.get('ManagedInstalls'): display_name = update.get('display_name', update['name']) update_name = update.get('name') version = str(update.get('installed_version', 'UNKNOWN')) installed = update.get('installed') if (update_name, version) not in seen_names_and_versions: seen_names_and_versions.append((update_name, version)) if (version != 'UNKNOWN' and version is not None and len(version) != 0): installed_update = InstalledUpdate( machine=machine, display_name=display_name, update_version=version, update=update_name, installed=installed) if IS_POSTGRES: installed_updates_to_save.append(installed_update) else: installed_update.save() if IS_POSTGRES: InstalledUpdate.objects.bulk_create(installed_updates_to_save) # Remove existing PendingAppleUpdates for the machine machine.pending_apple_updates.all().delete() if 'AppleUpdates' in report_data: for update in report_data.get('AppleUpdates'): display_name = update.get('display_name', update['name']) update_name = update.get('name') version = str(update['version_to_install']) try: pending_update = PendingAppleUpdate.objects.get( machine=machine, display_name=display_name, update_version=version, update=update_name) except PendingAppleUpdate.DoesNotExist: pending_update = PendingAppleUpdate(machine=machine, display_name=display_name, update_version=version, update=update_name) pending_update.save() # Let's handle some of those lovely pending installs into the UpdateHistory Model try: update_history = UpdateHistory.objects.get(name=update_name, version=version, machine=machine, update_type='apple') except UpdateHistory.DoesNotExist: update_history = UpdateHistory(name=update_name, version=version, machine=machine, update_type='apple') update_history.save() if not update_history.pending_recorded: update_history_item = UpdateHistoryItem( update_history=update_history, status='pending', recorded=now, uuid=uuid) update_history_item.save() update_history.pending_recorded = True update_history.save() # if Facter data is submitted, we need to first remove any existing facts for this machine if IS_POSTGRES: # If we are using postgres, we can just dump them all and do a bulk create if 'Facter' in report_data: facts = machine.facts.all().delete() try: datelimit = django.utils.timezone.now() - timedelta( days=historical_days) HistoricalFact.objects.filter( fact_recorded__lt=datelimit).delete() except Exception: pass try: historical_facts = settings.HISTORICAL_FACTS except Exception: historical_facts = [] pass facts_to_be_created = [] historical_facts_to_be_created = [] for fact_name, fact_data in report_data['Facter'].iteritems(): skip = False if hasattr(settings, 'IGNORE_FACTS'): for prefix in settings.IGNORE_FACTS: if fact_name.startswith(prefix): skip = True if skip: continue facts_to_be_created.append( Fact(machine=machine, fact_data=fact_data, fact_name=fact_name)) if fact_name in historical_facts: historical_facts_to_be_created.append( HistoricalFact(machine=machine, fact_data=fact_data, fact_name=fact_name)) Fact.objects.bulk_create(facts_to_be_created) if len(historical_facts_to_be_created) != 0: HistoricalFact.objects.bulk_create( historical_facts_to_be_created) else: if 'Facter' in report_data: facts = machine.facts.all() for fact in facts: skip = False if hasattr(settings, 'IGNORE_FACTS'): for prefix in settings.IGNORE_FACTS: if fact.fact_name.startswith(prefix): skip = True fact.delete() break if not skip: continue found = False for fact_name, fact_data in report_data['Facter'].iteritems(): if fact.fact_name == fact_name: found = True break if not found: fact.delete() # Delete old historical facts try: datelimit = django.utils.timezone.now() - timedelta( days=historical_days) HistoricalFact.objects.filter( fact_recorded__lt=datelimit).delete() except Exception: pass try: historical_facts = settings.HISTORICAL_FACTS except Exception: historical_facts = [] pass # now we need to loop over the submitted facts and save them facts = machine.facts.all() for fact_name, fact_data in report_data['Facter'].iteritems(): if machine.os_family == 'Windows': # We had a little trouble parsing out facts on Windows, clean up here if fact_name.startswith('value=>'): fact_name = fact_name.replace('value=>', '', 1) # does fact exist already? found = False skip = False if hasattr(settings, 'IGNORE_FACTS'): for prefix in settings.IGNORE_FACTS: if fact_name.startswith(prefix): skip = True break if skip: continue for fact in facts: if fact_name == fact.fact_name: # it exists, make sure it's got the right info found = True if fact_data == fact.fact_data: # it's right, break break else: fact.fact_data = fact_data fact.save() break if not found: fact = Fact(machine=machine, fact_data=fact_data, fact_name=fact_name) fact.save() if fact_name in historical_facts: fact = HistoricalFact(machine=machine, fact_name=fact_name, fact_data=fact_data, fact_recorded=datetime.now()) fact.save() if IS_POSTGRES: if 'Conditions' in report_data: machine.conditions.all().delete() conditions_to_be_created = [] for condition_name, condition_data in report_data[ 'Conditions'].iteritems(): # Skip the conditions that come from facter if 'Facter' in report_data and condition_name.startswith( 'facter_'): continue condition_data = text_utils.stringify(condition_data) conditions_to_be_created.append( Condition(machine=machine, condition_name=condition_name, condition_data=text_utils.safe_unicode( condition_data))) Condition.objects.bulk_create(conditions_to_be_created) else: if 'Conditions' in report_data: conditions = machine.conditions.all() for condition in conditions: found = False for condition_name, condition_data in report_data[ 'Conditions'].iteritems(): if condition.condition_name == condition_name: found = True break if found is False: condition.delete() conditions = machine.conditions.all() for condition_name, condition_data in report_data[ 'Conditions'].iteritems(): # Skip the conditions that come from facter if 'Facter' in report_data and condition_name.startswith( 'facter_'): continue # if it's a list (more than one result), # we're going to conacetnate it into one comma separated string. condition_data = text_utils.stringify(condition_data) found = False for condition in conditions: if condition_name == condition.condition_name: # it exists, make sure it's got the right info found = True if condition_data == condition.condition_data: # it's right, break break else: condition.condition_data = condition_data condition.save() break if found is False: condition = Condition( machine=machine, condition_name=condition_name, condition_data=text_utils.safe_unicode(condition_data)) condition.save() utils.run_plugin_processing(machine, report_data) if utils.get_setting('send_data') in (None, True): # If setting is None, it hasn't been configured yet; assume True current_version = utils.send_report() else: current_version = utils.get_current_release_version_number() if current_version: utils.set_setting('current_version', current_version) return HttpResponse("Sal report submmitted for %s" % data.get('name'))