From 466f01b92622d25256f3a5474264eebb2e2fddab Mon Sep 17 00:00:00 2001 From: Gabor Apati-Nagy Date: Thu, 31 Mar 2016 15:40:23 +0100 Subject: [PATCH] CP-15717: UI: Implement basic upload/precheck/patch/cleanup logic Signed-off-by: Gabor Apati-Nagy --- XenAdmin/AppIcon.ico | 0 XenAdmin/Core/Updates.cs | 20 +- .../Wizards/PatchingWizard/PatchingWizard.cs | 1 + .../PatchingWizard_AutoUpdatingPage.cs | 599 ++---------------- .../PatchingWizard_SelectServers.cs | 2 +- .../PlanActions/DownloadAndUploadPatch.cs | 5 +- .../RemoveUpdateFilesFromMaster.cs | 63 ++ XenAdmin/XenAdmin.csproj | 1 + .../Updates/DownloadUpdatesXmlAction.cs | 5 +- XenModel/Actions/Updates/XenServerPatch.cs | 11 +- XenModel/Messages.Designer.cs | 18 + XenModel/Messages.resx | 6 + 12 files changed, 171 insertions(+), 560 deletions(-) create mode 100644 XenAdmin/AppIcon.ico create mode 100644 XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs diff --git a/XenAdmin/AppIcon.ico b/XenAdmin/AppIcon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/XenAdmin/Core/Updates.cs b/XenAdmin/Core/Updates.cs index 2b5bf92dd..97f3dbf8e 100644 --- a/XenAdmin/Core/Updates.cs +++ b/XenAdmin/Core/Updates.cs @@ -425,6 +425,18 @@ namespace XenAdmin.Core && Helpers.HostProductVersion(master) == version.Version.ToString()); }); +/* + * + * + * REMOVE - TEMP CODE FOR EASIER DEBUGGING + * + * + */ +if (serverVersions.Count == 0) +{ + serverVersions.Add(XenServerVersions.Last()); +} + List allPatches = new List(); if (serverVersions.Count > 0) @@ -456,8 +468,10 @@ namespace XenAdmin.Core var p = neededPatches[ii]; //checking requirements - if (// no requirements - p.RequiredPatches == null + if (//not applied yet + !appliedPatches.Any(ap => string.Equals(ap.uuid, p.Uuid, StringComparison.OrdinalIgnoreCase)) + // and either no requirements or they are meet + && (p.RequiredPatches == null || p.RequiredPatches.Count == 0 // all requirements met? || p.RequiredPatches.All( @@ -468,7 +482,7 @@ namespace XenAdmin.Core //the required-patch has already been applied || (appliedPatches.Count != 0 && appliedPatches.Any(ap => string.Equals(ap.uuid, rp, StringComparison.OrdinalIgnoreCase))) ) - ) + )) { // this patch can be added to the upgrade sequence now sequence.Add(p); diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs index c64842c83..28d5fb95d 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs @@ -195,6 +195,7 @@ namespace XenAdmin.Wizards.PatchingWizard else if (prevPageType == typeof(PatchingWizard_PrecheckPage)) { PatchingWizard_PatchingPage.ProblemsResolvedPreCheck = PatchingWizard_PrecheckPage.ProblemsResolvedPreCheck; + PatchingWizard_AutoUpdatingPage.ProblemsResolvedPreCheck = PatchingWizard_PrecheckPage.ProblemsResolvedPreCheck; } } diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs index fc014bf38..36d9f5e21 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs @@ -55,9 +55,11 @@ namespace XenAdmin.Wizards.PatchingWizard public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; } private BackgroundWorker actionsWorker = null; + private bool _thisPageHasBeenCompleted = false; + + public List ProblemsResolvedPreCheck { private get; set; } public List SelectedMasters { private get; set; } - //public List SelectedServers { private get; set; } private List patchMappings = new List(); private Dictionary AllDownloadedPatches = new Dictionary(); @@ -109,21 +111,24 @@ namespace XenAdmin.Wizards.PatchingWizard { base.PageLoaded(direction); - //if (_thisPageHasBeenCompleted) - //{ - // actionsWorker = null; - // return; - //} + if (_thisPageHasBeenCompleted) + { + actionsWorker = null; + return; + } Dictionary> planActionsPerPool = new Dictionary>(); foreach (var master in SelectedMasters) { - List planActionsForAPool = new List(); + Dictionary> planActionsForAPool = new Dictionary>(); Dictionary> delayedActionsForAPool = new Dictionary>(); foreach (var host in master.Connection.Cache.Hosts) + { + planActionsForAPool.Add(host, new List()); delayedActionsForAPool.Add(host, new List()); + } //var master = Helpers.GetMaster(pool.Connection); var hosts = master.Connection.Cache.Hosts; @@ -134,11 +139,11 @@ namespace XenAdmin.Wizards.PatchingWizard { if (master != null && us.ContainsKey(master) && us[master].Any(p => string.Equals(p.Uuid, patch.Uuid, StringComparison.InvariantCultureIgnoreCase))) { - planActionsForAPool.AddRange(CompileActionList(master, patch)); + planActionsForAPool[master].AddRange(CompileActionList(master, patch)); if (patch.GuidanceMandatory) { var mandatoryGuidance = CompileAfterPatchGuidanceActionList(master, patch); - planActionsForAPool.AddRange(mandatoryGuidance); + planActionsForAPool[master].AddRange(mandatoryGuidance); //remove delayed action of the same kind for this host foreach (var mg in mandatoryGuidance) @@ -158,13 +163,13 @@ namespace XenAdmin.Wizards.PatchingWizard { if (!host.IsMaster() && us.ContainsKey(host) && us[host].Any(p => string.Equals(p.Uuid, patch.Uuid, StringComparison.InvariantCultureIgnoreCase))) { - planActionsForAPool.AddRange(CompileActionList(host, patch)); + planActionsForAPool[host].AddRange(CompileActionList(host, patch)); if (patch.GuidanceMandatory) { var mandatoryGuidance = CompileAfterPatchGuidanceActionList(host, patch); - planActionsForAPool.AddRange(mandatoryGuidance); + planActionsForAPool[host].AddRange(mandatoryGuidance); //remove delayed action of the same kind for this host foreach (var mg in mandatoryGuidance) @@ -183,50 +188,45 @@ namespace XenAdmin.Wizards.PatchingWizard }//patch - //add all delayed actions to the end of the actions - foreach (var delayedActionsPerHost in delayedActionsForAPool.Values) - planActionsForAPool.AddRange(delayedActionsPerHost); - - //todo cleanup - - //if (RemoveUpdateFile) - //{ - // planActionsForAPool.Add(new RemoveUpdateFile(pool, poolPatch)); - //} + //add all delayed actions to the end of the actions, per host + foreach (var kvp in delayedActionsForAPool) + { + planActionsForAPool[kvp.Key].AddRange(kvp.Value); + } //add all actions for the pool to the main actions list - planActionsPerPool[master] = planActionsForAPool; + //master first + foreach (var kvp in planActionsForAPool) + { + if (!planActionsPerPool.ContainsKey(master)) + planActionsPerPool.Add(master, new List()); + + planActionsPerPool[master].AddRange(kvp.Value); + } + + planActionsPerPool[master].Add(new RemoveUpdateFilesFromMaster(master, patchMappings)); + + } //foreach in SelectedMasters + + var planActions = new List(); + + //actions list for serial execution + foreach (var actionListPerPool in planActionsPerPool) + { + planActions.AddRange(actionListPerPool.Value); } + planActions.Add(new UnwindProblemsAction(ProblemsResolvedPreCheck)); - //todo run the planactions - - //planActions.Add(new UnwindProblemsAction(ProblemsResolvedPreCheck)); - - //actionsWorker = new BackgroundWorker(); - //actionsWorker.DoWork += new DoWorkEventHandler(PatchingWizardAutomaticPatchWork); - //actionsWorker.WorkerReportsProgress = true; - //actionsWorker.ProgressChanged += new ProgressChangedEventHandler(actionsWorker_ProgressChanged); - //actionsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(actionsWorker_RunWorkerCompleted); - //actionsWorker.WorkerSupportsCancellation = true; - //actionsWorker.RunWorkerAsync(planActions); + actionsWorker = new BackgroundWorker(); + actionsWorker.DoWork += new DoWorkEventHandler(PatchingWizardAutomaticPatchWork); + actionsWorker.WorkerReportsProgress = true; + actionsWorker.ProgressChanged += new ProgressChangedEventHandler(actionsWorker_ProgressChanged); + actionsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(actionsWorker_RunWorkerCompleted); + actionsWorker.WorkerSupportsCancellation = true; + actionsWorker.RunWorkerAsync(planActions); } - - - - - - - - - - - - - - - #region automatic_mode private void actionsWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) @@ -294,9 +294,8 @@ namespace XenAdmin.Wizards.PatchingWizard _nextEnabled = true; } OnPageUpdated(); - //todo below - //_thisPageHasBeenCompleted = true; + _thisPageHasBeenCompleted = true; } private List CompileActionList(Host host, XenServerPatch patch) @@ -428,506 +427,10 @@ namespace XenAdmin.Wizards.PatchingWizard private void FinishedSuccessfully() { - //labelTitle.Text = string.Format(Messages.UPDATE_WAS_SUCCESSFULLY_INSTALLED, GetUpdateName()); + labelTitle.Text = Messages.PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE; pictureBox1.Image = null; labelError.Text = Messages.CLOSE_WIZARD_CLICK_FINISH; } - - /* - private List GetPatchesForHost(Host h) - { - if (h == null) - return null; - - return UpgradeSequences[h]; - } - - private List DelayedGuidancesForHost(Host h) - { - if (h == null) - return null; - - return null; - //return UpgradeSequences[h].Where(p => !string.IsNullOrEmpty(p.Guidance)).Select(p => ); //todo change from string - } - - - private List GetAllActionsForPool(IXenConnection conn) - { - var master = Helpers.GetMaster(conn); - var hosts = Connection.Cache.Hosts; - - var us = Updates.GetUpgradeSequence(conn); - - var actions = new List(); - - foreach (var patch in us.UniquePatches) - { - //master first - - actions.Add(GetDownloadFileAction(patch)); - actions.Add(PrepareUploadToHostActions(master, patch)); - - - - //////RUN actions - //now we should have pool_patch on master - - var poolPatches = new List(master.Connection.Cache.Pool_patches); - var poolPatch = poolPatches.Find(pp => string.Equals(pp.uuid, patch.Uuid)); - - var precheck = new XenAdmin.Diagnostics.Checks.PatchPrecheckCheck(master, poolPatch); - var problem = precheck.RunCheck(); - if (problem != null) - //there is a problem - throw Exception(); //todo stop - - //precheck - actions.Add(new ApplyPatchAction(patch, new List() { master })); - - if (patch.GuidanceMandatory) - { - var afterGuidancePlanActions = CompileAfterApplyGuidanceActionListForPatch(master, patch); - - actionsWorker = new BackgroundWorker(); - actionsWorker.DoWork += new DoWorkEventHandler(PatchingWizardAutomaticPatchWork); - actionsWorker.WorkerReportsProgress = true; - actionsWorker.ProgressChanged += new ProgressChangedEventHandler(actionsWorker_ProgressChanged); - actionsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(actionsWorker_RunWorkerCompleted); - actionsWorker.WorkerSupportsCancellation = true; - actionsWorker.RunWorkerAsync(afterGuidancePlanActions); - - } - - //guidances master - - //hosts after - //apply - //precheck - //after patch guidances - //celanup host - - //cleanup master - } - - * - * Patch - * Master - * Download - * Upload to master - * Precheck - * ApplyPatchAction - * Remove - * Restart, Other Actions - * Host1 - * ... - * Host2 - * ... - * - - - - var patches = GetPatchesForHost(host); - foreach (var patch in patches) - { - - - //List poolPatches = new List(host.Connection.Cache.Pool_patches); - //Pool_patch poolPatch = poolPatches.Find(pp => string.Equals(pp.uuid, patch.Uuid)); - - - //ClearUpHostAfterPatch(patch, host); PoolPatchCleanAction - - - ApplyAfterPatchGuidancesIfMandatoryNow(patch, host); - } - - actions.AddRange(ApplyAfterPatchGuidancesIfDelayedNeeded(host)); - - - - using (var multipleAction = new MultipleAction(Connection, "", "", "", actions, true, true, true)) - { - multipleAction.Changed += action_Changed; - multipleAction.Completed += action_Completed; - multipleAction.RunAsync(); - } - - - } - - - - private void PatchingWizardAutomaticPatchWork(object obj, DoWorkEventArgs doWorkEventArgs) - { - List actionList = (List)doWorkEventArgs.Argument; - foreach (PlanAction action in actionList) - { - try - { - if (actionsWorker.CancellationPending) - { - doWorkEventArgs.Cancel = true; - return; - } - this.actionsWorker.ReportProgress(0, action); - action.Run(); - Thread.Sleep(1000); - - this.actionsWorker.ReportProgress((int)((1.0 / (double)actionList.Count) * 100), action); - - } - catch (Exception e) - { - - log.Error("Failed to carry out plan.", e); - log.Debug(actionList); - doWorkEventArgs.Result = new Exception(action.Title, e); - break; - } - } - } - - private void actionsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - if (!e.Cancelled) - { - Exception exception = e.Result as Exception; - if (exception != null) - { - FinishedWithErrors(exception); - - } - else - { - FinishedSuccessfully(); - } - - progressBar.Value = 100; - _cancelEnabled = false; - _nextEnabled = true; - } - OnPageUpdated(); - _thisPageHasBeenCompleted = true; - - } - - - - private void FinishedWithErrors(Exception exception) - { - //labelTitle.Text = string.Format(Messages.UPDATE_WAS_NOT_COMPLETED, GetUpdateName()); - - //string errorMessage = null; - - //if (exception != null && exception.InnerException != null && exception.InnerException is Failure) - //{ - // var innerEx = exception.InnerException as Failure; - // errorMessage = innerEx.Message; - - // if (innerEx.ErrorDescription != null && innerEx.ErrorDescription.Count > 0) - // log.Error(string.Concat(innerEx.ErrorDescription.ToArray())); - //} - - //labelError.Text = errorMessage ?? string.Format(Messages.PATCHING_WIZARD_ERROR, exception.Message); - - //log.ErrorFormat("Error message displayed: {0}", labelError.Text); - - //pictureBox1.Image = SystemIcons.Error.ToBitmap(); - //if (exception.InnerException is SupplementalPackInstallFailedException) - //{ - // errorLinkLabel.Visible = true; - // errorLinkLabel.Tag = exception.InnerException; - //} - //panel1.Visible = true; - } - - - private void FinishedSuccessfully() - { - //labelTitle.Text = string.Format(Messages.UPDATE_WAS_SUCCESSFULLY_INSTALLED, GetUpdateName()); - //pictureBox1.Image = null; - //labelError.Text = Messages.CLOSE_WIZARD_CLICK_FINISH; - } - - - - - - - - - - - - - - - - - - - - - - - - - private void action_Changed(ActionBase sender) - { - //AsyncAction action = (AsyncAction)sender; - //Program.Invoke(Program.MainWindow, delegate { progressBar.Value = action.PercentComplete; }); - } - - private void action_Completed(ActionBase sender) - { - //_nextEnabled = true; - //_cancelEnabled = false; - - //try - //{ - // if (sender.Exception != null) - // { - // Program.Invoke(Program.MainWindow, () => FinishedWithErrors(new Exception(sender.Title, sender.Exception))); - // } - // else - // Program.Invoke(Program.MainWindow, FinishedSuccessfully); - //} - //catch (Exception except) - //{ - // Program.Invoke(Program.MainWindow, () => FinishedWithErrors(except)); - //} - //Program.Invoke(Program.MainWindow, OnPageUpdated); - //_thisPageHasBeenCompleted = true; - } - - - - private List ApplyPatchAction(Host host, Pool_patch patch) - { - - - - - - } - - private List CompileAfterApplyGuidanceActionListForPatch(Host host, XenServerPatch patch) - { - List actions = new List(); - - if (patch == null) - return actions; - - List> runningVMs = RunningVMs(host); - - //actions.Add(new ApplyPatchPlanAction(host, patch)); - - if (patch.after_apply_guidance == after_apply_guidance.restartHost) - { - actions.Add(new EvacuateHostPlanAction(host)); - actions.Add(new RebootHostPlanAction(host)); - actions.Add(new BringBabiesBackAction(runningVMs, host, false)); - } - - if (patch.after_apply_guidance == after_apply_guidance.restartXAPI) - { - actions.Add(new RestartAgentPlanAction(host)); - } - - if (patch.after_apply_guidance == after_apply_guidance.restartHVM) - { - actions.Add(new RebootVMsPlanAction(host, RunningHvmVMs(host))); - } - - if (patch.after_apply_guidance == after_apply_guidance.restartPV) - { - actions.Add(new RebootVMsPlanAction(host, RunningPvVMs(host))); - } - - return actions; - } - - //private List ApplyAfterPatchGuidancesIfDelayedNeeded(Host host) - //{ - // List actions = new List(); - - // var guidances = DelayedGuidancesForHost(host); - - // List> runningVMs = RunningVMs(host); - - // if (guidances.Any(g => g == after_apply_guidance.restartHost)) - // { - // actions.Add(new EvacuateHostPlanAction(host)); - // actions.Add(new RebootHostPlanAction(host)); - // actions.Add(new BringBabiesBackAction(runningVMs, host, false)); - // } - - // if (guidances.Any(g => g == after_apply_guidance.restartXAPI)) - // { - // actions.Add(new RestartAgentPlanAction(host)); - // } - - // if (guidances.Any(g => g == after_apply_guidance.restartHVM)) - // { - // actions.Add(new RebootVMsPlanAction(host, RunningHvmVMs(host))); - // } - - // if (guidances.Any(g => g == after_apply_guidance.restartPV)) - // { - // actions.Add(new RebootVMsPlanAction(host, RunningPvVMs(host))); - // } - - // return actions; - //} - - private void AddToUploadedUpdates(string patchPath, Host host) - { - if (!uploadedUpdates.ContainsKey(patchPath)) - { - List hosts = new List(); - hosts.Add(host); - uploadedUpdates.Add(patchPath, hosts); - } - else if (!uploadedUpdates[patchPath].Contains(host)) - { - uploadedUpdates[patchPath].Add(host); - } - } - - private AsyncAction PrepareUploadToHostActions(Host host, XenServerPatch patch) - { - AsyncAction action = null; - - var master = Helpers.GetMaster(host.Connection); - - var patchTempFile = downloadedPatches[patch.Uuid]; - - if (!PatchExistsOnPool(patch, master) - || !uploadedUpdates.ContainsKey(patchTempFile) - || !uploadedUpdates[patchTempFile].Contains(master)) - { - action = new UploadPatchAction(master.Connection, patchTempFile, true, false); - AddToUploadedUpdates(patchTempFile, master); - - - } - - - - return action; - - - //if (action != null) - //{ - // action.Changed += singleAction_Changed; - // action.Completed += singleAction_Completed; - //} - //else - //{ - // _patch = GetPatchFromPatchPath(); - //} - //uploadActions.Add(selectedServer, action); - - - //foreach (KeyValuePair uploadAction in uploadActions) - //{ - // flickerFreeListBox1.Items.Add(uploadAction); - //} - - //flickerFreeListBox1.Refresh(); - //OnPageUpdated(); - } - - - private static bool PatchExistsOnPool(XenServerPatch patch, Host poolMaster) - { - var poolPatches = new List(poolMaster.Connection.Cache.Pool_patches); - - return (poolPatches.Exists(p => string.Equals(p.uuid, patch.Uuid, StringComparison.OrdinalIgnoreCase))); - } - - private static List> RunningVMs(Host host) - { - List> vms = new List>(); - foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs)) - { - if (!vm.is_a_real_vm) - continue; - - vms.Add(new XenRef(vm.opaque_ref)); - } - return vms; - } - - private static List> RunningHvmVMs(Host host) - { - List> vms = new List>(); - foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs)) - { - if (!vm.IsHVM || !vm.is_a_real_vm) - continue; - vms.Add(new XenRef(vm.opaque_ref)); - } - return vms; - } - - private static List> RunningPvVMs(Host host) - { - List> vms = new List>(); - foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs)) - { - if (vm.IsHVM || !vm.is_a_real_vm) - continue; - vms.Add(new XenRef(vm.opaque_ref)); - } - return vms; - } - - - - - - private Dictionary> uploadedUpdates = new Dictionary>(); - - private Dictionary downloadedPatches = new Dictionary(); - - private AsyncAction GetDownloadFileAction(XenServerPatch patch) - { - string patchUri = patch.PatchUrl; - if (string.IsNullOrEmpty(patchUri)) - throw new NullReferenceException("PatchUrl"); - - Uri address = new Uri(patchUri); - string tempFile = Path.GetTempFileName(); - - var downloadAction = new DownloadAndUnzipXenServerPatchAction(patch.Name, address, tempFile, Branding.Update); - downloadedPatches[patch.Uuid] = tempFile; - return downloadAction; - - //if (downloadAction != null) - //{ - // downloadAction.Changed += singleAction_Changed; - // downloadAction.Completed += singleAction_Completed; - //} - - //downloadAction.RunAsync(); - - //flickerFreeListBox1.Items.Clear(); - //flickerFreeListBox1.Items.Add(downloadAction); - //flickerFreeListBox1.Refresh(); - //OnPageUpdated(); - - //UpdateActionProgress(downloadAction); - } - - - - - - - - - */ } } + diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs index 80ab4f017..3a5e1eb85 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs @@ -118,7 +118,7 @@ namespace XenAdmin.Wizards.PatchingWizard { int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, hasPool)); EnabledRow(host, SelectedUpdateType, index); - } + } } // restore server selection diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadAndUploadPatch.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadAndUploadPatch.cs index 61284acc4..792e1c05c 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadAndUploadPatch.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadAndUploadPatch.cs @@ -50,7 +50,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions private string tempFileName = null; public DownloadAndUploadPatch(IXenConnection connection, XenServerPatch patch, List mappings, Dictionary allDownloadedPatches) - : base(connection, string.Format("Download and upload {0} {1}", patch.Name, connection.Name)) + : base(connection, string.Format("Downloading and uploading {0} to {1}...", patch.Name, connection.Name)) { this.patch = patch; this.mappings = mappings; @@ -93,7 +93,6 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions if (!mappings.Any(m => m.Host == newMapping.Host && m.Pool_patch == newMapping.Pool_patch && m.XenServerPatch == patch)) mappings.Add(newMapping); } - } private void DownloadFile(ref Session session) @@ -145,7 +144,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions { Host master = Helpers.GetMaster(action.Connection); - AllDownloadedPatches[patch] = tempFileName; + AllDownloadedPatches[patch] = (action as DownloadAndUnzipXenServerPatchAction).PatchPath; } } diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs new file mode 100644 index 000000000..9e82518ca --- /dev/null +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs @@ -0,0 +1,63 @@ +/* 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 XenAdmin.Core; +using XenAPI; + +namespace XenAdmin.Wizards.PatchingWizard.PlanActions +{ + class RemoveUpdateFilesFromMaster : PlanActionWithSession + { + private readonly List patchMappings = new List(); + private readonly Host master = null; + + public RemoveUpdateFilesFromMaster(Host master, List patchMappings) + : base(master.Connection, string.Format(Messages.UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL, master.Name)) + { + this.master = master; + this.patchMappings = patchMappings; + } + + protected override void RunWithSession(ref Session session) + { + foreach (var m in patchMappings) + { + if (m.Host == master) + { + var task = Pool_patch.async_pool_clean(session, m.Pool_patch.opaque_ref); + PollTaskForResultAndDestroy(Connection, ref session, task); + } + } + + } + } +} diff --git a/XenAdmin/XenAdmin.csproj b/XenAdmin/XenAdmin.csproj index f52ef36da..32c1f15d4 100644 --- a/XenAdmin/XenAdmin.csproj +++ b/XenAdmin/XenAdmin.csproj @@ -864,6 +864,7 @@ + diff --git a/XenModel/Actions/Updates/DownloadUpdatesXmlAction.cs b/XenModel/Actions/Updates/DownloadUpdatesXmlAction.cs index 0be04fca3..1c225198c 100644 --- a/XenModel/Actions/Updates/DownloadUpdatesXmlAction.cs +++ b/XenModel/Actions/Updates/DownloadUpdatesXmlAction.cs @@ -149,6 +149,7 @@ namespace XenAdmin.Actions string name = ""; string description = ""; string guidance = ""; + string guidance_mandatory = ""; string patchVersion = ""; string url = ""; string patchUrl = ""; @@ -166,6 +167,8 @@ namespace XenAdmin.Actions description = attrib.Value; else if (attrib.Name == "after-apply-guidance") guidance = attrib.Value; + else if (attrib.Name == "guidance-mandatory") + guidance_mandatory = attrib.Value; else if (attrib.Name == "version") patchVersion = attrib.Value; else if (attrib.Name == "url") @@ -183,7 +186,7 @@ namespace XenAdmin.Actions var conflictingPatches = GetPatchDependencies(version, ConflictingPatchesNode, ConflictingPatchNode); var requiredPatches = GetPatchDependencies(version, RequiredPatchesNode, RequiredPatchNode); - XenServerPatches.Add(new XenServerPatch(uuid, name, description, guidance, patchVersion, url, + XenServerPatches.Add(new XenServerPatch(uuid, name, description, guidance, guidance_mandatory, patchVersion, url, patchUrl, timestamp, priority, installationSize, conflictingPatches, requiredPatches)); } } diff --git a/XenModel/Actions/Updates/XenServerPatch.cs b/XenModel/Actions/Updates/XenServerPatch.cs index 1717bd62f..3ee389843 100644 --- a/XenModel/Actions/Updates/XenServerPatch.cs +++ b/XenModel/Actions/Updates/XenServerPatch.cs @@ -41,6 +41,7 @@ namespace XenAdmin.Core public readonly string Name; public readonly string Description; public readonly string Guidance; + public readonly string Guidance_mandatory; public readonly Version Version; public readonly string Url; public readonly string PatchUrl; @@ -53,13 +54,14 @@ namespace XenAdmin.Core private const int DEFAULT_PRIORITY = 2; - public XenServerPatch(string uuid, string name, string description, string guidance, string version, string url, + public XenServerPatch(string uuid, string name, string description, string guidance, string guidance_mandatory , string version, string url, string patchUrl, string timestamp, string priority, string installationSize) { _uuid = uuid; Name = name; Description = description; Guidance = guidance; + Guidance_mandatory = guidance_mandatory; Version = new Version(version); if (url.StartsWith("/XenServer")) url = XenServerVersion.UpdateRoot + url; @@ -72,10 +74,11 @@ namespace XenAdmin.Core InstallationSize = 0; } - public XenServerPatch(string uuid, string name, string description, string guidance, string version, string url, + public XenServerPatch(string uuid, string name, string description, string guidance, string guidance_mandatory, string version, string url, string patchUrl, string timestamp, string priority, string installationSize, List conflictingPatches, List requiredPatches) - : this(uuid, name, description, guidance, version, url, patchUrl, timestamp, priority, installationSize) + : this(uuid, name, description, guidance, guidance_mandatory, version, url, patchUrl, timestamp, priority, installationSize) { + ConflictingPatches = conflictingPatches; RequiredPatches = requiredPatches; } @@ -118,7 +121,7 @@ namespace XenAdmin.Core { get { - return this.Guidance != null && this.Guidance.ToLowerInvariant().Contains("mandatory"); + return !string.IsNullOrEmpty(Guidance_mandatory) && this.Guidance_mandatory.ToLowerInvariant().Contains("true"); } } diff --git a/XenModel/Messages.Designer.cs b/XenModel/Messages.Designer.cs index 5d5d31194..210cbbecd 100755 --- a/XenModel/Messages.Designer.cs +++ b/XenModel/Messages.Designer.cs @@ -25972,6 +25972,15 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to Automatic update has finished.. + /// + public static string PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE { + get { + return ResourceManager.GetString("PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE", resourceCulture); + } + } + /// /// Looks up a localized string similar to [XenCenter] is now downloading your update and uploading it to the servers specified in the previous step. ///Please wait for these operations to complete, then click Next to continue with the installation.. @@ -32740,6 +32749,15 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to Removing update files from {0}.... + /// + public static string UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL { + get { + return ResourceManager.GetString("UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL", resourceCulture); + } + } + /// /// Looks up a localized string similar to Click here to repair. /// diff --git a/XenModel/Messages.resx b/XenModel/Messages.resx index 8357491c7..9eba0880b 100755 --- a/XenModel/Messages.resx +++ b/XenModel/Messages.resx @@ -8979,6 +8979,9 @@ However, there is not enough space to perform the repartitioning, so the current Select the servers you wish to update + + Automatic update has finished. + [XenCenter] is now downloading your update and uploading it to the servers specified in the previous step. Please wait for these operations to complete, then click Next to continue with the installation. @@ -11318,6 +11321,9 @@ Check your settings and try again. Removing update {0} from {1}... + + Removing update files from {0}... + Click here to repair