2017-01-16 20:59:50 +01:00
/ * Copyright ( c ) Citrix Systems , Inc .
2013-06-24 13:41:48 +02:00
* 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 .
* /
2018-06-21 13:28:49 +02:00
using System ;
2013-06-24 13:41:48 +02:00
using System.Collections.Generic ;
using System.Drawing ;
using System.Linq ;
2018-06-21 13:28:49 +02:00
using System.Windows.Forms ;
2018-06-22 11:58:08 +02:00
using XenAdmin.Core ;
2018-06-21 13:28:49 +02:00
using XenAdmin.Dialogs ;
using XenAdmin.Wizards.PatchingWizard ;
using XenAdmin.Wizards.PatchingWizard.PlanActions ;
2013-06-24 13:41:48 +02:00
using XenAdmin.Wizards.RollingUpgradeWizard.PlanActions ;
2018-06-21 13:28:49 +02:00
using XenAPI ;
2013-06-24 13:41:48 +02:00
namespace XenAdmin.Wizards.RollingUpgradeWizard
{
2018-06-21 13:28:49 +02:00
public partial class RollingUpgradeUpgradePage : AutomatedUpdatesBasePage
2013-06-24 13:41:48 +02:00
{
public RollingUpgradeUpgradePage ( )
{
InitializeComponent ( ) ;
}
#region XenTabPage overrides
public override string PageTitle { get { return Messages . UPGRADE_PLAN ; } }
public override string Text { get { return Messages . UPGRADE_PLAN ; } }
public override string HelpID { get { return "Upgradepools" ; } }
#endregion
#region Accessors
public bool ManualModeSelected { private get ; set ; }
public Dictionary < string , string > InstallMethodConfig { private get ; set ; }
#endregion
2018-06-21 13:28:49 +02:00
#region AutomatedUpdatesBesePage overrides
2018-06-22 16:57:31 +02:00
protected override string BlurbText ( )
{
return Messages . ROLLING_UPGRADE_UPGRADE_IN_PROGRESS ;
}
protected override string SuccessMessageOnCompletion ( bool multiplePools )
2013-06-24 13:41:48 +02:00
{
2018-06-22 16:57:31 +02:00
return multiplePools ? Messages . ROLLING_UPGRADE_SUCCESS_MANY : Messages . ROLLING_UPGRADE_SUCCESS_ONE ;
}
protected override string FailureMessageOnCompletion ( bool multiplePools )
{
return multiplePools ? Messages . ROLLING_UPGRADE_ERROR_MANY : Messages . ROLLING_UPGRADE_ERROR_ONE ;
}
protected override string SuccessMessagePerPool ( )
{
return Messages . ROLLING_UPGRADE_SUCCESS_ONE ;
}
protected override string FailureMessagePerPool ( bool multipleErrors )
{
return multipleErrors ? Messages . ROLLING_UPGRADE_ERROR_POOL_MANY : Messages . ROLLING_UPGRADE_ERROR_POOL_ONE ;
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
protected override void GeneratePlanActions ( Pool pool , List < HostPlanActions > planActions , List < PlanAction > finalActions )
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
//Add masters first, then the slaves that are not ugpraded
var hostNeedUpgrade = pool . HostsToUpgrade ( ) ;
foreach ( var host in hostNeedUpgrade )
2013-06-24 13:41:48 +02:00
{
2018-06-22 11:58:08 +02:00
planActions . Add ( GetSubTasksFor ( host ) ) ;
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
//add a revert pre-check action for this pool
var problemsToRevert = ProblemsResolvedPreCheck . Where ( p = > hostNeedUpgrade . ToList ( ) . Select ( h = > h . uuid ) . ToList ( ) . Contains ( p . Check . Host . uuid ) ) . ToList ( ) ;
if ( problemsToRevert . Count > 0 )
finalActions . Add ( new UnwindProblemsAction ( problemsToRevert , string . Format ( Messages . REVERTING_RESOLVED_PRECHECKS_POOL , pool . Connection . Name ) ) ) ;
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
protected override bool ManageSemiAutomaticPlanAction ( UpdateProgressBackgroundWorker bgw , PlanAction planAction )
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
var upgradeHostPlanAction = planAction as UpgradeManualHostPlanAction ;
if ( upgradeHostPlanAction = = null | | ! upgradeHostPlanAction . IsManual )
return false ;
2013-06-24 13:41:48 +02:00
//Show dialog prepare host boot from CD or PXE boot and click OK to reboot
2018-06-21 13:28:49 +02:00
string msg = string . Format ( Messages . ROLLING_UPGRADE_REBOOT_MESSAGE , upgradeHostPlanAction . GetResolvedHost ( ) . Name ( ) ) ;
2013-06-24 13:41:48 +02:00
UpgradeManualHostPlanAction action = upgradeHostPlanAction ;
2015-04-16 15:17:02 +02:00
Program . Invoke ( this , ( ) = >
2013-06-24 13:41:48 +02:00
{
2018-06-22 17:29:38 +02:00
using ( var dialog = new NonModalThreeButtonDialog ( SystemIcons . Information , msg , Messages . REBOOT , Messages . SKIP_SERVER ) )
2013-06-24 13:41:48 +02:00
{
2018-06-23 00:44:40 +02:00
if ( dialog . ShowDialog ( this ) ! = DialogResult . OK ) // Cancel or Unknown
2013-06-24 13:41:48 +02:00
{
2018-03-06 16:12:04 +01:00
if ( action . GetResolvedHost ( ) . IsMaster ( ) )
2018-06-21 13:28:49 +02:00
{
action . Error = new ApplicationException ( Messages . EXCEPTION_USER_CANCELLED_MASTER ) ;
throw action . Error ;
}
action . Error = new CancelledException ( ) ;
2013-06-24 13:41:48 +02:00
}
}
} ) ;
2018-06-21 13:28:49 +02:00
if ( action . Error ! = null )
return true ;
2018-03-06 16:12:04 +01:00
string beforeRebootProductVersion = upgradeHostPlanAction . GetResolvedHost ( ) . LongProductVersion ( ) ;
string hostName = upgradeHostPlanAction . GetResolvedHost ( ) . Name ( ) ;
upgradeHostPlanAction . Timeout + = upgradeHostPlanAction_Timeout ;
2013-06-24 13:41:48 +02:00
try
{
do
{
2018-06-21 13:28:49 +02:00
if ( bgw . CancellationPending )
2013-06-24 13:41:48 +02:00
break ;
//Reboot with timeout of 20 min
upgradeHostPlanAction . Run ( ) ;
//if comes back and does not have a different product version
2018-03-06 16:12:04 +01:00
if ( Helpers . SameServerVersion ( upgradeHostPlanAction . GetResolvedHost ( ) , beforeRebootProductVersion ) )
2013-06-24 13:41:48 +02:00
{
2018-06-22 17:29:38 +02:00
using ( var dialog = new NonModalThreeButtonDialog ( SystemIcons . Exclamation ,
2013-06-24 13:41:48 +02:00
string . Format ( Messages . ROLLING_UPGRADE_REBOOT_AGAIN_MESSAGE , hostName )
, Messages . REBOOT_AGAIN_BUTTON_LABEL , Messages . SKIP_SERVER ) )
{
2015-04-16 15:17:02 +02:00
Program . Invoke ( this , ( ) = > dialog . ShowDialog ( this ) ) ;
2013-06-24 13:41:48 +02:00
if ( dialog . DialogResult ! = DialogResult . OK ) // Cancel or Unknown
2018-06-21 13:28:49 +02:00
{
if ( upgradeHostPlanAction . GetResolvedHost ( ) . IsMaster ( ) )
{
upgradeHostPlanAction . Error = new Exception ( Messages . HOST_REBOOTED_SAME_VERSION ) ;
throw upgradeHostPlanAction . Error ;
}
upgradeHostPlanAction . Error = new CancelledException ( ) ;
break ;
}
2013-06-24 13:41:48 +02:00
else
2018-03-06 16:12:04 +01:00
upgradeHostPlanAction = new UpgradeManualHostPlanAction ( upgradeHostPlanAction . GetResolvedHost ( ) ) ;
2013-06-24 13:41:48 +02:00
}
}
2018-03-06 16:12:04 +01:00
} while ( Helpers . SameServerVersion ( upgradeHostPlanAction . GetResolvedHost ( ) , beforeRebootProductVersion ) ) ;
2013-06-24 13:41:48 +02:00
}
finally
{
2018-03-06 16:12:04 +01:00
upgradeHostPlanAction . Timeout - = upgradeHostPlanAction_Timeout ;
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
return true ; // the action has been handled here
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
protected override bool SkipInitialPlanActions ( Host host )
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
//Skip hosts already upgraded
if ( host . IsMaster ( ) )
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
var pool = Helpers . GetPoolOfOne ( host . Connection ) ;
if ( pool ! = null & & pool . IsMasterUpgraded ( ) )
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
log . Debug ( string . Format ( "Skipping master '{0}' because it is upgraded" , host . Name ( ) ) ) ;
return true ;
2013-06-24 13:41:48 +02:00
}
}
2018-06-21 13:28:49 +02:00
else
2013-06-24 13:41:48 +02:00
{
2018-06-21 13:28:49 +02:00
var master = Helpers . GetMaster ( host . Connection ) ;
if ( master ! = null & & host . LongProductVersion ( ) = = master . LongProductVersion ( ) )
2016-03-17 17:12:43 +01:00
{
2018-06-21 13:28:49 +02:00
log . Debug ( string . Format ( "Skipping host '{0}' because it is upgraded" , host . Name ( ) ) ) ;
return true ;
2016-03-17 17:12:43 +01:00
}
2018-06-21 13:28:49 +02:00
}
return false ;
2013-06-24 13:41:48 +02:00
}
2018-06-22 11:58:08 +02:00
2018-06-22 16:57:31 +02:00
private Dictionary < UpdateProgressBackgroundWorker , List < XenServerPatch > > AllUploadedPatches = new Dictionary < UpdateProgressBackgroundWorker , List < XenServerPatch > > ( ) ;
private Dictionary < UpdateProgressBackgroundWorker , List < XenServerPatch > > MinimalPatches = new Dictionary < UpdateProgressBackgroundWorker , List < XenServerPatch > > ( ) ; // should be calculated only once per pool (to ensure update homogeneity)
2018-06-22 11:58:08 +02:00
protected override void DoAfterInitialPlanActions ( UpdateProgressBackgroundWorker bgw , Host host , List < Host > hosts )
{
2018-06-22 16:57:31 +02:00
var hostPlanActions = bgw . HostActions . FirstOrDefault ( ha = > ha . Host . Equals ( host ) ) ;
if ( hostPlanActions = = null )
2018-06-22 11:58:08 +02:00
return ;
2018-06-22 16:57:31 +02:00
if ( hostPlanActions . UpdatesPlanActions . Count > 0 ) // this is a retry; do not recreate actions
return ;
2018-06-22 11:58:08 +02:00
2018-06-22 16:57:31 +02:00
if ( ! ApplyUpdatesToNewVersion | | host . Connection . Cache . Hosts . Any ( Host . RestrictBatchHotfixApply ) )
return ;
if ( ! MinimalPatches . ContainsKey ( bgw ) )
MinimalPatches . Add ( bgw , Updates . GetMinimalPatches ( host . Connection ) ) ;
2018-06-22 11:58:08 +02:00
2018-06-22 16:57:31 +02:00
var minimalPatches = MinimalPatches [ bgw ] ;
2018-06-22 11:58:08 +02:00
if ( minimalPatches = = null )
return ;
2018-06-22 16:57:31 +02:00
if ( ! AllUploadedPatches . ContainsKey ( bgw ) )
AllUploadedPatches . Add ( bgw , new List < XenServerPatch > ( ) ) ;
var uploadedPatches = AllUploadedPatches [ bgw ] ;
2018-06-22 11:58:08 +02:00
var hostActions = GetUpdatePlanActionsForHost ( host , hosts , minimalPatches , uploadedPatches , new KeyValuePair < XenServerPatch , string > ( ) ) ;
if ( hostActions . UpdatesPlanActions ! = null & & hostActions . UpdatesPlanActions . Count > 0 )
{
2018-06-22 17:29:38 +02:00
hostPlanActions . UpdatesPlanActions = hostActions . UpdatesPlanActions ;
hostPlanActions . DelayedActions . InsertRange ( 0 , hostActions . DelayedActions ) ;
2018-06-22 11:58:08 +02:00
}
}
2018-06-21 13:28:49 +02:00
#endregion
2013-06-24 13:41:48 +02:00
2018-06-21 13:28:49 +02:00
#region Private methods
2018-06-22 11:58:08 +02:00
private HostPlanActions GetSubTasksFor ( Host host )
2013-06-24 13:41:48 +02:00
{
2018-06-22 11:58:08 +02:00
var hostPlanActions = new HostPlanActions ( host ) ;
2018-06-23 00:44:40 +02:00
var runningVMs = host . GetRunningVMs ( ) ;
2018-03-06 16:12:04 +01:00
var upgradeAction = ManualModeSelected
? new UpgradeManualHostPlanAction ( host )
: new UpgradeHostPlanAction ( host , InstallMethodConfig ) ;
2018-06-22 11:58:08 +02:00
hostPlanActions . InitialPlanActions = new List < PlanAction > ( )
2018-03-06 16:12:04 +01:00
{
new EvacuateHostPlanAction ( host ) ,
2018-06-22 11:58:08 +02:00
upgradeAction
} ;
hostPlanActions . DelayedActions = new List < PlanAction > ( )
{
2018-03-06 16:12:04 +01:00
new BringBabiesBackAction ( runningVMs , host , true )
} ;
2018-06-22 11:58:08 +02:00
return hostPlanActions ;
}
2013-06-24 13:41:48 +02:00
2018-06-21 13:28:49 +02:00
private void upgradeHostPlanAction_Timeout ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
2018-06-22 17:29:38 +02:00
var dialog = new NonModalThreeButtonDialog ( SystemIcons . Exclamation , Messages . ROLLING_UPGRADE_TIMEOUT . Replace ( "\\n" , "\n" ) , Messages . KEEP_WAITING_BUTTON_LABEL . Replace ( "\\n" , "\n" ) , Messages . CANCEL ) ;
2018-06-21 13:28:49 +02:00
Program . Invoke ( this , ( ) = > dialog . ShowDialog ( this ) ) ;
if ( dialog . DialogResult ! = DialogResult . OK ) // Cancel or Unknown
{
UpgradeHostPlanAction action = ( UpgradeHostPlanAction ) sender ;
action . Cancel ( ) ;
}
2013-06-24 13:41:48 +02:00
}
2018-06-21 13:28:49 +02:00
#endregion
2013-06-24 13:41:48 +02:00
}
}