2013-11-14 13:59:08 +01:00
|
|
|
|
/* 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;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2013-11-14 12:06:50 +01:00
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using XenAdmin.Controls.DataGridViewEx;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
using XenAdmin.Network;
|
2013-11-14 12:06:50 +01:00
|
|
|
|
using XenAdmin.Properties;
|
|
|
|
|
using XenAPI;
|
|
|
|
|
|
|
|
|
|
namespace XenAdmin.Controls.GPU
|
|
|
|
|
{
|
|
|
|
|
public partial class GpuRow : UserControl
|
|
|
|
|
{
|
|
|
|
|
public GpuRow()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-11 11:30:06 +01:00
|
|
|
|
public GpuRow(IXenObject xenObject, List<PGPU> pGpuList)
|
2013-11-14 12:06:50 +01:00
|
|
|
|
: this()
|
|
|
|
|
{
|
2013-12-11 11:30:06 +01:00
|
|
|
|
this.xenObject = xenObject;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
pGpuLabel.Text = pGpuList[0].Name;
|
|
|
|
|
RepopulateAllowedTypes(pGpuList[0]);
|
|
|
|
|
Rebuild(pGpuList);
|
|
|
|
|
SetupPage();
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-11 11:30:06 +01:00
|
|
|
|
private readonly IXenObject xenObject;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
|
|
|
|
|
private Dictionary<PGPU, CheckBox> pGpus = new Dictionary<PGPU, CheckBox>();
|
|
|
|
|
|
|
|
|
|
private void Rebuild(List<PGPU> pGpuList)
|
2013-11-14 12:06:50 +01:00
|
|
|
|
{
|
2013-11-14 12:23:35 +01:00
|
|
|
|
Program.AssertOnEventThread();
|
|
|
|
|
if (!Visible)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
shinyBarsContainerPanel.SuspendLayout();
|
|
|
|
|
|
|
|
|
|
// Store a list of the current controls. We remove them at the end because it makes less flicker that way.
|
|
|
|
|
var oldControls = new List<Control>(shinyBarsContainerPanel.Controls.Count);
|
|
|
|
|
oldControls.AddRange(shinyBarsContainerPanel.Controls.Cast<Control>());
|
|
|
|
|
|
2013-12-11 11:30:06 +01:00
|
|
|
|
bool showingHostLabel = (xenObject is Pool) && xenObject.Connection.Cache.Hosts.Length > 1;
|
2013-11-14 12:39:31 +01:00
|
|
|
|
|
2013-11-14 12:23:35 +01:00
|
|
|
|
int index = 1;
|
|
|
|
|
XenRef<Host> hostRef = null;
|
2013-11-14 12:39:31 +01:00
|
|
|
|
|
2013-11-14 12:23:35 +01:00
|
|
|
|
foreach (PGPU pgpu in pGpuList)
|
|
|
|
|
{
|
2013-12-11 11:30:06 +01:00
|
|
|
|
var host = xenObject.Connection.Resolve(pgpu.host);
|
2013-11-14 12:23:35 +01:00
|
|
|
|
|
|
|
|
|
// add host label if needed
|
2013-11-14 12:39:31 +01:00
|
|
|
|
if (showingHostLabel && (hostRef == null || pgpu.host.opaque_ref != hostRef.opaque_ref))
|
2013-11-14 12:23:35 +01:00
|
|
|
|
{
|
|
|
|
|
AddHostLabel(new Label { Text = String.Format(Messages.GPU_ON_HOST_LABEL, host.Name)}, ref index);
|
|
|
|
|
hostRef = pgpu.host;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add pGPU shiny bar
|
|
|
|
|
var gpuShinyBar = new GpuShinyBar();
|
2013-11-14 12:28:43 +01:00
|
|
|
|
var checkBox = pGpuList.Count > 1 ? new CheckBox() : null;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
AddShinyBar(gpuShinyBar, checkBox, ref index);
|
|
|
|
|
gpuShinyBar.Initialize(pgpu);
|
|
|
|
|
|
|
|
|
|
pGpus.Add(pgpu, checkBox);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove old controls
|
|
|
|
|
foreach (Control c in oldControls)
|
2013-11-14 12:06:50 +01:00
|
|
|
|
{
|
2013-11-14 12:23:35 +01:00
|
|
|
|
shinyBarsContainerPanel.Controls.Remove(c);
|
|
|
|
|
c.Dispose();
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
2013-11-14 12:23:35 +01:00
|
|
|
|
shinyBarsContainerPanel.ResumeLayout();
|
|
|
|
|
ReLayout();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddShinyBar(UserControl shinyBar, CheckBox checkBox, ref int index)
|
|
|
|
|
{
|
|
|
|
|
if (checkBox != null)
|
|
|
|
|
{
|
|
|
|
|
shinyBarsContainerPanel.Controls.Add(checkBox, 0, index);
|
|
|
|
|
checkBox.Dock = DockStyle.Fill;
|
2013-11-14 12:39:31 +01:00
|
|
|
|
checkBox.Margin = new Padding(3, 14, 0, 0);
|
2013-11-14 12:28:43 +01:00
|
|
|
|
checkBox.CheckedChanged += CheckedChanged;
|
|
|
|
|
checkBox.Checked = true;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shinyBarsContainerPanel.Controls.Add(shinyBar, 1, index);
|
|
|
|
|
shinyBar.Dock = DockStyle.Fill;
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddHostLabel(Label label, ref int index)
|
|
|
|
|
{
|
|
|
|
|
shinyBarsContainerPanel.Controls.Add(label, 0, index);
|
|
|
|
|
shinyBarsContainerPanel.SetColumnSpan(label, 2);
|
|
|
|
|
label.Dock = DockStyle.Fill;
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ReLayout()
|
|
|
|
|
{
|
|
|
|
|
Program.AssertOnEventThread();
|
|
|
|
|
Height = tableLayoutPanel1.Height + 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetupPage()
|
|
|
|
|
{
|
|
|
|
|
multipleSelectionPanel.Visible = (pGpus.Count > 1);
|
2013-11-14 12:41:05 +01:00
|
|
|
|
editButton.Text = (pGpus.Count > 1) ? Messages.GPU_EDIT_ALLOWED_TYPES_MULTIPLE : Messages.GPU_EDIT_ALLOWED_TYPES_SINGLE;
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-14 12:28:43 +01:00
|
|
|
|
private GpuShinyBar FindGpuShinyBar(PGPU pGpu)
|
2013-11-14 12:06:50 +01:00
|
|
|
|
{
|
2013-11-14 12:28:43 +01:00
|
|
|
|
return pGpu != null
|
|
|
|
|
? shinyBarsContainerPanel.Controls.OfType<GpuShinyBar>().FirstOrDefault(
|
|
|
|
|
shinyBar => shinyBar.PGPU == pGpu)
|
|
|
|
|
: null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RefreshGpu(PGPU pGpu)
|
|
|
|
|
{
|
|
|
|
|
Program.AssertOnEventThread();
|
|
|
|
|
if (!Visible)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
GpuShinyBar gpuShinyBar = FindGpuShinyBar(pGpu);
|
|
|
|
|
if (gpuShinyBar != null)
|
2013-11-14 12:06:50 +01:00
|
|
|
|
{
|
2013-11-14 12:28:43 +01:00
|
|
|
|
gpuShinyBar.Initialize(pGpu);
|
|
|
|
|
gpuShinyBar.Refresh();
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
2013-11-14 12:28:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<PGPU> PGPUs
|
|
|
|
|
{
|
|
|
|
|
get
|
2013-11-14 12:06:50 +01:00
|
|
|
|
{
|
2013-11-14 12:28:43 +01:00
|
|
|
|
return pGpus.Keys;
|
2013-11-14 12:23:35 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<PGPU> SelectedPGPUs
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (pGpus.Count == 0)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return pGpus.Count > 1
|
|
|
|
|
? (from kvp in pGpus where kvp.Value != null && kvp.Value.Checked select kvp.Key).ToList()
|
|
|
|
|
: new List<PGPU> {pGpus.Keys.ElementAt(0)};
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-14 12:23:35 +01:00
|
|
|
|
|
|
|
|
|
private void selectAllButton_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
foreach (var checkBox in pGpus.Values.Where(checkBox => checkBox != null))
|
|
|
|
|
{
|
|
|
|
|
checkBox.Checked = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void clearAllButton_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
foreach (var checkBox in pGpus.Values.Where(checkBox => checkBox != null))
|
|
|
|
|
{
|
|
|
|
|
checkBox.Checked = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void editButton_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new GpuConfiguration(SelectedPGPUs).ShowDialog(Program.MainWindow);
|
|
|
|
|
}
|
2013-11-14 12:28:43 +01:00
|
|
|
|
|
|
|
|
|
private void CheckedChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
2013-11-14 12:39:31 +01:00
|
|
|
|
editButton.Enabled = clearAllButton.Enabled =
|
2013-11-14 12:28:43 +01:00
|
|
|
|
(pGpus.Values.Where(checkBox => checkBox != null).Any(checkBox => checkBox.Checked));
|
|
|
|
|
selectAllButton.Enabled =
|
|
|
|
|
(pGpus.Values.Where(checkBox => checkBox != null).Any(checkBox => !checkBox.Checked));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Allowed vGpu types
|
|
|
|
|
private void RepopulateAllowedTypes(PGPU pGpu)
|
|
|
|
|
{
|
|
|
|
|
allowedTypesGrid.SuspendLayout();
|
|
|
|
|
allowedTypesGrid.Rows.Clear();
|
|
|
|
|
allowedTypesGrid.Cursor = Cursors.WaitCursor;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
allowedTypesGrid.Rows.Clear();
|
|
|
|
|
if (pGpu.supported_VGPU_types != null && pGpu.supported_VGPU_types.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
allowedTypesGrid.Rows.AddRange((from vGpuTypeRef in pGpu.supported_VGPU_types
|
|
|
|
|
let vGpuType = pGpu.Connection.Resolve(vGpuTypeRef)
|
|
|
|
|
let enabledType = pGpu.enabled_VGPU_types.Contains(vGpuTypeRef)
|
|
|
|
|
orderby vGpuType.Capacity ascending
|
|
|
|
|
select new VGpuTypeRow(vGpuType, enabledType)).ToArray());
|
|
|
|
|
}
|
2013-11-14 12:39:31 +01:00
|
|
|
|
allowedTypesGrid.Height = allowedTypesGrid.Rows[0].Height * (allowedTypesGrid.RowCount);
|
2013-11-14 12:28:43 +01:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
allowedTypesGrid.ResumeLayout();
|
|
|
|
|
allowedTypesGrid.Cursor = Cursors.Default;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2013-11-14 12:06:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class VGpuTypeRow : DataGridViewExRow
|
|
|
|
|
{
|
|
|
|
|
public VGPU_type VGpuType;
|
|
|
|
|
public bool EnabledType;
|
|
|
|
|
|
|
|
|
|
private readonly DataGridViewExImageCell ImageCell = new DataGridViewExImageCell();
|
|
|
|
|
private readonly DataGridViewTextBoxCell NameCell = new DataGridViewTextBoxCell();
|
|
|
|
|
|
|
|
|
|
public VGpuTypeRow(VGPU_type vGpuType, bool enabledType)
|
|
|
|
|
{
|
|
|
|
|
VGpuType = vGpuType;
|
|
|
|
|
EnabledType = enabledType;
|
|
|
|
|
|
|
|
|
|
Cells.AddRange(ImageCell,
|
|
|
|
|
NameCell);
|
|
|
|
|
|
|
|
|
|
UpdateDetails();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateDetails()
|
|
|
|
|
{
|
|
|
|
|
ImageCell.Value = EnabledType ? Resources._000_Tick_h32bit_16 : Resources._000_Abort_h32bit_16;
|
|
|
|
|
NameCell.Value = VGpuType.Name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|