/// <summary>
        /// Initializes a new instance of the <see cref="HypervMachineModel"/> class.
        /// </summary>
        /// <param name="model">The object that handles the data storage.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="model"/> is <see langword="null" />.
        /// </exception>
        public HypervMachineModel(HypervMachineDescription model)
            : base(model)
        {
            {
                Lokad.Enforce.Argument(() => model);
            }

            m_Model = model;
        }
        /// <summary>
        /// Adds a new Hyper-V machine.
        /// </summary>
        /// <param name="machine">The new machine.</param>
        public void Add(HypervMachineDescription machine)
        {
            VerifySchemaVersion();

            var result = StoredMachineDescriptions.Add(machine) as HypervMachineDescription;
            Debug.Assert(result != null, "The machine should be a Hyper-V machine.");

            Patch(result);
        }
        private void Update(HypervMachineDescription stored, HypervMachineDescription changed)
        {
            var shouldPatch = Update(stored as MachineDescription, changed as MachineDescription);
            stored.Image = changed.Image;
            stored.SnapshotToReturnTo = changed.SnapshotToReturnTo;
            if (!string.Equals(stored.HostMachineId, changed.HostMachineId, StringComparison.Ordinal))
            {
                stored.HostMachine.HypervMachines.Remove(stored);

                stored.HostMachineId = changed.HostMachineId;
                stored.HostMachine = null;

                shouldPatch = true;
            }

            if (shouldPatch)
            {
                stored.IsPatched = false;
                Patch(stored);
            }
        }
        private HypervMachineDescription Patch(HypervMachineDescription description)
        {
            var result = (StoredMachineDescriptions.Find(description.Id) ?? StoredMachineDescriptions.Add(description)) as HypervMachineDescription;
            Debug.Assert(result != null, "The machine should be a Hyper-V machine.");

            if (!result.IsPatched && !result.IsPatching)
            {
                result.IsPatching = true;
                try
                {
                    result.HypervMachines = new List<HypervMachineDescription>();

                    var selectedMachineApplications = GetMachineApplicationByMachineId(result.Id)
                        .Select(Patch)
                        .ToList();
                    result.MachineApplications = selectedMachineApplications;

                    var selectedOperatingSystem = GetOperatingSystemsById(result.OperatingSystemId)
                        .Select(Patch)
                        .FirstOrDefault();
                    result.OperatingSystem = selectedOperatingSystem;
                    result.HostMachine = Machine(result.HostMachineId);

                    var selectedTestEnvironments = GetTestEnvironmentByMachineId(result.Id)
                        .Select(Patch)
                        .ToList();
                    result.TestEnvironments = selectedTestEnvironments;

                    result.IsPatched = true;
                }
                finally
                {
                    result.IsPatching = false;
                }
            }

            return result;
        }
        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);
        }