/* Copyright (c) Cloud Software Group, Inc. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System.Collections.Generic; using System.Linq; using Moq; using NUnit.Framework; using XenAdmin.Network; using XenAdmin.XenSearch; using XenAPI; namespace XenAdminTests.SearchTests { [TestFixture, Category(TestCategories.Unit)] public class VirtualisationStatePropertyQueryTests { private List> _allVms = new List>(); [OneTimeSetUp] public void TestFixtureSetUp() { var conn = new Mock(MockBehavior.Strict); conn.Setup(x => x.Name).Returns("conn"); var cache = new Cache(); conn.Setup(x => x.Cache).Returns(cache); var host = new Mock(); host.Object.Connection = conn.Object; host.Object.opaque_ref = "OpaqueRef:host"; host.Setup(x => x.PlatformVersion()).Returns("3.2.0"); var pool = new Mock(); pool.Object.Connection = conn.Object; pool.Setup(x => x.master).Returns(new XenRef(host.Object.opaque_ref)); //Linux VM with outdated tools var m0 = new Mock(); m0.Object.Connection = conn.Object; m0.Object.opaque_ref = "OpaqueRef:m0"; var g0 = new Mock(); g0.Object.Connection = conn.Object; g0.Object.opaque_ref = "OpaqueRef:g0"; g0.Setup(x => x.PV_drivers_detected).Returns(true); g0.Setup(x => x.PV_drivers_up_to_date).Returns(false); g0.Setup(x => x.PV_drivers_version).Returns(new Dictionary {{"major", "1"}, {"minor", "1"}}); var vm0 = new Mock(); vm0.Object.Connection = conn.Object; vm0.Setup(x => x.Name()).Returns("vm0"); vm0.Setup(x => x.power_state).Returns(vm_power_state.Running); vm0.Setup(x => x.guest_metrics).Returns(new XenRef(g0.Object.opaque_ref)); vm0.Setup(x => x.metrics).Returns(new XenRef(m0.Object.opaque_ref)); //Linux VM with up to date tools var m1 = new Mock(); m1.Object.Connection = conn.Object; m1.Object.opaque_ref = "OpaqueRef:m1"; var g1 = new Mock(); g1.Object.Connection = conn.Object; g1.Object.opaque_ref = "OpaqueRef:g1"; g1.Setup(x => x.PV_drivers_detected).Returns(true); g1.Setup(x => x.PV_drivers_up_to_date).Returns(true); g1.Setup(x => x.PV_drivers_version).Returns(new Dictionary {{"major", "9"}, {"minor", "0"}}); var vm1 = new Mock(); vm1.Object.Connection = conn.Object; vm1.Setup(x => x.Name()).Returns("vm1"); vm1.Setup(x => x.power_state).Returns(vm_power_state.Running); vm1.Setup(x => x.guest_metrics).Returns(new XenRef(g1.Object.opaque_ref)); vm1.Setup(x => x.metrics).Returns(new XenRef(m1.Object.opaque_ref)); //Windows VM without tools var m2 = new Mock(); m2.Object.Connection = conn.Object; m2.Object.opaque_ref = "OpaqueRef:m2"; var g2 = new Mock(); g2.Object.Connection = conn.Object; g2.Object.opaque_ref = "OpaqueRef:g2"; g2.Setup(x => x.PV_drivers_detected).Returns(false); var vm2 = new Mock(); vm2.Object.Connection = conn.Object; vm2.Setup(x => x.Name()).Returns("vm2"); vm2.Setup(x => x.power_state).Returns(vm_power_state.Running); vm2.Setup(x => x.HVM_boot_policy).Returns("BIOS order"); vm2.Setup(x => x.platform).Returns(new Dictionary {{"viridian", "true"}}); vm2.Setup(x => x.guest_metrics).Returns(new XenRef(g2.Object.opaque_ref)); vm2.Setup(x => x.metrics).Returns(new XenRef(m2.Object.opaque_ref)); //Windows VM IO optimised only var m3 = new Mock(); m3.Object.Connection = conn.Object; m3.Object.opaque_ref = "OpaqueRef:m3"; var g3 = new Mock(); g3.Object.Connection = conn.Object; g3.Object.opaque_ref = "OpaqueRef:g3"; g3.Setup(x => x.PV_drivers_detected).Returns(true); var vm3 = new Mock(); vm3.Object.Connection = conn.Object; vm3.Setup(x => x.Name()).Returns("vm3"); vm3.Setup(x => x.power_state).Returns(vm_power_state.Running); vm3.Setup(x => x.HVM_boot_policy).Returns("BIOS order"); vm3.Setup(x => x.platform).Returns(new Dictionary {{"viridian", "true"}}); vm3.Setup(x => x.guest_metrics).Returns(new XenRef(g3.Object.opaque_ref)); vm3.Setup(x => x.metrics).Returns(new XenRef(m3.Object.opaque_ref)); //Windows VM with management agent installed only var m4 = new Mock(); m4.Object.Connection = conn.Object; m4.Object.opaque_ref = "OpaqueRef:m4"; var g4 = new Mock(); g4.Object.Connection = conn.Object; g4.Object.opaque_ref = "OpaqueRef:g4"; g4.Setup(x => x.PV_drivers_detected).Returns(false); g4.Setup(x => x.other).Returns(new Dictionary {{"feature-static-ip-setting", "1"}}); var vm4 = new Mock(); vm4.Object.Connection = conn.Object; vm4.Setup(x => x.Name()).Returns("vm4"); vm4.Setup(x => x.power_state).Returns(vm_power_state.Running); vm4.Setup(x => x.HVM_boot_policy).Returns("BIOS order"); vm4.Setup(x => x.platform).Returns(new Dictionary {{"viridian", "true"}}); vm4.Setup(x => x.guest_metrics).Returns(new XenRef(g4.Object.opaque_ref)); vm4.Setup(x => x.metrics).Returns(new XenRef(m4.Object.opaque_ref)); //Windows VM fully optimised var m5 = new Mock(); m5.Object.Connection = conn.Object; m5.Object.opaque_ref = "OpaqueRef:m5"; var g5 = new Mock(); g5.Object.Connection = conn.Object; g5.Object.opaque_ref = "OpaqueRef:g5"; g5.Setup(x => x.PV_drivers_detected).Returns(true); g5.Setup(x => x.other).Returns(new Dictionary {{"feature-static-ip-setting", "1"}}); var vm5 = new Mock(); vm5.Object.Connection = conn.Object; vm5.Setup(x => x.Name()).Returns("vm5"); vm5.Setup(x => x.power_state).Returns(vm_power_state.Running); vm5.Setup(x => x.HVM_boot_policy).Returns("BIOS order"); vm5.Setup(x => x.platform).Returns(new Dictionary {{"viridian", "true"}}); vm5.Setup(x => x.guest_metrics).Returns(new XenRef(g5.Object.opaque_ref)); vm5.Setup(x => x.metrics).Returns(new XenRef(m5.Object.opaque_ref)); //Linux VM with unknown state var m6 = new Mock(); m6.Object.Connection = conn.Object; m6.Object.opaque_ref = "OpaqueRef:m6"; var vm6 = new Mock(); vm6.Object.Connection = conn.Object; vm6.Setup(x => x.Name()).Returns("vm6"); vm6.Setup(x => x.power_state).Returns(vm_power_state.Running); vm6.Setup(x => x.metrics).Returns(new XenRef(m6.Object.opaque_ref)); _allVms.AddRange(new[] {vm0, vm1, vm2, vm3, vm4, vm5, vm6}); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m0"))).Returns(m0.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m1"))).Returns(m1.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m2"))).Returns(m2.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m3"))).Returns(m3.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m4"))).Returns(m4.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m5"))).Returns(m5.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:m6"))).Returns(null as VM_metrics); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g0"))).Returns(g0.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g1"))).Returns(g1.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g2"))).Returns(g2.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g3"))).Returns(g3.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g4"))).Returns(g4.Object); conn.Setup(x => x.Resolve(new XenRef("OpaqueRef:g5"))).Returns(g5.Object); } [Test, Sequential] [TestCase("Not optimized", new[] {"vm2"})] [TestCase("Unknown", new[] {"vm6"})] [TestCase("Out of date", new[] {"vm0"})] [TestCase("I/O optimized only", new[] {"vm3"})] [TestCase("Management Agent installed only", new[] {"vm4"})] [TestCase("Fully optimized", new[] {"vm1", "vm5"})] public void TestVirtStatusIs(string filter, string[] expectedVmNames) { var dict = PropertyAccessors.Geti18nFor(PropertyNames.virtualisation_status) as Dictionary; Assert.NotNull(dict, "Did not find i18n for VM.VirtualisationStatus"); Assert.IsTrue(dict.TryGetValue(filter, out var status), $"Did not find i18n for {filter}"); var query = new EnumPropertyQuery(PropertyNames.virtualisation_status, status, true); CheckMatch(query, expectedVmNames); } [Test, Sequential] [TestCase("Not optimized", new[] {"vm0", "vm1", "vm3", "vm4", "vm5", "vm6"})] [TestCase("Unknown", new[] {"vm0", "vm1", "vm2", "vm3", "vm4", "vm5"})] [TestCase("Out of date", new[] {"vm1", "vm2", "vm3", "vm4", "vm5", "vm6"})] [TestCase("I/O optimized only", new[] {"vm0", "vm1", "vm2", "vm4", "vm5", "vm6"})] [TestCase("Management Agent installed only", new[] {"vm0", "vm1", "vm2", "vm3", "vm5", "vm6"})] [TestCase("Fully optimized", new[] {"vm0", "vm2", "vm3", "vm4", "vm6"})] public void TestVirtStatusIsNot(string filter, string[] expectedVmNames) { var dict = PropertyAccessors.Geti18nFor(PropertyNames.virtualisation_status) as Dictionary; Assert.NotNull(dict, "Did not find i18n for VM.VirtualisationStatus"); Assert.IsTrue(dict.TryGetValue(filter, out var status), $"Did not find i18n for {filter}"); var query = new EnumPropertyQuery(PropertyNames.virtualisation_status, status, false); CheckMatch(query, expectedVmNames); } private void CheckMatch(EnumPropertyQuery query, string[] expectedVmNames) { foreach (var moqVm in _allVms) { var vm = moqVm.Object; bool? match = query.MatchProperty(vm.GetVirtualisationStatus(out _)); Assert.True(match.HasValue); var name = vm.Name(); if (expectedVmNames.Contains(name)) Assert.True(match.Value, $"VM {name} was not in the expected query results"); else Assert.False(match.Value, $"Found unexpected VM {name} in the query results"); } } } }