// ARM private async Task <ResourceGroup> ActivateResourceGroup(TryWebsitesIdentity userIdentity, AppService appService, DeploymentType deploymentType, Func <ResourceGroup, InProgressOperation, Task <ResourceGroup> > func) { ResourceGroup resourceGroup = null; if (userIdentity == null) { throw new InvalidUserIdentityException(); } var userId = userIdentity.Name; try { if (_backgroundQueueManager.ResourceGroupsInUse.TryGetValue(userId, out resourceGroup)) { throw new MoreThanOneResourceGroupException(); } if (_backgroundQueueManager.FreeResourceGroups.TryDequeue(out resourceGroup)) { //mark site in use as soon as it's checked out so that if there is a reload it will be sorted out to the used queue. await resourceGroup.MarkInUse(userId, appService); var rbacTask = Task.FromResult(false); //RbacHelper.AddRbacUser(userIdentity.Puid, userIdentity.Email, resourceGroup); var process = new InProgressOperation(resourceGroup, deploymentType); _backgroundQueueManager.ResourceGroupsInProgress.AddOrUpdate(userId, s => process, (s, task) => process); SimpleTrace.Diagnostics.Information("resourceGroup {resourceGroupId} is now in use", resourceGroup.CsmId); resourceGroup = await func(resourceGroup, process); var addedResourceGroup = _backgroundQueueManager.ResourceGroupsInUse.GetOrAdd(userId, resourceGroup); if (addedResourceGroup.ResourceGroupName == resourceGroup.ResourceGroupName) { //this means we just added the resourceGroup for the user. await addedResourceGroup.MarkInUse(userId, appService); return(addedResourceGroup); } else { //this means the user is trying to add more than 1 site. //delete the new site that's not yet added to the used list await resourceGroup.DeleteAndCreateReplacement(); throw new MoreThanOneResourceGroupException(); } } else { throw new NoFreeResourceGroupsException(); } // End site specific stuff } catch (MoreThanOneResourceGroupException) { throw; } catch (NoFreeResourceGroupsException) { throw; } catch (InvalidGithubRepoException) { throw; } catch (Exception e) { //unknown exception, log it SimpleTrace.Diagnostics.Fatal(e, "Unknown error during UserCreate, Count {Count}", Interlocked.Increment(ref _unknownErrorInCreateErrorCount)); } finally { InProgressOperation temp; if (_backgroundQueueManager.ResourceGroupsInProgress.TryRemove(userId, out temp)) { temp.Complete(); LogQueueStatistics(); } } //if we are here that means a bad exception happened above, but we might leak a site if we don't remove the site and replace it correctly. if (resourceGroup != null) { DeleteResourceGroup(resourceGroup); } throw new Exception(Resources.Server.Error_GeneralErrorMessage); }
// ARM private async Task <ResourceGroup> ActivateResourceGroup(TryWebsitesIdentity userIdentity, AppService appService, DeploymentType deploymentType, Func <ResourceGroup, InProgressOperation, Task <ResourceGroup> > func, string template = "") { ResourceGroup resourceGroup = null; if (userIdentity == null) { throw new InvalidUserIdentityException(); } var userId = userIdentity.Name; try { if (_backgroundQueueManager.ResourceGroupsInUse.TryGetValue(userId, out resourceGroup)) { throw new MoreThanOneResourceGroupException(); } bool resourceGroupFound = false; if (appService == AppService.Containers || appService == AppService.Linux) { resourceGroupFound = _backgroundQueueManager.FreeLinuxResourceGroups.TryDequeue(out resourceGroup); } else if ((appService == AppService.VSCodeLinux)) { if (_backgroundQueueManager.FreeVSCodeLinuxResourceGroups[template] != null) { resourceGroupFound = _backgroundQueueManager.FreeVSCodeLinuxResourceGroups[template].TryDequeue(out resourceGroup); } else { resourceGroupFound = false; } } else if ((appService != AppService.MonitoringTools)) { resourceGroupFound = _backgroundQueueManager.FreeResourceGroups.TryDequeue(out resourceGroup); } else if ((appService == AppService.MonitoringTools)) { resourceGroup = _backgroundQueueManager.MonitoringResourceGroup; BackgroundQueueManager.MonitoringResourceGroupCheckoutTimes.AddOrUpdate(userId, DateTime.UtcNow, (key, oldValue) => DateTime.UtcNow); SimpleTrace.Diagnostics.Information("resourceGroup {resourceGroupId} is now assigned", resourceGroup.CsmId); return(await func(resourceGroup, null)); } if (resourceGroupFound) { //mark site in use as soon as it's checked out so that if there is a reload it will be sorted out to the used queue. await resourceGroup.MarkInUse(userId, appService); //var rbacTask = Task.FromResult(false); //RbacHelper.AddRbacUser(userIdentity.Puid, userIdentity.Email, resourceGroup); var process = new InProgressOperation(resourceGroup, deploymentType); _backgroundQueueManager.ResourceGroupsInProgress.AddOrUpdate(userId, s => process, (s, task) => process); SimpleTrace.Diagnostics.Information("site {siteId} is now in use", String.Concat(resourceGroup.CsmId, "/", resourceGroup.Sites.FirstOrDefault(s => s.IsSimpleWAWSOriginalSite).SiteName)); resourceGroup = await func(resourceGroup, process); var addedResourceGroup = _backgroundQueueManager.ResourceGroupsInUse.GetOrAdd(userId, resourceGroup); if (addedResourceGroup.ResourceGroupName == resourceGroup.ResourceGroupName) { //this means we just added the resourceGroup for the user. //Removing this line since we have already marked the resourcegroup as in use by the user //await addedResourceGroup.MarkInUse(userId, appService); return(addedResourceGroup); } else { //this means the user is trying to add more than 1 site. //delete the new site that's not yet added to the used list SimpleTrace.Diagnostics.Information("User asked for more than 1 site. Replacing {resourceGroup.CsmId}", resourceGroup.CsmId); await resourceGroup.DeleteAndCreateReplacement(); throw new MoreThanOneResourceGroupException(); } } else { throw new NoFreeResourceGroupsException(); } // End site specific stuff } catch (MoreThanOneResourceGroupException) { throw; } catch (NoFreeResourceGroupsException) { throw; } catch (InvalidGithubRepoException) { throw; } catch (Exception e) { //unknown exception, log it SimpleTrace.Diagnostics.Fatal(e, "Unknown error during UserCreate, Count {Count}", Interlocked.Increment(ref _unknownErrorInCreateErrorCount)); } finally { InProgressOperation temp; if (_backgroundQueueManager.ResourceGroupsInProgress.TryRemove(userId, out temp)) { temp.Complete(); LogQueueStatistics(); } } //if we are here that means a bad exception happened above, but we might leak a site if we don't remove the site and replace it correctly. if (resourceGroup != null) { DeleteResourceGroup(resourceGroup); } throw new Exception(Resources.Server.Error_GeneralErrorMessage); }
// ARM private async Task<ResourceGroup> ActivateResourceGroup(TryWebsitesIdentity userIdentity, AppService appService, DeploymentType deploymentType, Func<ResourceGroup, InProgressOperation, Task<ResourceGroup>> func) { ResourceGroup resourceGroup = null; if (userIdentity == null) { throw new InvalidUserIdentityException(); } var userId = userIdentity.Name; try { if (_backgroundQueueManager.ResourceGroupsInUse.TryGetValue(userId, out resourceGroup)) { throw new MoreThanOneResourceGroupException(); } if (_backgroundQueueManager.FreeResourceGroups.TryDequeue(out resourceGroup)) { //mark site in use as soon as it's checked out so that if there is a reload it will be sorted out to the used queue. await resourceGroup.MarkInUse(userId, ResourceGroupExpiryTime, appService); var rbacTask = Task.FromResult(false); //RbacHelper.AddRbacUser(userIdentity.Puid, userIdentity.Email, resourceGroup); var process = new InProgressOperation(resourceGroup, deploymentType); _backgroundQueueManager.ResourceGroupsInProgress.AddOrUpdate(userId, s => process, (s, task) => process); SimpleTrace.Diagnostics.Information("resourceGroup {resourceGroupId} is now in use", resourceGroup.CsmId); resourceGroup = await func(resourceGroup, process); var addedResourceGroup = _backgroundQueueManager.ResourceGroupsInUse.GetOrAdd(userId, resourceGroup); if (addedResourceGroup.ResourceGroupName == resourceGroup.ResourceGroupName) { //this means we just added the resourceGroup for the user. await addedResourceGroup.MarkInUse(userId, ResourceGroupExpiryTime, appService); return addedResourceGroup; } else { //this means the user is trying to add more than 1 site. //delete the new site that's not yet added to the used list await resourceGroup.DeleteAndCreateReplacement(); throw new MoreThanOneResourceGroupException(); } } else { throw new NoFreeResourceGroupsException(); } // End site specific stuff } catch (MoreThanOneResourceGroupException) { throw; } catch (NoFreeResourceGroupsException) { throw; } catch (InvalidGithubRepoException) { throw; } catch (Exception e) { //unknown exception, log it SimpleTrace.Diagnostics.Fatal(e, "Unknown error during UserCreate, Count {Count}", Interlocked.Increment(ref _unknownErrorInCreateErrorCount)); } finally { InProgressOperation temp; _backgroundQueueManager.ResourceGroupsInProgress.TryRemove(userId, out temp); temp.Complete(); LogQueueStatistics(); } //if we are here that means a bad exception happened above, but we might leak a site if we don't remove the site and replace it correctly. if (resourceGroup != null) { //no need to await this call //this call is to fix our internal state, return an error right away to the caller ThreadPool.QueueUserWorkItem(async o => await DeleteResourceGroup(resourceGroup).IgnoreFailure()); } throw new Exception(Resources.Server.Error_GeneralErrorMessage); }
// ARM private async Task <ResourceGroup> ActivateResourceGroup(TryWebsitesIdentity userIdentity, AppService appService, DeploymentType deploymentType, Func <ResourceGroup, InProgressOperation, Task <ResourceGroup> > func, BaseTemplate template = null) { ResourceGroup resourceGroup = null; if (userIdentity == null) { throw new InvalidUserIdentityException(); } var userId = userIdentity.Name; try { if (await StorageHelper.GetAssignedResourceGroup(userId) != null) { throw new MoreThanOneResourceGroupException(); } bool resourceGroupFound = false; SimpleTrace.TraceInformation($"Searching vscodequeue for template '{template.QueueName}': Count of templates:{await StorageHelper.GetQueueCount(template.QueueName)} "); if (await StorageHelper.GetQueueCount(template.QueueName) > 0) { var totalTries = 3; var tries = 0; //bool siteFound = false; while (tries++ < totalTries && !resourceGroupFound) { resourceGroup = await StorageHelper.GetQueueMessage(template.QueueName); resourceGroupFound = (resourceGroup != null); if (resourceGroupFound) { // try // { // var a = Dns.GetHostEntry(resourceGroup.Sites.FirstOrDefault().HostName); // if (a != null) // { // siteFound = true; // } // } // catch // { // resourceGroupFound = false; // SimpleTrace.TraceInformation($"Found ResourceGroup but HostName isnt active '{resourceGroup.ResourceGroupName}' with template {resourceGroup.DeployedTemplateName}"); // } SimpleTrace.TraceInformation($"Found ResourceGroup '{resourceGroup.ResourceGroupName}' with template {resourceGroup.DeployedTemplateName}"); } else { SimpleTrace.TraceInformation($"No resource found in free queue for '{template.Name}' "); } } } if (resourceGroupFound) { //mark site in use as soon as it's checked out so that if there is a reload it will be sorted out to the used queue. await resourceGroup.MarkInUse(userId, appService); //var rbacTask = Task.FromResult(false); //RbacHelper.AddRbacUser(userIdentity.Puid, userIdentity.Email, resourceGroup); var process = new InProgressOperation(resourceGroup, deploymentType); _backgroundQueueManager.ResourceGroupsInProgress.AddOrUpdate(userId, s => process, (s, task) => process); SimpleTrace.Diagnostics.Information("site {siteId} is now in use", String.Concat(resourceGroup.CsmId, "/", resourceGroup.Site.SiteName)); resourceGroup = await func(resourceGroup, process); var addedResourceGroup = await StorageHelper.AssignResourceGroup(userId, resourceGroup); if (addedResourceGroup) { //this means we just added the resourceGroup for the user. //Removing this line since we have already marked the resourcegroup as in use by the user //await addedResourceGroup.MarkInUse(userId, appService); return(resourceGroup); } else { //this means the user is trying to add more than 1 site. //delete the new site that's not yet added to the used list SimpleTrace.Diagnostics.Information("User asked for more than 1 site. Replacing {resourceGroup.CsmId}", resourceGroup.CsmId); await resourceGroup.DeleteAndCreateReplacement(); throw new MoreThanOneResourceGroupException(); } } else { SimpleTrace.Diagnostics.Information("No resource group found yet. Shouldnt be here"); throw new NoFreeResourceGroupsException(); } // End site specific stuff } catch (MoreThanOneResourceGroupException) { throw; } catch (NoFreeResourceGroupsException) { throw; } catch (InvalidGithubRepoException) { throw; } catch (Exception e) { //unknown exception, log it SimpleTrace.Diagnostics.Fatal(e, "Unknown error during UserCreate, Count {Count}", Interlocked.Increment(ref _unknownErrorInCreateErrorCount)); } finally { InProgressOperation temp; if (_backgroundQueueManager.ResourceGroupsInProgress.TryRemove(userId, out temp)) { temp.Complete(); LogQueueStatistics(); } } //if we are here that means a bad exception happened above, but we might leak a site if we don't remove the site and replace it correctly. if (resourceGroup != null) { DeleteResourceGroup(resourceGroup); } throw new Exception(Resources.Server.Error_GeneralErrorMessage); }