aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml.cs
blob: 269324f43085e9fe2e0c22e586e14e17bb193f7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Tango.BL.Entities;
using Tango.DragAndDrop;
using Tango.MachineStudio.UsersAndRoles.ViewModels;
using static Tango.SharedUI.Controls.MultiTransitionControl;
using static Tango.SharedUI.Controls.NavigationControl;

namespace Tango.MachineStudio.UsersAndRoles.Views
{
    /// <summary>
    /// Interaction logic for UserManagementView.xaml
    /// </summary>
    public partial class UserManagementView : UserControl, INavigationView
    {
        private MainViewVM _vm;
        
        public DraggingSurface DraggingSurface
        {
            get { return (DraggingSurface)GetValue(DraggingSurfaceProperty); }
            set { SetValue(DraggingSurfaceProperty, value); }
        }
        public static readonly DependencyProperty DraggingSurfaceProperty =
            DependencyProperty.Register("DraggingSurface", typeof(DraggingSurface), typeof(UserManagementView), new PropertyMetadata(null));

        public UserManagementView()
        {
            InitializeComponent();
            DraggingSurface = dragSurface;
            Loaded += (_, __) => _vm = DataContext as MainViewVM;
        }

        private void OnDropRole(object sender, DropEventArgs e)
        {
            if (e.Draggable.DataContext is Role)
            {
                _vm.OnDropRole(e.Draggable.DataContext as Role);
            }
        }

        public void OnNavigatedTo()
        {
            address_auto.Text = "";
        }

