/// <summary>
        /// Starts the migration batch in Exchange Online.
        /// </summary>
        /// <param name="entity">An instance of <see cref="MigrationBatchEntity"/> that represents the migration batch to start.</param>
        /// <returns>An instance of <see cref="Task"/> that represents the asynchronous operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="entity"/> is null.
        /// </exception>
        public async Task MigrationBatchStartAsync(MigrationBatchEntity entity)
        {
            Command command;
            CommandParameterCollection parameters;
            EnvironmentEntity          environment;
            PSCredential        credential;
            Uri                 connectionUri;
            WSManConnectionInfo connectionInfo;

            entity.AssertNotNull(nameof(entity));

            try
            {
                credential = new PSCredential(
                    service.Configuration.ExchangeOnlineUsername,
                    service.Configuration.ExchangeOnlinePassword.ToSecureString());

                environment = await service.Storage.GetEntityAsync <EnvironmentEntity>(
                    MigrationConstants.EnvironmentTableName,
                    entity.CustomerId,
                    entity.PartitionKey);

                connectionUri  = new Uri($"{MigrationConstants.ExchangeOnlineEndpoint}{environment.Organization}");
                connectionInfo = GetConnectionInfo(connectionUri, MigrationConstants.SchemaUri, credential);

                command = new Command("Start-MigrationBatch");

                parameters = new CommandParameterCollection
                {
                    { "Identity", entity.Name }
                };

                using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
                {
                    scriptManager.InvokeCommand(runspace, command, parameters);
                }

                entity.Started = true;
                await service.Storage.WriteToTableAsync(MigrationConstants.MigrationBatchTable, entity);
            }
            finally
            {
                connectionInfo = null;
                connectionUri  = null;
                credential     = null;
                parameters     = null;
            }
        }
        /// <summary>
        /// Get statistics for the specified migration batch.
        /// </summary>
        /// <param name="entity">An instance of <see cref="MigrationBatchEntity"/> that represents the migration batch</param>
        /// <returns>An instance of <see cref="Task"/> that represents the asynchronous operation.</returns>
        public async Task MigrationBatchStatisticsAsync(MigrationBatchEntity entity)
        {
            Command           command;
            List <Command>    commands;
            EnvironmentEntity environment;
            PSCredential      credential;
            Uri connectionUri;
            WSManConnectionInfo connectionInfo;

            entity.AssertNotNull(nameof(entity));

            try
            {
                credential = new PSCredential(
                    service.Configuration.ExchangeOnlineUsername,
                    service.Configuration.ExchangeOnlinePassword.ToSecureString());

                environment = await service.Storage.GetEntityAsync <EnvironmentEntity>(
                    MigrationConstants.EnvironmentTableName,
                    entity.CustomerId,
                    entity.PartitionKey);

                connectionUri  = new Uri($"{MigrationConstants.ExchangeOnlineEndpoint}{environment.Organization}");
                connectionInfo = GetConnectionInfo(connectionUri, MigrationConstants.SchemaUri, credential);

                commands = new List <Command>();

                command = new Command("Get-MigrationUser");
                command.Parameters.Add("BatchId", entity.Name);
                commands.Add(command);

                command = new Command("Get-MigrationUserStatistics");
                commands.Add(command);

                using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
                {
                    scriptManager.InvokeCommand(runspace, commands);
                }
            }
            finally
            {
                commands       = null;
                connectionInfo = null;
                connectionUri  = null;
                credential     = null;
            }
        }
