diff --git a/XenAdmin/Dialogs/CallHome/CallHomeOverviewDialog.cs b/XenAdmin/Dialogs/CallHome/CallHomeOverviewDialog.cs index ab66ff9b1..53f4714c9 100644 --- a/XenAdmin/Dialogs/CallHome/CallHomeOverviewDialog.cs +++ b/XenAdmin/Dialogs/CallHome/CallHomeOverviewDialog.cs @@ -313,7 +313,7 @@ namespace XenAdmin.Dialogs.CallHome var callHomeSettings = poolRow.Pool.CallHomeSettings; if (callHomeSettings.CanRequestNewUpload) { - callHomeSettings.NewUploadRequest = DateTime.UtcNow.ToString(); + callHomeSettings.NewUploadRequest = CallHomeSettings.DateTimeToString(DateTime.UtcNow); new SaveCallHomeSettingsAction(poolRow.Pool, callHomeSettings, null, null, null, false).RunAsync(); } } diff --git a/XenModel/XenAPI-Extensions/Pool.cs b/XenModel/XenAPI-Extensions/Pool.cs index 40e325e88..519a65aba 100644 --- a/XenModel/XenAPI-Extensions/Pool.cs +++ b/XenModel/XenAPI-Extensions/Pool.cs @@ -36,6 +36,7 @@ using System.Net; using XenAdmin; using XenAdmin.Core; using XenAdmin.Network; +using System.Globalization; namespace XenAPI { @@ -559,6 +560,21 @@ namespace XenAPI { return new Random().Next(1, 5); } + + public static string DateTimeToString(DateTime dateTime) + { + // Round-trip format time + DateTime rtime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); + return rtime.ToString("o"); + } + + public static DateTime StringToDateTime(string dateTimeString) + { + // Round-trip format time + DateTime dateTime = DateTime.ParseExact(dateTimeString, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + return dateTime; + } + #endregion public string GetSecretyInfo(IXenConnection connection, string secretType) diff --git a/XenServerHealthCheck/CredentialReceiver.cs b/XenServerHealthCheck/CredentialReceiver.cs index af5960a5b..4c56de8dd 100755 --- a/XenServerHealthCheck/CredentialReceiver.cs +++ b/XenServerHealthCheck/CredentialReceiver.cs @@ -51,8 +51,11 @@ namespace XenServerHealthCheck { lock (pipeServerLock) { - pipeServer.Close(); - pipeServer = null; + if (pipeServer != null) + { + pipeServer.Close(); + pipeServer = null; + } } } diff --git a/XenServerHealthCheck/RequestUploadTask.cs b/XenServerHealthCheck/RequestUploadTask.cs index 51de15ec9..1ed277059 100755 --- a/XenServerHealthCheck/RequestUploadTask.cs +++ b/XenServerHealthCheck/RequestUploadTask.cs @@ -58,7 +58,7 @@ namespace XenServerHealthCheck } private static double DueAfterHour = 24; - private static bool CanLock(string UploadLock) + private static bool CanLock(string UploadLock, bool onDemand) { if (UploadLock.Length == 0) return true; @@ -67,6 +67,9 @@ namespace XenServerHealthCheck DateTime currentTime = DateTime.UtcNow; DateTime lockTime = DateTime.Parse(currentLock[1]); + if (currentLock[0] == Properties.Settings.Default.UUID && onDemand) + return true; + if (currentLock[0] == Properties.Settings.Default.UUID) { if ((DateTime.Compare(lockTime.AddHours(DueAfterHour), currentTime) <= 0)) @@ -80,9 +83,9 @@ namespace XenServerHealthCheck private static int SleepForLockConfirm = 10 * 1000; // 10 seconds private static bool getLock(IXenConnection connection, Session session) { - Dictionary config = new Dictionary(); + Dictionary config = Pool.get_health_check_config(session, connection.Cache.Pools[0].opaque_ref); string newUploadLock = Properties.Settings.Default.UUID; - newUploadLock += "|" + DateTime.UtcNow.ToString(); + newUploadLock += "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow); config[CallHomeSettings.UPLOAD_LOCK] = newUploadLock; Pool.set_health_check_config(session, connection.Cache.Pools[0].opaque_ref, config); System.Threading.Thread.Sleep(SleepForLockConfirm); @@ -101,7 +104,7 @@ namespace XenServerHealthCheck return false; } //Check if there already some service doing the uploading already - if (CanLock(Get(config, CallHomeSettings.UPLOAD_LOCK)) == false) + if (CanLock(Get(config, CallHomeSettings.UPLOAD_LOCK), false) == false) { log.InfoFormat("Will not report for XenServer {0} that already locked", connection.Hostname); return false; @@ -115,7 +118,8 @@ namespace XenServerHealthCheck { try { - lastSuccessfulUpload = DateTime.Parse(Get(config, CallHomeSettings.LAST_SUCCESSFUL_UPLOAD)); + + lastSuccessfulUpload = CallHomeSettings.StringToDateTime(Get(config, CallHomeSettings.LAST_SUCCESSFUL_UPLOAD)); haveSuccessfulUpload = true; } catch (Exception exn) @@ -137,7 +141,7 @@ namespace XenServerHealthCheck { try { - DateTime LastFailedUpload = DateTime.Parse(Get(config, CallHomeSettings.LAST_FAILED_UPLOAD)); + DateTime LastFailedUpload = CallHomeSettings.StringToDateTime(Get(config, CallHomeSettings.LAST_FAILED_UPLOAD)); if (haveSuccessfulUpload) { @@ -199,7 +203,7 @@ namespace XenServerHealthCheck } //Check if there already some service doing the uploading already - if (CanLock(Get(config, CallHomeSettings.UPLOAD_LOCK)) == false) + if (CanLock(Get(config, CallHomeSettings.UPLOAD_LOCK), true) == false) { log.InfoFormat("Will not report for XenServer {0} that already locked", connection.Hostname); return false; @@ -207,7 +211,8 @@ namespace XenServerHealthCheck if (config.ContainsKey(CallHomeSettings.NEW_UPLOAD_REQUEST)) { - DateTime newUploadRequestDueTime = DateTime.Parse(Get(config, CallHomeSettings.NEW_UPLOAD_REQUEST)).AddMinutes(DemandTimeOutMinutes); + + DateTime newUploadRequestDueTime = CallHomeSettings.StringToDateTime(Get(config, CallHomeSettings.NEW_UPLOAD_REQUEST)).AddMinutes(DemandTimeOutMinutes);; if (DateTime.Compare(newUploadRequestDueTime, DateTime.UtcNow) >= 0) { return getLock(connection, session); diff --git a/XenServerHealthCheck/XenServerHealthCheckBundleUpload.cs b/XenServerHealthCheck/XenServerHealthCheckBundleUpload.cs index b2f18bd79..137fb18df 100644 --- a/XenServerHealthCheck/XenServerHealthCheckBundleUpload.cs +++ b/XenServerHealthCheck/XenServerHealthCheckBundleUpload.cs @@ -1,210 +1,256 @@ -/* 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.IO; -using System.Threading; -using XenAdmin.Core; -using XenAdmin.Network; -using XenAPI; - - -namespace XenServerHealthCheck -{ - public class XenServerHealthCheckBundleUpload - { - public XenServerHealthCheckBundleUpload(IXenConnection _connection) - { - connection = _connection; - } - - private IXenConnection connection; - - private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public const int TIMEOUT = 24 * 60 * 60 * 1000; - public const int VERBOSITY_LEVEL = 2; - - public void runUpload() - { - DateTime startTime = DateTime.UtcNow; - string uploadToken = ""; - Session session = new Session(connection.Hostname, 80); - session.APIVersion = API_Version.LATEST; - - try - { - session.login_with_password(connection.Username, connection.Password); - connection.LoadCache(session); - var pool = Helpers.GetPoolOfOne(connection); - if (pool != null) - { - uploadToken = pool.CallHomeSettings.GetSecretyInfo(connection, CallHomeSettings.UPLOAD_TOKEN_SECRET); - } - - if (string.IsNullOrEmpty(uploadToken)) - { - if (session != null) - session.logout(); - session = null; - log.ErrorFormat("The upload token is not retrieved for {0}", connection.Hostname); - updateCallHomeSettings(false, startTime); - return; - } - - } - catch (Exception e) - { - if (session != null) - session.logout(); - session = null; - log.Error(e, e); - updateCallHomeSettings(false, startTime); - return; - } - - try - { - CancellationTokenSource cts = new CancellationTokenSource(); - Func upload = delegate() - { - try - { - return bundleUpload(connection, session, uploadToken, cts.Token); - } - catch (OperationCanceledException) - { - return ""; - } - }; - System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(upload); - task.Start(); - if (!task.Wait(TIMEOUT)) - { - cts.Cancel(); - updateCallHomeSettings(false, startTime); - task.Wait(); - return; - } - - if (task.Status == System.Threading.Tasks.TaskStatus.RanToCompletion) - { - string upload_uuid = task.Result; - if(!string.IsNullOrEmpty(upload_uuid)) - updateCallHomeSettings(true, startTime, upload_uuid); - else - updateCallHomeSettings(false, startTime); - } - else - updateCallHomeSettings(false, startTime); - } - catch (Exception e) - { - if (session != null) - session.logout(); - session = null; - log.Error(e, e); - updateCallHomeSettings(false, startTime); - } - - } - - public void updateCallHomeSettings(bool success, DateTime time, string uploadUuid = "") - { - Session session = new Session(connection.Hostname, 80); - session.login_with_password(connection.Username, connection.Password); - connection.LoadCache(session); - - // Round-trip format time - DateTime rtime = DateTime.SpecifyKind(time, DateTimeKind.Utc); - string stime = rtime.ToString("o"); - - // record upload_uuid, - // release the lock, - // set the time of LAST_SUCCESSFUL_UPLOAD or LAST_FAILED_UPLOAD - Dictionary config = Pool.get_health_check_config(session, connection.Cache.Pools[0].opaque_ref); - config[CallHomeSettings.UPLOAD_LOCK] = ""; - if (success) - { - config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = stime; - config[CallHomeSettings.UPLOAD_UUID] = uploadUuid; - } - else - config[CallHomeSettings.LAST_FAILED_UPLOAD] = stime; - Pool.set_health_check_config(session, connection.Cache.Pools[0].opaque_ref, config); - - if (session != null) - session.logout(); - session = null; - } - - public string bundleUpload(IXenConnection connection, Session session, string uploadToken, System.Threading.CancellationToken cancel) - { - // Collect the server status report and generate zip file to upload. - XenServerHealthCheckBugTool bugTool = new XenServerHealthCheckBugTool(); - try - { - bugTool.RunBugtool(connection, session); - } - catch (Exception e) - { - if (session != null) - session.logout(); - session = null; - log.Error(e, e); - return ""; - } - - string bundleToUpload = bugTool.outputFile; - if(string.IsNullOrEmpty(bundleToUpload) || !File.Exists(bundleToUpload)) - { - log.ErrorFormat("Server Status Report is NOT collected"); - return ""; - } - - // Upload the zip file to CIS uploading server. - XenServerHealthCheckUpload upload = new XenServerHealthCheckUpload(uploadToken, VERBOSITY_LEVEL); - string upload_uuid = upload.UploadZip(bundleToUpload, cancel); - if (File.Exists(bundleToUpload)) - File.Delete(bundleToUpload); - - // Return the uuid of upload. - if(string.IsNullOrEmpty(upload_uuid)) - { - // Fail to upload the zip to CIS server. - log.ErrorFormat("Fail to upload the Server Status Report {0} to CIS server", bundleToUpload); - return ""; - } - - return upload_uuid; - } - } -} +/* 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.IO; +using System.Threading; +using XenAdmin.Core; +using XenAdmin.Network; +using XenAPI; + + +namespace XenServerHealthCheck +{ + public class XenServerHealthCheckBundleUpload + { + public XenServerHealthCheckBundleUpload(IXenConnection _connection) + { + connection = _connection; + server.HostName = connection.Hostname; + server.UserName = connection.Username; + server.Password = connection.Password; + } + + private IXenConnection connection; + + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + public const int TIMEOUT = 24 * 60 * 60 * 1000; + public const int INTERVAL = 10 * 1000; + public const int VERBOSITY_LEVEL = 2; + private ServerInfo server = new ServerInfo(); + + public void runUpload(System.Threading.CancellationToken serviceStop) + { + DateTime startTime = DateTime.UtcNow; + string uploadToken = ""; + Session session = new Session(connection.Hostname, 80); + session.APIVersion = API_Version.LATEST; + + try + { + session.login_with_password(connection.Username, connection.Password); + connection.LoadCache(session); + var pool = Helpers.GetPoolOfOne(connection); + if (pool != null) + { + try + { + string opaqueref = Secret.get_by_uuid(session, pool.CallHomeSettings.UploadTokenSecretUuid); + uploadToken = Secret.get_value(session, opaqueref); + } + catch (Exception e) + { + log.Error("Exception getting the upload token from the xapi secret", e); + uploadToken = null; + } + } + + if (string.IsNullOrEmpty(uploadToken)) + { + if (session != null) + session.logout(); + session = null; + log.ErrorFormat("The upload token is not retrieved for {0}", connection.Hostname); + updateCallHomeSettings(false, startTime); + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + return; + } + + } + catch (Exception e) + { + if (session != null) + session.logout(); + session = null; + log.Error(e, e); + updateCallHomeSettings(false, startTime); + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + return; + } + + try + { + CancellationTokenSource cts = new CancellationTokenSource(); + Func upload = delegate() + { + try + { + return bundleUpload(connection, session, uploadToken, cts.Token); + } + catch (OperationCanceledException) + { + return ""; + } + }; + System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(upload); + task.Start(); + + // Check if the task runs to completion before timeout. + for (int i = 0; i < TIMEOUT; i += INTERVAL) + { + // If the task finishes, set CallHomeSettings accordingly. + if (task.IsCompleted || task.IsCanceled || task.IsFaulted) + { + if (task.Status == System.Threading.Tasks.TaskStatus.RanToCompletion) + { + string upload_uuid = task.Result; + if (!string.IsNullOrEmpty(upload_uuid)) + updateCallHomeSettings(true, startTime, upload_uuid); + else + updateCallHomeSettings(false, startTime); + } + else + updateCallHomeSettings(false, startTime); + + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + return; + } + + // If the main thread (XenServerHealthCheckService) stops, + // set the cancel token to notify the working task to return. + if (serviceStop.IsCancellationRequested) + { + cts.Cancel(); + updateCallHomeSettings(false, startTime); + task.Wait(); + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + return; + } + + System.Threading.Thread.Sleep(INTERVAL); + } + + // The task has run for 24h, cancel the task and mark it as a failure upload. + cts.Cancel(); + updateCallHomeSettings(false, startTime); + task.Wait(); + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + return; + } + catch (Exception e) + { + if (session != null) + session.logout(); + session = null; + log.Error(e, e); + server.task = null; + ServerListHelper.instance.UpdateServerInfo(server); + } + + } + + public void updateCallHomeSettings(bool success, DateTime time, string uploadUuid = "") + { + Session session = new Session(connection.Hostname, 80); + session.login_with_password(connection.Username, connection.Password); + connection.LoadCache(session); + + // Round-trip format time + DateTime rtime = DateTime.SpecifyKind(time, DateTimeKind.Utc); + string stime = CallHomeSettings.DateTimeToString(rtime); + + // record upload_uuid, + // release the lock, + // set the time of LAST_SUCCESSFUL_UPLOAD or LAST_FAILED_UPLOAD + Dictionary config = Pool.get_health_check_config(session, connection.Cache.Pools[0].opaque_ref); + config[CallHomeSettings.UPLOAD_LOCK] = ""; + if (success) + { + config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = stime; + config[CallHomeSettings.UPLOAD_UUID] = uploadUuid; + } + else + config[CallHomeSettings.LAST_FAILED_UPLOAD] = stime; + Pool.set_health_check_config(session, connection.Cache.Pools[0].opaque_ref, config); + + if (session != null) + session.logout(); + session = null; + } + + public string bundleUpload(IXenConnection connection, Session session, string uploadToken, System.Threading.CancellationToken cancel) + { + // Collect the server status report and generate zip file to upload. + XenServerHealthCheckBugTool bugTool = new XenServerHealthCheckBugTool(); + try + { + bugTool.RunBugtool(connection, session); + } + catch (Exception e) + { + if (session != null) + session.logout(); + session = null; + log.Error(e, e); + return ""; + } + + string bundleToUpload = bugTool.outputFile; + if(string.IsNullOrEmpty(bundleToUpload) || !File.Exists(bundleToUpload)) + { + log.ErrorFormat("Server Status Report is NOT collected"); + return ""; + } + + // Upload the zip file to CIS uploading server. + XenServerHealthCheckUpload upload = new XenServerHealthCheckUpload(uploadToken, VERBOSITY_LEVEL); + string upload_uuid = upload.UploadZip(bundleToUpload, cancel); + if (File.Exists(bundleToUpload)) + File.Delete(bundleToUpload); + + // Return the uuid of upload. + if(string.IsNullOrEmpty(upload_uuid)) + { + // Fail to upload the zip to CIS server. + log.ErrorFormat("Fail to upload the Server Status Report {0} to CIS server", bundleToUpload); + return ""; + } + + return upload_uuid; + } + } +} diff --git a/XenServerHealthCheck/XenServerHealthCheckService.cs b/XenServerHealthCheck/XenServerHealthCheckService.cs index a702b7777..ed605a948 100755 --- a/XenServerHealthCheck/XenServerHealthCheckService.cs +++ b/XenServerHealthCheck/XenServerHealthCheckService.cs @@ -42,6 +42,7 @@ namespace XenServerHealthCheck public partial class XenServerHealthCheckService : ServiceBase { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private CancellationTokenSource cts = new CancellationTokenSource(); public XenServerHealthCheckService() { @@ -91,6 +92,7 @@ namespace XenServerHealthCheck { log.Info("XenServer Health Check Service stopping..."); CredentialReceiver.instance.UnInit(); + cts.Cancel(); bool canStop; do { @@ -115,7 +117,7 @@ namespace XenServerHealthCheck List servers = ServerListHelper.instance.GetServerList(); foreach (ServerInfo server in servers) { - if(server.task != null) + if (server.task != null && (!server.task.IsCompleted || !server.task.IsCanceled || !server.task.IsFaulted)) { continue; } @@ -139,10 +141,13 @@ namespace XenServerHealthCheck XenServerHealthCheckBundleUpload upload = new XenServerHealthCheckBundleUpload(connectionInfo); Action uploadAction = delegate() { - upload.runUpload(); + upload.runUpload(cts.Token); }; System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(uploadAction); task.Start(); + + server.task = task; + ServerListHelper.instance.UpdateServerInfo(server); } session.logout(); session = null; diff --git a/XenServerHealthCheck/XenServerHealthCheckUpload.cs b/XenServerHealthCheck/XenServerHealthCheckUpload.cs index 66e755e6a..9363e6dbe 100644 --- a/XenServerHealthCheck/XenServerHealthCheckUpload.cs +++ b/XenServerHealthCheck/XenServerHealthCheckUpload.cs @@ -195,8 +195,11 @@ namespace XenServerHealthCheck } // Fail to upload the chunk for 3 times so fail the bundle upload. - log.ErrorFormat("Fail to upload the chunk"); - return ""; + if (i == 2) + { + log.ErrorFormat("Fail to upload the chunk"); + return ""; + } } } catch (Exception e) diff --git a/XenServerHealthCheckTests/CredentialTests.cs b/XenServerHealthCheckTests/CredentialTests.cs index 2c8d25c9a..46e22a495 100755 --- a/XenServerHealthCheckTests/CredentialTests.cs +++ b/XenServerHealthCheckTests/CredentialTests.cs @@ -90,19 +90,33 @@ namespace XenServerHealthCheckTests Assert.IsTrue(con.Count == conSize); - //6. semd 2 credential + //7. semd 2 credential pipeClient = new NamedPipeClientStream(".", CallHomeSettings.HEALTH_CHECK_PIPE, PipeDirection.Out); pipeClient.Connect(); - HostName = "host1"; + HostName = "host3"; credential = EncryptionUtils.ProtectForLocalMachine(String.Join(SEPARATOR.ToString(), new[] { HostName, UserName, Password })); pipeClient.Write(Encoding.UTF8.GetBytes(credential), 0, credential.Length); - HostName = "host2"; + HostName = "host4"; credential = EncryptionUtils.ProtectForLocalMachine(String.Join(SEPARATOR.ToString(), new[] { HostName, UserName, Password })); pipeClient.Write(Encoding.UTF8.GetBytes(credential), 0, credential.Length); pipeClient.Close(); System.Threading.Thread.Sleep(1000); con = ServerListHelper.instance.GetServerList(); Assert.IsTrue(con.Count == conSize + 2); + + //8. remove 2 credential + pipeClient = new NamedPipeClientStream(".", CallHomeSettings.HEALTH_CHECK_PIPE, PipeDirection.Out); + pipeClient.Connect(); + HostName = "host3"; + credential = EncryptionUtils.ProtectForLocalMachine(String.Join(SEPARATOR.ToString(), new[] { HostName })); + pipeClient.Write(Encoding.UTF8.GetBytes(credential), 0, credential.Length); + HostName = "host4"; + credential = EncryptionUtils.ProtectForLocalMachine(String.Join(SEPARATOR.ToString(), new[] { HostName })); + pipeClient.Write(Encoding.UTF8.GetBytes(credential), 0, credential.Length); + pipeClient.Close(); + System.Threading.Thread.Sleep(1000); + con = ServerListHelper.instance.GetServerList(); + Assert.IsTrue(con.Count == conSize); } catch (Exception) { } diff --git a/XenServerHealthCheckTests/RequestUploadTaskTests.cs b/XenServerHealthCheckTests/RequestUploadTaskTests.cs index 373aeff06..dedd9212e 100755 --- a/XenServerHealthCheckTests/RequestUploadTaskTests.cs +++ b/XenServerHealthCheckTests/RequestUploadTaskTests.cs @@ -90,20 +90,20 @@ namespace XenServerHealthCheckTests //2.If the lock has already set by current service and not due, the lock should not been set again. config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + DateTime.UtcNow.ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.Request(connection, _session)); //3. If the lock already due or no one set the lock, but current schedule DayOfWeek and TimeOfDay is not correct, the lock should not been set. config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.Request(connection, _session)); //4. For lock due or not set by others and schedule meet, lock should be set. config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); config[CallHomeSettings.DAY_OF_WEEK] = DateTime.UtcNow.DayOfWeek.ToString(); config[CallHomeSettings.TIME_OF_DAY] = DateTime.UtcNow.Hour.ToString(); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); @@ -111,13 +111,13 @@ namespace XenServerHealthCheckTests //5. For Lock set by other service and not due, the lock should not been set by us. config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + DateTime.UtcNow.ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.Request(connection, _session)); //6. For Lock set by other service but already due, the lock can be set by current service config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); config[CallHomeSettings.DAY_OF_WEEK] = DateTime.UtcNow.DayOfWeek.ToString(); config[CallHomeSettings.TIME_OF_DAY] = DateTime.UtcNow.Hour.ToString(); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); @@ -125,27 +125,27 @@ namespace XenServerHealthCheckTests //7 Check LastFailedUpload is not empty and > LastSuccessfulUpload && INTERVAL_IN_DAYS using default, lock can be set config = cleanStack(); - config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); - config[CallHomeSettings.LAST_FAILED_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(8)).ToString(); + config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); + config[CallHomeSettings.LAST_FAILED_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(8))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsTrue(RequestUploadTask.Request(connection, _session)); //8 For not due uploading, lock should not been set config = cleanStack(); - config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(6)).ToString(); + config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(6))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.Request(connection, _session)); //9 For failed upload, retry was needed but not meet RetryIntervalInDays, lock should not been set config = cleanStack(); - config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); - config[CallHomeSettings.LAST_FAILED_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(5)).ToString(); + config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); + config[CallHomeSettings.LAST_FAILED_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(5))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.Request(connection, _session)); //10 For failed upload, retry was needed and meet RetryIntervalInDays, lock should be set config = cleanStack(); - config[CallHomeSettings.LAST_FAILED_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(7)).ToString(); + config[CallHomeSettings.LAST_FAILED_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(7))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsTrue(RequestUploadTask.Request(connection, _session)); @@ -153,13 +153,13 @@ namespace XenServerHealthCheckTests //11 Retry needed because no LAST_SUCCESSFUL_UPLOAD but not meet RetryIntervalInDays, lock should not be set config = cleanStack(); config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = ""; - config[CallHomeSettings.LAST_FAILED_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(8)).ToString(); + config[CallHomeSettings.LAST_FAILED_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(8))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsTrue(RequestUploadTask.Request(connection, _session)); //12 For no LAST_FAILED_UPLOAD or invalid LAST_FAILED_UPLOAD, lock should not be set if not due config = cleanStack(); - config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = DateTime.UtcNow.Subtract(TimeSpan.FromDays(13)).ToString(); + config[CallHomeSettings.LAST_SUCCESSFUL_UPLOAD] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(13))); config[CallHomeSettings.LAST_FAILED_UPLOAD] = "asd"; Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse (RequestUploadTask.Request(connection, _session)); @@ -180,29 +180,29 @@ namespace XenServerHealthCheckTests connection.LoadCache(_session); //1 Uploading is inprocess by current service, demand will be ignore config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + DateTime.UtcNow.ToString(); - config[CallHomeSettings.NEW_UPLOAD_REQUEST] = DateTime.UtcNow.ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = UUID + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow); + config[CallHomeSettings.NEW_UPLOAD_REQUEST] = CallHomeSettings.DateTimeToString(DateTime.UtcNow); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.OnDemandRequest(connection, _session)); //2 Uploading is inprocess by other service, demand will be ignore config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + DateTime.UtcNow.ToString(); - config[CallHomeSettings.NEW_UPLOAD_REQUEST] = DateTime.UtcNow.ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow); + config[CallHomeSettings.NEW_UPLOAD_REQUEST] = CallHomeSettings.DateTimeToString(DateTime.UtcNow); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.OnDemandRequest(connection, _session)); //3 Uploading is not due and demand due, demand will be ignore config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); - config[CallHomeSettings.NEW_UPLOAD_REQUEST] = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(31)).ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); + config[CallHomeSettings.NEW_UPLOAD_REQUEST] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(31))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsFalse(RequestUploadTask.OnDemandRequest(connection, _session)); //4 Uploading is due and demand not due, lock will be set config = cleanStack(); - config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + DateTime.UtcNow.Subtract(TimeSpan.FromDays(14)).ToString(); - config[CallHomeSettings.NEW_UPLOAD_REQUEST] = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(28)).ToString(); + config[CallHomeSettings.UPLOAD_LOCK] = "test2-test2" + "|" + CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromDays(14))); + config[CallHomeSettings.NEW_UPLOAD_REQUEST] = CallHomeSettings.DateTimeToString(DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(28))); Pool.set_health_check_config(_session, connection.Cache.Pools[0].opaque_ref, config); Assert.IsTrue(RequestUploadTask.OnDemandRequest(connection, _session)); }