【问题标题】:How do i filter using a partial VM name (string) in vmware vSphere client REST API?如何在 vmware vSphere 客户端 REST API 中使用部分虚拟机名称(字符串)进行过滤?
【发布时间】:2020-01-08 14:03:31
【问题描述】:

美好的一天!

我正在尝试自动执行一些要对我组织中的虚拟机执行的操作。 要执行的操作取决于 VM 名称中的 a 子字符串。

例如,我需要删除所有名称以“delete”开头的虚拟机,等等。

我可以使用以下 API 来获取 VM 列表:

GET https://{{vc}}/rest/vcenter/vm

但是,此 API 最多只能获取 1000 个 VM。

有什么方法可以过滤并仅获取来自该 API 的带有预期子字符串的 VM 列表?

据我了解,将 filter.names.1 附加到上述 API 是可行的,但为此我需要输入准确的完整 VM 名称。

有没有一种方法可以搜索带有部分文本的 VM 列表?

抱歉,我是新手。

感谢您的宝贵时间!

【问题讨论】:

    标签: vsphere vmware-tools


    【解决方案1】:
    Since vSphere API does not provide such capability to search by partial VM name there is a tricky way to do this.
    I am using the search functionality in vSphere Client 6.7.0.
    Prerequisite is to get the following cookies first:
    
        VSPHERE-USERNAME
        VSPHERE-CLIENT-SESSION-INDEX
        VSPHERE-UI-JSESSIONID
    
    You have to do three calls in order to get them:
    
    1. GET "https://[URL]/ui/login" you will be forwarded to a new URL from where you can take "SAMLRequest token"
    2. POST "https://[URL]/websso/SAML2/SSO/vsphere.local?SAMLRequest=[SAMLRequest token]", set as header "CastleAuthorization=Basic%20[credentials]" where credentials is the Base64 encoding of "User:Password". Get the value of "SAMLResponse" hidden field from the response.
    3. POST "https://[URL]/ui/saml/websso/sso", set "SAMLResponse=[SAMLResponse value]", where "SAMLResponse value" you have it from the previous response. From this response you will get the cookies.
    
    Once you have those three cookies, make a new call as you set the cookies
    4. GET "https://[URL]/ui/search/quicksearch/?opId=0&query=[partial VM name]"
    
    For example for this call "https://[URL]/ui/search/quicksearch/?opId=0&query=test"
    you will get response like this:
    [{
            "icon": "vsphere-icon-vm",
            "labelPlural": "Virtual Machines",
            "label": "Virtual Machine",
            "results": [{
                    "id": "urn:vmomi:VirtualMachine:vm-2153:103ac083-e314-47ea-942a-c685d9a4e6c9",
                    "type": "VirtualMachine",
                    "name": "TestVM1"
                }, {
                    "id": "urn:vmomi:VirtualMachine:vm-3391:103ac083-e314-47ea-942a-c685d9a4e6c9",
                    "type": "VirtualMachine",
                    "name": "TestVM2"
                }, {
                    "id": "urn:vmomi:VirtualMachine:vm-3438:103ac083-e314-47ea-942a-c685d9a4e6c9",
                    "type": "VirtualMachine",
                    "name": "TestVM3"
                }
            ]
        }
    ]
    

    下面是我自己用 C# 编写的 vSphere Search Proxy Client:

    using System;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web;
    
    namespace VsphereSearchProxy
    {
        static class Program
        {
            const string VSPHERE_URL = "VSPHERE_URL";
    
            static string VSPHERE_CRED_BASE64
            {
                get
                {
                    var plainTextCred = Encoding.UTF8.GetBytes("USER:PASS");
                    return Convert.ToBase64String(plainTextCred);
                }
            }
    
            static void Main(string[] args)
            {
                if (args.Length == 0)
                {
                    Console.WriteLine("Expected one argument: Virtual Machine name");
                    return;
                }
    
                var vmName = args[0];
                var vsphereUri = VSPHERE_URL.TrimEnd('/');
    
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                ServicePointManager.Expect100Continue = true;
    
                //=================================================================
    
                Console.WriteLine("\nStep 1\n");
    
                var url1 = vsphereUri + "/ui/login";
    
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url1);
                request.Method = "GET";
                request.KeepAlive = true;
                request.AllowAutoRedirect = true;
    
                var response = (HttpWebResponse)request.GetResponse();
                var url2 = response.ResponseUri.AbsoluteUri;
                Console.WriteLine("url2: " + url2);
    
                WebHeaderCollection headerCollection = response.Headers;
                Console.WriteLine("\nResponse headers\n");
    
                for (int i = 0; i < headerCollection.Count; i++)
                {
                    Console.WriteLine("\t" + headerCollection.GetKey(i) + " = " + headerCollection.Get(i));
                }
    
                //=================================================================
    
                Console.WriteLine("\nStep 2\n");
    
                request = (HttpWebRequest)WebRequest.Create(url2);
                request.Method = "POST";
                request.Headers.Add("Authorization: Basic " + VSPHERE_CRED_BASE64);
                request.ContentType = "application/x-www-form-urlencoded";
                request.KeepAlive = true;
                request.AllowAutoRedirect = false;
    
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write("CastleAuthorization=Basic%20" + VSPHERE_CRED_BASE64);
                    streamWriter.Flush();
                    streamWriter.Close();
                }
    
                response = (HttpWebResponse)request.GetResponse();
    
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception("Expected 200 OK, but got " + response.StatusCode);
                }
    
                headerCollection = response.Headers;
                Console.WriteLine("\nResponse headers\n");
    
                for (int i = 0; i < headerCollection.Count; i++)
                {
                    Console.WriteLine("\t" + headerCollection.GetKey(i) + " = " + headerCollection.Get(i));
                }
    
                var responseString = "";
    
                using (Stream stream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    responseString = reader.ReadToEnd();
                }
    
                var SAMLResponse = "";
                Match match = Regex.Match(responseString, "<input[^>]*type=\"hidden\"\\s+name=\"SAMLResponse\"[^>]*value=\"([^\"]*)\"");
    
                if (match.Success)
                {
                    SAMLResponse = match.Groups[1].Value;
                    SAMLResponse = SAMLResponse.Replace("\n", "");
                    //Console.WriteLine("SAMLResponse: " + SAMLResponse);
                }
    
                if (string.IsNullOrWhiteSpace(SAMLResponse))
                {
                    throw new Exception("SAMLResponse is missing or blank");
                }
    
                //=================================================================
    
                Console.WriteLine("\nStep 3\n");
    
                var url3 = vsphereUri + "/ui/saml/websso/sso";
    
                request = (HttpWebRequest)WebRequest.Create(url3);
                request.Method = "POST";
                request.Headers.Add("Authorization: Basic " + VSPHERE_CRED_BASE64);
                request.ContentType = "application/x-www-form-urlencoded";
                request.KeepAlive = true;
                request.AllowAutoRedirect = false;
    
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write("SAMLResponse=" + HttpUtility.UrlEncode(SAMLResponse));
                    streamWriter.Flush();
                    streamWriter.Close();
                }
    
                response = (HttpWebResponse)request.GetResponse();
    
                var cookies = response.Headers["Set-Cookie"];
                Console.WriteLine("cookies: " + cookies);
    
                headerCollection = response.Headers;
                Console.WriteLine("\nResponse headers\n");
    
                for (int i = 0; i < headerCollection.Count; i++)
                {
                    Console.WriteLine("\t" + headerCollection.GetKey(i) + " = " + headerCollection.Get(i));
                }
    
                //=================================================================
    
                Console.WriteLine("\nStep 4\n");
    
                var url4 = vsphereUri + "/ui/search/quicksearch/?opId=:1&query=" + vmName;
    
                request = (HttpWebRequest)WebRequest.Create(url4);
                request.Method = "GET";
                request.Headers.Add("Cookie: " + cookies);
                request.KeepAlive = true;
                request.AllowAutoRedirect = false;
    
                response = (HttpWebResponse)request.GetResponse();
    
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception("Expected 200 OK, but got " + response.StatusCode);
                }
    
                var jsonResp = "";
    
                using (Stream stream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    jsonResp = reader.ReadToEnd();
                }
    
                Console.WriteLine(jsonResp);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      不幸的是,vSphere 自动化 API 未设置为过滤部分名称,甚至在使用通配符时也未设置。一些可用的过滤器可以帮助您将输出限制在 1000 个对象限制以下(例如:过滤特定的集群和/或文件夹)。

      希望这是在未来版本中添加的内容。

      【讨论】:

      • 非常感谢您的回答,凯尔。目前,正如您所建议的那样,我使用了另一个过滤器将结果限制在 1000 个结果以内,并且由于我使用邮递员来触发 API,我将编写 javascript 代码来过滤并获取 VM 的列表 i需要基于子字符串。
      猜你喜欢
      • 2022-05-26
      • 1970-01-01
      • 2021-03-27
      • 2021-03-09
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-15
      相关资源
      最近更新 更多