/// <summary> /// TODO: Clean this up. check and errors. /// /// Should check the loadbalancer.inner.status to see if update is already in progress. /// Also should batch the queue items, add and configure multiple up configurations at once if they are in the queue. /// </summary> /// <param name="tenantDeployment"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task <TenantDeployment> ProcessIpDeploymentAsync(TenantDeployment tenantDeployment, CancellationToken cancellationToken) { var spId = Environment.GetEnvironmentVariable("SERVICE_PRINCIPAL_ID"); var spSecret = Environment.GetEnvironmentVariable("SERVICE_PRINCIPAL_SECRET"); var spTenantId = Environment.GetEnvironmentVariable("SERVICE_PRINCIPAL_TENANT_ID"); var subscriptionId = Environment.GetEnvironmentVariable("SUBSCRIPTION_ID"); var creds = new AzureCredentialsFactory().FromServicePrincipal(spId, spSecret, spTenantId, AzureEnvironment.AzureGlobalCloud); var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId); string loadBalancerName = Environment.GetEnvironmentVariable("LOAD_BALANCER"); string backendPool = Environment.GetEnvironmentVariable("BACKENDPOOL"); string resourcegroup = Environment.GetEnvironmentVariable("RESOURCEGROUP"); string tenantname = $"deployment-{tenantDeployment.Name}"; //TODO check provisioning state of load balancer and delay if currently busy //var provisioningState = azure.ResourceGroups.GetByName(loadBalancer.ResourceGroupName).ProvisioningState; try { var loadBalancer = await azure.LoadBalancers.GetByResourceGroupAsync(resourcegroup, loadBalancerName, cancellationToken); ILoadBalancerPublicFrontend publicFrontend = loadBalancer.PublicFrontends.First().Value; var publicIpAddress = publicFrontend.GetPublicIPAddress(); await loadBalancer.Update() .DefineTcpProbe(tenantname + "_mc") .WithPort(tenantDeployment.InternalPort) .Attach() .DefineLoadBalancingRule($"{tenantname}_mc") .WithProtocol(TransportProtocol.Tcp) .FromExistingPublicIPAddress(publicIpAddress) .FromFrontendPort(tenantDeployment.InternalPort) .ToBackend(backendPool) .ToBackendPort(tenantDeployment.InternalPort) .WithProbe(tenantname + "_mc") .Attach() .DefineTcpProbe(tenantname + "_rcon") .WithPort(tenantDeployment.RconPort) .Attach() .DefineLoadBalancingRule($"{tenantname}_rcon") .WithProtocol(TransportProtocol.Tcp) .FromExistingPublicIPAddress(publicIpAddress) .FromFrontendPort(tenantDeployment.RconPort) .ToBackend(backendPool) .ToBackendPort(tenantDeployment.RconPort) .WithProbe(tenantname + "_rcon") .Attach() .ApplyAsync(cancellationToken); return(new TenantDeployment(CreationStatus.Created, tenantDeployment, publicIpAddress.Fqdn)); } catch (Exception e) { ServiceEventSource.Current.ServiceMessage(this.Context, "error provisioning ip addresses.", e.Message); return(new TenantDeployment(CreationStatus.InProcess, tenantDeployment)); } }
public override ILoadBalancer UpdateResource(ILoadBalancer resource) { ILoadBalancerBackend backend = resource.Backends.Values.First(); ILoadBalancerInboundNatRule natRule = resource.InboundNatRules.Values.First(); ILoadBalancerPublicFrontend publicFrontend = (ILoadBalancerPublicFrontend)natRule.Frontend; IPublicIPAddress pip = resource.Manager.PublicIPAddresses.Define(loadBalancerHelper.PipNames[1]) .WithRegion(loadBalancerHelper.Region) .WithExistingResourceGroup(loadBalancerHelper.GroupName) .WithLeafDomainLabel(loadBalancerHelper.PipNames[1]) .Create(); resource = resource.Update() .UpdatePublicFrontend(publicFrontend.Name) .WithExistingPublicIPAddress(pip) .Parent() .DefineBackend("backend2") .Attach() .WithoutBackend(backend.Name) .WithoutInboundNatRule("natrule1") .WithTag("tag1", "value1") .WithTag("tag2", "value2") .Apply(); Assert.True(resource.Tags.ContainsKey("tag1")); // Verify frontends Assert.Equal(1, resource.Frontends.Count); Assert.Equal(1, resource.PublicFrontends.Count); Assert.Equal(0, resource.PrivateFrontends.Count); Assert.True(resource.Frontends.ContainsKey(publicFrontend.Name)); var frontend = resource.Frontends[publicFrontend.Name]; Assert.True(frontend.IsPublic); publicFrontend = (ILoadBalancerPublicFrontend)frontend; Assert.Equal(pip.Id, publicFrontend.PublicIPAddressId, ignoreCase: true); Assert.Equal(0, publicFrontend.LoadBalancingRules.Count); // Verify probes Assert.Equal(0, resource.TcpProbes.Count); Assert.Equal(0, resource.HttpProbes.Count); // Verify backends Assert.True(resource.Backends.ContainsKey("backend2")); Assert.True(!resource.Backends.ContainsKey(backend.Name)); // Verify NAT rules Assert.Equal(0, resource.InboundNatRules.Count); // Verify load balancing rules Assert.Equal(0, resource.LoadBalancingRules.Count); return(resource); }
// This test put multiple zonal virtual machine's NIC into backend pool of a zone-redundant load balancer. // There is a bug in the service, where such an attempt will fail with error // "error": { // "code": "NetworkInterfaceAndLoadBalancerAreInDifferentAvailabilitySets", // "message": "Network interface /subscriptions/<sub-id>/resourceGroups/<rg-name>/providers/Microsoft.Network/networkInterfaces/<nic-name> uses load balancer /subscriptions/<sub-id>/resourceGroups/<rg-name>/providers/Microsoft.Compute/virtualMachines/<vm-name>).", // "details": [] // } // Enable this test once it is fixed. // public void CanCreateZonedVMsAndAssociateThemWithSingleBackendPoolOfZoneResilientLB() { using (var context = FluentMockContext.Start(GetType().FullName)) { string rgName = TestUtilities.GenerateName("rgzoned"); try { var region = Region.USEast2; string networkName = TestUtilities.GenerateName("net"); var azure = TestHelper.CreateRollupClient(); var network = azure.Networks.Define(networkName) .WithRegion(region) .WithNewResourceGroup(rgName) .WithAddressSpace("10.0.0.0/28") .WithSubnet("subnet1", "10.0.0.0/29") .WithSubnet("subnet2", "10.0.0.8/29") .Create(); string pipDnsLabel = TestUtilities.GenerateName("pip"); var subnets = network.Subnets.Values.GetEnumerator(); // Define first regional virtual machine // subnets.MoveNext(); var creatableVM1 = azure.VirtualMachines .Define(TestUtilities.GenerateName("vm1")) .WithRegion(region) .WithExistingResourceGroup(rgName) .WithExistingPrimaryNetwork(network) .WithSubnet(subnets.Current.Name) // Put VM in first subnet .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer16_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("abc!@#F0orL") // Optionals .WithAvailabilityZone(AvailabilityZoneId.Zone_1) .WithSize(VirtualMachineSizeTypes.StandardD3V2); subnets.MoveNext(); var creatableVM2 = azure.VirtualMachines .Define(TestUtilities.GenerateName("vm2")) .WithRegion(region) .WithExistingResourceGroup(rgName) .WithExistingPrimaryNetwork(network) .WithSubnet(subnets.Current.Name) // Put VM in second subnet .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer16_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("abc!@#F0orL") // Optionals .WithAvailabilityZone(AvailabilityZoneId.Zone_1) .WithSize(VirtualMachineSizeTypes.StandardD3V2); ICreatedResources <IVirtualMachine> createdVMs = azure.VirtualMachines.Create(creatableVM1, creatableVM2); var itr = createdVMs.GetEnumerator(); itr.MoveNext(); IVirtualMachine firstVirtualMachine = itr.Current; itr.MoveNext(); IVirtualMachine secondVirtualMachine = itr.Current; var publicIPAddress = azure.PublicIPAddresses .Define(pipDnsLabel) .WithRegion(region) .WithExistingResourceGroup(rgName) .WithStaticIP() // Optionals .WithSku(PublicIPSkuType.Standard) // STANDARD LB requires STANDARD PIP // Create PIP .Create(); // Creates a Internet-Facing LoadBalancer with one front-end IP configuration and // two backend pool associated with this IP Config // var lbName = TestUtilities.GenerateName("lb"); ILoadBalancer lb = azure.LoadBalancers .Define(lbName) .WithRegion(region) .WithExistingResourceGroup(rgName) .DefineLoadBalancingRule("rule-1") .WithProtocol(TransportProtocol.Tcp) .FromFrontend("front-end-1") .FromFrontendPort(80) .ToExistingVirtualMachines(firstVirtualMachine, secondVirtualMachine) .WithProbe("tcpProbe-1") .Attach() .DefinePublicFrontend("front-end-1") // Define the frontend IP configuration used by the LB rule .WithExistingPublicIPAddress(publicIPAddress) .Attach() .DefineTcpProbe("tcpProbe-1") // Define the Probe used by the LB rule .WithPort(25) .WithIntervalInSeconds(15) .WithNumberOfProbes(5) .Attach() .WithSku(LoadBalancerSkuType.Standard) // "zone-resilient LB" which don't have the constraint that all VMs needs to be in the same availability set .Create(); // Zone resilient LB does not care VMs are zoned or regional, in the above cases VMs are regional. // // rx.Completable.merge(firstVirtualMachine.startAsync(), secondVirtualMachine.startAsync()).await(); // Verify frontends Assert.Equal(1, lb.Frontends.Count); Assert.Equal(1, lb.PublicFrontends.Count); Assert.Equal(0, lb.PrivateFrontends.Count); ILoadBalancerFrontend frontend = lb.Frontends.Values.First(); Assert.True(frontend.IsPublic); ILoadBalancerPublicFrontend publicFrontend = (ILoadBalancerPublicFrontend)frontend; Assert.Equal(publicIPAddress.Id, publicFrontend.PublicIPAddressId, ignoreCase: true); // Verify backends Assert.Equal(1, lb.Backends.Count); // Verify probes Assert.Equal(1, lb.TcpProbes.Count); Assert.True(lb.TcpProbes.ContainsKey("tcpProbe-1")); // Verify rules Assert.Equal(1, lb.LoadBalancingRules.Count); Assert.True(lb.LoadBalancingRules.ContainsKey("rule-1")); ILoadBalancingRule rule = lb.LoadBalancingRules["rule-1"]; Assert.NotNull(rule.Backend); Assert.Equal("tcpProbe-1", rule.Probe.Name, ignoreCase: true); // Zone resilient LB does not care VMs are zoned or regional, in the above cases VMs are zoned. // // Note that above configuration is not possible for BASIC LB, BASIC LB has following limitation // It supports VMs only in a single availability Set in a backend pool, though multiple backend pool // can be associated with VMs in the single availability set, you cannot create a set of VMs in another // availability set and put it in a different backend pool. } finally { try { var resourceManager = TestHelper.CreateResourceManager(); resourceManager.ResourceGroups.DeleteByName(rgName); } catch { } } } }