Merge pull request #3033 from danilo-delbusso/bug/prevent-host-reset

Prevent host reset when moving between wizard pages using `SelectMultipleVMDestinationPage`
This commit is contained in:
Konstantina Chremmou 2022-10-27 10:58:54 +01:00 committed by GitHub
commit de6a4f89c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 360 additions and 363 deletions

View File

@ -164,7 +164,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
protected override bool PerformCheck()
{
if (ChosenItem != null && (ChosenItem.Connection == null || !ChosenItem.Connection.IsConnected))
if (SelectedTargetPool != null && (SelectedTargetPool.Connection == null || !SelectedTargetPool.Connection.IsConnected))
{
CrossPoolMigrateWizard.ShowWarningMessageBox(Messages.CPM_WIZARD_ERROR_TARGET_DISCONNECTED);
return false;

View File

@ -188,7 +188,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
VmMappings = m_vmMappings,
Connection = selection.GetConnectionOfFirstItem()
};
m_pageDestination.SetDefaultTarget(hostPreSelection);
m_pageDestination.SelectedTarget = hostPreSelection;
m_pageStorage = new CrossPoolMigrateStoragePage(wizardMode);
m_pageNetwork = new CrossPoolMigrateNetworkingPage(HasTemplatesOnly, wizardMode);
@ -350,7 +350,7 @@ namespace XenAdmin.Wizards.CrossPoolMigrateWizard
RemovePage(m_pageTransferNetwork);
RemovePage(m_pageTargetRbac);
m_vmMappings = m_pageDestination.VmMappings;
TargetConnection = m_pageDestination.ChosenItem?.Connection;
TargetConnection = m_pageDestination.SelectedTargetPool?.Connection;
m_pageStorage.TargetConnection = TargetConnection;
m_pageNetwork.TargetConnection = TargetConnection;

View File

@ -69,7 +69,6 @@ namespace XenAdmin.Wizards.GenericPages
xenObject = toCopy.Item;
failureReason = toCopy.FailureReason;
Enabled = toCopy.Enabled;
PreferAsSelectedItem = toCopy.PreferAsSelectedItem;
}
/// <summary>
@ -77,17 +76,6 @@ namespace XenAdmin.Wizards.GenericPages
/// </summary>
public IXenObject Item => xenObject;
/// <summary>
/// You would prefer this item to be the one that is selected
/// As the items are threaded they may exist and be disabled but required
/// as a selected item if they load successfully.
///
/// Use this in the event handler for the ReasonUpdated flag to find out
/// which item should be the selected one and thus which to
/// set in the combo box
/// </summary>
public bool PreferAsSelectedItem { get; set; }
/// <summary>
/// Create a thread and fetch the reason
/// </summary>
@ -138,15 +126,6 @@ namespace XenAdmin.Wizards.GenericPages
FailureReason = Messages.DELAY_LOADED_COMBO_BOX_ITEM_FAILURE_UNKNOWN;
}
/// <summary>
/// Trigger event
/// </summary>
private void OnReasonChanged()
{
if (ReasonUpdated != null)
ReasonUpdated(this);
}
public bool Enabled { get; private set; }
/// <summary>
@ -160,11 +139,12 @@ namespace XenAdmin.Wizards.GenericPages
{
if (failureReason == value)
return;
failureReason = value;
Enabled = String.IsNullOrEmpty(failureReason);
Enabled = string.IsNullOrEmpty(failureReason);
OnReasonChanged();
ReasonUpdated?.Invoke(this);
}
}
@ -177,7 +157,7 @@ namespace XenAdmin.Wizards.GenericPages
if (string.IsNullOrEmpty(FailureReason))
return Item.Name();
return String.Format(Messages.DELAY_LOADED_COMBO_BOX_ITEM_FAILURE_REASON, Item.Name(), FailureReason);
return string.Format(Messages.DELAY_LOADED_COMBO_BOX_ITEM_FAILURE_REASON, Item.Name(), FailureReason);
}
}
}

View File

@ -103,6 +103,7 @@
this.m_dataGridView.Name = "m_dataGridView";
this.m_dataGridView.RowHeadersVisible = false;
this.m_dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.m_dataGridView_CellClick);
this.m_dataGridView.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.m_dataGridView_CellValueChanged);
this.m_dataGridView.CurrentCellDirtyStateChanged += new System.EventHandler(this.m_dataGridView_CurrentCellDirtyStateChanged);
//
// m_colVmName

View File

