protected override void Run() { List<LicenseFailure> licenseFailures = new List<LicenseFailure>(); // PR-1102: hosts that have been updated, plus the previous edition information - this data will be sent to the licensing server Dictionary<Host, LicensingHelper.LicenseDataStruct> updatedHosts = new Dictionary<Host, LicensingHelper.LicenseDataStruct>(); this.Description = Messages.LICENSE_UPDATING_LICENSES; foreach (IXenObject xo in xos) { Connection = xo.Connection; if (!Connection.IsConnected) { continue; } Host host = null; Pool pool = null; if(xo is Host) host = xo as Host; if(xo is Pool) { pool = xo as Pool; host = xo.Connection.Resolve(pool.master); } string previousLicenseServerAddress = null; string previousLicenseServerPort = null; CollectionChangeEventHandler alertsChangeHandler = null; string alertText = null; object lck = new object(); if (host != null && host.license_server.ContainsKey("address")) { previousLicenseServerAddress = host.license_server["address"]; } if (host != null && host.license_server.ContainsKey("port")) { previousLicenseServerPort = host.license_server["port"]; } try { if(pool != null) pool.Connection.Cache.Hosts.ToList().ForEach(h=>SetLicenseServer(h, _licenseServerAddress, _licenseServerPort)); else SetLicenseServer(host, _licenseServerAddress, _licenseServerPort); IXenObject xoClosure = xo; alertsChangeHandler = delegate(object sender, CollectionChangeEventArgs e) { if (e.Action == CollectionChangeAction.Add) { lock (lck) { Alert alert = (Alert)e.Element; if (host != null && host.uuid == alert.HostUuid) { if (alert.Title == PropertyManager.GetFriendlyName("Message.name-license_not_available")) { // the license server reported there were no licenses available. alertText = string.Format(PropertyManager.GetFriendlyName("Message.body-license_not_available"), xoClosure.Name); } else if (alert.Title == PropertyManager.GetFriendlyName("Message.name-license_server_unreachable")) { // couldn't check out license because couldn't contact license server alertText = string.Format(PropertyManager.GetFriendlyName("Message.body-license_server_unreachable"), xoClosure.Name); } else if (alert.Title == PropertyManager.GetFriendlyName("Message.name-grace_license")) { alertText = string.Empty; } } } } }; Alert.XenCenterAlerts.CollectionChanged += alertsChangeHandler; // PR-1102: catch the host's license data, before applying the new one, so it can be sent later to the licensing server LicensingHelper.LicenseDataStruct previousLicenseData = new LicensingHelper.LicenseDataStruct(host); if(xo is Host) { Host.apply_edition(host.Connection.Session, host.opaque_ref, Host.GetEditionText(_edition)); // PR-1102: populate the list of updated hosts updatedHosts.Add(host, previousLicenseData); } if (xo is Pool) { if(!Helpers.ClearwaterOrGreater(xo.Connection)) { foreach (Host poolHost in xo.Connection.Cache.Hosts) { Host.apply_edition(host.Connection.Session, poolHost.opaque_ref, Host.GetEditionText(_edition)); } } else { Pool.apply_edition(xo.Connection.Session, pool.opaque_ref, Host.GetEditionText(_edition)); //TODO: Look into why this is required. Event.Next returning late? XAPI returning before updated? Thread.Sleep(200); } xo.Connection.Cache.Hosts.ToList().ForEach(h => updatedHosts.Add(h, previousLicenseData)); } Description = Messages.APPLYLICENSE_UPDATED; } catch (Failure e) { for (int i = 0; i < 50; i++) { Thread.Sleep(100); lock (lck) { if (alertText != null) break; } } licenseFailures.Add(new LicenseFailure(host, alertText ?? e.Message)); if (pool != null) pool.Connection.Cache.Hosts.ToList().ForEach(h => SetLicenseServer(h, previousLicenseServerAddress, previousLicenseServerPort)); else SetLicenseServer(host, previousLicenseServerAddress, previousLicenseServerPort); } finally { Alert.XenCenterAlerts.CollectionChanged -= alertsChangeHandler; } } // PR-1102: Send licensing data to the activation server if (updatedHosts.Count > 0) { LicensingHelper.SendLicenseEditionData(updatedHosts, Host.GetEditionText(_edition)); } if (licenseFailures.Count > 0) { string exceptionText = licenseFailures.Count == 1 ? string.Format(Messages.LICENSE_ERROR_1, licenseFailures[0].Host.Name) : string.Format(Messages.LICENSE_ERROR_MANY, licenseFailures.Count, new List<IXenObject>(xos).Count); if (DoOnLicensingFailure != null) DoOnLicensingFailure(licenseFailures, exceptionText); throw new InvalidOperationException(exceptionText); } }
protected override void Run() { SafeToExit = false; if (Connection.IsConnected) { if (!File.Exists(Filepath)) { throw new Exception(Messages.LICENSE_FILE_DOES_NOT_EXIST); } if (new FileInfo(Filepath).Length > 1048576) { throw new Exception(Messages.LICENSE_FILE_TOO_LARGE); } string encodedContent = Convert.ToBase64String(File.ReadAllBytes(Filepath)); // PR-1102: catch the host's license data, before applying the new one, so it can be sent later to the licensing server LicensingHelper.LicenseDataStruct previousLicenseData = new LicensingHelper.LicenseDataStruct(this.Host); this.Description = string.Format(Messages.APPLYLICENSE_APPLYING, Filepath); log.DebugFormat("Applying license to server {0}", this.Host.Name); RelatedTask = XenAPI.Host.async_license_apply(this.Session, this.Host.opaque_ref, encodedContent); PollToCompletion(); this.Description = Messages.APPLYLICENSE_APPLIED; // PR-1102: send licensing data to the activation server Dictionary<Host, LicensingHelper.LicenseDataStruct> hosts = new Dictionary<Host, LicensingHelper.LicenseDataStruct>(); hosts.Add(this.Host, previousLicenseData); if (ActivateFreeLicense) LicensingHelper.SendActivationData(hosts); else LicensingHelper.SendLicenseEditionData(hosts, ""); } }