def _process_project(project, bucket): """Collects coverage information for all fuzz targets in the given project and the total stats for the project.""" project_name = _basename(project) logs.log('Processing coverage for %s project.' % project_name) report_path = storage.get_cloud_storage_file_path(bucket, project) report_info = _read_json(report_path) if not report_info: logs.log_warn('Skipping code coverage for %s project.' % project_name) return # Iterate through report_info['fuzzer_stats_dir'] and prepare # CoverageInformation entities for invididual fuzz targets. entities = [] for fuzzer in storage.list_blobs(report_info['fuzzer_stats_dir'], recursive=False): entities.append( _process_fuzzer_stats(fuzzer, report_info, project_name, bucket)) logs.log('Processed coverage for %d targets in %s project.' % (len(entities), project_name)) # Prepare CoverageInformation entity for the total project stats. entities.append(_process_project_stats(report_info, project_name)) ndb_utils.put_multi(entities)
def _query_and_upload_strategy_probabilities(engine): """Uploads queried data into datastore. Calls query functions and uploads query results to datastore to use as new probabilities. Probabilities are based on new_edges feature.""" strategy_data = [] data = _query_multi_armed_bandit_probabilities(engine) logs.log('Queried distribution for {}.'.format(engine.name)) # TODO(mukundv): Update once we choose a temperature parameter for final # implementation. for row in data: curr_strategy = data_types.FuzzStrategyProbability() curr_strategy.strategy_name = str(row['strategy']) curr_strategy.probability = float(row['bandit_weight']) curr_strategy.engine = engine.name strategy_data.append(curr_strategy) query = data_types.FuzzStrategyProbability.query( data_types.FuzzStrategyProbability.engine == engine.name) ndb_utils.delete_multi( [entity.key for entity in ndb_utils.get_all_from_query(query)]) ndb_utils.put_multi(strategy_data) logs.log('Uploaded queried distribution to ndb for {}'.format(engine.name)) _store_probabilities_in_bigquery(engine, data) logs.log('Uploaded queried distribution to BigQuery for {}'.format( engine.name))
def execute(args): """Build keywords.""" count_diff = 0 query = data_types.Testcase.query().order(-data_types.Testcase.timestamp) for testcases in batcher.iterate(query, BATCH_SIZE): for testcase in testcases: before_testcase = to_dict(testcase) attribute_builder.populate(testcase) after_testcase = to_dict(testcase) diff = get_diff(before_testcase, after_testcase) if (count_diff % 10) == 0 and diff: print('Migrate (dry=%s) id:%s\n%s' % (not args.non_dry_run, testcase.key.id(), diff)) if diff: count_diff += 1 if args.non_dry_run: try: ndb_utils.put_multi(testcases) except Exception: for testcase in testcases: try: testcase.put() except Exception: print('Error: %s %s' % (testcase.key.id(), sys.exc_info())) print('Done (count_diff=%d)' % count_diff)
def update_mappings_for_fuzzer(fuzzer, mappings=None): """Clear existing mappings for a fuzzer, and replace them.""" if mappings is None: mappings = fuzzer.jobs query = data_types.FuzzerJob.query() query = query.filter(data_types.FuzzerJob.fuzzer == fuzzer.name) entities = ndb_utils.get_all_from_query(query) old_mappings = {} for entity in entities: old_mappings[entity.job] = entity new_mappings = [] for job_name in mappings: mapping = old_mappings.pop(job_name, None) if mapping: continue job = data_types.Job.query(data_types.Job.name == job_name).get() if not job: logs.log_error('An unknown job %s was selected for fuzzer %s.' % (job_name, fuzzer.name)) continue mapping = data_types.FuzzerJob() mapping.fuzzer = fuzzer.name mapping.job = job_name mapping.platform = job.platform new_mappings.append(mapping) ndb_utils.put_multi(new_mappings) ndb_utils.delete_multi([m.key for m in list(old_mappings.values())])
def update_platform_for_job(job_name, new_platform): """Update platform for all mappings for a particular job.""" query = data_types.FuzzerJob.query() query = query.filter(data_types.FuzzerJob.job == job_name) mappings = ndb_utils.get_all_from_query(query) new_mappings = [] for mapping in mappings: mapping.platform = new_platform new_mappings.append(mapping) ndb_utils.put_multi(new_mappings)
def update_project_cpus(self, projects, project_infos, high_end_projects, high_end_project_infos, cluster): """Update CPU allocations for each project.""" # Calculate CPUs in each cluster. if not cluster.distribute: self.pending_updates.append( self.thread_pool.submit(self.update_cluster, cluster, cluster.name, cluster.instance_count)) return if cluster.high_end: current_projects = high_end_projects current_project_infos = high_end_project_infos else: current_projects = projects current_project_infos = project_infos cpu_counts = self.distribute_cpus(current_projects, cluster.instance_count) # Resize projects starting with ones that reduce number of CPUs. This is # so that we always have quota when we're resizing a project cluster. # pylint: disable=cell-var-from-loop def _cpu_diff_key(index): cluster_info = current_project_infos[index].get_cluster_info( cluster.name) if cluster_info and cluster_info.cpu_count is not None: old_cpu_count = cluster_info.cpu_count else: old_cpu_count = 0 return cpu_counts[index] - old_cpu_count resize_order = sorted(list(range(len(cpu_counts))), key=_cpu_diff_key) for i in resize_order: project = current_projects[i] project_info = current_project_infos[i] self.update_project_cluster(project, project_info, cluster, cpu_counts[i], disk_size_gb=project.disk_size_gb) self.wait_updates() ndb_utils.put_multi(project_infos) ndb_utils.put_multi(high_end_project_infos) # If the workers are done, we're ready to assign them. # Note: This assumes that hosts are always specified before workers. if cluster.name in self.worker_to_assignment: self.assign_hosts_to_workers( self.worker_to_assignment[cluster.name])
def assign_hosts_to_workers(self, assignment): """Assign host instances to workers.""" host_cluster = self.gce_project.get_cluster(assignment.host) worker_cluster = self.gce_project.get_cluster(assignment.worker) if host_cluster.gce_zone != worker_cluster.gce_zone: logging.error('Mismatching zones for %s and %s.', assignment.host, assignment.worker) return if (host_cluster.instance_count * assignment.workers_per_host != worker_cluster.instance_count): logging.error('Invalid host/worker cluster size for %s and %s.', assignment.host, assignment.worker) return if host_cluster.high_end != worker_cluster.high_end: logging.error('Mismatching high end setting for %s and %s', assignment.host, assignment.worker) return manager = bot_manager.BotManager(self.gce_project.project_id, host_cluster.gce_zone) host_instance_group = manager.instance_group(host_cluster.name) if not host_instance_group.exists(): logging.error('Host instance group %s does not exist.', host_cluster.name) return host_names = [ _instance_name_from_url(instance['instance']) for instance in host_instance_group.list_managed_instances() ] self.all_host_names.update(host_names) worker_instances = self.get_all_workers_in_cluster( manager, worker_cluster.name) if len(worker_instances) != worker_cluster.instance_count: logging.error( 'Actual number of worker instances for %s did not match. ' 'Expected %d, got %d.', worker_cluster.name, worker_cluster.instance_count, len(worker_instances)) return new_assignments = self.do_assign_hosts_to_workers( host_names, worker_instances, assignment.workers_per_host) ndb_utils.put_multi(new_assignments)
def update_job_weight(job_name, multiplier): """Update a job weight.""" tool_name = environment.get_memory_tool_name(job_name) multiplier *= SANITIZER_WEIGHTS.get(tool_name, DEFAULT_SANITIZER_WEIGHT) engine = environment.get_engine_for_job(job_name) multiplier *= ENGINE_WEIGHTS.get(engine, DEFAULT_ENGINE_WEIGHT) query = data_types.FuzzerJob.query(data_types.FuzzerJob.job == job_name) changed_weights = [] for fuzzer_job in query: if fuzzer_job.multiplier != multiplier: fuzzer_job.multiplier = multiplier changed_weights.append(fuzzer_job) if changed_weights: ndb_utils.put_multi(changed_weights)