public void ApplyConfiguration(OdsSqlConfiguration sqlConfiguration, CloudOdsDatabaseSecurityConfiguration securityConfiguration)
        {
            var databaseName = _cloudOdsDatabaseNameProvider.GetDatabaseName(securityConfiguration.TargetDatabase);

            RunSqlProcessOnDatabase(databaseName, sqlConfiguration, (connection, configuration) =>
            {
                CreateDatabaseRoles(sqlConfiguration, securityConfiguration);

                foreach (var user in securityConfiguration.Users)
                {
                    AddUserToDatabase(connection, user.UserCredential);
                    AddUserToRole(connection, user.UserCredential, user.Roles.ToArray());
                }
            });
        }
示例#2
0
        public async Task <ProductionApiProvisioningWarnings> Execute(CloudOdsInstance cloudOdsInstance)
        {
            var result = new ProductionApiProvisioningWarnings
            {
                ResolutionUrl = "https://portal.azure.com"
            };

            var warnings = new List <string>();

            using (var conn = _rawSqlConnectionService.GetDatabaseConnectionFromConfigFile(_cloudOdsDatabaseNameProvider.GetDatabaseName(CloudOdsDatabases.ProductionOds)))
            {
                var sqlPerformanceLevel = _azureDatabaseManagementService.GetDatabasePerformanceLevel(conn, CloudOdsDatabaseNames.ProductionOds);

                //we have to be careful here not to output a warning in case the user is not running against an Azure Sql instance, hence the validity check
                if (sqlPerformanceLevel.IsValid() && sqlPerformanceLevel < _expectedDatabasePerformanceLevel)
                {
                    warnings.Add($"Azure Sql performance tier '{_expectedDatabasePerformanceLevel.ServiceObjective}' or above is recommended");
                }
            }

            var cloudOdsApiOperationContext = new CloudOdsApiOperationContext(cloudOdsInstance, CloudOdsEnvironment.Production);
            var serverPerformanceLevel      = await _getAzureCloudOdsWebsitePerformanceLevelQuery.Execute(cloudOdsApiOperationContext);

            if (serverPerformanceLevel != null && serverPerformanceLevel < _expectedWebsitePerformanceLevel)
            {
                warnings.Add($"Azure Website performance tier '{_expectedWebsitePerformanceLevel.ServiceObjective}' or above is recommended");
            }

            result.Warnings = warnings;
            return(result);
        }
        public WorkflowResult ResetByCopyingTemplate(OdsSqlConfiguration sqlConfiguration, CloudOdsDatabases templateDatabase, CloudOdsDatabases copyToDatabase, CancellationToken cancellationToken)
        {
            AzurePerformanceLevel performanceLevel;
            var templateDatabaseName = _cloudOdsDatabaseNameProvider.GetDatabaseName(templateDatabase);
            var copyToDatabaseName   = _cloudOdsDatabaseNameProvider.GetDatabaseName(copyToDatabase);
            var masterDatabaseName   = _cloudOdsDatabaseNameProvider.GetDatabaseName(CloudOdsDatabases.Master);

            using (var connection = _rawSqlConnectionService.GetDatabaseConnectionWithAdminCredentials(sqlConfiguration, copyToDatabaseName))
            {
                performanceLevel = _azureDatabaseManagementService.GetDatabasePerformanceLevel(connection, copyToDatabaseName);
            }

            using (var connection = _rawSqlConnectionService.GetDatabaseConnectionWithAdminCredentials(sqlConfiguration, masterDatabaseName))
            {
                var now        = DateTime.UtcNow;
                var tempDbName = $"{copyToDatabaseName}_temp_{now:yyyyMMddHHmmss}";
                var oldDbName  = $"{copyToDatabaseName}_old_{now:yyyyMMddHHmmss}";

                _ddlSqlWorkflowManager = new DdlSqlWorkflowManager(connection, cancellationToken);

                _ddlSqlWorkflowManager.JobStarted    += () => OnStatusUpdated(GetStatus());
                _ddlSqlWorkflowManager.JobCompleted  += () => OnStatusUpdated(GetStatus());
                _ddlSqlWorkflowManager.StepStarted   += () => OnStatusUpdated(GetStatus());
                _ddlSqlWorkflowManager.StepCompleted += () => OnStatusUpdated(GetStatus());

                _ddlSqlWorkflowManager
                .SetWorkflowName($"Copy Azure database {templateDatabaseName} to {copyToDatabaseName}")
                .StartWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction =
                        conn =>
                    {
                        _azureDatabaseManagementService.CopyDatabase(conn, templateDatabaseName, tempDbName);
                        _azureDatabaseManagementService.EnsureCopyDatabaseCompleted(conn, tempDbName);
                    },
                    RollBackAction         = conn => _azureDatabaseManagementService.DropDatabase(conn, tempDbName), //delete the extra database copy
                    StatusMessage          = "Copying template database",
                    RollbackStatusMessage  = "Removing copy of template database",
                    FailureMessage         = $"Error trying to copy {templateDatabase.DisplayName} to new database",
                    RollbackFailureMessage = $"Error trying to remove temporary database '{tempDbName}'",
                }
                    ).ContinueWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction         = conn => _azureDatabaseManagementService.RenameDatabase(conn, copyToDatabaseName, oldDbName),
                    RollBackAction        = conn => _azureDatabaseManagementService.RenameDatabase(conn, oldDbName, copyToDatabaseName),
                    StatusMessage         = "Renaming old database",
                    RollbackStatusMessage = "Renaming old database",
                    FailureMessage        =
                        $"Error trying to rename old {copyToDatabase.DisplayName} database from '{copyToDatabaseName}' to '{oldDbName}' prior to removal",
                    RollbackFailureMessage =
                        $"Error trying to rename old {copyToDatabase.DisplayName} database '{oldDbName}' back to '{copyToDatabaseName}'"
                }
                    ).ContinueWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction  = conn => _azureDatabaseManagementService.RenameDatabase(conn, tempDbName, copyToDatabaseName),
                    RollBackAction = conn => { },
                    //worst case there's an extra DB online, but the old database is still online.  nothing to cleanup in this step as we'll delete the temp db further up the chain
                    StatusMessage         = "Renaming copied database",
                    RollbackStatusMessage = "",
                    FailureMessage        =
                        $"Error trying to rename new {copyToDatabase.DisplayName} database from '{tempDbName}' to '{copyToDatabaseName}'",
                    RollbackFailureMessage = ""
                }
                    ).ContinueWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction =
                        conn =>
                    {
                        var securityConfiguration =
                            _cloudOdsDatabaseSqlServerSecurityConfiguration.GetRuntimeConfiguration(sqlConfiguration)
                            .Where(d => d.TargetDatabase == copyToDatabase);

                        _cloudOdsSqlConfigurator.ApplyConfiguration(sqlConfiguration, securityConfiguration);
                    },
                    RollBackAction         = conn => { },
                    StatusMessage          = $"Resetting security on {copyToDatabaseName}",
                    RollbackStatusMessage  = "",
                    FailureMessage         = $"Error trying to re-create database logins in {copyToDatabaseName}",
                    RollbackFailureMessage = "",
                }
                    ).ContinueWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction  = conn => _azureDatabaseManagementService.UpdateDatabasePerformanceLevel(conn, copyToDatabaseName, performanceLevel),
                    RollBackAction = conn => { },
                    //scale up request failed, nothing to rollback
                    StatusMessage         = "Updating database performance level",
                    RollbackStatusMessage = "",
                    FailureMessage        =
                        $"Error trying to scale {copyToDatabase.DisplayName} database to correct performance level",
                    RollbackFailureMessage = ""
                }
                    ).ContinueWith(
                    new DdlSqlWorkflowStep
                {
                    ExecuteAction  = conn => _azureDatabaseManagementService.DropDatabase(conn, oldDbName),
                    RollBackAction = conn => { },
                    FailureMessage =
                        $"Error trying to remove database {oldDbName}.  You should remove this database manually in the Azure Portal to avoid incurring extra charges.",
                    StatusMessage          = "Deleting old database",
                    RollbackStatusMessage  = "",
                    RollbackFailureMessage = "",
                    RollbackPreviousSteps  = false
                                             //worst case there's an extra DB online, but the system is still operational, so there's nothing to rollback here
                }
                    );

                return(_ddlSqlWorkflowManager.Execute());
            }
        }