public async Task <CloudResource> CreateVmEntryAsync(int sandboxId, CloudResource resourceGroup, string region, Dictionary <string, string> tags, string vmName, int operationDependsOn, string configString)
        {
            try
            {
                await ValidateThatNameDoesNotExistThrowIfInvalid(vmName);

                var currentUser = await _userService.GetCurrentUserAsync();

                var sessionId = _requestIdService.GetRequestId();

                var resourceEntry = CloudResourceFactory.CreateSandboxResourceEntry(
                    currentUser, sessionId,
                    sandboxId, region, AzureResourceType.VirtualMachine,
                    resourceGroup.Id, resourceName: vmName, tags: tags, configString: configString,
                    dependsOn: operationDependsOn,
                    resourceGroupName: resourceGroup.ResourceGroupName,
                    sandboxControlled: false
                    );

                await SaveToDb(resourceEntry);

                return(resourceEntry);
            }
            catch (Exception ex)
            {
                throw new Exception($"Unable to create database resource entry for Virtual Machine for Sandbox {sandboxId}. See inner Exception for details", ex);
            }
        }
예제 #2
0
        public static CloudResource Create(string region,
                                           string resourceType,
                                           string resourceGroup,
                                           string resourceName,
                                           string resourceId            = null,
                                           string resourceKey           = null,
                                           string purpose               = null,
                                           bool sandboxControlled       = false,
                                           string batchId               = null,
                                           CloudResource parentResource = null,
                                           bool createOperationFinished = true,
                                           bool deleted         = false,
                                           bool deleteSucceeded = false)
        {
            var cloudResource = CreateBasic(region, resourceType, resourceGroup, resourceName, resourceId, resourceKey, purpose, sandboxControlled, parentResource);

            cloudResource.Operations.Add(createOperationFinished ? CloudResourceOperationFactory.SucceededOperation("create" + resourceName, batchId: batchId) : CloudResourceOperationFactory.NewOperation("create" + resourceName, batchId: batchId));

            if (deleted)
            {
                cloudResource.Operations.Add(deleteSucceeded ?
                                             CloudResourceOperationFactory.SucceededOperation("delete" + resourceName, operationType: CloudResourceOperationType.DELETE)
                    : CloudResourceOperationFactory.NewOperation("delete" + resourceName, operationType: CloudResourceOperationType.DELETE));
            }

            return(cloudResource);
        }
예제 #3
0
        public static CloudResource CreateFailing(string region,
                                                  string resourceType,
                                                  string resourceGroup,
                                                  string resourceName,
                                                  string resourceId             = null,
                                                  string resourceKey            = null,
                                                  string purpose                = null,
                                                  bool sandboxControlled        = false,
                                                  string batchId                = null,
                                                  CloudResource parentResource  = null,
                                                  string statusOfFailedResource = CloudResourceOperationState.FAILED,
                                                  int tryCount         = CloudResourceConstants.RESOURCE_MAX_TRY_COUNT,
                                                  int maxTryCount      = CloudResourceConstants.RESOURCE_MAX_TRY_COUNT,
                                                  bool deleted         = false,
                                                  bool deleteSucceeded = false

                                                  )
        {
            var cloudResource = CreateBasic(region, resourceType, resourceGroup, resourceName, resourceId, resourceKey, purpose, sandboxControlled, parentResource);

            cloudResource.LastKnownProvisioningState = null;
            cloudResource.Operations.Add(CloudResourceOperationFactory.FailedOperation("create" + resourceName, batchId: batchId, status: statusOfFailedResource, tryCount: tryCount, maxTryCount: maxTryCount));

            if (deleted)
            {
                cloudResource.Operations.Add(deleteSucceeded ?
                                             CloudResourceOperationFactory.SucceededOperation("delete" + resourceName, operationType: CloudResourceOperationType.DELETE)
                    : CloudResourceOperationFactory.NewOperation("delete" + resourceName, operationType: CloudResourceOperationType.DELETE));
            }

            return(cloudResource);
        }
        string ReScheduleResourceLogPrefix(CloudResource resource, string logText, CloudResourceOperation operation = null)
        {
            var logMessage = $"Re-schedule resource operation";

            if (resource.StudyId.HasValue)
            {
                logMessage += $" | Study {resource.StudyId.Value}";
            }

            if (resource.SandboxId.HasValue)
            {
                logMessage += $" | Sandbox {resource.SandboxId.Value}";
            }

            logMessage += $" | Resource: {resource.Id}";

            if (operation != null)
            {
                logMessage += $" | Operation {operation.Id} | {operation.Description}";
            }

            logMessage += $" | {logText}";

            return(logMessage);
        }
