mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2025-01-20 07:19:18 +01:00
CA-110160: Fixed uncaught exception in VM migrate wizard observed while concurrent migrate operation is triggered on same VM
- before leaving each page of the wizard, check if all selected VMs are still available for migration Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
This commit is contained in:
parent
8c9502e4ba
commit
739c3d4837
@ -103,13 +103,6 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
return filters;
|
||||
}
|
||||
|
||||
private void ShowWarningMessageBox(string message)
|
||||
{
|
||||
new ThreeButtonDialog(
|
||||
new ThreeButtonDialog.Details(SystemIcons.Warning, message, Messages.CPM_WIZARD_TITLE)).ShowDialog(
|
||||
Program.MainWindow);
|
||||
}
|
||||
|
||||
public override void PageLeave(XenAdmin.Controls.PageLoadedDirection direction, ref bool cancel)
|
||||
{
|
||||
if (!cancel)
|
||||
@ -120,12 +113,19 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
{
|
||||
if (Connection == null || !Connection.IsConnected)
|
||||
{
|
||||
ShowWarningMessageBox(Messages.CPM_WIZARD_ERROR_TARGET_DISCONNECTED);
|
||||
CrossPoolMigrateWizard.ShowWarningMessageBox(Messages.CPM_WIZARD_ERROR_TARGET_DISCONNECTED);
|
||||
targetDisconnected = true;
|
||||
}
|
||||
});
|
||||
cancel = targetDisconnected;
|
||||
}
|
||||
|
||||
if (!cancel && !CrossPoolMigrateWizard.AllVMsAvailable(selectedVMs))
|
||||
{
|
||||
cancel = true;
|
||||
SetButtonNextEnabled(false);
|
||||
}
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using XenAdmin.Controls;
|
||||
using XenAdmin.Wizards.GenericPages;
|
||||
using XenAPI;
|
||||
|
||||
@ -66,5 +69,17 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
List<VIF> vifs = Connection.ResolveAll(vm.VIFs);
|
||||
return new CrossPoolMigrationNetworkResourceContainer(vifs);
|
||||
}
|
||||
|
||||
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
||||
{
|
||||
if (!CrossPoolMigrateWizard.AllVMsAvailable(VmMappings, Connection))
|
||||
{
|
||||
cancel = true;
|
||||
SetButtonNextEnabled(false);
|
||||
SetButtonPreviousEnabled(false);
|
||||
}
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using XenAdmin.Controls;
|
||||
using XenAdmin.Wizards.GenericPages;
|
||||
using XenAPI;
|
||||
|
||||
@ -75,9 +77,25 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
public override StorageResourceContainer ResourceData(string sysId)
|
||||
{
|
||||
VM vm = Connection.Resolve(new XenRef<VM>(sysId));
|
||||
|
||||
if (vm == null)
|
||||
return null;
|
||||
|
||||
List<VDI> vdis = Connection.ResolveAll(vm.VBDs).Select(v => vm.Connection.Resolve(v.VDI)).ToList();
|
||||
vdis.RemoveAll(vdi => vdi == null || Connection.Resolve(vdi.SR).GetSRType(true) == SR.SRTypes.iso);
|
||||
return new CrossPoolMigrationStorageResourceContainer(vdis);
|
||||
}
|
||||
|
||||
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
||||
{
|
||||
if (!CrossPoolMigrateWizard.AllVMsAvailable(VmMappings, Connection))
|
||||
{
|
||||
cancel = true;
|
||||
SetButtonNextEnabled(false);
|
||||
SetButtonPreviousEnabled(false);
|
||||
}
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,13 +31,17 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using XenAdmin.Controls;
|
||||
using XenAPI;
|
||||
|
||||
namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
{
|
||||
public partial class CrossPoolMigrateTransferNetworkPage : XenTabPage
|
||||
{
|
||||
public CrossPoolMigrateTransferNetworkPage()
|
||||
private List<VM> selectedVMs;
|
||||
|
||||
public CrossPoolMigrateTransferNetworkPage(List<VM> selectedVMs)
|
||||
{
|
||||
this.selectedVMs = selectedVMs;
|
||||
InitializeComponent();
|
||||
InitializeCustomPageElements();
|
||||
}
|
||||
@ -49,6 +53,9 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
networkComboBox.IncludeOnlyNetworksWithIPAddresses = true;
|
||||
}
|
||||
|
||||
private bool m_buttonNextEnabled;
|
||||
private bool m_buttonPreviousEnabled;
|
||||
|
||||
#region Base class (XenTabPage) overrides
|
||||
|
||||
/// <summary>
|
||||
@ -74,7 +81,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
public override void PageLoaded(PageLoadedDirection direction)
|
||||
{
|
||||
base.PageLoaded(direction);//call first so the page gets populated
|
||||
OnPageUpdated();
|
||||
SetButtonsEnabled(true);
|
||||
}
|
||||
|
||||
public override void PopulatePage()
|
||||
@ -89,7 +96,33 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
get { return networkComboBox.SelectedNetworkUuid; }
|
||||
}
|
||||
|
||||
public override bool EnableNext()
|
||||
{
|
||||
return m_buttonNextEnabled;
|
||||
}
|
||||
|
||||
public override bool EnablePrevious()
|
||||
{
|
||||
return m_buttonPreviousEnabled;
|
||||
}
|
||||
|
||||
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
||||
{
|
||||
if (!CrossPoolMigrateWizard.AllVMsAvailable(selectedVMs))
|
||||
{
|
||||
cancel = true;
|
||||
SetButtonsEnabled(false);
|
||||
}
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected void SetButtonsEnabled(bool enabled)
|
||||
{
|
||||
m_buttonNextEnabled = enabled;
|
||||
m_buttonPreviousEnabled = enabled;
|
||||
OnPageUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
|
||||
m_pageStorage = new CrossPoolMigrateStoragePage();
|
||||
m_pageNetwork = new CrossPoolMigrateNetworkingPage();
|
||||
m_pageTransferNetwork = new CrossPoolMigrateTransferNetworkPage();
|
||||
m_pageTransferNetwork = new CrossPoolMigrateTransferNetworkPage(VmsFromSelection(selection));
|
||||
m_pageFinish = new CrossPoolMigrateFinishPage {SummaryRetreiver = GetVMMappingSummary};
|
||||
m_pageTargetRbac = new RBACWarningPage();
|
||||
|
||||
@ -143,6 +143,12 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
|
||||
protected override void FinishWizard()
|
||||
{
|
||||
if (!AllVMsAvailable(m_vmMappings, xenConnection))
|
||||
{
|
||||
base.FinishWizard();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, VmMapping> pair in m_vmMappings)
|
||||
{
|
||||
VM vm = xenConnection.Resolve(new XenRef<VM>(pair.Key));
|
||||
@ -314,5 +320,58 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
|
||||
}
|
||||
return summary.Details;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if all VMs are still available for migration and shows a warning message if the check fails
|
||||
/// </summary>
|
||||
/// <returns>true if check succeded, false if failed</returns>
|
||||
internal static bool AllVMsAvailable(List<VM> vms)
|
||||
{
|
||||
Func<bool> vmCheck = delegate
|
||||
{
|
||||
if (vms == null || vms.Count == 0 || vms[0] == null || vms[0].Connection == null)
|
||||
return false;
|
||||
var connection = vms[0].Connection; // the connection on which to check VM availability
|
||||
return vms.All(vm => connection.Resolve(new XenRef<VM>(vm.opaque_ref)) != null);
|
||||
};
|
||||
|
||||
return PerformCheck(vmCheck);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if all VMs are still available for migration and shows a warning message if the check fails
|
||||
/// </summary>
|
||||
/// <returns>true if check succeded, false if failed</returns>
|
||||
internal static bool AllVMsAvailable(Dictionary<string, VmMapping> vmMappings, IXenConnection connection)
|
||||
{
|
||||
Func<bool> vmCheck = delegate
|
||||
{
|
||||
if (vmMappings == null || vmMappings.Count == 0 || connection == null)
|
||||
return false;
|
||||
return vmMappings.All(kvp => connection.Resolve(new XenRef<VM>(kvp.Key)) != null);
|
||||
};
|
||||
|
||||
return PerformCheck(vmCheck);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a certain check and shows a warning message if the check fails
|
||||
/// </summary>
|
||||
/// <param name="check">The check to perform</param>
|
||||
/// <returns>true if check succeded, false if failed</returns>
|
||||
private static bool PerformCheck(Func<bool> check)
|
||||
{
|
||||
if (check())
|
||||
return true;
|
||||
ShowWarningMessageBox(Messages.CPM_WIZARD_VM_MISSING_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static void ShowWarningMessageBox(string message)
|
||||
{
|
||||
new ThreeButtonDialog(
|
||||
new ThreeButtonDialog.Details(SystemIcons.Warning, message, Messages.CPM_WIZARD_TITLE)).ShowDialog(
|
||||
Program.MainWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,8 +204,8 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
public abstract DelayLoadingOptionComboBoxItem CreateDelayLoadingOptionComboBoxItem(IXenObject xenItem);
|
||||
|
||||
#region Private methods
|
||||
|
||||
private void SetButtonNextEnabled(bool enabled)
|
||||
|
||||
protected void SetButtonNextEnabled(bool enabled)
|
||||
{
|
||||
m_buttonNextEnabled = enabled;
|
||||
OnPageUpdated();
|
||||
|
@ -95,15 +95,6 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
||||
{
|
||||
targetConnection = null;
|
||||
|
||||
if (VmMappings.Select(kvp => kvp.Key).Any(sysId => NetworkData(sysId) == null))
|
||||
{
|
||||
ShowWarningMessageBox(Messages.CPM_WIZARD_VM_MISSING_ERROR);
|
||||
cancel = true;
|
||||
SetButtonNextEnabled(false);
|
||||
SetButtonPreviousEnabled(false);
|
||||
}
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
|
||||
@ -288,13 +279,5 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
m_dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private void ShowWarningMessageBox(string message)
|
||||
{
|
||||
new ThreeButtonDialog(
|
||||
new ThreeButtonDialog.Details(SystemIcons.Warning, message, Messages.CPM_WIZARD_TITLE)).ShowDialog(
|
||||
Program.MainWindow);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
private ulong m_totalSpaceRequired;
|
||||
private Dictionary<string, VmMapping> m_vmMappings;
|
||||
private bool m_buttonNextEnabled;
|
||||
private bool m_buttonPreviousEnabled;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -142,11 +143,17 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
{
|
||||
TargetConnection = null;
|
||||
|
||||
if (direction == PageLoadedDirection.Forward && IsDirty && ImplementsIsDirty())
|
||||
if (!cancel && direction == PageLoadedDirection.Forward && IsDirty && ImplementsIsDirty())
|
||||
cancel = !PerformCheck(CheckStorageRequirements);
|
||||
|
||||
base.PageLeave(direction, ref cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PageLoaded(PageLoadedDirection direction)
|
||||
{
|
||||
base.PageLoaded(direction);//call first so the page gets populated
|
||||
SetButtonPreviousEnabled(true);
|
||||
}
|
||||
|
||||
public abstract StorageResourceContainer ResourceData(string sysId);
|
||||
|
||||
@ -292,6 +299,11 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
return m_buttonNextEnabled;
|
||||
}
|
||||
|
||||
public override bool EnablePrevious()
|
||||
{
|
||||
return m_buttonPreviousEnabled;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
@ -341,12 +353,18 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
return success;
|
||||
}
|
||||
|
||||
private void SetButtonNextEnabled(bool enabled)
|
||||
protected void SetButtonNextEnabled(bool enabled)
|
||||
{
|
||||
m_buttonNextEnabled = enabled;
|
||||
OnPageUpdated();
|
||||
}
|
||||
|
||||
protected void SetButtonPreviousEnabled(bool enabled)
|
||||
{
|
||||
m_buttonPreviousEnabled = enabled;
|
||||
OnPageUpdated();
|
||||
}
|
||||
|
||||
private bool CheckStorageRequirements(out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
|
@ -204,6 +204,9 @@ namespace XenAdmin.Wizards.GenericPages
|
||||
foreach (var pair in mapping.Storage)
|
||||
{
|
||||
VDI vdi = connection.Resolve(new XenRef<VDI>(pair.Key));
|
||||
if (vdi == null)
|
||||
continue;
|
||||
|
||||
string valueToAdd = vdi.Name + separatorText + pair.Value.Name;
|
||||
|
||||
if (pair.Key == mapping.Storage.First().Key)
|
||||
|
Loading…
Reference in New Issue
Block a user