mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2025-01-20 15:29:26 +01:00
Merge pull request #2848 from kc284/datasources
* DataSet field Uuid is not really a uuid. Renamed to Id to avoid misunderstandings. * Renamed properties DataSet.Type and DataSourceItem.DataType to Category. The old name was not reflecting what they were. * Renamed property DataSet.TypeString to DataSet.DataSourceName so it reflects better what it is. * Renamed property DataSet.Name to DataSet.FriendlyName for clarity. Removed duplicate string.Format() call. * The DataSourceItem.Uuid is not really a uuid. Renamed it to Id to avoid misunderstandings. Also, compacted DataSourceItem constructors. * Removed unused and duplicate properties. - DataKey.Hide was unused. Once removed, DataSet.Deselected was unused, hence was also removed. - Dataset.Draw was duplicating DataSet.Show, hence was removed. - DataSet.NeverShow is not necessary, DataSet.Hide can be used both for datasources that should not be shown at all as well as datasources that are wrong for this object. * Made DataSet.FriendlyName a get-only property and compacted repetitive code. * Use the Helpers regular expressions for assigning the datasource category. * Removed id from the DataSet constructor parameters. It can be constructed from the XenObject and the datasource name. * Compacted the code for readability (it was difficult to follow the build of the URIs). Also, removed use of Helper.GetUuid to avoid the use of reflection. Minimised casts. * CP-36567: Use the datasource units as specified in the API instead of deducing them from the datasource name. - Also, merged static method DataSet.Create into the DataSet constructor. - Minor restructuring of the ArchiveMaintainer file (moved all private fields and properties closer together). - Added new resource file so the units can be separated from Messages.
This commit is contained in:
commit
af832f23cf
@ -33,6 +33,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
@ -46,20 +47,6 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public class ArchiveMaintainer
|
||||
{
|
||||
private delegate void ReaderDelegate(XmlReader reader, IXenObject xmo);
|
||||
private delegate Uri URIDelegate(Session session, Host host, ArchiveInterval interval, IXenObject xmo);
|
||||
|
||||
internal const string RrdUpdatesPath = "rrd_updates";
|
||||
private const string RrdHostPath = "host_rrds";
|
||||
private const string RrdVmPath = "vm_rrds";
|
||||
internal const string RrdCFAverage = "AVERAGE";
|
||||
|
||||
private const string RrdHostUpdatesQuery = "session_id={0}&start={1}&cf={2}&interval={3}&host=true&vm_uuid=";
|
||||
internal const string RrdHostAndVmUpdatesQuery = "session_id={0}&start={1}&cf={2}&interval={3}&host=true";
|
||||
private const string RrdVmUpdatesQuery = "session_id={0}&start={1}&cf={2}&interval={3}&vm_uuid={4}";
|
||||
private const string RrdHostQuery = "session_id={0}";
|
||||
private const string RrdVmQuery = "session_id={0}&uuid={1}";
|
||||
|
||||
private const long TicksInOneSecond = 10000000;
|
||||
private const long TicksInFiveSeconds = 50000000;
|
||||
internal const long TicksInTenSeconds = 100000000;
|
||||
@ -119,8 +106,18 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
/// </summary>
|
||||
private List<DataSet> SetsAdded;
|
||||
|
||||
private List<Data_source> _enabledDataSources = new List<Data_source>();
|
||||
|
||||
private IXenObject _xenObject;
|
||||
|
||||
private long EndTime;
|
||||
private bool BailOut;
|
||||
private long CurrentInterval;
|
||||
private long StepSize;
|
||||
private long CurrentTime;
|
||||
private int ValueCount;
|
||||
private string LastNode = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gui Thread
|
||||
/// </summary>
|
||||
@ -144,17 +141,13 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
public DateTime LastOneDayCollection = DateTime.MinValue;
|
||||
|
||||
public bool FirstTime = true;
|
||||
public bool LoadingInitialData;
|
||||
|
||||
public bool LoadingInitialData = false;
|
||||
private DateTime ServerNow => DateTime.UtcNow.Subtract(ClientServerOffset);
|
||||
|
||||
public TimeSpan ClientServerOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
IXenObject m = XenObject;
|
||||
return m == null ? TimeSpan.Zero : m.Connection.ServerTimeOffset;
|
||||
}
|
||||
}
|
||||
public DateTime GraphNow => DateTime.Now - (ClientServerOffset + TimeSpan.FromSeconds(15));
|
||||
|
||||
public TimeSpan ClientServerOffset => XenObject?.Connection.ServerTimeOffset ?? TimeSpan.Zero;
|
||||
|
||||
public ArchiveMaintainer()
|
||||
{
|
||||
@ -176,9 +169,8 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
while (RunThread)
|
||||
{
|
||||
IXenObject xenObject = XenObject;
|
||||
Host Host = GetHost(xenObject);
|
||||
|
||||
DateTime ServerWas = ServerNow(); // get time before updating so we don't miss any 5 second updates if getting the past data
|
||||
DateTime serverWas = ServerNow; // get time before updating so we don't miss any 5 second updates if getting the past data
|
||||
|
||||
if (FirstTime)
|
||||
{
|
||||
@ -194,44 +186,58 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
Archives[ArchiveInterval.OneDay].MaxPoints = DaysInOneYear;
|
||||
}
|
||||
|
||||
_enabledDataSources.Clear();
|
||||
|
||||
foreach (DataArchive a in Archives.Values)
|
||||
a.ClearSets();
|
||||
|
||||
LoadingInitialData = true;
|
||||
OnArchivesUpdated();
|
||||
Get(ArchiveInterval.None, RrdsUri, RRD_Full_InspectCurrentNode, Host, xenObject);
|
||||
LoadingInitialData = false;
|
||||
OnArchivesUpdated();
|
||||
try
|
||||
{
|
||||
LoadingInitialData = true;
|
||||
ArchivesUpdated?.Invoke();
|
||||
|
||||
LastFiveSecondCollection = ServerWas;
|
||||
LastOneMinuteCollection = ServerWas;
|
||||
LastOneHourCollection = ServerWas;
|
||||
LastOneDayCollection = ServerWas;
|
||||
if (xenObject is Host h)
|
||||
_enabledDataSources = Host.get_data_sources(h.Connection.Session, h.opaque_ref).Where(d => d.enabled).ToList();
|
||||
else if (xenObject is VM vm && vm.power_state == vm_power_state.Running)
|
||||
_enabledDataSources = VM.get_data_sources(vm.Connection.Session, vm.opaque_ref).Where(d => d.enabled).ToList();
|
||||
|
||||
Get(ArchiveInterval.None, RrdsUri, RRD_Full_InspectCurrentNode, xenObject);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LoadingInitialData = false;
|
||||
ArchivesUpdated?.Invoke();
|
||||
}
|
||||
|
||||
LastFiveSecondCollection = serverWas;
|
||||
LastOneMinuteCollection = serverWas;
|
||||
LastOneHourCollection = serverWas;
|
||||
LastOneDayCollection = serverWas;
|
||||
FirstTime = false;
|
||||
}
|
||||
|
||||
if (ServerWas - LastFiveSecondCollection > FiveSeconds)
|
||||
if (serverWas - LastFiveSecondCollection > FiveSeconds)
|
||||
{
|
||||
GetUpdate(ArchiveInterval.FiveSecond, Host, xenObject);
|
||||
LastFiveSecondCollection = ServerWas;
|
||||
Get(ArchiveInterval.FiveSecond, UpdateUri, RRD_Update_InspectCurrentNode, xenObject);
|
||||
LastFiveSecondCollection = serverWas;
|
||||
Archives[ArchiveInterval.FiveSecond].Load(SetsAdded);
|
||||
}
|
||||
if (ServerWas - LastOneMinuteCollection > OneMinute)
|
||||
if (serverWas - LastOneMinuteCollection > OneMinute)
|
||||
{
|
||||
GetUpdate(ArchiveInterval.OneMinute, Host, xenObject);
|
||||
LastOneMinuteCollection = ServerWas;
|
||||
Get(ArchiveInterval.OneMinute, UpdateUri, RRD_Update_InspectCurrentNode, xenObject);
|
||||
LastOneMinuteCollection = serverWas;
|
||||
Archives[ArchiveInterval.OneMinute].Load(SetsAdded);
|
||||
}
|
||||
if (ServerWas - LastOneHourCollection > OneHour)
|
||||
if (serverWas - LastOneHourCollection > OneHour)
|
||||
{
|
||||
GetUpdate(ArchiveInterval.OneHour, Host, xenObject);
|
||||
LastOneHourCollection = ServerWas;
|
||||
Get(ArchiveInterval.OneHour, UpdateUri, RRD_Update_InspectCurrentNode, xenObject);
|
||||
LastOneHourCollection = serverWas;
|
||||
Archives[ArchiveInterval.OneHour].Load(SetsAdded);
|
||||
}
|
||||
if (ServerWas - LastOneDayCollection > OneDay)
|
||||
if (serverWas - LastOneDayCollection > OneDay)
|
||||
{
|
||||
GetUpdate(ArchiveInterval.OneDay, Host, xenObject);
|
||||
LastOneDayCollection = ServerWas;
|
||||
Get(ArchiveInterval.OneDay, UpdateUri, RRD_Update_InspectCurrentNode, xenObject);
|
||||
LastOneDayCollection = serverWas;
|
||||
Archives[ArchiveInterval.OneDay].Load(SetsAdded);
|
||||
}
|
||||
|
||||
@ -247,37 +253,16 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
public DateTime ServerNow()
|
||||
private void Get(ArchiveInterval interval, Func<ArchiveInterval, IXenObject, Uri> uriBuilder,
|
||||
Action<XmlReader, IXenObject>Reader, IXenObject xenObject)
|
||||
{
|
||||
return DateTime.UtcNow.Subtract(ClientServerOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
private void GetUpdate(ArchiveInterval interval, Host host, IXenObject xo)
|
||||
{
|
||||
Get(interval, UpdateUri, RRD_Update_InspectCurrentNode, host, xo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
private void Get(ArchiveInterval interval, URIDelegate URI, ReaderDelegate Reader,
|
||||
Host host, IXenObject xenObject)
|
||||
{
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Session session = xenObject.Connection.Session;
|
||||
if (session == null)
|
||||
var uri = uriBuilder(interval, xenObject);
|
||||
if (uri == null)
|
||||
return;
|
||||
using (Stream httpstream = HTTPHelper.GET(URI(session, host, interval, xenObject), xenObject.Connection, true))
|
||||
|
||||
using (Stream httpstream = HTTPHelper.GET(uri, xenObject.Connection, true))
|
||||
{
|
||||
using (XmlReader reader = XmlReader.Create(httpstream))
|
||||
{
|
||||
@ -298,39 +283,62 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
private Uri UpdateUri(Session session, Host host, ArchiveInterval interval, IXenObject xo)
|
||||
private Uri UpdateUri(ArchiveInterval interval, IXenObject xo)
|
||||
{
|
||||
string query =
|
||||
xo is Host ?
|
||||
string.Format(RrdHostUpdatesQuery, Uri.EscapeDataString(session.opaque_ref), TimeFromInterval(interval), RrdCFAverage, ToSeconds(interval)) :
|
||||
xo is VM ?
|
||||
string.Format(RrdVmUpdatesQuery, Uri.EscapeDataString(session.opaque_ref), TimeFromInterval(interval), RrdCFAverage, ToSeconds(interval), Helpers.GetUuid(xo)) :
|
||||
"";
|
||||
return BuildUri(host, RrdUpdatesPath, query);
|
||||
var sessionRef = xo?.Connection?.Session?.opaque_ref;
|
||||
if (sessionRef == null)
|
||||
return null;
|
||||
|
||||
var escapedRef = Uri.EscapeDataString(sessionRef);
|
||||
var startTime = TimeFromInterval(interval);
|
||||
var duration = ToSeconds(interval);
|
||||
|
||||
if (xo is Host host)
|
||||
{
|
||||
return BuildUri(host, "rrd_updates",
|
||||
$"session_id={escapedRef}&start={startTime}&cf=AVERAGE&interval={duration}&host=true");
|
||||
}
|
||||
|
||||
if (xo is VM vm)
|
||||
{
|
||||
var vmHost = vm.Connection.Resolve(vm.resident_on) ?? Helpers.GetMaster(vm.Connection);
|
||||
BuildUri(vmHost, "rrd_updates",
|
||||
$"session_id={escapedRef}&start={startTime}&cf=AVERAGE&interval={duration}&vm_uuid={vm.uuid}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Uri RrdsUri(Session session, Host host, ArchiveInterval interval, IXenObject xo)
|
||||
private static Uri RrdsUri(ArchiveInterval interval, IXenObject xo)
|
||||
{
|
||||
string query =
|
||||
xo is Host ?
|
||||
string.Format(RrdHostQuery, Uri.EscapeDataString(session.opaque_ref)) :
|
||||
xo is VM ?
|
||||
string.Format(RrdVmQuery, Uri.EscapeDataString(session.opaque_ref), Helpers.GetUuid(xo)) :
|
||||
"";
|
||||
return BuildUri(host, xo is Host ? RrdHostPath : RrdVmPath, query);
|
||||
var sessionRef = xo.Connection.Session?.opaque_ref;
|
||||
if (sessionRef == null)
|
||||
return null;
|
||||
|
||||
var escapedRef = Uri.EscapeDataString(sessionRef);
|
||||
|
||||
if (xo is Host host)
|
||||
return BuildUri(host, "host_rrds", $"session_id={escapedRef}");
|
||||
|
||||
if (xo is VM vm)
|
||||
{
|
||||
var vmHost = vm.Connection.Resolve(vm.resident_on) ?? Helpers.GetMaster(vm.Connection);
|
||||
return BuildUri(vmHost, "vm_rrds", $"session_id={escapedRef}&uuid={vm.uuid}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Uri BuildUri(Host host, string path, string query)
|
||||
{
|
||||
UriBuilder builder = new UriBuilder();
|
||||
builder.Scheme = host.Connection.UriScheme;
|
||||
builder.Host = host.address;
|
||||
builder.Port = host.Connection.Port;
|
||||
builder.Path = path;
|
||||
builder.Query = query;
|
||||
UriBuilder builder = new UriBuilder
|
||||
{
|
||||
Scheme = host.Connection.UriScheme,
|
||||
Host = host.address,
|
||||
Port = host.Connection.Port,
|
||||
Path = path,
|
||||
Query = query
|
||||
};
|
||||
return builder.Uri;
|
||||
}
|
||||
|
||||
@ -395,15 +403,6 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private long EndTime = 0;
|
||||
private bool BailOut = false;
|
||||
private long CurrentInterval = 0;
|
||||
private long StepSize = 0;
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
private void RRD_Full_InspectCurrentNode(XmlReader reader, IXenObject xmo)
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
@ -429,7 +428,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
ArchiveInterval i = GetArchiveIntervalFromFiveSecs(CurrentInterval);
|
||||
if (i != ArchiveInterval.None)
|
||||
Archives[i].CopyLoad(SetsAdded);
|
||||
Archives[i].CopyLoad(SetsAdded, _enabledDataSources);
|
||||
|
||||
foreach (DataSet set in SetsAdded)
|
||||
set.Points.Clear();
|
||||
@ -443,8 +442,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (LastNode == "name")
|
||||
{
|
||||
string str = reader.ReadContentAsString();
|
||||
string id = string.Format("{0}:{1}:{2}", xmo is Host ? "host" : "vm", Helpers.GetUuid(xmo), str);
|
||||
SetsAdded.Add(DataSet.Create(id, xmo, true, str));
|
||||
SetsAdded.Add(new DataSet(xmo, false, str, _enabledDataSources));
|
||||
}
|
||||
else if (LastNode == "step")
|
||||
{
|
||||
@ -472,7 +470,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
else if (LastNode == "cf")
|
||||
{
|
||||
string str = reader.ReadContentAsString();
|
||||
if (str != RrdCFAverage)
|
||||
if (str != "AVERAGE")
|
||||
BailOut = true;
|
||||
}
|
||||
else if (LastNode == "v")
|
||||
@ -482,19 +480,11 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
DataSet set = SetsAdded[ValueCount];
|
||||
string str = reader.ReadContentAsString();
|
||||
set.AddPoint(str, CurrentTime, SetsAdded);
|
||||
set.AddPoint(str, CurrentTime, SetsAdded, _enabledDataSources);
|
||||
ValueCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private long CurrentTime = 0;
|
||||
private int ValueCount;
|
||||
|
||||
private string LastNode = "";
|
||||
|
||||
/// <summary>
|
||||
/// UpdaterThread Thread
|
||||
/// </summary>
|
||||
private void RRD_Update_InspectCurrentNode(XmlReader reader, IXenObject xo)
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
@ -509,7 +499,29 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (LastNode == "entry")
|
||||
{
|
||||
string str = reader.ReadContentAsString();
|
||||
SetsAdded.Add(DataSet.Create(str, xo));
|
||||
DataSet set = null;
|
||||
|
||||
if (DataSet.ParseId(str, out string objType, out string objUuid, out string dataSourceName))
|
||||
{
|
||||
if (objType == "host")
|
||||
{
|
||||
Host host = xo.Connection.Cache.Hosts.FirstOrDefault(h => h.uuid == objUuid);
|
||||
if (host != null)
|
||||
set = new DataSet(host, (xo as Host)?.uuid != objUuid, dataSourceName, _enabledDataSources);
|
||||
}
|
||||
|
||||
if (objType == "vm")
|
||||
{
|
||||
VM vm = xo.Connection.Cache.VMs.FirstOrDefault(v => v.uuid == objUuid);
|
||||
if (vm != null)
|
||||
set = new DataSet(vm, (xo as VM)?.uuid != objUuid, dataSourceName, _enabledDataSources);
|
||||
}
|
||||
}
|
||||
|
||||
if (set == null)
|
||||
set = new DataSet(null, true, str, _enabledDataSources);
|
||||
|
||||
SetsAdded.Add(set);
|
||||
}
|
||||
else if (LastNode == "t")
|
||||
{
|
||||
@ -521,7 +533,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (SetsAdded.Count <= ValueCount) return;
|
||||
DataSet set = SetsAdded[ValueCount];
|
||||
string str = reader.ReadContentAsString();
|
||||
set.AddPoint(str, CurrentTime, SetsAdded);
|
||||
set.AddPoint(str, CurrentTime, SetsAdded, _enabledDataSources);
|
||||
ValueCount++;
|
||||
}
|
||||
}
|
||||
@ -586,38 +598,5 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return ArchiveInterval.None;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime GraphNow
|
||||
{
|
||||
get
|
||||
{
|
||||
return DateTime.Now - (ClientServerOffset + TimeSpan.FromSeconds(15));
|
||||
}
|
||||
}
|
||||
|
||||
private static Host GetHost(IXenObject xmo)
|
||||
{
|
||||
if (xmo is Host)
|
||||
{
|
||||
return (Host)xmo;
|
||||
}
|
||||
else if (xmo is VM)
|
||||
{
|
||||
VM vm = (VM)xmo;
|
||||
return xmo.Connection.Resolve(vm.resident_on) ?? Helpers.GetMaster(xmo.Connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Trace.Assert(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnArchivesUpdated()
|
||||
{
|
||||
if (ArchivesUpdated != null)
|
||||
ArchivesUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using XenAPI;
|
||||
|
||||
namespace XenAdmin.Controls.CustomDataGraph
|
||||
{
|
||||
@ -68,7 +69,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
set.Points.Sort();
|
||||
|
||||
var other = Sets.FirstOrDefault(s => s.Uuid == set.Uuid);
|
||||
var other = Sets.FirstOrDefault(s => s.Id == set.Id);
|
||||
|
||||
if (other == null)
|
||||
{
|
||||
@ -101,16 +102,15 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
/// <summary>
|
||||
/// Asserts off the event thread, for use when copying off the updater thread. Invokes onto event thread to update the sets safely.
|
||||
/// </summary>
|
||||
/// <param name="SetsAdded"></param>
|
||||
internal void CopyLoad(List<DataSet> SetsAdded)
|
||||
internal void CopyLoad(List<DataSet> setsAdded, List<Data_source> datasources)
|
||||
{
|
||||
Program.AssertOffEventThread();
|
||||
if (SetsAdded == null)
|
||||
if (setsAdded == null)
|
||||
return;
|
||||
foreach (DataSet set in SetsAdded)
|
||||
foreach (DataSet set in setsAdded)
|
||||
{
|
||||
Palette.LoadSetColor(set);
|
||||
DataSet copy = DataSet.Create(set.Uuid, set.XenObject, set.Show, set.TypeString);
|
||||
DataSet copy = new DataSet(set.XenObject, set.Hide, set.DataSourceName, datasources);
|
||||
foreach (DataPoint p in set.Points)
|
||||
copy.AddPoint(new DataPoint(p.X,p.Y));
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
lock (Palette.PaletteLock)
|
||||
{
|
||||
using (var thickPen = Palette.CreatePen(item.Sets[ArchiveInterval.FiveSecond].Uuid, Palette.PEN_THICKNESS_THICK))
|
||||
using (var thickPen = Palette.CreatePen(item.Sets[ArchiveInterval.FiveSecond].Id, Palette.PEN_THICKNESS_THICK))
|
||||
{
|
||||
e.Graphics.DrawLine(thickPen,
|
||||
new Point(e.Bounds.Left + 2, e.Bounds.Top + e.Bounds.Height / 2),
|
||||
@ -116,7 +116,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
{
|
||||
var wrapper = new DataSetCollectionWrapper();
|
||||
|
||||
if (!DataSourceUUIDsToShow.Contains(fivesecond.Uuid))
|
||||
if (!DataSourceUUIDsToShow.Contains(fivesecond.Id))
|
||||
continue;
|
||||
|
||||
wrapper.Sets.Add(ArchiveInterval.FiveSecond, fivesecond);
|
||||
@ -124,7 +124,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
foreach (var interval in intervals)
|
||||
{
|
||||
var found = archives[interval].Sets.FirstOrDefault(s => s.Uuid == fivesecond.Uuid);
|
||||
var found = archives[interval].Sets.FirstOrDefault(s => s.Id == fivesecond.Id);
|
||||
if (found != null)
|
||||
wrapper.Sets.Add(interval, found);
|
||||
}
|
||||
@ -263,15 +263,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public void SelectDataSet(DataSet set)
|
||||
{
|
||||
SelectedItem = SelectWrapperFromUuid(set.Uuid);
|
||||
}
|
||||
|
||||
public DataSetCollectionWrapper SelectWrapperFromUuid(string uuid)
|
||||
{
|
||||
return CurrentKeys.Find(new Predicate<DataSetCollectionWrapper>(delegate(DataSetCollectionWrapper item)
|
||||
{
|
||||
return item.Uuid == uuid;
|
||||
}));
|
||||
SelectedItem = CurrentKeys.Find(item => item.Id == set.Id);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
@ -290,7 +282,6 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
public Dictionary<ArchiveInterval, DataSet> Sets = new Dictionary<ArchiveInterval, DataSet>();
|
||||
|
||||
private bool _selected;
|
||||
private bool _hide;
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
@ -305,19 +296,6 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
}
|
||||
}
|
||||
|
||||
public bool Hide
|
||||
{
|
||||
get { return _hide; }
|
||||
set
|
||||
{
|
||||
_hide = value;
|
||||
foreach (DataSet set in Sets.Values)
|
||||
{
|
||||
set.Deselected = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DataRange YRange
|
||||
{
|
||||
get
|
||||
@ -337,7 +315,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (!Sets.ContainsKey(ArchiveInterval.FiveSecond))
|
||||
return false;
|
||||
|
||||
return Sets[ArchiveInterval.FiveSecond].Show;
|
||||
return !Sets[ArchiveInterval.FiveSecond].Hide;
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,14 +324,14 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
}
|
||||
|
||||
public string Uuid
|
||||
public string Id
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Sets.ContainsKey(ArchiveInterval.FiveSecond))
|
||||
return base.ToString();
|
||||
|
||||
return Sets[ArchiveInterval.FiveSecond].Uuid;
|
||||
return Sets[ArchiveInterval.FiveSecond].Id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +345,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public bool Equals(DataSetCollectionWrapper other)
|
||||
{
|
||||
return Uuid.Equals(other.Uuid);
|
||||
return Id.Equals(other?.Id);
|
||||
}
|
||||
|
||||
public int CompareTo(DataSetCollectionWrapper other)
|
||||
|
@ -263,7 +263,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
bool require_tools = true;
|
||||
foreach (DataSetCollectionWrapper set in DataKey.CurrentKeys)
|
||||
{
|
||||
if (set.Sets[ArchiveInterval.FiveSecond].TypeString != "memory")
|
||||
if (set.Sets[ArchiveInterval.FiveSecond].DataSourceName != "memory")
|
||||
{
|
||||
require_tools = false;
|
||||
break;
|
||||
@ -280,7 +280,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
// Refresh all sets
|
||||
foreach (DataSet set in DataPlotNav.CurrentArchive.Sets.ToArray())
|
||||
{
|
||||
if (!set.Draw || !DataKey.DataSourceUUIDsToShow.Contains(set.Uuid))
|
||||
if (set.Hide || !DataKey.DataSourceUUIDsToShow.Contains(set.Id))
|
||||
continue;
|
||||
|
||||
List<DataPoint> todraw;
|
||||
@ -363,16 +363,16 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
Array.Reverse(sets_to_show);
|
||||
foreach (DataSet set in sets_to_show)
|
||||
{
|
||||
if (!set.Draw || DataKey == null || !DataKey.DataSourceUUIDsToShow.Contains(set.Uuid))
|
||||
if (set.Hide || DataKey == null || !DataKey.DataSourceUUIDsToShow.Contains(set.Id))
|
||||
continue;
|
||||
|
||||
lock (Palette.PaletteLock)
|
||||
{
|
||||
using (var thickPen = Palette.CreatePen(set.Uuid, Palette.PEN_THICKNESS_THICK))
|
||||
using (var thickPen = Palette.CreatePen(set.Id, Palette.PEN_THICKNESS_THICK))
|
||||
{
|
||||
using (var normalPen = Palette.CreatePen(set.Uuid, Palette.PEN_THICKNESS_NORMAL))
|
||||
using (var normalPen = Palette.CreatePen(set.Id, Palette.PEN_THICKNESS_NORMAL))
|
||||
{
|
||||
using (var shadowBrush = Palette.CreateBrush(set.Uuid))
|
||||
using (var shadowBrush = Palette.CreateBrush(set.Id))
|
||||
{
|
||||
LineRenderer.Render(paintEventArgs.Graphics, SlightlySmaller, DataPlotNav.XRange, set.CustomYRange ?? SelectedYRange, set.Selected ? thickPen : normalPen, shadowBrush, set.CurrentlyDisplayed, true);
|
||||
}
|
||||
@ -387,8 +387,10 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
SizeF labelsize = new SizeF(0,0);
|
||||
if (SelectedPoint != null && DataKey.SelectedDataSet != null)
|
||||
{
|
||||
string label = string.Format(string.Format("{0} - {1} = {2}", DataPlotNav.XRange.GetString(SelectedPoint.X + ArchiveMaintainer.ClientServerOffset.Ticks), DataKey.SelectedDataSet.Name,
|
||||
SelectedPoint.Y >= 0 ? SelectedYRange.GetString(SelectedPoint.Y) : Messages.GRAPHS_NO_DATA));
|
||||
string label = string.Format("{0} - {1} = {2}",
|
||||
DataPlotNav.XRange.GetString(SelectedPoint.X + ArchiveMaintainer.ClientServerOffset.Ticks),
|
||||
DataKey.SelectedDataSet.FriendlyName,
|
||||
SelectedPoint.Y >= 0 ? SelectedYRange.GetString(SelectedPoint.Y) : Messages.GRAPHS_NO_DATA);
|
||||
labelsize = paintEventArgs.Graphics.MeasureString(label,Palette.LabelFont);
|
||||
paintEventArgs.Graphics.DrawString(label, Palette.LabelFont, Palette.LabelBrush, SlightlySmaller.Right - labelsize.Width, SlightlySmaller.Top - (labelsize.Height + 1));
|
||||
}
|
||||
@ -533,7 +535,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
{
|
||||
foreach (DataSet set in DataPlotNav.CurrentArchive.Sets.ToArray())
|
||||
{
|
||||
if (!set.Draw || DataKey == null || !DataKey.DataSourceUUIDsToShow.Contains(set.Uuid))
|
||||
if (set.Hide || DataKey == null || !DataKey.DataSourceUUIDsToShow.Contains(set.Id))
|
||||
continue;
|
||||
if (set.OnMouseClick(new MouseActionArgs(e.Location, GraphRectangle(), DataPlotNav.XRange, SelectedYRange)))
|
||||
{
|
||||
|
@ -479,7 +479,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
foreach (DataSet set in ScrollWideArchive.Sets.ToArray())
|
||||
{
|
||||
if (!set.Draw || !DisplayedUuids.Contains(set.Uuid))
|
||||
if (set.Hide || !DisplayedUuids.Contains(set.Id))
|
||||
continue;
|
||||
|
||||
List<DataPoint> todraw;
|
||||
@ -520,12 +520,12 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
foreach (DataSet set in ScrollWideArchive.Sets.ToArray())
|
||||
{
|
||||
if (!set.Draw || !DisplayedUuids.Contains(set.Uuid))
|
||||
if (set.Hide || !DisplayedUuids.Contains(set.Id))
|
||||
continue;
|
||||
|
||||
lock (Palette.PaletteLock)
|
||||
{
|
||||
using (var normalPen = Palette.CreatePen(set.Uuid, Palette.PEN_THICKNESS_NORMAL))
|
||||
using (var normalPen = Palette.CreatePen(set.Id, Palette.PEN_THICKNESS_NORMAL))
|
||||
{
|
||||
LineRenderer.Render(paintEventArgs.Graphics, ScrollViewRectangle, everything, set.CustomYRange, normalPen, null, set.CurrentlyDisplayed, false);
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return Util.NanoSecondsString(constrVal);
|
||||
case Unit.CountsPerSecond:
|
||||
return Util.CountsPerSecondString(constrVal);
|
||||
case Unit.SecondsPerSecond:
|
||||
return Util.SecondsPerSecondString(constrVal);
|
||||
case Unit.MilliWatt:
|
||||
return Util.MilliWattString(constrVal);
|
||||
case Unit.Centigrade:
|
||||
@ -135,6 +137,8 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return unit;
|
||||
case Unit.CountsPerSecond:
|
||||
return Messages.COUNTS_PER_SEC_UNIT;
|
||||
case Unit.SecondsPerSecond:
|
||||
return UnitStrings.SEC_PER_SEC_UNIT;
|
||||
case Unit.Centigrade:
|
||||
return "\u2103";
|
||||
case Unit.MilliWatt:
|
||||
@ -170,6 +174,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
case Unit.MegaHertz:
|
||||
return Util.MegaHertzValue(constrVal, out unit);
|
||||
case Unit.CountsPerSecond://fall through
|
||||
case Unit.SecondsPerSecond://fall through
|
||||
default:
|
||||
return constrVal.ToString();
|
||||
}
|
||||
@ -201,6 +206,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
case Unit.Percentage:
|
||||
case Unit.NanoSeconds:
|
||||
case Unit.CountsPerSecond:
|
||||
case Unit.SecondsPerSecond:
|
||||
case Unit.MilliWatt:
|
||||
case Unit.Centigrade:
|
||||
case Unit.MegaHertz:
|
||||
@ -257,5 +263,17 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public enum RangeScaleMode { Fixed, Auto, Delegate }
|
||||
|
||||
public enum Unit { None, Percentage, BytesPerSecond, Bytes, NanoSeconds, CountsPerSecond, MilliWatt, Centigrade, MegaHertz }
|
||||
public enum Unit
|
||||
{
|
||||
None,
|
||||
Percentage,
|
||||
BytesPerSecond,
|
||||
Bytes,
|
||||
NanoSeconds,
|
||||
CountsPerSecond,
|
||||
SecondsPerSecond,
|
||||
MilliWatt,
|
||||
Centigrade,
|
||||
MegaHertz
|
||||
}
|
||||
}
|
||||
|
@ -43,329 +43,143 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
{
|
||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private const int NegativeValue = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Things can only be added to the beginning or end of this list; it should
|
||||
/// be sorted by X co-ordinate (which will be larger at the beginning of the list)
|
||||
/// </summary>
|
||||
public List<DataPoint> Points = new List<DataPoint>();
|
||||
public string Name;
|
||||
|
||||
public bool Selected;
|
||||
public List<DataPoint> CurrentlyDisplayed = new List<DataPoint>();
|
||||
public IXenObject XenObject;
|
||||
public string Uuid;
|
||||
private bool _hide;
|
||||
private bool _deselected;
|
||||
|
||||
/// <summary>
|
||||
/// A guess at the data type
|
||||
/// </summary>
|
||||
public DataType Type;
|
||||
/// <summary>
|
||||
/// What it really is
|
||||
/// </summary>
|
||||
public string TypeString;
|
||||
|
||||
private const int NegativeValue = -1;
|
||||
public readonly string Id = "";
|
||||
public string DataSourceName;
|
||||
public string FriendlyName { get; }
|
||||
private int MultiplyingFactor = 1;
|
||||
public DataRange CustomYRange = new DataRange(1, 0, 1, Unit.None, RangeScaleMode.Auto);
|
||||
public bool Hide { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Can show in the lisbox
|
||||
/// </summary>
|
||||
public bool Show
|
||||
{
|
||||
get { return !_hide && !NeverShow; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This dataset is of the wrong xenobject
|
||||
/// </summary>
|
||||
public bool Hide
|
||||
{
|
||||
get { return _hide; }
|
||||
set { _hide = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user has chosen not to show this graph
|
||||
/// </summary>
|
||||
public bool Deselected
|
||||
{
|
||||
get { return _deselected; }
|
||||
set { _deselected = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Never ever draw on graph or put in listbox
|
||||
/// </summary>
|
||||
private bool NeverShow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Can draw on graph
|
||||
/// </summary>
|
||||
public bool Draw
|
||||
{
|
||||
get { return !_hide && !NeverShow && !_deselected; }
|
||||
}
|
||||
|
||||
public DataRange CustomYRange;
|
||||
|
||||
private DataSet(string uuid, IXenObject xo, bool show, string settype)
|
||||
public DataSet(IXenObject xo, bool hide, string datasourceName, List<Data_source> datasources)
|
||||
{
|
||||
XenObject = xo;
|
||||
_hide = !show;
|
||||
Uuid = uuid;
|
||||
TypeString = settype;
|
||||
Name = Helpers.GetFriendlyDataSourceName(settype, XenObject);
|
||||
}
|
||||
Hide = datasourceName == "xapi_open_fds" ||
|
||||
datasourceName == "pool_task_count" ||
|
||||
datasourceName == "pool_session_count" ||
|
||||
datasourceName == "memory" ||
|
||||
datasourceName == "memory_total_kib" || hide;
|
||||
|
||||
#region Static methods
|
||||
DataSourceName = datasourceName;
|
||||
|
||||
public static DataSet Create(string uuid, IXenObject xo, bool show, string settype)
|
||||
{
|
||||
var dataSet = new DataSet(uuid, xo, show, settype);
|
||||
if(settype == "xapi_open_fds" || settype == "pool_task_count" || settype == "pool_session_count")
|
||||
{
|
||||
dataSet.NeverShow = true;
|
||||
}
|
||||
if (settype.StartsWith("latency") || settype.EndsWith("latency"))
|
||||
{
|
||||
if (settype.StartsWith("latency_") || settype.StartsWith("read_latency_") ||
|
||||
settype.StartsWith("write_latency_") || settype.StartsWith("vbd"))
|
||||
{
|
||||
//if it's storage or vbd latency xapi units are in microseconds
|
||||
dataSet.MultiplyingFactor = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
//otherwise they are in seconds
|
||||
dataSet.MultiplyingFactor = 1000000000;
|
||||
}
|
||||
if (xo is Host host)
|
||||
Id = $"host:{host.uuid}:{datasourceName}";
|
||||
else if (xo is VM vm)
|
||||
Id = $"vm:{vm.uuid}:{datasourceName}";
|
||||
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.NanoSeconds, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Latency;
|
||||
}
|
||||
else if (settype.StartsWith("vif") || settype.StartsWith("pif"))
|
||||
{
|
||||
//xapi units are in bytes/sec or errors/sec
|
||||
Unit unit = settype.EndsWith("errors") ? Unit.CountsPerSecond : Unit.BytesPerSecond;
|
||||
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, unit, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Network;
|
||||
}
|
||||
else if (settype.StartsWith("vbd"))
|
||||
{
|
||||
if (settype.Contains("iops"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.CountsPerSecond, RangeScaleMode.Auto);
|
||||
else if (settype.Contains("io_throughput"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
dataSet.MultiplyingFactor = (int)Util.BINARY_MEGA; //xapi units are in mebibytes/sec
|
||||
}
|
||||
else if (settype.EndsWith("iowait"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Auto);
|
||||
dataSet.MultiplyingFactor = 100;
|
||||
}
|
||||
else if (settype.EndsWith("inflight") || settype.EndsWith("avgqu_sz"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.None, RangeScaleMode.Auto);
|
||||
else
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
|
||||
dataSet.Type = DataType.Disk;
|
||||
}
|
||||
else if ((settype.Contains("memory") || settype.Contains("allocation")) && !settype.Contains("utilisation"))
|
||||
{
|
||||
dataSet.Type = settype.Contains("gpu") ? DataType.Gpu : DataType.Memory;
|
||||
|
||||
dataSet.MultiplyingFactor = settype.Contains("kib") || settype == "memory_internal_free"
|
||||
? (int)Util.BINARY_KILO
|
||||
: 1;
|
||||
|
||||
if (settype == "memory" || settype == "memory_total_kib")
|
||||
{
|
||||
dataSet.NeverShow = true;
|
||||
}
|
||||
else if (settype == "memory_free_kib" && xo is Host)
|
||||
{
|
||||
dataSet.Name = Helpers.GetFriendlyDataSourceName("memory_used_kib", dataSet.XenObject);
|
||||
Host host = (Host)xo;
|
||||
Host_metrics metrics = host.Connection.Resolve(host.metrics);
|
||||
long max = metrics != null ? metrics.memory_total : 100;
|
||||
dataSet.CustomYRange = new DataRange(max, 0, max / 10d, Unit.Bytes, RangeScaleMode.Delegate)
|
||||
{
|
||||
UpdateMax = dataSet.GetMemoryMax,
|
||||
UpdateResolution = dataSet.GetMemoryResolution
|
||||
};
|
||||
}
|
||||
else if (settype == "memory_internal_free" && xo is VM)
|
||||
{
|
||||
dataSet.Name = Helpers.GetFriendlyDataSourceName("memory_internal_used", dataSet.XenObject);
|
||||
VM vm = (VM)xo;
|
||||
VM_metrics metrics = vm.Connection.Resolve(vm.metrics);
|
||||
long max = metrics != null ? metrics.memory_actual : (long)vm.memory_dynamic_max;
|
||||
dataSet.CustomYRange = new DataRange(max, 0, max / 10d, Unit.Bytes, RangeScaleMode.Delegate)
|
||||
{
|
||||
UpdateMax = dataSet.GetMemoryMax,
|
||||
UpdateResolution = dataSet.GetMemoryResolution
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.Bytes, RangeScaleMode.Auto);
|
||||
}
|
||||
}
|
||||
else if (settype.StartsWith("loadavg"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Auto);
|
||||
dataSet.MultiplyingFactor = 100;
|
||||
dataSet.Type = DataType.LoadAverage;
|
||||
}
|
||||
else if (settype.EndsWith("-avg-freq"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.MegaHertz, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Cpu;
|
||||
}
|
||||
else if (settype.StartsWith("cpu") || settype == "avg_cpu" || settype.StartsWith("runstate"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Fixed);
|
||||
dataSet.MultiplyingFactor = 100;
|
||||
dataSet.Type = DataType.Cpu;
|
||||
}
|
||||
else if (settype.StartsWith("io_throughput"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
dataSet.MultiplyingFactor = (int)Util.BINARY_MEGA; //xapi units are in mebibytes/sec
|
||||
dataSet.Type = DataType.Storage;
|
||||
}
|
||||
else if (settype.StartsWith("sr"))
|
||||
{
|
||||
dataSet.Type = DataType.Storage;
|
||||
|
||||
if (settype.EndsWith("cache_size"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.Bytes, RangeScaleMode.Auto);
|
||||
else if (settype.EndsWith("cache_hits") || settype.EndsWith("cache_misses"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.CountsPerSecond, RangeScaleMode.Auto);
|
||||
}
|
||||
else if (settype.StartsWith("iops"))
|
||||
{
|
||||
//xapi units are in requests/sec
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.CountsPerSecond, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Storage;
|
||||
}
|
||||
else if (settype.StartsWith("iowait"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Auto);
|
||||
dataSet.MultiplyingFactor = 100;
|
||||
dataSet.Type = DataType.Storage;
|
||||
}
|
||||
else if (settype.StartsWith("inflight") || settype.StartsWith("avgqu_sz"))
|
||||
{
|
||||
//xapi units are in requests
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.None, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Storage;
|
||||
}
|
||||
else if (settype.StartsWith("gpu"))
|
||||
{
|
||||
if (settype.Contains("power_usage"))
|
||||
{
|
||||
//xapi units are in mW
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.MilliWatt, RangeScaleMode.Auto);
|
||||
}
|
||||
else if (settype.Contains("temperature"))
|
||||
{
|
||||
//xapi units are in Centigrade
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.Centigrade, RangeScaleMode.Auto);
|
||||
}
|
||||
else if (settype.Contains("utilisation"))
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Fixed);
|
||||
dataSet.MultiplyingFactor = 100;
|
||||
}
|
||||
dataSet.Type = DataType.Gpu;
|
||||
}
|
||||
else if (settype.StartsWith("pvsaccelerator"))
|
||||
{
|
||||
if (settype.Contains("traffic") || settype.EndsWith("evicted"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
else if (settype.EndsWith("read_total") || settype.EndsWith("read_hits") || settype.EndsWith("read_misses"))
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.CountsPerSecond, RangeScaleMode.Auto);
|
||||
else if (settype.Contains("utilization"))
|
||||
dataSet.CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Fixed); // values range from 0 to 100
|
||||
else
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.None, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Pvs;
|
||||
}
|
||||
else if (settype.StartsWith("read_latency") || settype.StartsWith("write_latency"))
|
||||
{
|
||||
// Units are microseconds
|
||||
dataSet.MultiplyingFactor = 1000;
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.NanoSeconds, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Latency;
|
||||
}
|
||||
else if (settype.StartsWith("read") || settype.StartsWith("write"))
|
||||
{
|
||||
// Units are Bytes/second
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Storage;
|
||||
}
|
||||
if (datasourceName == "memory_free_kib")
|
||||
FriendlyName = Helpers.GetFriendlyDataSourceName("memory_used_kib", xo);
|
||||
else if (datasourceName == "memory_internal_free")
|
||||
FriendlyName = Helpers.GetFriendlyDataSourceName("memory_internal_used", xo);
|
||||
else
|
||||
FriendlyName = Helpers.GetFriendlyDataSourceName(datasourceName, xo);
|
||||
|
||||
var units = datasources.FirstOrDefault(d => datasourceName.StartsWith(d.name_label))?.units;
|
||||
|
||||
switch (units)
|
||||
{
|
||||
dataSet.CustomYRange = new DataRange(1, 0, 1, Unit.None, RangeScaleMode.Auto);
|
||||
dataSet.Type = DataType.Custom;
|
||||
case "count":
|
||||
case "requests":
|
||||
case "sessions":
|
||||
case "tasks":
|
||||
case "file descriptors":
|
||||
break;
|
||||
case "(fraction)":
|
||||
//CP-34000: use Auto instead of Fixed scale
|
||||
CustomYRange = new DataRange(100, 0, 10, Unit.Percentage, RangeScaleMode.Auto);
|
||||
MultiplyingFactor = 100;
|
||||
break;
|
||||
case "MHz":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.MegaHertz, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "requests/s":
|
||||
case "err/s":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.CountsPerSecond, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "s/s":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.SecondsPerSecond, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "s":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.NanoSeconds, RangeScaleMode.Auto);
|
||||
MultiplyingFactor = (int)Util.DEC_GIGA;
|
||||
break;
|
||||
case "ms":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.NanoSeconds, RangeScaleMode.Auto);
|
||||
MultiplyingFactor = (int)Util.DEC_MEGA;
|
||||
break;
|
||||
case "μs":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.NanoSeconds, RangeScaleMode.Auto);
|
||||
MultiplyingFactor = (int)Util.DEC_KILO;
|
||||
break;
|
||||
case "B":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.Bytes, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "KiB":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.Bytes, RangeScaleMode.Auto);
|
||||
MultiplyingFactor = (int)Util.BINARY_KILO;
|
||||
break;
|
||||
case "B/s":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "MiB/s":
|
||||
MultiplyingFactor = (int)Util.BINARY_MEGA;
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.BytesPerSecond, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "mW":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.MilliWatt, RangeScaleMode.Auto);
|
||||
break;
|
||||
case "Centigrade":
|
||||
CustomYRange = new DataRange(1, 0, 1, Unit.Centigrade, RangeScaleMode.Auto);
|
||||
break;
|
||||
default:
|
||||
if (!string.IsNullOrEmpty(units))
|
||||
System.Diagnostics.Debug.Assert(false, $"Unhandled units {units}!");
|
||||
break;
|
||||
}
|
||||
|
||||
return dataSet;
|
||||
if (datasourceName == "memory_free_kib" || datasourceName == "memory_internal_free")
|
||||
{
|
||||
var max = GetMemoryMax(xo);
|
||||
var resolution = GetMemoryResolution(max);
|
||||
|
||||
CustomYRange = new DataRange(max, 0, resolution, Unit.Bytes, RangeScaleMode.Delegate)
|
||||
{
|
||||
UpdateMax = GetMemoryMax,
|
||||
UpdateResolution = GetMemoryResolution
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static DataSet Create(string id, IXenObject xenObject)
|
||||
public static bool ParseId(string id, out string objType, out string objUuid, out string dataSourceName)
|
||||
{
|
||||
string[] bits = id.Split(':');
|
||||
if (bits.Length < 3)
|
||||
return Create(id, null, false, id);
|
||||
var bits = id.Split(':').ToList();
|
||||
|
||||
string theId;
|
||||
string theObjType;
|
||||
string theUuid;
|
||||
string theDataName;
|
||||
if (bits.Count > 3)
|
||||
bits.RemoveAt(0);
|
||||
|
||||
if (bits.Length == 4)
|
||||
if (bits.Count >= 3)
|
||||
{
|
||||
string[] important_bits = new string[3];
|
||||
Array.Copy(bits, 1, important_bits, 0, 3);
|
||||
|
||||
theId = string.Join(":", important_bits);
|
||||
theObjType = bits[1];
|
||||
theUuid = bits[2];
|
||||
theDataName = bits[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
theId = id;
|
||||
theObjType = bits[0];
|
||||
theUuid = bits[1];
|
||||
theDataName = bits[2];
|
||||
objType = bits[0];
|
||||
objUuid = bits[1];
|
||||
dataSourceName = bits[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theObjType == "host")
|
||||
{
|
||||
Host host = xenObject.Connection.Cache.Find_By_Uuid<Host>(theUuid);
|
||||
if (host != null)
|
||||
return Create(theId, host, (xenObject is Host && ((Host)xenObject).uuid == theUuid), theDataName);
|
||||
}
|
||||
|
||||
if (theObjType == "vm")
|
||||
{
|
||||
VM vm = xenObject.Connection.Cache.Find_By_Uuid<VM>(theUuid);
|
||||
if (vm != null)
|
||||
return Create(theId, vm, (xenObject is VM && ((VM)xenObject).uuid == theUuid), theDataName);
|
||||
}
|
||||
|
||||
return Create(id, null, false, id);
|
||||
objType = null;
|
||||
objUuid = null;
|
||||
dataSourceName = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public List<DataPoint> GetRange(DataTimeRange xrange, long intervalneed, long intervalat)
|
||||
{
|
||||
List<DataPoint> fine = BinaryChop(Points, xrange);
|
||||
@ -396,38 +210,25 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return listout;
|
||||
}
|
||||
|
||||
private double GetMemoryMax(IXenObject xo)
|
||||
private static double GetMemoryMax(IXenObject xo)
|
||||
{
|
||||
if (xo is Host)
|
||||
{
|
||||
Host host = (Host)xo;
|
||||
Host_metrics metrics = host.Connection.Resolve(host.metrics);
|
||||
return metrics != null ? metrics.memory_total : 100;
|
||||
}
|
||||
else if (xo is VM)
|
||||
{
|
||||
VM vm = (VM)xo;
|
||||
VM_metrics metrics = vm.Connection.Resolve(vm.metrics);
|
||||
return metrics != null ? metrics.memory_actual : vm.memory_dynamic_max;
|
||||
}
|
||||
if (xo is Host host)
|
||||
return host.Connection.Resolve(host.metrics)?.memory_total ?? 100;
|
||||
|
||||
if (xo is VM vm)
|
||||
return (vm.Connection.Resolve(vm.metrics))?.memory_actual ?? vm.memory_dynamic_max;
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
private double GetMemoryResolution(IXenObject xmo)
|
||||
private static double GetMemoryResolution(IXenObject xmo)
|
||||
{
|
||||
if (xmo is Host)
|
||||
{
|
||||
Host host = (Host)xmo;
|
||||
Host_metrics metrics = host.Connection.Resolve(host.metrics);
|
||||
return metrics != null ? metrics.memory_total / 10 : 10;
|
||||
}
|
||||
else if (xmo is VM)
|
||||
{
|
||||
VM vm = (VM)xmo;
|
||||
VM_metrics metrics = vm.Connection.Resolve(vm.metrics);
|
||||
return ((metrics != null ? metrics.memory_actual : (long)vm.memory_dynamic_max) / 10d);
|
||||
}
|
||||
return 10;
|
||||
return GetMemoryMax(xmo) / 10d;
|
||||
}
|
||||
|
||||
private static double GetMemoryResolution(double max)
|
||||
{
|
||||
return max / 10d;
|
||||
}
|
||||
|
||||
public static double GetMaxY(List<DataPoint> dataPoints)
|
||||
@ -494,13 +295,11 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
return FriendlyName;
|
||||
}
|
||||
|
||||
public DataPoint OnMouseMove(MouseActionArgs args)
|
||||
{
|
||||
if (Deselected)
|
||||
return null;
|
||||
LongPoint p = LongPoint.DeTranslateFromScreen(new LongPoint(args.Point), args.XRange, args.YRange, new LongRectangle(args.Rectangle));
|
||||
return ClosestPointTo(p);
|
||||
}
|
||||
@ -540,7 +339,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return poly.Contains(new LongPoint(args.Point));
|
||||
}
|
||||
|
||||
public void AddPoint(string str, long currentTime, List<DataSet> setsAdded)
|
||||
public void AddPoint(string str, long currentTime, List<DataSet> setsAdded, List<Data_source> dataSources)
|
||||
{
|
||||
double value = Helpers.StringToDouble(str);
|
||||
bool isNanOrInfinity = double.IsNaN(value) || double.IsInfinity(value);
|
||||
@ -551,12 +350,12 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
var matchDelegate = new Func<string, bool>(s => Helpers.CpuRegex.IsMatch(s) &&
|
||||
!Helpers.CpuStateRegex.IsMatch(s));
|
||||
|
||||
if (matchDelegate(TypeString))
|
||||
if (matchDelegate(DataSourceName))
|
||||
{
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.TypeString == "avg_cpu");
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.DataSourceName == "avg_cpu");
|
||||
if (other == null)
|
||||
{
|
||||
other = Create(Palette.GetUuid("avg_cpu", XenObject), XenObject, true, "avg_cpu");
|
||||
other = new DataSet(XenObject, false, "avg_cpu", dataSources);
|
||||
setsAdded.Add(other);
|
||||
}
|
||||
|
||||
@ -575,7 +374,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
foreach (DataSet s in setsAdded)
|
||||
{
|
||||
if (matchDelegate(s.TypeString) && s.GetPointAt(currentTime) != null && s != this)
|
||||
if (matchDelegate(s.DataSourceName) && s.GetPointAt(currentTime) != null && s != this)
|
||||
cpu_vals_added++;
|
||||
}
|
||||
|
||||
@ -587,9 +386,9 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
#region memory
|
||||
|
||||
if (TypeString == "memory_total_kib")
|
||||
if (DataSourceName == "memory_total_kib")
|
||||
{
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.TypeString == "memory_free_kib");
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.DataSourceName == "memory_free_kib");
|
||||
if (other != null && other.Points.Count - 1 == Points.Count)
|
||||
{
|
||||
yValue = isNanOrInfinity || other.Points[other.Points.Count - 1].Y < 0
|
||||
@ -598,9 +397,9 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
other.Points[other.Points.Count - 1].Y = yValue;
|
||||
}
|
||||
}
|
||||
else if (TypeString == "memory_free_kib")
|
||||
else if (DataSourceName == "memory_free_kib")
|
||||
{
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.TypeString == "memory_total_kib");
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.DataSourceName == "memory_total_kib");
|
||||
if (other != null && other.Points.Count - 1 == Points.Count)
|
||||
{
|
||||
yValue = isNanOrInfinity || other.Points[other.Points.Count - 1].Y < 0
|
||||
@ -608,9 +407,9 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
: other.Points[other.Points.Count - 1].Y - (value * MultiplyingFactor);
|
||||
}
|
||||
}
|
||||
else if (TypeString == "memory")
|
||||
else if (DataSourceName == "memory")
|
||||
{
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.TypeString == "memory_internal_free");
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.DataSourceName == "memory_internal_free");
|
||||
if (other != null && other.Points.Count - 1 == Points.Count)
|
||||
{
|
||||
yValue = isNanOrInfinity || other.Points[other.Points.Count - 1].Y < 0
|
||||
@ -619,9 +418,9 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
other.Points[other.Points.Count - 1].Y = yValue;
|
||||
}
|
||||
}
|
||||
else if (TypeString == "memory_internal_free")
|
||||
else if (DataSourceName == "memory_internal_free")
|
||||
{
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.TypeString == "memory");
|
||||
DataSet other = setsAdded.FirstOrDefault(s => s.DataSourceName == "memory");
|
||||
if (other != null && other.Points.Count - 1 == Points.Count)
|
||||
{
|
||||
yValue = isNanOrInfinity || other.Points[other.Points.Count - 1].Y < 0
|
||||
@ -684,14 +483,14 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
DataSet other = (DataSet)obj;
|
||||
|
||||
return Uuid == other.Uuid;
|
||||
return Id == other.Id;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Uuid))
|
||||
if (string.IsNullOrEmpty(Id))
|
||||
return base.GetHashCode();
|
||||
return Uuid.GetHashCode();
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
|
||||
internal void InsertPointCollection(List<DataPoint> list)
|
||||
@ -791,12 +590,12 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public int CompareTo(DataSet other)
|
||||
{
|
||||
if (Uuid == other.Uuid)
|
||||
if (Id == other.Id)
|
||||
return 0;
|
||||
|
||||
int comp = DisplayArea.CompareTo(other.DisplayArea);
|
||||
if (comp == 0)
|
||||
return StringUtility.NaturalCompare(Name, other.Name);
|
||||
return StringUtility.NaturalCompare(FriendlyName, other.FriendlyName);
|
||||
return comp;
|
||||
}
|
||||
|
||||
@ -810,36 +609,4 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum DataType { Cpu, Memory, Disk, Storage, Network, Latency, LoadAverage, Gpu, Pvs, Custom };
|
||||
|
||||
public static class DatatypeExtensions
|
||||
{
|
||||
public static string ToStringI18N(this DataType datatype)
|
||||
{
|
||||
switch (datatype)
|
||||
{
|
||||
case DataType.Cpu:
|
||||
return Messages.DATATYPE_CPU;
|
||||
case DataType.Memory:
|
||||
return Messages.DATATYPE_MEMORY;
|
||||
case DataType.Disk:
|
||||
return Messages.DATATYPE_DISK;
|
||||
case DataType.Storage:
|
||||
return Messages.DATATYPE_STORAGE;
|
||||
case DataType.Network:
|
||||
return Messages.DATATYPE_NETWORK;
|
||||
case DataType.Latency:
|
||||
return Messages.DATATYPE_LATENCY;
|
||||
case DataType.LoadAverage:
|
||||
return Messages.DATATYPE_LOADAVERAGE;
|
||||
case DataType.Gpu:
|
||||
return Messages.DATATYPE_GPU;
|
||||
case DataType.Pvs:
|
||||
return Messages.DATATYPE_PVS;
|
||||
default:
|
||||
return Messages.DATATYPE_CUSTOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
DisplayName = sourceGraph.DisplayName;
|
||||
foreach (DataSourceItem dsi in sourceGraph.DataSources)
|
||||
{
|
||||
DataSources.Add(new DataSourceItem(dsi.DataSource, dsi.ToString(), dsi.Color, dsi.Uuid));
|
||||
DataSources.Add(new DataSourceItem(dsi.DataSource, dsi.ToString(), dsi.Color, dsi.Id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
for (int i = 0; i < this.DataSources.Count; i++)
|
||||
{
|
||||
if (this.DataSources[i].Uuid != other.DataSources[i].Uuid)
|
||||
if (this.DataSources[i].Id != other.DataSources[i].Id)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -129,28 +129,24 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
private string friendlyName;
|
||||
public Color Color;
|
||||
public bool ColorChanged;
|
||||
public string Uuid;
|
||||
public DataType DataType;
|
||||
public string Id;
|
||||
public Helpers.DataSourceCategory Category;
|
||||
|
||||
public DataSourceItem(Data_source ds, string friendlyname, Color color, string uuid)
|
||||
public DataSourceItem(Data_source ds, string friendlyname, Color color, string id, IXenObject xo = null)
|
||||
{
|
||||
DataSource = ds;
|
||||
Enabled = DataSource.enabled;
|
||||
friendlyName = friendlyname;
|
||||
Color = color;
|
||||
Uuid = uuid;
|
||||
}
|
||||
Id = id;
|
||||
|
||||
public DataSourceItem(Data_source ds, string friendlyname, Color color, string uuid, IXenObject xo)
|
||||
: this(ds, friendlyname, color, uuid)
|
||||
{
|
||||
DataSet dataSet = DataSet.Create(uuid, xo);
|
||||
DataType = dataSet.Type;
|
||||
if (DataSet.ParseId(id, out _, out _, out string dataSourceName))
|
||||
Category = Helpers.GetDataSourceCategory(dataSourceName);
|
||||
}
|
||||
|
||||
public string GetDataSource()
|
||||
{
|
||||
string[] lst = Uuid.Split(':');
|
||||
string[] lst = Id.Split(':');
|
||||
return lst.Length == 0 ? "" : lst[lst.Length - 1];
|
||||
}
|
||||
|
||||
@ -166,7 +162,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
|
||||
public bool Equals(DataSourceItem other)
|
||||
{
|
||||
return Uuid.Equals(other.Uuid);
|
||||
return Id.Equals(other?.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
DataKey newkey =
|
||||
CreateKey(new Point(left - HorizontalScroll.Value, CONTROL_PADDING + y + GRAPH_PADDING));
|
||||
foreach (DataSourceItem item in designedGraph.DataSources)
|
||||
newkey.DataSourceUUIDsToShow.Add(item.Uuid);
|
||||
newkey.DataSourceUUIDsToShow.Add(item.Id);
|
||||
newplot.DataKey = newkey;
|
||||
newkey.Enter += new EventHandler(dataKey_Enter);
|
||||
newkey.MouseDown += new MouseEventHandler(dataKey_MouseDown);
|
||||
@ -489,10 +489,10 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
found = graph.DataSources.Contains(dsi);
|
||||
if (found)
|
||||
{
|
||||
if (!Palette.HasCustomColour(dsi.Uuid))
|
||||
if (!Palette.HasCustomColour(dsi.Id))
|
||||
{
|
||||
dsi.ColorChanged = true;
|
||||
Palette.SetCustomColor(dsi.Uuid, dsi.Color);
|
||||
Palette.SetCustomColor(dsi.Id, dsi.Color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -514,11 +514,11 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (datasourceName == "memory_total_kib" || datasourceName == "memory")
|
||||
continue;
|
||||
|
||||
if (!Palette.HasCustomColour(dsi.Uuid))
|
||||
if (!Palette.HasCustomColour(dsi.Id))
|
||||
{
|
||||
dsi.DataSource.name_label = datasourceName;
|
||||
dsi.ColorChanged = true;
|
||||
Palette.SetCustomColor(dsi.Uuid, dsi.Color);
|
||||
Palette.SetCustomColor(dsi.Id, dsi.Color);
|
||||
dataSources.Add(dsi);
|
||||
}
|
||||
}
|
||||
@ -686,7 +686,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
Plots[index].DisplayName = newGraph.DisplayName;
|
||||
Keys[index].DataSourceUUIDsToShow.Clear();
|
||||
foreach (DataSourceItem item in newGraph.DataSources)
|
||||
Keys[index].DataSourceUUIDsToShow.Add(item.Uuid);
|
||||
Keys[index].DataSourceUUIDsToShow.Add(item.Id);
|
||||
Keys[index].UpdateItems();
|
||||
|
||||
if (isSelected)
|
||||
|
@ -140,7 +140,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if(pool == null)
|
||||
return;
|
||||
|
||||
string key = GetColorKey(set.TypeString, set.XenObject);
|
||||
string key = GetColorKey(set.DataSourceName, set.XenObject);
|
||||
|
||||
Dictionary<string, string> gui_config = Helpers.GetGuiConfig(pool);
|
||||
|
||||
@ -151,7 +151,7 @@ namespace XenAdmin.Controls.CustomDataGraph
|
||||
if (!int.TryParse(gui_config[key], out argb))
|
||||
return;
|
||||
|
||||
SetCustomColor(set.Uuid, Color.FromArgb(argb));
|
||||
SetCustomColor(set.Id, Color.FromArgb(argb));
|
||||
}
|
||||
|
||||
public static string GetColorKey(string ds_name, IXenObject xo)
|
||||
|
@ -323,7 +323,7 @@ namespace XenAdmin.Dialogs
|
||||
this.dsi = dataSourceItem;
|
||||
var displayOnGraphCell = new DataGridViewCheckBoxCell { Value = displayOnGraph };
|
||||
var datasourceCell = new DataGridViewTextBoxCell { Value = dsi.ToString() };
|
||||
var typeCell = new DataGridViewTextBoxCell { Value = dsi.DataType.ToStringI18N() };
|
||||
var typeCell = new DataGridViewTextBoxCell { Value = dsi.Category.ToStringI18N() };
|
||||
var colourCell = new DataGridViewTextBoxCell { Value = dsi.Color };
|
||||
Cells.AddRange(displayOnGraphCell, datasourceCell, typeCell, colourCell);
|
||||
}
|
||||
|
72
XenModel/UnitStrings.Designer.cs
generated
Normal file
72
XenModel/UnitStrings.Designer.cs
generated
Normal file
@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace XenAdmin {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class UnitStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal UnitStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("XenAdmin.UnitStrings", typeof(UnitStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to s/s.
|
||||
/// </summary>
|
||||
public static string SEC_PER_SEC_UNIT {
|
||||
get {
|
||||
return ResourceManager.GetString("SEC_PER_SEC_UNIT", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
XenModel/UnitStrings.ja.resx
Normal file
101
XenModel/UnitStrings.ja.resx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
104
XenModel/UnitStrings.resx
Normal file
104
XenModel/UnitStrings.resx
Normal file
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="SEC_PER_SEC_UNIT" xml:space="preserve">
|
||||
<value>s/s</value>
|
||||
</data>
|
||||
</root>
|
101
XenModel/UnitStrings.zh-CN.resx
Normal file
101
XenModel/UnitStrings.zh-CN.resx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@ -959,31 +959,114 @@ namespace XenAdmin.Core
|
||||
|
||||
#endregion
|
||||
|
||||
public enum DataSourceCategory
|
||||
{
|
||||
Cpu,
|
||||
Memory,
|
||||
Disk,
|
||||
Storage,
|
||||
Network,
|
||||
Latency,
|
||||
LoadAverage,
|
||||
Gpu,
|
||||
Pvs,
|
||||
Custom
|
||||
}
|
||||
|
||||
public static string ToStringI18N(this DataSourceCategory category)
|
||||
{
|
||||
switch (category)
|
||||
{
|
||||
case DataSourceCategory.Cpu:
|
||||
return Messages.DATATYPE_CPU;
|
||||
case DataSourceCategory.Memory:
|
||||
return Messages.DATATYPE_MEMORY;
|
||||
case DataSourceCategory.Disk:
|
||||
return Messages.DATATYPE_DISK;
|
||||
case DataSourceCategory.Storage:
|
||||
return Messages.DATATYPE_STORAGE;
|
||||
case DataSourceCategory.Network:
|
||||
return Messages.DATATYPE_NETWORK;
|
||||
case DataSourceCategory.Latency:
|
||||
return Messages.DATATYPE_LATENCY;
|
||||
case DataSourceCategory.LoadAverage:
|
||||
return Messages.DATATYPE_LOADAVERAGE;
|
||||
case DataSourceCategory.Gpu:
|
||||
return Messages.DATATYPE_GPU;
|
||||
case DataSourceCategory.Pvs:
|
||||
return Messages.DATATYPE_PVS;
|
||||
default:
|
||||
return Messages.DATATYPE_CUSTOM;
|
||||
}
|
||||
}
|
||||
|
||||
public static Regex CpuRegex = new Regex("^cpu([0-9]+)$");
|
||||
public static Regex CpuAvgFreqRegex = new Regex("^CPU([0-9]+)-avg-freq$");
|
||||
static Regex CpuAvgFreqRegex = new Regex("^CPU([0-9]+)-avg-freq$");
|
||||
public static Regex CpuStateRegex = new Regex("^cpu([0-9]+)-(C|P)([0-9]+)$");
|
||||
static Regex CpuOtherRegex = new Regex("^cpu_avg|avg_cpu$");
|
||||
private static Regex VcpuRegex = new Regex("^runstate_(blocked|concurrency_hazard|full_contention|fullrun|partial_contention|partial_run)$");
|
||||
static Regex VifRegex = new Regex("^vif_([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifEthRegex = new Regex("^pif_eth([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifVlanRegex = new Regex("^pif_eth([0-9]+).([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifVlanRegex = new Regex("^pif_eth([0-9]+).([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifBrRegex = new Regex("^pif_xenbr([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifXapiRegex = new Regex("^pif_xapi([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifXapiRegex = new Regex("^pif_xapi([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifTapRegex = new Regex("^pif_tap([0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifLoRegex = new Regex("^pif_lo_(tx|rx)((_errors)?)$");
|
||||
static Regex PifBondRegex = new Regex("^pif_(bond[0-9]+)_(tx|rx)((_errors)?)$");
|
||||
static Regex PifOtherRegex = new Regex("^pif_aggr_(tx|rx)$");
|
||||
static Regex DiskRegex = new Regex("^vbd_((xvd|hd)[a-z]+)(_(read|write))?(_latency)?$");
|
||||
static Regex DiskIopsRegex = new Regex("^vbd_((xvd|hd)[a-z]+)_iops_(read|write|total)$");
|
||||
static Regex DiskThroughputRegex = new Regex("^vbd_((xvd|hd)[a-z]+)_io_throughput_(read|write|total)$");
|
||||
static Regex DiskOtherRegex = new Regex("^vbd_((xvd|hd)[a-z]+)_(avgqu_sz|inflight|iowait)$");
|
||||
static Regex NetworkLatencyRegex = new Regex("^network/latency$");
|
||||
static Regex XapiLatencyRegex = new Regex("^xapi_healthcheck/latency$");
|
||||
static Regex XapiMemoryRegex = new Regex("^xapi_(allocation|free_memory|live_memory|memory_usage)_kib$");
|
||||
static Regex StatefileLatencyRegex = new Regex("^statefile/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/latency$");
|
||||
static Regex LoadAvgRegex = new Regex("loadavg");
|
||||
static Regex SrRegex = new Regex("^sr_[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}_cache_(size|hits|misses)");
|
||||
static Regex SrRegex = new Regex("^sr_[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}_cache_(size|hits|misses)");
|
||||
static Regex SrIORegex = new Regex("^(io_throughput|iops)_(read|write|total)_([a-f0-9]{8})$");
|
||||
static Regex SrOtherRegex = new Regex("^(latency|avgqu_sz|inflight|iowait)_([a-f0-9]{8})$");
|
||||
static Regex SrReadWriteRegex = new Regex("^((read|write)(_latency)?)_([a-f0-9]{8})$");
|
||||
static Regex GpuRegex = new Regex(@"^gpu_((memory_(free|used))|power_usage|temperature|(utilisation_(compute|memory_io)))_((([a-fA-F0-9]{4}\/)|([a-fA-F0-9]{8}\/))?[a-fA-F0-9]{2}\/[0-1][a-fA-F0-9].[0-7])$");
|
||||
|
||||
public static DataSourceCategory GetDataSourceCategory(string name)
|
||||
{
|
||||
if (CpuRegex.IsMatch(name) || CpuAvgFreqRegex.IsMatch(name) ||
|
||||
CpuStateRegex.IsMatch(name) || CpuOtherRegex.IsMatch(name) || VcpuRegex.IsMatch(name))
|
||||
return DataSourceCategory.Cpu;
|
||||
|
||||
if (VifRegex.IsMatch(name) || PifEthRegex.IsMatch(name) || PifVlanRegex.IsMatch(name) ||
|
||||
PifBrRegex.IsMatch(name) || PifXapiRegex.IsMatch(name) || PifBondRegex.IsMatch(name) ||
|
||||
PifLoRegex.IsMatch(name) || PifTapRegex.IsMatch(name) || PifOtherRegex.IsMatch(name))
|
||||
return DataSourceCategory.Network;
|
||||
|
||||
if (DiskRegex.IsMatch(name) || DiskIopsRegex.IsMatch(name) ||
|
||||
DiskThroughputRegex.IsMatch(name) || DiskOtherRegex.IsMatch(name))
|
||||
return DataSourceCategory.Disk;
|
||||
|
||||
if (SrRegex.IsMatch(name) || SrIORegex.IsMatch(name) ||
|
||||
SrOtherRegex.IsMatch(name) || SrReadWriteRegex.IsMatch(name))
|
||||
return DataSourceCategory.Storage;
|
||||
|
||||
if (GpuRegex.IsMatch(name))
|
||||
return DataSourceCategory.Gpu;
|
||||
|
||||
if (NetworkLatencyRegex.IsMatch(name) || XapiLatencyRegex.IsMatch(name) ||
|
||||
StatefileLatencyRegex.IsMatch(name))
|
||||
return DataSourceCategory.Latency;
|
||||
|
||||
if (LoadAvgRegex.IsMatch(name))
|
||||
return DataSourceCategory.LoadAverage;
|
||||
|
||||
if (name.StartsWith("pvsaccelerator"))
|
||||
return DataSourceCategory.Pvs;
|
||||
|
||||
if (XapiMemoryRegex.IsMatch(name) || name.StartsWith("memory"))
|
||||
return DataSourceCategory.Memory;
|
||||
|
||||
return DataSourceCategory.Custom;
|
||||
}
|
||||
|
||||
public static string GetFriendlyDataSourceName(string name, IXenObject iXenObject)
|
||||
{
|
||||
if (iXenObject == null)
|
||||
|
@ -411,6 +411,11 @@ namespace XenAdmin
|
||||
return string.Format(Messages.VAL_FORMAT, p, Messages.COUNTS_PER_SEC_UNIT);
|
||||
}
|
||||
|
||||
public static string SecondsPerSecondString(double p)
|
||||
{
|
||||
return string.Format(Messages.VAL_FORMAT, p, UnitStrings.SEC_PER_SEC_UNIT);
|
||||
}
|
||||
|
||||
public static string MegaHertzString(double t)
|
||||
{
|
||||
string unit;
|
||||
|
@ -168,6 +168,11 @@
|
||||
<Compile Include="Actions\ZipStatusReportAction.cs" />
|
||||
<Compile Include="Alerts\Types\Alert.cs" />
|
||||
<Compile Include="BrandManager.cs" />
|
||||
<Compile Include="UnitStrings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>UnitStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Utils\StringExtensions.cs" />
|
||||
<Compile Include="Utils\TimeSpanExtensions.cs" />
|
||||
<Compile Include="WLB\WlbPoolConfiguration.cs" />
|
||||
@ -607,6 +612,13 @@
|
||||
<EmbeddedResource Include="Messages.zh-CN.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UnitStrings.ja.resx" />
|
||||
<EmbeddedResource Include="UnitStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>UnitStrings.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UnitStrings.zh-CN.resx" />
|
||||
<EmbeddedResource Include="XenAPI\FriendlyErrorNames.ja.resx" />
|
||||
<EmbeddedResource Include="XenAPI\FriendlyErrorNames.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
|
Loading…
Reference in New Issue
Block a user