        public void OnNavigatedFrom()
        {
            
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ionic.Zip;
using Microsoft.Azure;
using Microsoft.Azure.Management.AppService.Fluent;
using Microsoft.Azure.Management.AppService.Fluent.Models;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.Monitor.Fluent;
using Microsoft.Azure.Management.RecoveryServices.Backup;
using Microsoft.Azure.Management.Sql.Fluent.Models;
using Microsoft.WindowsAzure.Storage;
using Tango.AzureUtils.ActiveDirectory;
using Tango.AzureUtils.Database;
using Tango.AzureUtils.Deployment;
using Tango.AzureUtils.FTP;
using Tango.AzureUtils.Storage;
using Tango.BL;
using Tango.Core;
using Tango.Core.DB;
using Tango.PMR.FirmwareUpgrade;

namespace Tango.AzureUtils.Environment
{
    public class EnvironmentManager : AzureUtilsComponentBase
    {
        private ActiveDirectoryManager _adManager;
        private DeploymentManager _deploymentManager;
        private DatabaseManager _databaseManager;
        private StorageManager _storageManager;
        private FtpManager _ftpManager;

        public EnvironmentManager(IAzure azure) : base(azure)
        {
            _adManager = CreateManager<ActiveDirectoryManager>();
            _deploymentManager = CreateManager<DeploymentManager>();
            _databaseManager = CreateManager<DatabaseManager>();
            _storageManager = CreateManager<StorageManager>();
            _ftpManager = CreateManager<FtpManager>();
        }

        #region Creation

        public async Task<IDeploymentSlot> CreateEnvironment(IWebApp app, IDeploymentSlot sourceSlot, String name, CreateEnvironmentConfiguration config)
        {
            OnProgress(AzureUtilsStage.Environment, $"Retrieving '{sourceSlot.Name}' settings...");

            var sourceSettings = await sourceSlot.GetMachineServiceSettingsAsync();
            var targetSettings = EnvironmentSettings.FromSlotName(app.Name, name);

            if (!config.IgnoreExistingSlot)
            {
                var deploymentSlots = await app.DeploymentSlots.ListAsync();
                if (deploymentSlots.ToList().Exists(x => x.Name.ToLower() == targetSettings.SLOT_NAME.ToLower()))
                {
                    throw new InvalidOperationException($"Deployment slot '{targetSettings.SLOT_NAME}' already exists.");
                }
            }

            //Add Environment Group
            if (config.CreateEnvironmentGroup)
            {
                await _adManager.Authenticate(config.Email, config.Password);

                if (!await _adManager.IsGroupExists(targetSettings.ENVIRONMENT_GROUP))
                {
                    await _adManager.AddGroup(targetSettings.ENVIRONMENT_GROUP);

                    if (config.AddEnvironmentGroupAdminUser)
                    {
                        await _adManager.AddUserToGroup(targetSettings.ENVIRONMENT_GROUP, config.Email);
                    }
                }
                else
                {
                    await RequestConfirmation($"Environment group '{targetSettings.ENVIRONMENT_GROUP}' already exists. Do you wish to continue?");
                }
            }


            //Add Deployment Slot
            var slot = await _deploymentManager.GetDeploymentSlot(app, targetSettings.SLOT_NAME);

            if (config.CreateDeploymentSlot)
            {
                if (slot == null)
                {
                    slot = await _deploymentManager.CreateDeploymentSlot(app, sourceSlot, name);
                }
                else
                {
                    await RequestConfirmation($"Deployment slot '{targetSettings.SLOT_NAME}' already exists. Do you wish to continue.");
                }
            }

            //Add Database
            if (config.CreateDatabase)
            {
                if (!await _databaseManager.IsDatabaseExists("twine", targetSettings.DB_CATALOG))
                {
                    await _databaseManager.AddDatabase("twine", targetSettings.DB_CATALOG);
                }
                else
                {
                    await RequestConfirmation($"Database '{targetSettings.DB_CATALOG}' already exists. Do you wish to continue?");
                }
            }

            //Add permissions for environment group on database
            if (config.AddDatabasePermissionsForEnvironmentGroup)
            {
                try
                {
                    await _databaseManager.AddEnvironmentGroupPermissions(sourceSettings.DB_ADDRESS, targetSettings.DB_CATALOG, targetSettings.ENVIRONMENT_GROUP, config.Email, config.Password);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Error creating/adding permissions for environment group '{targetSettings.ENVIRONMENT_GROUP}' on database.\n{ex.FlattenMessage()}\n\nDo you wish to continue?");
                }
            }

            //Create backup user
            if (config.CreateDatabaseBackupUser)
            {
                try
                {
                    await _databaseManager.AddBackupUser(sourceSettings.DB_ADDRESS, targetSettings.DB_CATALOG, sourceSettings.DB_USER_NAME, sourceSettings.DB_PASSWORD);
                }
                catch (Exception ex)
                {

                    await RequestConfirmation($"Error creating/adding permissions for BackupUser on database.\n{ex.FlattenMessage()}\n\nDo you wish to continue?");
                }
            }

            //Create Tango web application user
            if (config.CreateDatabaseTangoWebApplicationUser)
            {
                try
                {
                    await _databaseManager.AddTangoWebAppUser(sourceSettings.DB_ADDRESS, targetSettings.DB_CATALOG, sourceSettings.DB_USER_NAME, sourceSettings.DB_PASSWORD);
                }
                catch (Exception ex)
                {

                    await RequestConfirmation($"Error creating/adding permissions for Tango web application on database.\n{ex.FlattenMessage()}\n\nDo you wish to continue?");
                }
            }

            //Synchronize Schema
            if (config.SynchronizeDatabaseSchema)
            {
                await _databaseManager.OpenSQLExaminerSchema(sourceSlot, slot);
                await RequestConfirmation($"Please synchronize the database schema between '{sourceSettings.DB_CATALOG}' and '{targetSettings.DB_CATALOG}'.\nPlease confirm in order to continue.");
                OnProgress(AzureUtilsStage.Environment, $"Waiting for database schema synchronization...");
            }


            //Synchronize Data
            if (config.SynchronizeDatabaseData)
            {
                await _databaseManager.OpenSQLExaminerData(sourceSlot, slot, true);
                await RequestConfirmation($"Please synchronize the database static collections between '{sourceSettings.DB_CATALOG}' and '{targetSettings.DB_CATALOG}'.\nPlease confirm in order to continue.");
                OnProgress(AzureUtilsStage.Environment, $"Waiting for database static collections synchronization...");
            }

            await _storageManager.Connect(sourceSettings.STORAGE_ACCOUNT);

            //Add Storage Containers
            if (config.CreateStorageContainers)
            {
                await _storageManager.CreateContainer(targetSettings.MACHINE_STUDIO_VERSIONS_CONTAINER);
                await _storageManager.CreateContainer(targetSettings.TANGO_VERSIONS_CONTAINER);
            }

            if (config.CopyStorageBlobs)
            {
                //Add Machine Studio storage versions.
                try
                {
                    await _storageManager.ValidateMachineStudioStorageUpgrade(sourceSlot, slot);
                    await _storageManager.UpgradeMachineStudioStorage(sourceSlot, slot);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading machine studio storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }

                //Add PPC storage versions.
                try
                {
                    await _storageManager.ValidatePPCStorageUpgrade(sourceSlot, slot);
                    await _storageManager.UpgradePPCStorage(sourceSlot, slot);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading PPC storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Copy Website files.
            if (config.CopyMachineServiceFiles)
            {
                await _ftpManager.CopyAppFiles(sourceSlot, slot);
            }

            //Configure Diagnostics logging.
            if (config.ConfigureMachineServiceLogging)
            {
                OnProgress(AzureUtilsStage.Environment, "Configuring diagnostics logging...");

                var diagnosticsContainer = await _storageManager.CreateContainer(targetSettings.MACHINE_SERVICE_LOGS_CONTAINER);
                String diagnosticsContainerSasUrl = diagnosticsContainer.GetSharedAccessUrl();

                await Azure.WebApps.Inner.UpdateDiagnosticLogsConfigSlotAsync(app.ResourceGroupName, app.Name, new Microsoft.Azure.Management.AppService.Fluent.Models.SiteLogsConfigInner()
                {
                    ApplicationLogs = new Microsoft.Azure.Management.AppService.Fluent.Models.ApplicationLogsConfig()
                    {
                        AzureBlobStorage = new Microsoft.Azure.Management.AppService.Fluent.Models.AzureBlobStorageApplicationLogsConfig()
                        {
                            Level = sourceSlot.DiagnosticLogsConfig.ApplicationLoggingStorageBlobLogLevel,
                            RetentionInDays = sourceSlot.DiagnosticLogsConfig.ApplicationLoggingStorageBlobRetentionDays,
                            SasUrl = diagnosticsContainerSasUrl,
                        }
                    },
                    DetailedErrorMessages = new Microsoft.Azure.Management.AppService.Fluent.Models.EnabledConfig(true),
                }, slot.Name);
            }

            //Configure Cloud Backup.
            if (config.ConfigureCloudBackup)
            {
                OnProgress(AzureUtilsStage.Environment, "Configuring cloud backup...");

                var sourceConfig = await Azure.WebApps.Inner.GetBackupConfigurationSlotAsync(app.ResourceGroupName, app.Name, sourceSlot.Name);

                var backupContainer = await _storageManager.CreateContainer(targetSettings.MACHINE_SERVICE_BACKUPS_CONTAINER);

                var connectionStrings = await slot.GetConnectionStringsAsync();
                var databaseConnectionString = connectionStrings.SingleOrDefault(x => x.Value.Name == targetSettings.DB_CATALOG);

                await Azure.WebApps.Inner.UpdateBackupConfigurationSlotAsync(app.ResourceGroupName, app.Name, new Microsoft.Azure.Management.AppService.Fluent.Models.BackupRequestInner()
                {
                    BackupSchedule = sourceConfig.BackupSchedule,
                    Enabled = sourceConfig.Enabled,
                    StorageAccountUrl = backupContainer.GetSharedAccessUrl(),
                    Databases = new List<DatabaseBackupSetting>()
                    {
                          new DatabaseBackupSetting()
                          {
                               DatabaseType = DatabaseType.SqlAzure,
                               ConnectionStringName = targetSettings.DB_CATALOG,
                               ConnectionString = databaseConnectionString.Value.Value,
                          }
                    }
                }, slot.Name);
            }

            //Restart slot.
            OnProgress(AzureUtilsStage.Environment, "Restarting deployment slot...");
            await slot.RestartAsync();

            OnCompleted("Environment created successfully.");

            return slot;
        }

        #endregion

        #region Upgrade

        public async Task UpgradeEnvironment(IWebAppBase sourceApp, IWebAppBase targetApp, UpgradeEnvironmentConfiguration config)
        {
            await ValidateEnvironmentUpgrade(sourceApp, targetApp, config);

            OnProgress(AzureUtilsStage.Environment, $"Retrieving '{sourceApp.Name}' settings...");
            var sourceSettings = await sourceApp.GetMachineServiceSettingsAsync();
            var targetSettings = await targetApp.GetMachineServiceSettingsAsync();


            //Synchronize Schema
            if (config.SynchronizeDatabaseSchema)
            {
                await _databaseManager.OpenSQLExaminerSchema(sourceApp, targetApp);
                await RequestConfirmation($"Please synchronize the database schema between '{sourceSettings.DB_CATALOG}' and '{targetSettings.DB_CATALOG}'.\nPlease confirm in order to continue.");
                OnProgress(AzureUtilsStage.Environment, $"Waiting for database schema synchronization...");
            }

            //Synchronize Data
            if (config.SynchronizeDatabaseData)
            {
                await _databaseManager.OpenSQLExaminerData(sourceApp, targetApp);
                await RequestConfirmation($"Please synchronize the database static collections between '{sourceSettings.DB_CATALOG}' and '{targetSettings.DB_CATALOG}'.\nPlease confirm in order to continue.");
                OnProgress(AzureUtilsStage.Environment, $"Waiting for database static collections synchronization...");
            }

            //Add Machine Studio storage versions.
            if (config.CopyMachineStudioStorageBlobs)
            {
                try
                {
                    await _storageManager.ValidateMachineStudioStorageUpgrade(sourceApp, targetApp);
                    await _storageManager.UpgradeMachineStudioStorage(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading machine studio storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Add PPC storage versions.
            if (config.CopyPPCStorageBlobs)
            {
                try
                {
                    await _storageManager.ValidatePPCStorageUpgrade(sourceApp, targetApp);
                    await _storageManager.UpgradePPCStorage(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading PPC storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Add FSE storage versions.
            if (config.CopyFSEStorageBlobs)
            {
                try
                {
                    await _storageManager.ValidateFSEStorageUpgrade(sourceApp, targetApp);
                    await _storageManager.UpgradeFSEStorage(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading FSE storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Upgrade machine studio database version.
            if (config.UpgradeMachineStudioDatabaseVersion)
            {
                try
                {
                    await _databaseManager.ValidateMachineStudioDatabaseUpgrade(sourceApp, targetApp);
                    await _databaseManager.UpgradeMachineStudioVersion(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading Machine Studio database versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Upgrade PPC database version.
            if (config.UpgradePPCDatabaseVersion)
            {
                try
                {
                    await _databaseManager.ValidatePPCDatabaseUpgrade(sourceApp, targetApp);
                    await _databaseManager.UpgradePPCVersion(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading PPC database versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            //Upgrade FSE database version.
            if (config.UpgradeFSEDatabaseVersion)
            {
                try
                {
                    await _databaseManager.ValidateFSEDatabaseUpgrade(sourceApp, targetApp);
                    await _databaseManager.UpgradeFSEVersion(sourceApp, targetApp);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Issues encountered with upgrading FSE database versions.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }


            //Copy Website files.
            if (config.CopyMachineServiceFiles)
            {
                await _ftpManager.CopyAppFiles(sourceApp, targetApp);
            }

            //Restart slot.
            OnProgress(AzureUtilsStage.Environment, "Restarting traget deployment slot...");
            await targetApp.RestartAsync();

            OnCompleted("Environment upgraded successfully.");
        }

        public async Task ValidateEnvironmentUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp, UpgradeEnvironmentConfiguration config)
        {
            if (sourceApp == targetApp || sourceApp.Name == targetApp.Name)
            {
                throw new InvalidOperationException("Source slot and target slot are identical.");
            }

            //Add Machine Studio storage versions.
            if (config.CopyMachineStudioStorageBlobs)
            {
                await _storageManager.ValidateMachineStudioStorageUpgrade(sourceApp, targetApp);
            }

            //Add PPC storage versions.
            if (config.CopyPPCStorageBlobs)
            {
                await _storageManager.ValidatePPCStorageUpgrade(sourceApp, targetApp);
            }

            //Add FSE storage versions.
            if (config.CopyFSEStorageBlobs)
            {
                await _storageManager.ValidateFSEStorageUpgrade(sourceApp, targetApp);
            }

            //Upgrade machine studio database version.
            if (config.UpgradeMachineStudioDatabaseVersion)
            {
                await _databaseManager.ValidateMachineStudioDatabaseUpgrade(sourceApp, targetApp);
            }

            //Upgrade PPC database version.
            if (config.UpgradePPCDatabaseVersion)
            {
                await _databaseManager.ValidatePPCDatabaseUpgrade(sourceApp, targetApp);
            }

            //Upgrade FSE database version.
            if (config.UpgradeFSEDatabaseVersion)
            {
                await _databaseManager.ValidateFSEDatabaseUpgrade(sourceApp, targetApp);
            }
        }

        #endregion

        #region Removal

        public async Task RemoveEnvironment(IDeploymentSlot slot, String slotName, RemoveEnvironmentConfiguration config)
        {
            OnProgress(AzureUtilsStage.Environment, $"Retrieving '{slot.Name}' settings...");

            var settings = await slot.GetMachineServiceSettingsAsync();

            if (settings.DEPLOYMENT_SLOT != slotName)
            {
                throw new ValidationException("The specified slot name confirmation does not match the specified slot instance.");
            }

            var envSettings = EnvironmentSettings.FromSlotName(slot.Parent.Name, settings.DEPLOYMENT_SLOT);

            //Remove Environment Group
            if (config.RemoveEnvironmentGroup)
            {
                await _adManager.Authenticate(config.Email, config.Password);

                if (await _adManager.IsGroupExists(settings.ENVIRONMENT_GROUP))
                {
                    await _adManager.RemoveGroup(settings.ENVIRONMENT_GROUP);
                }
                else
                {
                    await RequestConfirmation($"Environment group '{settings.ENVIRONMENT_GROUP}' does not exist. Do you wish to continue?");
                }
            }

            //Remove Deployment Slot
            if (config.RemoveDeploymentSlot)
            {
                try
                {
                    await _deploymentManager.RemoveDeploymentSlot(slot);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Encountered an error while trying to remove deployment slot.\n{ex.FlattenMessage()}\nDo you wish to continue.");
                }
            }

            await _storageManager.Connect(settings.STORAGE_ACCOUNT);

            //Remove Storage Containers
            if (config.RemoveStorageContainers)
            {
                await _storageManager.RemoveContainer(settings.MACHINE_STUDIO_VERSIONS_CONTAINER);
                await _storageManager.RemoveContainer(settings.TANGO_VERSIONS_CONTAINER);
                await _storageManager.RemoveContainer(envSettings.MACHINE_SERVICE_LOGS_CONTAINER);
                await _storageManager.RemoveContainer(envSettings.MACHINE_SERVICE_BACKUPS_CONTAINER);
            }

            //Remove Database
            if (config.RemoveDatabase)
            {
                await _databaseManager.RemoveDatabase("twine", settings.DB_CATALOG);
            }

            OnCompleted("Environment removed successfully.");
        }

        #endregion

        #region Rollback

        public async Task RollbackEnvironment(IWebAppBase app, RollbackEnvironmentConfiguration config)
        {
            OnProgress(AzureUtilsStage.Environment, $"Retrieving settings for '{app.Name}'...");

            var settings = await app.GetMachineServiceSettingsAsync();
            await _storageManager.Connect(settings.STORAGE_ACCOUNT);

            if (config.RollbackMachineStudio)
            {
                try
                {
                    await _storageManager.DowngradeMachineStudioStorage(app);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Error occurred while trying to remove machine studio storage blobs.\n{ex.FlattenMessage()}\nDo you wish to continue?");    
                }

                try
                {
                    await _databaseManager.DowngradeMachineStudioVersion(app);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Error occurred while trying to remove machine studio database version.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            if (config.RollbackPPC)
            {
                try
                {
                    await _storageManager.DowngradePPCStorage(app);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Error occurred while trying to remove PPC storage blobs.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }

                try
                {
                    await _databaseManager.DowngradePPCVersion(app);
                }
                catch (Exception ex)
                {
                    await RequestConfirmation($"Error occurred while trying to remove PPC database version.\n{ex.FlattenMessage()}\nDo you wish to continue?");
                }
            }

            OnCompleted("Environment rollback completed successfully.");
        }

        #endregion
    }
}