public static void RefreshUpdate(Host host, HostUpdateMapping mapping, Session session)
 {
     // re-introduce pool_update if needed
     if (mapping is PoolUpdateMapping poolUpdateMapping &&
         session.Connection.Cache.Pool_updates.FirstOrDefault(u => string.Equals(u.uuid, poolUpdateMapping.Pool_update.uuid, StringComparison.OrdinalIgnoreCase)) == null)
     {
         log.InfoFormat("Re-introduce update on '{0}'. Update = '{1}' (uuid = '{2}'; old opaque_ref = '{3}')",
                        host.Name(), poolUpdateMapping.Pool_update.Name(), poolUpdateMapping.Pool_update.uuid,
                        poolUpdateMapping.Pool_update.opaque_ref);
         try
         {
             var newUpdateRef = Pool_update.introduce(session, poolUpdateMapping.Pool_update.vdi.opaque_ref);
             session.Connection.WaitForCache(newUpdateRef);
         }
         catch (Exception e)
         {
             if (e is Failure failure && failure.ErrorDescription != null && failure.ErrorDescription.Count > 1 && failure.ErrorDescription[0] == Failure.UPDATE_ALREADY_EXISTS)
             {
                 log.InfoFormat("Update '{0}' already exists", poolUpdateMapping.Pool_update.Name());
             }
        private string UploadSupplementalPack(SR sr)
        {
            this.Description = String.Format(Messages.SUPP_PACK_UPLOADING_TO, sr.Name());

            String result;

            log.DebugFormat("Creating vdi of size {0} bytes on SR '{1}'", diskSize, sr.Name());

            VDI          vdi    = NewVDI(sr);
            XenRef <VDI> vdiRef = null;

            try
            {
                vdiRef = VDI.create(Session, vdi);
            }
            catch (Exception ex)
            {
                log.ErrorFormat("{0} {1}", "Failed to create VDI", ex.Message);
                throw;
            }

            log.DebugFormat("Uploading file '{0}' to VDI '{1}' on SR '{2}'", suppPackFilePath, vdi.Name(), sr.Name());

            Host localStorageHost = sr.GetStorageHost();

            string hostUrl;

            if (localStorageHost == null)
            {
                Uri uri = new Uri(Session.Url);
                hostUrl = uri.Host;
            }
            else
            {
                log.DebugFormat("SR is not shared -- redirecting to {0}", localStorageHost.address);
                hostUrl = localStorageHost.address;
            }

            log.DebugFormat("Using {0} for import", hostUrl);

            try
            {
                HTTP.UpdateProgressDelegate progressDelegate = delegate(int percent)
                {
                    var actionPercent = (int)(((totalUploaded * 100) + percent) / totalCount);
                    Tick(actionPercent, Description);
                };

                Session session = NewSession();
                RelatedTask = Task.create(Session, "uploadTask", hostUrl);

                result = HTTPHelper.Put(progressDelegate, GetCancelling, true, Connection, RelatedTask, ref session, suppPackFilePath, hostUrl,
                                        (HTTP_actions.put_sss)HTTP_actions.put_import_raw_vdi,
                                        session.opaque_ref, vdiRef.opaque_ref);
            }
            catch (Exception ex)
            {
                log.ErrorFormat("{0} {1}", "Failed to import a virtual disk over HTTP.", ex.Message);

                if (vdiRef != null)
                {
                    log.DebugFormat("Removing the VDI on a best effort basis.");

                    try
                    {
                        RemoveVDI(Session, vdiRef);
                    }
                    catch (Exception removeEx)
                    {
                        //best effort
                        log.Error("Failed to remove the VDI.", removeEx);
                    }
                }

                //after having tried to remove the VDI, the original exception is thrown for the UI
                if (ex is TargetInvocationException && ex.InnerException != null)
                {
                    throw ex.InnerException;
                }
                else
                {
                    throw ex;
                }
            }
            finally
            {
                Task.destroy(Session, RelatedTask);
                RelatedTask = null;
            }

            if (localStorageHost != null)
            {
                VdiRefsToCleanUp.Add(localStorageHost, vdiRef);
            }
            else // shared SR
            {
                foreach (var server in servers)
                {
                    VdiRefsToCleanUp.Add(server, vdiRef);
                }
            }

            //introduce ISO for Ely and higher
            if (Helpers.ElyOrGreater(Connection))
            {
                try
                {
                    var poolUpdateRef = Pool_update.introduce(Connection.Session, vdiRef);
                    poolUpdate = Connection.WaitForCache(poolUpdateRef);

                    if (poolUpdate == null)
                    {
                        throw new Exception(Messages.UPDATE_ERROR_INTRODUCE); // This should not happen, because such case will result in a XAPI Failure. But this code has to be protected at this point.
                    }
                    VdiRefsToCleanUp.Clear();
                }
                catch (Failure ex)
                {
                    if (ex.ErrorDescription != null && ex.ErrorDescription.Count > 1 && string.Equals("UPDATE_ALREADY_EXISTS", ex.ErrorDescription[0], StringComparison.InvariantCultureIgnoreCase))
                    {
                        string uuidFound = ex.ErrorDescription[1];

                        poolUpdate = Connection.Cache.Pool_updates.FirstOrDefault(pu => string.Equals(pu.uuid, uuidFound, System.StringComparison.InvariantCultureIgnoreCase));

                        //clean-up the VDI we've just created
                        try
                        {
                            RemoveVDI(Session, vdiRef);

                            //remove the vdi that have just been cleaned up
                            var remaining = VdiRefsToCleanUp.Where(kvp => kvp.Value != null && kvp.Value.opaque_ref != vdiRef.opaque_ref).ToList();
                            VdiRefsToCleanUp.Clear();
                            remaining.ForEach(rem => VdiRefsToCleanUp.Add(rem.Key, rem.Value));
                        }
                        catch
                        {
                            //best effort cleanup
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    log.ErrorFormat("Upload failed when introducing update from VDI {0} on {1}: {2}", vdi.opaque_ref, Connection, ex.Message);
                    poolUpdate = null;

                    throw;
                }
            }
            else
            {
                poolUpdate = null;
            }

            totalUploaded++;
            Description = String.Format(Messages.SUPP_PACK_UPLOADED, sr.Name());

            foreach (Host host in servers)
            {
                SrUploadedUpdates[host] = sr;
            }

            return(result);
        }
        private string UploadSupplementalPack(SR sr)
        {
            this.Description = String.Format(Messages.SUPP_PACK_UPLOADING_TO, _updateName, sr.Name());
            log.DebugFormat("Creating vdi of size {0} bytes on SR '{1}'", _totalUpdateSize, sr.Name());

            VDI vdi    = NewVDI(sr);
            var vdiRef = VDI.create(Session, vdi);

            Host localStorageHost = sr.GetStorageHost();

            string hostUrl;

            if (localStorageHost == null)
            {
                Uri uri = new Uri(Session.Url);
                hostUrl = uri.Host;
            }
            else
            {
                log.DebugFormat("SR is not shared -- redirecting to {0}", localStorageHost.address);
                hostUrl = localStorageHost.address;
            }

            log.DebugFormat("Using {0} for import", hostUrl);

            string result;

            try
            {
                log.DebugFormat("Uploading file '{0}' to VDI '{1}' on SR '{2}'", suppPackFilePath, vdi.Name(), sr.Name());

                HTTP.UpdateProgressDelegate progressDelegate = delegate(int percent)
                {
                    var sr1   = sr;
                    var descr = string.Format(Messages.UPLOAD_PATCH_UPLOADING_TO_SR_PROGRESS_DESCRIPTION, _updateName, sr1.Name(),
                                              Util.DiskSizeString(percent * _totalUpdateSize / 100, "F1"), Util.DiskSizeString(_totalUpdateSize));

                    var actionPercent = (int)((totalUploaded * 100 + percent) / totalCount);
                    ByteProgressDescription = descr;
                    Tick(actionPercent, descr);
                };

                Session session = NewSession();
                RelatedTask = Task.create(Session, "uploadTask", hostUrl);

                result = HTTPHelper.Put(progressDelegate, GetCancelling, true, Connection, RelatedTask, ref session, suppPackFilePath, hostUrl,
                                        (HTTP_actions.put_sss)HTTP_actions.put_import_raw_vdi,
                                        session.opaque_ref, vdiRef.opaque_ref);
            }
            catch (Exception ex)
            {
                log.Error("Failed to import a virtual disk over HTTP", ex);

                if (vdiRef != null)
                {
                    try
                    {
                        log.ErrorFormat("Deleting VDI '{0}' on a best effort basis.", vdiRef.opaque_ref);
                        Thread.Sleep(1000);
                        VDI.destroy(Session, vdiRef);
                    }
                    catch (Exception removeEx)
                    {
                        log.Error("Failed to remove VDI.", removeEx);
                    }
                }

                //after having tried to remove the VDI, the original exception is thrown for the UI
                if (ex is TargetInvocationException && ex.InnerException != null)
                {
                    throw ex.InnerException;
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                Task.destroy(Session, RelatedTask);
                RelatedTask = null;
            }

            //introduce ISO for Ely and higher
            if (Helpers.ElyOrGreater(Connection))
            {
                try
                {
                    var poolUpdateRef = Pool_update.introduce(Connection.Session, vdiRef);
                    poolUpdate = Connection.WaitForCache(poolUpdateRef);

                    if (poolUpdate == null)
                    {
                        throw new Exception(Messages.UPDATE_ERROR_INTRODUCE); // This should not happen, because such case will result in a XAPI Failure. But this code has to be protected at this point.
                    }
                }
                catch (Exception ex)
                {
                    //clean-up the VDI we've just created
                    try
                    {
                        log.ErrorFormat("Deleting VDI '{0}' on a best effor basis.", vdiRef);
                        VDI.destroy(Session, vdiRef);
                    }
                    catch (Exception removeEx)
                    {
                        log.Error("Failed to remove VDI", removeEx);
                    }

                    var failure = ex as Failure;
                    if (failure != null && failure.ErrorDescription != null && failure.ErrorDescription.Count > 1 && failure.ErrorDescription[0] == Failure.UPDATE_ALREADY_EXISTS)
                    {
                        string uuidFound = failure.ErrorDescription[1];

                        poolUpdate = Connection.Cache.Pool_updates.FirstOrDefault(pu => string.Equals(pu.uuid, uuidFound, StringComparison.InvariantCultureIgnoreCase));
                    }
                    else
                    {
                        log.Error("Failed to introduce the update", ex);
                        poolUpdate = null;
                        throw;
                    }
                }
            }
            else
            {
                poolUpdate = null;
            }

            if (localStorageHost != null)
            {
                VdiRefsPerHost.Add(localStorageHost, vdiRef);
            }
            else // shared SR
            {
                foreach (var server in servers)
                {
                    VdiRefsPerHost.Add(server, vdiRef);
                }
            }

            totalUploaded++;
            Description = string.Format(Messages.SUPP_PACK_UPLOADED, sr.Name());

            foreach (Host host in servers)
            {
                SrsWithUploadedUpdatesPerHost[host] = sr;
            }

            return(result);
        }