2013-06-24 13:41:48 +02:00
/ * Copyright ( c ) Citrix Systems Inc .
* All rights reserved .
*
* Redistribution and use in source and binary forms ,
* with or without modification , are permitted provided
* that the following conditions are met :
*
* * Redistributions of source code must retain the above
* copyright notice , this list of conditions and the
* following disclaimer .
* * Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the
* following disclaimer in the documentation and / or other
* materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ,
* INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Drawing ;
using System.Linq ;
using System.Text ;
using System.Windows.Forms ;
2013-07-18 14:56:40 +02:00
using XenAdmin.Controls ;
2013-06-24 13:41:48 +02:00
using XenAdmin.Core ;
2013-08-30 13:46:28 +02:00
using XenAdmin.Dialogs ;
2013-06-24 13:41:48 +02:00
using XenAdmin.Network ;
using XenAPI ;
using XenAdmin.Alerts ;
using XenAdmin.Help ;
using System.Threading ;
using XenAdmin.Actions ;
using System.IO ;
2013-08-30 13:46:28 +02:00
namespace XenAdmin.TabPages
2013-06-24 13:41:48 +02:00
{
2013-08-30 13:46:28 +02:00
public partial class AlertSummaryPage : UserControl
2013-06-24 13:41:48 +02:00
{
private static readonly log4net . ILog log = log4net . LogManager . GetLogger ( System . Reflection . MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
private static readonly int ALERT_CAP = 1000 ;
2013-07-03 14:00:24 +02:00
private readonly CollectionChangeEventHandler m_alertCollectionChangedWithInvoke ;
Dictionary < string , bool > expandedState = new Dictionary < string , bool > ( ) ;
private bool inAlertBuild ;
private bool retryAlertBuild ;
2013-08-30 13:46:28 +02:00
public AlertSummaryPage ( )
2013-06-24 13:41:48 +02:00
{
InitializeComponent ( ) ;
GridViewAlerts . Sort ( ColumnDate , ListSortDirection . Descending ) ;
LabelCappingEntries . Text = String . Format ( Messages . ALERT_CAP_LABEL , ALERT_CAP ) ;
GridViewAlerts . ScrollBars = ScrollBars . Vertical ;
UpdateActionEnablement ( ) ;
2013-07-03 14:00:24 +02:00
m_alertCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( AlertsCollectionChanged ) ;
2013-11-21 12:57:57 +01:00
Alert . RegisterAlertCollectionChanged ( m_alertCollectionChangedWithInvoke ) ;
2013-07-03 14:00:24 +02:00
2013-07-11 19:20:18 +02:00
toolStripSplitButtonDismiss . DefaultItem = tsmiDismissAll ;
toolStripSplitButtonDismiss . Text = tsmiDismissAll . Text ;
2013-06-24 13:41:48 +02:00
}
2013-08-30 13:46:28 +02:00
public void RefreshAlertList ( )
2013-06-24 13:41:48 +02:00
{
2013-08-13 11:15:52 +02:00
toolStripDropDownButtonServerFilter . InitializeHostList ( ) ;
toolStripDropDownButtonServerFilter . BuildFilterList ( ) ;
2013-06-24 13:41:48 +02:00
Rebuild ( ) ;
}
2013-07-03 12:10:21 +02:00
private void SetFilterLabel ( )
{
2013-08-14 17:59:25 +02:00
toolStripLabelFiltersOnOff . Text = FilterIsOn
2013-07-03 12:10:21 +02:00
? Messages . FILTERS_ON
: Messages . FILTERS_OFF ;
}
2013-06-24 13:41:48 +02:00
2013-08-14 17:59:25 +02:00
private bool FilterIsOn
{
get
{
return toolStripDropDownButtonDateFilter . FilterIsOn
| | toolStripDropDownButtonServerFilter . FilterIsOn
| | toolStripDropDownSeveritiesFilter . FilterIsOn ;
}
}
2013-06-24 13:41:48 +02:00
#region AlertListCode
private void Rebuild ( )
{
2014-04-28 16:04:23 +02:00
if ( ! Visible )
return ;
2013-06-24 13:41:48 +02:00
log . Debug ( "Rebuilding alertList" ) ;
Thread t = new Thread ( _Rebuild ) ;
t . Name = "Building alert list" ;
t . IsBackground = true ;
t . Start ( ) ;
}
private void _Rebuild ( )
{
log . Debug ( "Rebuilding alertList: Starting background thread" ) ;
Program . AssertOffEventThread ( ) ;
lock ( GridViewAlerts )
{
if ( inAlertBuild )
{
// queue up a rebuild after the current one has completed
log . Debug ( "Rebuilding alertList: In build already, exiting" ) ;
retryAlertBuild = true ;
return ;
}
inAlertBuild = true ;
log . Debug ( "Rebuilding alertList: taking inAlertBuild lock" ) ;
}
try
{
// 1) Add all the alerts that have not been filtered out to an array
// 2) Create rows for each of these
// 3) Sort them
// 4) Take the top n as set by the filters
// 5) Add them to the control using the optimized AddRange()
2013-07-03 12:10:21 +02:00
Program . Invoke ( this , SetFilterLabel ) ;
2013-06-24 13:41:48 +02:00
List < Alert > alerts = Alert . NonDismissingAlerts ;
2013-07-12 12:07:10 +02:00
alerts . RemoveAll ( FilterAlert ) ;
2013-06-24 13:41:48 +02:00
log . DebugFormat ( "Rebuilding alertList: there are {0} alerts in total. After filtering we have {1}" ,
Alert . AlertCount ,
alerts . Count ) ;
if ( GridViewAlerts . SortedColumn ! = null )
{
2013-07-12 12:07:10 +02:00
if ( GridViewAlerts . SortedColumn . Index = = ColumnMessage . Index )
2013-06-24 13:41:48 +02:00
{
2013-07-03 13:00:00 +02:00
alerts . Sort ( Alert . CompareOnTitle ) ;
2013-06-24 13:41:48 +02:00
}
else if ( GridViewAlerts . SortedColumn . Index = = ColumnDate . Index )
{
2013-07-03 13:00:00 +02:00
alerts . Sort ( Alert . CompareOnDate ) ;
2013-06-24 13:41:48 +02:00
}
2013-07-12 12:07:10 +02:00
else if ( GridViewAlerts . SortedColumn . Index = = ColumnLocation . Index )
2013-06-24 13:41:48 +02:00
{
2013-07-03 13:00:00 +02:00
alerts . Sort ( Alert . CompareOnAppliesTo ) ;
2013-06-24 13:41:48 +02:00
}
2013-07-12 12:07:10 +02:00
else if ( GridViewAlerts . SortedColumn . Index = = ColumnSeverity . Index )
2013-06-24 13:41:48 +02:00
{
2013-07-03 13:00:00 +02:00
alerts . Sort ( Alert . CompareOnPriority ) ;
2013-06-24 13:41:48 +02:00
}
if ( GridViewAlerts . SortOrder = = SortOrder . Descending )
{
alerts . Reverse ( ) ;
}
}
int alertsFound = alerts . Count ;
if ( ALERT_CAP < alerts . Count )
{
log . DebugFormat ( "Rebuilding alertList: hit alert cap, hiding {0} alerts" , alerts . Count - ALERT_CAP ) ;
alerts . RemoveRange ( ALERT_CAP , alerts . Count - ALERT_CAP ) ;
}
Program . Invoke ( this , delegate
{
List < DataGridViewRow > gridRows = new List < DataGridViewRow > ( ) ;
log . Debug ( "Rebuilding alertList: Adding alert rows" ) ;
foreach ( Alert alert in alerts )
gridRows . Add ( NewAlertRow ( alert ) ) ;
log . DebugFormat ( "Rebuilding alertList: Added {0} rows" , gridRows . Count ) ;
List < string > selection = ( GridViewAlerts . SelectedRows . Cast < DataGridViewRow > ( ) . Select (
selectedRow = > ( ( Alert ) selectedRow . Tag ) . uuid ) ) . ToList ( ) ;
GridViewAlerts . Rows . Clear ( ) ;
log . Debug ( "Rebuilding alertList: Cleared rows" ) ;
GridViewAlerts . Rows . AddRange ( gridRows . ToArray ( ) ) ;
log . DebugFormat ( "Rebuilding alertList: Added {0} rows to the grid" , GridViewAlerts . Rows . Count ) ;
2013-08-30 13:46:28 +02:00
tableLayoutPanel3 . Visible = alertsFound > ALERT_CAP ;
2013-06-24 13:41:48 +02:00
//restore selection
if ( selection . Count > 0 )
{
log . Debug ( "Rebuilding alertList: Restoring alert selection" ) ;
foreach ( DataGridViewRow alertRow in GridViewAlerts . Rows )
{
alertRow . Selected = selection . Contains ( ( ( Alert ) alertRow . Tag ) . uuid ) ;
}
if ( GridViewAlerts . SelectedRows . Count = = 0 & & GridViewAlerts . Rows . Count > 0 )
{
GridViewAlerts . Rows [ 0 ] . Selected = true ;
}
log . DebugFormat ( "Rebuilding alertList: Selected {0} alerts" , selection . Count ) ;
}
UpdateActionEnablement ( ) ;
} ) ;
}
catch ( Exception e )
{
log . ErrorFormat ( "Encountered exception when building list: {0}" , e ) ;
}
finally
{
log . Debug ( "Rebuilding alertList: Waiting for lock to clear inAlertBuild" ) ;
lock ( GridViewAlerts )
{
inAlertBuild = false ;
log . Debug ( "Rebuilding alertList: cleared inAlertBuild" ) ;
if ( retryAlertBuild )
{
// we received a request to build while we were building, rebuild in case we missed something
retryAlertBuild = false ;
log . Debug ( "Rebuilding alertList: we received a request to build while we were building, rebuild in case we missed something" ) ;
_Rebuild ( ) ;
}
}
}
}
private DataGridViewRow NewAlertRow ( Alert alert )
{
2013-07-18 14:56:40 +02:00
var expanderCell = new DataGridViewImageCell ( ) ;
var imageCell = new DataGridViewImageCell ( ) ;
var appliesCell = new DataGridViewTextBoxCell ( ) ;
var detailCell = new DataGridViewTextBoxCell ( ) ;
var dateCell = new DataGridViewTextBoxCell ( ) ;
var actionItems = GetAlertActionItems ( alert ) ;
var actionCell = new DataGridViewDropDownSplitButtonCell ( actionItems . ToArray ( ) ) ;
var newRow = new DataGridViewRow { Tag = alert , MinimumHeight = DataGridViewDropDownSplitButtonCell . MIN_ROW_HEIGHT } ;
2013-06-24 13:41:48 +02:00
// Get the relevant image for the row depending on the type of the alert
Image typeImage = alert is MessageAlert & & ( ( MessageAlert ) alert ) . Message . ShowOnGraphs
? Images . GetImage16For ( ( ( MessageAlert ) alert ) . Message . Type )
: Images . GetImage16For ( alert . Priority ) ;
imageCell . Value = typeImage ;
// Set the detail cell content and expanding arrow
if ( expandedState . ContainsKey ( alert . uuid ) )
{
// show the expanded arrow and the body detail
expanderCell . Value = Properties . Resources . expanded_triangle ;
detailCell . Value = String . Format ( "{0}\n\n{1}" , alert . Title , alert . Description ) ;
}
else
{
// show the expand arrow and just the title
expanderCell . Value = Properties . Resources . contracted_triangle ;
detailCell . Value = alert . Title ;
}
appliesCell . Value = alert . AppliesTo ;
dateCell . Value = HelpersGUI . DateTimeToString ( alert . Timestamp . ToLocalTime ( ) , Messages . DATEFORMAT_DMY_HM , true ) ;
2013-07-18 14:56:40 +02:00
newRow . Cells . AddRange ( expanderCell , imageCell , detailCell , appliesCell , dateCell , actionCell ) ;
2013-06-24 13:41:48 +02:00
return newRow ;
}
/// <summary>
/// Runs all the current filters on the alert to determine if it should be shown in the list or not.
/// </summary>
/// <param name="alert"></param>
2013-07-12 12:07:10 +02:00
private bool FilterAlert ( Alert alert )
2013-06-24 13:41:48 +02:00
{
2013-07-02 20:06:11 +02:00
bool hide = false ;
Program . Invoke ( this , ( ) = >
hide = toolStripDropDownButtonDateFilter . HideByDate ( alert . Timestamp . ToLocalTime ( ) )
2013-07-03 14:00:24 +02:00
| | toolStripDropDownButtonServerFilter . HideByLocation ( alert . HostUuid )
| | toolStripDropDownSeveritiesFilter . HideBySeverity ( alert . Priority ) ) ;
return hide ;
2013-06-24 13:41:48 +02:00
}
private void RemoveAlertRow ( Alert a )
{
for ( int i = 0 ; i < GridViewAlerts . Rows . Count ; i + + )
{
if ( ( ( Alert ) GridViewAlerts . Rows [ i ] . Tag ) . uuid = = a . uuid )
GridViewAlerts . Rows . RemoveAt ( i ) ;
}
if ( GridViewAlerts . Rows . Count < ALERT_CAP )
2013-08-30 13:46:28 +02:00
tableLayoutPanel3 . Visible = false ;
2013-06-24 13:41:48 +02:00
}
2013-07-15 07:41:54 +02:00
private void GridViewAlerts_CellClick ( object sender , DataGridViewCellEventArgs e )
2013-06-24 13:41:48 +02:00
{
// If you click on the headers you can get -1 as the index.
if ( e . ColumnIndex < 0 | | e . RowIndex < 0 | | e . ColumnIndex ! = ColumnExpand . Index )
return ;
2013-07-18 14:56:40 +02:00
ToggleExpandedState ( e . RowIndex ) ;
2013-06-24 13:41:48 +02:00
}
2013-07-15 07:41:54 +02:00
private void GridViewAlerts_CellDoubleClick ( object sender , DataGridViewCellEventArgs e )
2013-06-24 13:41:48 +02:00
{
// If you click on the headers you can get -1 as the index.
if ( e . ColumnIndex < 0 | | e . RowIndex < 0 )
return ;
2013-07-18 14:56:40 +02:00
if ( e . ColumnIndex ! = ColumnActions . Index )
ToggleExpandedState ( e . RowIndex ) ;
2013-06-24 13:41:48 +02:00
}
2013-07-15 07:41:54 +02:00
private void GridViewAlerts_KeyDown ( object sender , KeyEventArgs e )
2013-06-24 13:41:48 +02:00
{
2013-07-15 07:41:54 +02:00
if ( e . KeyCode = = Keys . Right ) // expand all selected rows
2013-06-24 13:41:48 +02:00
{
2013-07-15 07:41:54 +02:00
foreach ( DataGridViewBand row in GridViewAlerts . SelectedRows )
{
Alert alert = ( Alert ) GridViewAlerts . Rows [ row . Index ] . Tag ;
if ( ! expandedState . ContainsKey ( alert . uuid ) )
{
2013-07-18 14:56:40 +02:00
ToggleExpandedState ( row . Index ) ;
2013-07-15 07:41:54 +02:00
}
}
2013-06-24 13:41:48 +02:00
}
2013-07-15 07:41:54 +02:00
else if ( e . KeyCode = = Keys . Left ) // collapse all selected rows
2013-06-24 13:41:48 +02:00
{
2013-07-15 07:41:54 +02:00
foreach ( DataGridViewBand row in GridViewAlerts . SelectedRows )
{
Alert alert = ( Alert ) GridViewAlerts . Rows [ row . Index ] . Tag ;
if ( expandedState . ContainsKey ( alert . uuid ) )
{
2013-07-18 14:56:40 +02:00
ToggleExpandedState ( row . Index ) ;
2013-07-15 07:41:54 +02:00
}
}
}
else if ( e . KeyCode = = Keys . Enter ) // toggle expanded state for all selected rows
{
foreach ( DataGridViewBand row in GridViewAlerts . SelectedRows )
{
2013-07-18 14:56:40 +02:00
ToggleExpandedState ( row . Index ) ;
2013-07-15 07:41:54 +02:00
}
2013-06-24 13:41:48 +02:00
}
}
2013-07-15 07:41:54 +02:00
private void GridViewAlerts_ColumnHeaderMouseClick ( object sender , DataGridViewCellMouseEventArgs e )
{
if ( GridViewAlerts . Columns [ e . ColumnIndex ] . SortMode = = DataGridViewColumnSortMode . Automatic )
{
Rebuild ( ) ;
}
}
private void GridViewAlerts_SelectionChanged ( object sender , EventArgs e )
{
// stop the buttons getting enabled/disabled during refresh, the rebuild will set them once it's finished
if ( inAlertBuild )
return ;
UpdateActionEnablement ( ) ;
}
2013-06-24 13:41:48 +02:00
/// <summary>
/// Handles the automatic sorting of the AlertsGridView for the non-string columns
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2013-07-15 07:41:54 +02:00
private void GridViewAlerts_SortCompare ( object sender , DataGridViewSortCompareEventArgs e )
2013-06-24 13:41:48 +02:00
{
Alert alert1 = ( Alert ) GridViewAlerts . Rows [ e . RowIndex1 ] . Tag ;
Alert alert2 = ( Alert ) GridViewAlerts . Rows [ e . RowIndex2 ] . Tag ;
if ( e . Column . Index = = ColumnDate . Index )
{
int SortResult = DateTime . Compare ( alert1 . Timestamp , alert2 . Timestamp ) ;
e . SortResult = ( GridViewAlerts . SortOrder = = SortOrder . Descending ) ? SortResult * = - 1 : SortResult ;
e . Handled = true ;
}
2013-07-12 12:07:10 +02:00
else if ( e . Column . Index = = ColumnSeverity . Index )
2013-06-24 13:41:48 +02:00
{
2013-07-03 13:00:00 +02:00
e . SortResult = Alert . CompareOnPriority ( alert1 , alert2 ) ;
2013-06-24 13:41:48 +02:00
e . Handled = true ;
}
}
2013-07-18 14:56:40 +02:00
private void ToggleExpandedState ( int rowIndex )
2013-07-15 07:41:54 +02:00
{
2013-07-18 14:56:40 +02:00
var row = GridViewAlerts . Rows [ rowIndex ] ;
Alert alert = row . Tag as Alert ;
if ( alert = = null )
return ;
2013-07-15 07:41:54 +02:00
if ( expandedState . ContainsKey ( alert . uuid ) )
{
expandedState . Remove ( alert . uuid ) ;
2013-07-18 14:56:40 +02:00
row . Cells [ ColumnExpand . Index ] . Value = Properties . Resources . contracted_triangle ;
row . Cells [ ColumnMessage . Index ] . Value = alert . Title ;
2013-07-15 07:41:54 +02:00
}
else
{
expandedState . Add ( alert . uuid , true ) ;
2013-07-18 14:56:40 +02:00
row . Cells [ ColumnExpand . Index ] . Value = Properties . Resources . expanded_triangle ;
row . Cells [ ColumnMessage . Index ] . Value = string . Format ( "{0}\n\n{1}" , alert . Title , alert . Description ) ;
2013-07-15 07:41:54 +02:00
}
}
2013-06-24 13:41:48 +02:00
#endregion
2014-06-30 15:49:16 +02:00
private DataGridViewRow FindAlertRow ( ToolStripMenuItem toolStripMenuItem )
{
if ( toolStripMenuItem = = null )
return null ;
return ( from DataGridViewRow row in GridViewAlerts . Rows
where row . Cells . Count > 0
let actionCell = row . Cells [ row . Cells . Count - 1 ] as DataGridViewDropDownSplitButtonCell
where actionCell ! = null & & actionCell . ContextMenu . Items . Cast < object > ( ) . Any ( item = > item is ToolStripMenuItem & & item = = toolStripMenuItem )
select row ) . FirstOrDefault ( ) ;
}
2013-07-18 14:56:40 +02:00
private void ToolStripMenuItemHelp_Click ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
// We should only be here if one item is selected, we dont do multi-help
if ( GridViewAlerts . SelectedRows . Count ! = 1 )
2014-07-02 14:13:37 +02:00
log . DebugFormat ( "Can only launch help for 1 alert at a time (Attempted to launch {0}). Launching for the clicked item." , GridViewAlerts . SelectedRows . Count ) ;
2014-06-30 15:49:16 +02:00
DataGridViewRow clickedRow = FindAlertRow ( sender as ToolStripMenuItem ) ;
if ( clickedRow = = null )
return ;
Alert alert = ( Alert ) clickedRow . Tag ;
if ( alert = = null )
return ;
2013-06-24 13:41:48 +02:00
if ( alert . HelpID = = null )
{
log . ErrorFormat ( "Attempted to launch help for alert {0} ({1}) but no helpID available. Not launching." , alert . Title , alert . uuid ) ;
return ;
}
HelpManager . Launch ( alert . HelpID ) ;
}
2013-07-18 14:56:40 +02:00
private void ToolStripMenuItemFix_Click ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
// We should only be here if one item is selected, we dont do multi-fix
2014-06-30 15:49:16 +02:00
if ( GridViewAlerts . SelectedRows . Count ! = 1 )
2014-07-02 14:13:37 +02:00
log . DebugFormat ( "Only 1 alert can be fixed at a time (Attempted to fix {0}). Fixing the clicked item." , GridViewAlerts . SelectedRows . Count ) ;
2014-06-30 15:49:16 +02:00
DataGridViewRow clickedRow = FindAlertRow ( sender as ToolStripMenuItem ) ;
if ( clickedRow = = null )
2013-06-24 13:41:48 +02:00
{
2014-07-02 14:13:37 +02:00
log . Debug ( "Attempted to fix alert with no alert selected." ) ;
2013-06-24 13:41:48 +02:00
return ;
}
2014-06-30 15:49:16 +02:00
Alert alert = ( Alert ) clickedRow . Tag ;
if ( alert = = null )
return ;
2013-06-24 13:41:48 +02:00
if ( alert . FixLinkAction = = null )
{
log . ErrorFormat ( "Attempted to fix alert {0} ({1}) but no fix link action available. Not fixing." , alert . Title , alert . uuid ) ;
return ;
}
alert . FixLinkAction . Invoke ( ) ;
}
2013-07-18 14:56:40 +02:00
private void ToolStripMenuItemDismiss_Click ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
2014-07-29 11:19:54 +02:00
if ( GridViewAlerts . SelectedRows . Count ! = 1 )
log . DebugFormat ( "Only 1 alert can be dismissed at a time (Attempted to dismiss {0}). Dismissing the clicked item." , GridViewAlerts . SelectedRows . Count ) ;
DataGridViewRow clickedRow = FindAlertRow ( sender as ToolStripMenuItem ) ;
if ( clickedRow = = null )
{
log . Debug ( "Attempted to dismiss alert with no alert selected." ) ;
return ;
}
Alert alert = ( Alert ) clickedRow . Tag ;
if ( alert = = null )
return ;
2013-11-18 15:31:00 +01:00
using ( var dlog = new ThreeButtonDialog (
2013-06-24 13:41:48 +02:00
new ThreeButtonDialog . Details ( null , Messages . ALERT_DISMISS_CONFIRM , Messages . XENCENTER ) ,
ThreeButtonDialog . ButtonYes ,
2013-11-18 15:31:00 +01:00
ThreeButtonDialog . ButtonNo ) )
{
if ( dlog . ShowDialog ( this ) ! = DialogResult . Yes )
return ;
}
2013-06-24 13:41:48 +02:00
2014-07-29 11:19:54 +02:00
DismissAlerts ( new List < Alert > { ( Alert ) clickedRow . Tag } ) ;
2013-06-24 13:41:48 +02:00
}
2013-07-11 19:20:18 +02:00
private void tsmiDismissAll_Click ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
DialogResult result ;
2013-08-14 17:59:25 +02:00
if ( ! FilterIsOn )
{
using ( var dlog = new ThreeButtonDialog (
2013-06-24 13:41:48 +02:00
new ThreeButtonDialog . Details ( null , Messages . ALERT_DISMISS_ALL_NO_FILTER_CONTINUE ) ,
new ThreeButtonDialog . TBDButton ( Messages . DISMISS_ALL_YES_CONFIRM_BUTTON , DialogResult . Yes ) ,
2013-08-14 17:59:25 +02:00
ThreeButtonDialog . ButtonCancel ) )
{
result = dlog . ShowDialog ( this ) ;
}
}
2013-06-24 13:41:48 +02:00
else
2013-08-14 17:59:25 +02:00
{
using ( var dlog = new ThreeButtonDialog (
2013-06-24 13:41:48 +02:00
new ThreeButtonDialog . Details ( null , Messages . ALERT_DISMISS_ALL_CONTINUE ) ,
new ThreeButtonDialog . TBDButton ( Messages . DISMISS_ALL_CONFIRM_BUTTON , DialogResult . Yes ) ,
new ThreeButtonDialog . TBDButton ( Messages . DISMISS_FILTERED_CONFIRM_BUTTON , DialogResult . No , ThreeButtonDialog . ButtonType . NONE ) ,
2013-08-14 17:59:25 +02:00
ThreeButtonDialog . ButtonCancel ) )
{
result = dlog . ShowDialog ( this ) ;
}
}
2013-06-24 13:41:48 +02:00
if ( result = = DialogResult . Cancel )
return ;
2014-01-09 14:57:41 +01:00
var alerts = result = = DialogResult . No
? ( from DataGridViewRow row in GridViewAlerts . Rows select row . Tag as Alert )
: Alert . Alerts ;
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
DismissAlerts ( alerts ) ;
2013-06-24 13:41:48 +02:00
}
2014-07-29 11:19:54 +02:00
private void tsmiDismissSelected_Click ( object sender , EventArgs e )
{
using ( var dlog = new ThreeButtonDialog (
new ThreeButtonDialog . Details ( null , Messages . ALERT_DISMISS_SELECTED_CONFIRM , Messages . XENCENTER ) ,
ThreeButtonDialog . ButtonYes ,
ThreeButtonDialog . ButtonNo ) )
{
if ( dlog . ShowDialog ( this ) ! = DialogResult . Yes )
return ;
}
if ( GridViewAlerts . SelectedRows . Count > 0 )
{
var selectedAlerts = from DataGridViewRow row in GridViewAlerts . SelectedRows select row . Tag as Alert ;
DismissAlerts ( selectedAlerts ) ;
}
}
2013-07-03 14:00:24 +02:00
private void AlertsCollectionChanged ( object sender , CollectionChangeEventArgs e )
2013-06-24 13:41:48 +02:00
{
Program . AssertOnEventThread ( ) ;
if ( e . Element = = null )
{
// We take the null element to mean there has been a batch remove
Rebuild ( ) ;
return ;
}
Alert a = e . Element as Alert ;
switch ( e . Action )
{
case CollectionChangeAction . Add :
Rebuild ( ) ; // rebuild entire alert list to ensure filtering and sorting
break ;
case CollectionChangeAction . Remove :
RemoveAlertRow ( a ) ;
break ;
}
}
private void UpdateActionEnablement ( )
{
2013-11-21 09:25:02 +01:00
toolStripDropDownSeveritiesFilter . Enabled =
toolStripDropDownButtonServerFilter . Enabled =
toolStripDropDownButtonDateFilter . Enabled =
2013-12-05 11:55:09 +01:00
toolStripButtonExportAll . Enabled = Alert . NonDismissingAlertCount > 0 ;
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
tsmiDismissAll . Enabled = AllowedToDismiss ( Alert . Alerts ) ;
2013-07-11 19:20:18 +02:00
tsmiDismissAll . AutoToolTip = ! tsmiDismissAll . Enabled ;
tsmiDismissAll . ToolTipText = tsmiDismissAll . Enabled
? string . Empty
: Alert . NonDismissingAlertCount > 0
? Messages . DELETE_ANY_MESSAGE_RBAC_BLOCKED
: Messages . NO_MESSAGES_TO_DISMISS ;
2014-01-09 14:57:41 +01:00
var selectedAlerts = from DataGridViewRow row in GridViewAlerts . SelectedRows
select row . Tag as Alert ;
tsmiDismissSelected . Enabled = AllowedToDismiss ( selectedAlerts ) ;
2013-07-11 19:20:18 +02:00
tsmiDismissSelected . AutoToolTip = ! tsmiDismissSelected . Enabled ;
tsmiDismissSelected . ToolTipText = tsmiDismissSelected . Enabled
? string . Empty
: Messages . DELETE_MESSAGE_RBAC_BLOCKED ;
2013-08-14 17:59:25 +02:00
2014-01-09 14:57:41 +01:00
toolStripSplitButtonDismiss . Enabled = tsmiDismissAll . Enabled | | tsmiDismissSelected . Enabled ;
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
if ( toolStripSplitButtonDismiss . DefaultItem ! = null & & ! toolStripSplitButtonDismiss . DefaultItem . Enabled )
2013-06-24 13:41:48 +02:00
{
2014-01-09 14:57:41 +01:00
foreach ( ToolStripItem item in toolStripSplitButtonDismiss . DropDownItems )
{
if ( item . Enabled )
{
toolStripSplitButtonDismiss . DefaultItem = item ;
toolStripSplitButtonDismiss . Text = item . Text ;
break ;
}
}
}
}
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
#region Alert dismissal
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
private bool AllowedToDismiss ( Alert alert )
{
return AllowedToDismiss ( new [ ] { alert } ) ;
2013-06-24 13:41:48 +02:00
}
2014-01-09 14:57:41 +01:00
private bool AllowedToDismiss ( IEnumerable < Alert > alerts )
2013-06-24 13:41:48 +02:00
{
2014-01-09 14:57:41 +01:00
var alertConnections = ( from Alert alert in alerts
where alert ! = null & & ! alert . Dismissing
let con = alert . Connection
select con ) . Distinct ( ) ;
2013-08-14 17:59:25 +02:00
2014-01-09 14:57:41 +01:00
if ( alertConnections . Count ( ) = = 0 )
2013-08-14 17:59:25 +02:00
return false ;
2014-01-09 14:57:41 +01:00
return alertConnections . Any ( AllowedToDismiss ) ;
2013-06-24 13:41:48 +02:00
}
2014-01-09 14:57:41 +01:00
/// <summary>
/// Checks the user has sufficient RBAC privileges to clear alerts on a given connection
/// </summary>
2013-06-24 13:41:48 +02:00
private bool AllowedToDismiss ( IXenConnection c )
{
// check if local alert
if ( c = = null )
return true ;
2014-01-09 14:57:41 +01:00
// have we disconnected? Alert will disappear soon, but for now block dismissal.
2013-06-24 13:41:48 +02:00
if ( c . Session = = null )
return false ;
if ( c . Session . IsLocalSuperuser | | ! Helpers . MidnightRideOrGreater ( c ) )
return true ;
List < Role > rolesAbleToCompleteAction = Role . ValidRoleList ( "Message.destroy" , c ) ;
foreach ( Role possibleRole in rolesAbleToCompleteAction )
{
if ( c . Session . Roles . Contains ( possibleRole ) )
return true ;
}
return false ;
}
2014-01-09 14:57:41 +01:00
private void DismissAlerts ( IEnumerable < Alert > 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 } ;
foreach ( var g in groups )
{
if ( AllowedToDismiss ( g . Connection ) )
2014-07-29 11:19:54 +02:00
{
foreach ( var alert in g . Alerts )
alert . Dismissing = true ;
Rebuild ( ) ;
2014-01-09 14:57:41 +01:00
new DeleteAllAlertsAction ( g . Connection , g . Alerts ) . RunAsync ( ) ;
2014-07-29 11:19:54 +02:00
}
2014-01-09 14:57:41 +01:00
}
}
#endregion
2013-07-18 14:56:40 +02:00
private List < ToolStripItem > GetAlertActionItems ( Alert alert )
2013-06-24 13:41:48 +02:00
{
2013-07-18 14:56:40 +02:00
var items = new List < ToolStripItem > ( ) ;
2013-06-24 13:41:48 +02:00
2014-01-09 14:57:41 +01:00
if ( AllowedToDismiss ( alert ) )
2013-07-18 14:56:40 +02:00
{
var dismiss = new ToolStripMenuItem ( Messages . ALERT_DISMISS ) ;
dismiss . Click + = ToolStripMenuItemDismiss_Click ;
items . Add ( dismiss ) ;
}
2013-06-24 13:41:48 +02:00
2013-07-18 14:56:40 +02:00
if ( ! string . IsNullOrEmpty ( alert . FixLinkText ) & & alert . FixLinkAction ! = null )
2013-06-24 13:41:48 +02:00
{
2013-07-18 14:56:40 +02:00
var fix = new ToolStripMenuItem ( alert . FixLinkText ) ;
fix . Click + = ToolStripMenuItemFix_Click ;
items . Add ( fix ) ;
}
2013-07-15 07:41:54 +02:00
2013-07-18 14:56:40 +02:00
if ( ! string . IsNullOrEmpty ( alert . HelpID ) )
{
var help = new ToolStripMenuItem ( alert . HelpLinkText ) ;
help . Click + = ToolStripMenuItemHelp_Click ;
items . Add ( help ) ;
}
2013-07-15 07:41:54 +02:00
2013-07-18 14:56:40 +02:00
if ( items . Count > 0 )
items . Add ( new ToolStripSeparator ( ) ) ;
2013-07-15 07:41:54 +02:00
2013-07-18 14:56:40 +02:00
var copy = new ToolStripMenuItem ( Messages . COPY ) ;
copy . Click + = copyToolStripMenuItem_Click ;
items . Add ( copy ) ;
2013-06-24 13:41:48 +02:00
2013-07-18 14:56:40 +02:00
return items ;
2013-06-24 13:41:48 +02:00
}
2013-07-11 19:20:18 +02:00
#region Top ToolStrip event handlers
2013-07-02 18:36:02 +02:00
private void toolStripDropDownButtonDateFilter_FilterChanged ( )
2013-06-24 13:41:48 +02:00
{
Rebuild ( ) ;
}
2013-07-02 20:06:11 +02:00
private void toolStripDropDownButtonServerFilter_FilterChanged ( )
{
Rebuild ( ) ;
}
2013-07-15 07:41:54 +02:00
private void toolStripDropDownSeveritiesFilter_FilterChanged ( )
{
Rebuild ( ) ;
}
2013-06-24 13:41:48 +02:00
2013-07-15 07:41:54 +02:00
private void toolStripButtonRefresh_Click ( object sender , EventArgs e )
{
Rebuild ( ) ;
}
2013-07-11 19:20:18 +02:00
2013-06-24 13:41:48 +02:00
private void toolStripButtonExportAll_Click ( object sender , EventArgs e )
{
2013-08-14 18:12:39 +02:00
bool exportAll = true ;
if ( FilterIsOn )
{
using ( var dlog = new ThreeButtonDialog (
new ThreeButtonDialog . Details ( null , Messages . ALERT_EXPORT_ALL_OR_FILTERED ) ,
new ThreeButtonDialog . TBDButton ( Messages . ALERT_EXPORT_ALL_BUTTON , DialogResult . Yes ) ,
new ThreeButtonDialog . TBDButton ( Messages . ALERT_EXPORT_FILTERED_BUTTON , DialogResult . No , ThreeButtonDialog . ButtonType . NONE ) ,
ThreeButtonDialog . ButtonCancel ) )
{
var result = dlog . ShowDialog ( this ) ;
if ( result = = DialogResult . No )
exportAll = false ;
else if ( result = = DialogResult . Cancel )
return ;
}
}
string fileName ;
using ( SaveFileDialog dialog = new SaveFileDialog
{
AddExtension = true ,
Filter = string . Format ( "{0} (*.csv)|*.csv|{1} (*.*)|*.*" ,
Messages . CSV_DESCRIPTION , Messages . ALL_FILES ) ,
FilterIndex = 0 ,
Title = Messages . EXPORT_ALL ,
RestoreDirectory = true ,
DefaultExt = "csv" ,
CheckPathExists = false ,
OverwritePrompt = true
} )
{
if ( dialog . ShowDialog ( this ) ! = DialogResult . OK )
return ;
fileName = dialog . FileName ;
}
2013-06-24 13:41:48 +02:00
new DelegatedAsyncAction ( null ,
2013-08-14 18:12:39 +02:00
string . Format ( Messages . EXPORT_SYSTEM_ALERTS , fileName ) ,
string . Format ( Messages . EXPORTING_SYSTEM_ALERTS , fileName ) ,
string . Format ( Messages . EXPORTED_SYSTEM_ALERTS , fileName ) ,
2013-07-18 14:56:40 +02:00
delegate
2013-06-24 13:41:48 +02:00
{
2013-08-14 18:12:39 +02:00
using ( StreamWriter stream = new StreamWriter ( fileName , false , UTF8Encoding . UTF8 ) )
2013-06-24 13:41:48 +02:00
{
2013-07-12 12:07:10 +02:00
stream . WriteLine ( "{0},{1},{2},{3},{4}" , Messages . TITLE ,
2013-08-14 18:12:39 +02:00
Messages . SEVERITY , Messages . DESCRIPTION ,
Messages . APPLIES_TO , Messages . TIMESTAMP ) ;
if ( exportAll )
2013-06-24 13:41:48 +02:00
{
2013-08-14 18:12:39 +02:00
foreach ( Alert a in Alert . Alerts )
2014-01-09 14:57:41 +01:00
{
if ( ! a . Dismissing )
stream . WriteLine ( a . GetAlertDetailsCSVQuotes ( ) ) ;
}
2013-08-14 18:12:39 +02:00
}
else
{
foreach ( DataGridViewRow row in GridViewAlerts . Rows )
{
var a = row . Tag as Alert ;
2014-01-09 14:57:41 +01:00
if ( a ! = null & & ! a . Dismissing )
2013-11-23 15:04:15 +01:00
stream . WriteLine ( a . GetAlertDetailsCSVQuotes ( ) ) ;
2013-08-14 18:12:39 +02:00
}
2013-06-24 13:41:48 +02:00
}
}
} ) . RunAsync ( ) ;
}
2013-07-11 19:20:18 +02:00
private void toolStripSplitButtonDismiss_DropDownItemClicked ( object sender , ToolStripItemClickedEventArgs e )
2013-06-24 13:41:48 +02:00
{
2013-07-11 19:20:18 +02:00
toolStripSplitButtonDismiss . DefaultItem = e . ClickedItem ;
toolStripSplitButtonDismiss . Text = toolStripSplitButtonDismiss . DefaultItem . Text ;
2013-06-24 13:41:48 +02:00
}
2013-11-23 15:04:15 +01:00
#endregion
2013-06-24 13:41:48 +02:00
private void copyToolStripMenuItem_Click ( object sender , EventArgs e )
{
2014-07-29 11:19:54 +02:00
if ( GridViewAlerts . SelectedRows . Count ! = 1 )
log . DebugFormat ( "Only 1 alert can be copied at a time (Attempted to copy {0}). Copying the clicked item." , GridViewAlerts . SelectedRows . Count ) ;
2014-06-30 15:49:16 +02:00
DataGridViewRow clickedRow = FindAlertRow ( sender as ToolStripMenuItem ) ;
if ( clickedRow = = null )
2013-06-24 13:41:48 +02:00
{
2014-07-02 14:13:37 +02:00
log . Debug ( "Attempted to copy alert with no alert selected." ) ;
2013-06-24 13:41:48 +02:00
return ;
}
2014-07-29 11:19:54 +02:00
Alert alert = ( Alert ) clickedRow . Tag ;
if ( alert = = null )
return ;
2013-07-12 12:07:10 +02:00
2013-06-24 13:41:48 +02:00
try
{
2014-07-29 11:19:54 +02:00
Clipboard . SetText ( alert . GetUpdateDetailsCSVQuotes ( ) ) ;
2013-06-24 13:41:48 +02:00
}
catch ( Exception ex )
{
log . Error ( "Exception while trying to set clipboard text." , ex ) ;
log . Error ( ex , ex ) ;
}
}
}
}