예제 #5
0
        public static CloudResource CreateBasicResource(UserDto currentUser, string sessionId, string region, string resourceType, string resourceName, Dictionary <string, string> tags, string resourceGroupName = null
                                                        )
        {
            var tagsString = TagUtils.TagDictionaryToString(tags);

            var newResource = new CloudResource()
            {
                ResourceType      = resourceType,
                Region            = region,
                ResourceGroupName = resourceGroupName,
                ResourceName      = resourceName,
                Tags        = tagsString,
                ResourceKey = AzureResourceNameUtil.AZURE_RESOURCE_INITIAL_ID_OR_NAME,
                ResourceId  = AzureResourceNameUtil.AZURE_RESOURCE_INITIAL_ID_OR_NAME,
                Operations  = new List <CloudResourceOperation> {
                    new CloudResourceOperation()
                    {
                        Status             = CloudResourceOperationState.NEW,
                        OperationType      = CloudResourceOperationType.CREATE,
                        CreatedBy          = currentUser.UserName,
                        CreatedBySessionId = sessionId,
                        MaxTryCount        = CloudResourceConstants.RESOURCE_MAX_TRY_COUNT
                    }
                },
                CreatedBy = currentUser.UserName
            };

            return(newResource);
        }
예제 #6
0
        public static string GetUserFriendlyName(CloudResource resource)
        {
            var resourceType = resource.ResourceType;

            switch (resourceType)
            {
            case AzureResourceType.ResourceGroup:
                return(AzureResourceTypeFriendlyName.ResourceGroup);

            case AzureResourceType.StorageAccount:
                return(AzureResourceTypeFriendlyName.StorageAccount);

            case AzureResourceType.VirtualNetwork:
                return(AzureResourceTypeFriendlyName.VirtualNetwork);

            case AzureResourceType.NetworkSecurityGroup:
                return(AzureResourceTypeFriendlyName.NetworkSecurityGroup);

            case AzureResourceType.Bastion:
                return(AzureResourceTypeFriendlyName.Bastion);

            case AzureResourceType.VirtualMachine:
                return(AzureResourceTypeFriendlyName.VirtualMachine);

            default:
                return("n/a");
            }
        }
예제 #7
0
        public IActionResult CreateMachine(CloudResource machine)
        {
            if (machine == null)
            {
                return(BadRequest(nameof(machine)));
            }

            try
            {
                machine.Lessor = _lessorRepository.GetItem(machine.Lessor.Id);
                var result = _machineService.Create(machine);
                if (result >= 1)
                {
                    return(Ok());
                }
            }
            catch (ArgumentNullException)
            {
                return(BadRequest(nameof(machine)));
            }
            catch (Exception)
            {
                return(StatusCode(500));
            }
            return(StatusCode(500));
        }
        async Task EnsureOperationIsReadyForRetryAndEnqueue(CloudResource resource, CloudResourceOperation operationToRetry)
        {
            var queueParentItem = QueueItemFactory.CreateParent(operationToRetry.Id, $"{operationToRetry.Description} (re-scheduled)");

            await EnsureOperationIsReadyForRetryAndAddToQueueItem(resource, operationToRetry, queueParentItem);

            await _provisioningQueueService.SendMessageAsync(queueParentItem);
        }
예제 #9
0
        public void DecideWhatOperationToBaseStatusOn_withEmptyParameter_shouldThrow()
        {
            var cloudResource = new CloudResource()
            {
            };

            var ex = Assert.Throws <ArgumentNullException>(() => ResourceStatusUtil.DecideWhatOperationToBaseStatusOn(cloudResource));
        }
예제 #10
0
 public static void ResourceAfterCreationAsserts(CloudResource cloudResource)
 {
     Assert.NotNull(cloudResource.ResourceId);
     Assert.NotNull(cloudResource.ResourceGroupName);
     Assert.NotNull(cloudResource.ResourceName);
     Assert.NotNull(cloudResource.CreatedBy);
     Assert.NotNull(cloudResource.LastKnownProvisioningState);
 }