@ -43,20 +43,21 @@ using XenAPI;
namespace XenAdmin.Wizards.GenericPages
{
/// <summary>
/// Class representing the page of the ImportAppliance wizard where the user specifies
/// the targets where the VMs of the appliance will be imported
/// </summary>
internal abstract partial class SelectMultipleVMDestinationPage : XenTabPage
{
private Dictionary<string, VmMapping> m_vmMappings;
private IXenObject m_selectedObject;
private bool updatingDestinationCombobox;
/// <summary>
/// Class representing the page of the ImportAppliance wizard where the user specifies
/// the targets where the VMs of the appliance will be imported
/// </summary>
internal abstract partial class SelectMultipleVMDestinationPage : XenTabPage
{
private Dictionary<string, VmMapping> m_vmMappings;
public IXenObject SelectedTarget { get; set; }
private bool updatingDestinationCombobox;
private bool restoreGridHomeServerSelection;
private bool updatingHomeServerList;
private bool m_buttonNextEnabled;
protected List<IXenConnection> ignoredConnections = new List<IXenConnection>();
private readonly CollectionChangeEventHandler Host_CollectionChangedWithInvoke;
private string _preferredHomeRef;
#region Nested classes
@ -102,46 +103,46 @@ namespace XenAdmin.Wizards.GenericPages
#endregion
protected SelectMultipleVMDestinationPage()
{
InitializeComponent();
protected SelectMultipleVMDestinationPage()
{
InitializeComponent();
InitializeText();
Host_CollectionChangedWithInvoke = Program.ProgramInvokeHandler(CollectionChanged);
ConnectionsManager.XenConnections.CollectionChanged += CollectionChanged;
ConnectionsManager.XenConnections.CollectionChanged += CollectionChanged;
ShowWarning(null);
}
}
protected void InitializeText()
{
m_labelIntro.Text = InstructionText;
label1.Text = TargetServerText;
label2.Text = TargetServerSelectionIntroText;
protected void InitializeText()
{
m_labelIntro.Text = InstructionText;
label1.Text = TargetServerText;
label2.Text = TargetServerSelectionIntroText;
m_colVmName.HeaderText = VmColumnHeaderText;
m_colTarget.HeaderText = TargetColumnHeaderText;
}
m_colTarget.HeaderText = TargetColumnHeaderText;
}
private IXenObject _chosenItem;
public IXenObject ChosenItem
{
get { return _chosenItem; }
private IXenObject _selectedTargetPool;
public IXenObject SelectedTargetPool
{
get => _selectedTargetPool;
protected set
{
_chosenItem = value;
_selectedTargetPool = value;
OnChosenItemChanged();
}
}
}
/// <summary>
/// <summary>
/// Text containing instructions for use - at the top of the page
/// </summary>
protected abstract string InstructionText { get; }
protected abstract string InstructionText { get; }
/// <summary>
/// Text demarking what the label for the target server drop down should be
/// </summary>
protected abstract string TargetServerText { get; }
protected virtual string VmColumnHeaderText
protected virtual string VmColumnHeaderText
{
get
{
@ -149,13 +150,13 @@ namespace XenAdmin.Wizards.GenericPages
}
}
protected virtual string TargetColumnHeaderText
{
get
{
return m_colTarget.HeaderText;
}
}
protected virtual string TargetColumnHeaderText
{
get
{
return m_colTarget.HeaderText;
}
}
/// <summary>
/// Text above the table containing a list of VMs and concomitant home server
@ -163,9 +164,9 @@ namespace XenAdmin.Wizards.GenericPages
protected abstract string TargetServerSelectionIntroText { get; }
protected virtual void OnChosenItemChanged()
{}
{ }
protected void ShowWarning(string warningText)
protected void ShowWarning(string warningText)
{
if (string.IsNullOrEmpty(warningText))
tableLayoutPanelWarning.Visible = false;
@ -176,14 +177,14 @@ namespace XenAdmin.Wizards.GenericPages
}
}
#region Base class (XenTabPage) overrides
#region Base class (XenTabPage) overrides
protected override void PageLoadedCore(PageLoadedDirection direction)
{
ChosenItem = null;
{
SelectedTargetPool = null;
restoreGridHomeServerSelection = direction == PageLoadedDirection.Back;
PopulateComboBox();
}
}
public override void PageCancelled(ref bool cancel)
{
@ -191,7 +192,7 @@ namespace XenAdmin.Wizards.GenericPages
CancelFilters();
ClearComboBox();
ClearDataGridView();
ChosenItem = null;
SelectedTargetPool = null;
}
protected override void PageLeaveCore(PageLoadedDirection direction, ref bool cancel)
@ -204,7 +205,6 @@ namespace XenAdmin.Wizards.GenericPages
}
UnregisterHandlers();
SetDefaultTarget(ChosenItem);
ClearComboBox();
}
@ -218,52 +218,47 @@ namespace XenAdmin.Wizards.GenericPages
return m_buttonNextEnabled;
}
#endregion
#endregion
#region Accessors
#region Accessors
public Dictionary<string, VmMapping> VmMappings
{
get
{
foreach (DataGridViewRow row in m_dataGridView.Rows)
{
string sysId = (string)row.Cells[0].Tag;
public Dictionary<string, VmMapping> VmMappings
{
get
{
foreach (DataGridViewRow row in m_dataGridView.Rows)
{
string sysId = (string)row.Cells[0].Tag;
if (m_vmMappings.ContainsKey(sysId))
{
var mapping = m_vmMappings[sysId];
if (m_vmMappings.ContainsKey(sysId))
{
var mapping = m_vmMappings[sysId];
DataGridViewEnableableComboBoxCell cbCell = row.Cells[m_colTarget.Index] as DataGridViewEnableableComboBoxCell;
System.Diagnostics.Debug.Assert(cbCell != null, "ComboBox cell was not found");
IEnableableXenObjectComboBoxItem selectedItem = cbCell.Value as IEnableableXenObjectComboBoxItem;
System.Diagnostics.Debug.Assert(selectedItem != null, "Vm has no target mapped");
var type = selectedItem.Item.GetType();
if (type == typeof(Pool))
IEnableableXenObjectComboBoxItem selectedItem = cbCell.Value as IEnableableXenObjectComboBoxItem;
System.Diagnostics.Debug.Assert(selectedItem != null, "Vm has no target mapped");
var type = selectedItem.Item.GetType();
if (type == typeof(Pool))
mapping.XenRef = new XenRef<Pool>(selectedItem.Item.opaque_ref);
else if (type == typeof(Host))
else if (type == typeof(Host))
mapping.XenRef = new XenRef<Host>(selectedItem.Item.opaque_ref);
mapping.TargetName = selectedItem.Item.Name();
}
}
}
}
return m_vmMappings;
}
set { m_vmMappings = value; }
}
return m_vmMappings;
}
set { m_vmMappings = value; }
}
#endregion
public void SetDefaultTarget(IXenObject xenObject)
{
m_selectedObject = xenObject;
}
#endregion
protected abstract DelayLoadingOptionComboBoxItem CreateDelayLoadingOptionComboBoxItem(IXenObject xenItem);
#region Private methods
#region Private methods
private void SetButtonNextEnabled(bool enabled)
{
@ -271,10 +266,10 @@ namespace XenAdmin.Wizards.GenericPages
OnPageUpdated();
}
protected virtual bool PerformCheck()
{
return true;
}
protected virtual bool PerformCheck()
{
return true;
}
private void ClearComboBox()
{
@ -301,68 +296,66 @@ namespace XenAdmin.Wizards.GenericPages
m_dataGridView.Refresh();
}
private void PopulateComboBox()
{
Program.AssertOnEventThread();
private void PopulateComboBox()
{
Program.AssertOnEventThread();
ClearDataGridView();
ClearDataGridView();
updatingDestinationCombobox = true;
ClearComboBox();
updatingDestinationCombobox = true;
ClearComboBox();
var targetConnections = ConnectionsManager.XenConnectionsCopy.Where(con => con.IsConnected).Except(ignoredConnections).ToList();
var targetConnections = ConnectionsManager.XenConnectionsCopy.Where(con => con.IsConnected).Except(ignoredConnections).ToList();
foreach (var xenConnection in targetConnections)
{
DelayLoadingOptionComboBoxItem item = null;
{
DelayLoadingOptionComboBoxItem item = null;
Pool pool = Helpers.GetPool(xenConnection);
Pool pool = Helpers.GetPool(xenConnection);
if (pool == null)
{
Host host = Helpers.GetCoordinator(xenConnection);
if (pool == null)
{
Host host = Helpers.GetCoordinator(xenConnection);
if (host != null)
{
if (host != null)
{
item = CreateDelayLoadingOptionComboBoxItem(host);
m_comboBoxConnection.Items.Add(item);
item.ReasonUpdated += DelayLoadedComboBoxItem_ReasonChanged;
item.LoadAsync();
host.PropertyChanged -= PropertyChanged;
host.PropertyChanged += PropertyChanged;
}
}
else
{
host.PropertyChanged -= PropertyChanged;
host.PropertyChanged += PropertyChanged;
}
}
else
{
item = CreateDelayLoadingOptionComboBoxItem(pool);
m_comboBoxConnection.Items.Add(item);
item.ReasonUpdated += DelayLoadedComboBoxItem_ReasonChanged;
item.LoadAsync();
pool.PropertyChanged -= PropertyChanged;
pool.PropertyChanged += PropertyChanged;
}
pool.PropertyChanged -= PropertyChanged;
pool.PropertyChanged += PropertyChanged;
}
if (item != null && m_selectedObject != null && item.Item.Connection == m_selectedObject.Connection)
item.PreferAsSelectedItem = true;
if (item != null && SelectedTarget != null && item.Item.Connection == SelectedTarget.Connection)
_preferredHomeRef = item.Item.opaque_ref;
xenConnection.ConnectionStateChanged -= xenConnection_ConnectionStateChanged;
xenConnection.ConnectionStateChanged += xenConnection_ConnectionStateChanged;
xenConnection.CachePopulated -= xenConnection_CachePopulated;
xenConnection.CachePopulated += xenConnection_CachePopulated;
xenConnection.Cache.RegisterCollectionChanged<Host>(Host_CollectionChangedWithInvoke);
}
xenConnection.ConnectionStateChanged -= xenConnection_ConnectionStateChanged;
xenConnection.ConnectionStateChanged += xenConnection_ConnectionStateChanged;
xenConnection.CachePopulated -= xenConnection_CachePopulated;
xenConnection.CachePopulated += xenConnection_CachePopulated;
xenConnection.Cache.RegisterCollectionChanged<Host>(Host_CollectionChangedWithInvoke);
}
m_comboBoxConnection.Items.Add(new AddHostRunningComboBoxItem());
updatingDestinationCombobox = false;
}
m_comboBoxConnection.Items.Add(new AddHostRunningComboBoxItem());
updatingDestinationCombobox = false;
}
private bool MatchingWithXenRefObject(IEnableableXenObjectComboBoxItem item, object xenRef)
{
XenRef<Host> hostRef = xenRef as XenRef<Host>;
if (hostRef != null)
if (xenRef is XenRef<Host> hostRef)
return hostRef.opaque_ref == item.Item.opaque_ref;
XenRef<Pool> poolRef = xenRef as XenRef<Pool>;
if (poolRef != null)
if (xenRef is XenRef<Pool> poolRef)
return poolRef.opaque_ref == item.Item.opaque_ref;
return false;
@ -372,22 +365,19 @@ namespace XenAdmin.Wizards.GenericPages
{
foreach (DataGridViewRow row in m_dataGridView.Rows)
{
string sysId = (string)row.Cells[0].Tag;
if (m_vmMappings.ContainsKey(sysId))
{
var mapping = m_vmMappings[sysId];
var cbCell = row.Cells[m_colTarget.Index] as DataGridViewEnableableComboBoxCell;
if (cbCell == null)
return;
string sysId = (string)row.Cells[m_colVmName.Index].Tag;
var list = cbCell.Items.OfType<IEnableableXenObjectComboBoxItem>().ToList();
var item = list.FirstOrDefault(cbi => MatchingWithXenRefObject(cbi, mapping.XenRef));
if (m_vmMappings.TryGetValue(sysId, out var mapping) &&
row.Cells[m_colTarget.Index] is DataGridViewEnableableComboBoxCell cbCell)
{
var item = cbCell.Items.OfType<IEnableableXenObjectComboBoxItem>()
.FirstOrDefault(cbi => MatchingWithXenRefObject(cbi, mapping.XenRef));
if (item != null)
cbCell.Value = item;
}
}
}
private void PopulateDataGridView()
{
Program.AssertOnEventThread();
@ -405,8 +395,8 @@ namespace XenAdmin.Wizards.GenericPages
foreach (var kvp in m_vmMappings)
{
var tb = new DataGridViewTextBoxCell {Value = kvp.Value.VmNameLabel, Tag = kvp.Key};
var cb = new DataGridViewEnableableComboBoxCell{FlatStyle = FlatStyle.Flat};
var tb = new DataGridViewTextBoxCell { Value = kvp.Value.VmNameLabel, Tag = kvp.Key };
var cb = new DataGridViewEnableableComboBoxCell { FlatStyle = FlatStyle.Flat };
if (target != null)
{
@ -420,9 +410,9 @@ namespace XenAdmin.Wizards.GenericPages
var item = new NoTargetServerPoolItem(pool);
cb.Items.Add(item);
if ((m_selectedObject != null && m_selectedObject.opaque_ref == pool.opaque_ref) ||
(target.Item.opaque_ref == pool.opaque_ref))
cb.Value = item;
if ((SelectedTarget != null && SelectedTarget.opaque_ref == pool.opaque_ref) ||
target.Item.opaque_ref == pool.opaque_ref)
_preferredHomeRef = item.Item.opaque_ref;
}
}
@ -431,16 +421,19 @@ namespace XenAdmin.Wizards.GenericPages
foreach (var host in sortedHosts)
{
var filters = CreateTargetServerFilterList(host, new List<string> {kvp.Key});
var filters = CreateTargetServerFilterList(host, new List<string> { kvp.Key });
var item = new DelayLoadingOptionComboBoxItem(host, filters);
cb.Items.Add(item);
item.ParentComboBox = cb;
item.PreferAsSelectedItem = m_selectedObject != null && m_selectedObject.opaque_ref == host.opaque_ref ||
target.Item.opaque_ref == host.opaque_ref ||
sortedHosts.Count == 1;
if (SelectedTarget != null && SelectedTarget.opaque_ref == host.opaque_ref ||
target.Item.opaque_ref == host.opaque_ref)
_preferredHomeRef = item.Item.opaque_ref;
item.ReasonUpdated += DelayLoadedGridComboBoxItem_ReasonChanged;
item.LoadAsync();
}
if (cb.Items.Count == 1 && cb.Items[0] is DelayLoadingOptionComboBoxItem it)
_preferredHomeRef = it.Item.opaque_ref;
}
SetComboBoxPreSelection(cb);
@ -463,47 +456,47 @@ namespace XenAdmin.Wizards.GenericPages
updatingHomeServerList = false;
m_dataGridView.ResumeLayout();
}
}
}
private void SetComboBoxPreSelection(DataGridViewEnableableComboBoxCell cb)
{
if (cb.Value == null)
{
var firstEnabled = cb.Items.OfType<IEnableableComboBoxItem>().FirstOrDefault(i => i.Enabled);
if (firstEnabled != null)
{
cb.Value = firstEnabled;
SetButtonNextEnabled(true);
}
else
{
SetButtonNextEnabled(false);
}
}
else
{
private void SetComboBoxPreSelection(DataGridViewEnableableComboBoxCell cb)
{
if (cb.Value == null)
{
var firstEnabled = cb.Items.OfType<IEnableableComboBoxItem>().FirstOrDefault(i => i.Enabled);
if (firstEnabled != null)
{
cb.Value = firstEnabled;
SetButtonNextEnabled(true);
}
else
{
SetButtonNextEnabled(false);
}
}
else
{
SetButtonNextEnabled(true);
}
}
}
}
private static bool HasPoolSharedStorage(IXenConnection conn)
{
private static bool HasPoolSharedStorage(IXenConnection conn)
{
if (conn == null)
return false;
return false;
foreach (var pbd in conn.Cache.PBDs.Where(thePbd => thePbd.SR != null))
{
{
var sr = conn.Resolve(pbd.SR);
if (sr != null && sr.SupportsVdiCreate() && sr.shared)
return true;
}
return false;
}
#endregion
if (sr != null && sr.SupportsVdiCreate() && sr.shared)
return true;
}
return false;
}
#region Event Handlers
#endregion
#region Event Handlers
private void DelayLoadedComboBoxItem_ReasonChanged(DelayLoadingOptionComboBoxItem item)
{
@ -538,7 +531,7 @@ namespace XenAdmin.Wizards.GenericPages
m_comboBoxConnection.Items.Insert(index, tempItem);
m_comboBoxConnection.SelectedIndex = selectedIndex;
if (tempItem.PreferAsSelectedItem)
if (_preferredHomeRef == tempItem.Item.opaque_ref)
m_comboBoxConnection.SelectedItem = tempItem;
}
finally
@ -549,98 +542,107 @@ namespace XenAdmin.Wizards.GenericPages
});
}
private void DelayLoadedGridComboBoxItem_ReasonChanged(DelayLoadingOptionComboBoxItem item)
{
if (item == null)
throw new NullReferenceException("Trying to update delay loaded reason but failed to extract reason");
private void DelayLoadedGridComboBoxItem_ReasonChanged(DelayLoadingOptionComboBoxItem item)
{
if (item == null)
throw new NullReferenceException("Trying to update delay loaded reason but failed to extract reason");
var cb = item.ParentComboBox as DataGridViewEnableableComboBoxCell;
if (cb == null)
return;
var cb = item.ParentComboBox as DataGridViewEnableableComboBoxCell;
if (cb == null)
return;
Program.Invoke(this, () =>
{
try
{
var selectedValue = cb.Value;
if (cb.DataGridView == null)
return;
{
try
{
if (cb.DataGridView == null)
return;
var selectedValue = cb.Value;
cb.DataGridView.RefreshEdit();
if (item.Enabled && item.PreferAsSelectedItem)
cb.Value = item;
else
cb.Value = selectedValue;
SetButtonNextEnabled(cb.Value is IEnableableComboBoxItem enableableComboBoxItem && enableableComboBoxItem.Enabled);
if (item.Enabled && _preferredHomeRef == item.Item.opaque_ref)
cb.Value = item;
else
cb.Value = selectedValue;
cb.DataGridView.Refresh();
SetButtonNextEnabled(cb.Value is IEnableableComboBoxItem enableableComboBoxItem && enableableComboBoxItem.Enabled);
}
finally
{
item.ReasonUpdated -= DelayLoadedGridComboBoxItem_ReasonChanged;
}
});
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "name_label" || e.PropertyName == "metrics" ||
e.PropertyName == "enabled" || e.PropertyName == "live" || e.PropertyName == "patches")
Program.Invoke(this, PopulateComboBox);
}
private void CollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.BeginInvoke(this, PopulateComboBox);
}
private void xenConnection_CachePopulated(IXenConnection conn)
{
Program.Invoke(this, PopulateComboBox);
finally
{
item.ReasonUpdated -= DelayLoadedGridComboBoxItem_ReasonChanged;
}
});
}
private void xenConnection_ConnectionStateChanged(IXenConnection conn)
{
Program.Invoke(this, PopulateComboBox);
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "name_label" || e.PropertyName == "metrics" ||
e.PropertyName == "enabled" || e.PropertyName == "live" || e.PropertyName == "patches")
Program.Invoke(this, PopulateComboBox);
}
#endregion
private void CollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.BeginInvoke(this, PopulateComboBox);
}
#region Control event handlers
private void m_comboBoxConnection_SelectedIndexChanged(object sender, EventArgs e)
{
private void xenConnection_CachePopulated(IXenConnection conn)
{
Program.Invoke(this, PopulateComboBox);
}
private void xenConnection_ConnectionStateChanged(IXenConnection conn)
{
Program.Invoke(this, PopulateComboBox);
}
#endregion
#region Control event handlers
private void m_comboBoxConnection_SelectedIndexChanged(object sender, EventArgs e)
{
if (updatingHomeServerList)
return;
// when selecting a new destination pool, reset the target host selection
if (SelectedTargetPool != null && !SelectedTargetPool.Equals(m_comboBoxConnection.SelectedItem))
{
SelectedTarget = null;
}
//If the item is delay loading and them item is disabled, null the selection made
//and clear the table containing server data
IEnableableXenObjectComboBoxItem item = m_comboBoxConnection.SelectedItem as IEnableableXenObjectComboBoxItem;
if(item != null && !item.Enabled)
if (item != null && !item.Enabled)
{
m_comboBoxConnection.SelectedIndex = -1;
m_dataGridView.Rows.Clear();
ChosenItem = null;
SelectedTargetPool = null;
return;
}
AddHostRunningComboBoxItem exeItem = m_comboBoxConnection.SelectedItem as AddHostRunningComboBoxItem;
AddHostRunningComboBoxItem exeItem = m_comboBoxConnection.SelectedItem as AddHostRunningComboBoxItem;
if (exeItem != null && !updatingDestinationCombobox)
exeItem.RunCommand(this);
else if(!updatingDestinationCombobox)
{
try
{
Cursor.Current = Cursors.WaitCursor;
ChosenItem = item?.Item;
else if (!updatingDestinationCombobox)
{
try
{
Cursor.Current = Cursors.WaitCursor;
SelectedTargetPool = item?.Item;
PopulateDataGridView();
}
finally
{
}
finally
{
Cursor.Current = Cursors.Default;
}
}
IsDirty = true;
}
}
}
IsDirty = true;
}
/// <summary>
/// Create a set of filters for the homeserver combo box selection
@ -654,27 +656,41 @@ namespace XenAdmin.Wizards.GenericPages
}
private void m_dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != m_colTarget.Index || e.RowIndex < 0 || e.RowIndex >= m_dataGridView.RowCount)
return;
{
if (e.ColumnIndex != m_colTarget.Index || e.RowIndex < 0 || e.RowIndex >= m_dataGridView.RowCount)
return;
m_dataGridView.BeginEdit(false);
m_dataGridView.BeginEdit(false);
var editingControl = m_dataGridView.EditingControl as ComboBox;
if (editingControl != null)
editingControl.DroppedDown = true;
}
var editingControl = m_dataGridView.EditingControl as ComboBox;
if (editingControl != null)
editingControl.DroppedDown = true;
}
private void m_dataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
m_dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
IsDirty = true;
private void m_dataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
m_dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
IsDirty = true;
if (!m_buttonNextEnabled)
SetButtonNextEnabled(true);
}
}
private void m_dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || e.ColumnIndex < 0)
{
return;
}
var cell = m_dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
if (cell.Value is IEnableableXenObjectComboBoxItem value)
{
SelectedTarget = value.Item;
}
}
#endregion
#endregion
private void UnregisterHandlers()
{
ConnectionsManager.XenConnections.CollectionChanged -= CollectionChanged;
@ -698,14 +714,14 @@ namespace XenAdmin.Wizards.GenericPages
}
}
private void CancelFilters()
{
foreach (var item in m_comboBoxConnection.Items)
{
DelayLoadingOptionComboBoxItem comboBoxItem = item as DelayLoadingOptionComboBoxItem;
private void CancelFilters()
{
foreach (var item in m_comboBoxConnection.Items)
{
DelayLoadingOptionComboBoxItem comboBoxItem = item as DelayLoadingOptionComboBoxItem;
if (comboBoxItem != null)
comboBoxItem.CancelFilters();
}
}
}
}

