2013-06-24 13:41:48 +02:00
/ * 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.Timers ;
using XenAdmin.Actions ;
2013-08-05 18:41:46 +02:00
using XenAdmin.Alerts ;
2013-06-24 13:41:48 +02:00
using XenAdmin.Core ;
using XenAdmin.Network ;
using XenAPI ;
using XenAdmin.Dialogs ;
namespace XenAdmin
{
/// <summary>
/// A custom Timer that checks at regular intervals if any server licenses have expired. Also contains logic
/// for testing license state on connection as to whether we should warn about a soon to expire license.
/// </summary>
class LicenseTimer : System . Timers . Timer
{
private static readonly log4net . ILog log = log4net . LogManager . GetLogger ( System . Reflection . MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
private static readonly TimeSpan EXPIRED_REMINDER_FREQUENCY = new TimeSpan ( 0 , 0 , 30 , 0 ) ; // How frequently to remind user when a license has expired
private static readonly TimeSpan CONNECTION_WARN_THRESHOLD = new TimeSpan ( 29 , 0 , 0 , 0 ) ; // When to start warning on connection
private static readonly TimeSpan RUNNING_WARN_FREQUENCY = new TimeSpan ( 1 , 0 , 0 , 0 ) ; // How frequently to remind when XC is running
private static DateTime lastPeriodicLicenseWarning ;
private readonly LicenseManagerLauncher licenseManagerLauncher ;
public LicenseTimer ( LicenseManagerLauncher licenseManagerLauncher )
{
Elapsed + = new ElapsedEventHandler ( licenseTimerElapsed ) ;
AutoReset = true ;
Interval = EXPIRED_REMINDER_FREQUENCY . TotalMilliseconds ;
lastPeriodicLicenseWarning = DateTime . UtcNow ;
this . licenseManagerLauncher = licenseManagerLauncher ;
Start ( ) ;
}
/// <summary>
/// Call this to check the server licenses when a connection has been made.
/// If a license has expired, the user is warned.
/// </summary>
internal void CheckActiveServerLicense ( IXenConnection connection )
{
DateTime now = DateTime . UtcNow - connection . ServerTimeOffset ;
foreach ( Host host in connection . Cache . Hosts )
{
if ( host . IsXCP )
continue ;
DateTime expiryDate = host . LicenseExpiryUTC ;
TimeSpan timeToExpiry = expiryDate . Subtract ( now ) ;
if ( expiryDate < now )
{
// License has expired already
Program . Invoke ( Program . MainWindow , delegate {
showLicenseSummaryExpired ( host , expiryDate ) ;
} ) ;
return ;
}
else if ( timeToExpiry < CONNECTION_WARN_THRESHOLD )
{
// If the license is sufficiently close to expiry warn now
Program . Invoke ( Program . MainWindow , delegate {
showLicenseSummaryWarning ( Helpers . GetName ( host ) , now , expiryDate ) ;
} ) ;
return ;
}
}
}
/// <summary>
/// Check to see if any licenses have expired as the timer periodically elapses.
/// </summary>
private void licenseTimerElapsed ( object sender , ElapsedEventArgs e )
{
if ( licenseManagerLauncher . LicenceDialogIsShowing )
return ;
foreach ( IXenConnection xc in ConnectionsManager . XenConnectionsCopy )
{
if ( periodicCheck ( xc ) )
return ;
}
}
/// <summary>
/// The logic for the periodic license warning check, only shows the less than 30 day warnings once every day XC is running.
/// Invokes dialog shows as is called from background timer threads.
/// </summary>
/// <param name="xc">The connection to check licenses on</param>
/// <returns></returns>
private bool periodicCheck ( IXenConnection xc )
{
DateTime now = DateTime . UtcNow - xc . ServerTimeOffset ;
foreach ( Host host in xc . Cache . Hosts )
{
if ( host . IsXCP )
continue ;
DateTime expiryDate = host . LicenseExpiryUTC ;
TimeSpan timeToExpiry = expiryDate . Subtract ( now ) ;
if ( expiryDate < now )
{
// License has expired. Pop up the License Manager.
Program . Invoke ( Program . MainWindow , delegate ( ) {
showLicenseSummaryExpired ( host , expiryDate ) ;
} ) ;
return true ;
}
else if ( timeToExpiry < CONNECTION_WARN_THRESHOLD & &
DateTime . UtcNow . Subtract ( lastPeriodicLicenseWarning ) > RUNNING_WARN_FREQUENCY )
{
// Check to see if XC has been open one day. If it has, show < 30 day expiry warnings
lastPeriodicLicenseWarning = DateTime . UtcNow ;
Program . Invoke ( Program . MainWindow , delegate ( ) {
showLicenseSummaryWarning ( Helpers . GetName ( host ) , now , expiryDate ) ;
} ) ;
return true ;
}
}
return false ;
}
/// <summary>
/// Shows the license summary dialog to the user as their license will soon expire.
/// </summary>
private void showLicenseSummaryWarning ( String hostname , DateTime now , DateTime expiryDate )
{
Program . AssertOnEventThread ( ) ;
2013-08-05 18:41:46 +02:00
log . InfoFormat ( "Server {0} is within 30 days of expiry ({1}). Show License Summary if needed" ,
hostname ,
HelpersGUI . DateTimeToString ( expiryDate , Messages . DATEFORMAT_DMY_HMS , true ) ) ;
var alert = new LicenseAlert ( hostname , now , expiryDate ) { LicenseManagerLauncher = licenseManagerLauncher } ;
Alert . AddAlert ( alert ) ;
2013-06-24 13:41:48 +02:00
if ( Program . RunInAutomatedTestMode )
2013-08-05 18:41:46 +02:00
log . DebugFormat ( "In automated test mode: quashing license expiry warning '{0}'" , alert . Description ) ;
2013-06-24 13:41:48 +02:00
else
{
licenseManagerLauncher . Parent = Program . MainWindow ;
licenseManagerLauncher . LaunchIfRequired ( true , ConnectionsManager . XenConnections ) ;
2013-08-05 18:41:46 +02:00
}
2013-06-24 13:41:48 +02:00
}
/// <summary>
/// Shows the license summary dialog to the user as their license has expired.
/// </summary>
/// <param name="host"></param>
/// <param name="expiryDate">Should be expressed in local time.</param>
private void showLicenseSummaryExpired ( Host host , DateTime expiryDate )
{
Program . AssertOnEventThread ( ) ;
log . InfoFormat ( "Server {0} has expired ({1}). Show License Summary if needed" , host . Name , HelpersGUI . DateTimeToString ( expiryDate , Messages . DATEFORMAT_DMY_HMS , true ) ) ;
if ( Program . RunInAutomatedTestMode )
log . DebugFormat ( "In automated test mode: quashing license expiry warning" ) ;
else
licenseManagerLauncher . LaunchIfRequired ( true , ConnectionsManager . XenConnections ) ;
}
}
}