예제 #11
0
        static void SetOperationProperties(CloudResource resource, string description, string batchId = null, int operationDependsOn = 0)
        {
            var operation = resource.Operations.SingleOrDefault();

            operation.Description          = description;
            operation.BatchId              = batchId;
            operation.DependsOnOperationId = operationDependsOn > 0 ? operationDependsOn : default(int?);
        }
        // Checks Tags from Resource in Azure with information from db.
        // Makes sure they are equal.
        async Task CheckAndUpdateTags(CloudResource resource)
        {
            try
            {
                var serviceForResource = AzureResourceServiceResolver.GetServiceWithTags(_serviceProvider, resource.ResourceType);

                if (serviceForResource == null)
                {
                    LogMonitoringError(resource, SepesEventId.MONITORING_NO_TAG_SERVICE, $"Could not resolve tag service for resource type: {resource.ResourceType}", critical: true);
                }
                else
                {
                    // Read info used to create tags from resourceGroup in DB
                    // These tags should be checked with the ones in Azure.
                    var tagsFromDb    = TagUtils.TagStringToDictionary(resource.Tags);
                    var tagsFromAzure = await serviceForResource.GetTagsAsync(resource.ResourceGroupName, resource.ResourceName);

                    if (tagsFromDb != null && tagsFromDb.Count > 0 && tagsFromAzure == null)
                    {
                        _logger.LogWarning(SepesEventId.MONITORING_NO_TAGS, $"No tags found for resource {resource.Id}!");
                        return;
                    }

                    // Check against tags from resource in Azure.
                    // If different => update Tags and report difference to Study Owner?
                    foreach (var tag in tagsFromAzure)
                    {
                        //Do not check CreatedByMachine-tag, as this will be different from original.
                        if (!tag.Key.Equals("CreatedByMachine"))
                        {
                            if (!tagsFromDb.TryGetValue(tag.Key, out string dbValue))
                            {
                                // If Tag exists in Azure but not in tags generated from DB-data, report.
                                // Means that user has added tags themselves in Azure.
                                LogMonitoringError(resource, SepesEventId.MONITORING_MANUALLY_ADDED_TAGS, $"Tag {tag.Key} : {tag.Value} has been added after resource creation!");
                            }
                            else
                            {
                                // If Tag exists in Azure and Db but has different value in Azure
                                if (!tag.Value.Equals(dbValue))
                                {
                                    LogMonitoringError(resource, SepesEventId.MONITORING_INCORRECT_TAGS, $"Tag {tag.Key} : {tag.Value} does not match value from Sepes : {dbValue}");

                                    //Update tag in Azure to match DB-information.
                                    await serviceForResource.UpdateTagAsync(resource.ResourceGroupName, resource.ResourceName, new KeyValuePair <string, string>(tag.Key, dbValue));

                                    _logger.LogWarning($"Updated Tag: {tag.Key} from value: {tag.Value} => {dbValue}");
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogMonitoringError(resource, SepesEventId.MONITORING_CRITICAL, $"Tag check/update failed", ex);
            }
        }
        public static CloudResourceOperation GetCreateOperation(CloudResource resource)
        {
            if (resource.Operations == null)
            {
                throw new NullReferenceException($"Operation collection is null, might be missing Include");
            }

            return(resource.Operations.Where(o => o.OperationType == CloudResourceOperationType.CREATE).SingleOrDefault());
        }
예제 #14
0
        public void StudySpecificDatasetResourceGroupName_ShouldContainStudyName(string expectedResult, string resourceType)
        {
            var resource = new CloudResource {
                ResourceType = resourceType
            };
            var result = AzureResourceTypeUtil.GetUserFriendlyName(resource);

            Assert.Equal(expectedResult, result);
        }
        public static bool HasSuccessfulCreateOperation(CloudResource resource)
        {
            var createOperation = GetCreateOperation(resource);

            if (createOperation == null)
            {
                return(false);
            }

            return(createOperation.Status == CloudResourceOperationState.DONE_SUCCESSFUL);
        }
예제 #16
0
        public void MarkAsDeleted_ShouldMarkAsDeletedWithCorrectName()
        {
            var deletedBy       = "John";
            var itemToBeDeleted = new CloudResource {
            };

            SoftDeleteUtil.MarkAsDeleted(itemToBeDeleted, deletedBy);

            Assert.Equal(itemToBeDeleted.DeletedBy, deletedBy);
            Assert.True(SoftDeleteUtil.IsMarkedAsDeleted(itemToBeDeleted));
        }
예제 #17
0
        public void MarkAsDeleted_ShouldMarkAsDeletedWithCorrectName5()
        {
            var deletedBy       = new UserDto {
            };
            var itemToBeDeleted = new CloudResource {
            };
            var ex = Assert.Throws <ArgumentNullException>(() => SoftDeleteUtil.MarkAsDeleted(null, ""));

            Assert.Contains("Item to delete was null", ex.Message);
            Assert.False(SoftDeleteUtil.IsMarkedAsDeleted(itemToBeDeleted));
        }
예제 #18
0
        public static bool InternetIsOpen(CloudResource vmResource)
        {
            var relevantRule = GetInternetRule(vmResource);

            if (relevantRule == null)
            {
                return(false);
            }

            return(relevantRule.Action == RuleAction.Allow);
        }
예제 #19
0
        public static string GetOsName(CloudResource resource)
        {
            var vmSettings = CloudResourceConfigStringSerializer.VmSettings(resource.ConfigString);

            if (vmSettings != null)
            {
                return(vmSettings.OperatingSystem);
            }

            return(null);
        }
예제 #20
0
        async Task ReadAllAndAssertExpectSuccess(CloudResource vm)
        {
            await GenericReader.ReadAndAssertExpectSuccess <StudyDetailsDto>(_restHelper, GenericReader.StudyUrl(vm.Sandbox.StudyId));

            await GenericReader.ReadAndAssertExpectSuccess <SandboxDetails>(_restHelper, GenericReader.SandboxUrl(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectSuccess <List <VmDto> >(_restHelper, GenericReader.SandboxVirtualMachines(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectSuccess <List <SandboxResourceLight> >(_restHelper, GenericReader.SandboxResources(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectSuccess <VmExtendedDto>(_restHelper, GenericReader.VirtualMachineExtendedInfo(vm.Id)); //Todo: Add this test, but remember to mock out azure vm service
        }
        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);
        }
예제 #22
0
        async Task ReadAllAndAssertExpectForbidden(CloudResource vm)
        {
            await GenericReader.ReadAndAssertExpectForbidden(_restHelper, GenericReader.StudyUrl(vm.Sandbox.StudyId));

            await GenericReader.ReadAndAssertExpectForbidden(_restHelper, GenericReader.SandboxUrl(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectForbidden(_restHelper, GenericReader.SandboxVirtualMachines(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectForbidden(_restHelper, GenericReader.SandboxResources(vm.Sandbox.Id));

            await GenericReader.ReadAndAssertExpectForbidden(_restHelper, GenericReader.VirtualMachineExtendedInfo(vm.Id)); //Todo: Add this test, but remember to mock out azure vm service
        }
예제 #23
0
        public static void StudyDatasetResourceGroupBeforeProvisioningAssert(CloudResource cloudResource)
        {
            StudyDatasetResourceGroupBasicAsserts(cloudResource);

            Assert.Null(cloudResource.LastKnownProvisioningState);

            foreach (var curOp in cloudResource.Operations)
            {
                Assert.Equal(CloudResourceOperationState.NEW, curOp.Status);
                Assert.NotNull(curOp.CreatedBy);
                Assert.Null(curOp.CarriedOutBySessionId);
            }
        }
        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));
        }
예제 #25
0
        public void DecideWhatOperationToBaseStatusOn_withEmptyList_shouldThrow()
        {
            var cloudResourceOperation = new List <CloudResourceOperation>()
            {
            };
            var cloudResource = new CloudResource()
            {
                Operations = cloudResourceOperation
            };
            var result = ResourceStatusUtil.DecideWhatOperationToBaseStatusOn(cloudResource);

            Assert.Null(result);
        }
        //Fetches the provisioning state for the resource and write this on our record of the resource
        async Task GetAndLogProvisioningState(CloudResource resource)
        {
            try
            {
                var provisioningState = await GetProvisioningState(resource);

                await _cloudResourceUpdateService.UpdateProvisioningState(resource.Id, provisioningState);
            }
            catch (Exception ex)
            {
                _logger.LogCritical(ex, $"Checking provisioning state failed for resource id: {resource.Id}");
            }
        }
예제 #27
0
        async Task CreateUpdateOperationAndAddQueueItem(CloudResource vm, string description)
        {
            //If un-started update allready exist, no need to create update op?
            if (await _sandboxResourceOperationReadService.HasUnstartedCreateOrUpdateOperation(vm.Id))
            {
                _logger.LogWarning($"Updating VM {vm.Id}: There is allready an unstarted VM Create or Update operation. Not creating additional");
            }
            else
            {
                var vmUpdateOperation = await _sandboxResourceOperationCreateService.CreateUpdateOperationAsync(vm.Id);

                await _provisioningQueueService.CreateItemAndEnqueue(vmUpdateOperation);
            }
        }
예제 #28
0
        public static CloudResource GetSibilingResource(CloudResource resource, string resourceType)
        {
            if (resource.Sandbox == null)
            {
                throw new NullReferenceException($"Cannot navigate to Sandbox for resource {resource.Id}");
            }

            if (resource.Sandbox.Resources == null)
            {
                throw new NullReferenceException($"Cannot navigate to Sandbox sibling resources for resource {resource.Id}");
            }

            return(resource.Sandbox.Resources.FirstOrDefault(r => r.ResourceType == resourceType));
        }
예제 #29
0
        public static void StudyDatasetResourceGroupAfterProvisioningAssert(CloudResource cloudResource)
        {
            StudyDatasetResourceGroupBasicAsserts(cloudResource);

            ResourceAfterCreationAsserts(cloudResource);

            Assert.Equal(CloudResourceProvisioningStates.SUCCEEDED, cloudResource.LastKnownProvisioningState);

            foreach (var curOp in cloudResource.Operations)
            {
                Assert.Equal(CloudResourceOperationState.DONE_SUCCESSFUL, curOp.Status);
                Assert.NotNull(curOp.CarriedOutBySessionId);
            }
        }
        async Task <CloudResourceOperation> CheckAnyIfOperationsToWaitFor(CloudResource resource, UserDto currentUser)
        {
            bool mostRecentOperation = true;

            foreach (var curOperation in resource.Operations.OrderByDescending(o => o.Created))
            {
                if (curOperation.OperationType == CloudResourceOperationType.DELETE)
                {
                    throw new Exception($"Error when adding operation to resource {resource.Id}, resource allready marked for deletion");
                }

                if (mostRecentOperation && curOperation.Status == CloudResourceOperationState.DONE_SUCCESSFUL)
                {
                    return(null);
                }

                if (curOperation.OperationType == CloudResourceOperationType.UPDATE || curOperation.OperationType == CloudResourceOperationType.ENSURE_ROLES || curOperation.OperationType == CloudResourceOperationType.ENSURE_FIREWALL_RULES || curOperation.OperationType == CloudResourceOperationType.ENSURE_CORS_RULES)
                {
                    if (curOperation.Status != CloudResourceOperationState.DONE_SUCCESSFUL && curOperation.Status != CloudResourceOperationState.ABORTED && curOperation.Status != CloudResourceOperationState.ABANDONED)
                    {
                        //If very old, set to aborted and continue the search
                        if (curOperation.Updated.AddMinutes(2) < DateTime.UtcNow)
                        {
                            curOperation.Description += " (appeared to be failing)";
                            curOperation.Status       = CloudResourceOperationState.ABANDONED;
                            curOperation.Updated      = DateTime.UtcNow;
                            curOperation.UpdatedBy    = currentUser.UserName;
                            await _db.SaveChangesAsync();
                        }
                        else
                        {
                            return(curOperation);
                        }
                    }
                }

                if (curOperation.OperationType == CloudResourceOperationType.CREATE)
                {
                    if (curOperation.Status != CloudResourceOperationState.DONE_SUCCESSFUL && curOperation.Status != CloudResourceOperationState.ABORTED && curOperation.Status != CloudResourceOperationState.ABANDONED)
                    {
                        return(curOperation);
                    }
                }

                mostRecentOperation = false;
            }

            return(null);
        }
예제 #31
0
 public static CloudResource CreateCloudResource(string resourceProviderNamespace)
 {
     CloudResource cloudResource = new CloudResource();
     cloudResource.ResourceProviderNamespace = resourceProviderNamespace;
     return cloudResource;
 }