View File

@ -151,7 +151,7 @@
<value>m_labelIntro</value>
</data>
<data name="&gt;&gt;m_labelIntro.Type" xml:space="preserve">
<value>XenAdmin.Controls.Common.AutoHeightLabel, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
<value>XenAdmin.Controls.Common.AutoHeightLabel, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;m_labelIntro.Parent" xml:space="preserve">
<value>tableLayoutPanel1</value>
@ -205,7 +205,7 @@
<value>m_comboBoxConnection</value>
</data>
<data name="&gt;&gt;m_comboBoxConnection.Type" xml:space="preserve">
<value>XenAdmin.Controls.EnableableComboBox, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
<value>XenAdmin.Controls.EnableableComboBox, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;m_comboBoxConnection.Parent" xml:space="preserve">
<value>tableLayoutPanel1</value>
@ -427,12 +427,12 @@
<value>m_colTarget</value>
</data>
<data name="&gt;&gt;m_colTarget.Type" xml:space="preserve">
<value>XenAdmin.Controls.EnableableComboBoxColumn, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
<value>XenAdmin.Controls.EnableableComboBoxColumn, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>SelectMultipleVMDestinationPage</value>
</data>
<data name="&gt;&gt;$this.Type" xml:space="preserve">
<value>XenAdmin.Controls.XenTabPage, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
<value>XenAdmin.Controls.XenTabPage, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
</root>

