public override void ExecuteCmdlet() { if (ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) { correlationId = Guid.NewGuid(); WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); var context = AsAzureClientSession.Instance.Profile.Context; AsAzureClientSession.Instance.Login(context); WriteProgress(new ProgressRecord(0, "Sync-AzureAnalysisServicesInstance.", string.Format("Authenticating user for '{0}' environment.", context.Environment.Name))); var clusterResolveResult = ClusterResolve(context, serverName); var virtualServerName = clusterResolveResult.CoreServerName.Split(":".ToCharArray())[0]; if (!serverName.Equals(virtualServerName) && !clusterResolveResult.CoreServerName.EndsWith(":rw")) { throw new SynchronizationFailedException("Sync request can only be sent to the management endpoint"); } this.clusterResolveResult = clusterResolveResult; Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, clusterResolveResult.ClusterFQDN)); var accessToken = this.TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId, context.Environment.Name); ScaleOutServerDatabaseSyncDetails syncResult = null; try { WriteProgress(new ProgressRecord(0, "Sync-AzureAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", context.Environment.Name))); syncResult = SynchronizeDatabaseAsync(context, clusterBaseUri, Database, accessToken).GetAwaiter().GetResult(); } catch (AggregateException aex) { foreach (var innerException in aex.Flatten().InnerExceptions) { WriteExceptionError(innerException); } } catch (Exception ex) { WriteExceptionError(ex); } if (syncResult == null) { throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( this.clusterResolveResult.CoreServerName, correlationId, DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); } if (syncResult.SyncState != DatabaseSyncState.Completed) { var serializedDetails = JsonConvert.SerializeObject(syncResult); throw new SynchronizationFailedException(serializedDetails); } if (PassThru.IsPresent) { WriteObject(syncResult, true); } } }
/// <inheritdoc cref="AzurePSCmdlet.ExecuteCmdlet"/> public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) { return; } WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", DnsSafeHost))); correlationId = Guid.NewGuid(); Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); ScaleOutServerDatabaseSyncDetails syncResult = null; try { WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); syncResult = SynchronizeDatabaseAsync(clusterBaseUri, Database).GetAwaiter().GetResult(); } catch (AggregateException aex) { foreach (var innerException in aex.Flatten().InnerExceptions) { WriteExceptionError(innerException); } } catch (Exception ex) { WriteExceptionError(ex); } if (syncResult == null) { throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( ServerName, correlationId, DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); } if (syncResult.SyncState != DatabaseSyncState.Completed) { var serializedDetails = JsonConvert.SerializeObject(syncResult); throw new SynchronizationFailedException(serializedDetails); } if (PassThru.IsPresent) { WriteObject(syncResult, true); } }
/// <summary> /// Worker Method for the synchronize request. /// </summary> /// <param name="syncBaseUri">Base Uri for sync</param> /// <param name="databaseName">Database name</param> /// <returns></returns> private async Task <ScaleOutServerDatabaseSyncDetails> SynchronizeDatabaseAsync( Uri syncBaseUri, string databaseName) { Tuple <Uri, RetryConditionHeaderValue> pollingUrlAndRetryAfter = new Tuple <Uri, RetryConditionHeaderValue>(null, null); ScaleOutServerDatabaseSyncDetails syncResult = null; return(await Task.Run(async() => { var syncEndpoint = string.Format(AsAzureEndpoints.SynchronizeEndpointPathFormat, this.ServerName, databaseName); this.AsAzureDataplaneClient.ResetHttpClient(); using (var message = await AsAzureDataplaneClient.CallPostAsync(syncBaseUri, syncEndpoint, correlationId)) { this.syncRequestRootActivityId = message.Headers.Contains(RootActivityIdHeaderName) ? message.Headers.GetValues(RootActivityIdHeaderName).FirstOrDefault() : string.Empty; this.syncRequestTimeStamp = message.Headers.Contains(CurrentUtcDateHeaderName) ? message.Headers.GetValues(CurrentUtcDateHeaderName).FirstOrDefault() : string.Empty; if (message.StatusCode != HttpStatusCode.Accepted) { var timestampNow = DateTime.Now; // Return sync details with exception message as details return new ScaleOutServerDatabaseSyncDetails { CorrelationId = correlationId.ToString(), Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.PostSyncRequestFailureMessage.FormatInvariant( ServerName, this.syncRequestRootActivityId, this.syncRequestTimeStamp, await message.Content.ReadAsStringAsync()), UpdatedAt = timestampNow, StartedAt = timestampNow }; } pollingUrlAndRetryAfter = new Tuple <Uri, RetryConditionHeaderValue>(message.Headers.Location, message.Headers.RetryAfter); } Uri pollingUrl = pollingUrlAndRetryAfter.Item1; var retryAfter = pollingUrlAndRetryAfter.Item2; try { ScaleOutServerDatabaseSyncResult result = await this.PollSyncStatusWithRetryAsync( databaseName, pollingUrl, retryAfter.Delta ?? DefaultPollingInterval); syncResult = ScaleOutServerDatabaseSyncDetails.FromResult(result, correlationId.ToString()); } catch (Exception e) { var timestampNow = DateTime.Now; // Append exception message to sync details and return syncResult = new ScaleOutServerDatabaseSyncDetails { CorrelationId = correlationId.ToString(), Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.SyncASPollStatusFailureMessage.FormatInvariant( ServerName, string.Empty, timestampNow.ToString(CultureInfo.InvariantCulture), string.Format(e.StackTrace)), UpdatedAt = timestampNow, StartedAt = timestampNow }; } return syncResult; })); }
/// <summary> /// Worker Method for the synchronize request. /// </summary> /// <param name="context">The AS azure context</param> /// <param name="syncBaseUri">Base Uri for sync</param> /// <param name="databaseName">Database name</param> /// <param name="accessToken">Access token</param> /// <param name="maxNumberOfAttempts">Max number of retries for get command</param> /// <returns></returns> private async Task <ScaleOutServerDatabaseSyncDetails> SynchronizeDatabaseAsync( AsAzureContext context, Uri syncBaseUri, string databaseName, string accessToken) { Tuple <Uri, RetryConditionHeaderValue> pollingUrlAndRetryAfter = new Tuple <Uri, RetryConditionHeaderValue>(null, null); ScaleOutServerDatabaseSyncDetails syncResult = null; return(await Task.Run(async() => { try { var synchronize = string.Format((string)context.Environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.SyncEndpoint], this.serverName, databaseName); this.AsAzureHttpClient.resetHttpClient(); using (var message = await AsAzureHttpClient.CallPostAsync( syncBaseUri, synchronize, accessToken, correlationId, null)) { this.syncRequestRootActivityId = message.Headers.Contains(RootActivityIdHeaderName) ? message.Headers.GetValues(RootActivityIdHeaderName).FirstOrDefault() : string.Empty; this.syncRequestTimeStamp = message.Headers.Contains(CurrentUtcDateHeaderName) ? message.Headers.GetValues(CurrentUtcDateHeaderName).FirstOrDefault() : string.Empty; message.EnsureSuccessStatusCode(); if (message.StatusCode != HttpStatusCode.Accepted) { var timestampNow = DateTime.Now; syncResult = new ScaleOutServerDatabaseSyncDetails { CorrelationId = correlationId.ToString(), Database = databaseName, SyncState = DatabaseSyncState.Completed, Details = string.Format("Http status code: {0}. Nothing readonly instances found to replicate databases.", message.StatusCode), UpdatedAt = timestampNow, StartedAt = timestampNow }; return syncResult; } pollingUrlAndRetryAfter = new Tuple <Uri, RetryConditionHeaderValue>(message.Headers.Location, message.Headers.RetryAfter); } } catch (Exception e) { var timestampNow = DateTime.Now; // Return sync details with exception message as details return new ScaleOutServerDatabaseSyncDetails { CorrelationId = correlationId.ToString(), Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.PostSyncRequestFailureMessage.FormatInvariant( this.clusterResolveResult.CoreServerName, this.syncRequestRootActivityId, this.syncRequestTimeStamp, string.Format(e.Message)), UpdatedAt = timestampNow, StartedAt = timestampNow }; } Uri pollingUrl = pollingUrlAndRetryAfter.Item1; var retryAfter = pollingUrlAndRetryAfter.Item2; try { ScaleOutServerDatabaseSyncResult result = await this.PollSyncStatusWithRetryAsync( databaseName, accessToken, pollingUrl, retryAfter.Delta ?? DefaultPollingInterval); syncResult = ScaleOutServerDatabaseSyncDetails.FromResult(result, correlationId.ToString()); } catch (Exception e) { var timestampNow = DateTime.Now; // Append exception message to sync details and return syncResult = new ScaleOutServerDatabaseSyncDetails { CorrelationId = correlationId.ToString(), Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.SyncASPollStatusFailureMessage.FormatInvariant( serverName, string.Empty, timestampNow.ToString(CultureInfo.InvariantCulture), string.Format(e.StackTrace)), UpdatedAt = timestampNow, StartedAt = timestampNow }; } return syncResult; })); }