/** * Azure Event Hub sample for managing geo disaster recovery pairing - * - Create two event hub namespaces * - Create a pairing between two namespaces * - Create an event hub in the primary namespace and retrieve it from the secondary namespace * - Retrieve the pairing connection string * - Fail over so that secondary namespace become primary. */ public static void RunSample(IAzure azure) { Region region = Region.USEast; string rgName = SdkContext.RandomResourceName("rgeh", 15); string primaryNamespaceName = SdkContext.RandomResourceName("ns", 15); string secondaryNamespaceName = SdkContext.RandomResourceName("ns", 15); string geoDRName = SdkContext.RandomResourceName("geodr", 14); string eventHubName = SdkContext.RandomResourceName("eh", 14); bool isFailOverSucceeded = false; IEventHubDisasterRecoveryPairing pairing = null; try { //============================================================ // Create resource group for the namespaces and recovery pairings // IResourceGroup resourceGroup = azure.ResourceGroups.Define(rgName) .WithRegion(Region.USSouthCentral) .Create(); Utilities.Log($"Creating primary event hub namespace {primaryNamespaceName}"); IEventHubNamespace primaryNamespace = azure.EventHubNamespaces .Define(primaryNamespaceName) .WithRegion(Region.USSouthCentral) .WithExistingResourceGroup(resourceGroup) .Create(); Utilities.Log("Primary event hub namespace created"); Utilities.Print(primaryNamespace); Utilities.Log($"Creating secondary event hub namespace {primaryNamespaceName}"); IEventHubNamespace secondaryNamespace = azure.EventHubNamespaces .Define(secondaryNamespaceName) .WithRegion(Region.USNorthCentral) .WithExistingResourceGroup(resourceGroup) .Create(); Utilities.Log("Secondary event hub namespace created"); Utilities.Print(secondaryNamespace); //============================================================ // Create primary and secondary namespaces and recovery pairing // Utilities.Log($"Creating geo-disaster recovery pairing {geoDRName}"); pairing = azure.EventHubDisasterRecoveryPairings .Define(geoDRName) .WithExistingPrimaryNamespace(primaryNamespace) .WithExistingSecondaryNamespace(secondaryNamespace) .Create(); while (pairing.ProvisioningState != ProvisioningStateDR.Succeeded) { pairing = pairing.Refresh(); SdkContext.DelayProvider.Delay(15 * 1000); if (pairing.ProvisioningState == ProvisioningStateDR.Failed) { throw new Exception("Provisioning state of the pairing is FAILED"); } } Utilities.Log($"Created geo-disaster recovery pairing {geoDRName}"); Utilities.Print(pairing); //============================================================ // Create an event hub and consumer group in primary namespace // Utilities.Log("Creating an event hub and consumer group in primary namespace"); IEventHub eventHubInPrimaryNamespace = azure.EventHubs .Define(eventHubName) .WithExistingNamespace(primaryNamespace) .WithNewConsumerGroup("consumerGrp1") .Create(); Utilities.Log("Created event hub and consumer group in primary namespace"); Utilities.Print(eventHubInPrimaryNamespace); Utilities.Log("Waiting for 60 seconds to allow metadata to sync across primary and secondary"); SdkContext.DelayProvider.Delay(60 * 1000); // Wait for syncing to finish Utilities.Log("Retrieving the event hubs in secondary namespace"); IEventHub eventHubInSecondaryNamespace = azure.EventHubs.GetByName(rgName, secondaryNamespaceName, eventHubName); Utilities.Log("Retrieved the event hubs in secondary namespace"); Utilities.Print(eventHubInSecondaryNamespace); //============================================================ // Retrieving the connection string // var rules = pairing.ListAuthorizationRules(); foreach (IDisasterRecoveryPairingAuthorizationRule rule in rules) { IDisasterRecoveryPairingAuthorizationKey key = rule.GetKeys(); Utilities.Print(key); } Utilities.Log("Initiating fail over"); pairing.FailOver(); isFailOverSucceeded = true; Utilities.Log("Fail over initiated"); } finally { try { try { // It is necessary to break pairing before deleting resource group // if (pairing != null && !isFailOverSucceeded) { pairing.BreakPairing(); } } catch (Exception ex) { Utilities.Log("Pairing breaking failed:" + ex.Message); } azure.ResourceGroups.BeginDeleteByName(rgName); } catch (NullReferenceException) { Utilities.Log("Did not create any resources in Azure. No clean up is necessary"); } catch (Exception ex) { Utilities.Log(ex); } } }
public void CanManageGeoDisasterRecoveryPairing() { using (var context = FluentMockContext.Start(GetType().FullName)) { var region = Region.USEast; var groupName = TestUtilities.GenerateName("rgns"); var geodrName = TestUtilities.GenerateName("geodr"); var namespaceName1 = TestUtilities.GenerateName("ns111"); var namespaceName2 = TestUtilities.GenerateName("ns222"); var azure = TestHelper.CreateRollupClient(); try { IEventHubNamespace primaryNamespace = azure.EventHubNamespaces .Define(namespaceName1) .WithRegion(Region.USSouthCentral) .WithNewResourceGroup(groupName) .Create(); IEventHubNamespace secondaryNamespace = azure.EventHubNamespaces .Define(namespaceName2) .WithRegion(Region.USNorthCentral) .WithExistingResourceGroup(groupName) .Create(); Exception exception = null; Exception breakingFailed = null; IEventHubDisasterRecoveryPairing pairing = null; try { pairing = azure.EventHubDisasterRecoveryPairings .Define(geodrName) .WithExistingPrimaryNamespace(primaryNamespace) .WithExistingSecondaryNamespace(secondaryNamespace) .Create(); while (pairing.ProvisioningState != ProvisioningStateDR.Succeeded) { pairing = pairing.Refresh(); SdkContext.DelayProvider.Delay(15 * 1000); if (pairing.ProvisioningState == ProvisioningStateDR.Failed) { Assert.True(false, "Provisioning state of the pairing is FAILED"); } } Assert.Equal(pairing.Name, geodrName, ignoreCase: true); Assert.Equal(pairing.PrimaryNamespaceResourceGroupName, groupName, ignoreCase: true); Assert.Equal(pairing.PrimaryNamespaceName, primaryNamespace.Name, ignoreCase: true); Assert.Equal(pairing.SecondaryNamespaceId, secondaryNamespace.Id, ignoreCase: true); var rules = pairing.ListAuthorizationRules(); Assert.True(rules.Count() > 0); foreach (IDisasterRecoveryPairingAuthorizationRule rule in rules) { IDisasterRecoveryPairingAuthorizationKey keys = rule.GetKeys(); Assert.NotNull(keys.AliasPrimaryConnectionString); Assert.NotNull(keys.AliasPrimaryConnectionString); Assert.NotNull(keys.PrimaryKey); Assert.NotNull(keys.SecondaryKey); } IEventHubDisasterRecoveryPairings pairingsCol = azure.EventHubDisasterRecoveryPairings; var pairings = pairingsCol .ListByNamespace(primaryNamespace.ResourceGroupName, primaryNamespace.Name); Assert.True(pairings.Count() > 0); bool found = false; foreach (IEventHubDisasterRecoveryPairing pairing1 in pairings) { if (pairing1.Name.Equals(pairing.Name, StringComparison.OrdinalIgnoreCase)) { found = true; Assert.Equal(pairing1.PrimaryNamespaceResourceGroupName, groupName); Assert.Equal(pairing1.PrimaryNamespaceName, primaryNamespace.Name); Assert.Equal(pairing1.SecondaryNamespaceId, secondaryNamespace.Id); } } Assert.True(found); } catch (Exception ex) { exception = ex; } finally { if (exception != null && pairing != null) { // Resource group cannot be deleted if the pairing-replication is // (backgroud work by RP) progress so pairing must forcefully break. try { pairing.BreakPairing(); } catch (Exception ex) { breakingFailed = ex; } } } if (exception != null && breakingFailed != null) { AggregateException cex = new AggregateException(exception, breakingFailed); throw cex; } if (exception != null) { throw exception; } if (breakingFailed != null) { throw breakingFailed; } pairing.Refresh(); pairing.FailOver(); } finally { try { azure.ResourceGroups.BeginDeleteByName(groupName); } catch { } } } }