mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-30 07:40:13 +01:00
427 lines
19 KiB
C#
427 lines
19 KiB
C#
|
/* Copyright (c) Citrix Systems Inc.
|
|||
|
* All rights reserved.
|
|||
|
*
|
|||
|
* 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;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using Moq;
|
|||
|
using NUnit.Framework;
|
|||
|
using XenAdmin;
|
|||
|
using XenAdmin.Controls;
|
|||
|
using XenAPI;
|
|||
|
|
|||
|
namespace XenAdminTests.Controls
|
|||
|
{
|
|||
|
public class SrPickerItemTests : DatabaseTester_TestFixture
|
|||
|
{
|
|||
|
private const string dbName = "TampaTwoHostPoolSelectioniSCSI.xml";
|
|||
|
private const string slaveHost = "dt16";
|
|||
|
private const string masterHost = "dt23";
|
|||
|
private const string largeISCSI = "large iSCSI";
|
|||
|
private const string mediumISCSI = "medium iSCSI";
|
|||
|
private const string smallISCSI = "small iSCSI";
|
|||
|
|
|||
|
public SrPickerItemTests() : base(dbName) { }
|
|||
|
|
|||
|
private class TestData
|
|||
|
{
|
|||
|
public long DiskSize;
|
|||
|
public SR Sr;
|
|||
|
public VDI[] VdisToMove;
|
|||
|
public Host Affinity;
|
|||
|
public string ExpectedFailureDescription;
|
|||
|
public override string ToString()
|
|||
|
{
|
|||
|
return String.Format("SR: {0}, Affinity {1}", Sr.name_label, Affinity.Name);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region Test Data
|
|||
|
private IEnumerable<TestData> CannotMigrateTestData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
yield return new TestData //iscsi shared -> local slave with restricted space
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
Sr = GetLocalSr(slaveHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => !v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
DiskSize = 8000000000000,
|
|||
|
ExpectedFailureDescription = "7450.58 GB required when only 220.28 GB available"
|
|||
|
};
|
|||
|
yield return new TestData //Local master to slave local
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
Sr = GetLocalSr(slaveHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.LOCAL_TO_LOCAL_MOVE
|
|||
|
};
|
|||
|
yield return new TestData //Master and slave VDIs selected together from a iSCSI -> master local SR
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.SRPICKER_ERROR_LOCAL_SR_MUST_BE_RESIDENT_HOSTS
|
|||
|
};
|
|||
|
yield return new TestData //Master VDI to a slave move
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
Sr = GetLocalSr(slaveHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.SRPICKER_ERROR_LOCAL_SR_MUST_BE_RESIDENT_HOSTS
|
|||
|
};
|
|||
|
yield return new TestData //Slave VDI to a master move
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => !v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.SRPICKER_ERROR_LOCAL_SR_MUST_BE_RESIDENT_HOSTS
|
|||
|
};
|
|||
|
yield return new TestData //Local master to shared restricted space
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
Sr = GetSr(smallISCSI),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
DiskSize = 2024 * 1024* 1024,
|
|||
|
ExpectedFailureDescription = "1.98 GB required when only 1008 MB available"
|
|||
|
};
|
|||
|
yield return new TestData //Move the vdis to the same place
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.CURRENT_LOCATION
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private IEnumerable<TestData> CanMigrateTestData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
//VDIs from master local storage -> shared storage
|
|||
|
yield return new TestData //Local master to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetSr(largeISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Local master to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetSr(mediumISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Local master to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetSr(smallISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
//VDIs from the shared storage -> local storage
|
|||
|
yield return new TestData //Master VDIs to a master
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Slave VDIs to a slave
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => !v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
Sr = GetLocalSr(slaveHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Shared to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI),
|
|||
|
Sr = GetSr(mediumISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private IEnumerable<TestData> CanMoveTestData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
yield return new TestData //Shared to local with different affinity
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Local master to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetSr(largeISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Local to local
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetLocalSr(slaveHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Shared to local
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
yield return new TestData //Shared to shared
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI),
|
|||
|
Sr = GetSr(mediumISCSI),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private IEnumerable<TestData> CannotMoveTestData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
yield return new TestData //Move the vdis to the same place
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
DiskSize = 1024 * 1024,
|
|||
|
ExpectedFailureDescription = Messages.CURRENT_LOCATION
|
|||
|
};
|
|||
|
yield return new TestData //Local master to shared restricted space
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
Sr = GetSr(smallISCSI),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
DiskSize = 2024 * 1024 * 1024,
|
|||
|
ExpectedFailureDescription = "1.98 GB required when only 1008 MB available"
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private TestData IsoSrData
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new TestData //ISO not supporting VDI create
|
|||
|
{
|
|||
|
Affinity = GetAffinity(slaveHost),
|
|||
|
VdisToMove = GetVDIsFromLocal(masterHost),
|
|||
|
Sr = GetLocalISOSr(slaveHost),
|
|||
|
DiskSize = 1024*1024
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
[Test]
|
|||
|
public void IsoSRMigrateScenario()
|
|||
|
{
|
|||
|
|
|||
|
SrPickerItem item = new SrPickerMigrateItem(IsoSrData.Sr, IsoSrData.Affinity,
|
|||
|
IsoSrData.DiskSize, IsoSrData.VdisToMove);
|
|||
|
|
|||
|
Assert.That(item.Show, Is.False, "Item Shown: Item: ISOSr migrate");
|
|||
|
Assert.That(item.Enabled, Is.True, "Item Enabled: Item: ISOSr migrate");
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void IsoSRMigrateScenarioNullStorageHost() //From CA-92099
|
|||
|
{
|
|||
|
TestData td = new TestData //Shared VDIs to local storage - this data can migrate - used above
|
|||
|
{
|
|||
|
Affinity = GetAffinity(masterHost),
|
|||
|
VdisToMove = GetVDIsOn(largeISCSI).Where(v => v.name_label.Contains("OnMaster")).ToArray(),
|
|||
|
Sr = GetLocalSr(masterHost),
|
|||
|
DiskSize = 1024 * 1024
|
|||
|
};
|
|||
|
|
|||
|
//Setup the data so that PBD count > 1 in order that GetStorageHost returns null
|
|||
|
Assert.That(td.Sr.PBDs.Count, Is.EqualTo(1), "PBD count before alteration");
|
|||
|
td.Sr.PBDs.Add(new XenRef<PBD>("dummy")); //Additional PBD should make GetStorageHost return null
|
|||
|
Assert.That(td.Sr.PBDs.Count, Is.EqualTo(2), "PBD count after alteration");
|
|||
|
Assert.IsNull(td.Sr.GetStorageHost(), "SR.GetStorageHost == null");
|
|||
|
|
|||
|
//Setup the item and test this
|
|||
|
SrPickerItem item = new SrPickerMigrateItem(td.Sr, td.Affinity,
|
|||
|
td.DiskSize, td.VdisToMove);
|
|||
|
|
|||
|
Assert.That(item.Show, Is.True, "Item Shown: Item: Null StorageHost");
|
|||
|
Assert.That(item.Enabled, Is.True, "Item Enabled: Item: Null StorageHost");
|
|||
|
|
|||
|
td.Sr.PBDs.Remove(new XenRef<PBD>("dummy"));
|
|||
|
Assert.That(td.Sr.PBDs.Count, Is.EqualTo(1), "PBD count after test");
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void IsoSRMoveScenario()
|
|||
|
{
|
|||
|
|
|||
|
SrPickerItem item = new SrPickerMoveCopyItem(IsoSrData.Sr, IsoSrData.Affinity,
|
|||
|
IsoSrData.DiskSize, IsoSrData.VdisToMove);
|
|||
|
|
|||
|
Assert.That(item.Show, Is.False, "Item Shown: Item: ISOSr migrate");
|
|||
|
Assert.That(item.Enabled, Is.True, "Item Enabled: Item: ISOSr migrate");
|
|||
|
}
|
|||
|
|
|||
|
[Test, Description("See PR-1255 for details")]
|
|||
|
public void TestCanMigrateScenarios()
|
|||
|
{
|
|||
|
CanDoScenario(SrPicker.SRPickerType.Migrate, CanMigrateTestData);
|
|||
|
}
|
|||
|
|
|||
|
[Test, Description("See PR-1255 for details")]
|
|||
|
public void TestCannotMigrateScenario()
|
|||
|
{
|
|||
|
CannotDoScenario(SrPicker.SRPickerType.Migrate, CannotMigrateTestData);
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestCanMoveScenario()
|
|||
|
{
|
|||
|
CanDoScenario(SrPicker.SRPickerType.MoveOrCopy, CanMoveTestData);
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestCannotMoveScenario()
|
|||
|
{
|
|||
|
CannotDoScenario(SrPicker.SRPickerType.MoveOrCopy, CannotMoveTestData);
|
|||
|
}
|
|||
|
|
|||
|
#region Helper methods for XenObjects
|
|||
|
private readonly SrPickerItemFactory factory = new SrPickerItemFactory();
|
|||
|
private void CannotDoScenario(SrPicker.SRPickerType type, IEnumerable<TestData> testData)
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
foreach (TestData data in testData)
|
|||
|
{
|
|||
|
SrPickerItem item = factory.PickerItem(data.Sr, type, data.Affinity,
|
|||
|
data.DiskSize, data.VdisToMove);
|
|||
|
Assert.That(item.Show, Is.True, "Item Shown: Item " + count);
|
|||
|
Assert.That(item.Enabled, Is.False, "Item Enabled: Item " + count);
|
|||
|
Assert.That(item.Description, Is.EqualTo(data.ExpectedFailureDescription), "Item Reason: Item " + count);
|
|||
|
count++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void CanDoScenario(SrPicker.SRPickerType type, IEnumerable<TestData> testData)
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
foreach (TestData data in testData)
|
|||
|
{
|
|||
|
SrPickerItem item = factory.PickerItem(data.Sr, type, data.Affinity,
|
|||
|
data.DiskSize, data.VdisToMove);
|
|||
|
Assert.That(item.Show, Is.True, "Item Shown: Item " + count);
|
|||
|
Assert.That(item.Enabled, Is.True, "Item Enabled: Item " + count);
|
|||
|
count++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private Host GetAffinity(string hostName)
|
|||
|
{
|
|||
|
return DatabaseManager.ConnectionFor(dbName).Cache.Hosts.FirstOrDefault(h => h.name_label == hostName);
|
|||
|
}
|
|||
|
|
|||
|
private VDI[] GetVDIsOn(string srName)
|
|||
|
{
|
|||
|
SR sr = GetSr(srName);
|
|||
|
return DatabaseManager.ConnectionFor(dbName).ResolveAll(sr.VDIs).ToArray();
|
|||
|
}
|
|||
|
|
|||
|
private SR GetLocalSr(string hostName)
|
|||
|
{
|
|||
|
List<SR> local = DatabaseManager.ConnectionFor(dbName).Cache.SRs.Where(s => s.IsLocalSR).ToList();
|
|||
|
return local.FirstOrDefault(s => s.GetStorageHost().name_label == hostName && s.name_label == "Local storage");
|
|||
|
}
|
|||
|
|
|||
|
private SR GetLocalISOSr(string hostName)
|
|||
|
{
|
|||
|
List<SR> local = DatabaseManager.ConnectionFor(dbName).Cache.SRs.Where(s => s.IsLocalSR).ToList();
|
|||
|
SR sr = local.FirstOrDefault(s => s.GetStorageHost().name_label == hostName && s.name_label.Contains("DVD"));
|
|||
|
return sr;
|
|||
|
}
|
|||
|
|
|||
|
private VDI[] GetVDIsFromLocal(string hostName)
|
|||
|
{
|
|||
|
SR srLocal = GetLocalSr(hostName);
|
|||
|
return DatabaseManager.ConnectionFor(dbName).ResolveAll(srLocal.VDIs).ToArray();
|
|||
|
}
|
|||
|
|
|||
|
private SR GetSr(string srName)
|
|||
|
{
|
|||
|
return DatabaseManager.ConnectionFor(dbName).Cache.SRs.FirstOrDefault(h => h.name_label == srName);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
public class SrPickerItemUnitTests : UnitTester_TestFixture
|
|||
|
{
|
|||
|
private const string id = "test";
|
|||
|
public SrPickerItemUnitTests() : base(id){}
|
|||
|
|
|||
|
private class SrPickerItemTest : SrPickerItem
|
|||
|
{
|
|||
|
public SrPickerItemTest(SR sr) : base(sr, null, 0 , null) {}
|
|||
|
protected override void SetImage(){} //Not needed here
|
|||
|
protected override bool CanBeEnabled { get { throw new NotImplementedException(); }}
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void LunPerVDIDisablesSrPickerItem()
|
|||
|
{
|
|||
|
Mock<SR> sr = ObjectManager.NewXenObject<SR>(id);
|
|||
|
sr.Setup(i => i.HBALunPerVDI).Returns(true);
|
|||
|
SrPickerItem spi = new SrPickerItemTest(sr.Object);
|
|||
|
Assert.That(spi.Show, Is.False);
|
|||
|
sr.Verify(a=>a.HBALunPerVDI, Times.Once());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|