Show update status for pools and hosts on the General tabPage:

- Show sync status for the pool in its Updates section.
- Moved update date for the host from the Version to the Updates section.

Signed-off-by: Konstantina Chremmou <Konstantina.Chremmou@cloud.com>
This commit is contained in:
Konstantina Chremmou 2023-07-22 16:50:43 +01:00
parent b0c23a2c36
commit 2774ea5c7f
6 changed files with 183 additions and 74 deletions

View File

@ -394,6 +394,13 @@ namespace XenAdmin.Controls
AddRow(CreateKeyCell(key), valueCell, null, contextMenuItems);
}
internal void AddEntryWithNoteLink(string key, string value, string note, Action action, params ToolStripMenuItem[] contextMenuItems)
{
var valueCell = new DataGridViewTextBoxCell { Value = value };
var noteCell = new DataGridViewLinkCell { Value = note, Tag = action };
AddRow(CreateKeyCell(key), valueCell, noteCell, contextMenuItems);
}
internal void AddEntryWithNoteLink(string key, string value, string note, Action action, Color fontColor, params ToolStripMenuItem[] contextMenuItems)
{
var valueCell = new DataGridViewTextBoxCell { Value = value };

View File

@ -71,7 +71,7 @@ namespace XenAdmin.Controls
comboBoxCacheSr.Items.Clear();
// add the "Not configured" item first
var notConfiguredItem = new SrComboBoxItem(null, Messages.PVS_CACHE_NOT_CONFIGURED);
var notConfiguredItem = new SrComboBoxItem(null, Messages.NOT_CONFIGURED);
comboBoxCacheSr.Items.Add(notConfiguredItem);
// add Memory SR; if no memory SR found, add a placeholder (we will create the memory SR in ConfigurePvsCacheAction)

View File

@ -109,7 +109,7 @@ namespace XenAdmin.Dialogs
var configuredRows = rows.Where(r => r.CacheSr != null).ToList();
if (configuredRows.Count == 0)
return Messages.PVS_CACHE_NOT_CONFIGURED;
return Messages.NOT_CONFIGURED;
return configuredRows.Any(row => row.CacheSr.GetSRType(false) != SR.SRTypes.tmpfs)
? Messages.PVS_CACHE_MEMORY_AND_DISK

View File

@ -35,11 +35,13 @@ using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Commands;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAdmin.CustomFields;
using XenAdmin.Dialogs;
using XenAdmin.Dialogs.ServerUpdates;
using XenAdmin.Model;
using XenAdmin.Network;
using XenAdmin.SettingsPanels;
@ -372,9 +374,8 @@ namespace XenAdmin.TabPages
base.Text = Messages.CONNECTION_GENERAL_TAB_TITLE;
else if (xenObject is Host)
base.Text = Messages.HOST_GENERAL_TAB_TITLE;
else if (xenObject is VM)
else if (xenObject is VM vm)
{
VM vm = (VM)xenObject;
if (vm.is_a_snapshot)
base.Text = Messages.SNAPSHOT_GENERAL_TAB_TITLE;
else if (vm.is_a_template)
@ -417,12 +418,12 @@ namespace XenAdmin.TabPages
GenerateVersionBox();
GenerateLicenseBox();
GenerateCPUBox();
GenerateHostPatchesBox();
GenerateHostUpdatesBox();
GenerateBootBox();
GenerateHABox();
GenerateStatusBox();
GenerateMultipathBox();
GeneratePoolPatchesBox();
GeneratePoolUpdatesBox();
GenerateMultipathBootBox();
GenerateVCPUsBox();
GenerateDockerInfoBox();
@ -543,24 +544,18 @@ namespace XenAdmin.TabPages
}
}
private void GeneratePoolPatchesBox()
private void GeneratePoolUpdatesBox()
{
if (!(xenObject is Pool pool))
return;
PDSection s = pdSectionUpdates;
var messages = CheckPoolUpdate(pool);
if (messages.Count > 0)
{
foreach (var kvp in messages)
s.AddEntry(kvp.Key, kvp.Value);
pdSectionUpdates.AddEntry(kvp.Key, kvp.Value);
}
Host coordinator = Helpers.GetCoordinator(xenObject.Connection);
if (coordinator == null)
return;
var fullyApplied = new List<string>();
var partAppliedError = new List<string>();
var partApplied = new List<string>();
@ -568,7 +563,11 @@ namespace XenAdmin.TabPages
var cache = xenObject.Connection.Cache;
var allHostCount = xenObject.Connection.Cache.HostCount;
if (Helpers.ElyOrGreater(xenObject.Connection))
if (Helpers.CloudOrGreater(pool.Connection))
{
GenerateCdnUpdatesBox(pool);
}
else if (Helpers.ElyOrGreater(xenObject.Connection))
{
foreach (var u in cache.Pool_updates)
{
@ -605,76 +604,127 @@ namespace XenAdmin.TabPages
if (fullyApplied.Count > 0)
{
fullyApplied.Sort(StringUtility.NaturalCompare);
s.AddEntry(FriendlyName("Pool_patch.fully_applied"), string.Join(Environment.NewLine, fullyApplied));
pdSectionUpdates.AddEntry(FriendlyName("Pool_patch.fully_applied"), string.Join(Environment.NewLine, fullyApplied));
}
if (partApplied.Count > 0)
{
var menuItems = new ToolStripMenuItem[] {new CommandToolStripMenuItem(new InstallNewUpdateCommand(Program.MainWindow), true)};
partApplied.Sort(StringUtility.NaturalCompare);
s.AddEntry(FriendlyName("Pool_patch.partially_applied"), string.Join(Environment.NewLine, partApplied), menuItems);
pdSectionUpdates.AddEntry(FriendlyName("Pool_patch.partially_applied"), string.Join(Environment.NewLine, partApplied), menuItems);
}
if (partAppliedError.Count > 0)
{
var menuItems = new ToolStripMenuItem[] {new CommandToolStripMenuItem(new InstallNewUpdateCommand(Program.MainWindow), true)};
partAppliedError.Sort(StringUtility.NaturalCompare);
s.AddEntry(string.Format(Messages.STRING_SPACE_STRING,
pdSectionUpdates.AddEntry(string.Format(Messages.STRING_SPACE_STRING,
FriendlyName("Pool_patch.partially_applied"), Messages.UPDATES_GENERAL_TAB_ENFORCE_HOMOGENEITY),
string.Join(Environment.NewLine, partAppliedError), Color.Red, menuItems);
}
}
private void GenerateHostPatchesBox()
private void GenerateCdnUpdatesBox(Pool pool)
{
Host host = xenObject as Host;
if (host == null)
return;
var repoNames = (from repoRef in pool.repositories
let repo = pool.Connection.Resolve(repoRef)
where repo != null
let found = RepoDescriptor.AllRepos.FirstOrDefault(rd => rd.MatchesRepository(repo))
where found != null
select found.FriendlyName).ToList();
PDSection s = pdSectionUpdates;
List<KeyValuePair<String, String>> messages;
bool elyOrGreater = Helpers.ElyOrGreater(host);
if (elyOrGreater)
{
// As of Ely we use host.updates_requiring_reboot to generate the list of reboot required messages
messages = CheckHostUpdatesRequiringReboot(host);
}
else
{
// For older versions no change to how messages are generated
messages = CheckServerUpdates(host);
}
if (messages.Count > 0)
{
foreach (KeyValuePair<String, String> kvp in messages)
pdSectionUpdates.AddEntryWithNoteLink(Messages.UPDATES_GENERAL_TAB_REPO,
repoNames.Count == 0 ? Messages.NOT_CONFIGURED : string.Join("\n", repoNames),
Messages.UPDATES_GENERAL_TAB_CONFIG,
() =>
{
s.AddEntry(kvp.Key, kvp.Value);
using (var dialog = new ConfigUpdatesDialog())
dialog.ShowDialog(this);
});
string lastSyncTime = Messages.INDETERMINABLE;
if (Helpers.XapiEqualOrGreater_23_18_0(pool.Connection))
{
lastSyncTime = Messages.NEVER;
if (pool.last_update_sync > Util.GetUnixMinDateTime())
{
lastSyncTime = HelpersGUI.DateTimeToString(pool.last_update_sync.ToLocalTime(), Messages.DATEFORMAT_DMY_HMS, true);
}
}
var appliedPatchesList = Helpers.HostAppliedPatchesList(host);
var appliedPatches = string.Join(Environment.NewLine, appliedPatchesList.ToArray());
pdSectionUpdates.AddEntryWithNoteLink(Messages.UPDATES_GENERAL_TAB_LAST_SYNCED,
lastSyncTime, Messages.UPDATES_GENERAL_TAB_SYNC_NOW,
() =>
{
var syncAction = new SyncWithCdnAction(pool);
syncAction.Completed += a => Updates.CheckForCdnUpdates(a.Connection);
syncAction.RunAsync();
});
}
private void GenerateHostUpdatesBox()
{
if (!(xenObject is Host host))
return;
bool elyOrGreater = Helpers.ElyOrGreater(host);
// As of Ely we use host.updates_requiring_reboot to generate the list of reboot required messages
// For older versions no change to how messages are generated
var messages = elyOrGreater ? CheckHostUpdatesRequiringReboot(host) : CheckServerUpdates(host);
foreach (var kvp in messages)
pdSectionUpdates.AddEntry(kvp.Key, kvp.Value);
var appliedPatches = string.Join(Environment.NewLine, Helpers.HostAppliedPatchesList(host));
if (!string.IsNullOrEmpty(appliedPatches))
{
s.AddEntry(FriendlyName("Pool_patch.applied"), appliedPatches);
}
pdSectionUpdates.AddEntry(FriendlyName("Pool_patch.applied"), appliedPatches);
var recommendedPatches = RecommendedPatchesForHost(host);
if (!string.IsNullOrEmpty(recommendedPatches))
{
s.AddEntry(FriendlyName("Pool_patch.required-updates"), recommendedPatches);
}
pdSectionUpdates.AddEntry(FriendlyName("Pool_patch.required-updates"), recommendedPatches);
if (!elyOrGreater)
{
// add supplemental packs
var suppPacks = hostInstalledSuppPacks(host);
if (!string.IsNullOrEmpty(suppPacks))
pdSectionUpdates.AddEntry(FriendlyName("Supplemental_packs.installed"), suppPacks);
}
if (Helpers.CloudOrGreater(host))
{
var pool = Helpers.GetPool(host.Connection);
if (pool == null) //standalone host
{
s.AddEntry(FriendlyName("Supplemental_packs.installed"), suppPacks);
pool = Helpers.GetPoolOfOne(host.Connection);
GenerateCdnUpdatesBox(pool);
}
if (Helpers.XapiEqualOrGreater_22_20_0(host))
{
var unixMinDateTime = Util.GetUnixMinDateTime();
var softwareVersionDate = unixMinDateTime;
if (host.software_version.ContainsKey("date"))
{
if (!Util.TryParseIso8601DateTime(host.software_version["date"], out softwareVersionDate))
Util.TryParseNonIso8601DateTime(host.software_version["date"], out softwareVersionDate);
}
string lastUpdateTime = Messages.NEVER;
if (host.last_software_update > softwareVersionDate && host.last_software_update > unixMinDateTime)
{
lastUpdateTime = HelpersGUI.DateTimeToString(host.last_software_update.ToLocalTime(), Messages.DATEFORMAT_DMY_HMS, true);
}
pdSectionUpdates.AddEntry(Messages.SOFTWARE_VERSION_LAST_UPDATED, lastUpdateTime);
}
}
}
@ -1080,19 +1130,16 @@ namespace XenAdmin.TabPages
private void GenerateVersionBox()
{
Host host = xenObject as Host;
if (host == null || host.software_version == null)
if (!(xenObject is Host host) || host.software_version == null)
return;
var softwareVersionDate = DateTime.MinValue;
var unixMinDateTime = Util.GetUnixMinDateTime();
if (host.software_version.ContainsKey("date"))
{
string buildDate = host.software_version["date"];
if (Util.TryParseIso8601DateTime(host.software_version["date"], out softwareVersionDate) && softwareVersionDate > unixMinDateTime)
if (Util.TryParseIso8601DateTime(host.software_version["date"], out var softwareVersionDate) && softwareVersionDate > unixMinDateTime)
buildDate = HelpersGUI.DateTimeToString(softwareVersionDate.ToLocalTime(), Messages.DATEFORMAT_DMY_HMS, true);
else if (Util.TryParseNonIso8601DateTime(host.software_version["date"], out softwareVersionDate) && softwareVersionDate > unixMinDateTime)
buildDate = HelpersGUI.DateTimeToString(softwareVersionDate.ToLocalTime(), Messages.DATEFORMAT_DMY, true);
@ -1116,11 +1163,6 @@ namespace XenAdmin.TabPages
if (host.software_version.ContainsKey("dbv"))
pdSectionVersion.AddEntry("DBV", host.software_version["dbv"]);
if (Helpers.CloudOrGreater(host) && Helpers.XapiEqualOrGreater_22_20_0(host) &&
host.last_software_update > softwareVersionDate && host.last_software_update > unixMinDateTime)
pdSectionVersion.AddEntry(Messages.SOFTWARE_VERSION_LAST_UPDATED,
HelpersGUI.DateTimeToString(host.last_software_update.ToLocalTime(), Messages.DATEFORMAT_DMY_HMS, true));
}
private void GenerateCPUBox()

View File

@ -21503,6 +21503,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Indeterminable.
/// </summary>
public static string INDETERMINABLE {
get {
return ResourceManager.GetString("INDETERMINABLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Disk snapshots are not currently available for this VM.
/// </summary>
@ -28382,6 +28391,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Not configured.
/// </summary>
public static string NOT_CONFIGURED {
get {
return ResourceManager.GetString("NOT_CONFIGURED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to not contained in.
/// </summary>
@ -31749,15 +31767,6 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Not configured.
/// </summary>
public static string PVS_CACHE_NOT_CONFIGURED {
get {
return ResourceManager.GetString("PVS_CACHE_NOT_CONFIGURED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This PVS cache storage cannot be changed because it is in use..
/// </summary>
@ -37410,6 +37419,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Configure updates....
/// </summary>
public static string UPDATES_GENERAL_TAB_CONFIG {
get {
return ResourceManager.GetString("UPDATES_GENERAL_TAB_CONFIG", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to (full application required).
/// </summary>
@ -37419,6 +37437,33 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Last synchronized.
/// </summary>
public static string UPDATES_GENERAL_TAB_LAST_SYNCED {
get {
return ResourceManager.GetString("UPDATES_GENERAL_TAB_LAST_SYNCED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Update channel.
/// </summary>
public static string UPDATES_GENERAL_TAB_REPO {
get {
return ResourceManager.GetString("UPDATES_GENERAL_TAB_REPO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Synchronize Now.
/// </summary>
public static string UPDATES_GENERAL_TAB_SYNC_NOW {
get {
return ResourceManager.GetString("UPDATES_GENERAL_TAB_SYNC_NOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Automatically check for {0} updates.
/// </summary>

View File

@ -7491,6 +7491,9 @@ This might result in failure to migrate VMs to this server during the RPU or to
<data name="INCORRECT_OLD_PASSWORD" xml:space="preserve">
<value>Incorrect old password</value>
</data>
<data name="INDETERMINABLE" xml:space="preserve">
<value>Indeterminable</value>
</data>
<data name="INFO_DISK_MODE" xml:space="preserve">
<value>Disk snapshots are not currently available for this VM</value>
</data>
@ -9858,6 +9861,9 @@ When you configure an NFS storage repository, you simply provide the host name o
<data name="NOT_ATTACHED_TO" xml:space="preserve">
<value>not attached to</value>
</data>
<data name="NOT_CONFIGURED" xml:space="preserve">
<value>Not configured</value>
</data>
<data name="NOT_CONTAINED_IN" xml:space="preserve">
<value>not contained in</value>
</data>
@ -10998,9 +11004,6 @@ Click Previous if you need to go back and specify a different network location o
<data name="PVS_CACHE_MEMORY_SR_NAME" xml:space="preserve">
<value>MemorySR</value>
</data>
<data name="PVS_CACHE_NOT_CONFIGURED" xml:space="preserve">
<value>Not configured</value>
</data>
<data name="PVS_CACHE_STORAGE_CANNOT_BE_CHANGED" xml:space="preserve">
<value>This PVS cache storage cannot be changed because it is in use.</value>
</data>
@ -12924,9 +12927,21 @@ Note that if RBAC is enabled, only updates which you have privileges to dismiss
<data name="UPDATES_DOWNLOAD_REQUIRED_XENCENTER" xml:space="preserve">
<value>Download {0}</value>
</data>
<data name="UPDATES_GENERAL_TAB_CONFIG" xml:space="preserve">
<value>Configure updates...</value>
</data>
<data name="UPDATES_GENERAL_TAB_ENFORCE_HOMOGENEITY" xml:space="preserve">
<value>(full application required)</value>
</data>
<data name="UPDATES_GENERAL_TAB_LAST_SYNCED" xml:space="preserve">
<value>Last synchronized</value>
</data>
<data name="UPDATES_GENERAL_TAB_REPO" xml:space="preserve">
<value>Update channel</value>
</data>
<data name="UPDATES_GENERAL_TAB_SYNC_NOW" xml:space="preserve">
<value>Synchronize Now</value>
</data>
<data name="UPDATES_OPTIONS_DESC" xml:space="preserve">
<value>Automatically check for {0} updates</value>
</data>