/* 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.Drawing; using System.Linq; using XenAdmin.Actions; using XenAdmin.Actions.HostActions; using XenAdmin.Controls; using XenAdmin.Core; using XenAdmin.Properties; using XenAPI; namespace XenAdmin.Wizards.RollingUpgradeWizard { public partial class RollingUpgradeWizardInstallMethodPage : XenTabPage { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private Bitmap testOK = Resources._000_Tick_h32bit_16; private TestLocationInstallerAction testingAction; public string SelectedSuppPack; public RollingUpgradeWizardInstallMethodPage() { InitializeComponent(); comboBoxUpgradeMethod.SelectedIndex = 0; } #region XenTabPage overrides public override string Text { get { return Messages.READY_UPGRADE; } } public override string PageTitle { get { return Messages.ROLLING_UPGRADE_METHOD_PAGE_TEXT; } } public override bool EnableNext() { if (ApplySuppPackAfterUpgrade && !WizardHelpers.IsValidFile(FilePath, out _)) return false; return pictureBox1.Visible && pictureBox1.Image == testOK; } public override string NextText(bool isLastPage) { return Messages.START_UPGRADE; } public override string HelpID { get { return "upgrademethod"; } } protected override void PageLeaveCore(PageLoadedDirection direction, ref bool cancel) { if (testingAction != null) { StopUrlTesting(); } if (direction == PageLoadedDirection.Forward && ApplySuppPackAfterUpgrade && !string.IsNullOrEmpty(FilePath)) { SelectedSuppPack = WizardHelpers.ParseSuppPackFile(FilePath, this, ref cancel); } } public override void PageCancelled() { if (testingAction != null) { StopUrlTesting(); } } #endregion private void ShowBottomError(string msg) { pictureBox2.Visible = true; labelErrors.Visible = true; labelErrors.Text = msg; } private void ShowSideIcon(Bitmap bitmap) { pictureBox1.Visible = true; pictureBox1.Image = bitmap; } private void HideBottomError() { pictureBox2.Visible = false; labelErrors.Visible = false; } private void HideSideIcon() { pictureBox1.Visible = false; } private void ResetCheckControls() { buttonTest.Enabled = !string.IsNullOrEmpty(watermarkTextBox1.Text); HideSideIcon(); HideBottomError(); OnPageUpdated(); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (InstallMethod == RollingUpgradeInstallMethod.nfs) { labelUser.Visible = labelPassword.Visible = textBoxPassword.Visible = textBoxUser.Visible = false; } //FTP or HTTP else { labelUser.Visible = labelPassword.Visible = textBoxPassword.Visible = textBoxUser.Visible = true; } switch (InstallMethod) { case RollingUpgradeInstallMethod.nfs: CueBannersManager.SetWatermark(watermarkTextBox1, "server:path/"); break; case RollingUpgradeInstallMethod.ftp: CueBannersManager.SetWatermark(watermarkTextBox1, "ftp.example.com/"); break; case RollingUpgradeInstallMethod.http: CueBannersManager.SetWatermark(watermarkTextBox1, "www.example.com/"); break; } ResetCheckControls(); } private RollingUpgradeInstallMethod InstallMethod { get { switch (comboBoxUpgradeMethod.SelectedIndex) { case 0: return RollingUpgradeInstallMethod.http; case 1: return RollingUpgradeInstallMethod.nfs; case 2: return RollingUpgradeInstallMethod.ftp; } throw new ArgumentException(); } } public Dictionary InstallMethodConfig { get { var dict = new Dictionary(); watermarkTextBox1.Text = watermarkTextBox1.Text.Trim().Replace(" ",""); var url = watermarkTextBox1.Text.EndsWith("/") ? watermarkTextBox1.Text : string.Format("{0}/", watermarkTextBox1.Text); url = ExtractBaseUrl(url); watermarkTextBox1.Text = url; if (InstallMethod != RollingUpgradeInstallMethod.nfs && textBoxUser.Text != string.Empty && textBoxPassword.Text != string.Empty) { dict.Add("url", string.Format("{0}://{1}:{2}@{3}", InstallMethod, textBoxUser.Text.UrlEncode(), textBoxPassword.Text.UrlEncode(), url)); } else dict.Add("url", string.Format("{0}://{1}", InstallMethod, url)); return dict; } } /// /// Strip away any prepended URL directives such as http:// etc.. based on the /// entries of the RollingUpgradeInstallMethod enum /// /// Some url with/without prepended directives /// base URL without any prepended directives private string ExtractBaseUrl(string url) { string baseUrl = url; foreach (string method in Enum.GetNames(typeof(RollingUpgradeInstallMethod))) { string prependedText = method.ToLower() + @"://"; baseUrl = baseUrl.ToLower().StartsWith(prependedText) ? baseUrl.Substring(prependedText.Length) : baseUrl; } return baseUrl; } public IEnumerable SelectedMasters { private get; set; } private void buttonTest_Click(object sender, EventArgs e) { if (testingAction == null) { StartUrlTesting(); } else { StopUrlTesting(); } } private void StartUrlTesting() { var host = SelectedMasters.First(); Pool pool = host != null ? Helpers.GetPoolOfOne(host.Connection) : null; host = pool != null ? pool.HostsToUpgrade().First() : null; if (host == null) { ShowBottomError(Messages.UPDATES_WIZARD_CONNECTION_LOST); ShowSideIcon(Resources._000_Abort_h32bit_16); OnPageUpdated(); return; } var action = new TestLocationInstallerAction(host, InstallMethodConfig); action.Completed += action_Completed; ShowSideIcon(Resources.ajax_loader); ChangeInputEnablement(false); buttonTest.Enabled = true; buttonTest.Text = Messages.ROLLING_UPGRADE_BUTTON_LABEL_STOP; testingAction = action; action.RunAsync(); } // The URL-Testing is not be able to cancel, as it is implemented as a plug-in on server side. // What we do is: // 1. Ignore the Completed event of the action, and // 2. Recover the button text and side icon. private void StopUrlTesting() { buttonTest.Text = Messages.ROLLING_UPGRADE_BUTTON_LABEL_TEST; testingAction.Completed -= action_Completed; testingAction = null; ChangeInputEnablement(true); HideSideIcon(); } private void action_Completed(ActionBase sender) { Program.BeginInvoke(this, () => StopUrlTesting()); var action = (AsyncAction)sender; bool result = false; string resultMessage = string.Empty; try { result = action.Result.ToLower() == "true"; } catch (Failure failure) { if (failure.ErrorDescription.Count == 4) { string fromResources = Messages.ResourceManager.GetString(failure.ErrorDescription[3]); resultMessage = string.IsNullOrEmpty(fromResources) ? failure.Message : fromResources; } else resultMessage = failure.Message; log.Error("Error testing upgrade hotfix", failure); } finally { Program.BeginInvoke(this, () => { if (result) { ShowSideIcon(testOK); HideBottomError(); } else { ShowBottomError(string.IsNullOrEmpty(resultMessage) ? Messages.INSTALL_FILES_CANNOT_BE_FOUND : resultMessage); ShowSideIcon(Resources._000_Abort_h32bit_16); } OnPageUpdated(); }); } } private string FilePath { get { return fileNameTextBox.Text; } set { fileNameTextBox.Text = value; } } public bool ApplySuppPackAfterUpgrade { get { return checkBoxInstallSuppPack.Checked; } } private void ChangeInputEnablement(bool value) { textBoxUser.Enabled = textBoxPassword.Enabled = watermarkTextBox1.Enabled = comboBoxUpgradeMethod.Enabled = buttonTest.Enabled = value; } private void watermarkTextBox1_TextChanged(object sender, EventArgs e) { ResetCheckControls(); } private void textBoxUser_TextChanged(object sender, EventArgs e) { ResetCheckControls(); } private void textBoxPassword_TextChanged(object sender, EventArgs e) { ResetCheckControls(); } private void BrowseButton_Click(object sender, EventArgs e) { checkBoxInstallSuppPack.Checked = true; var suppPack = WizardHelpers.GetSuppPackFromDisk(this); if (!string.IsNullOrEmpty(suppPack)) FilePath = suppPack; OnPageUpdated(); } private void fileNameTextBox_TextChanged(object sender, EventArgs e) { checkBoxInstallSuppPack.Checked = true; OnPageUpdated(); } private void fileNameTextBox_Enter(object sender, EventArgs e) { checkBoxInstallSuppPack.Checked = true; OnPageUpdated(); } private void checkBoxInstallSuppPack_CheckedChanged(object sender, EventArgs e) { OnPageUpdated(); } } public enum RollingUpgradeInstallMethod { http, nfs, ftp } }