Example #1
0
 private void DeleteAndCreateResourceGroupOperation(ResourceGroup resourceGroup)
 {
     AddOperation(new BackgroundOperation <ResourceGroup>
     {
         Description = $"Deleting and creating resourceGroup {resourceGroup.ResourceGroupName}",
         Type        = OperationType.ResourceGroupDeleteThenCreate,
         Task        = resourceGroup.DeleteAndCreateReplacement(),
         RetryAction = () => DeleteAndCreateResourceGroupOperation(resourceGroup)
     });
 }
        // 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);
        }
Example #3
0
        // 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, 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);
        }