示例#1
0
        private Pool_patch UploadRetailPatch()
        {
            Session session = NewSession();

            Host master = Helpers.GetMaster(Connection);

            log.InfoFormat("Uploading file '{0}' to server '{1}'", _patchName, master.Name());
            this.Description = string.Format(Messages.UPLOAD_PATCH_UPLOADING_DESCRIPTION, _patchName);

            try
            {
                RelatedTask = Task.create(session, "put_pool_patch_upload_task", master.address);
                log.DebugFormat("HTTP PUTTING file from {0} to {1}", retailPatchPath, master.address);

                HTTP_actions.put_pool_patch_upload(UpdateProgress,
                                                   () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                                   XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                   master.address,
                                                   XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                   retailPatchPath, RelatedTask.opaque_ref, session.opaque_ref);

                PollToCompletion();
                return(Connection.WaitForCache(new XenRef <Pool_patch>(new XenRef <Pool_patch>(Result))));
            }
            catch (Exception e)
            {
                PollToCompletion(suppressFailures: true);

                if (e is TargetInvocationException ex)
                {
                    if (ex.InnerException == null)
                    {
                        throw;
                    }
                    else
                    {
                        throw ex.InnerException;
                    }
                }

                if (e is CancelledException || e is HTTP.CancelledException || e.InnerException is CancelledException)
                {
                    if (deleteFileOnCancel && File.Exists(retailPatchPath))
                    {
                        File.Delete(retailPatchPath);
                    }
                    throw new CancelledException();
                }

                throw;
            }
        }
示例#2
0
        private string applyFile()
        {
            log.DebugFormat("Importing XVA from {0} to SR {1}", m_filename, SR.Name());

            Host host = SR.GetStorageHost();

            string hostURL;

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

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

            try
            {
                RelatedTask = Task.create(Session, "put_import_task", hostURL);
                log.DebugFormat("HTTP PUTTING file from {0} to {1}", m_filename, hostURL);

                HTTP_actions.put_import(percent => PercentComplete = percent,
                                        () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                        HTTP_PUT_TIMEOUT, hostURL,
                                        XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                        m_filename, RelatedTask.opaque_ref, Session.opaque_ref, false, false, SR.opaque_ref);

                PollToCompletion();
                return(Result);
            }
            catch (Exception e)
            {
                PollToCompletion(suppressFailures: true);
                if (e is CancelledException || e is HTTP.CancelledException || e.InnerException is CancelledException)
                {
                    throw new CancelledException();
                }
                throw;
            }
        }
示例#3
0
        protected override void Run()
        {
            LogDescriptionChanges = false;

            try
            {
                switch (type)
                {
                case HostBackupRestoreType.backup:
                    Description = string.Format(Messages.BACKINGUP_HOST, Host.Name());
                    RelatedTask = Task.create(Session, "get_host_backup_task", Host.address);
                    log.DebugFormat("HTTP GETTING file from {0} to {1}", Host.address, filename);

                    HTTP_actions.get_host_backup(DataReceived,
                                                 () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                                 XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                 Host.address,
                                                 XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                 filename, RelatedTask.opaque_ref, Session.opaque_ref);

                    PollToCompletion();
                    Description = string.Format(Messages.HOST_BACKEDUP, Host.Name());
                    break;

                case HostBackupRestoreType.restore:
                    Description = string.Format(Messages.RESTORING_HOST, Host.Name());
                    RelatedTask = Task.create(Session, "put_host_restore_task", Host.address);
                    log.DebugFormat("HTTP PUTTING file from {0} to {1}", filename, Host.address);

                    HTTP_actions.put_host_restore(percent => PercentComplete = percent,
                                                  () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                                  XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                  Host.address,
                                                  XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                  filename, RelatedTask.opaque_ref, Session.opaque_ref);

                    PollToCompletion();
                    Description = string.Format(Messages.HOST_RESTORED, Host.Name());
                    break;
                }
            }
            catch (Exception e)
            {
                PollToCompletion(suppressFailures: true);

                if (e is WebException && e.InnerException is IOException ioe && Win32.GetHResult(ioe) == Win32.ERROR_DISK_FULL)
                {
                    throw e.InnerException;
                }

                if (e is CancelledException || e is HTTP.CancelledException || e.InnerException is CancelledException)
                {
                    throw new CancelledException();
                }

                if (e.InnerException?.Message == "Received error code HTTP/1.1 403 Forbidden\r\n from the server")
                {
                    // RBAC Failure
                    List <Role> roles = Connection.Session.Roles;
                    roles.Sort();
                    throw new Exception(String.Format(Messages.RBAC_HTTP_FAILURE, roles[0].FriendlyName()), e);
                }

                if (e.InnerException != null)
                {
                    throw e.InnerException;
                }
                throw;
            }
            finally
            {
                LogDescriptionChanges = true;
            }
        }
