2017-01-16 21:14:56 +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;
|
2014-06-05 14:00:14 +02:00
|
|
|
|
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;
|
2016-02-12 18:01:05 +01:00
|
|
|
|
private long maxNoOfCoresPerSocket;
|
2014-06-05 14:00:14 +02:00
|
|
|
|
|
|
|
|
|
/// <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>();
|
2014-07-17 13:46:59 +02:00
|
|
|
|
var maxCoresPerSocket = maxNoOfCoresPerSocket > 0 ? Math.Min(noOfVCPUs, maxNoOfCoresPerSocket) : noOfVCPUs;
|
2014-06-05 14:00:14 +02:00
|
|
|
|
for (var cores = 1; cores <= maxCoresPerSocket; cores++)
|
|
|
|
|
{
|
2016-02-12 18:01:05 +01:00
|
|
|
|
if (noOfVCPUs % cores == 0 && noOfVCPUs / cores <= VM.MAX_SOCKETS)
|
2014-06-05 14:00:14 +02:00
|
|
|
|
result.Add(new TopologyTuple(noOfVCPUs / cores, cores));
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2016-02-12 18:01:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsValidVCPU(long noOfVCPUs)
|
|
|
|
|
{
|
|
|
|
|
return GetTopologies(noOfVCPUs, maxNoOfCoresPerSocket).Count != 0;
|
2014-06-05 14:00:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
{
|
2014-07-14 16:17:47 +02:00
|
|
|
|
return VM.GetTopology(Sockets, Cores);
|
2014-06-05 14:00:14 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|