diff --git a/instances/jobs.py b/instances/jobs.py index d59919e1..8dd43110 100644 --- a/instances/jobs.py +++ b/instances/jobs.py @@ -968,7 +968,6 @@ class MigrateInstance(Kind): ctx.record_intent() ctx.set_phase(gettext_noop("Migrating the VM")) try: - # migrate_instance logs the outcome utils.migrate_instance(Compute.objects.get(pk=p["target"]), instance, op.user, disk_pools=p["disk_pools"], **{k: p[k] for k in MIGRATE_OPTIONS}) @@ -982,8 +981,19 @@ class MigrateInstance(Kind): if isinstance(err, util.OperationError): raise raise util.OperationError(str(err)) from err + finally: + # migrate_instance wrote the outcome's Logs row (log_entry) + ctx.record_intent(outcome_logged=True) return {} + def log_entry(self, op, state): + """A row for an end migrate_instance did not log: refused before it + ran, cancelled while queued, or ended by recovery.""" + if op.intent.get("outcome_logged"): + return None + target = Compute.objects.filter(pk=op.params["target"]).values_list("name", flat=True).first() + return _log(op, state, f"migrate to {target}") + def progress(self, op): info = _proxy(_instance(op.params["instance"])).instance.jobInfo() return (info[4], info[3]) if info[3] else None diff --git a/instances/tests/test_migrate_job.py b/instances/tests/test_migrate_job.py index cca07075..3bb01429 100644 --- a/instances/tests/test_migrate_job.py +++ b/instances/tests/test_migrate_job.py @@ -213,3 +213,18 @@ class MigrateJobTestCase(TransactionTestCase): proxy.return_value.instance.isActive.return_value = False get_kind(op.kind).cancel(op) proxy.return_value.instance.abortJob.assert_not_called() + + def test_each_end_of_a_migration_leaves_one_logs_row(self): + from logs.models import Logs + + op = self.queue(live_migrate="true") + ctx = self.start(op) + get_kind(op.kind).run(op, ctx) # migrate_instance writes its row + op.refresh_from_db() + self.assertIsNone(MigrateInstance().log_entry(op, Operation.SUCCEEDED)) + self.assertEqual(Logs.objects.filter(instance_uuid=UUID).count(), 1) + # ended without migrate_instance: refused, cancelled while queued, or by recovery + queued = Operation(params={"instance": self.vm.pk, "target": self.dest.pk}, intent={"uuid": UUID}, + resource_label="mig-src/mig-vm") + self.assertEqual(MigrateInstance().log_entry(queued, Operation.CANCELLED), + ("mig-src", "mig-vm", UUID, "VM mig-vm: migrate to mig-dst (cancelled)"))