public async Task CreateResourceGroupForStudySpecificDatasetsAsync(Study study, CancellationToken cancellationToken = default)
        {
            var studyForCreation = await _studyModelService.GetForDatasetCreationNoAccessCheckAsync(study.Id);

            var resourceGroupForDatasets = GetResourceGroupForStudySpecificDataset(studyForCreation);

            var parentQueueItem = QueueItemFactory.CreateParent("Create resource group for Study specific datasets");

            if (resourceGroupForDatasets == null)
            {
                var resourceGroupName = AzureResourceNameUtil.StudySpecificDatasetResourceGroup(studyForCreation.Name);
                var tags = ResourceTagFactory.StudySpecificDatasourceResourceGroupTags(_config, studyForCreation);
                resourceGroupForDatasets = await _cloudResourceCreateService.CreateStudySpecificResourceGroupEntryAsync(studyForCreation.Id, resourceGroupName, "norwayeast", tags);

                ProvisioningQueueUtil.CreateChildAndAdd(parentQueueItem, resourceGroupForDatasets);
            }
            else
            {
                throw new Exception("Resource group allready exists");
            }

            await ScheduleResourceGroupRoleAssignments(studyForCreation, resourceGroupForDatasets, parentQueueItem);

            await _provisioningQueueService.SendMessageAsync(parentQueueItem, cancellationToken : cancellationToken);
        }
        async Task ScheduleResourceGroupRoleAssignments(Study study, CloudResource resourceGroup, ProvisioningQueueParentDto queueParentItem)
        {
            var participants = await _db.StudyParticipants.Include(sp => sp.User).Where(p => p.StudyId == study.Id).ToListAsync();

            var desiredState = CloudResourceConfigStringSerializer.Serialize(new CloudResourceOperationStateForRoleUpdate(study.Id));

            var resourceGroupCreateOperation = CloudResourceOperationUtil.GetCreateOperation(resourceGroup);

            var roleAssignmentUpdateOperation = await _cloudResourceOperationCreateService.CreateUpdateOperationAsync(resourceGroup.Id, CloudResourceOperationType.ENSURE_ROLES, dependsOn : resourceGroupCreateOperation.Id, desiredState : desiredState);

            ProvisioningQueueUtil.CreateChildAndAdd(queueParentItem, roleAssignmentUpdateOperation);
        }
        async Task <CloudResource> CreateResourceGroupForStudySpecificDatasetsInternalAsync(Study study, ProvisioningQueueParentDto parentQueueItem)
        {
            var resourceGroupName = AzureResourceNameUtil.StudySpecificDatasetResourceGroup(study.Name);
            var tags = ResourceTagFactory.StudySpecificDatasourceResourceGroupTags(_config, study);
            var resourceGroupForDatasets = await _cloudResourceCreateService.CreateStudySpecificResourceGroupEntryAsync(study.Id, resourceGroupName, "norwayeast", tags);

            ProvisioningQueueUtil.CreateChildAndAdd(parentQueueItem, resourceGroupForDatasets);

            await ScheduleResourceGroupRoleAssignments(study, resourceGroupForDatasets, parentQueueItem);

            return(resourceGroupForDatasets);
        }
        async Task OrderCreationOfStudySpecificDatasetStorageAccount(Study study, Dataset dataset, CloudResource resourceGroup, string clientIp, ProvisioningQueueParentDto queueParent, CancellationToken cancellationToken)
        {
            try
            {
                if (resourceGroup == null)
                {
                    throw new ArgumentNullException("resourceGroup", "Resource group entry is null");
                }

                _logger.LogInformation($"CreateResourcesForStudySpecificDataset - Dataset Id: {dataset.Id}");

                var currentUser = await _userService.GetCurrentUserAsync();

                var tagsForStorageAccount = ResourceTagFactory.StudySpecificDatasourceStorageAccountTags(_config, study, dataset.Name);
                var storageAccountName    = AzureResourceNameUtil.StudySpecificDataSetStorageAccount(dataset.Name);

                var resourceEntry = await _cloudResourceCreateService.CreateStudySpecificDatasetEntryAsync(dataset.Id, resourceGroup.Id, resourceGroup.Region, resourceGroup.ResourceGroupName, storageAccountName, tagsForStorageAccount);

                ProvisioningQueueUtil.CreateChildAndAdd(queueParent, resourceEntry);

                var serverPublicIp = await _publicIpService.GetIp();

                DatasetFirewallUtils.EnsureDatasetHasFirewallRules(_logger, currentUser, dataset, clientIp, serverPublicIp);

                await _db.SaveChangesAsync();

                var stateForFirewallOperation = DatasetFirewallUtils.TranslateAllowedIpsToOperationDesiredState(dataset.FirewallRules.ToList());

                var createStorageAccountOperation = CloudResourceOperationUtil.GetCreateOperation(resourceEntry);
                var firewallUpdateOperation       = await _cloudResourceOperationCreateService.CreateUpdateOperationAsync(resourceEntry.Id, CloudResourceOperationType.ENSURE_FIREWALL_RULES, dependsOn : createStorageAccountOperation.Id, desiredState : stateForFirewallOperation);

                ProvisioningQueueUtil.CreateChildAndAdd(queueParent, firewallUpdateOperation);

                var stateForCorsRules   = DatasetCorsUtils.CreateDatasetCorsRules(_config);
                var corsUpdateOperation = await _cloudResourceOperationCreateService.CreateUpdateOperationAsync(resourceEntry.Id, CloudResourceOperationType.ENSURE_CORS_RULES, dependsOn : firewallUpdateOperation.Id, desiredState : stateForCorsRules);

                ProvisioningQueueUtil.CreateChildAndAdd(queueParent, corsUpdateOperation);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to schedule creation of Azure Storage Account", ex);
            }
        }
        async Task <CloudResource> EnsureResourceGroupExists(Study study, Dataset dataset, ProvisioningQueueParentDto parentQueueItem)
        {
            try
            {
                var resourceGroupDb = GetResourceGroupForStudySpecificDataset(study);

                if (resourceGroupDb == null)
                {
                    resourceGroupDb = await CreateResourceGroupForStudySpecificDatasetsInternalAsync(study, parentQueueItem);
                }
                else
                {
                    if (String.IsNullOrWhiteSpace(resourceGroupDb.LastKnownProvisioningState))
                    {
                        var resourceGroupCreateOperation = CloudResourceOperationUtil.GetCreateOperation(resourceGroupDb);

                        //Old and failed, give it another try
                        if (resourceGroupCreateOperation != null &&
                            resourceGroupCreateOperation.Created.AddMinutes(10) <= DateTime.UtcNow &&
                            (resourceGroupCreateOperation.Status == CloudResourceOperationState.FAILED || resourceGroupCreateOperation.Status == CloudResourceOperationState.ABORTED))
                        {
                            ProvisioningQueueUtil.CreateChildAndAdd(parentQueueItem, resourceGroupDb);
                        }
                    }
                    else
                    {
                        if (resourceGroupDb.LastKnownProvisioningState == CloudResourceProvisioningStates.SUCCEEDED || resourceGroupDb.LastKnownProvisioningState == CloudResourceProvisioningStates.CREATING)
                        {
                            return(resourceGroupDb);
                        }
                    }
                }

                return(resourceGroupDb);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to locate or ensure that resource group exist for storage account", ex);
            }
        }