mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 14:27:26 +01:00
Merge pull request #930 from MihaelaStoica/CA-206761
CA-206761: Health Check shows "No issues found" when the report analysis is not yet available
This commit is contained in:
commit
dc35b2549d
78
XenAdminTests/UnitTests/HealthCheckAnalysisProgressTest.cs
Normal file
78
XenAdminTests/UnitTests/HealthCheckAnalysisProgressTest.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* 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 NUnit.Framework;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
|
||||||
|
namespace XenAdminTests.UnitTests
|
||||||
|
{
|
||||||
|
[TestFixture, Category(TestCategories.Unit)]
|
||||||
|
public class HealthCheckAnalysisProgressTest
|
||||||
|
{
|
||||||
|
private Dictionary<string, double> expectedResults = new Dictionary<string, double>()
|
||||||
|
{
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 0 }", 0 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 10 }", 10 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 100 }", 100 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 100.0 }", 100 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 0.01 }", 0.01 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 99.99 }", 99.99 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 10, \"131-435\" : 12 }", 10 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1\" : 12, \"30253b07-138a-1b17-80a1-117317ded3ca\" : 10 }", 10 },
|
||||||
|
{ "{ 30253b07-138a-1b17-80a1-117317ded3ca : 10 }", 10 },
|
||||||
|
{ "{ 30253b07-138a-1b17-80a1-117317ded3ca : 10, 2345: 25 }", 10 },
|
||||||
|
{ "{ 2345: 25, 30253b07-138a-1b17-80a1-117317ded3ca : 10 }", 10 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : not a number }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : \"not a number\" }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : \"10\" }", 10 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : \"-10\" }", -1},
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : -0.56 }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : -10 }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : -100 }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 123 }", -1 },
|
||||||
|
{ "{ \"30253b07-138a-1b17-80a1-117317ded3ca\" : 123.89 }", -1 },
|
||||||
|
{ string.Empty, -1 },
|
||||||
|
{ " ", -1 },
|
||||||
|
{ "{ }", -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
foreach (var expectedResult in expectedResults)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(expectedResult.Value, GetHealthCheckAnalysisResultAction.ParseAnalysisProgress(expectedResult.Key, "30253b07-138a-1b17-80a1-117317ded3ca"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -68,6 +68,7 @@
|
|||||||
<Compile Include="HealthCheckTests\CredentialTests.cs" />
|
<Compile Include="HealthCheckTests\CredentialTests.cs" />
|
||||||
<Compile Include="HealthCheckTests\RequestUploadTaskTests.cs" />
|
<Compile Include="HealthCheckTests\RequestUploadTaskTests.cs" />
|
||||||
<Compile Include="UnitTests\CPUFeaturesTest.cs" />
|
<Compile Include="UnitTests\CPUFeaturesTest.cs" />
|
||||||
|
<Compile Include="UnitTests\HealthCheckAnalysisProgressTest.cs" />
|
||||||
<Compile Include="UnitTests\SubnetworkMaskValidatorTest.cs" />
|
<Compile Include="UnitTests\SubnetworkMaskValidatorTest.cs" />
|
||||||
<Compile Include="UnitTests\ExceptionSerializationTest.cs" />
|
<Compile Include="UnitTests\ExceptionSerializationTest.cs" />
|
||||||
<Compile Include="XenModelTests\ActionTests\ActionTest.cs" />
|
<Compile Include="XenModelTests\ActionTests\ActionTest.cs" />
|
||||||
@ -490,4 +491,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
@ -45,6 +45,7 @@ namespace XenAdmin.Actions
|
|||||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private const string DIAG_RESULT_URL = "/diag_sdk/diag_results/";
|
private const string DIAG_RESULT_URL = "/diag_sdk/diag_results/";
|
||||||
|
private const string ANALYSIS_PROGRESS_URL = "/diag_sdk/analysis_progress";
|
||||||
private readonly string diagnosticDomainName = "https://cis.citrix.com";
|
private readonly string diagnosticDomainName = "https://cis.citrix.com";
|
||||||
|
|
||||||
public GetHealthCheckAnalysisResultAction(Pool pool, bool suppressHistory)
|
public GetHealthCheckAnalysisResultAction(Pool pool, bool suppressHistory)
|
||||||
@ -71,18 +72,37 @@ namespace XenAdmin.Actions
|
|||||||
var diagnosticToken = Pool.HealthCheckSettings.GetSecretyInfo(Session, HealthCheckSettings.DIAGNOSTIC_TOKEN_SECRET);
|
var diagnosticToken = Pool.HealthCheckSettings.GetSecretyInfo(Session, HealthCheckSettings.DIAGNOSTIC_TOKEN_SECRET);
|
||||||
if (string.IsNullOrEmpty(diagnosticToken))
|
if (string.IsNullOrEmpty(diagnosticToken))
|
||||||
{
|
{
|
||||||
log.InfoFormat("Cannot get the diagnostic result for {0}, because couldn't retrieve the diagnostic token", Pool.Name);
|
log.DebugFormat("Cannot get the diagnostic result for {0}, because couldn't retrieve the diagnostic token", Pool.Name);
|
||||||
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Pool.HealthCheckSettings.HasUpload)
|
if (!Pool.HealthCheckSettings.HasUpload)
|
||||||
{
|
{
|
||||||
log.InfoFormat("Cannot get the diagnostic result for {0}, because the there is no upload completed yet", Pool.Name);
|
log.DebugFormat("Cannot get the diagnostic result for {0}, because the there is no upload completed yet", Pool.Name);
|
||||||
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var analysisProgress = GetAnalysisProgress(diagnosticToken, Pool.HealthCheckSettings.UploadUuid);
|
||||||
|
|
||||||
|
if (analysisProgress >= 0 && analysisProgress < 100) // check if the progress is a valid value less than 100
|
||||||
|
{
|
||||||
|
log.DebugFormat("Analysis for {0} not completed yet", Pool.Name);
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var analysisResult = GetAnalysisResult(diagnosticToken, Pool.HealthCheckSettings.UploadUuid);
|
var analysisResult = GetAnalysisResult(diagnosticToken, Pool.HealthCheckSettings.UploadUuid);
|
||||||
log.Info("Saving analysis result");
|
|
||||||
|
if (analysisResult.Count == 0 && analysisProgress == -1 && DateTime.Compare(Pool.HealthCheckSettings.LastSuccessfulUploadTime.AddMinutes(10), DateTime.UtcNow) > 0)
|
||||||
|
{
|
||||||
|
log.DebugFormat("Diagnostic result for {0} is empty. Maybe analysis result is not yet available", Pool.Name);
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Saving analysis result");
|
||||||
Dictionary<string, string> newConfig = Pool.health_check_config;
|
Dictionary<string, string> newConfig = Pool.health_check_config;
|
||||||
newConfig[HealthCheckSettings.REPORT_ANALYSIS_SEVERITY] = GetMaxSeverity(analysisResult).ToString();
|
newConfig[HealthCheckSettings.REPORT_ANALYSIS_SEVERITY] = GetMaxSeverity(analysisResult).ToString();
|
||||||
newConfig[HealthCheckSettings.REPORT_ANALYSIS_ISSUES_DETECTED] = GetDistinctIssueCount(analysisResult).ToString();
|
newConfig[HealthCheckSettings.REPORT_ANALYSIS_ISSUES_DETECTED] = GetDistinctIssueCount(analysisResult).ToString();
|
||||||
@ -92,7 +112,7 @@ namespace XenAdmin.Actions
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.InfoFormat("Exception while getting diagnostic result from {0}. Exception Message: {1} ", diagnosticDomainName, e.Message);
|
log.ErrorFormat("Exception while getting diagnostic result from {0}. Exception Message: {1} ", diagnosticDomainName, e.Message);
|
||||||
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
Description = Messages.ACTION_GET_HEALTH_CHECK_RESULT_FAILED;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -118,6 +138,62 @@ namespace XenAdmin.Actions
|
|||||||
return issues.Select(issue => issue.name).Distinct().Count();
|
return issues.Select(issue => issue.name).Distinct().Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to retrieve the analysis progress for a particulat upload
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="diagnosticToken"></param>
|
||||||
|
/// <param name="uploadUuid"></param>
|
||||||
|
/// <returns>the analysis progress as pecentage, or -1 if the progress cannot be retrieved</returns>
|
||||||
|
private double GetAnalysisProgress(string diagnosticToken, string uploadUuid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var urlString = string.Format("{0}{1}?upload_id={2}", diagnosticDomainName, ANALYSIS_PROGRESS_URL, uploadUuid);
|
||||||
|
var authorizationHeader = "BT " + diagnosticToken;
|
||||||
|
var httpWebRequest = (HttpWebRequest)WebRequest.Create(urlString);
|
||||||
|
httpWebRequest.Headers.Add("Authorization", authorizationHeader);
|
||||||
|
httpWebRequest.Method = "GET";
|
||||||
|
|
||||||
|
string result;
|
||||||
|
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
|
||||||
|
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||||
|
{
|
||||||
|
result = streamReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseAnalysisProgress(result, uploadUuid);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.DebugFormat("Exception while getting analysis progress result from {0}. Exception Message: {1} ", diagnosticDomainName, e.Message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialize the analysis progress from a JSON object that has "upload_id" as key and a number (percentage from 0 to 100) as a value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="jsonString"></param>
|
||||||
|
/// <param name="uploadUuid"></param>
|
||||||
|
/// <returns>the analysis progress as pecentage, or -1 if the JSON object is invalid</returns>
|
||||||
|
public static double ParseAnalysisProgress(string jsonString, string uploadUuid)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(jsonString))
|
||||||
|
return -1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serializer = new JavaScriptSerializer();
|
||||||
|
Dictionary<string, object> result = serializer.DeserializeObject(jsonString) as Dictionary<string, object>;
|
||||||
|
var progress = result != null && result.ContainsKey(uploadUuid) ? Convert.ToDouble(result[uploadUuid]) : -1;
|
||||||
|
return progress >= 0 && progress <= 100 ? progress : -1;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.DebugFormat("Exception while deserializing json: {0}. Exception Message: {1} ", jsonString, e.Message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<AnalysisResult> GetAnalysisResult(string diagnosticToken, string uploadUuid)
|
private List<AnalysisResult> GetAnalysisResult(string diagnosticToken, string uploadUuid)
|
||||||
{
|
{
|
||||||
var urlString = string.Format("{0}{1}?upload_uuid={2}", diagnosticDomainName, DIAG_RESULT_URL, uploadUuid);
|
var urlString = string.Format("{0}{1}?upload_uuid={2}", diagnosticDomainName, DIAG_RESULT_URL, uploadUuid);
|
||||||
|
Loading…
Reference in New Issue
Block a user