/* 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.Windows.Forms;
using XenAdmin.Network;
using XenAPI;
using XenAdmin.Core;
using XenAdmin.Controls.DataGridViewEx;
using System.Collections.Generic;
namespace XenAdmin.Controls
{
///
/// This control is used by both the New VM Wizard and the Import VM Wizard.
///
public partial class AffinityPicker : UserControl
{
private IXenConnection Connection;
private Host SrHost;
private Host Affinity;
public event EventHandler SelectedAffinityChanged = new EventHandler(OnSelectedAffinityChanged);
private static void OnSelectedAffinityChanged(object obj, EventArgs e) { }
public AffinityPicker()
{
InitializeComponent();
}
public void SetAffinity(IXenConnection connection, Host affinity, Host srhost)
{
Connection = connection;
Affinity = affinity;
SrHost = srhost;
tableLayoutPanelWlbWarning.Visible = Helpers.WlbEnabledAndConfigured(connection);
LoadServers();
_UpdateControl();
SelectRadioButtons();
SelectedAffinityChanged(SelectedAffinity, new EventArgs());
}
private void LoadServers()
{
ServersGridView.Rows.Clear();
List hosts = new List(Connection.Cache.Hosts);
hosts.Sort();
foreach (Host host in hosts)
ServersGridView.Rows.Add(new ServerGridRow(host, true));
}
private void UpdateControl()
{
_UpdateControl();
SelectedAffinityChanged(SelectedAffinity, new EventArgs());
}
///
/// does not fire selected affinity changed event
///
private void _UpdateControl()
{
if (Connection == null)
return;
// Update enablement
DynamicRadioButton.Enabled = (Helpers.HasFullyConnectedSharedStorage(Connection) && SrHost == null) || Affinity == null;
ServersGridView.Enabled = StaticRadioButton.Checked;
DynamicRadioButton.Text = Helpers.HasFullyConnectedSharedStorage(Connection)
? Messages.AFFINITY_PICKER_DYNAMIC_SHARED_SR
: Messages.AFFINITY_PICKER_DYNAMIC_NOT_SHARED_SR;
}
private void SelectRadioButtons()
{
if (!SelectAffinityServer() && DynamicRadioButton.Enabled)
{
//Trace.Assert(DynamicRadioButton.Enabled, "Could not select any hosts or find shared storage");
DynamicRadioButton.Checked = true; // always set dynamic check state before static because static check has an event handler
StaticRadioButton.Checked = false;
}
else
{
DynamicRadioButton.Checked = false; // always set dynamic check state before static because static check has an event handler
StaticRadioButton.Checked = true;
}
}
public Host SelectedAffinity
{
get
{
return DynamicRadioButton.Checked ? null : SelectedServer();
}
}
private Host SelectedServer()
{
if (ServersGridView.SelectedRows.Count == 0)
return null;
Host h = ((ServerGridRow)ServersGridView.SelectedRows[0]).Server;
if (h == null)
return null;
return h;
}
private bool SelectServer(Host host)
{
foreach (ServerGridRow row in ServersGridView.Rows)
{
if (row.Server.opaque_ref != host.opaque_ref)
continue;
if (row.Enabled)
{
row.Selected = true;
return true;
}
return false;
}
return false;
}
private bool SelectAffinityServer()
{
return Affinity != null && SelectServer(Affinity);
}
private bool SelectSomething()
{
//Now decide if we want to select anything.
bool selected = false;
if (Affinity != null)
selected = SelectServer(Affinity);
if (!selected && SrHost != null)
selected = SelectServer(SrHost);
/* if (!selected)
selected = SelectAnyServer();*/
return selected;
}
public bool ValidState()
{
return SelectedAffinity != null || DynamicRadioButton.Checked;
}
private void affinityListBox_SelectedValueChanged(object sender, EventArgs e)
{
UpdateControl();
}
// we dont need to bother firing events if the other radio button gets checked or unchecked
private void StaticRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (StaticRadioButton.Checked && SelectedServer() == null)
SelectSomething();
UpdateControl();
if (StaticRadioButton.Checked)
ServersGridView.Select();
}
protected override void OnEnter(EventArgs e)
{
if (DynamicRadioButton.Checked)
DynamicRadioButton.Select();
else
ServersGridView.Select();
}
}
internal class ServerGridRow : DataGridViewExRow
{
public readonly Host Server;
private readonly DataGridViewExImageCell ImageCell = new DataGridViewExImageCell();
private readonly DataGridViewTextBoxCell NameCell = new DataGridViewTextBoxCell();
private readonly DataGridViewTextBoxCell ReasonCell = new DataGridViewTextBoxCell();
private readonly bool showReason;
public ServerGridRow(Host server, bool showReason)
{
Server = server;
this.showReason = showReason;
Cells.Add(ImageCell);
Cells.Add(NameCell);
if (showReason)
{
Cells.Add(ReasonCell);
}
UpdateDetails();
}
private void UpdateDetails()
{
ImageCell.Value = Images.GetImage16For(Server);
NameCell.Value = Server.Name;
Enabled = Server.IsLive;
if (showReason)
{
ReasonCell.Value = Server.IsLive ? Server.HostMemoryString : Messages.HOMESERVER_PICKER_HOST_NOT_LIVE;
}
}
}
}