如何使用Azure SDK获取Azure虚拟机的公共IP

5

针对特定的虚拟机,我希望能够检索公共 IP 地址。

我知道如何获取资源组中所有公共 IP 地址,也知道如何获取特定虚拟机的 nic-id,但是我无法将两者连接起来。

这是我的代码:

var resourceGroupName = "My-Resource-Group";
var vmName = "MyVM";
var subscriptionId = "bzz-bzz-bzz-bzz-bzz-bzz";

var tenantId = "bar-bar-bar-bar-bar-bar";

string clientId = "foo-foo-foo-foo-foo-foo";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        
var token = GetAccessTokenAsync(tenantId, clientId, clientSecret);
var credential = new TokenCredentials(token.Result.AccessToken);

var computeManagementClient = new ComputeManagementClient(credential) { SubscriptionId = subscriptionId };

var vmResult = await computeManagementClient.VirtualMachines.GetAsync(resourceGroupName, vmName, InstanceViewTypes.InstanceView);

//Get the NIC ID for the VM: 

foreach (NetworkInterfaceReference nic in vmResult.NetworkProfile.NetworkInterfaces)
        {
            Console.WriteLine("  networkInterface id: " + nic.Id);
        }    
这使我得到类似于这样的东西:

/subscriptions/[guid]/resourceGroups/My-Resource-Group/providers/Microsoft.Network/networkInterfaces/myvm123

要获取资源组的所有公共IP,我可以这样做:
using (var client = new NetworkManagementClient(credential))
        {
            client.SubscriptionId = subscriptionId;
            foreach (var publicIpAddress in client.PublicIPAddresses.ListAll())
            {
                Console.WriteLine(publicIpAddress.IpAddress);
            }
}

然而,检查nic-id和public ip对象的属性,没有明显的方法可以从一个对象获取另一个对象。

问题:

如何从nic-id字符串获取到VM/nic的实际公共IP地址?

辅助函数:

private static async Task<AuthenticationResult> GetAccessTokenAsync(string tenantId, string clientId, string clientSecret)
    {
        var cc = new ClientCredential(clientId, clientSecret);
        var context = new AuthenticationContext($"https://login.windows.net/{tenantId}");
        var token = context.AcquireToken("https://management.azure.com/", cc);

        if (token == null)
        {
            throw new InvalidOperationException("Could not get the token");
        }
        return token;
    }

你看过ComputeManagementClient.Deployments吗?你可以获取RoleInstance,它有一个PublicIPs属性。 - Sorceri
@Sorceri 我已经可以获取公共IP了 - 我只是不知道如何获取命名虚拟机的特定IP。 - Kjensen
Deployment.RoleInstances[index] 是虚拟机,Deployment.RoleInstances[index].InstanceName 是该虚拟机的名称,deployment.RoleInstances[index].PublicIPs 是与该虚拟机相关联的公共 IP。希望这有所帮助。 - Sorceri
@Sorceri 我会去看一下,谢谢! :) - Kjensen
@Sorceri,我正在使用的ComputeManagementClient v.14上没有.Deployments,也没有明显的替代品。但是我创建了另一种解决方法,虽然不是很满意,但它可以工作。我会更新我的帖子。 - Kjensen
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4

我找到了一种解决方法。不太美观,但是它可以工作。

假设您已经有一个类似于以下内容的 Microsoft.Azure.Management.Compute.Models.VirtualMachine 对象:

VirtualMachine vmResult = await computeManagementClient.VirtualMachines.GetAsync(resourceGroupName, vmName, InstanceViewTypes.InstanceView);

然后,您可以获取第一个NIC的最后一部分作为ID:

        var firstNic = vmResult.NetworkProfile.NetworkInterfaces.First();

        var nicNameParts = firstNic.Id.Split('/');
        string networkIntefaceName = nicNameParts.Last();

        using (var client = new NetworkManagementClient(credential))
        {
            client.SubscriptionId = subscriptionId;

            string publicNicId = string.Empty;

            //Query ALL Networkinterfaces in the client, and find the one with the matching NIC-name

            var nic = client.NetworkInterfaces.ListAll().FirstOrDefault(x => x.Name == networkIntefaceName);

            if (nic != null)
            {
                //If we find that, we can now use that to find the ID of the PublicIPAddress for said NIC

                publicNicId = nic.IpConfigurations[0].PublicIPAddress.Id;
                //...And when we have that, we can now query all public IP addresses for that specific public Nic ID
                var publicIp = client.PublicIPAddresses.ListAll().FirstOrDefault(x => x.Id == publicNicId);
                if (publicIp != null)
                {
                    vmInfo.PublicIP = publicIp.IpAddress;
                    Console.WriteLine("  public ip: " + publicIp.IpAddress);
                }
                else
                {
                    Console.WriteLine("  public ip: unknown");
                }
            }
        }

是的,它不是非常优雅,可以进行优化等等-但是它有效,这是一个开始。


我对你的解决方案没有成功。我曾经使用Microsoft提供的这种方法从虚拟机中获取信息,参考链接:https://learn.microsoft.com/zh-cn/azure/virtual-machines/windows/csharp - Thadeu Melo

0
对于使用 Azure.ResourceManager.Compute 的用户,调用资源上的 Get 方法会填充其数据属性。
var client = new ArmClient(new DefaultAzureCredential());
var subscriptionIdentifier = SubscriptionResource.CreateResourceIdentifier(_vmSettings.SubscriptionId);
var subscription = client.GetSubscriptionResource(subscriptionIdentifier);
var resourceGroup = subscription.GetResourceGroup(_vmSettings.ResourceGroupName);
var vms = resourceGroup.Value.GetVirtualMachines();
foreach (var vm in vms)
{
    if (vm == null) { continue; }

    var vmRes = vm;
    if (!vmRes.HasData)
    {
        vmRes = vm.Get().Value;
        continue;
    }

    var networkProfile = vmRes.Data.NetworkProfile.NetworkInterfaces.FirstOrDefault();
    if(networkProfile == null) { continue; }

    var networkInterfaceResource = client.GetNetworkInterfaceResource(new ResourceIdentifier(networkProfile.Id));
    var ipAddressRes = networkInterfaceResource.GetNetworkInterfaceIPConfigurations().FirstOrDefault();
    if(ipAddressRes == null) { continue; }

    if (!ipAddressRes.HasData)
    {
        ipAddressRes = ipAddressRes.Get().Value;
    }

    var publicIpAddressRes = client.GetPublicIPAddressResource(new ResourceIdentifier(ipAddressRes.Data.PublicIPAddress.Id));
    if(publicIpAddressRes == null) { continue; }

    if(!publicIpAddressRes.HasData)
    {
        publicIpAddressRes = publicIpAddressRes.Get().Value;
    }

    _vms.Add(new VirtualMachine(vmRes.Data.Name, vmRes.Data.Id, publicIpAddressRes.Data.IPAddress));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,