PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/NewAzureDeployment.cs

https://gitlab.com/jslee1/azure-powershell
C# | 284 lines | 234 code | 33 blank | 17 comment | 27 complexity | 0212531332a4695d7ce303f59d37d598 MD5 | raw file
  1. // ----------------------------------------------------------------------------------
  2. //
  3. // Copyright Microsoft Corporation
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. // ----------------------------------------------------------------------------------
  14. using System;
  15. using System.Management.Automation;
  16. using System.Net;
  17. using Microsoft.Azure.Commands.Common.Authentication.Models;
  18. using Microsoft.WindowsAzure.Commands.Common;
  19. using Microsoft.WindowsAzure.Commands.ServiceManagement.Extensions;
  20. using Microsoft.WindowsAzure.Commands.ServiceManagement.Helpers;
  21. using Microsoft.WindowsAzure.Commands.ServiceManagement.Properties;
  22. using Microsoft.WindowsAzure.Commands.Utilities.Common;
  23. using Microsoft.WindowsAzure.Management.Compute.Models;
  24. using Microsoft.WindowsAzure.Management.Compute;
  25. namespace Microsoft.WindowsAzure.Commands.ServiceManagement.HostedServices
  26. {
  27. using PVM = Model;
  28. using Hyak.Common;
  29. /// <summary>
  30. /// Create a new deployment. Note that there shouldn't be a deployment
  31. /// of the same name or in the same slot when executing this command.
  32. /// </summary>
  33. [Cmdlet(VerbsCommon.New, "AzureDeployment", DefaultParameterSetName = "PaaS"), OutputType(typeof(ManagementOperationContext))]
  34. public class NewAzureDeploymentCommand : ServiceManagementBaseCmdlet
  35. {
  36. [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Cloud service name.")]
  37. [ValidateNotNullOrEmpty]
  38. public string ServiceName
  39. {
  40. get;
  41. set;
  42. }
  43. [Parameter(Position = 1, Mandatory = true, HelpMessage = "Package location. This parameter specifies the path or URI to a .cspkg in blob storage. The storage account must belong to the same subscription as the deployment.")]
  44. [ValidateNotNullOrEmpty]
  45. public string Package
  46. {
  47. get;
  48. set;
  49. }
  50. [Parameter(Position = 2, Mandatory = true, HelpMessage = "Configuration file path. This parameter should specifiy a .cscfg file on disk.")]
  51. [ValidateNotNullOrEmpty]
  52. public string Configuration
  53. {
  54. get;
  55. set;
  56. }
  57. [Parameter(Position = 3, Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Deployment slot [Staging | Production].")]
  58. [ValidateSet(Microsoft.WindowsAzure.Commands.ServiceManagement.Model.DeploymentSlotType.Staging, Microsoft.WindowsAzure.Commands.ServiceManagement.Model.DeploymentSlotType.Production, IgnoreCase = true)]
  59. public string Slot
  60. {
  61. get;
  62. set;
  63. }
  64. [Parameter(Position = 4, Mandatory = false, HelpMessage = "Label for the new deployment.")]
  65. [ValidateNotNullOrEmpty]
  66. public string Label
  67. {
  68. get;
  69. set;
  70. }
  71. [Parameter(Position = 5, HelpMessage = "Deployment name.")]
  72. [Alias("DeploymentName")]
  73. [ValidateNotNullOrEmpty]
  74. public string Name
  75. {
  76. get;
  77. set;
  78. }
  79. [Parameter(Mandatory = false, HelpMessage = "Do not start deployment upon creation.")]
  80. public SwitchParameter DoNotStart
  81. {
  82. get;
  83. set;
  84. }
  85. [Parameter(Mandatory = false, HelpMessage = "Indicates whether to treat package validation warnings as errors.")]
  86. public SwitchParameter TreatWarningsAsError
  87. {
  88. get;
  89. set;
  90. }
  91. [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "Extension configurations.")]
  92. public ExtensionConfigurationInput[] ExtensionConfiguration
  93. {
  94. get;
  95. set;
  96. }
  97. public virtual void NewPaaSDeploymentProcess()
  98. {
  99. bool removePackage = false;
  100. AssertNoPersistenVmRoleExistsInDeployment(PVM.DeploymentSlotType.Production);
  101. AssertNoPersistenVmRoleExistsInDeployment(PVM.DeploymentSlotType.Staging);
  102. var storageName = Profile.Context.Subscription.GetStorageAccountName();
  103. Uri packageUrl;
  104. if (this.Package.StartsWith(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
  105. this.Package.StartsWith(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
  106. {
  107. packageUrl = new Uri(this.Package);
  108. }
  109. else
  110. {
  111. if (string.IsNullOrEmpty(storageName))
  112. {
  113. throw new ArgumentException(Resources.CurrentStorageAccountIsNotSet);
  114. }
  115. var progress = new ProgressRecord(0, Resources.WaitForUploadingPackage, Resources.UploadingPackage);
  116. WriteProgress(progress);
  117. removePackage = true;
  118. packageUrl = this.RetryCall(s =>
  119. AzureBlob.UploadPackageToBlob(
  120. this.StorageClient,
  121. storageName,
  122. this.Package,
  123. null));
  124. }
  125. ExtensionConfiguration extConfig = null;
  126. if (ExtensionConfiguration != null)
  127. {
  128. string errorConfigInput = null;
  129. if (!ExtensionManager.Validate(ExtensionConfiguration, out errorConfigInput))
  130. {
  131. throw new Exception(string.Format(Resources.ServiceExtensionCannotApplyExtensionsInSameType, errorConfigInput));
  132. }
  133. foreach (ExtensionConfigurationInput context in ExtensionConfiguration)
  134. {
  135. if (context != null && context.X509Certificate != null)
  136. {
  137. ExecuteClientActionNewSM(
  138. null,
  139. string.Format(Resources.ServiceExtensionUploadingCertificate, CommandRuntime, context.X509Certificate.Thumbprint),
  140. () => this.ComputeClient.ServiceCertificates.Create(this.ServiceName, CertUtilsNewSM.Create(context.X509Certificate)));
  141. }
  142. }
  143. Func<DeploymentSlot, DeploymentGetResponse> func = t =>
  144. {
  145. DeploymentGetResponse d = null;
  146. try
  147. {
  148. d = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, t);
  149. }
  150. catch (CloudException ex)
  151. {
  152. if (ex.Response.StatusCode != HttpStatusCode.NotFound && IsVerbose() == false)
  153. {
  154. WriteExceptionError(ex);
  155. }
  156. }
  157. return d;
  158. };
  159. var slotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true);
  160. DeploymentGetResponse currentDeployment = null;
  161. InvokeInOperationContext(() => currentDeployment = func(slotType));
  162. var peerSlottype = slotType == DeploymentSlot.Production ? DeploymentSlot.Staging : DeploymentSlot.Production;
  163. DeploymentGetResponse peerDeployment = null;
  164. InvokeInOperationContext(() => peerDeployment = func(peerSlottype));
  165. ExtensionManager extensionMgr = new ExtensionManager(this, ServiceName);
  166. extConfig = extensionMgr.Set(currentDeployment, peerDeployment, ExtensionConfiguration, this.Slot);
  167. }
  168. var deploymentInput = new DeploymentCreateParameters
  169. {
  170. PackageUri = packageUrl,
  171. Configuration = GeneralUtilities.GetConfiguration(this.Configuration),
  172. ExtensionConfiguration = extConfig,
  173. Label = this.Label,
  174. Name = this.Name,
  175. StartDeployment = !this.DoNotStart.IsPresent,
  176. TreatWarningsAsError = this.TreatWarningsAsError.IsPresent,
  177. };
  178. InvokeInOperationContext(() =>
  179. {
  180. try
  181. {
  182. var progress = new ProgressRecord(0, Resources.WaitForUploadingPackage, Resources.CreatingNewDeployment);
  183. WriteProgress(progress);
  184. ExecuteClientActionNewSM(
  185. deploymentInput,
  186. CommandRuntime.ToString(),
  187. () => this.ComputeClient.Deployments.Create(
  188. this.ServiceName,
  189. (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true),
  190. deploymentInput));
  191. if (removePackage == true)
  192. {
  193. this.RetryCall(s => AzureBlob.DeletePackageFromBlob(
  194. this.StorageClient,
  195. storageName,
  196. packageUrl));
  197. }
  198. }
  199. catch (CloudException ex)
  200. {
  201. WriteExceptionError(ex);
  202. }
  203. });
  204. }
  205. private void AssertNoPersistenVmRoleExistsInDeployment(string slot)
  206. {
  207. InvokeInOperationContext(() =>
  208. {
  209. try
  210. {
  211. var currentDeployment = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), slot, true));
  212. if (currentDeployment.Roles != null)
  213. {
  214. if (string.Compare(currentDeployment.Roles[0].RoleType, "PersistentVMRole", StringComparison.OrdinalIgnoreCase) == 0)
  215. {
  216. throw new ArgumentException(String.Format(Resources.CanNotCreateNewDeploymentWhileVMsArePresent, slot));
  217. }
  218. }
  219. }
  220. catch (CloudException ex)
  221. {
  222. if (ex.Response.StatusCode != HttpStatusCode.NotFound && IsVerbose() == false)
  223. {
  224. WriteExceptionError(ex);
  225. }
  226. }
  227. });
  228. }
  229. protected override void OnProcessRecord()
  230. {
  231. ServiceManagementProfile.Initialize();
  232. this.ValidateParameters();
  233. this.NewPaaSDeploymentProcess();
  234. }
  235. protected virtual void ValidateParameters()
  236. {
  237. if (string.IsNullOrEmpty(this.Slot))
  238. {
  239. this.Slot = PVM.DeploymentSlotType.Production;
  240. }
  241. if (string.IsNullOrEmpty(this.Name))
  242. {
  243. this.Name = Guid.NewGuid().ToString();
  244. }
  245. if (string.IsNullOrEmpty(this.Label))
  246. {
  247. this.Label = this.Name;
  248. }
  249. }
  250. }
  251. }