Example #1
0
        public async Task<IHttpActionResult> Update(UpdateVersion version)
        {
            return await DoActionAsync("UpdateController.Update", async (serviceClient) =>
            {
                var updateClient = new UpdateClient(null, DashConfiguration.PackageUpdateServiceLocation);
                var updateManifest = await updateClient.GetUpdateVersionAsync(UpdateClient.Components.DashServer, version.Version);
                if (updateManifest == null)
                {
                    return NotFound();
                }
                var package = updateManifest.GetPackage(UpdateClient.GetPackageFlavorLabel(AzureService.GetServiceFlavor()));
                if (package == null)
                {
                    return NotFound();
                }
                var servicePackage = package.FindFileByExtension(".cspkg");
                var serviceConfig = package.FindFileByExtension(".cscfg");
                if (servicePackage == null || serviceConfig == null)
                {
                    return NotFound();
                }
                var operationId = DashTrace.CorrelationId.ToString();
                try
                {
                    var operationStatus = await UpdateConfigStatus.GetConfigUpdateStatus(operationId);
                    await operationStatus.UpdateStatus(UpdateConfigStatus.States.PreServiceUpdate, "Begin software upgrade to version [{0}]. Operation Id: [{1}]", version.Version, operationId);
                    // Do a couple of things up-front to ensure that we can upgrade & then kick the upgrade off & don't wait for it to complete.
                    // Make sure reverse-DNS is configured
                    var updateResponse = await serviceClient.UpdateService(new HostedServiceUpdateParameters
                    {
                        ReverseDnsFqdn = String.Format("{0}.cloudapp.net.", serviceClient.ServiceName),
                    });
                    // Copy current config to config for new version
                    var currentConfig = await serviceClient.GetDeploymentConfiguration();
                    var currentSettings = AzureServiceConfiguration.GetSettingsProjected(currentConfig);
                    var newConfigDoc = XDocument.Load(
                        await updateClient.DownloadPackageFileAsync(UpdateClient.Components.DashServer, updateManifest, package, serviceConfig.Name));
                    var newSettings = AzureServiceConfiguration.GetSettings(newConfigDoc);
                    // Keep the same number of instances
                    var ns = AzureServiceConfiguration.Namespace;
                    AzureServiceConfiguration.GetInstances(newConfigDoc).Value = AzureServiceConfiguration.GetInstances(currentConfig).Value;
                    foreach (var currentSetting in currentSettings)
                    {
                        var newSetting = AzureServiceConfiguration.GetSetting(newSettings, currentSetting.Item1);
                        if (newSetting != null)
                        {
                            newSetting.SetAttributeValue("value", currentSetting.Item2);
                        }
                    }
                    // Certificates (if there are any)
                    var currentCerts = AzureServiceConfiguration.GetCertificates(currentConfig);
                    if (currentCerts != null)
                    {
                        var newCerts = AzureServiceConfiguration.GetCertificates(newConfigDoc);
                        newCerts.RemoveNodes();
                        foreach (var currentCert in currentCerts.Elements())
                        {
                            var newCert = new XElement(ns + "Certificate");
                            foreach (var currentAttrib in currentCert.Attributes())
                            {
                                newCert.SetAttributeValue(currentAttrib.Name, currentAttrib.Value);
                            }
                            newCerts.Add(newCert);
                        }
                    }
                    // Send the update to the service
                    Uri packageUri;
                    if (!String.IsNullOrWhiteSpace(servicePackage.SasUri))
                    {
                        packageUri = new Uri(servicePackage.SasUri);
                    }
                    else
                    {
                        packageUri = await updateClient.GetPackageFileSasUriAsync(UpdateClient.Components.DashServer, updateManifest, package, servicePackage.Name);
                    }
                    await operationStatus.UpdateStatus(UpdateConfigStatus.States.PreServiceUpdate, "Service upgrade using package [{0}].", packageUri.ToString());
                    var upgradeResponse = await serviceClient.UpgradeDeployment(new DeploymentUpgradeParameters
                    {
                        Label = String.Format("Dash.ManagementAPI-{0:o}", DateTime.UtcNow),
                        PackageUri = packageUri,
                        Configuration = newConfigDoc.ToString(),
                        Mode = DeploymentUpgradeMode.Auto,
                    });
                    operationStatus.CloudServiceUpdateOperationId = upgradeResponse.RequestId;
                    await operationStatus.UpdateStatus(UpdateConfigStatus.States.UpdatingService, "Service upgrade in progress.");
                    await EnqueueServiceOperationUpdate(serviceClient, operationId);
                    // Manually fire up the async worker 
                    var queueTask = ProcessOperationMessageLoop(operationId, null, null, GetMessageDelay(), null);

                    return Content(upgradeResponse.StatusCode, new OperationResult 
                    { 
                        OperationId = operationId, 
                    });
                }
                catch (CloudException ex)
                {
                    return Content(ex.Response.StatusCode, new OperationResult
                    {
                        OperationId = operationId,
                        ErrorCode = ex.ErrorCode,
                        ErrorMessage = ex.ErrorMessage,
                    });
                }
                catch (Exception ex)
                {
                    return InternalServerError(ex);
                }
            });
        }