Ejemplo n.º 3
0
        public async Task <MigrationBatchViewModel> CreateBatchAsync([FromBody] MigrationBatchViewModel batch)
        {
            Customer                    customer;
            CustomerPrincipal           principal;
            DateTime                    startTime;
            Dictionary <string, double> eventMetrics;
            Dictionary <string, string> eventProperties;
            List <MailboxEntity>        entries;
            MigrationBatchEntity        entity;
            string targetDeliveryDomain;

            batch.AssertNotNull(nameof(batch));

            try
            {
                startTime = DateTime.Now;
                principal = (CustomerPrincipal)HttpContext.Current.User;

                if (string.IsNullOrEmpty(batch.Id))
                {
                    batch.Id = Guid.NewGuid().ToString();
                }

                customer = await operations.GetCustomerAsync(principal.CustomerId);

                targetDeliveryDomain = $"{customer.CompanyProfile.Domain.Split('.')[0]}.{MigrationConstants.TargetDeliveryDomainSuffix}";

                entity = new MigrationBatchEntity(batch.EnvironmentId, batch.Id)
                {
                    CustomerId           = principal.CustomerId,
                    ETag                 = "*",
                    Name                 = batch.Name,
                    StartTime            = DateTime.Parse(batch.StartTime),
                    Started              = false,
                    TargetDeliveryDomain = targetDeliveryDomain
                };

                entries = batch.Mailboxes.Select(m => new MailboxEntity(batch.EnvironmentId, m.Guid)
                {
                    DisplayName        = m.DisplayName,
                    ETag               = "*",
                    Name               = m.Name,
                    MigrationBatchId   = batch.Id,
                    PrimarySmtpAddress = m.PrimarySmtpAddress,
                    SamAccountName     = m.SamAccountName,
                    UserPrincipalName  = m.UserPrincipalName
                }).ToList();

                await Service.Storage.WriteToTableAsync(MigrationConstants.MigrationBatchTable, entity);

                await Service.Storage.WriteBatchToTableAsync(MigrationConstants.MailboxTableName, entries);

                await Service.ServiceBus.WriteToQueueAsync(MigrationConstants.MigrationBatchQueueName, entity);

                // Capture the request for the customer summary for analysis.
                eventProperties = new Dictionary <string, string>
                {
                    { "Email", principal.Email },
                    { "EnvironmentId", batch.EnvironmentId },
                    { "MigrationBatchName", batch.Name },
                    { "PrincipalCustomerId", principal.CustomerId }
                };

                // Track the event measurements for analysis.
                eventMetrics = new Dictionary <string, double>
                {
                    { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
                    { "NumberOfMailboxes", batch.Mailboxes.Count }
                };

                Service.Telemetry.TrackEvent("/api/migrationbatch/create", eventProperties, eventMetrics);

                return(batch);
            }
            finally
            {
                entity          = null;
                eventMetrics    = null;
                eventProperties = null;
                principal       = null;
            }
        }
        /// <summary>
        /// Creates a new migration batch in Exchange Online.
        /// </summary>
        /// <param name="entity">An instance of <see cref="MigrationBatchEntity"/> that represents the new migration batch.</param>
        /// <returns>An instance of <see cref="Task"/> that represents the asynchronous operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="entity"/> is null.
        /// </exception>
        public async Task CreateMigrationBatchAsync(MigrationBatchEntity entity)
        {
            Command command;
            CommandParameterCollection parameters;
            EnvironmentEntity          environment;
            List <MailboxEntity>       entites;;
            PSCredential        credential;
            Uri                 connectionUri;
            WSManConnectionInfo connectionInfo;
            string              csvData;

            entity.AssertNotNull(nameof(entity));

            try
            {
                credential = new PSCredential(
                    service.Configuration.ExchangeOnlineUsername,
                    service.Configuration.ExchangeOnlinePassword.ToSecureString());

                environment = await service.Storage.GetEntityAsync <EnvironmentEntity>(
                    MigrationConstants.EnvironmentTableName,
                    entity.CustomerId,
                    entity.PartitionKey);

                connectionUri  = new Uri($"{MigrationConstants.ExchangeOnlineEndpoint}{environment.Organization}");
                connectionInfo = GetConnectionInfo(connectionUri, MigrationConstants.SchemaUri, credential);

                entites = await service.Storage.GetEntitiesAsync <MailboxEntity>(
                    MigrationConstants.MailboxTableName,
                    m => m.PartitionKey.Equals(environment.RowKey) &&
                    !string.IsNullOrEmpty(m.MigrationBatchId) &&
                    m.MigrationBatchId.Equals(entity.RowKey));

                csvData = entites.Aggregate(new StringBuilder("EmailAddress\n"),
                                            (sb, v) => sb.Append(v.PrimarySmtpAddress).Append("\n"),
                                            sb => { if (0 < sb.Length)
                                                    {
                                                        sb.Length--;
                                                    }
                                                    return(sb.ToString()); });

                command = new Command("New-MigrationBatch");

                parameters = new CommandParameterCollection
                {
                    { "CSVData", Encoding.ASCII.GetBytes(csvData) },
                    { "Name", entity.Name },
                    { "SourceEndpoint", environment.Name },
                    { "TargetDeliveryDomain", entity.TargetDeliveryDomain }
                };

                using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
                {
                    scriptManager.InvokeCommand(runspace, command, parameters);
                }
            }
            finally
            {
                connectionInfo = null;
                connectionUri  = null;
                credential     = null;
                parameters     = null;
            }
        }