Beispiel #1
0
 public static void CreateChildAndAdd(ProvisioningQueueParentDto parent, CloudResourceOperationDto operation)
 {
     parent.Children.Add(new ProvisioningQueueChildDto()
     {
         ResourceOperationId = operation.Id
     });
 }
Beispiel #2
0
        public static ProvisioningQueueParentDto CreateParent(string description)
        {
            var queueParentItem = new ProvisioningQueueParentDto
            {
                Description = description
            };

            return(queueParentItem);
        }
        public async Task IncreaseInvisibilityAsync(ProvisioningQueueParentDto message, int invisibleForInSeconds)
        {
            _logger.LogInformation($"Queue: Increasing message invisibility for {message.MessageId} with description \"{message.Description}\" by {invisibleForInSeconds} seconds.");
            var messageAsJson = JsonSerializerUtil.Serialize(message);
            var updateReceipt = await _queueService.UpdateMessageAsync(message.MessageId, message.PopReceipt, messageAsJson, invisibleForInSeconds);
            message.PopReceipt = updateReceipt.PopReceipt;
            message.NextVisibleOn = updateReceipt.NextVisibleOn;
            _logger.LogInformation($"Queue: Message {message.MessageId} will be visible again at {updateReceipt.NextVisibleOn} (UTC)");

        }
        public async Task CreateItemAndEnqueue(int operationId, string operationDescription)
        {
            var queueParentItem = new ProvisioningQueueParentDto
            {
                Description = operationDescription
            };

            queueParentItem.Children.Add(new ProvisioningQueueChildDto() { ResourceOperationId = operationId });

            await SendMessageAsync(queueParentItem);
        }
        public async Task AddNewQueueMessageForOperation(CloudResourceOperation operation)
        {
            var queueParentItem = new ProvisioningQueueParentDto
            {
                Description = operation.Description
            };

            queueParentItem.Children.Add(new ProvisioningQueueChildDto() { ResourceOperationId = operation.Id });

            await SendMessageAsync(queueParentItem, visibilityTimeout: TimeSpan.FromSeconds(5));
        }
        public async Task ReQueueMessageAsync(ProvisioningQueueParentDto message, int? invisibleForInSeconds = default, CancellationToken cancellationToken = default)
        {
            _logger.LogInformation($"Queue: Re-queuing message: {message.Description}, having {message.Children.Count} children.");

            await DeleteMessageAsync(message);
            message.DequeueCount = 0;
            message.PopReceipt = null;
            message.MessageId = null;

            TimeSpan invisibleForTimespan = invisibleForInSeconds.HasValue ? new TimeSpan(0, 0, invisibleForInSeconds.Value) : new TimeSpan(0, 0, 10);
            await SendMessageAsync(message, visibilityTimeout: invisibleForTimespan, cancellationToken: cancellationToken);
        }
        public async Task<ProvisioningQueueParentDto> SendMessageAsync(ProvisioningQueueParentDto message, TimeSpan? visibilityTimeout = null, CancellationToken cancellationToken = default)
        {
            _logger.LogInformation($"Queue: Adding message: {message.Description}, having {message.Children.Count} children");
            var serializedMessage = JsonSerializerUtil.Serialize(message);
            var sendtMessage = await _queueService.SendMessageAsync(serializedMessage, visibilityTimeout, cancellationToken);

            message.MessageId = sendtMessage.MessageId;
            message.PopReceipt = sendtMessage.PopReceipt;
            message.NextVisibleOn = sendtMessage.NextVisibleOn;

            return message;

        }
        public async Task MoveUpAnyDependentOperations(ProvisioningQueueParentDto queueParentItem)
        {
            _provisioningLogService.QueueParentProgressInformation(queueParentItem, "Moving up relevant dependent operations");

            try
            {
                int movedUpCount = 0;

                CloudResourceOperation currentOperation = null;

                foreach (var queueChildItem in queueParentItem.Children)
                {
                    currentOperation = await _resourceOperationModelService.GetForOperationPromotion(queueChildItem.ResourceOperationId);

                    if (currentOperation.DependantOnThisOperation != null && currentOperation.DependantOnThisOperation.Count > 0)
                    {
                        foreach (var curDependantOnThisOp in currentOperation.DependantOnThisOperation)
                        {
                            if (!curDependantOnThisOp.Resource.Deleted)
                            {
                                if (curDependantOnThisOp.Status == CloudResourceOperationState.NEW && String.IsNullOrWhiteSpace(curDependantOnThisOp.BatchId))
                                {
                                    if (!String.IsNullOrWhiteSpace(curDependantOnThisOp.QueueMessageId) && String.IsNullOrWhiteSpace(curDependantOnThisOp.QueueMessagePopReceipt))
                                    {
                                        if (curDependantOnThisOp.QueueMessageVisibleAgainAt.HasValue && curDependantOnThisOp.QueueMessageVisibleAgainAt.Value > DateTime.UtcNow.AddSeconds(15))
                                        {
                                            //Create a new queue item for immediate pickup
                                            await _provisioningQueueService.AddNewQueueMessageForOperation(curDependantOnThisOp);

                                            //Delete existing message
                                            await _provisioningQueueService.DeleteMessageAsync(curDependantOnThisOp.QueueMessageId, curDependantOnThisOp.QueueMessagePopReceipt);

                                            //Clear stored message details on operation record
                                            await _resourceOperationUpdateService.ClearQueueInformationAsync(curDependantOnThisOp.Id);

                                            movedUpCount++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                _provisioningLogService.QueueParentProgressInformation(queueParentItem, $"Done moving up relevant dependent operations. Moved up {movedUpCount} operations");
            }
            catch (Exception ex)
            {
                _provisioningLogService.QueueParentProgressError(queueParentItem, $"Failed when moving up relevant dependent operations. ", ex);
            }
        }
Beispiel #9
0
        public async Task CreateBasicSandboxResourcesAsync(Sandbox sandbox)
        {
            _logger.LogInformation($"Creating basic sandbox resources for sandbox: {sandbox.Name}. First creating Resource Group, other resources are created by worker");

            try
            {
                var tags = ResourceTagFactory.SandboxResourceTags(_configuration, sandbox.Study, sandbox);

                var creationAndSchedulingDto =
                    new SandboxResourceCreationAndSchedulingDto()
                {
                    StudyId     = sandbox.Study.Id,
                    SandboxId   = sandbox.Id,
                    StudyName   = sandbox.Study.Name,
                    SandboxName = sandbox.Name,
                    Region      = sandbox.Region,
                    Tags        = tags,
                    BatchId     = Guid.NewGuid().ToString()
                };

                var queueParentItem = new ProvisioningQueueParentDto
                {
                    Description = $"Create basic resources for Sandbox: {creationAndSchedulingDto.SandboxId}"
                };

                await ScheduleCreationOfSandboxResourceGroup(creationAndSchedulingDto, queueParentItem);
                await ScheduleCreationOfSandboxResourceGroupRoleAssignments(creationAndSchedulingDto, queueParentItem);
                await ScheduleCreationOfDiagStorageAccount(creationAndSchedulingDto, queueParentItem);
                await ScheduleCreationOfNetworkSecurityGroup(creationAndSchedulingDto, queueParentItem);
                await ScheduleCreationOfVirtualNetwork(creationAndSchedulingDto, queueParentItem);
                await ScheduleCreationOfBastion(creationAndSchedulingDto, queueParentItem);

                await _provisioningQueueService.SendMessageAsync(queueParentItem);

                _logger.LogInformation($"Done ordering creation of basic resources for sandbox: {creationAndSchedulingDto.SandboxName}");
            }
            catch (Exception ex)
            {
                throw new Exception($"Unable to create basic sandbox resources.", ex);
            }
        }
Beispiel #10
0
        async Task ScheduleCreationOfSandboxResourceGroupRoleAssignments(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem)
        {
            var desiredState = CloudResourceConfigStringSerializer.Serialize(new CloudResourceOperationStateForRoleUpdate(dto.StudyId));
            var resourceGroupCreateOperation = dto.ResourceGroup.Operations.FirstOrDefault().Id;
            var updateOpId = await _cloudResourceOperationCreateService.CreateUpdateOperationAsync(dto.ResourceGroup.Id, CloudResourceOperationType.ENSURE_ROLES, dependsOn : resourceGroupCreateOperation, desiredState : desiredState);

            queueParentItem.Children.Add(new ProvisioningQueueChildDto()
            {
                ResourceOperationId = updateOpId.Id
            });
        }
Beispiel #11
0
 async Task ScheduleCreationOfSandboxResourceGroup(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem)
 {
     dto.ResourceGroupName = AzureResourceNameUtil.SandboxResourceGroup(dto.StudyName, dto.SandboxName);
     dto.ResourceGroup     = await CreateResourceGroupEntryAndAddToQueue(dto, queueParentItem, dto.ResourceGroupName);
 }
Beispiel #12
0
        async Task <CloudResource> CreateResourceEntryAndAddToQueue(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem, string resourceType, string resourceName = AzureResourceNameUtil.AZURE_RESOURCE_INITIAL_ID_OR_NAME, string configString = null, int dependsOn = 0)
        {
            var resourceEntry = await _cloudResourceCreateService.CreateSandboxResourceEntryAsync(dto, resourceType, resourceName : resourceName, configString : configString, dependsOn : dependsOn);

            queueParentItem.Children.Add(new ProvisioningQueueChildDto()
            {
                ResourceOperationId = resourceEntry.Operations.FirstOrDefault().Id
            });
            return(resourceEntry);
        }
Beispiel #13
0
        async Task <CloudResource> CreateResourceGroupEntryAndAddToQueue(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem, string resourceGroupName)
        {
            var resourceEntry = await _cloudResourceCreateService.CreateSandboxResourceGroupEntryAsync(dto, resourceGroupName);

            queueParentItem.Children.Add(new ProvisioningQueueChildDto()
            {
                ResourceOperationId = resourceEntry.Operations.FirstOrDefault().Id
            });
            return(resourceEntry);
        }
 string QueueParentProgressLogMessage(ProvisioningQueueParentDto queueParentItem, string suffix)
 {
     return($"MessageId: {queueParentItem.MessageId} - {queueParentItem.Description} | {suffix}");
 }
 public void QueueParentProgressInformation(ProvisioningQueueParentDto queueParentItem, string suffix)
 {
     _logger.LogInformation(QueueParentProgressLogMessage(queueParentItem, suffix));
 }
 public void QueueParentProgressError(ProvisioningQueueParentDto queueParentItem, string suffix, Exception exeption = null)
 {
     _logger.LogError(exeption, QueueParentProgressLogMessage(queueParentItem, suffix));
 }
 // Message needs to be retrieved with ReceiveMessageAsync() to be able to be deleted.
 public async Task DeleteMessageAsync(ProvisioningQueueParentDto message)
 {
     _logger.LogInformation($"Queue: Deleting message: {message.MessageId} with description \"{message.Description}\", having {message.Children.Count} children");
     await _queueService.DeleteMessageAsync(message.MessageId, message.PopReceipt);
 }
 public void QueueParentProgressCritical(ProvisioningQueueParentDto queueParentItem, string suffix)
 {
     _logger.LogCritical(QueueParentProgressLogMessage(queueParentItem, suffix));
 }
Beispiel #19
0
        public static void CreateChildAndAdd(ProvisioningQueueParentDto parent, CloudResource resource)
        {
            var createOperation = CloudResourceOperationUtil.GetCreateOperation(resource);

            CreateChildAndAdd(parent, createOperation);
        }
        public async Task HandleWork(ProvisioningQueueParentDto queueParentItem)
        {
            _provisioningLogService.HandlingQueueParent(queueParentItem);

            //One per child item in queue item
            CloudResourceOperationDto currentOperation = null;

            //Get's re-used amonong child elements because the operations might share variables
            var currentProvisioningParameters = new ResourceProvisioningParameters();

            ResourceProvisioningResult currentProvisioningResult = null;

            try
            {
                //If more than one child/operation, run basic checks on all operations before starting
                if (queueParentItem.Children.Count > 1)
                {
                    _provisioningLogService.QueueParentProgressInformation(queueParentItem,
                                                                           "Multiple child item, running pre checks");

                    foreach (var queueChildItem in queueParentItem.Children)
                    {
                        currentOperation = await _resourceOperationReadService.GetByIdAsync(queueChildItem.ResourceOperationId);

                        _operationCheckService.ThrowIfPossiblyInProgress(currentOperation);
                    }
                }

                foreach (var queueChildItem in queueParentItem.Children)
                {
                    try
                    {
                        currentOperation = await _resourceOperationReadService.GetByIdAsync(queueChildItem.ResourceOperationId);

                        _provisioningLogService.OperationInformation(currentOperation, "Starting operation");

                        _operationCheckService.ThrowIfTryCountExceededOrAborted(currentOperation);

                        _operationCheckService.ThrowIfResourceIsDeletedAndOperationIsNotADelete(currentOperation);

                        _operationCheckService.ThrowIfPossiblyInProgress(currentOperation);

                        await _operationCheckService.ThrowIfDependentOnUnfinishedOperationAsync(currentOperation, queueParentItem);

                        string networkSecurityGroupName = null;

                        //Only relevant for Sandbox Resource Creation
                        if (currentOperation.Resource.SandboxId.HasValue)
                        {
                            var nsg = CloudResourceUtil.GetSibilingResource(await _resourceReadService.GetByIdNoAccessCheckAsync(currentOperation.Resource.Id), AzureResourceType.NetworkSecurityGroup);
                            networkSecurityGroupName = nsg?.ResourceName;
                        }

                        ProvisioningParamaterUtil.PrepareForNewOperation(currentProvisioningParameters, currentOperation, currentProvisioningResult, networkSecurityGroupName);

                        await _provisioningQueueService.IncreaseInvisibleBasedOnResource(currentOperation, queueParentItem);

                        _provisioningLogService.OperationInformation(currentOperation, "Initial checks passed");

                        if (_createAndUpdateService.CanHandle(currentOperation))
                        {
                            _provisioningLogService.OperationInformation(currentOperation, "Operation is CREATE or UPDATE");

                            var provisioningService = AzureResourceServiceResolver.GetProvisioningServiceOrThrow(_serviceProvider, currentOperation.Resource.ResourceType);

                            if (await _operationCompletedService.HandledAsAllreadyCompletedAsync(currentOperation))
                            {
                                _provisioningLogService.OperationInformation(currentOperation, "Operation is allready completed");
                                currentProvisioningResult = await provisioningService.GetSharedVariables(currentProvisioningParameters);

                                continue;
                            }
                            else
                            {
                                currentOperation = await _resourceOperationUpdateService.SetInProgressAsync(currentOperation.Id, _requestIdService.GetRequestId());

                                currentProvisioningResult = await _createAndUpdateService.Handle(currentOperation, currentProvisioningParameters, provisioningService);
                            }

                            currentOperation = await _resourceOperationUpdateService.TouchAsync(currentOperation.Id);

                            await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id,
                                                                                    CloudResourceOperationState.DONE_SUCCESSFUL,
                                                                                    updatedProvisioningState : currentProvisioningResult.CurrentProvisioningState);
                        }
                        else if (_deleteOperationService.CanHandle(currentOperation))
                        {
                            _provisioningLogService.OperationInformation(currentOperation, "Operation is DELETE");
                            var provisioningService = AzureResourceServiceResolver.GetProvisioningServiceOrThrow(_serviceProvider, currentOperation.Resource.ResourceType);
                            currentOperation = await _resourceOperationUpdateService.SetInProgressAsync(currentOperation.Id, _requestIdService.GetRequestId());

                            currentProvisioningResult = await _deleteOperationService.Handle(currentOperation, currentProvisioningParameters, provisioningService);

                            await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id, CloudResourceOperationState.DONE_SUCCESSFUL, updatedProvisioningState : null);
                        }
                        else if (_roleProvisioningService.CanHandle(currentOperation))
                        {
                            _provisioningLogService.OperationInformation(currentOperation, "Operation is ENSURE ROLES");
                            currentOperation = await _resourceOperationUpdateService.SetInProgressAsync(currentOperation.Id, _requestIdService.GetRequestId());

                            await _roleProvisioningService.Handle(currentOperation);

                            await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id, CloudResourceOperationState.DONE_SUCCESSFUL);
                        }
                        else if (_firewallService.CanHandle(currentOperation))
                        {
                            _provisioningLogService.OperationInformation(currentOperation, "Operation is ENSURE FIREWALL");
                            var firewallRuleService = AzureResourceServiceResolver.GetFirewallRuleService(_serviceProvider, currentOperation.Resource.ResourceType);
                            currentOperation = await _resourceOperationUpdateService.SetInProgressAsync(currentOperation.Id, _requestIdService.GetRequestId());

                            if (firewallRuleService is IHasFirewallRules)
                            {
                                await _firewallService.Handle(currentOperation,
                                                              firewallRuleService
                                                              );

                                await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id, CloudResourceOperationState.DONE_SUCCESSFUL);
                            }
                            else
                            {
                                throw new ProvisioningException($"Service {firewallRuleService.GetType().Name} does not support firewall operations", CloudResourceOperationState.ABORTED, deleteFromQueue: true);
                            }
                        }
                        else if (_corsRuleProvisioningService.CanHandle(currentOperation))
                        {
                            _provisioningLogService.OperationInformation(currentOperation, "Operation is ENSURE CORS RULES");
                            var corsRuleService = AzureResourceServiceResolver.GetCorsRuleServiceOrThrow(_serviceProvider, currentOperation.Resource.ResourceType);
                            currentOperation = await _resourceOperationUpdateService.SetInProgressAsync(currentOperation.Id, _requestIdService.GetRequestId());

                            if (corsRuleService is IHasCorsRules)
                            {
                                await _corsRuleProvisioningService.Handle(currentOperation, corsRuleService);

                                await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id, CloudResourceOperationState.DONE_SUCCESSFUL);
                            }
                            else
                            {
                                throw new ProvisioningException($"Service {corsRuleService.GetType().Name} does not support CORS operations", CloudResourceOperationState.ABORTED, deleteFromQueue: true);
                            }
                        }
                        else
                        {
                            throw new ProvisioningException("Unknown operation type", CloudResourceOperationState.ABORTED);
                        }

                        _provisioningLogService.OperationInformation(currentOperation, "Successfully handeled operation");
                    }
                    catch (ProvisioningException ex) //Inner loop, ordinary exception is not catched
                    {
                        if (ex.LogAsWarning)
                        {
                            if (ex.IncludeExceptionInWarningLog)
                            {
                                _provisioningLogService.OperationWarning(currentOperation, "Operation aborted", ex);
                            }
                            else
                            {
                                _provisioningLogService.OperationWarning(currentOperation, $"Operation aborted: {ex.Message}");
                            }
                        }
                        else
                        {
                            _provisioningLogService.OperationError(ex, currentOperation, "Operation failed");
                        }

                        currentOperation = await _resourceOperationUpdateService.SetErrorMessageAsync(currentOperation.Id, ex);

                        if (!String.IsNullOrWhiteSpace(ex.NewOperationStatus))
                        {
                            currentOperation = await _resourceOperationUpdateService.UpdateStatusAsync(currentOperation.Id, ex.NewOperationStatus);
                        }

                        if (!ex.ProceedWithOtherOperations)
                        {
                            throw;
                        }
                    }
                } //foreach

                _provisioningLogService.QueueParentProgressInformation(queueParentItem, "Done");

                await _provisioningQueueService.DeleteMessageAsync(queueParentItem);
                await MoveUpAnyDependentOperations(queueParentItem);
            }
            catch (ProvisioningException ex) //Outer loop catch 1
            {
                if (ex.DeleteFromQueue)
                {
                    _provisioningLogService.QueueParentProgressWarning(queueParentItem, "Deleting due to exception");
                    await _provisioningQueueService.DeleteMessageAsync(queueParentItem);
                }
                else if (ex.PostponeQueueItemFor.HasValue && ex.PostponeQueueItemFor.Value > 0)
                {
                    if (currentOperation.TryCount < currentOperation.MaxTryCount)
                    {
                        if (queueParentItem.DequeueCount == 5)
                        {
                            _provisioningLogService.QueueParentProgressWarning(queueParentItem, "Re-queuing after exception");

                            await _provisioningQueueService.ReQueueMessageAsync(queueParentItem, ex.PostponeQueueItemFor.Value);
                        }
                        else
                        {
                            _provisioningLogService.QueueParentProgressWarning(queueParentItem, "Increasing invisibility after exception");
                            await _provisioningQueueService.IncreaseInvisibilityAsync(queueParentItem, ex.PostponeQueueItemFor.Value);
                        }
                    }
                }

                if (ex.StoreQueueInfoOnOperation)
                {
                    if (!queueParentItem.NextVisibleOn.HasValue)
                    {
                        _provisioningLogService.QueueParentProgressError(queueParentItem, "Could not store queue info on operation, no next visible time exist");
                    }
                    else
                    {
                        currentOperation = await _resourceOperationUpdateService.SetQueueInformationAsync(currentOperation.Id, queueParentItem.MessageId, queueParentItem.PopReceipt, queueParentItem.NextVisibleOn.Value);
                    }
                }
            }
            catch (Exception ex) //Outer loop catch 2
            {
                _provisioningLogService.QueueParentProgressError(queueParentItem, "Unhandled exception occured");
                await _provisioningQueueService.DeleteMessageAsync(queueParentItem);
            }
        }
 public async Task IncreaseInvisibleBasedOnResource(CloudResourceOperationDto currentOperation, ProvisioningQueueParentDto queueParentItem)
 {
     var increaseBy = ResourceProivisoningTimeoutResolver.GetTimeoutForOperationInSeconds(currentOperation.Resource.ResourceType, currentOperation.OperationType);
     await IncreaseInvisibilityAsync(queueParentItem, increaseBy);
 }
 public void HandlingQueueParent(ProvisioningQueueParentDto queueParentItem)
 {
     _logger.LogInformation($"Handling: {queueParentItem.MessageId} - {queueParentItem.Description}");
 }
 public void QueueParentProgressWarning(ProvisioningQueueParentDto queueParentItem, string suffix)
 {
     _logger.LogWarning(QueueParentProgressLogMessage(queueParentItem, suffix));
 }
Beispiel #24
0
        async Task ScheduleCreationOfBastion(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem, string configString = null)
        {
            var vNetCreateOperation = dto.Network.Operations.FirstOrDefault().Id;

            var bastionName = AzureResourceNameUtil.Bastion(dto.StudyName, dto.SandboxName);

            _ = await CreateResourceEntryAndAddToQueue(dto, queueParentItem, AzureResourceType.Bastion, resourceName : bastionName, configString : configString, dependsOn : vNetCreateOperation);
        }
Beispiel #25
0
        async Task ScheduleCreationOfDiagStorageAccount(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem)
        {
            var resourceName = AzureResourceNameUtil.DiagnosticsStorageAccount(dto.StudyName, dto.SandboxName);
            var resourceGroupCreateOperation = dto.ResourceGroup.Operations.FirstOrDefault().Id;
            var resourceEntry = await CreateResourceEntryAndAddToQueue(dto, queueParentItem, AzureResourceType.StorageAccount, resourceName : resourceName, dependsOn : resourceGroupCreateOperation);

            dto.DiagnosticsStorage = resourceEntry;
        }
        public async Task <VmDto> CreateAsync(int sandboxId, VirtualMachineCreateDto userInput)
        {
            CloudResource vmResourceEntry = null;

            try
            {
                ValidateVmPasswordOrThrow(userInput.Password);

                GenericNameValidation.ValidateName(userInput.Name);

                _logger.LogInformation($"Creating Virtual Machine for sandbox: {sandboxId}");

                var sandbox = await _sandboxModelService.GetByIdForResourceCreationAsync(sandboxId, UserOperation.Study_Crud_Sandbox);

                var virtualMachineName = AzureResourceNameUtil.VirtualMachine(sandbox.Study.Name, sandbox.Name, userInput.Name);

                await _cloudResourceCreateService.ValidateThatNameDoesNotExistThrowIfInvalid(virtualMachineName);

                var tags = ResourceTagFactory.SandboxResourceTags(_config, sandbox.Study, sandbox);

                var region = RegionStringConverter.Convert(sandbox.Region);

                userInput.DataDisks = await TranslateDiskSizes(sandbox.Region, userInput.DataDisks);

                var resourceGroup = await CloudResourceQueries.GetResourceGroupEntry(_db, sandboxId);

                //Make this dependent on bastion create operation to be completed, since bastion finishes last
                var dependsOn = await CloudResourceQueries.GetCreateOperationIdForBastion(_db, sandboxId);

                vmResourceEntry = await _cloudResourceCreateService.CreateVmEntryAsync(sandboxId, resourceGroup, region.Name, tags, virtualMachineName, dependsOn, null);

                //Create vm settings and immeately attach to resource entry
                var vmSettingsString = await CreateVmSettingsString(sandbox.Region, vmResourceEntry.Id, sandbox.Study.Id, sandboxId, userInput);

                vmResourceEntry.ConfigString = vmSettingsString;
                await _cloudResourceUpdateService.Update(vmResourceEntry.Id, vmResourceEntry);

                var queueParentItem = new ProvisioningQueueParentDto
                {
                    Description = $"Create VM for Sandbox: {sandboxId}"
                };

                queueParentItem.Children.Add(new ProvisioningQueueChildDto()
                {
                    ResourceOperationId = vmResourceEntry.Operations.FirstOrDefault().Id
                });

                await _provisioningQueueService.SendMessageAsync(queueParentItem);

                var dtoMappedFromResource = _mapper.Map <VmDto>(vmResourceEntry);

                return(dtoMappedFromResource);
            }
            catch (Exception ex)
            {
                try
                {
                    //Delete resource if created
                    if (vmResourceEntry != null)
                    {
                        await _cloudResourceDeleteService.HardDeleteAsync(vmResourceEntry.Id);
                    }
                }
                catch (Exception rollbackEx)
                {
                    _logger.LogError(rollbackEx, $"Failed to roll back VM creation for sandbox {sandboxId}");
                }

                throw new Exception($"Failed to create VM: {ex.Message}", ex);
            }
        }
Beispiel #27
0
        async Task ScheduleCreationOfNetworkSecurityGroup(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem)
        {
            var nsgName = AzureResourceNameUtil.NetworkSecGroupSubnet(dto.StudyName, dto.SandboxName);
            var diagStorageAccountCreateOperation = dto.DiagnosticsStorage.Operations.FirstOrDefault().Id;
            var resourceEntry = await CreateResourceEntryAndAddToQueue(dto, queueParentItem, AzureResourceType.NetworkSecurityGroup, resourceName : nsgName, dependsOn : diagStorageAccountCreateOperation);

            dto.NetworkSecurityGroup = resourceEntry;
        }
Beispiel #28
0
        async Task ScheduleCreationOfVirtualNetwork(SandboxResourceCreationAndSchedulingDto dto, ProvisioningQueueParentDto queueParentItem)
        {
            var networkName       = AzureResourceNameUtil.VNet(dto.StudyName, dto.SandboxName);
            var sandboxSubnetName = AzureResourceNameUtil.SubNet(dto.StudyName, dto.SandboxName);

            var networkSettings = new NetworkSettingsDto()
            {
                SandboxSubnetName = sandboxSubnetName
            };
            var networkSettingsString = CloudResourceConfigStringSerializer.Serialize(networkSettings);

            var nsgCreateOperation = dto.NetworkSecurityGroup.Operations.FirstOrDefault().Id;

            var resourceEntry = await CreateResourceEntryAndAddToQueue(dto, queueParentItem, AzureResourceType.VirtualNetwork, resourceName : networkName, configString : networkSettingsString, dependsOn : nsgCreateOperation);

            dto.Network = resourceEntry;
        }
Beispiel #29
0
        public async Task ThrowIfDependentOnUnfinishedOperationAsync(CloudResourceOperationDto operation, ProvisioningQueueParentDto queueParentItem)
        {
            if (operation.DependsOnOperationId.HasValue)
            {
                if (!(await _cloudResourceOperationReadService.OperationIsFinishedAndSucceededAsync(operation.DependsOnOperationId.Value)))
                {
                    var increaseBy = CloudResourceConstants.INCREASE_QUEUE_INVISIBLE_WHEN_DEPENDENT_ON_NOT_FINISHED;

                    bool storeQueueInformationOnOperation = queueParentItem.Children.Count == 1;

                    throw new ProvisioningException($"Dependant operation {operation.DependsOnOperationId.Value} is not finished. Invisibility increased by {increaseBy}", proceedWithOtherOperations: false, deleteFromQueue: false, postponeQueueItemFor: increaseBy, storeQueueInfoOnOperation: storeQueueInformationOnOperation, logAsWarning: true, includeExceptionInWarningLog: false);
                }
            }
        }
        async Task EnsureOperationIsReadyForRetryAndAddToQueueItem(CloudResource resource, CloudResourceOperation operationToRetry, ProvisioningQueueParentDto queueParentItem)
        {
            await EnsureOperationIsReadyForRetry(resource, operationToRetry);

            _logger.LogInformation(ReScheduleResourceLogPrefix(resource, $"Re-queing item", operationToRetry));

            queueParentItem.Children.Add(new ProvisioningQueueChildDto()
            {
                ResourceOperationId = operationToRetry.Id
            });

            _logger.LogInformation(ReScheduleResourceLogPrefix(resource, $"Item re-queued", operationToRetry));
        }