示例#4
0
        protected XenRef <Pool_patch> BringPatchToPoolForHost(Host host, Pool_patch patch)
        {
            // Check the patch exists on the pool this host is connected to
            XenRef <Pool_patch> patch_ref = host.Connection.Cache.FindRef(patch);

            if (patch_ref != null)
            {
                return(patch_ref);
            }

            // 1st download patch from the pool that has it (the connection on the xenobject)

            string filename = Path.GetTempFileName();

            try
            {
                Connection = patch.Connection;
                Session    = patch.Connection.DuplicateSession();

                try
                {
                    RelatedTask = Task.create(Session, "get_pool_patch_download_task", patch.Connection.Hostname);
                    log.DebugFormat("HTTP GETTING file from {0} to {1}", patch.Connection.Hostname, filename);

                    HTTP_actions.get_pool_patch_download(
                        bytes =>
                    {
                        PercentComplete = (int)(100 * (double)bytes / patch.size);

                        Description = string.Format(Messages.DOWNLOADING_PATCH_FROM, patch.Connection.Name,
                                                    Util.DiskSizeString(bytes, 1, "F1"), Util.DiskSizeString(patch.size));
                    },
                        () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                        XenAdminConfigManager.Provider.GetProxyTimeout(true),
                        patch.Connection.Hostname,
                        XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                        filename, RelatedTask.opaque_ref, Session.opaque_ref, patch.uuid);

                    PollToCompletion();
                }
                catch (Exception e)
                {
                    PollToCompletion(suppressFailures: true);

                    if (e is WebException && e.InnerException is IOException ioe && Win32.GetHResult(ioe) == Win32.ERROR_DISK_FULL)
                    {
                        throw new PatchDownloadFailedException(string.Format(Messages.PATCH_DOWNLOAD_FAILED, patch.name_label, patch.Connection.Name), e.InnerException);
                    }

                    if (e is CancelledException || e is HTTP.CancelledException || e.InnerException is CancelledException)
                    {
                        throw new CancelledException();
                    }

                    if (e.InnerException?.Message == "Received error code HTTP/1.1 403 Forbidden\r\n from the server")
                    {
                        // RBAC Failure
                        List <Role> roles = Connection.Session.Roles;
                        roles.Sort();
                        throw new Exception(String.Format(Messages.RBAC_HTTP_FAILURE, roles[0].FriendlyName()), e);
                    }

                    throw new PatchDownloadFailedException(string.Format(Messages.PATCH_DOWNLOAD_FAILED, patch.name_label, patch.Connection.Name), e.InnerException ?? e);
                }
                finally
                {
                    Session    = null;
                    Connection = null;
                }

                // Then, put it on the pool that doesn't have it

                Description = String.Format(Messages.UPLOADING_PATCH_TO, host.Name());
                Connection  = host.Connection;
                Session     = host.Connection.DuplicateSession();

                try
                {
                    RelatedTask = Task.create(Session, "put_pool_patch_upload_task", host.Connection.Hostname);
                    log.DebugFormat("HTTP PUTTING file from {0} to {1}", filename, host.Connection.Hostname);

                    HTTP_actions.put_pool_patch_upload(percent => PercentComplete = percent,
                                                       () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                                       XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                       host.Connection.Hostname,
                                                       XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                       filename, RelatedTask.opaque_ref, Session.opaque_ref);

                    PollToCompletion();
                    Description = string.Format(Messages.PATCH_UPLOADED, host.Name());
                    return(new XenRef <Pool_patch>(Result));
                }
                catch (Exception e)
                {
                    PollToCompletion(suppressFailures: true);

                    if (e is CancelledException || e is HTTP.CancelledException || e.InnerException is CancelledException)
                    {
                        throw new CancelledException();
                    }
                    throw;
                }
                finally
                {
                    Session    = null;
                    Connection = null;
                }
            }
            finally
            {
                File.Delete(filename);
            }
        }
        protected override void Run()
        {
            Description = string.Format(Messages.ACTION_SYSTEM_STATUS_COMPILING, Helpers.GetName(host));
            Status      = ReportStatus.compiling;

            string hostname = Helpers.GetName(host);

            hostname = TarSanitization.SanitizeTarPathMember(hostname);
            if (hostname.Length > 20)
            {
                hostname = hostname.Truncate(20);
            }

            string filename = string.Format("{1}\\{2}-bugtool-{0}.tar", hostname, filePath, timeString);

            string entries_string = string.Join(",", capabilityKeys);

            log.DebugFormat("Getting system status for {0} on {1}", entries_string, hostname);

            if (Session == null)
            {
                throw new Exception(Messages.CONNECTION_IO_EXCEPTION);
            }

            try
            {
                RelatedTask = Task.create(Session, "get_system_status_task", host.address);
                log.DebugFormat("HTTP GETTING file from {0} to {1}", host.address, filename);

                HTTP_actions.get_system_status(dataRxDelegate,
                                               () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                               XenAdminConfigManager.Provider.GetProxyTimeout(false),
                                               host.address,
                                               XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                               filename, RelatedTask.opaque_ref, Session.opaque_ref, entries_string, "tar");

                PollToCompletion();
                Status          = ReportStatus.succeeded;
                Description     = Messages.COMPLETED;
                PercentComplete = 100;
            }
            catch (Exception e)
            {
                PollToCompletion(suppressFailures: true);

                if (e is HTTP.CancelledException || e is CancelledException)
                {
                    log.Info("Getting system status cancelled");
                    Status      = ReportStatus.cancelled;
                    Error       = e;
                    Description = Messages.ACTION_SYSTEM_STATUS_CANCELLED;
                    throw new CancelledException();
                }

                log.Error(string.Format("Getting system status from {0} failed", hostname), e);
                Status = ReportStatus.failed;
                Error  = e;

                if (Win32.GetHResult(e) == Win32.ERROR_DISK_FULL)
                {
                    Description = Messages.ACTION_SYSTEM_STATUS_DISK_FULL;
                    return;
                }

                if (!string.IsNullOrEmpty(Error.Message) && RBAC_FAIL_STRINGS.All(s => Error.Message.Contains(s)))
                {
                    var roles = Host.Connection.Session.Roles;
                    roles.Sort();
                    Description = string.Format(Messages.BUGTOOL_RBAC_FAILURE, roles[0].FriendlyName());
                    return;
                }

                Description = Messages.BUGTOOL_REPORTSTATUS_FAILED;
            }
        }
