CA-272150: Optimize destination page of cross-pool-migrate wizard. (#1941)

* CA-272150: Optimize destination page of cross-pool-migrate wizard.

Signed-off-by: Michael Zhao <michael.zhao@citrix.com>
This commit is contained in:
Michael 2018-03-01 22:06:04 +08:00 committed by Mihaela Stoica
parent 34ec571fa1
commit a4aaeb1165
5 changed files with 84 additions and 10 deletions

View File

@ -43,8 +43,12 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
{
private List<VM> selectedVMs;
private WizardMode wizardMode;
// A 2-level cache to store the result of CrossPoolMigrateCanMigrateFilter.
// Cache structure is like: <vm-ref, <host-ref, fault-reason>>.
private IDictionary<string, IDictionary<string, string>> migrateFilterCache =
new Dictionary<string, IDictionary<string, string>>();
public CrossPoolMigrateDestinationPage()
: this(null, null, WizardMode.Migrate, null)
{
@ -142,7 +146,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
var filters = new List<ReasoningFilter>
{
new ResidentHostIsSameAsSelectionFilter(xenItem, selectedVMs),
new CrossPoolMigrateCanMigrateFilter(xenItem, selectedVMs, wizardMode),
new CrossPoolMigrateCanMigrateFilter(xenItem, selectedVMs, wizardMode, migrateFilterCache),
new WlbEnabledFilter(xenItem, selectedVMs)
};
return new DelayLoadingOptionComboBoxItem(xenItem, filters);
@ -159,7 +163,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
vmList.Add(selectedVMs.Find(vm => vm.opaque_ref == opaqueRef));
filters.Add(new ResidentHostIsSameAsSelectionFilter(selectedItem.Item, vmList));
filters.Add(new CrossPoolMigrateCanMigrateFilter(selectedItem.Item, vmList, wizardMode));
filters.Add(new CrossPoolMigrateCanMigrateFilter(selectedItem.Item, vmList, wizardMode, migrateFilterCache));
filters.Add(new WlbEnabledFilter(selectedItem.Item, vmList));
}

View File

@ -45,17 +45,29 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard.Filters
private readonly WizardMode _wizardMode;
private string disableReason = string.Empty;
private readonly List<VM> preSelectedVMs;
private IDictionary<string, IDictionary<string, string>> cache;
private bool canceled = false;
private static readonly Object cacheLock = new Object();
public CrossPoolMigrateCanMigrateFilter(IXenObject itemAddedToComboBox, List<VM> preSelectedVMs, WizardMode wizardMode)
public CrossPoolMigrateCanMigrateFilter(IXenObject itemAddedToComboBox, List<VM> preSelectedVMs, WizardMode wizardMode, IDictionary<string, IDictionary<string, string>> cache = null)
: base(itemAddedToComboBox)
{
_wizardMode = wizardMode;
if (cache == null)
this.cache = new Dictionary<string, IDictionary<string, string>>();
else
this.cache = cache;
if (preSelectedVMs == null)
throw new ArgumentNullException("Pre-selected VMs are null");
this.preSelectedVMs = preSelectedVMs;
}
public override void Cancel()
{
canceled = true;
}
public override bool FailureFound
{
get
@ -73,6 +85,20 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard.Filters
foreach (VM vm in preSelectedVMs)
{
if (canceled)
return excludedHosts.Count == targets.Count;
// obtain the cache data for a vm
IDictionary<string, string> vmCache;
lock (cacheLock)
{
if (!cache.ContainsKey(vm.opaque_ref))
{
cache.Add(vm.opaque_ref, new Dictionary<string, string>());
}
vmCache = cache[vm.opaque_ref];
}
try
{
//CA-220218: for intra-pool motion of halted VMs we do a move, so no need to assert we can migrate
@ -91,6 +117,16 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard.Filters
continue;
}
if (vmCache.ContainsKey(host.opaque_ref))
{
disableReason = vmCache[host.opaque_ref];
if (!string.IsNullOrEmpty(disableReason) && !excludedHosts.Contains(host.opaque_ref))
{
excludedHosts.Add(host.opaque_ref);
}
continue;
}
PIF managementPif = host.Connection.Cache.PIFs.First(p => p.management);
XenAPI.Network network = host.Connection.Cache.Resolve(managementPif.network);
@ -103,6 +139,10 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard.Filters
GetVdiMap(vm, targetSrs),
vm.Connection == host.Connection ? new Dictionary<XenRef<VIF>, XenRef<XenAPI.Network>>() : GetVifMap(vm, targetNetwork),
new Dictionary<string, string>());
lock (cacheLock)
{
vmCache.Add(host.opaque_ref, string.Empty);
}
}
catch (Failure failure)
{
@ -111,8 +151,13 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard.Filters
else
disableReason = failure.Message;
log.ErrorFormat("VM: {0}, Host: {1} - Reason: {2};", vm.opaque_ref, host.opaque_ref, failure.Message);
lock (cacheLock)
{
vmCache.Add(host.opaque_ref, disableReason.Clone().ToString());
}
log.ErrorFormat("VM: {0}, Host: {1} - Reason: {2};", vm.opaque_ref, host.opaque_ref, failure.Message);
if (!excludedHosts.Contains(host.opaque_ref))
excludedHosts.Add(host.opaque_ref);
}

View File

@ -116,6 +116,12 @@ namespace XenAdmin.Wizards.GenericPages
ThreadPool.QueueUserWorkItem(delegate { FetchFailureReasonWithRetry(defaultRetries, defaultTimeOut); });
}
public void CancelFilters()
{
foreach (ReasoningFilter filter in _filters)
filter.Cancel();
}
private void FetchFailureReasonWithRetry(int retries, int timeOut)
{
string threadFailureReason = Messages.DELAY_LOADED_COMBO_BOX_ITEM_FAILURE_UNKOWN;

View File

@ -56,5 +56,7 @@ namespace XenAdmin.Wizards.GenericPages
ItemToFilterOn = xenObject;
return FailureFound;
}
public virtual void Cancel() { }
}
}

