def _power_off_instances(self, power_off_time): """ Mark all running instances belonging to this CloudAccount as powered off. Args: power_off_time (datetime.datetime): time to set when stopping the instances """ from api.util import recalculate_runs # Avoid circular import. instances = self.instance_set.all() for instance in instances: last_event = ( InstanceEvent.objects.filter(instance=instance) .order_by("-occurred_at") .first() ) if last_event and last_event.event_type != InstanceEvent.TYPE.power_off: content_object_class = last_event.content_object.__class__ cloud_specific_event = content_object_class.objects.create() event = InstanceEvent.objects.create( event_type=InstanceEvent.TYPE.power_off, occurred_at=power_off_time, instance=instance, content_object=cloud_specific_event, ) recalculate_runs(event)
def recalculate_runs_from_events(events): """ Run recalculate_runs on multiple events. Args: events (list(model.InstanceEvents)): events to recalculate """ for event in events: recalculate_runs(event)
def process_instance_event(event): """ Process instance events that have been saved during log analysis. Note: When processing power_on type events, this triggers a recalculation of ConcurrentUsage objects. If the event is at some point in the not-too-recent past, this may take a while as every day since the event will get recalculated and saved. We do not anticipate this being a real problem in practice, but this has the potential to slow down unit test execution over time since their occurred_at values are often static and will recede father into the past from "today", resulting in more days needing to recalculate. This effect could be mitigated in tests by patching parts of the datetime module that are used to find "today". """ after_run = Q(start_time__gt=event.occurred_at) during_run = Q(start_time__lte=event.occurred_at, end_time__gt=event.occurred_at) during_run_no_end = Q(start_time__lte=event.occurred_at, end_time=None) filters = after_run | during_run | during_run_no_end instance = Instance.objects.get(id=event.instance_id) if Run.objects.filter(filters, instance=instance).exists(): recalculate_runs(event) elif event.event_type == InstanceEvent.TYPE.power_on: normalized_runs = normalize_runs([event]) runs = [] for index, normalized_run in enumerate(normalized_runs): logger.info("Processing run {} of {}".format( index + 1, len(normalized_runs))) run = Run( start_time=normalized_run.start_time, end_time=normalized_run.end_time, machineimage_id=normalized_run.image_id, instance_id=normalized_run.instance_id, instance_type=normalized_run.instance_type, memory=normalized_run.instance_memory, vcpu=normalized_run.instance_vcpu, ) run.save() runs.append(run) calculate_max_concurrent_usage_from_runs(runs)