//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 async Task RunSample(TokenCredential credential) { string region = "eastus"; string subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); string rgName = Utilities.RandomResourceName("rgeh", 15); string primaryNamespaceName = Utilities.RandomResourceName("ns", 15); string secondaryNamespaceName = Utilities.RandomResourceName("ns", 15); string geoDRName = Utilities.RandomResourceName("geodr", 14); string eventHubName = Utilities.RandomResourceName("eh", 14); bool isFailOverSucceeded = false; ArmDisasterRecovery pairing = null; var eventHubsManagementClient = new EventHubsManagementClient(subscriptionId, credential); var namespaces = eventHubsManagementClient.Namespaces; var eventHubs = eventHubsManagementClient.EventHubs; var consumerGroups = eventHubsManagementClient.ConsumerGroups; var disasterRecoveryConfigs = eventHubsManagementClient.DisasterRecoveryConfigs; try { await ResourceGroupHelper.CreateOrUpdateResourceGroup(rgName, region); // Create resource group for the namespaces and recovery pairings Utilities.Log($"Creating primary event hub namespace {primaryNamespaceName}"); var primaryResult = await namespaces.StartCreateOrUpdateAsync( rgName, primaryNamespaceName, new EHNamespace { Location = "southcentralus" }); var primaryNamespace = (await primaryResult.WaitForCompletionAsync()).Value; Utilities.Log("Primary event hub namespace created"); Utilities.Print(primaryNamespace); Utilities.Log($"Creating secondary event hub namespace {primaryNamespaceName}"); var secondaryResult = await namespaces.StartCreateOrUpdateAsync( rgName, secondaryNamespaceName, new EHNamespace { Location = "northcentralus" }); var secondaryNamespace = (await secondaryResult.WaitForCompletionAsync()).Value; 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 = (await disasterRecoveryConfigs.CreateOrUpdateAsync( rgName, primaryNamespaceName, geoDRName, new ArmDisasterRecovery { PartnerNamespace = secondaryNamespace.Id } )).Value; while ((await disasterRecoveryConfigs.GetAsync(rgName, primaryNamespaceName, geoDRName)).Value.ProvisioningState != ProvisioningStateDR.Succeeded) { Utilities.Log("Wait for create disaster recovery"); Thread.Sleep(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"); var primaryEventHub = (await eventHubs.CreateOrUpdateAsync( rgName, primaryNamespaceName, eventHubName, new Eventhub() )).Value; var primaryConsumerGroup = (await consumerGroups.CreateOrUpdateAsync( rgName, primaryNamespaceName, eventHubName, "consumerGrp1", new ConsumerGroup() )).Value; var eventHubInPrimaryNamespace = (await namespaces.GetAsync(rgName, primaryNamespaceName)).Value; 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"); Thread.Sleep(60 * 1000); // Wait for syncing to finish Utilities.Log("Retrieving the event hubs in secondary namespace"); var eventHubInSecondaryNamespace = (await namespaces.GetAsync(rgName, secondaryNamespaceName)).Value; Utilities.Log("Retrieved the event hubs in secondary namespace"); Utilities.Print(eventHubInSecondaryNamespace); // Retrieving the connection string var rules = await disasterRecoveryConfigs.ListAuthorizationRulesAsync(rgName, primaryNamespaceName, geoDRName).ToEnumerableAsync(); foreach (var rule in rules) { var key = (await disasterRecoveryConfigs.ListKeysAsync(rgName, primaryNamespaceName, geoDRName, rule.Name)).Value; Utilities.Print(key); } Utilities.Log("Initiating fail over"); var failOverResult = await disasterRecoveryConfigs.FailOverAsync(rgName, secondaryNamespaceName, geoDRName); Thread.Sleep(10 * 1000); while ((await disasterRecoveryConfigs.GetAsync(rgName, secondaryNamespaceName, geoDRName)).Value.ProvisioningState == ProvisioningStateDR.Accepted) { Utilities.Log("Wait for fail over"); Thread.Sleep(10 * 1000); } if ((await disasterRecoveryConfigs.GetAsync(rgName, secondaryNamespaceName, geoDRName)).Value.ProvisioningState == ProvisioningStateDR.Succeeded) { isFailOverSucceeded = true; Utilities.Log("Fail over initiated"); } else { Utilities.Log("Fail over is FAILED"); } } finally { try { try { // It is necessary to break pairing before deleting resource group if (pairing != null && !isFailOverSucceeded) { await disasterRecoveryConfigs.BreakPairingAsync(rgName, primaryNamespaceName, geoDRName); Thread.Sleep(10 * 1000); while ((await disasterRecoveryConfigs.GetAsync(rgName, primaryNamespaceName, geoDRName)).Value.ProvisioningState == ProvisioningStateDR.Accepted) { Thread.Sleep(10 * 1000); } if ((await disasterRecoveryConfigs.GetAsync(rgName, primaryNamespaceName, geoDRName)).Value.ProvisioningState == ProvisioningStateDR.Failed) { throw new Exception("Provisioning state of the break pairing is FAILED"); } } } catch (Exception ex) { Utilities.Log("Pairing breaking failed:" + ex.Message); } await ResourceGroupHelper.DeleteResourceGroup(rgName); } catch (NullReferenceException) { Utilities.Log("Did not create any resources in Azure. No clean up is necessary"); } catch (Exception ex) { Utilities.Log(ex); } } }
public static async Task RunSample(TokenCredential credential) { string region = "eastus"; string subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); string rgName = Utilities.RandomResourceName("rgeh", 15); string namespaceName1 = Utilities.RandomResourceName("ns", 15); string namespaceName2 = Utilities.RandomResourceName("ns", 15); string storageAccountName = Utilities.RandomResourceName("stg", 14); string eventHubName1 = Utilities.RandomResourceName("eh", 14); string eventHubName2 = Utilities.RandomResourceName("eh", 14); var eventHubsManagementClient = new EventHubsManagementClient(subscriptionId, credential); var namespaces = eventHubsManagementClient.Namespaces; var eventHubs = eventHubsManagementClient.EventHubs; var consumerGroups = eventHubsManagementClient.ConsumerGroups; var storageManagementClient = new StorageManagementClient(subscriptionId, credential); var storageAccounts = storageManagementClient.StorageAccounts; var blobContainers = storageManagementClient.BlobContainers; try { await ResourceGroupHelper.CreateOrUpdateResourceGroup(rgName, region); //============================================================ // Create an event hub namespace // Utilities.Log("Creating a namespace"); var rawResult = await namespaces.StartCreateOrUpdateAsync( rgName, namespaceName1, new EHNamespace { Location = "eastus2" }); var namespace1 = (await rawResult.WaitForCompletionAsync()).Value; Utilities.Print(namespace1); Utilities.Log("Created a namespace"); //============================================================ // Create an event hub in the namespace with data capture enabled, with consumer group and auth rule // var storageAccountCreatable = (await(await storageAccounts.StartCreateAsync( rgName, storageAccountName, new StorageAccountCreateParameters( new Azure.ResourceManager.Storage.Models.Sku("Standard_LRS"), new Kind("StorageV2"), "eastus2") )).WaitForCompletionAsync()).Value; var container = await blobContainers.CreateAsync( rgName, storageAccountName, "datacpt", new BlobContainer() ); Utilities.Log("Creating an event hub with data capture enabled with a consumer group and rule in it"); var eventHub1 = (await eventHubs.CreateOrUpdateAsync( rgName, namespace1.Name, eventHubName1, new Eventhub { MessageRetentionInDays = 4, PartitionCount = 4, Status = EntityStatus.Active, // Optional - configure data capture CaptureDescription = new CaptureDescription { Enabled = true, Encoding = EncodingCaptureDescription.Avro, IntervalInSeconds = 120, SizeLimitInBytes = 10485763, Destination = new Destination { Name = "EventHubArchive.AzureBlockBlob", BlobContainer = "datacpt", ArchiveNameFormat = "{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}", StorageAccountResourceId = "/subscriptions/" + subscriptionId + "/resourcegroups/" + rgName + "/providers/Microsoft.Storage/storageAccounts/" + storageAccountName }, SkipEmptyArchives = true } } )).Value; // Optional - create one consumer group in event hub var consumerGroup1 = await consumerGroups.CreateOrUpdateAsync( rgName, namespaceName1, eventHubName1, "cg1", new ConsumerGroup { UserMetadata = "sometadata" } ); // Optional - create an authorization rule for event hub var listenRule1 = await eventHubs.CreateOrUpdateAuthorizationRuleAsync( rgName, namespaceName1, eventHubName1, "listenrule1", new AuthorizationRule { Rights = new List <AccessRights>() { AccessRights.Listen, AccessRights.Send } } ); Utilities.Log("Created an event hub with data capture enabled with a consumer group and rule in it"); var result = (await eventHubs.GetAsync(rgName, namespaceName1, eventHubName1)).Value; Utilities.Print(result); //============================================================ // Retrieve consumer groups in the event hub // Utilities.Log("Retrieving consumer groups"); var listResult = await consumerGroups.ListByEventHubAsync(rgName, namespaceName1, eventHubName1).ToEnumerableAsync(); Utilities.Log("Retrieved consumer groups"); foreach (var group in listResult) { Utilities.Print(group); } //============================================================ // Create another event hub in the namespace // Utilities.Log("Creating another event hub in the namespace"); var eventHub2 = (await eventHubs.CreateOrUpdateAsync( rgName, namespaceName1, eventHubName2, new Eventhub() )).Value; Utilities.Log("Created second event hub"); Utilities.Print(eventHub2); //============================================================ // Create a consumer group in the event hub // Utilities.Log("Creating a consumer group in the second event hub"); var consumerGroup2 = (await consumerGroups.CreateOrUpdateAsync( rgName, namespaceName1, eventHubName2, "cg2", // Optional new ConsumerGroup { UserMetadata = "sometadata" } )).Value; Utilities.Log("Created a consumer group in the second event hub"); Utilities.Print(consumerGroup2); //============================================================ // Retrieve consumer groups in the event hub // Utilities.Log("Retrieving consumer groups in the second event hub"); listResult = await consumerGroups.ListByEventHubAsync(rgName, namespaceName1, eventHubName2).ToEnumerableAsync(); Utilities.Log("Retrieved consumer groups in the seoond event hub"); foreach (var group in listResult) { Utilities.Print(group); } //============================================================ // Create an event hub namespace with event hub // Utilities.Log("Creating an event hub namespace along with event hub"); var rawResult2 = await namespaces.StartCreateOrUpdateAsync( rgName, namespaceName2, new EHNamespace { Location = "eastus2" }); var namespace2 = (await rawResult2.WaitForCompletionAsync()).Value; var newEventHub2 = (await eventHubs.CreateOrUpdateAsync( rgName, namespaceName2, eventHubName2, new Eventhub() )).Value; Utilities.Log("Created an event hub namespace along with event hub"); Utilities.Print(namespace2); foreach (var eh in await eventHubs.ListByNamespaceAsync(rgName, namespaceName2).ToEnumerableAsync()) { Utilities.Print(eh); } } finally { try { await ResourceGroupHelper.DeleteResourceGroup(rgName); } catch (NullReferenceException) { Utilities.Log("Did not create any resources in Azure. No clean up is necessary"); } catch (Exception ex) { Utilities.Log(ex); } } }
public static async Task RunSample(TokenCredential credential) { string region = "eastus"; string subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); string rgName = Utilities.RandomResourceName("rgEvHb", 15); string namespaceName = Utilities.RandomResourceName("ns", 15); string eventHubName = "FirstEventHub"; var eventHubsManagementClient = new EventHubsManagementClient(subscriptionId, credential); var namespaces = eventHubsManagementClient.Namespaces; var eventHubs = eventHubsManagementClient.EventHubs; try { await ResourceGroupHelper.CreateOrUpdateResourceGroup(rgName, region); // Creates a Event Hub namespace and an Event Hub in it. Utilities.Log("Creating event hub namespace and event hub"); Utilities.Log("Creating a namespace"); var rawResult = await namespaces.StartCreateOrUpdateAsync( rgName, namespaceName, new EHNamespace { Location = "eastus2" }); var ehNamespace = (await rawResult.WaitForCompletionAsync()).Value; Utilities.Print(ehNamespace); Utilities.Log("Created a namespace"); var eventHub = (await eventHubs.CreateOrUpdateAsync( rgName, ehNamespace.Name, eventHubName, new Eventhub { MessageRetentionInDays = 4, PartitionCount = 4, Status = EntityStatus.Active, } )).Value; Utilities.Log($"Created event hub namespace {ehNamespace.Name} and event hub {eventHubName}"); Utilities.Print(ehNamespace); // Create a Authorization Rule for Event Hub created. Utilities.Log("Creating a Authorization Rule"); var listenRule = (await eventHubs.CreateOrUpdateAuthorizationRuleAsync( rgName, namespaceName, eventHubName, "listenrule1", new AuthorizationRule { Rights = new List <AccessRights>() { AccessRights.Listen, AccessRights.Send } } )).Value; Utilities.Log("Created a Authorization Rule"); // Send events using dataplane eventhub sdk. Utilities.Log("Sending events"); var keys = (await eventHubs.ListKeysAsync(rgName, namespaceName, eventHubName, listenRule.Name)).Value; var producerClient = new EventHubProducerClient(keys.PrimaryConnectionString, eventHubName); using EventDataBatch eventBatch = await producerClient.CreateBatchAsync(); eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Hello, Event Hubs!"))); eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("The middle event is this one"))); eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Goodbye, Event Hubs!"))); await producerClient.SendAsync(eventBatch); Utilities.Log("Sent events"); Utilities.Log("Reading events"); var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, keys.PrimaryConnectionString, eventHubName); using CancellationTokenSource cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(90)); int eventsRead = 0; int maximumEvents = 3; await foreach (PartitionEvent partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { Utilities.Log($"Event Read: { Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray()) }"); eventsRead++; if (eventsRead >= maximumEvents) { break; } } } finally { try { await ResourceGroupHelper.DeleteResourceGroup(rgName); } catch (NullReferenceException) { Utilities.Log("Did not create any resources in Azure. No clean up is necessary"); } catch (Exception ex) { Utilities.Log(ex); } } }