CP-21184: Add a check for the XenCenter version

- On the Updates tab: for new versions, check that the version of XenCenter is at least the latest. If not, give an additional option to download a newer XenCenter (for both updates and upgrades), and not offer "Download and Install" (for updates).
- In the Patching wizard: if the update is a new version, we force the user to first update their XenCenter to the new version
- In the RPU wizard: if the server version is not the latest and their XenCenter version is not the latest from updates.xml, we assume that they want to upgrade to the latest XenServer version and we force the user to first update their XenCenter to the latest version.

Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
This commit is contained in:
Mihaela Stoica 2017-03-22 10:59:32 +00:00
parent aaa3ff3f03
commit b65084fdc3
13 changed files with 348 additions and 9 deletions

View File

@ -36,6 +36,7 @@ using XenAdmin.Network;
using XenAdmin.Actions;
using XenAdmin.Core;
using XenAPI;
using System.Text;
namespace XenAdmin.Alerts
@ -44,7 +45,7 @@ namespace XenAdmin.Alerts
{
public XenServerPatch Patch;
public XenServerVersion NewServerVersion;
/// <summary>
/// Can we apply this alert. Calling this sets the CannotApplyReason where applicable
/// </summary>
@ -93,6 +94,8 @@ namespace XenAdmin.Alerts
{
Patch = patch;
NewServerVersion = newServerVersion;
if (NewServerVersion != null)
RequiredXenCenterVersion = Updates.GetRequiredXenCenterVersion(NewServerVersion);
_priority = patch.Priority;
_timestamp = Patch.TimeStamp;
}
@ -121,12 +124,21 @@ namespace XenAdmin.Alerts
{
get
{
var patchDescription = NewServerVersion != null
StringBuilder sb = new StringBuilder();
sb.Append(NewServerVersion != null
? string.Format(Messages.DOWLOAD_LATEST_XS_TITLE, NewServerVersion.Name)
: Patch.Description;
: Patch.Description);
if (Patch.InstallationSize != 0)
return string.Format(Messages.PATCH_DESCRIPTION_AND_INSTALLATION_SIZE, patchDescription, Util.DiskSizeString(Patch.InstallationSize));
return patchDescription;
{
sb.AppendLine();
sb.AppendFormat(Messages.PATCH_INSTALLATION_SIZE, Util.DiskSizeString(Patch.InstallationSize));
}
if (RequiredXenCenterVersion != null)
{
sb.AppendLine();
sb.AppendFormat(Messages.PATCH_NEEDS_NEW_XENCENTER, RequiredXenCenterVersion.Version);
}
return sb.ToString();
}
}

View File

@ -45,6 +45,8 @@ namespace XenAdmin.Alerts
protected readonly List<IXenConnection> connections = new List<IXenConnection>();
private readonly List<Host> hosts = new List<Host>();
public XenCenterVersion RequiredXenCenterVersion;
public bool CanIgnore
{
get { return (connections.Count == 0 && hosts.Count == 0) || IsDismissed(); }

View File

@ -47,6 +47,7 @@ namespace XenAdmin.Alerts
public XenServerVersionAlert(XenServerVersion version)
{
Version = version;
RequiredXenCenterVersion = Updates.GetRequiredXenCenterVersion(Version);
_timestamp = version.TimeStamp;
}

View File

@ -462,6 +462,36 @@ namespace XenAdmin.Core
return true;
}
/// <summary>
/// Returns the latest XenCenter version or null, if the current version is the latest.
/// If a server version is provided, it returns the XenCenter version that is required to work with that server.
/// If no server version is provided it will return the latestCr XenCenter.
/// </summary>
/// <param name="serverVersion"></param>
/// <returns></returns>
public static XenCenterVersion GetRequiredXenCenterVersion(XenServerVersion serverVersion)
{
if (XenCenterVersions.Count == 0)
return null;
var currentProgramVersion = Program.Version;
if (currentProgramVersion == new Version(0, 0, 0, 0))
return null;
var latestVersions = from v in XenCenterVersions where v.Latest select v;
var latest = latestVersions.FirstOrDefault(xcv => xcv.Lang == Program.CurrentLanguage) ??
latestVersions.FirstOrDefault(xcv => string.IsNullOrEmpty(xcv.Lang));
var latestCrVersions = from v in XenCenterVersions where v.LatestCr select v;
var latestCr = latestCrVersions.FirstOrDefault(xcv => xcv.Lang == Program.CurrentLanguage) ??
latestCrVersions.FirstOrDefault(xcv => string.IsNullOrEmpty(xcv.Lang));
if (serverVersion != null && serverVersion.Latest && latest != null)
return latest.Version > currentProgramVersion ? latest : null;
return latestCr != null && latestCr.Version > currentProgramVersion ? latestCr : null;
}
/// <summary>
/// This method returns the minimal set of patches for a host if this class already has information about them. Otherwise it returns empty list.

View File

@ -0,0 +1,64 @@
/* 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 XenAPI;
using XenAdmin.Diagnostics.Problems;
using XenAdmin.Core;
using XenAdmin.Diagnostics.Problems.PoolProblem;
using XenAdmin.Alerts;
namespace XenAdmin.Diagnostics.Checks
{
public class XenCenterVersionCheck : Check
{
private XenServerVersion _newServerVersion;
public XenCenterVersionCheck(XenServerVersion newServerVersion)
: base(null)
{
_newServerVersion = newServerVersion;
}
protected override Problem RunCheck()
{
var requiredXenCenterVersion = Updates.GetRequiredXenCenterVersion(_newServerVersion);
if (requiredXenCenterVersion != null)
return new XenCenterVersionProblem(this, requiredXenCenterVersion);
return null;
}
public override string Description
{
get { return Messages.XENCENTER_VERSION_CHECK_DESCRIPTION; }
}
}
}

View File

@ -0,0 +1,65 @@
/* 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 XenAdmin.Core;
using XenAdmin.Diagnostics.Checks;
namespace XenAdmin.Diagnostics.Problems
{
public class XenCenterVersionProblem : Problem
{
private XenCenterVersion _requiredXenCenterVersion;
public XenCenterVersionProblem(Check check, XenCenterVersion requiredXenCenterVersion)
: base(check)
{
_requiredXenCenterVersion = requiredXenCenterVersion;
}
public override string Title
{
get { return Messages.PROBLEM_XENCENTER_VERSION_TITLE; }
}
public override string Description
{
get { return string.Format(Messages.UPDATES_WIZARD_NEWER_XENCENTER_REQUIRED, _requiredXenCenterVersion.Version); }
}
public override string HelpMessage
{
get
{
return "";
}
}
}
}

View File

@ -443,13 +443,22 @@ namespace XenAdmin.TabPages
items.Add(dismiss);
}
if (patchAlert != null && patchAlert.CanApply && !string.IsNullOrEmpty(patchAlert.Patch.PatchUrl))
if (patchAlert != null && patchAlert.CanApply && !string.IsNullOrEmpty(patchAlert.Patch.PatchUrl) && patchAlert.RequiredXenCenterVersion == null)
{
var download = new ToolStripMenuItem(Messages.UPDATES_DOWNLOAD_AND_INSTALL);
download.Click += ToolStripMenuItemDownload_Click;
items.Add(download);
}
var updateAlert = alert as XenServerUpdateAlert;
if (updateAlert != null && updateAlert.RequiredXenCenterVersion != null)
{
var downloadNewXenCenter = new ToolStripMenuItem(Messages.UPDATES_DOWNLOAD_REQUIRED_XENCENTER);
downloadNewXenCenter.Click += ToolStripMenuItemDownloadNewXenCenter_Click;
items.Add(downloadNewXenCenter);
}
if (!string.IsNullOrEmpty(alert.WebPageLabel))
{
var fix = new ToolStripMenuItem(alert.FixLinkText);
@ -708,6 +717,24 @@ namespace XenAdmin.TabPages
});
}
private void ToolStripMenuItemDownloadNewXenCenter_Click(object sender, EventArgs e)
{
DataGridViewRow clickedRow = FindAlertRow(sender as ToolStripMenuItem);
if (clickedRow == null)
return;
XenServerUpdateAlert updateAlert = (XenServerUpdateAlert)clickedRow.Tag;
if (updateAlert == null || updateAlert.RequiredXenCenterVersion == null)
return;
string xenCenterUrl = updateAlert.RequiredXenCenterVersion.Url;
if (string.IsNullOrEmpty(xenCenterUrl))
return;
Program.Invoke(Program.MainWindow, () => Program.OpenURL(xenCenterUrl));
}
private void ToolStripMenuItemCopy_Click(object sender, EventArgs e)
{
DataGridViewRow clickedRow = FindAlertRow(sender as ToolStripMenuItem);

View File

@ -85,6 +85,7 @@ namespace XenAdmin.Wizards.PatchingWizard
PatchingWizard_SelectPatchPage.SelectDownloadAlert(alert);
PatchingWizard_SelectPatchPage.SelectedUpdateAlert = alert;
PatchingWizard_SelectServers.SelectedUpdateAlert = alert;
PatchingWizard_PrecheckPage.UpdateAlert = alert;
PatchingWizard_UploadPage.SelectedUpdateAlert = alert;
}
@ -117,6 +118,7 @@ namespace XenAdmin.Wizards.PatchingWizard
PatchingWizard_SelectServers.SelectedUpdateType = updateType;
PatchingWizard_SelectServers.Patch = existPatch;
PatchingWizard_SelectServers.SelectedUpdateAlert = alertPatch;
PatchingWizard_PrecheckPage.UpdateAlert = alertPatch ?? fileFromDiskAlertPatch;
PatchingWizard_SelectServers.FileFromDiskAlert = fileFromDiskAlertPatch;
RemovePage(PatchingWizard_UploadPage);

View File

@ -37,6 +37,7 @@ using System.Linq;
using System.Threading;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Alerts;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAdmin.Diagnostics.Checks;
@ -66,6 +67,8 @@ namespace XenAdmin.Wizards.PatchingWizard
}
}
public XenServerPatchAlert UpdateAlert { private get; set; }
public PatchingWizard_PrecheckPage()
{
InitializeComponent();
@ -346,10 +349,19 @@ namespace XenAdmin.Wizards.PatchingWizard
protected virtual List<KeyValuePair<string, List<Check>>> GenerateCommonChecks()
{
List<KeyValuePair<string, List<Check>>> checks = new List<KeyValuePair<string, List<Check>>>();
List<Check> checkGroup;
//XenCenter version check
if (UpdateAlert != null && UpdateAlert.NewServerVersion != null)
{
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_XENCENTER_VERSION, new List<Check>()));
checkGroup = checks[checks.Count - 1].Value;
checkGroup.Add(new XenCenterVersionCheck(UpdateAlert.NewServerVersion));
}
//HostLivenessCheck checks
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_HOST_LIVENESS_STATUS, new List<Check>()));
List<Check> checkGroup = checks[checks.Count - 1].Value;
checkGroup = checks[checks.Count - 1].Value;
foreach (Host host in SelectedServers)
{
checkGroup.Add(new HostLivenessCheck(host));
@ -646,7 +658,10 @@ namespace XenAdmin.Wizards.PatchingWizard
{
description = _check.SuccessfulCheckDescription;
if (string.IsNullOrEmpty(description))
description = String.Format(Messages.PATCHING_WIZARD_HOST_CHECK_OK, _check.Host.Name, _check.Description);
description = _check.Host != null
? String.Format(Messages.PATCHING_WIZARD_HOST_CHECK_OK, _check.Host.Name, _check.Description)
: String.Format(Messages.PATCHING_WIZARD_CHECK_OK, _check.Description);
}
if (description != string.Empty)

View File

@ -147,10 +147,21 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
protected override List<KeyValuePair<string, List<Check>>> GenerateChecks(Pool_patch patch)
{
List<KeyValuePair<string, List<Check>>> checks = new List<KeyValuePair<string, List<Check>>>();
List<Check> checkGroup;
//XenCenter version check (if any of the selected server version is not the latest)
var latestCrVersion = Updates.XenServerVersions.FindAll(item => item.LatestCr).OrderByDescending(v => v.Version).FirstOrDefault();
if (latestCrVersion != null &&
SelectedServers.Any(host => new Version(Helpers.HostProductVersion(host)) < latestCrVersion.Version))
{
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_XENCENTER_VERSION, new List<Check>()));
checkGroup = checks[checks.Count - 1].Value;
checkGroup.Add(new XenCenterVersionCheck(null));
}
//HostMaintenanceModeCheck checks
checks.Add(new KeyValuePair<string, List<Check>>(Messages.CHECKING_HOST_LIVENESS_STATUS, new List<Check>()));
List<Check> checkGroup = checks[checks.Count - 1].Value;
checkGroup = checks[checks.Count - 1].Value;
foreach (Host host in SelectedServers)
{
checkGroup.Add(new HostMaintenanceModeCheck(host));

View File

@ -225,6 +225,7 @@
<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\HostProblem\PrerequisiteUpdateMissing.cs" />
<Compile Include="Diagnostics\Problems\HostProblem\HostNeedsReboot.cs" />
<Compile Include="Diagnostics\Problems\HostProblem\HostNotSafeToUpgradeWarning.cs" />
@ -235,6 +236,7 @@
<Compile Include="Diagnostics\Problems\ProblemWithInformationUrl.cs" />
<Compile Include="Diagnostics\Problems\SRProblem\UnsupportedStorageLinkSrIsPresentProblem.cs" />
<Compile Include="Diagnostics\Problems\VMProblem\InvalidVCPUConfiguration.cs" />
<Compile Include="Diagnostics\Problems\XenCenterVersionProblem.cs" />
<Compile Include="Dialogs\EnablePvsReadCachingDialog.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -7052,6 +7052,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Checking [XenCenter] version.
/// </summary>
public static string CHECKING_XENCENTER_VERSION {
get {
return ResourceManager.GetString("CHECKING_XENCENTER_VERSION", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cross-server private network.
/// </summary>
@ -23624,6 +23633,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to New [XenCenter] version required.
/// </summary>
public static string NEW_XENCENTER_REQUIRED_INFO {
get {
return ResourceManager.GetString("NEW_XENCENTER_REQUIRED_INFO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You need to shutdown and then restart the VM before it can access the new disk..
/// </summary>
@ -26476,6 +26494,24 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Installation size: {0}.
/// </summary>
public static string PATCH_INSTALLATION_SIZE {
get {
return ResourceManager.GetString("PATCH_INSTALLATION_SIZE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This version requires [XenCenter] {0} or newer.
/// </summary>
public static string PATCH_NEEDS_NEW_XENCENTER {
get {
return ResourceManager.GetString("PATCH_NEEDS_NEW_XENCENTER", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not found.
/// </summary>
@ -26522,6 +26558,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to {0} ok..
/// </summary>
public static string PATCHING_WIZARD_CHECK_OK {
get {
return ResourceManager.GetString("PATCHING_WIZARD_CHECK_OK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The patch {0} is going to be deleted. Do you want to continue?.
/// </summary>
@ -28252,6 +28297,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to [XenCenter] version.
/// </summary>
public static string PROBLEM_XENCENTER_VERSION_TITLE {
get {
return ResourceManager.GetString("PROBLEM_XENCENTER_VERSION_TITLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &amp;Proceed.
/// </summary>
@ -33705,6 +33759,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Download [XenCenter].
/// </summary>
public static string UPDATES_DOWNLOAD_REQUIRED_XENCENTER {
get {
return ResourceManager.GetString("UPDATES_DOWNLOAD_REQUIRED_XENCENTER", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Install Update.
/// </summary>
@ -34051,6 +34114,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to [XenCenter] version {0} or newer is required..
/// </summary>
public static string UPDATES_WIZARD_NEWER_XENCENTER_REQUIRED {
get {
return ResourceManager.GetString("UPDATES_WIZARD_NEWER_XENCENTER_REQUIRED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No further action is required for this update..
/// </summary>
@ -39317,6 +39389,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to [XenCenter] version check.
/// </summary>
public static string XENCENTER_VERSION_CHECK_DESCRIPTION {
get {
return ResourceManager.GetString("XENCENTER_VERSION_CHECK_DESCRIPTION", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Saved Searches (*.{0})|*.{0}.
/// </summary>

View File

@ -2558,6 +2558,9 @@ Do you want to assign it to the schedule '{2}' instead?</value>
<data name="CHECKING_WSS_STATUS" xml:space="preserve">
<value>Checking the possible presence of WSS appliances</value>
</data>
<data name="CHECKING_XENCENTER_VERSION" xml:space="preserve">
<value>Checking [XenCenter] version</value>
</data>
<data name="CHECK_WLB_ENABLED" xml:space="preserve">
<value>Pool '{0}' cannot have WLB enabled</value>
</data>
@ -8853,6 +8856,9 @@ It is strongly recommended that you Cancel and apply the latest version of the p
<data name="NEW_VM_WIZARD_TEMPLATEPAGE_UBUNTU" xml:space="preserve">
<value>Ubuntu</value>
</data>
<data name="NEW_XENCENTER_REQUIRED_INFO" xml:space="preserve">
<value>New [XenCenter] version required</value>
</data>
<data name="NFS_ISO_ALREADY_ATTACHED" xml:space="preserve">
<value>This NFS ISO storage is already attached to '{0}'</value>
</data>
@ -9424,6 +9430,9 @@ Please wait for this operation to complete, then click Next to continue with the
<data name="PATCHING_WARNING_HA" xml:space="preserve">
<value>Disable HA until after all the hosts have been rebooted</value>
</data>
<data name="PATCHING_WIZARD_CHECK_OK" xml:space="preserve">
<value>{0} ok.</value>
</data>
<data name="PATCHING_WIZARD_CONFIRMATION_DELETE" xml:space="preserve">
<value>The patch {0} is going to be deleted. Do you want to continue?</value>
</data>
@ -9485,6 +9494,12 @@ Size: {3}</value>
<data name="PATCH_FOR_XENSERVER_VERSION" xml:space="preserve">
<value>{0}: This patch is for servers with version matching the regular expression '{1}'.</value>
</data>
<data name="PATCH_INSTALLATION_SIZE" xml:space="preserve">
<value>Installation size: {0}</value>
</data>
<data name="PATCH_NEEDS_NEW_XENCENTER" xml:space="preserve">
<value>This version requires [XenCenter] {0} or newer</value>
</data>
<data name="PATCH_NOT_FOUND" xml:space="preserve">
<value>Not found</value>
</data>
@ -9826,6 +9841,9 @@ The VM protection policy for this VM does not have automatic archiving configure
<data name="PROBLEM_VMPROBLEM_TITLE" xml:space="preserve">
<value>VM '{0}'</value>
</data>
<data name="PROBLEM_XENCENTER_VERSION_TITLE" xml:space="preserve">
<value>[XenCenter] version</value>
</data>
<data name="PROCEED" xml:space="preserve">
<value>&amp;Proceed</value>
</data>
@ -11637,6 +11655,9 @@ Verify that the file is a valid {1} export.</value>
<data name="UPDATES_DOWNLOAD_AND_INSTALL" xml:space="preserve">
<value>Download and Install</value>
</data>
<data name="UPDATES_DOWNLOAD_REQUIRED_XENCENTER" xml:space="preserve">
<value>Download [XenCenter]</value>
</data>
<data name="UPDATES_WIZARD" xml:space="preserve">
<value>Install Update</value>
</data>
@ -11755,6 +11776,9 @@ Check your settings and try again.</value>
<data name="UPDATES_WIZARD_LOCAL_STORAGE" xml:space="preserve">
<value>{0}: The VM '{1}' uses local storage and cannot be migrated.</value>
</data>
<data name="UPDATES_WIZARD_NEWER_XENCENTER_REQUIRED" xml:space="preserve">
<value>[XenCenter] version {0} or newer is required.</value>
</data>
<data name="UPDATES_WIZARD_NOTVALID_EXTENSION" xml:space="preserve">
<value>The selected file does not have a valid extension. Valid extensions are: *.{0} and *.iso</value>
</data>
@ -13574,6 +13598,9 @@ Are you sure you want to enable automated power management for this Host?</value
<data name="XENCENTER_NEWER_AVAILABLE" xml:space="preserve">
<value>Newer [XenCenter] Available</value>
</data>
<data name="XENCENTER_VERSION_CHECK_DESCRIPTION" xml:space="preserve">
<value>[XenCenter] version check</value>
</data>
<data name="XENSEARCH_SAVED_SEARCH" xml:space="preserve">
<value>Saved Searches (*.{0})|*.{0}</value>
</data>