mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 06:16:37 +01:00
17527eebe4
- Added Topology drop-down box with available values for sockets and cores per socket, so that the number of vCPUs is divisible by the number of cores per socket. E.g. if user specified 8 vCPUs, Cores per socket can only be 1, 2, 4, or 8. - This updates VM's platform:cores-per-socket property. - Can only be set when the VM is shut down (similar to number of vCPUs). - Text on CPU page - changed to include topology. Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
146 lines
5.5 KiB
C#
146 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using XenAPI;
|
|
|
|
namespace XenAdmin.Controls
|
|
{
|
|
public partial class CPUTopologyComboBox : LongStringComboBox
|
|
{
|
|
public CPUTopologyComboBox()
|
|
{
|
|
DropDownStyle = ComboBoxStyle.DropDownList;
|
|
Sorted = false;
|
|
}
|
|
|
|
public long CoresPerSocket { get; private set; }
|
|
private long origNoOfVCPUs;
|
|
private long origCoresPerSocket;
|
|
private long maxNoOfCoresPerSocket;
|
|
|
|
/// <summary>
|
|
/// Populate the combo box options, based on maxVCPUs.
|
|
/// </summary>
|
|
/// <param name="noOfVCPUs">Current value VCPUs_at_startup</param>
|
|
/// <param name="maxVCPUs">Current value of VCPUs_max</param>
|
|
/// <param name="coresPerSocket">Current value of platform:cores-per-socket</param>
|
|
/// <param name="maxCoresPerSocket">Number of cores per socket on the underlying server</param>
|
|
public void Populate(long noOfVCPUs, long maxVCPUs, long coresPerSocket, long maxCoresPerSocket)
|
|
{
|
|
origNoOfVCPUs = noOfVCPUs;
|
|
origCoresPerSocket = CoresPerSocket = coresPerSocket;
|
|
maxNoOfCoresPerSocket = maxCoresPerSocket;
|
|
Update(maxVCPUs);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Repopulate the combobox options, based on number of vCPUs and update the selected item
|
|
/// </summary>
|
|
/// <param name="noOfVCPUs"></param>
|
|
public void Update(long noOfVCPUs)
|
|
{
|
|
BeginUpdate();
|
|
try
|
|
{
|
|
Items.Clear();
|
|
// Build the list of topologies, based on number of vCPUs
|
|
var topologies = GetTopologies(noOfVCPUs, maxNoOfCoresPerSocket);
|
|
Items.AddRange(topologies.ToArray());
|
|
|
|
// if the original value is not in the list (because is invalid) and the noOfVCPU hasn't changed,
|
|
// then add it to the combo box as an invalid configuration
|
|
if (origNoOfVCPUs == noOfVCPUs &&
|
|
!topologies.Any(topologyTuple => topologyTuple.Cores == origCoresPerSocket))
|
|
{
|
|
Items.Add(new TopologyTuple(origCoresPerSocket));
|
|
}
|
|
|
|
// try to re-select the current value
|
|
foreach (var item in Items)
|
|
{
|
|
if (item as TopologyTuple != null && (item as TopologyTuple ).Cores.Equals(CoresPerSocket))
|
|
{
|
|
SelectedItem = item;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (SelectedIndex < 0 && Items.Count > 0) // if nothing selected, select first item
|
|
SelectedIndex = 0;
|
|
EndUpdate();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build the list of topologies, based on number of vCPUs.
|
|
/// This list will contain only valid values, i.e. cores per socket is a factor of number of vCPUs
|
|
/// and does not exceed the number of cores per socket on the underlying server.
|
|
/// </summary>
|
|
/// <param name="noOfVCPUs">Number of vCPUs</param>
|
|
/// <param name="maxNoOfCoresPerSocket">Maximum number of cores per socket</param>
|
|
/// <returns>A list of topologies</returns>
|
|
private static List<TopologyTuple> GetTopologies(long noOfVCPUs, long maxNoOfCoresPerSocket)
|
|
{
|
|
var result = new List<TopologyTuple>();
|
|
var maxCoresPerSocket = Math.Min(noOfVCPUs, maxNoOfCoresPerSocket);
|
|
for (var cores = 1; cores <= maxCoresPerSocket; cores++)
|
|
{
|
|
if (noOfVCPUs % cores == 0)
|
|
result.Add(new TopologyTuple(noOfVCPUs / cores, cores));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
protected override void OnSelectedIndexChanged(EventArgs e)
|
|
{
|
|
var selectedTopology = SelectedItem as TopologyTuple;
|
|
if (selectedTopology != null)
|
|
CoresPerSocket = selectedTopology.Cores;
|
|
base.OnSelectedIndexChanged(e);
|
|
}
|
|
}
|
|
|
|
public class TopologyTuple
|
|
{
|
|
public readonly long Sockets;
|
|
public readonly long Cores;
|
|
|
|
/// <summary>
|
|
/// Constructor used for valid configurations
|
|
/// </summary>
|
|
/// <param name="sockets"></param>
|
|
/// <param name="cores"></param>
|
|
public TopologyTuple(long sockets, long cores)
|
|
{
|
|
this.Sockets = sockets;
|
|
this.Cores = cores;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor used for invalid cores per socket value
|
|
/// </summary>
|
|
/// <param name="cores"></param>
|
|
public TopologyTuple(long cores)
|
|
{
|
|
this.Sockets = 0;
|
|
this.Cores = cores;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if (Sockets == 0) // invalid cores value
|
|
return string.Format(Messages.CPU_TOPOLOGY_STRING_INVALID_VALUE, Cores);
|
|
if (Sockets == 1 && Cores == 1)
|
|
return Messages.CPU_TOPOLOGY_STRING_1_SOCKET_1_CORE;
|
|
if (Sockets == 1)
|
|
return string.Format(Messages.CPU_TOPOLOGY_STRING_1_SOCKET_N_CORE, Cores);
|
|
if (Cores == 1)
|
|
return string.Format(Messages.CPU_TOPOLOGY_STRING_N_SOCKET_1_CORE, Sockets);
|
|
return string.Format(Messages.CPU_TOPOLOGY_STRING_N_SOCKET_N_CORE, Sockets, Cores);
|
|
}
|
|
}
|
|
}
|