xenadmin/XenAdmin/Wlb/WlbReports/WorkloadReports.cs
Konstantina Chremmou ae22560ce8 Converted all extension get properties of the API classes to methods in order to
prevent them from being serialised alongside the API properties. This will also
be useful for moving the API bindings out of XenModel.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
2017-09-03 03:35:30 +01:00

1033 lines
41 KiB
C#

/* 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.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Web;
using XenAdmin.Controls;
using XenAPI;
using XenAdmin.Core;
using XenAdmin.Wlb;
using XenAdmin.Dialogs;
using XenAdmin.Actions;
using XenAdmin.Actions.Wlb;
using XenAdmin.Help;
using XenAdmin.Controls.Wlb;
// Report viewer control dependencies
using Microsoft.Reporting.WinForms;
namespace XenAdmin
{
public delegate void CustomRefreshEventHandler(object sender, System.EventArgs e);
public partial class WorkloadReports : XenDialogBase
{
#region Private Variables
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private IEnumerable<Host> _hosts;
private Pool _pool;
private WlbReportSubscriptionCollection _subscriptionCollection;
private string _reportFile;
private bool _runReport;
private bool _isCreedenceOrLater;
private List<string> _midnightRideReports = new List<string>(new []
{
Messages.WLBREPORT_POOL_AUDIT_HISTORY,
Messages.WLBREPORT_POOL_OPTIMIZATION_HISTORY
});
#endregion
#region Properties
/// <summary>
/// Object set to current pool
/// </summary>
public Pool Pool
{
get { return _pool; }
set { _pool = value; }
}
/// <summary>
/// Collection of hosts for the current pool
/// </summary>
public IEnumerable<Host> Hosts
{
get { return _hosts; }
set { _hosts = value; }
}
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public WorkloadReports() : this(string.Empty, false) {}
/// <summary>
/// Overloaded constructor provides access to a specific report upon load
/// </summary>
/// <param name="reportName"></param>
public WorkloadReports(string reportFile, bool run)
{
InitializeComponent();
_reportFile = reportFile;
_runReport = run;
}
#endregion
internal override string HelpName
{
get { return "WLBReports"; }
}
#region Private Methods
/// <summary>
/// Populates the treeview with ReportInfo and SubscriptionInfo nodes
/// </summary>
private void SetTreeViewReportList()
{
bool errorLoading = false;
// Prep treeview for population
treeViewReportList.BeginUpdate();
treeViewReportList.Nodes.Clear();
// Set up the image list for the tree
this.treeViewReportList.ImageList = CreateReportImageList();
//_subscriptionCollection = null;
try
{
// retrieve subscription
SetSubscriptionCollection();
this.wlbReportView1.btnSubscribe.Visible = false;
this.wlbReportView1.btnLaterReport.Visible = false;
this.wlbReportView1.IsCreedenceOrLater = _isCreedenceOrLater;
PopulateTreeView();
}
catch (XenAdmin.CancelledException xc)
{
// User cancelled entering credentials when prompted by action
log.Debug(xc);
errorLoading = true;
}
catch (Exception ex)
{
log.Debug(ex, ex);
using (var dlg = new ThreeButtonDialog(new ThreeButtonDialog.Details(SystemIcons.Error, Messages.WLBREPORT_REPORT_CONFIG_ERROR, Messages.XENCENTER)))
{
dlg.ShowDialog(this);
}
errorLoading = true;
}
finally
{
if ((treeViewReportList != null) && (!errorLoading))
treeViewReportList.EndUpdate();
else
this.Close();
}
}
/// <summary>
/// Populates the subscription list with items of type WlbReportSubscription
/// </summary>
private void SetTreeViewSubscriptionList()
{
// Prep treeview for population
treeViewSubscriptionList.BeginUpdate();
treeViewSubscriptionList.Nodes.Clear();
treeViewSubscriptionList.ImageList = CreateReportImageList();
if (_subscriptionCollection != null)
{
this.lblSubscriptions.Visible = true;
this.treeViewSubscriptionList.Visible = true;
foreach (string key in _subscriptionCollection.Keys)
{
treeViewSubscriptionList.Nodes.Add(GetReportSubscriptionTreeNode(_subscriptionCollection[key]));
}
}
else
{
this.lblSubscriptions.Visible = false;
this.treeViewSubscriptionList.Visible = false;
}
treeViewSubscriptionList.EndUpdate();
}
/// <summary>
/// Used by drilldown and back events from the reportviewer to maintain treeview state
/// </summary>
private void SynchTreeViewReportList(string reportName)
{
WlbReportInfo reportInfo;
wlbReportView1.ResetReportViewer = false;
string reportFile = String.Format("{0}.{1}", reportName, "rdlc");
for (int i = 0; i < treeViewReportList.Nodes.Count; i++)
{
if ((treeViewReportList.Nodes[i].Tag != null) &&
(treeViewReportList.Nodes[i].Tag.GetType() == typeof(WlbReportInfo)))
{
reportInfo = (WlbReportInfo)treeViewReportList.Nodes[i].Tag;
if (reportInfo.ReportFile == reportFile)
{
treeViewReportList.SelectedNode = treeViewReportList.Nodes[i];
treeViewReportList.Select();
wlbReportView1.ViewerReportInfo = reportInfo;
break;
}
}
}
}
/// <summary>
/// Update report treeView when edit/add/delete report subscriptions
/// </summary>
private void UpdateReportTreeView()
{
// Begin update report treeView
treeViewReportList.BeginUpdate();
// If there is a selected subscription node, need to save it before it got cleared
// There is no need to save selected report node since it never got cleared
WlbReportSubscription selectedSub = null;
String selectedSubReportFile = String.Empty;
if (this.treeViewReportList.SelectedNode != null && this.treeViewReportList.SelectedNode.Tag != null && this.treeViewReportList.SelectedNode.Tag.GetType() == typeof(WlbReportSubscription))
{
// Save selected subscription node for later
selectedSub = (WlbReportSubscription)this.treeViewReportList.SelectedNode.Tag;
// Save the report file of the selected subscription node for later
selectedSubReportFile = ((WlbReportInfo)this.treeViewReportList.SelectedNode.Parent.Parent.Tag).ReportFile;
}
// Update subscription nodes
foreach (TreeNode reportNode in this.treeViewReportList.Nodes)
{
// Get subscriptions under the report node
Dictionary<string, WlbReportSubscription> subscriptionList = _subscriptionCollection.GetReportSubscriptionByReportName(((WlbReportInfo)reportNode.Tag).ReportFile);
// If there's subscriptions for the current report, add them
if (subscriptionList.Count > 0)
{
// Add a subscriptions folder if there isn't one
if (reportNode.GetNodeCount(true) == 0)
{
TreeNode subscriptionFolderNode = new TreeNode(Messages.WLB_SUBSCRIPTIONS, 2, 2);
reportNode.Nodes.Add(subscriptionFolderNode);
}
// Delete all the nodes to build the updated list
reportNode.Nodes[0].Nodes.Clear();
// Add in the latest nodes
if (selectedSub != null && String.Compare(selectedSubReportFile, ((WlbReportInfo)reportNode.Tag).ReportFile, true) == 0)
{
// Add new subscription node and retrieve selected node if there is one
AddNewSubscriptionNode(reportNode.Nodes[0], subscriptionList, ((WlbReportInfo)reportNode.Tag).ReportName, selectedSub);
}
else
{
// Add new subscription node
AddNewSubscriptionNode(reportNode.Nodes[0], subscriptionList, ((WlbReportInfo)reportNode.Tag).ReportName, null);
}
}
else
{
// Force to select reportNode before clear reportNode's children node
// only if the original selected subscription has been deleted
// and there are no more subscriptions under the report
if (selectedSub != null && String.Compare(selectedSubReportFile, ((WlbReportInfo)reportNode.Tag).ReportFile, true) == 0)
{
this.treeViewReportList.SelectedNode = reportNode;
}
// Clear reportNode's children node (subscription folder node)
// if there is no subscription under the reportNode
reportNode.Nodes.Clear();
}
}
// End updating report treeView
treeViewReportList.EndUpdate();
}
/// <summary>
/// Update subscriptionTreeView when Add/Edit/Delete subscription
/// </summary>
private void UpdateSubscriptionTreeView()
{
// Begin update subscription treeView
treeViewSubscriptionList.BeginUpdate();
// Save selected node if there is one
WlbReportSubscription selectedSub = null;
if (treeViewSubscriptionList.SelectedNode != null)
{
selectedSub = (WlbReportSubscription)treeViewSubscriptionList.SelectedNode.Tag;
}
// Delete all nodes
treeViewSubscriptionList.Nodes.Clear();
// Add subscription nodes if there is any
if (_subscriptionCollection.Count > 0)
{
foreach (string key in _subscriptionCollection.Keys)
{
TreeNode subNode = GetReportSubscriptionTreeNode(_subscriptionCollection[key]);
treeViewSubscriptionList.Nodes.Add(subNode);
// Retrieve selected node if there is one
if (selectedSub != null && String.Compare(_subscriptionCollection[key].Id, selectedSub.Id, true) == 0)
{
treeViewSubscriptionList.SelectedNode = subNode;
}
}
// Force to set selected node to the first node
// only if treeViewSubscriptionList has selected subscription node before update
// but the selected subscription doesn't exist anymore
if (selectedSub != null && treeViewSubscriptionList.SelectedNode == null)
{
treeViewSubscriptionList.SelectedNode = treeViewSubscriptionList.Nodes[0];
}
}
else if (selectedSub != null)
{
// No nodes left in the tree so select the current report in the reportviewer tree
foreach (TreeNode reportNode in this.treeViewReportList.Nodes)
{
if (((WlbReportInfo)reportNode.Tag).ReportName == selectedSub.ReportDisplayName)
{
treeViewReportList.SelectedNode = reportNode;
break;
}
}
}
// End update subscription treeView
treeViewSubscriptionList.EndUpdate();
}
/// <summary>
/// Adds an image list to the current treeview for use by each of the nodes types
/// </summary>
private ImageList CreateReportImageList()
{
ImageList reportImageList;
reportImageList = new ImageList();
reportImageList.Images.Add(XenAdmin.Properties.Resources._000_GetServerReport_h32bit_16);
reportImageList.Images.Add(XenAdmin.Properties.Resources.subscribe);
reportImageList.Images.Add(XenAdmin.Properties.Resources._000_Folder_open_h32bit_16);
return reportImageList;
}
/// <summary>
/// Retrieve subscriptions and set _subscriptionCollection
/// </summary>
private void SetSubscriptionCollection()
{
_subscriptionCollection = null;
WlbPoolConfiguration poolConfiguration;
RetrieveWlbConfigurationAction action = new RetrieveWlbConfigurationAction(_pool);
using (var dialog = new ActionProgressDialog(action, ProgressBarStyle.Blocks))
{
dialog.ShowCancel = true;
dialog.ShowDialog(this);
}
if (action.Succeeded)
{
poolConfiguration = new WlbPoolConfiguration(action.WlbConfiguration);
_isCreedenceOrLater = poolConfiguration.IsCreedenceOrLater;
this.splitContainerLeftPane.Panel2Collapsed = true;
this.wlbReportView1.btnSubscribe.Visible=false;
}
else
{
throw (action.Exception);
}
}
/// <summary>
/// Populate report treeView on initial load report window
/// </summary>
private void PopulateTreeView()
{
XmlNodeList currentNodes;
XmlDocument xmlReportDoc = new XmlDocument();
// Attempt to get the latest set of reports from the WLB server. WLB version 2.0
// and beyond will respond to this.
xmlReportDoc = GetServerReportsConfig();
// No report definitons on WLB server, obtain them locally (the old way)
if ((!xmlReportDoc.HasChildNodes) || (!xmlReportDoc.DocumentElement.HasChildNodes))
xmlReportDoc = GetLocalReportsConfig();
// Get each of the reports from the config and load them into combo box
currentNodes = xmlReportDoc.SelectNodes(@"Reports/Report");
// pupulate treeNode
for (int i = 0; i < currentNodes.Count; i++)
{
// Adds the report node
TreeNode currentReportTreeNode = GetReportTreeNode(currentNodes[i]);
treeViewReportList.Nodes.Add(currentReportTreeNode);
// Force to highlight the proper report treeNode if WLBReportWindow is called from WLB tab
if (!String.IsNullOrEmpty(_reportFile))
{
string currentReportFile = ((WlbReportInfo)currentReportTreeNode.Tag).ReportFile.Split('.')[0];
if (String.Compare(currentReportFile, _reportFile, true, System.Globalization.CultureInfo.InvariantCulture) == 0)
{
treeViewReportList.SelectedNode = currentReportTreeNode;
_reportFile = String.Empty;
}
}
}
treeViewReportList.Sort();
}
/// <summary>
/// Obtains report configuration from local report.xml definition
/// This method is only utilized when WLB server is version 1.0 and 1.1.
/// Subsequent versions utilize GetReportConfig(XmlDocument)
/// </summary>
/// <returns></returns>
private XmlDocument GetLocalReportsConfig()
{
XmlDocument xmlReportsDoc = new XmlDocument();
// Load up report info from XML file
xmlReportsDoc.Load(String.Format(@"{0}\{1}", Application.StartupPath.ToString(), "reports.xml"));
return xmlReportsDoc;
}
/// <summary>
/// Invokes and executes a call to the Kirkwood database via Xapi
/// to obtain report configuration data including the actual
/// rdlc report definitions
/// </summary>
/// <returns>Report definition list XML document</returns>
private XmlDocument GetServerReportsConfig()
{
string returnValue;
XmlDocument xmlReportsDoc = new XmlDocument();
string reportName = "get_report_definitions";
// Parameters
Dictionary<string, string> parms = new Dictionary<string, string>();
parms.Add("LocaleCode", Program.CurrentLanguage);
if (_isCreedenceOrLater)
{
parms.Add("ReportVersion", "Creedence");
parms.Add("PoolId", _pool.uuid);
}
AsyncAction action = new WlbReportAction(_pool.Connection,
Helpers.GetMaster(_pool.Connection),
reportName,
Messages.WLB_REPORT_DEFINITIONS,
true,
parms);
using (var dlg = new ActionProgressDialog(action, ProgressBarStyle.Marquee))
dlg.ShowDialog();
returnValue = action.Result;
if ((action.Succeeded) && (!String.IsNullOrEmpty(returnValue)))
{
try
{
xmlReportsDoc.LoadXml(returnValue);
string rdlcText;
foreach (XmlNode currentRdlc in xmlReportsDoc.SelectNodes(@"Reports/Report/Rdlc"))
{
rdlcText = currentRdlc.InnerText;
currentRdlc.InnerText = String.Empty;
currentRdlc.InnerText = rdlcText;
}
}
catch (Exception)
{
xmlReportsDoc = null;
}
}
return xmlReportsDoc;
}
// To enhance pool audit trail report, WLB server updates RDLC and would send user and object lists.
// These values are sent along with parameter keys "AuditUser", "AuditObject".
// The GetCustomXmlElement functions are used to retrieve the parameter values from WLB server.
private static XmlElement GetCustomXmlElement(XmlElement root)
{
XmlNodeList labelNodes = root.GetElementsByTagName("Custom");
if (labelNodes != null && labelNodes.Count > 0)
{
string xmlCustom = labelNodes[0].InnerXml;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" + xmlCustom + "</root>");
return xmlDoc.DocumentElement;
}
else
{
XmlDocument xmlDoc = new XmlDocument();
string searchStart = "Function Custom() As String";
string searchEnd = "\nEnd Function";
string xmlDocString = root.InnerXml;
int startPos = xmlDocString.IndexOf(searchStart, 0);
if (startPos > -1)
{
int endPos = xmlDocString.IndexOf(searchEnd, startPos);
string customString = xmlDocString.Substring(startPos + searchStart.Length, endPos - startPos - searchStart.Length);
customString = customString.Trim().Substring("Return".Length).Trim().Trim("\"".ToCharArray());
customString = HttpUtility.HtmlDecode(customString);
xmlDoc.LoadXml(customString);
return xmlDoc.DocumentElement;
}
else
{
return null;
}
}
}
private static XmlElement GetCustomXmlElement(XmlNode root)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" + root.InnerXml + "</root>");
return GetCustomXmlElement(xmlDoc.DocumentElement);
}
private static XmlElement GetCustomXmlElement(XmlElement root, string version)
{
XmlElement customXml = GetCustomXmlElement(root);
if (customXml != null)
{
XmlNodeList versionNodes = customXml.GetElementsByTagName("Version");
foreach (XmlNode thisNode in versionNodes)
{
if (thisNode.Attributes["value"].Value == version)
{
XmlDocument thisDoc = new XmlDocument();
thisDoc.LoadXml("<root>" + thisNode.InnerXml + "</root>");
return thisDoc.DocumentElement;
}
}
}
return null;
}
private static XmlElement GetCustomXmlElement(XmlElement root, string version, string tagName)
{
XmlElement customXml = GetCustomXmlElement(root, version);
if (customXml != null)
{
XmlNodeList tagNodes = customXml.GetElementsByTagName(tagName);
if (tagNodes != null && tagNodes.Count > 0)
{
XmlDocument thisDoc = new XmlDocument();
thisDoc.LoadXml("<root>" + tagNodes[0].InnerXml + "</root>");
return thisDoc.DocumentElement;
}
}
return null;
}
private static XmlElement GetCustomXmlElement(XmlNode root, string version, string tagName)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" + root.InnerXml + "</root>");
return GetCustomXmlElement(xmlDoc.DocumentElement, version, tagName);
}
/// <summary>
/// Creates a node of type ReportTreeNode based on information specified from the XML report
/// configuration file.
/// </summary>
/// <param name="currentNode">Current report XML node from config file</param>
/// <returns></returns>
private TreeNode GetReportTreeNode(XmlNode currentNode)
{
string nodeFileName;
string nodeNameLabel;
string nodeReportDefinition;
bool nodeDisplayHosts;
bool nodeDisplayFilter;
bool nodeDisplayUsers;
bool nodeDisplayAuditObjects;
OrderedDictionary nodeParamDict;
WlbReportInfo reportInfo;
TreeNode reportTreeNode;
nodeFileName = currentNode.Attributes["File"].Value;
XmlElement queryParametersXmlElement = GetCustomXmlElement(currentNode, "Creedence", "QueryParameters");
// If the report definition node doesn't exist (old WLB version), load the definition from the
// local file system. Otherwise, the definition is present in the config from the WLB server
if (currentNode.SelectSingleNode(@"Rdlc") == null)
{
XmlDocument xmlReportDefinition = new XmlDocument();
xmlReportDefinition.Load(String.Format(@"{0}\{1}", Application.StartupPath.ToString(), nodeFileName));
nodeReportDefinition = xmlReportDefinition.OuterXml.ToString();
}
else
{
nodeReportDefinition = currentNode.SelectSingleNode(@"Rdlc").InnerText;
}
// If the report definition was obtained from the WLB server, use the localized name provided.
// Otherwise, get the label locally. If all else fails, just use NameLabel attribute from
// xml config
if (currentNode.Attributes["Name"] != null)
{
nodeNameLabel = currentNode.Attributes["Name"].Value;
}
else if (Messages.ResourceManager.GetObject(currentNode.Attributes["NameLabel"].Value) != null)
{
nodeNameLabel = Messages.ResourceManager.GetObject(currentNode.Attributes["NameLabel"].Value).ToString();
}
else
{
nodeNameLabel = currentNode.Attributes["NameLabel"].Value;
}
// Boolean variuable to determine the display the Filter drop down menu?
if (currentNode.SelectSingleNode(@"QueryParameters/QueryParameter[@Name='Filter']") == null)
{
nodeDisplayFilter = false;
}
else
{
nodeDisplayFilter = true;
}
// Boolean variuable to determine the display the Host drop down menu?
if (currentNode.SelectSingleNode(@"QueryParameters/QueryParameter[@Name='HostID']") == null)
{
nodeDisplayHosts = false;
}
else
{
nodeDisplayHosts = true;
}
// Boolean variable to determine the display of the User drop down menu
if (currentNode.SelectSingleNode(@"QueryParameters/QueryParameter[@Name='AuditUser']") == null)
{
nodeDisplayUsers = false;
}
else
{
nodeDisplayUsers = true;
}
// Boolean variable to determine the display of the Object drop down menu
if (currentNode.SelectSingleNode(@"QueryParameters/QueryParameter[@Name='AuditObject']") == null)
{
nodeDisplayAuditObjects = false;
}
else
{
nodeDisplayAuditObjects = true;
}
// Get a list of query params
nodeParamDict = GetSQLQueryParamNames(currentNode, queryParametersXmlElement);
// Create a report node and add it to the treeview for the current report
reportInfo = new WlbReportInfo(nodeNameLabel,
nodeFileName,
nodeReportDefinition,
nodeDisplayHosts,
nodeDisplayFilter,
nodeDisplayUsers,
nodeDisplayAuditObjects,
nodeParamDict);
reportTreeNode = new TreeNode();
reportTreeNode.Tag = reportInfo;
reportTreeNode.Text = nodeNameLabel;
reportTreeNode.ImageIndex = 0;
reportTreeNode.SelectedImageIndex = 0;
return reportTreeNode;
}
/// <summary>
/// Creates a treeNode for give report name and subscription object
/// </summary>
/// <param name="reportName">Name of the report that has the subscription</param>
/// <param name="subscription">Instance of a subscription</param>
/// <returns>Return a instance of TreeNode</returns>
private TreeNode GetReportSubscriptionTreeNode(WlbReportSubscription subscription)
{
TreeNode subscriptionTreeNode = new TreeNode();
subscriptionTreeNode.Text = subscription.Name;
subscriptionTreeNode.Tag = subscription;
subscriptionTreeNode.ImageIndex = 1;
subscriptionTreeNode.SelectedImageIndex = 1;
return subscriptionTreeNode;
}
/// <summary>
/// Returns a list of parameters names whose values will be required for reports' SQL query
/// to execute. These names are specified in the Report XML configuration file.
/// </summary>
/// <param name="currentNode">Current report XML node from config file</param>
/// <param name="queryParametersXmlElement">Current report XML node from config file</param>
/// <returns>OrderedDictionary of parameter names and contents whose values are required by the report SQL query</returns>
private OrderedDictionary GetSQLQueryParamNames(XmlNode currentNode, XmlElement queryParametersXmlElement)
{
OrderedDictionary paramNames = new OrderedDictionary();
XmlNodeList paramNameNodes = currentNode.SelectNodes("QueryParameters/QueryParameter");
foreach (XmlNode paramNode in paramNameNodes)
{
if (paramNode.Attributes["Name"] != null)
{
string value = paramNode.Attributes["Name"].Value;
// To implement the AuditUser and AuditObject dropdowns, the values are set
// along with parameter "AuditUser' and "AuditObject" from WLB server.
// If the query parameters contain values, store them in dictionary.
// Else just store the parameter as key with "" value.
if(_isCreedenceOrLater && queryParametersXmlElement != null)
{
XmlNodeList valueTagNodes = queryParametersXmlElement.GetElementsByTagName(value);
if (valueTagNodes != null && valueTagNodes.Count > 0)
{
paramNames.Add(value, valueTagNodes[0].InnerText);
}
else
{
paramNames.Add(value, "");
}
}
else
{
paramNames.Add(value, "");
}
}
}
return paramNames;
}
/// <summary>
/// Add subscription nodes if a report has subscriptions
/// </summary>
/// <param name="topNode">Report subscription top node</param>
/// <param name="subscriptionList">A dictionary contains WlbReportSubscription instances</param>
/// <param name="reportName">Report display name that can be added to WlbReportSubscription instance</param>
/// <param name="selectedSub">The original selected node before update</param>
private void AddNewSubscriptionNode(TreeNode subscriptionFolder, Dictionary<string, WlbReportSubscription> subscriptions, string reportName, WlbReportSubscription selectedSub)
{
foreach (WlbReportSubscription sub in subscriptions.Values)
{
sub.ReportDisplayName = reportName;
TreeNode subNode = GetReportSubscriptionTreeNode(sub);
subscriptionFolder.Nodes.Add(subNode);
// Retrieve selected subscription node if there is one
if (selectedSub != null && String.Compare(selectedSub.Id, sub.Id, true) == 0)
{
this.treeViewReportList.SelectedNode = subNode;
}
}
// Force to set selected node to the first subscription node of the report
// only if the original selected subscription node of the report has been deleted.
if (selectedSub != null && subscriptions.Count > 0 && (this.treeViewReportList.SelectedNode == null || this.treeViewReportList.SelectedNode.Tag == null))
{
this.treeViewReportList.SelectedNode = subscriptionFolder.Nodes[0];
}
}
#endregion
#region Event Handlers
/// <summary>
/// Load report form
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ReportForm_Load(object sender, EventArgs e)
{
// Add event handlers for creating/editing/deleting subscription
this.subscriptionView1.OnChangeOK += new CustomRefreshEventHandler(OnChangeOK_Refresh);
this.wlbReportView1.OnChangeOK += new CustomRefreshEventHandler(OnChangeOK_Refresh);
}
/// <summary>
/// When the report window is displayed, the current pool and a list of hosts that
/// correlate to the pool need to be set in the viewer control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WlbReportWindow_Shown(object sender, EventArgs e)
{
wlbReportView1.Pool = _pool;
subscriptionView1.Pool = _pool;
wlbReportView1.Hosts = _hosts;
// Populate report treeview with report and subscription on the top of left panel
SetTreeViewReportList();
// Populate subscription treeview with subscription on the bottom of the left panel
SetTreeViewSubscriptionList();
}
/// <summary>
/// Update report treeView and subscription treeView
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnChangeOK_Refresh(object sender, EventArgs e)
{
try
{
// set _subscriptionCollection
SetSubscriptionCollection();
// Start update treeViews
if (_subscriptionCollection != null)
{
// Update subscription treeView must be before updating report treeView
this.UpdateSubscriptionTreeView();
// Update report treeView
this.UpdateReportTreeView();
// Rebuild panel if ReportSubscriptionView is visible
if (sender is WlbReportSubscriptionView)
{
this.subscriptionView1.BuildPanel();
}
}
}
catch (Exception ex)
{
log.Debug(ex, ex);
using (var dlg = new ThreeButtonDialog(new ThreeButtonDialog.Details(SystemIcons.Error, Messages.WLBREPORT_REPORT_CONFIG_ERROR, Messages.XENCENTER)))
{
dlg.ShowDialog(this);
}
this.Close();
}
}
/// <summary>
/// Event handler addresses various UI nuances depending on the type the node selected in the tree:
/// - Hides/displays the ReportView control
/// - Hides/displays host dropdown menu in ReportView control (and it's label)
/// - Disables/enables Run Report button in ReportView control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeViewReportList_AfterSelect(object sender, TreeViewEventArgs e)
{
if (this.treeViewReportList.SelectedNode.Tag != null)
{
// Display report view if a report node gets selected
if (this.treeViewReportList.SelectedNode.Tag.GetType() == typeof(WlbReportInfo))
{
// Reset reportView and disable subscriptionView
this.subscriptionView1.Visible = false;
this.wlbReportView1.SynchReportViewer((WlbReportInfo)treeViewReportList.SelectedNode.Tag);
// Run report if necessary
if (_runReport)
{
this.wlbReportView1.ExecuteReport();
// Reset _runReport flag back to false
_runReport = false;
}
}
else
{
// Display the subscription view if it's that type of node
if (this.treeViewReportList.SelectedNode.Tag.GetType() == typeof(WlbReportSubscription))
{
// Reset subscriptionView and disable reportView
this.wlbReportView1.Visible = false;
this.subscriptionView1.ResetSubscriptionView((WlbReportSubscription)treeViewReportList.SelectedNode.Tag);
}
}
// Deselect treeViewsubscriptionList
this.treeViewSubscriptionList.SelectedNode = null;
}
}
/// <summary>
/// Event handler for the the Subscriptions list box. Displays/Hides the Report View control
/// and the Subscription View control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeViewSubscriptionList_AfterSelect(object sender, TreeViewEventArgs e)
{
// Display the subscription view if it's that type of node
if (treeViewSubscriptionList.SelectedNode.Tag != null)
{
// Reset the reportview control and hide it (if it isn't already)
this.wlbReportView1.Visible = false;
this.subscriptionView1.ResetSubscriptionView((WlbReportSubscription)treeViewSubscriptionList.SelectedNode.Tag);
// Deselect treeViewReportList
this.treeViewReportList.SelectedNode = null;
}
}
/// <summary>
/// Event handler for when a report is drilled in to from the MS Viewer inside the ReportView control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wlbReportView1_ReportDrilledThrough(object sender, DrillthroughEventArgs e)
{
SynchTreeViewReportList(e.ReportPath.ToString());
}
/// <summary>
/// Event handler for when the back button is clicked inside the reportviewer control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wlbReportView1_ReportBack(object sender, BackEventArgs e)
{
//SynchTreeViewReportList();
}
/// <summary>
/// Event handler for report close button
/// </summary>
/// <param name="sender"></param>
private void wlbReportView1_Close(object sender, EventArgs e)
{
this.Close();
this.Dispose();
}
/// <summary>
/// Event handler for a lost pool connection
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wlbReportView1_PoolConnectionLost(object sender, EventArgs e)
{
using (var dlg = new ThreeButtonDialog(new ThreeButtonDialog.Details(SystemIcons.Information, String.Format(Messages.WLB_REPORT_POOL_CONNECTION_LOST, _pool.Name()), Messages.WLBREPORT_POOL_CONNECTION_LOST_CAPTION)))
{
dlg.ShowDialog(this);
}
this.Close();
this.Dispose();
}
#endregion
}
}