View File

@ -36,37 +36,37 @@ using XenModel;
namespace XenAdmin.Wizards.ImportWizard
{
internal partial class ImageVMConfigPage : XenTabPage
{
private const ulong KB = 1024;
private const ulong MB = (KB * 1024);
private const ulong GB = (MB * 1024);
internal partial class ImageVMConfigPage : XenTabPage
{
private const ulong KB = 1024;
private const ulong MB = (KB * 1024);
private const ulong GB = (MB * 1024);
private bool m_buttonNextEnabled;
public ImageVMConfigPage()
{
InitializeComponent();
public ImageVMConfigPage()
{
InitializeComponent();
m_upDownMemory.Minimum = m_upDownMemory.Increment = (decimal)VM.DEFAULT_MEM_MIN_IMG_IMPORT / Util.BINARY_MEGA;
m_upDownMemory.Maximum = (decimal)VM.DEFAULT_MEM_ALLOWED / Util.BINARY_MEGA;
m_ctrlError.HideError();
}
m_ctrlError.HideError();
}
#region Base class (XenTabPage) overrides
#region Base class (XenTabPage) overrides
/// <summary>
/// Gets the page's title (headline)
/// </summary>
/// <summary>
/// Gets the page's title (headline)
/// </summary>
public override string PageTitle => Messages.IMAGE_DEFINITION_PAGE_TITLE;
/// <summary>
/// Gets the page's label in the (left hand side) wizard progress panel
/// </summary>
/// <summary>
/// Gets the page's label in the (left hand side) wizard progress panel
/// </summary>
public override string Text => Messages.IMAGE_DEFINITION_PAGE_TEXT;
/// <summary>
/// Gets the value by which the help files section for this page is identified
/// </summary>
/// <summary>
/// Gets the value by which the help files section for this page is identified
/// </summary>
public override string HelpID => "VMConfig";
protected override bool ImplementsIsDirty()
@ -75,15 +75,15 @@ namespace XenAdmin.Wizards.ImportWizard
}
public override void PopulatePage()
{
//CA-61385: remove wim support for Boston
m_groupBoxAddSpace.Visible = false;
m_groupBoxAddSpace.Enabled = IsWim;
m_textBoxVMName.Text = string.Empty;
m_upDownMemory.Value = m_upDownMemory.Minimum;
m_upDownCpuCount.Value = m_upDownCpuCount.Minimum;
m_upDownAddSpace.Value = m_upDownAddSpace.Minimum;
}
{
//CA-61385: remove wim support for Boston
m_groupBoxAddSpace.Visible = false;
m_groupBoxAddSpace.Enabled = IsWim;
m_textBoxVMName.Text = string.Empty;
m_upDownMemory.Value = m_upDownMemory.Minimum;
m_upDownCpuCount.Value = m_upDownCpuCount.Minimum;
m_upDownAddSpace.Value = m_upDownAddSpace.Minimum;
}
public override void SelectDefaultControl()
{
@ -95,11 +95,11 @@ namespace XenAdmin.Wizards.ImportWizard
return m_buttonNextEnabled;
}
#endregion
#endregion
#region Accessors
#region Accessors
public bool IsWim { internal get; set; }
public bool IsWim { internal get; set; }
public string VmName => m_textBoxVMName.Text;
@ -109,52 +109,52 @@ namespace XenAdmin.Wizards.ImportWizard
public ulong AdditionalSpace => m_groupBoxAddSpace.Visible && m_groupBoxAddSpace.Enabled ? (ulong)m_upDownAddSpace.Value * GB : 0;
#endregion
#endregion
#region Private Methods
#region Private Methods
private bool CheckVmNameValid(string name, out string error)
{
error = string.Empty;
{
error = string.Empty;
if (String.IsNullOrEmpty(name))
return false;
if (String.IsNullOrEmpty(name))
return false;
if (!PathValidator.IsFileNameValid(name, out string invalidNameMsg))
{
error = invalidNameMsg;
return false;
}
return true;
}
if (!PathValidator.IsFileNameValid(name, out string invalidNameMsg))
{
error = invalidNameMsg;
return false;
}
return true;
}
#endregion
#endregion
#region Control event handlers
#region Control event handlers
private void m_textBoxVMName_TextChanged(object sender, EventArgs e)
{
private void m_textBoxVMName_TextChanged(object sender, EventArgs e)
{
m_buttonNextEnabled = m_ctrlError.PerformCheck((out string error) => CheckVmNameValid(m_textBoxVMName.Text, out error));
OnPageUpdated();
IsDirty = true;
}
private void m_upDownMemory_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
IsDirty = true;
}
private void m_upDownCpuCount_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
private void m_upDownMemory_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
private void m_upDownAddSpace_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
private void m_upDownCpuCount_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
#endregion
private void m_upDownAddSpace_ValueChanged(object sender, EventArgs e)
{
IsDirty = true;
}
#endregion
}
}