View File

@ -88,6 +88,7 @@ namespace XenAdmin.Wizards.GenericPages
public override void PageCancelled()
{
CancelFilters();
Program.Invoke(Program.MainWindow, ClearComboBox);
Program.Invoke(Program.MainWindow, ClearDataGridView);
ChosenItem = null;
@ -404,16 +405,21 @@ namespace XenAdmin.Wizards.GenericPages
}
}
foreach (var host in Connection.Cache.Hosts)
var sortedHosts = new List<Host>(Connection.Cache.Hosts);
sortedHosts.Sort();
var items = new List<DelayLoadingOptionComboBoxItem>();
foreach (var host in sortedHosts)
{
var item = new DelayLoadingOptionComboBoxItem(host, homeserverFilters);
item.LoadAndWait();
cb.Items.Add(item);
if (item.Enabled && ((m_selectedObject != null && m_selectedObject.opaque_ref == host.opaque_ref) ||
(target != null && target.Item.opaque_ref == host.opaque_ref)))
(target != null && target.Item.opaque_ref == host.opaque_ref)))
cb.Value = item;
}
}
SetComboBoxPreSelection(cb);
@ -635,6 +641,17 @@ namespace XenAdmin.Wizards.GenericPages
xenConnection.CachePopulated -= xenConnection_CachePopulated;
xenConnection.Cache.DeregisterCollectionChanged<Host>(Host_CollectionChangedWithInvoke);
}
}
}
}
private void CancelFilters()
{
foreach (var item in m_comboBoxConnection.Items)
{
DelayLoadingOptionComboBoxItem comboBoxItem = item as DelayLoadingOptionComboBoxItem;
if (comboBoxItem != null)
comboBoxItem.CancelFilters();
}
}
}
}