Merge pull request #1817 from GaborApatiNagy/master_new

CA-267330: [Update Wizard Improvements] The Update wizard: block the installation of an update on slaves if a reboot or a toolstack restart is pending on master
This commit is contained in:
Joey 2017-10-18 09:53:51 +01:00 committed by GitHub
commit 2dc9c00e41
6 changed files with 329 additions and 9 deletions

View File

@ -0,0 +1,130 @@
/* 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.Collections.Generic;
using System.Linq;
using XenAdmin.Core;
using XenAdmin.Diagnostics.Hotfixing;
using XenAdmin.Diagnostics.Problems;
using XenAdmin.Diagnostics.Problems.HostProblem;
using XenAdmin.Diagnostics.Problems.PoolProblem;
using XenAPI;
namespace XenAdmin.Diagnostics.Checks
{
class RestartHostOrToolstackPendingOnMasterCheck : Check
{
public string UpdateUuid { get; private set; }
private readonly Pool pool;
public RestartHostOrToolstackPendingOnMasterCheck(Pool pool, string updateUuid)
: base(Helpers.GetMaster(pool.Connection))
{
this.pool = pool;
this.UpdateUuid = updateUuid;
}
protected override Problem RunCheck()
{
if (!Host.IsLive())
return new HostNotLiveWarning(this, Host);
var elyOrGreater = Helpers.ElyOrGreater(Host);
double bootTime = Host.BootTime();
double agentStart = Host.AgentStartTime();
//check reboot
if (elyOrGreater)
{
foreach (var updateRef in Host.updates_requiring_reboot)
{
var update = Host.Connection.Resolve(updateRef);
if (string.IsNullOrEmpty(UpdateUuid) || //automated mode, any update
string.Equals(update.uuid, UpdateUuid, System.StringComparison.InvariantCultureIgnoreCase)) //normal mode the given update
{
return new MasterIsPendingRestartHostProblem(this, pool);
}
}
}
else
{
if (bootTime == 0.0 || agentStart == 0.0)
return null; //fine
var hostRestartRequiredPatches = Host.AppliedPatches().Where(p => p.after_apply_guidance.Contains(after_apply_guidance.restartHost) && ((double)Util.ToUnixTime(p.AppliedOn(Host)) > agentStart));
foreach (Pool_patch patch in hostRestartRequiredPatches)
{
if (string.IsNullOrEmpty(UpdateUuid) //automated mode, any update
|| string.Equals(patch.uuid, UpdateUuid, System.StringComparison.InvariantCultureIgnoreCase)) //normal mode the given update
{
return new MasterIsPendingRestartHostProblem(this, pool);
}
}
}
//check toolstack restart
var toolstackRestartRequiredPatches = Host.AppliedPatches().Where(p => p.after_apply_guidance.Contains(after_apply_guidance.restartXAPI) && ((double)Util.ToUnixTime(p.AppliedOn(Host)) > agentStart));
foreach (Pool_patch patch in toolstackRestartRequiredPatches)
{
if (string.IsNullOrEmpty(UpdateUuid)) //automated mode
{
return new MasterIsPendingRestartToolstackProblem(this, pool);
}
if (!elyOrGreater) //normal mode pre-Ely
{
if (bootTime == 0.0 || agentStart == 0.0)
return null; //fine
if (string.Equals(patch.uuid, UpdateUuid, System.StringComparison.InvariantCultureIgnoreCase))
return new MasterIsPendingRestartToolstackProblem(this, pool);
}
else //normal mode Ely+
{
var poolUpdate = Host.Connection.Resolve(patch.pool_update);
if (poolUpdate != null && string.Equals(UpdateUuid, poolUpdate.uuid, System.StringComparison.InvariantCultureIgnoreCase))
{
return new MasterIsPendingRestartToolstackProblem(this, pool);
}
}
}
return null;
}
public override string Description
{
get { return Messages.PENDING_RESTART_CHECK; }
}
}
}

View File

@ -0,0 +1,94 @@
/* 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.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using XenAdmin.Core;
using XenAdmin.Diagnostics.Checks;
using XenAdmin.Diagnostics.Hotfixing;
using XenAdmin.Properties;
using XenAPI;
namespace XenAdmin.Diagnostics.Problems.PoolProblem
{
class MasterIsPendingRestartHostProblem : PoolProblem
{
public MasterIsPendingRestartHostProblem(RestartHostOrToolstackPendingOnMasterCheck check, Pool pool)
: base(check, pool)
{ }
public override string Description
{
get
{
return string.Format(
((RestartHostOrToolstackPendingOnMasterCheck)Check).UpdateUuid != null
? Messages.PROBLEM_MASTER_PENDING_RESTART_HOST_THIS_UPDATE
: Messages.PROBLEM_MASTER_PENDING_RESTART_HOST,
Helpers.GetName(Pool).Ellipsise(30));
}
}
public override string HelpMessage
{
get { return null; }
}
}
class MasterIsPendingRestartToolstackProblem : PoolProblem
{
public MasterIsPendingRestartToolstackProblem(RestartHostOrToolstackPendingOnMasterCheck check, Pool pool)
: base(check, pool)
{ }
public override string Description
{
get
{
return string.Format(
((RestartHostOrToolstackPendingOnMasterCheck)Check).UpdateUuid != null
? Messages.PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK_THIS_UPDATE
: Messages.PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK,
Helpers.GetName(Pool).Ellipsise(30));
}
}
public override string HelpMessage
{
get { return null; }
}
}
}

View File

@ -493,6 +493,17 @@ namespace XenAdmin.Wizards.PatchingWizard
}
}
if (patch != null || WizardMode == WizardMode.AutomatedUpdates)
{
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_FOR_PENDING_RESTART, new List<Check>()));
checkGroup = checks[checks.Count - 1].Value;
foreach (var pool in SelectedPools)
{
checkGroup.Add(new RestartHostOrToolstackPendingOnMasterCheck(pool, WizardMode == WizardMode.AutomatedUpdates ? null : patch.uuid));
}
}
return checks;
}
@ -541,6 +552,17 @@ namespace XenAdmin.Wizards.PatchingWizard
}
}
if (update != null || WizardMode == WizardMode.AutomatedUpdates)
{
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_FOR_PENDING_RESTART, new List<Check>()));
checkGroup = checks[checks.Count - 1].Value;
foreach (var pool in SelectedPools)
{
checkGroup.Add(new RestartHostOrToolstackPendingOnMasterCheck(pool, WizardMode == WizardMode.AutomatedUpdates ? null : update.uuid));
}
}
return checks;
}

View File

@ -224,10 +224,12 @@
<Compile Include="Diagnostics\Checks\AssertCanEvacuateCheck.cs" />
<Compile Include="Diagnostics\Checks\AssertCanEvacuateUpgradeCheck.cs" />
<Compile Include="Diagnostics\Checks\DiskSpaceForBatchUpdatesCheck.cs" />
<Compile Include="Diagnostics\Checks\RebootPendingOnMasterCheck.cs" />
<Compile Include="Diagnostics\Checks\HostNeedsRebootCheck.cs" />
<Compile Include="Diagnostics\Checks\SafeToUpgradeCheck.cs" />
<Compile Include="Diagnostics\Checks\HostHasUnsupportedStorageLinkSRCheck.cs" />
<Compile Include="Diagnostics\Checks\XenCenterVersionCheck.cs" />
<Compile Include="Diagnostics\Problems\PoolProblem\MasterIsPendingRestartProblems.cs" />
<Compile Include="Diagnostics\Problems\HostProblem\PrerequisiteUpdateMissing.cs" />
<Compile Include="Diagnostics\Problems\HostProblem\HostNeedsReboot.cs" />
<Compile Include="Diagnostics\Problems\HostProblem\HostNotSafeToUpgradeWarning.cs" />

View File

@ -6785,6 +6785,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Checking for pending restart.
/// </summary>
public static string CHECKING_FOR_PENDING_RESTART {
get {
return ResourceManager.GetString("CHECKING_FOR_PENDING_RESTART", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Checking HA and WLB status.
/// </summary>
@ -27316,6 +27325,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Pending restart check.
/// </summary>
public static string PENDING_RESTART_CHECK {
get {
return ResourceManager.GetString("PENDING_RESTART_CHECK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Interval must be a multiple of 5.
/// </summary>
@ -28209,6 +28227,42 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to {0}: The master needs to be rebooted first.
/// </summary>
public static string PROBLEM_MASTER_PENDING_RESTART_HOST {
get {
return ResourceManager.GetString("PROBLEM_MASTER_PENDING_RESTART_HOST", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}: This update requires the master to be rebooted first.
/// </summary>
public static string PROBLEM_MASTER_PENDING_RESTART_HOST_THIS_UPDATE {
get {
return ResourceManager.GetString("PROBLEM_MASTER_PENDING_RESTART_HOST_THIS_UPDATE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}: Toolstack on master needs to be restarted first.
/// </summary>
public static string PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK {
get {
return ResourceManager.GetString("PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}: This update requires the toolstack on master to be restarted first.
/// </summary>
public static string PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK_THIS_UPDATE {
get {
return ResourceManager.GetString("PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK_THIS_UPDATE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pool &apos;{0}&apos;.
/// </summary>

View File

@ -291,15 +291,15 @@
<data name="ACTION_DISABLED_PVS_READ_CACHING" xml:space="preserve">
<value>Disabled PVS-Accelerator for selected VMs</value>
</data>
<data name="ACTION_DISABLE_IGMP_SNOOPING" xml:space="preserve">
<value>Disable IGMP snooping</value>
</data>
<data name="ACTION_DISABLE_CHANGED_BLOCK_TRACKING" xml:space="preserve">
<value>Disable Changed Block Tracking</value>
</data>
<data name="ACTION_DISABLE_CHANGED_BLOCK_TRACKING_FOR" xml:space="preserve">
<value>Disabling Changed Block Tracking for VM '{0}'</value>
</data>
<data name="ACTION_DISABLE_IGMP_SNOOPING" xml:space="preserve">
<value>Disable IGMP snooping</value>
</data>
<data name="ACTION_DISABLE_LIVE_PATCHING" xml:space="preserve">
<value>Disable live patching</value>
</data>
@ -2465,6 +2465,9 @@ Do you want to assign it to the schedule '{2}' instead?</value>
<data name="CHECKING_CANEVACUATE_STATUS" xml:space="preserve">
<value>Checking VM migration status</value>
</data>
<data name="CHECKING_FOR_PENDING_RESTART" xml:space="preserve">
<value>Checking for pending restart</value>
</data>
<data name="CHECKING_HA_STATUS" xml:space="preserve">
<value>Checking HA and WLB status</value>
</data>
@ -6846,8 +6849,8 @@ Size: {3}</value>
<data name="LICENSE_ERROR_TITLE" xml:space="preserve">
<value>Licensing Error</value>
</data>
<data name="LICENSE_UNLICENSED" xml:space="preserve">
<value>Unlicensed</value>
<data name="LICENSE_EXPIRED" xml:space="preserve">
<value>License expired</value>
</data>
<data name="LICENSE_EXPIRED_NO_LICENSES_AVAILABLE" xml:space="preserve">
<value>No licenses available</value>
@ -6871,9 +6874,6 @@ Size: {3}</value>
<value>[XenServer] Online</value>
<comment>this text could be improved</comment>
</data>
<data name="LICENSE_EXPIRED" xml:space="preserve">
<value>License expired</value>
</data>
<data name="LICENSE_FIELD_DISABLED" xml:space="preserve">
<value>This field is disabled due to license restrictions on the server.</value>
</data>
@ -6972,6 +6972,9 @@ Standard features only</value>
<data name="LICENSE_TOO_MANY_SERVERS_SELECTED_CAPTION" xml:space="preserve">
<value>Activation keys can only be applied to one Free [XenServer] product at a time.</value>
</data>
<data name="LICENSE_UNLICENSED" xml:space="preserve">
<value>Unlicensed</value>
</data>
<data name="LICENSE_UNSUPPORTED" xml:space="preserve">
<value>Unsupported</value>
</data>
@ -9508,6 +9511,9 @@ File not found</value>
<data name="PDSECTION_TITLE" xml:space="preserve">
<value>Title</value>
</data>
<data name="PENDING_RESTART_CHECK" xml:space="preserve">
<value>Pending restart check</value>
</data>
<data name="PERFORMANCE_TAB_TITLE" xml:space="preserve">
<value>Performance Graphs</value>
</data>
@ -9807,6 +9813,18 @@ Please reconnect the host and try again</value>
<data name="PROBLEM_MAC_ADDRESS_IS_DUPLICATE_TITLE" xml:space="preserve">
<value>Duplicate MAC address</value>
</data>
<data name="PROBLEM_MASTER_PENDING_RESTART_HOST" xml:space="preserve">
<value>{0}: The master needs to be rebooted first</value>
</data>
<data name="PROBLEM_MASTER_PENDING_RESTART_HOST_THIS_UPDATE" xml:space="preserve">
<value>{0}: This update requires the master to be rebooted first</value>
</data>
<data name="PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK" xml:space="preserve">
<value>{0}: Toolstack on master needs to be restarted first</value>
</data>
<data name="PROBLEM_MASTER_PENDING_RESTART_TOOLSTACK_THIS_UPDATE" xml:space="preserve">
<value>{0}: This update requires the toolstack on master to be restarted first</value>
</data>
<data name="PROBLEM_POOLPROBLEM_TITLE" xml:space="preserve">
<value>Pool '{0}'</value>
</data>