Repository: canonical/multipass (C++)

Issue:
Daemon fails to start intermittently on Windows
The daemon fails to start due to an exception being thrown in the Hyper-V VM constructor:

```
[powershell.exe] At line:1 char:1
+ Set-VM -Name testing-20-04 -AutomaticCheckpointsEnabled $false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Set-VM], VirtualizationException
    + FullyQualifiedErrorId : InvalidState,Microsoft.HyperV.PowerShell.Commands.SetVM

[testing-20-04] [9524] stderr: Set-VM : Modifying the properties of 'testing-20-04' failed.
The operation cannot be performed while the object is in its current state.
At line:1 char:1
+ Set-VM -Name testing-20-04 -AutomaticCheckpointsEnabled $false
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Set-VM], VirtualizationException
    + FullyQualifiedErrorId : InvalidState,Microsoft.HyperV.PowerShell.Commands.SetVM
```

The culprit is this line:

```c++
    power_shell->easy_run({"Set-VM", "-Name", name, "-AutomaticCheckpointsEnabled", "$false"},
                          "Could not disable automatic snapshots"); // TODO move to new VMs only in
```

The reason is that sometimes the VM is not in an appropriate state for setting the automatic checkpoint status, which causes an exception to be thrown in the Hyper-V VM constructor. This exception is then propagated to the daemon constructor and eventually leads to a crash.


Discussion:

Patch:
diff --git a/src/platform/backends/hyperv/hyperv_virtual_machine.cpp b/src/platform/backends/hyperv/hyperv_virtual_machine.cpp
index f012d1dc86..d8370ba0ff 100644
--- a/src/platform/backends/hyperv/hyperv_virtual_machine.cpp
+++ b/src/platform/backends/hyperv/hyperv_virtual_machine.cpp
@@ -106,15 +106,6 @@ auto instance_state_for(mp::PowerShell* power_shell, const QString& name)
     return mp::VirtualMachine::State::unknown;
 }
 
-void delete_automatic_snapshots(mp::PowerShell* power_shell, const QString& name)
-{
-    power_shell->easy_run(
-        {"Get-VMCheckpoint -VMName",
-         name,
-         "| Where-Object { $_.IsAutomaticCheckpoint } | Remove-VMCheckpoint -Confirm:$false"},
-        "Could not delete existing automatic checkpoints");
-}
-
 void add_extra_net(mp::PowerShell& ps,
                    const QString& vm_name,
                    const mp::NetworkInterface& extra_interface)
@@ -193,6 +184,8 @@ mp::HyperVVirtualMachine::HyperVVirtualMachine(const VirtualMachineDescription&
             "Could not setup cloud-init drive");
         power_shell->easy_run({"Set-VMMemory", "-VMName", name, "-DynamicMemoryEnabled", "$false"},
                               "Could not disable dynamic memory");
+        power_shell->easy_run({"Set-VM", "-Name", name, "-AutomaticCheckpointsEnabled", "$false"},
+                              "Could not disable automatic snapshots");
 
         setup_network_interfaces();
 
@@ -202,12 +195,6 @@ mp::HyperVVirtualMachine::HyperVVirtualMachine(const VirtualMachineDescription&
     {
         state = instance_state_for(power_shell.get(), name);
     }
-
-    power_shell->easy_run({"Set-VM", "-Name", name, "-AutomaticCheckpointsEnabled", "$false"},
-                          "Could not disable automatic snapshots"); // TODO move to new VMs only in
-                                                                    // a couple of releases
-    delete_automatic_snapshots(power_shell.get(),
-                               name); // TODO drop in a couple of releases (going in on v1.13)
 }
 
 mp::HyperVVirtualMachine::HyperVVirtualMachine(const std::string& source_vm_name,


Test patch:
diff --git a/tests/hyperv/test_hyperv_backend.cpp b/tests/hyperv/test_hyperv_backend.cpp
index 6c4346435f..11a95bc878 100644
--- a/tests/hyperv/test_hyperv_backend.cpp
+++ b/tests/hyperv/test_hyperv_backend.cpp
@@ -114,8 +114,9 @@ struct HyperVBackend : public Test
                                                                  {"-EnableSecureBoot Off"},
                                                                  {"Set-VMProcessor"},
                                                                  {"Add-VMDvdDrive"},
-                                                                 {"Set-VMMemory"}};
-    inline static const std::vector<RunSpec> postfix_ctor_runs = {{"Set-VM"}, {"Get-VMCheckpoint"}};
+                                                                 {"Set-VMMemory"},
+                                                                 {"Set-VM"}};
+    inline static const std::vector<RunSpec> postfix_ctor_runs = {};
     inline static const RunSpec default_network_run = {"Set-VMNetworkAdapter"};
     inline static const RunSpec min_dtor_run = {"-ExpandProperty State", "Off"};