示例#6
0
        private EnvelopeType Export(string targetDir, VM vm, Action <float> updatePercentage)
        {
            if (vm.power_state != vm_power_state.Halted && vm.power_state != vm_power_state.Suspended)
            {
                log.Error($"Cannot export VM {vm.Name()} ({vm.opaque_ref}); it is neither halted nor suspended.");
                throw new Exception(string.Format(Messages.ERROR_VM_NOT_HALTED, vm.Name()));
            }

            log.Info($"Exporting metadata for {vm.name_label}...");

            #region CREATE ENVELOPE / ADD VIRTUAL SYSTEM
            EnvelopeType ovfEnv = OVF.CreateEnvelope(m_applianceFileName);
            string       vsId   = OVF.AddVirtualSystem(ovfEnv, vm.name_label);
            string       vhsId  = OVF.AddVirtualHardwareSection(ovfEnv, vsId);
            #endregion

            #region TRY TO ID OS

            VM_guest_metrics vmgm = Connection.Resolve(vm.guest_metrics);

            if (vmgm?.os_version != null && vmgm.os_version.TryGetValue("name", out string osName))
            {
                ushort osId = ValueMaps.OperatingSystem(osName);
                if (osId == 0xFFFF)
                {
                    osId = 1; // change to OTHER since search failed.
                }
                string version = OVF.GetContentMessage("SECTION_OPERATINGSYSTEM_INFO");

                if (vmgm.os_version.TryGetValue("major", out string major) &&
                    vmgm.os_version.TryGetValue("minor", out string minor))
                {
                    version = string.Format(OVF.GetContentMessage("SECTION_OPERATINGSYSTEM_VERSION"), major, minor);
                }

                string[] osNameParts = osName.Split('|');
                if (osNameParts.Length > 0)
                {
                    OVF.UpdateOperatingSystemSection(ovfEnv, vsId, osNameParts[0], version, osId);
                }
            }

            #endregion

            #region ADD VirtualSystemType identification
            var pv     = vm.IsHVM() ? "hvm" : "xen";
            var arch   = string.IsNullOrEmpty(vm.domarch) ? "unknown" : vm.domarch;
            var vmType = string.Format("{0}-3.0-{1}", pv, arch);

            OVF.AddVirtualSystemSettingData(ovfEnv, vsId, vhsId, vm.name_label, OVF.GetContentMessage("VSSD_CAPTION"), vm.name_description, Guid.NewGuid().ToString(), vmType);
            #endregion

            #region ADD CPUS
            OVF.SetCPUs(ovfEnv, vsId, (ulong)vm.VCPUs_max);
            #endregion

            #region ADD MEMORY
            OVF.SetMemory(ovfEnv, vsId, (ulong)(vm.memory_dynamic_max / Util.BINARY_MEGA), "MB");
            #endregion

            #region ADD NETWORKS

            foreach (XenRef <VIF> vifRef in vm.VIFs)
            {
                VIF vif = Connection.Resolve(vifRef);
                if (vif == null)
                {
                    continue;
                }

                XenAPI.Network net = Connection.Resolve(vif.network);
                if (net == null)
                {
                    continue;
                }

                OVF.AddNetwork(ovfEnv, vsId, net.uuid, net.name_label, net.name_description, vif.MAC);
            }

            #endregion

            #region SET STARTUP OPTIONS
            OVF.AddStartupSection(ovfEnv, true, vsId, vm.order, vm.start_delay, vm.shutdown_delay);
            #endregion

            #region EXPORT DISKS

            int diskIndex = 0;
            var vbdRefs   = vm.VBDs;

            for (int i = 0; i < vbdRefs.Count; i++)
            {
                int          curVbd = i;
                XenRef <VBD> vbdRef = vbdRefs[i];

                VBD vbd = Connection.Resolve(vbdRef);
                if (vbd == null)
                {
                    continue;
                }

                if (vbd.type == vbd_type.CD)
                {
                    string rasdid = OVF.AddCDROM(ovfEnv, vsId, vbd.uuid, OVF.GetContentMessage("RASD_16_CAPTION"), OVF.GetContentMessage("RASD_16_DESCRIPTION"));
                    OVF.SetTargetDeviceInRASD(ovfEnv, vsId, rasdid, vbd.userdevice);
                    continue;
                }

                VDI vdi = Connection.Resolve(vbd.VDI);
                if (vdi == null)
                {
                    continue;
                }

                try
                {
                    var diskFilename = $"{vdi.uuid}.vhd";
                    var diskPath     = Path.Combine(targetDir, diskFilename);

                    if (File.Exists(diskPath))
                    {
                        var oldFileName = diskFilename;
                        diskFilename = $"{vdi.uuid}_{Thread.CurrentThread.ManagedThreadId}.vhd";
                        diskPath     = Path.Combine(targetDir, diskFilename);
                        log.InfoFormat("VHD Name collision, renamed {0} to {1}", oldFileName, diskFilename);
                    }

                    string diskName = vdi.name_label;
                    if (string.IsNullOrEmpty(diskName))
                    {
                        diskName = $"{OVF.GetContentMessage("RASD_19_CAPTION")} {diskIndex}";
                    }

                    if (!MetaDataOnly)
                    {
                        log.Info($"Exporting disk {diskName} to {diskFilename} for {vm.name_label}...");

                        var taskRef = Task.create(Connection.Session, "export_raw_vdi_task",
                                                  $"Exporting VDI {vdi.uuid} to {diskFilename}");

                        HTTP_actions.get_export_raw_vdi(b =>
                        {
                            Description = string.Format(Messages.EXPORTING_VDI, diskName, diskFilename,
                                                        Util.DiskSizeString(b, 2, "F2"), Util.DiskSizeString(vdi.virtual_size));
                            updatePercentage((curVbd + (float)b / vdi.virtual_size) / vbdRefs.Count);
                        },
                                                        () => Cancelling, XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                        Connection.Hostname, XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                        diskPath, taskRef, Connection.Session.opaque_ref, vdi.uuid, "vhd");

                        if (m_shouldVerify)
                        {
                            Description = string.Format(Messages.EXPORTING_VDI_VERIFICATION, diskFilename);

                            using (var stream = new FileStream(diskPath, FileMode.Open, FileAccess.Read))
                                using (var sw = new StringWriter())
                                {
                                    var vhdChecker = new FileChecker(stream);
                                    var result     = vhdChecker.Check(sw, ReportLevels.All);
                                    log.InfoFormat("Verifying disk {0}:\n{1}", diskFilename, sw.ToString().Replace("\0", ""));
                                    if (!result)
                                    {
                                        throw new Exception(string.Format(Messages.EXPORTING_VDI_VERIFICATION_FAILURE, diskFilename));
                                    }
                                }
                        }
                    }

                    string diskId = Guid.NewGuid().ToString();

                    OVF.AddDisk(ovfEnv, vsId, diskId, diskFilename, vbd.bootable, diskName,
                                vdi.name_description, (ulong)vdi.physical_utilisation, (ulong)vdi.virtual_size);
                    OVF.SetTargetDeviceInRASD(ovfEnv, vsId, diskId, vbd.userdevice);

                    diskIndex++;
                }
                catch (HTTP.CancelledException)
                {
                    throw new CancelledException();
                }
            }

            #endregion

            #region ADD XEN SPECIFICS

            var _params = vm.HVM_boot_params;
            if (_params != null && _params.Count > 0)
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "HVM_boot_params", string.Join(";", _params.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value))), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_6"));
            }

            if (!string.IsNullOrEmpty(vm.HVM_boot_policy))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "HVM_boot_policy", vm.HVM_boot_policy, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_2"));
            }

            if (vm.HVM_shadow_multiplier != 1.0)
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "HVM_shadow_multiplier", Convert.ToString(vm.HVM_shadow_multiplier), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            var platform = vm.platform;
            if (platform != null && platform.Count > 0)
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "platform", string.Join(";", platform.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value))), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_3"));
            }

            var nvram = vm.NVRAM;
            if (nvram != null && nvram.Count > 0)
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "NVRAM", string.Join(";", nvram.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value))), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_7"));
            }

            if (!string.IsNullOrEmpty(vm.PV_args))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_args", vm.PV_args, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.PV_bootloader))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_bootloader", vm.PV_bootloader, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.PV_bootloader_args))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_bootloader_args", vm.PV_bootloader_args, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.PV_kernel))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_kernel", vm.PV_kernel, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.PV_legacy_args))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_legacy_args", vm.PV_legacy_args, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.PV_ramdisk))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "PV_ramdisk", vm.PV_ramdisk, OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (vm.hardware_platform_version >= 0)
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "hardware_platform_version", vm.hardware_platform_version.ToString(), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (!string.IsNullOrEmpty(vm.recommendations))
            {
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "recommendations", vm.recommendations.ToString(), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            if (vm.has_vendor_device)
            {
                //serialise it with a different name to avoid it being deserialised automatically and getting the wrong type
                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "VM_has_vendor_device", vm.has_vendor_device.ToString(), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_1"));
            }

            foreach (XenRef <VGPU> gpuRef in vm.VGPUs)
            {
                VGPU vgpu = Connection.Resolve(gpuRef);

                if (vgpu != null)
                {
                    var vgpuGroup = Connection.Resolve(vgpu.GPU_group);
                    var vgpuType  = Connection.Resolve(vgpu.type);

                    var sb = new StringBuilder();
                    sb.AppendFormat("GPU_types={{{0}}};",
                                    vgpuGroup?.GPU_types == null || vgpuGroup.GPU_types.Length < 1
                            ? ""
                            : string.Join(";", vgpuGroup.GPU_types));
                    sb.AppendFormat("VGPU_type_vendor_name={0};", vgpuType?.vendor_name ?? "");
                    sb.AppendFormat("VGPU_type_model_name={0};", vgpuType?.model_name ?? "");
                    OVF.AddOtherSystemSettingData(ovfEnv, vsId, "vgpu", sb.ToString(), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_4"), true);
                }
            }

            string pvsSiteUuid = string.Empty;
            var    allProxies  = Connection.Cache.PVS_proxies;

            foreach (var p in allProxies.Where(p => p != null && p.VIF != null))
            {
                var vif = Connection.Resolve(p.VIF);
                if (vif != null)
                {
                    var vmFromVif = Connection.Resolve(vif.VM);
                    if (vmFromVif != null && vmFromVif.uuid == vm.uuid)
                    {
                        var pvsSite = Connection.Resolve(p.site);
                        if (pvsSite != null)
                        {
                            pvsSiteUuid = pvsSite.uuid;
                        }

                        break;
                    }
                }
            }

            if (!string.IsNullOrEmpty(pvsSiteUuid))
            {
                var sb = new StringBuilder();
                sb.AppendFormat("PVS_SITE={{{0}}};", string.Format("uuid={0}", pvsSiteUuid));

                OVF.AddOtherSystemSettingData(ovfEnv, vsId, "pvssite", sb.ToString(), OVF.GetContentMessage("OTHER_SYSTEM_SETTING_DESCRIPTION_5"));
            }

            #endregion

            OVF.FinalizeEnvelope(ovfEnv);
            return(ovfEnv);
        }
        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, "put_import_raw_vdi_task", hostUrl);
                log.DebugFormat("HTTP PUTTING file from {0} to {1}", suppPackFilePath, hostUrl);

                HTTP_actions.put_import_raw_vdi(progressDelegate,
                                                () => XenAdminConfigManager.Provider.ForcedExiting || GetCancelling(),
                                                XenAdminConfigManager.Provider.GetProxyTimeout(true),
                                                hostUrl,
                                                XenAdminConfigManager.Provider.GetProxyFromSettings(Connection),
                                                suppPackFilePath, RelatedTask.opaque_ref, session.opaque_ref, vdiRef.opaque_ref);

                PollToCompletion();
                result = Result;
            }
            catch (Exception ex)
            {
                PollToCompletion(suppressFailures: true);

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

                if (ex is CancelledException || ex is HTTP.CancelledException || ex.InnerException is CancelledException)
                {
                    throw new CancelledException();
                }

                log.Error("Failed to import a virtual disk over HTTP", ex);

                //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;
                }
            }

            //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);
        }