View File

@ -133,7 +133,7 @@ namespace XenAdmin.Wizards.ImportWizard
{
var warnings = new List<string>();
if (ChosenItem != null)
if (SelectedTargetPool != null)
{
if (!CheckDestinationSupportsVendorDevice())
{
@ -157,7 +157,7 @@ namespace XenAdmin.Wizards.ImportWizard
ShowWarning(string.Join("\n", warnings));
if (ConnectionSelectionChanged != null)
ConnectionSelectionChanged(ChosenItem?.Connection);
ConnectionSelectionChanged(SelectedTargetPool?.Connection);
}
protected override DelayLoadingOptionComboBoxItem CreateDelayLoadingOptionComboBoxItem(IXenObject xenItem)
@ -189,7 +189,7 @@ namespace XenAdmin.Wizards.ImportWizard
var types = m.Groups[1].Value.Split(';');
var gpuGroup = ChosenItem.Connection.Cache.GPU_groups.FirstOrDefault(g =>
var gpuGroup = SelectedTargetPool.Connection.Cache.GPU_groups.FirstOrDefault(g =>
g.GPU_types.Length == types.Length &&
g.GPU_types.Intersect(types).Count() == types.Length);
@ -199,7 +199,7 @@ namespace XenAdmin.Wizards.ImportWizard
string vendorName = m.Groups[2].Value;
string modelName = m.Groups[3].Value;
var vgpuType = ChosenItem.Connection.Cache.VGPU_types.FirstOrDefault(v =>
var vgpuType = SelectedTargetPool.Connection.Cache.VGPU_types.FirstOrDefault(v =>
v.vendor_name == vendorName && v.model_name == modelName);
if (vgpuType == null)
@ -211,7 +211,7 @@ namespace XenAdmin.Wizards.ImportWizard
private bool CheckDestinationSupportsVendorDevice()
{
var dundeeOrNewerHosts = Helpers.DundeeOrGreater(ChosenItem.Connection) ? ChosenItem.Connection.Cache.Hosts : new Host[] {};
var dundeeOrNewerHosts = Helpers.DundeeOrGreater(SelectedTargetPool.Connection) ? SelectedTargetPool.Connection.Cache.Hosts : new Host[] {};
foreach (var setting in vendorDeviceSettings)
{

View File

@ -212,7 +212,7 @@ namespace XenAdmin.Wizards.ImportWizard
m_vmMappings.Add(sysId, new VmMapping(sysId) {VmNameLabel = FindVMName(_selectedOvfPackage.OvfEnvelope, sysId)});
m_pageHost.SelectedOvfEnvelope = _selectedOvfPackage.OvfEnvelope;
m_pageHost.SetDefaultTarget(m_pageHost.ChosenItem ?? m_selectedObject);
m_pageHost.SelectedTarget = m_pageHost.SelectedTargetPool ?? m_selectedObject;
m_pageHost.VmMappings = m_vmMappings;
m_pageStorage.SelectedOvfEnvelope = _selectedOvfPackage.OvfEnvelope;
lunPerVdiMappingPage.SelectedOvfEnvelope = _selectedOvfPackage.OvfEnvelope;
@ -296,7 +296,7 @@ namespace XenAdmin.Wizards.ImportWizard
m_vmMappings.Add(sysId, newMapping);
m_pageHost.VmMappings = m_vmMappings;
m_pageHost.SetDefaultTarget(m_pageHost.ChosenItem ?? m_selectedObject);
m_pageHost.SelectedTarget = m_pageHost.SelectedTargetPool ?? m_selectedObject;
m_pageHost.SelectedOvfEnvelope = m_envelopeFromVhd;
m_pageStorage.SelectedOvfEnvelope = m_envelopeFromVhd;
@ -309,7 +309,7 @@ namespace XenAdmin.Wizards.ImportWizard
else if (type == typeof(ImportSelectHostPage))
{
var oldTargetConnection = _targetConnection;
_targetConnection = m_pageHost.ChosenItem?.Connection;
_targetConnection = m_pageHost.SelectedTargetPool?.Connection;
var oldHostSelection = m_vmMappings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.TargetName);
m_vmMappings = m_pageHost.VmMappings;