private static void KillAndResetVirtualMachine(HypervVirtualMachine virtualMachine, HypervMachineDescription specification) { virtualMachine.Terminate(); DateTimeOffset killTime = DateTimeOffset.Now + TimeSpan.FromMilliseconds(GlobalConstants.DefaultMaximumMachineShutdownTime); while ((virtualMachine.State != HypervVirtualMachineState.TurnedOff) && (DateTimeOffset.Now <= killTime)) { Thread.Sleep(10); } virtualMachine.RestoreToSnapshot(specification.SnapshotToReturnTo); }
private void ShutdownVirtualMachine(MachineDescription environment, ITestSectionBuilder sectionBuilder) { var specification = environment as HypervMachineDescription; if (specification == null) { throw new InvalidEnvironmentSpecificationException(); } // See if the host machine is alive var host = specification.HostMachineId; var hostSpecification = m_EnvironmentById(host); if (hostSpecification == null) { sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Could not locate VM host: {0}", hostSpecification.NetworkName)); sectionBuilder.FinalizeAndStore(false); throw new CouldNotLoadEnvironmentException(); } Diagnostics.Log( LevelToLog.Debug, HyperVConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Terminating Hyper-V virtual machine {0} [image: {1}] on host {2}", specification.Name, specification.Image, hostSpecification.Name)); // Connect to the Hyper-V host for the given environment var virtualMachine = new HypervVirtualMachine(specification.Image); try { virtualMachine.Terminate(); } catch (FailedToRestoreEnvironmentException) { sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Failed to shut down virtual machine: {0}", specification.NetworkName)); sectionBuilder.FinalizeAndStore(false); throw; } var killTime = DateTimeOffset.Now + TimeSpan.FromMilliseconds(GlobalConstants.DefaultMaximumMachineShutdownTime); while ((virtualMachine.State != HypervVirtualMachineState.TurnedOff) && (DateTimeOffset.Now <= killTime)) { Thread.Sleep(10); } try { virtualMachine.RestoreToSnapshot(specification.SnapshotToReturnTo); } catch (FailedToRestoreEnvironmentException) { sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Failed to restore virtual machine snapshot [{0}] for machine {1}", specification.SnapshotToReturnTo, specification.NetworkName)); sectionBuilder.FinalizeAndStore(false); throw; } Diagnostics.Log( LevelToLog.Debug, HyperVConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Hyper-V virtual machine {0} terminated", specification.Name)); sectionBuilder.AddInformationMessage( string.Format( CultureInfo.InvariantCulture, "Virtual machine shut down: {0}", specification.NetworkName)); sectionBuilder.FinalizeAndStore(true); }
/// <summary> /// Load the environment. /// </summary> /// <param name="environment">The specification for the environment.</param> /// <param name="pingTimeoutInMilliseconds">The number of milliseconds that the ping operation should wait for a response.</param> /// <param name="maximumWaitTimeInMilliseconds"> /// The number of milliseconds that the operation should wait for the machine to come online. /// </param> /// <param name="pingCycleTimeInMilliseconds">The amount of time the operation should wait between consecutive ping operations.</param> /// <param name="sectionBuilder"> /// The object used to write information to the report about the starting and stopping of the environment. /// </param> /// <returns>An action that should be used to return the environment to its previous state in case the environment load fails.</returns> protected override Action LoadEnvironment( MachineDescription environment, int pingTimeoutInMilliseconds, int maximumWaitTimeInMilliseconds, int pingCycleTimeInMilliseconds, ITestSectionBuilder sectionBuilder) { var specification = environment as HypervMachineDescription; if (specification == null) { throw new InvalidEnvironmentSpecificationException(); } // See if the host machine is alive var host = specification.HostMachineId; var hostSpecification = m_EnvironmentById(host); if (hostSpecification == null) { sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Unable to locate host machine: {0}", hostSpecification.NetworkName)); sectionBuilder.FinalizeAndStore(false); throw new CouldNotLoadEnvironmentException(); } // See if the host is awake and if not try to wake it up. var physicalHostSpecification = hostSpecification as PhysicalMachineDescription; var canStartRemotely = physicalHostSpecification != null && physicalHostSpecification.CanStartRemotely; if (!MachineHelpers.WakeNetworkedMachineAndWaitForNetworkSignIn( hostSpecification.NetworkName, hostSpecification.MacAddress, Diagnostics, canStartRemotely, pingTimeoutInMilliseconds, maximumWaitTimeInMilliseconds, pingCycleTimeInMilliseconds)) { sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Unable to start host machine: {0}", hostSpecification.NetworkName)); sectionBuilder.FinalizeAndStore(false); throw new CouldNotLoadEnvironmentException(); } // Connect to the Hyper-V host for the given environment var virtualMachine = new HypervVirtualMachine(specification.Image); if (virtualMachine.State == HypervVirtualMachineState.Paused || virtualMachine.State == HypervVirtualMachineState.Running) { sectionBuilder.AddWarningMessage( string.Format( CultureInfo.InvariantCulture, "Virtual machine running unexpectedly: {0}", specification.NetworkName)); sectionBuilder.AddWarningMessage( string.Format( CultureInfo.InvariantCulture, "Resetting virtual machine: {0}", specification.NetworkName)); KillAndResetVirtualMachine(virtualMachine, specification); } virtualMachine.Start(); Diagnostics.Log( LevelToLog.Debug, HyperVConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Started Hyper-V virtual machine {0} [image: {1}] on host {2}", specification.Name, specification.Image, hostSpecification.Name)); sectionBuilder.AddInformationMessage( string.Format( CultureInfo.InvariantCulture, "Started machine: {0}", specification.NetworkName)); return () => { Diagnostics.Log( LevelToLog.Debug, HyperVConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Terminating Hyper-V virtual machine {0} [image: {1}] on host {2}", specification.Name, specification.Image, hostSpecification.Name)); KillAndResetVirtualMachine(virtualMachine, specification); sectionBuilder.AddErrorMessage( string.Format( CultureInfo.InvariantCulture, "Terminated machine: {0}", specification.NetworkName)); sectionBuilder.FinalizeAndStore(false); }; }