def UpdateInstallLogSchema(cursor=None, num_updated=0): """Puts all InstallLog entities so any new properties are created.""" q = models.InstallLog.all() if cursor: logging.debug('Continuing with cursor: %s', cursor) q.with_cursor(cursor) entities = q.fetch(INSTALL_LOG_MAX_FETCH) if not entities: logging.debug('No remaining entities to convert.') return entities_to_put = [] for e in entities: e.success = e.IsSuccess() e.applesus = getattr(e, 'applesus', False) if not getattr(e, 'server_datetime', False): e.server_datetime = e.mtime entities_to_put.append(e) gae_util.BatchDatastoreOp(models.db.put, entities_to_put, 100) cursor = q.cursor() num_updated += len(entities_to_put) logging.info('%s entities converted', num_updated) deferred.defer(UpdateInstallLogSchema, cursor=cursor, num_updated=num_updated)
def Log(cls, products, action): """Puts batches of product changes to AdminAppleSUSProductLog. Args: products: list of or single models.AppleSUSProduct entity. action: str, description of the change taking place to the batch. """ # Support products being a single product entity. if not isinstance(products, (list, tuple)): products = (products, ) to_put = [] for p in products: log = cls(product_id=p.product_id, action=action, tracks=p.tracks) log.mtime = datetime.datetime.utcnow() to_put.append(log) # Put all log entities together. gae_util.BatchDatastoreOp(db.put, to_put)
def _AddManifestModification(self): """Adds a new manifest modification to Datastore.""" mod_type = self.request.get('mod_type') targets = [ x.strip() for x in self.request.get('target').split(',') if x.strip() ] munki_pkg_name = self.request.get('munki_pkg_name').strip() manifests = self.request.get_all('manifests') install_types = self.request.get_all('install_types') remove_from_manifest = bool(self.request.get('remove-from-manifest')) # Security users are only able to inject specific packages. if not self.IsAdminUser(): grp = None if auth.IsSupportUser(): grp = common.MANIFEST_MOD_SUPPORT_GROUP # Support users can only inject items into optional_installs. install_types = ['optional_installs'] elif auth.IsSecurityUser(): grp = common.MANIFEST_MOD_SECURITY_GROUP # Security users can only inject items into managed_installs. install_types = ['managed_installs'] munki_pkg_names = models.PackageInfo.GetManifestModPkgNames( grp, only_names=True) if munki_pkg_name not in munki_pkg_names: self.response.out.write('You are not allowed to inject: %s' % munki_pkg_name) self.response.set_status(httplib.FORBIDDEN) return elif mod_type not in [k for k, _ in MOD_GROUP_TYPES.get(grp, [])]: self.response.out.write( 'You are not allowed to inject to: %s' % mod_type) self.response.set_status(httplib.FORBIDDEN) return # Validation. error_msg = None if not targets or not munki_pkg_name or not install_types: error_msg = ( 'target, munki_pkg_name, and install_types are all required') if not error_msg: for manifest in manifests: if manifest not in common.TRACKS: error_msg = 'manifest %s is not in %s' % (manifest, common.TRACKS) if not error_msg: for install_type in install_types: if install_type not in common.INSTALL_TYPES: error_msg = 'install_type %s is not in %s' % ( install_type, common.INSTALL_TYPES) if not error_msg: if not models.PackageInfo.all().filter('name =', munki_pkg_name).get(): error_msg = 'No package found with Munki name: %s' % munki_pkg_name if not error_msg and len(targets) > MAX_TARGETS_PER_POST: error_msg = 'too many targets' if error_msg: self.redirect('/admin/manifest_modifications?msg=%s' % error_msg) return to_put = [] for target in targets: mod = models.BaseManifestModification.GenerateInstance( mod_type, target, munki_pkg_name, manifests=manifests, install_types=install_types, user=users.get_current_user(), remove=remove_from_manifest) to_put.append(mod) gae_util.BatchDatastoreOp(db.put, to_put) for target in targets: models.BaseManifestModification.ResetModMemcache(mod_type, target) msg = 'Manifest Modification successfully saved.' self.redirect('/admin/manifest_modifications?mod_type=%s&msg=%s' % (mod_type, msg))
pkg = '%s-%s' % (name, version) entity = models.InstallLog(uuid=computer.uuid, computer=computer, package=pkg, status=status, on_corp=on_corp, applesus=applesus, unattended=unattended, duration_seconds=duration_seconds, mtime=install_datetime, dl_kbytes_per_sec=dl_kbytes_per_sec) entity.success = entity.IsSuccess() to_put.append(entity) gae_util.BatchDatastoreOp(models.db.put, to_put) def post(self): """Reports get handler. Returns: A webapp.Response() response. """ session = gaeserver.DoMunkiAuth() uuid = main_common.SanitizeUUID(session.uuid) report_type = self.request.get('_report_type') feedback_requested = self.request.get('_feedback') message = None details = None client_id = None computer = None
def _LogInstalls(self, installs, computer): """Logs a batch of installs for a given computer. Args: installs: list, of str install data from a preflight/postflight report. computer: models.Computer entity. """ if not installs: return on_corp = self.request.get('on_corp') if on_corp == '1': on_corp = True elif on_corp == '0': on_corp = False else: on_corp = None to_put = [] for install in installs: if install.startswith('Install of'): d = { 'applesus': 'false', 'duration_seconds': None, 'download_kbytes_per_sec': None, 'name': install, 'status': 'UNKNOWN', 'version': '', 'unattended': 'false', } # support for old 'Install of FooPkg-1.0: SUCCESSFUL' style strings. try: m = LEGACY_INSTALL_RESULTS_STRING_REGEX.search(install) if not m: raise ValueError elif m.group(3) == INSTALL_RESULT_SUCCESSFUL: d['status'] = 0 else: d['status'] = m.group(4) d['name'] = m.group(1) d['version'] = m.group(2) except (IndexError, AttributeError, ValueError): logging.warning('Unknown install string format: %s', install) else: # support for new 'name=pkg|version=foo|...' style strings. d = common.KeyValueStringToDict(install) name = d.get('display_name', '') or d.get('name', '') version = d.get('version', '') status = str(d.get('status', '')) applesus = common.GetBoolValueFromString(d.get('applesus', '0')) unattended = common.GetBoolValueFromString(d.get( 'unattended', '0')) try: duration_seconds = int(d.get('duration_seconds', None)) except (TypeError, ValueError): duration_seconds = None try: dl_kbytes_per_sec = int(d.get('download_kbytes_per_sec', None)) # Ignore zero KB/s download speeds, as that's how Munki reports # unknown speed. if dl_kbytes_per_sec == 0: dl_kbytes_per_sec = None except (TypeError, ValueError): dl_kbytes_per_sec = None try: install_datetime = util.Datetime.utcfromtimestamp( d.get('time', None)) except ValueError as e: logging.info('Ignoring invalid install_datetime: %s', str(e)) install_datetime = datetime.datetime.utcnow() except util.EpochExtremeFutureValueError as e: logging.info('Ignoring extreme future install_datetime: %s', str(e)) install_datetime = datetime.datetime.utcnow() except util.EpochFutureValueError: install_datetime = datetime.datetime.utcnow() pkg = '%s-%s' % (name, version) entity = models.InstallLog(uuid=computer.uuid, computer=computer, package=pkg, status=status, on_corp=on_corp, applesus=applesus, unattended=unattended, duration_seconds=duration_seconds, mtime=install_datetime, dl_kbytes_per_sec=dl_kbytes_per_sec) entity.success = entity.IsSuccess() to_put.append(entity) gae_util.BatchDatastoreOp(models.db.put, to_put)