diff --git a/XenAdmin/Actions/GUIActions/DeleteAllAlertsAction.cs b/XenAdmin/Actions/GUIActions/DeleteAllAlertsAction.cs index 08ce61241..31ac5c733 100644 --- a/XenAdmin/Actions/GUIActions/DeleteAllAlertsAction.cs +++ b/XenAdmin/Actions/GUIActions/DeleteAllAlertsAction.cs @@ -29,29 +29,23 @@ * SUCH DAMAGE. */ -using System; using System.Collections.Generic; -using System.Linq; using XenAdmin.Alerts; using XenAdmin.Network; using XenAdmin.Core; -using XenAPI; namespace XenAdmin.Actions { public class DeleteAllAlertsAction : AsyncAction { - private readonly IEnumerable Alerts; + private readonly List _alerts; - /// May be null; this is expected for client-side alerts. - /// - public DeleteAllAlertsAction(IXenConnection connection, IEnumerable alerts) - : base(connection, - GetActionTitle(connection, alerts.Count()), - Messages.ACTION_REMOVE_ALERTS_DESCRIPTION) + public DeleteAllAlertsAction(List alerts, IXenConnection connection = null) + : base(connection, GetActionTitle(connection, alerts.Count), + Messages.ACTION_REMOVE_ALERTS_DESCRIPTION) { - this.Alerts = alerts; + _alerts = new List(alerts); if (connection != null) { @@ -73,58 +67,25 @@ namespace XenAdmin.Actions protected override void Run() { - int i = 0; - int max = Alerts.Count(); - Exception e = null; LogDescriptionChanges = false; - List toBeDismissed = new List(); try { - var myList = new List(Alerts); - foreach (Alert a in myList) + for (var i = 0; i < _alerts.Count; i++) { - PercentComplete = (i * 100) / max; - i++; - Description = string.Format(Messages.ACTION_REMOVE_ALERTS_PROGRESS_DESCRIPTION, i, max); - - Alert a1 = a; - BestEffort(ref e, delegate - { - try - { - if (a1 is XenServerPatchAlert || a1 is XenServerVersionAlert) - { - toBeDismissed.Add(a1); - } - else if(a1 is XenCenterUpdateAlert) - { - a1.Dismiss(); - } - else - { - a1.DismissSingle(Session); - } - } - catch (Failure exn) - { - if (exn.ErrorDescription[0] != Failure.HANDLE_INVALID) - throw; - //remove alert from XenCenterAlerts; this will trigger the CollectionChanged event, on which we update the alert count - if (Alert.FindAlert(a1) != null) - Alert.RemoveAlert(a1); - } - }); + Description = string.Format(Messages.ACTION_REMOVE_ALERTS_PROGRESS_DESCRIPTION, i, _alerts.Count); + _alerts[i].Dismiss(); + PercentComplete = i * 100 / _alerts.Count; } - - Updates.DismissUpdates(toBeDismissed); } finally { LogDescriptionChanges = true; } - Description = max == 1 ? Messages.ACTION_REMOVE_ALERTS_DONE_ONE : string.Format(Messages.ACTION_REMOVE_ALERTS_DONE, max); + Description = _alerts.Count == 1 + ? Messages.ACTION_REMOVE_ALERTS_DONE_ONE + : string.Format(Messages.ACTION_REMOVE_ALERTS_DONE, _alerts.Count); } } } diff --git a/XenAdmin/Actions/GUIActions/RestoreDismissedUpdatesAction.cs b/XenAdmin/Actions/GUIActions/RestoreDismissedUpdatesAction.cs index eb6348f6d..23af05116 100644 --- a/XenAdmin/Actions/GUIActions/RestoreDismissedUpdatesAction.cs +++ b/XenAdmin/Actions/GUIActions/RestoreDismissedUpdatesAction.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using System.Text; +using XenAdmin.Alerts; using XenAdmin.Network; using XenAdmin.Core; using XenAPI; @@ -56,11 +57,11 @@ namespace XenAdmin.Actions Dictionary other_config = pool.other_config; - if (other_config.ContainsKey(Updates.IgnorePatchKey)) - other_config.Remove(Updates.IgnorePatchKey); + if (other_config.ContainsKey(XenServerPatchAlert.IgnorePatchKey)) + other_config.Remove(XenServerPatchAlert.IgnorePatchKey); - if (other_config.ContainsKey(Updates.LAST_SEEN_SERVER_VERSION_KEY)) - other_config.Remove(Updates.LAST_SEEN_SERVER_VERSION_KEY); + if (other_config.ContainsKey(XenServerVersionAlert.LAST_SEEN_SERVER_VERSION_KEY)) + other_config.Remove(XenServerVersionAlert.LAST_SEEN_SERVER_VERSION_KEY); XenAPI.Pool.set_other_config(Connection.Session, pool.opaque_ref, other_config); diff --git a/XenAdmin/Alerts/Types/MessageAlert.cs b/XenAdmin/Alerts/Types/MessageAlert.cs index ff854701f..327b82615 100644 --- a/XenAdmin/Alerts/Types/MessageAlert.cs +++ b/XenAdmin/Alerts/Types/MessageAlert.cs @@ -44,7 +44,7 @@ namespace XenAdmin.Alerts { public class MessageAlert : Alert { - public XenAPI.Message Message; + public readonly Message Message; public IXenObject XenObject; private const int DEFAULT_PRIORITY = 0; @@ -438,14 +438,28 @@ namespace XenAdmin.Alerts public override void Dismiss() { - new DestroyMessageAction(Message.Connection, Message.opaque_ref).RunAsync(); - base.Dismiss(); + new DestroyMessageAction(Message).RunExternal(Connection.Session); + RemoveAlert(this); } - public override void DismissSingle(Session s) + public override bool AllowedToDismiss() { - Message.destroy(s, Message.opaque_ref); - base.Dismiss(); + if (Dismissing) + return false; + + // this shouldn't happen for this type of alert, but check for safety + if (Connection == null) + return true; + + // if we are disconnected do not dismiss as the alert will disappear soon + if (Connection.Session == null) + return false; + + if (Connection.Session.IsLocalSuperuser) + return true; + + var allowedRoles = Role.ValidRoleList("Message.destroy", Connection); + return allowedRoles.Any(r => Connection.Session.Roles.Contains(r)); } public static void RemoveAlert(Message m) diff --git a/XenAdmin/Alerts/Types/XenServerPatchAlert.cs b/XenAdmin/Alerts/Types/XenServerPatchAlert.cs index c6ba928ed..dd2980f6a 100644 --- a/XenAdmin/Alerts/Types/XenServerPatchAlert.cs +++ b/XenAdmin/Alerts/Types/XenServerPatchAlert.cs @@ -42,6 +42,8 @@ namespace XenAdmin.Alerts { public class XenServerPatchAlert : XenServerUpdateAlert { + public const string IgnorePatchKey = "XenCenter.IgnorePatches"; + public readonly XenServerPatch Patch; public readonly XenServerVersion NewServerVersion; @@ -169,15 +171,32 @@ namespace XenAdmin.Alerts Dictionary other_config = pool.other_config; - if (other_config.ContainsKey(Updates.IgnorePatchKey)) + if (other_config.ContainsKey(IgnorePatchKey)) { - List current = new List(other_config[Updates.IgnorePatchKey].Split(',')); + List current = new List(other_config[IgnorePatchKey].Split(',')); if (current.Contains(Patch.Uuid, StringComparer.OrdinalIgnoreCase)) return true; } return false; } + protected override void Dismiss(Dictionary otherConfig) + { + if (otherConfig.ContainsKey(IgnorePatchKey)) + { + var current = new List(otherConfig[IgnorePatchKey].Split(',')); + if (current.Contains(Patch.Uuid, StringComparer.OrdinalIgnoreCase)) + return; + + current.Add(Patch.Uuid); + otherConfig[IgnorePatchKey] = string.Join(",", current.ToArray()); + } + else + { + otherConfig.Add(IgnorePatchKey, Patch.Uuid); + } + } + public override bool Equals(Alert other) { if (other is XenServerPatchAlert patchAlert) diff --git a/XenAdmin/Alerts/Types/XenServerUpdateAlert.cs b/XenAdmin/Alerts/Types/XenServerUpdateAlert.cs index ec38a6649..9a849b5a2 100644 --- a/XenAdmin/Alerts/Types/XenServerUpdateAlert.cs +++ b/XenAdmin/Alerts/Types/XenServerUpdateAlert.cs @@ -147,6 +147,50 @@ namespace XenAdmin.Alerts } } + private bool AllowedToDismiss(IXenConnection connection) + { + if (connection == null) + return true; + + // if we are disconnected do not dismiss as the alert will disappear soon + if (connection.Session == null) + return false; + + // prevent dismissal if the alert is not relevant to the current connection + if (!Connections.Contains(connection) && DistinctHosts.All(h => h.Connection != connection)) + return false; + + if (connection.Session.IsLocalSuperuser) + return true; + + var allowedRoles = Role.ValidRoleList("pool.set_other_config", connection); + return allowedRoles.Any(r => connection.Session.Roles.Contains(r)); + } + + public override bool AllowedToDismiss() + { + return !Dismissing && ConnectionsManager.XenConnectionsCopy.Any(AllowedToDismiss); + } + + public override void Dismiss() + { + foreach (IXenConnection connection in ConnectionsManager.XenConnectionsCopy) + { + if (!AllowedToDismiss(connection)) + continue; + + Pool pool = Helpers.GetPoolOfOne(connection); + if (pool == null) + continue; + + var otherConfig = pool.other_config; + Dismiss(otherConfig); + Pool.set_other_config(connection.Session, pool.opaque_ref, otherConfig); + } + + Updates.RemoveUpdate(this); + } + public override bool IsDismissed() { lock (connectionsLock) @@ -155,6 +199,8 @@ namespace XenAdmin.Alerts } } + protected abstract void Dismiss(Dictionary otherConfig); + protected abstract bool IsDismissed(IXenConnection connection); } } diff --git a/XenAdmin/Alerts/Types/XenServerVersionAlert.cs b/XenAdmin/Alerts/Types/XenServerVersionAlert.cs index 5f56834a2..6043bd597 100644 --- a/XenAdmin/Alerts/Types/XenServerVersionAlert.cs +++ b/XenAdmin/Alerts/Types/XenServerVersionAlert.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; +using System.Linq; using XenAdmin.Core; using XenAdmin.Network; using XenAPI; @@ -40,6 +41,8 @@ namespace XenAdmin.Alerts { public class XenServerVersionAlert : XenServerUpdateAlert { + public const string LAST_SEEN_SERVER_VERSION_KEY = "XenCenter.LastSeenServerVersion"; + public readonly XenServerVersion Version; public XenServerVersionAlert(XenServerVersion version) @@ -76,15 +79,31 @@ namespace XenAdmin.Alerts Dictionary other_config = pool.other_config; - if (other_config.ContainsKey(Updates.LAST_SEEN_SERVER_VERSION_KEY)) + if (other_config.ContainsKey(LAST_SEEN_SERVER_VERSION_KEY)) { - List current = new List(other_config[Updates.LAST_SEEN_SERVER_VERSION_KEY].Split(',')); + List current = new List(other_config[LAST_SEEN_SERVER_VERSION_KEY].Split(',')); if (current.Contains(Version.Version.ToString())) return true; } return false; } + protected override void Dismiss(Dictionary otherConfig) + { + if (otherConfig.ContainsKey(LAST_SEEN_SERVER_VERSION_KEY)) + { + List current = new List(otherConfig[LAST_SEEN_SERVER_VERSION_KEY].Split(',')); + if (current.Contains(Version.Version.ToString())) + return; + current.Add(Version.Version.ToString()); + otherConfig[LAST_SEEN_SERVER_VERSION_KEY] = string.Join(",", current.ToArray()); + } + else + { + otherConfig.Add(LAST_SEEN_SERVER_VERSION_KEY, Version.Version.ToString()); + } + } + public override bool Equals(Alert other) { if (other is XenServerVersionAlert versionAlert) diff --git a/XenAdmin/Core/Updates.cs b/XenAdmin/Core/Updates.cs index 527ec97fd..308b0a2e4 100644 --- a/XenAdmin/Core/Updates.cs +++ b/XenAdmin/Core/Updates.cs @@ -32,17 +32,17 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; -using XenAdmin.Actions; -using XenAPI; -using XenAdmin.Alerts; -using XenAdmin.Network; using System.Diagnostics; -using System.Windows.Forms; -using XenAdmin.Dialogs; +using System.Linq; using System.Text; +using System.Windows.Forms; +using XenAdmin.Actions; +using XenAdmin.Alerts; using XenAdmin.Alerts.Types; -using XenCenterLib; +using XenAdmin.Dialogs; +using XenAdmin.Network; +using XenAPI; + namespace XenAdmin.Core { @@ -50,9 +50,12 @@ namespace XenAdmin.Core { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly string CheckForUpdatesUrl = Registry.CustomUpdatesXmlLocation ?? BrandManager.UpdatesUrl; + public static event Action CheckForUpdatesCompleted; public static event Action CheckForUpdatesStarted; public static event Action RestoreDismissedUpdatesStarted; + public static event Action UpdateAlertCollectionChanged; private static readonly object downloadedUpdatesLock = new object(); private static List XenServerVersionsForAutoCheck = new List(); @@ -61,119 +64,27 @@ namespace XenAdmin.Core public static List XenServerVersions = new List(); private static readonly object updateAlertsLock = new object(); - private static readonly ChangeableList updateAlerts = new ChangeableList(); + private static readonly List updateAlerts = new List(); - public const string IgnorePatchKey = "XenCenter.IgnorePatches"; - public const string LAST_SEEN_SERVER_VERSION_KEY = "XenCenter.LastSeenServerVersion"; - - public static IEnumerable UpdateAlerts => updateAlerts; - - public static int UpdateAlertsCount => updateAlerts.Count; - - private static void AddUpdate(Alert update) + /// + /// Locks and creates a new list of the update alerts + /// + public static List UpdateAlerts { - try + get { lock (updateAlertsLock) - { - if(!updateAlerts.Contains(update)) - { - updateAlerts.Add(update); - } - } - } - catch (Exception e) - { - log.Error("Failed to add update", e); + return updateAlerts.ToList(); } } public static void RemoveUpdate(Alert update) - { - try - { - lock (updateAlertsLock) - { - if(updateAlerts.Contains(update)) - { - updateAlerts.Remove(update); - } - } - } - catch (Exception e) - { - log.Error("Failed to remove update", e); - } - } - - /// - /// Dismisses the updates in the given list i.e. they are added in the - /// other_config list of each pool and removed from the Updates.UpdateAlerts list. - /// - public static void DismissUpdates(List toBeDismissed) - { - if (toBeDismissed.Count == 0) - return; - - foreach(IXenConnection connection in ConnectionsManager.XenConnectionsCopy) - { - if (!Alert.AllowedToDismiss(connection)) - continue; - - Pool pool = Helpers.GetPoolOfOne(connection); - if (pool == null) - continue; - - Dictionary other_config = pool.other_config; - - foreach (Alert alert in toBeDismissed) - { - if (alert is XenServerPatchAlert patchAlert) - { - if (other_config.ContainsKey(IgnorePatchKey)) - { - List current = new List(other_config[IgnorePatchKey].Split(',')); - if (current.Contains(patchAlert.Patch.Uuid, StringComparer.OrdinalIgnoreCase)) - continue; - current.Add(patchAlert.Patch.Uuid); - other_config[IgnorePatchKey] = string.Join(",", current.ToArray()); - } - else - { - other_config.Add(IgnorePatchKey, patchAlert.Patch.Uuid); - } - } - - if (alert is XenServerVersionAlert versionAlert) - { - - if (other_config.ContainsKey(LAST_SEEN_SERVER_VERSION_KEY)) - { - List current = new List(other_config[LAST_SEEN_SERVER_VERSION_KEY].Split(',')); - if (current.Contains(versionAlert.Version.Version.ToString())) - continue; - current.Add(versionAlert.Version.Version.ToString()); - other_config[LAST_SEEN_SERVER_VERSION_KEY] = string.Join(",", current.ToArray()); - } - else - { - other_config.Add(LAST_SEEN_SERVER_VERSION_KEY, versionAlert.Version.Version.ToString()); - } - } - - RemoveUpdate(alert); - } - - Pool.set_other_config(connection.Session, pool.opaque_ref, other_config); - } - } - - private static Alert FindUpdate(Predicate predicate) { lock (updateAlertsLock) - return updateAlerts.Find(predicate); - } + updateAlerts.Remove(update); + UpdateAlertCollectionChanged?.Invoke(new CollectionChangeEventArgs(CollectionChangeAction.Remove, update)); + } /// /// If AutomaticCheck is enabled it checks for updates regardless the @@ -270,46 +181,25 @@ namespace XenAdmin.Core return action.Succeeded; } - public static string CheckForUpdatesUrl => Registry.CustomUpdatesXmlLocation ?? BrandManager.UpdatesUrl; - private static void actionCompleted(ActionBase sender) { Program.AssertOffEventThread(); - DownloadUpdatesXmlAction action = sender as DownloadUpdatesXmlAction; - if (action == null) + if (!(sender is DownloadUpdatesXmlAction action)) return; bool succeeded = action.Succeeded; string errorMessage = string.Empty; - lock (updateAlertsLock) - updateAlerts.Clear(); - if (succeeded) { lock (downloadedUpdatesLock) { XenCenterVersions = action.XenCenterVersions; - XenServerVersionsForAutoCheck = action.XenServerVersionsForAutoCheck; - XenServerVersions = action.XenServerVersions; - XenServerPatches = action.XenServerPatches; } - - var xenCenterAlerts = NewXenCenterUpdateAlerts(XenCenterVersions, Program.Version); - if (xenCenterAlerts != null) - updateAlerts.AddRange(xenCenterAlerts.Where(a=>!a.IsDismissed())); - - var xenServerUpdateAlerts = NewXenServerVersionAlerts(XenServerVersionsForAutoCheck); - if (xenServerUpdateAlerts != null) - updateAlerts.AddRange(xenServerUpdateAlerts.Where(a=>!a.CanIgnore)); - - var xenServerPatchAlerts = NewXenServerPatchAlerts(XenServerVersions, XenServerPatches); - if (xenServerPatchAlerts != null) - updateAlerts.AddRange(xenServerPatchAlerts.Where(alert => !alert.CanIgnore)); } else { @@ -332,29 +222,37 @@ namespace XenAdmin.Core errorMessage = Messages.AVAILABLE_UPDATES_INTERNAL_ERROR; } - if (CheckForUpdatesCompleted != null) - CheckForUpdatesCompleted(succeeded, errorMessage); + lock (updateAlertsLock) + { + updateAlerts.Clear(); + + if (succeeded) + { + var xenCenterAlerts = NewXenCenterUpdateAlerts(XenCenterVersions, Program.Version); + updateAlerts.AddRange(xenCenterAlerts.Where(a => !a.IsDismissed())); + + var xenServerUpdateAlerts = NewXenServerVersionAlerts(XenServerVersionsForAutoCheck); + updateAlerts.AddRange(xenServerUpdateAlerts.Where(a => !a.CanIgnore)); + + var xenServerPatchAlerts = NewXenServerPatchAlerts(XenServerVersions, XenServerPatches); + updateAlerts.AddRange(xenServerPatchAlerts.Where(a => !a.CanIgnore)); + } + } + + UpdateAlertCollectionChanged?.Invoke(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, UpdateAlerts)); + + CheckForUpdatesCompleted?.Invoke(succeeded, errorMessage); } - - public static void RegisterCollectionChanged(CollectionChangeEventHandler handler) - { - updateAlerts.CollectionChanged += handler; - } - - public static void DeregisterCollectionChanged(CollectionChangeEventHandler handler) - { - updateAlerts.CollectionChanged -= handler; - } - - public static List NewXenCenterUpdateAlerts(List xenCenterVersions, Version currentProgramVersion) { if (Helpers.CommonCriteriaCertificationRelease) - return null; + return new List(); + var alerts = new List(); XenCenterVersion latest = null, latestCr = null; + if (xenCenterVersions.Count != 0 && currentProgramVersion != new Version(0, 0, 0, 0)) { var latestVersions = from v in xenCenterVersions where v.Latest select v; @@ -395,7 +293,7 @@ namespace XenAdmin.Core List xenServerPatches) { if (Helpers.CommonCriteriaCertificationRelease) - return null; + return new List(); var alerts = new List(); @@ -778,7 +676,7 @@ namespace XenAdmin.Core public static List NewXenServerVersionAlerts(List xenServerVersions) { if (Helpers.CommonCriteriaCertificationRelease) - return null; + return new List(); var latestVersion = xenServerVersions.FindAll(item => item.Latest).OrderByDescending(v => v.Version).FirstOrDefault(); var latestCrVersion = xenServerVersions.FindAll(item => item.LatestCr).OrderByDescending(v => v.Version).FirstOrDefault(); @@ -840,38 +738,54 @@ namespace XenAdmin.Core return serverVersions; } - public static void CheckServerVersion() + public static void RefreshUpdateAlerts(UpdateType flags) { - var alerts = NewXenServerVersionAlerts(XenServerVersionsForAutoCheck); - if (alerts == null) - return; + var alerts = new List(); - alerts.ForEach(CheckUpdate); - } + if (flags.HasFlag(UpdateType.ServerVersion)) + alerts.AddRange(NewXenServerVersionAlerts(XenServerVersionsForAutoCheck)); - public static void CheckServerPatches() - { - var alerts = NewXenServerPatchAlerts(XenServerVersions, XenServerPatches); - if (alerts == null) - return; + if (flags.HasFlag(UpdateType.ServerPatches)) + alerts.AddRange(NewXenServerPatchAlerts(XenServerVersions, XenServerPatches)); - alerts.ForEach(CheckUpdate); - } + bool changed = false; - private static void CheckUpdate(XenServerUpdateAlert alert) - { - var existingAlert = FindUpdate(a => a.Equals(alert)); - - if (existingAlert != null && alert.CanIgnore) - RemoveUpdate(existingAlert); - else if (existingAlert is XenServerUpdateAlert updAlert) + try { - RemoveUpdate(updAlert); - updAlert.CopyConnectionsAndHosts(alert); - AddUpdate(updAlert); + lock (updateAlertsLock) + { + foreach (var alert in alerts) + { + var existingAlert = updateAlerts.FirstOrDefault(a => a.Equals(alert)); + + if (existingAlert != null && alert.CanIgnore) + { + updateAlerts.Remove(existingAlert); + changed = true; + } + else if (existingAlert is XenServerUpdateAlert updAlert) + { + updateAlerts.Remove(updAlert); + updAlert.CopyConnectionsAndHosts(alert); + if (!updateAlerts.Contains(updAlert)) + updateAlerts.Add(updAlert); + changed = true; + } + else if (!alert.CanIgnore && !updateAlerts.Contains(alert)) + { + updateAlerts.Add(alert); + changed = true; + } + } + } + + if (changed) + UpdateAlertCollectionChanged?.Invoke(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, UpdateAlerts)); + } + catch (Exception e) + { + log.Error("Failed to refresh the updates", e); } - else if (!alert.CanIgnore) - AddUpdate(alert); } public static void RestoreDismissedUpdates() @@ -883,8 +797,7 @@ namespace XenAdmin.Core var action = new ParallelAction(Messages.RESTORE_DISMISSED_UPDATES, Messages.RESTORING, Messages.COMPLETED, actions, true, false); action.Completed += action_Completed; - if (RestoreDismissedUpdatesStarted != null) - RestoreDismissedUpdatesStarted(); + RestoreDismissedUpdatesStarted?.Invoke(); action.RunAsync(); } @@ -902,7 +815,7 @@ namespace XenAdmin.Core private static XenServerPatchAlert FindPatchAlert(Predicate predicate) { - var existingAlert = FindUpdate(a => a is XenServerPatchAlert patchAlert && predicate(patchAlert.Patch)); + var existingAlert = UpdateAlerts.FirstOrDefault(a => a is XenServerPatchAlert patchAlert && predicate(patchAlert.Patch)); if (existingAlert != null) return existingAlert as XenServerPatchAlert; @@ -991,5 +904,14 @@ namespace XenAdmin.Core Alert.RemoveAlert(a => a is HotfixEligibilityAlert); Alert.AddAlertRange(alerts); } + + [Flags] + public enum UpdateType : short + { + None = 0, + ServerPatches = 1, + ServerVersion = 2, + XenCenterVersion = 4 + } } } diff --git a/XenAdmin/MainWindow.cs b/XenAdmin/MainWindow.cs index 452a04a34..ca4355d47 100755 --- a/XenAdmin/MainWindow.cs +++ b/XenAdmin/MainWindow.cs @@ -253,7 +253,7 @@ namespace XenAdmin //ClipboardViewer is registered in OnHandleCreated OtherConfigAndTagsWatcher.RegisterEventHandlers(); Alert.RegisterAlertCollectionChanged(XenCenterAlerts_CollectionChanged); - Updates.RegisterCollectionChanged(Updates_CollectionChanged); + Updates.UpdateAlertCollectionChanged += Updates_CollectionChanged; ConnectionsManager.History.CollectionChanged += History_CollectionChanged; //ConnectionsManager.XenConnections.CollectionChanged is registered in OnShown Properties.Settings.Default.SettingChanging += Default_SettingChanging; @@ -266,7 +266,7 @@ namespace XenAdmin Clip.UnregisterClipboardViewer(); OtherConfigAndTagsWatcher.DeregisterEventHandlers(); Alert.DeregisterAlertCollectionChanged(XenCenterAlerts_CollectionChanged); - Updates.DeregisterCollectionChanged(Updates_CollectionChanged); + Updates.UpdateAlertCollectionChanged -= Updates_CollectionChanged; ConnectionsManager.History.CollectionChanged -= History_CollectionChanged; ConnectionsManager.XenConnections.CollectionChanged -= XenConnection_CollectionChanged; Properties.Settings.Default.SettingChanging -= Default_SettingChanging; @@ -873,8 +873,7 @@ namespace XenAdmin { CloseActiveWizards(connection); Alert.RemoveAlert(alert => alert.Connection != null && alert.Connection.Equals(connection)); - Updates.CheckServerPatches(); - Updates.CheckServerVersion(); + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches | Updates.UpdateType.ServerVersion); RequestRefreshTreeView(); } @@ -996,9 +995,8 @@ namespace XenAdmin ThreadPool.QueueUserWorkItem(CheckHealthCheckEnrollment, connection); ThreadPool.QueueUserWorkItem(HealthCheck.CheckForAnalysisResults, connection); ThreadPool.QueueUserWorkItem(InformHealthCheckEnrollment, connection); - - Updates.CheckServerPatches(); - Updates.CheckServerVersion(); + + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches | Updates.UpdateType.ServerVersion); Updates.CheckHotfixEligibility(connection); HealthCheck.SendMetadataToHealthCheck(); @@ -1122,8 +1120,7 @@ namespace XenAdmin // other_config may contain HideFromXenCenter UpdateToolbars(); // other_config contains which patches to ignore - Updates.CheckServerPatches(); - Updates.CheckServerVersion(); + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches | Updates.UpdateType.ServerVersion); break; case "name_label": @@ -1169,17 +1166,11 @@ namespace XenAdmin case "patches": if (!Helpers.ElyOrGreater(host)) - { - Updates.CheckServerPatches(); - Updates.CheckServerVersion(); - } + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches | Updates.UpdateType.ServerVersion); break; case "updates": if (Helpers.ElyOrGreater(host)) - { - Updates.CheckServerPatches(); - Updates.CheckServerVersion(); - } + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches | Updates.UpdateType.ServerVersion); break; } } @@ -2571,11 +2562,11 @@ namespace XenAdmin navigationPane.SelectObject(obj); } - private void Updates_CollectionChanged(object sender, CollectionChangeEventArgs e) + private void Updates_CollectionChanged(CollectionChangeEventArgs e) { Program.Invoke(this, () => { - int updatesCount = Updates.UpdateAlertsCount; + int updatesCount = Updates.UpdateAlerts.Count; navigationPane.UpdateNotificationsButton(NotificationsSubMode.Updates, updatesCount); statusLabelUpdates.Text = string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_STATUS, updatesCount); diff --git a/XenAdmin/TabPages/AlertSummaryPage.cs b/XenAdmin/TabPages/AlertSummaryPage.cs index fd089a9de..b6f72b922 100644 --- a/XenAdmin/TabPages/AlertSummaryPage.cs +++ b/XenAdmin/TabPages/AlertSummaryPage.cs @@ -522,7 +522,7 @@ namespace XenAdmin.TabPages } } - DismissAlerts(new List {(Alert) clickedRow.Tag}); + DismissAlerts((Alert)clickedRow.Tag); } private void tsmiDismissAll_Click(object sender, EventArgs e) @@ -559,7 +559,7 @@ namespace XenAdmin.TabPages return; var alerts = result == DialogResult.No - ? (from DataGridViewRow row in GridViewAlerts.Rows select row.Tag as Alert) + ? (from DataGridViewRow row in GridViewAlerts.Rows select row.Tag as Alert).ToArray() : Alert.Alerts; DismissAlerts(alerts); @@ -588,7 +588,7 @@ namespace XenAdmin.TabPages if (GridViewAlerts.SelectedRows.Count > 0) { var selectedAlerts = from DataGridViewRow row in GridViewAlerts.SelectedRows select row.Tag as Alert; - DismissAlerts(selectedAlerts); + DismissAlerts(selectedAlerts.ToArray()); } } @@ -621,7 +621,7 @@ namespace XenAdmin.TabPages { toolStripButtonExportAll.Enabled = Alert.NonDismissingAlertCount > 0; - tsmiDismissAll.Enabled = Alert.AllowedToDismiss(Alert.Alerts); + tsmiDismissAll.Enabled = Alert.Alerts.Any(a => a.AllowedToDismiss()); tsmiDismissAll.AutoToolTip = !tsmiDismissAll.Enabled; tsmiDismissAll.ToolTipText = tsmiDismissAll.Enabled ? string.Empty @@ -629,16 +629,25 @@ namespace XenAdmin.TabPages ? Messages.DELETE_ANY_MESSAGE_RBAC_BLOCKED : Messages.NO_MESSAGES_TO_DISMISS; - var selectedAlerts = from DataGridViewRow row in GridViewAlerts.SelectedRows - select row.Tag as Alert; + var selectedAlerts = (from DataGridViewRow row in GridViewAlerts.SelectedRows + select row.Tag as Alert).ToArray(); - tsmiDismissSelected.Enabled = Alert.AllowedToDismiss(selectedAlerts); + tsmiDismissSelected.Enabled = selectedAlerts.Any(a => a.AllowedToDismiss()); tsmiDismissSelected.AutoToolTip = !tsmiDismissSelected.Enabled; tsmiDismissSelected.ToolTipText = tsmiDismissSelected.Enabled ? string.Empty : Messages.DELETE_MESSAGE_RBAC_BLOCKED; toolStripSplitButtonDismiss.Enabled = tsmiDismissAll.Enabled || tsmiDismissSelected.Enabled; + toolStripSplitButtonDismiss.AutoToolTip = tsmiDismissAll.AutoToolTip || tsmiDismissSelected.AutoToolTip; + + if (toolStripSplitButtonDismiss.AutoToolTip) + { + if (!string.IsNullOrEmpty(tsmiDismissAll.ToolTipText)) + toolStripSplitButtonDismiss.ToolTipText = tsmiDismissAll.ToolTipText; + else if (!string.IsNullOrEmpty(tsmiDismissSelected.ToolTipText)) + toolStripSplitButtonDismiss.ToolTipText = tsmiDismissSelected.ToolTipText; + } if (toolStripSplitButtonDismiss.DefaultItem != null && !toolStripSplitButtonDismiss.DefaultItem.Enabled) { @@ -656,23 +665,20 @@ namespace XenAdmin.TabPages #region Alert dismissal - private void DismissAlerts(IEnumerable alerts) + private void DismissAlerts(params Alert[] alerts) { var groups = from Alert alert in alerts - where alert != null && !alert.Dismissing + where alert != null && alert.AllowedToDismiss() group alert by alert.Connection into g select new { Connection = g.Key, Alerts = g }; foreach (var g in groups) { - if (Alert.AllowedToDismiss(g.Connection)) - { - foreach (var alert in g.Alerts) - alert.Dismissing = true; - Rebuild(); - new DeleteAllAlertsAction(g.Connection, g.Alerts).RunAsync(); - } + foreach (var alert in g.Alerts) + alert.Dismissing = true; + + new DeleteAllAlertsAction(g.Alerts.ToList(), g.Connection).RunAsync(); } } @@ -682,7 +688,7 @@ namespace XenAdmin.TabPages { var items = new List(); - if (Alert.AllowedToDismiss(alert)) + if (alert.AllowedToDismiss()) { var dismiss = new ToolStripMenuItem(Messages.ALERT_DISMISS); dismiss.Click += ToolStripMenuItemDismiss_Click; @@ -797,8 +803,7 @@ namespace XenAdmin.TabPages { foreach (DataGridViewRow row in GridViewAlerts.Rows) { - var a = row.Tag as Alert; - if (a != null && !a.Dismissing) + if (row.Tag is Alert a && !a.Dismissing) stream.WriteLine(a.GetAlertDetailsCSVQuotes()); } } diff --git a/XenAdmin/TabPages/ManageUpdatesPage.cs b/XenAdmin/TabPages/ManageUpdatesPage.cs index d4cbfc61c..0504c6efa 100644 --- a/XenAdmin/TabPages/ManageUpdatesPage.cs +++ b/XenAdmin/TabPages/ManageUpdatesPage.cs @@ -70,7 +70,6 @@ namespace XenAdmin.TabPages InitializeComponent(); spinner.SuccessImage = SystemIcons.Information.ToBitmap(); tableLayoutPanel1.Visible = false; - UpdateButtonEnablement(); toolStripSplitButtonDismiss.DefaultItem = dismissAllToolStripMenuItem; toolStripSplitButtonDismiss.Text = dismissAllToolStripMenuItem.Text; @@ -86,6 +85,8 @@ namespace XenAdmin.TabPages { checksQueue--; } + + UpdateButtonEnablement(); } #region NotificationPage overrides @@ -99,7 +100,7 @@ namespace XenAdmin.TabPages protected override void RegisterEventHandlers() { - Updates.RegisterCollectionChanged(UpdatesCollectionChanged); + Updates.UpdateAlertCollectionChanged += UpdatesCollectionChanged; Updates.RestoreDismissedUpdatesStarted += Updates_RestoreDismissedUpdatesStarted; Updates.CheckForUpdatesStarted += CheckForUpdates_CheckForUpdatesStarted; Updates.CheckForUpdatesCompleted += CheckForUpdates_CheckForUpdatesCompleted; @@ -107,7 +108,7 @@ namespace XenAdmin.TabPages protected override void DeregisterEventHandlers() { - Updates.DeregisterCollectionChanged(UpdatesCollectionChanged); + Updates.UpdateAlertCollectionChanged -= UpdatesCollectionChanged; Updates.RestoreDismissedUpdatesStarted -= Updates_RestoreDismissedUpdatesStarted; Updates.CheckForUpdatesStarted -= CheckForUpdates_CheckForUpdatesStarted; Updates.CheckForUpdatesCompleted -= CheckForUpdates_CheckForUpdatesCompleted; @@ -117,12 +118,12 @@ namespace XenAdmin.TabPages #endregion - private void UpdatesCollectionChanged(object sender, CollectionChangeEventArgs e) + private void UpdatesCollectionChanged(CollectionChangeEventArgs e) { switch (e.Action) { - case CollectionChangeAction.Add: - Rebuild(); // rebuild entire alert list to ensure filtering and sorting + case CollectionChangeAction.Refresh: + Rebuild(); break; case CollectionChangeAction.Remove: if (e.Element is Alert a) @@ -422,7 +423,7 @@ namespace XenAdmin.TabPages { // versions with no minimum patches var updatesList = new List(); - var alerts = new List(Updates.UpdateAlerts); + var alerts = Updates.UpdateAlerts; if (alerts.Count == 0) return String.Empty; @@ -581,7 +582,7 @@ namespace XenAdmin.TabPages ToggleCentreWarningVisibility(); - var updates = new List(Updates.UpdateAlerts); + var updates = Updates.UpdateAlerts; if (updates.Count == 0) return; @@ -610,7 +611,7 @@ namespace XenAdmin.TabPages private void ToggleCentreWarningVisibility() { - if (byUpdateToolStripMenuItem.Checked && Updates.UpdateAlertsCount == 0) + if (byUpdateToolStripMenuItem.Checked && Updates.UpdateAlerts.Count == 0) { spinner.ShowSuccessImage(); labelProgress.Text = Messages.AVAILABLE_UPDATES_NOT_FOUND; @@ -691,7 +692,29 @@ namespace XenAdmin.TabPages { if (byUpdateToolStripMenuItem.Checked) { - toolStripButtonExportAll.Enabled = toolStripSplitButtonDismiss.Enabled = Updates.UpdateAlertsCount > 0; + var allAlerts = Updates.UpdateAlerts; + toolStripButtonExportAll.Enabled = allAlerts.Count > 0; + + dismissSelectedToolStripMenuItem.Enabled = (from DataGridViewRow row in dataGridViewUpdates.SelectedRows + select row.Tag as Alert).Any(a => a.AllowedToDismiss()); + + dismissAllToolStripMenuItem.Enabled = allAlerts.Any(a => a.AllowedToDismiss()); + toolStripSplitButtonDismiss.Enabled = dismissAllToolStripMenuItem.Enabled || dismissSelectedToolStripMenuItem.Enabled; + + if (toolStripSplitButtonDismiss.DefaultItem != null && !toolStripSplitButtonDismiss.DefaultItem.Enabled) + { + foreach (ToolStripItem item in toolStripSplitButtonDismiss.DropDownItems) + { + if (item.Enabled) + { + toolStripSplitButtonDismiss.DefaultItem = item; + toolStripSplitButtonDismiss.Text = item.Text; + break; + } + } + } + + ShowInformationHelper(); } else { @@ -700,8 +723,19 @@ namespace XenAdmin.TabPages } } - private void ShowInformationHelper(string reason) + private void ShowInformationHelper() { + string reason = null; + + foreach (DataGridViewRow row in dataGridViewUpdates.SelectedRows) + { + if (row.Tag is XenServerPatchAlert alert) + { + reason = alert.CannotApplyReason; + break; + } + } + if (string.IsNullOrEmpty(reason)) { tableLayoutPanel1.Visible = false; @@ -758,25 +792,22 @@ namespace XenAdmin.TabPages { var items = new List(); - var patchAlert = alert as XenServerPatchAlert; - - if (Alert.AllowedToDismiss(alert)) + if (alert.AllowedToDismiss()) { var dismiss = new ToolStripMenuItem(Messages.ALERT_DISMISS); dismiss.Click += ToolStripMenuItemDismiss_Click; items.Add(dismiss); } - if (patchAlert != null && patchAlert.CanApply && !string.IsNullOrEmpty(patchAlert.Patch.PatchUrl) && patchAlert.RequiredXenCenterVersion == null) + if (alert is XenServerPatchAlert patchAlert && patchAlert.CanApply && + !string.IsNullOrEmpty(patchAlert.Patch.PatchUrl) && patchAlert.RequiredXenCenterVersion == null) { var download = new ToolStripMenuItem(Messages.UPDATES_DOWNLOAD_AND_INSTALL); download.Click += ToolStripMenuItemDownload_Click; items.Add(download); } - var updateAlert = alert as XenServerUpdateAlert; - - if (updateAlert != null && updateAlert.RequiredXenCenterVersion != null) + if (alert is XenServerUpdateAlert updateAlert && updateAlert.RequiredXenCenterVersion != null) { var downloadNewXenCenter = new ToolStripMenuItem(Messages.UPDATES_DOWNLOAD_REQUIRED_XENCENTER); downloadNewXenCenter.Click += ToolStripMenuItemDownloadNewXenCenter_Click; @@ -803,28 +834,17 @@ namespace XenAdmin.TabPages #region Update dismissal - private void DismissUpdates(IEnumerable alerts) + private void DismissUpdates(List alerts) { - var groups = from Alert alert in alerts - where alert != null && !alert.Dismissing - group alert by alert.Connection - into g - select new { Connection = g.Key, Alerts = g }; + var filtered = alerts.Where(a => a.AllowedToDismiss()).ToList(); - foreach (var g in groups) - { - if (Alert.AllowedToDismiss(g.Connection)) - { - foreach (Alert alert in g.Alerts) - { - alert.Dismissing = true; - } - toolStripButtonRestoreDismissed.Enabled = false; - DeleteAllAlertsAction action = new DeleteAllAlertsAction(g.Connection, g.Alerts); - action.Completed += DeleteAllAlertsAction_Completed; - action.RunAsync(); - } - } + foreach (Alert alert in filtered) + alert.Dismissing = true; + + toolStripButtonRestoreDismissed.Enabled = false; + var action = new DeleteAllAlertsAction(filtered); + action.Completed += DeleteAllAlertsAction_Completed; + action.RunAsync(); } /// @@ -890,7 +910,7 @@ namespace XenAdmin.TabPages return; var alerts = result == DialogResult.No - ? from DataGridViewRow row in dataGridViewUpdates.Rows select row.Tag as Alert + ? (from DataGridViewRow row in dataGridViewUpdates.Rows select row.Tag as Alert).ToList() : Updates.UpdateAlerts; DismissUpdates(alerts); @@ -923,7 +943,7 @@ namespace XenAdmin.TabPages if (dataGridViewUpdates.SelectedRows.Count > 0) { var selectedAlerts = from DataGridViewRow row in dataGridViewUpdates.SelectedRows select row.Tag as Alert; - DismissUpdates(selectedAlerts); + DismissUpdates(selectedAlerts.ToList()); } } @@ -961,7 +981,7 @@ namespace XenAdmin.TabPages } } - DismissUpdates(new List { (Alert)clickedRow.Tag }); + DismissUpdates(new List {(Alert)clickedRow.Tag}); } private DataGridViewRow FindAlertRow(ToolStripMenuItem toolStripMenuItem) @@ -1071,17 +1091,10 @@ namespace XenAdmin.TabPages private void dataGridViewUpdates_SelectionChanged(object sender, EventArgs e) { - string reason = null; + if (_buildInProgress) + return; - if (dataGridViewUpdates.SelectedRows.Count > 0) - { - var alert = dataGridViewUpdates.SelectedRows[0].Tag as XenServerPatchAlert; - - if (alert != null) - reason = alert.CannotApplyReason; - } - - ShowInformationHelper(reason); + UpdateButtonEnablement(); } private void dataGridViewUpdates_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) @@ -1249,15 +1262,15 @@ namespace XenAdmin.TabPages if (exportAll) { - foreach (Alert a in Updates.UpdateAlerts) + var alerts = Updates.UpdateAlerts; + foreach (Alert a in alerts) stream.WriteLine(a.GetUpdateDetailsCSVQuotes()); } else { foreach (DataGridViewRow row in dataGridViewUpdates.Rows) { - var a = row.Tag as Alert; - if (a != null) + if (row.Tag is Alert a) stream.WriteLine(a.GetUpdateDetailsCSVQuotes()); } } diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs index 21d4e0851..f39fd0d2c 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs @@ -250,7 +250,7 @@ namespace XenAdmin.Wizards.PatchingWizard { CleanUploadedPatches(); RemoveDownloadedPatches(); - Updates.CheckServerPatches(); + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches); base.FinishWizard(); } diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectPatchPage.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectPatchPage.cs index 0e17e8ae1..033b0a543 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectPatchPage.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectPatchPage.cs @@ -364,7 +364,7 @@ namespace XenAdmin.Wizards.PatchingWizard { try { - var updates = Updates.UpdateAlerts.ToList(); + var updates = Updates.UpdateAlerts; if (dataGridViewPatches.SortedColumn != null) { @@ -484,7 +484,7 @@ namespace XenAdmin.Wizards.PatchingWizard private void _backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { - Updates.CheckServerPatches(); + Updates.RefreshUpdateAlerts(Updates.UpdateType.ServerPatches); } private void _backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) diff --git a/XenModel/Actions/Message/DestroyMessageAction.cs b/XenModel/Actions/Message/DestroyMessageAction.cs index a24973c25..fd9ac0c43 100644 --- a/XenModel/Actions/Message/DestroyMessageAction.cs +++ b/XenModel/Actions/Message/DestroyMessageAction.cs @@ -29,24 +29,35 @@ * SUCH DAMAGE. */ -using XenAdmin.Network; using XenAPI; namespace XenAdmin.Actions { public class DestroyMessageAction : PureAsyncAction { - private readonly string OpaqueRef; + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public DestroyMessageAction(IXenConnection connection, string messageopaqueref) - : base(connection, "destroying message", string.Format("message opaque_ref = {0}", messageopaqueref), true) + private readonly string _opaqueRef; + + public DestroyMessageAction(Message message) + : base(message.Connection, "destroying message", string.Format("message opaque_ref = {0}", message.opaque_ref), true) { - OpaqueRef = messageopaqueref; + _opaqueRef = message.opaque_ref; } protected override void Run() { - Message.destroy(Session, OpaqueRef); + try + { + Message.destroy(Session, _opaqueRef); + } + catch (Failure exn) + { + if (exn.ErrorDescription[0] != Failure.HANDLE_INVALID) + throw; + + log.Error(exn); + } } } } diff --git a/XenModel/Alerts/Types/Alert.cs b/XenModel/Alerts/Types/Alert.cs index 3c288dd8f..4d8084a3a 100644 --- a/XenModel/Alerts/Types/Alert.cs +++ b/XenModel/Alerts/Types/Alert.cs @@ -216,24 +216,14 @@ namespace XenAdmin.Alerts /// public DateTime Timestamp => _timestamp; - /// - /// Dismisses the Alert: marks it as dealt with in some way. May only be called once. - /// public virtual void Dismiss() { RemoveAlert(this); } - /// - /// Dismiss the alert, making a single API call if this is a remote message (Dismiss will launch a complete - /// action). - /// - /// The normal behaviour here is the same as Dismiss() -- it's only when overridden by MessageAlert that there - /// is a difference. - /// - public virtual void DismissSingle(Session s) + public virtual bool AllowedToDismiss() { - Dismiss(); + return !Dismissing; } public virtual bool IsDismissed() @@ -278,7 +268,7 @@ namespace XenAdmin.Alerts /// public abstract string HelpID { get; } - public IXenConnection Connection; + public IXenConnection Connection { get; protected set; } public virtual bool Equals(Alert other) { @@ -358,52 +348,8 @@ namespace XenAdmin.Alerts sortResult = string.Compare(alert1.uuid, alert2.uuid); return sortResult; } - - - #region Update dismissal - - public static bool AllowedToDismiss(Alert alert) - { - return AllowedToDismiss(new[] { alert }); - } - - public static bool AllowedToDismiss(IEnumerable alerts) - { - var alertConnections = (from Alert alert in alerts - where alert != null && !alert.Dismissing - let con = alert.Connection - select con).Distinct(); - - return alertConnections.Any(AllowedToDismiss); - } - - /// - /// Checks the user has sufficient RBAC privileges to clear updates on a given connection - /// - public static bool AllowedToDismiss(IXenConnection c) - { - // check if local alert - if (c == null) - return true; - - // have we disconnected? Alert will disappear soon, but for now block dismissal. - if (c.Session == null) - return false; - - if (c.Session.IsLocalSuperuser) - return true; - - List rolesAbleToCompleteAction = Role.ValidRoleList("Message.destroy", c); - foreach (Role possibleRole in rolesAbleToCompleteAction) - { - if (c.Session.Roles.Contains(possibleRole)) - return true; - } - return false; - } - - #endregion } + public enum AlertPriority { /// diff --git a/XenModel/Messages.Designer.cs b/XenModel/Messages.Designer.cs index e7951e550..f50865a04 100755 --- a/XenModel/Messages.Designer.cs +++ b/XenModel/Messages.Designer.cs @@ -11954,7 +11954,7 @@ namespace XenAdmin { } /// - /// Looks up a localized string similar to There are no alerts remaining which you have permission to dismiss.. + /// Looks up a localized string similar to You have no permission to dismiss the selected alerts.. /// public static string DELETE_MESSAGE_RBAC_BLOCKED { get { diff --git a/XenModel/Messages.resx b/XenModel/Messages.resx index 2733c5db4..7a302f535 100755 --- a/XenModel/Messages.resx +++ b/XenModel/Messages.resx @@ -4278,7 +4278,7 @@ This will also delete its subfolders. Are you sure you want to delete '{0}'? This operation cannot be undone. - There are no alerts remaining which you have permission to dismiss. + You have no permission to dismiss the selected alerts. Delete Patch