首页 > 解决方案 > 将虚拟机搜索限制到特定集群?

问题描述

我正在使用 C# 和 VMware.Vim vsphere API 进行一些搜索,并且在大多数情况下它运行良好,只是我无法弄清楚如何限制数据中心中的特定集群。

例如:

NameValueCollection filter = new NameValueCollection();
filter.Add("Name", vmName2LookFor);

var ret = vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, viewProperties);
var VMs = ret.Cast<VMware.Vim.VirtualMachine>().ToList();

我已经看到了使用 parent 属性递归地爬上树直到达到集群级别的建议,但是当你获得更多结果时,这似乎是一个非常糟糕的想法。

我还看到了使用 TraversalSpec 的参考资料,但我真的找不到任何好的文档。

有人可以帮我吗?

您将如何以高性能方式获取集群中的所有虚拟机和/或是否有任何文档,或者您能否给我一些使用 TraversalSpec 的示例?

标签: vmware

解决方案


我最终只是为整个数据中心构建了一个 host=>cluster 映射,然后根据该映射检查 vm.Runtime.Host 属性,以确保 vm 实际上在特定集群下运行。

这最终是有效的,但下面是我关于如何使用 TraversalSpec 的问题的答案。代码在下面,下面是解释。

public SelectionSpec[] buildTraversalFromDatacenterToVM() {
  // Recurse through all ResourcePools
  TraversalSpec rpToVm = new TraversalSpec() {
    Name = "rpToVm",
    Type = "ResourcePool",
    Path = "vm",
    Skip = false
  };
  // Recurse through all ResourcePools

  TraversalSpec rpToRp = new TraversalSpec() {
    Name = "rpToRp",
    Type = "ResourcePool",
    Path = "resourcePool",
    Skip = false,
    SelectSet = new[] {
      new SelectionSpec() { Name = "rpToRp" },
      new SelectionSpec() { Name = "rpToVm" }
    }
  };

  // Traversal through ResourcePool branch
  TraversalSpec crToRp = new TraversalSpec() {
    Name = "crToRp",
    Type = "ComputeResource",
    Path = "resourcePool",
    Skip = false,
    SelectSet = new[] {
      new SelectionSpec() { Name = "rpToRp" },
      new SelectionSpec() { Name = "rpToVm" },
    }
  };

  // Traversal through host branch
  TraversalSpec crToH = new TraversalSpec();
  crToH.Name = "crToH";
  crToH.Type = "ComputeResource";
  crToH.Path = "host";
  crToH.Skip = false;

  // Traversal through hostFolder branch
  TraversalSpec dcToHf = new TraversalSpec() {
    Name = "dcToHf",
    Type = "Datacenter",
    Path = "hostFolder",
    Skip = false,
    SelectSet = new[] { new SelectionSpec() { Name = "visitFolders" } }
  };

  // Traversal through vmFolder branch
  TraversalSpec dcToVmf = new TraversalSpec() {
    Name = "dcToVmf",
    Type = "Datacenter",
    Path = "vmFolder",
    Skip = false,
    SelectSet = new[] { new SelectionSpec() { Name = "visitFolders" } }
  };

  // Recurse through all Hosts
  TraversalSpec HToVm = new TraversalSpec() {
    Name = "HToVm",
    Type = "HostSystem",
    Path = "vm",
    Skip = false,
    SelectSet = new[] { new SelectionSpec() { Name = "visitFolders" } }
  };

  // Recurse through the folders
  TraversalSpec visitFolders = new TraversalSpec();
  visitFolders.Name = "visitFolders";
  visitFolders.Type = "Folder";
  visitFolders.Path = "childEntity";
  visitFolders.Skip = false;
  visitFolders.SelectSet = new[] {
    new SelectionSpec() { Name ="visitFolders" },
    new SelectionSpec() { Name ="dcToHf" },
    new SelectionSpec() { Name ="dcToVmf" },
    new SelectionSpec() { Name ="crToH" },
    new SelectionSpec() { Name ="crToRp" },
    new SelectionSpec() { Name ="HToVm" },
    new SelectionSpec() { Name ="rpToVm" },
    new SelectionSpec() { Name ="HToVm" },
  };

  return new SelectionSpec[] { visitFolders, dcToVmf, dcToHf, crToH, crToRp, rpToRp, HToVm, rpToVm };
}



public PropertyFilterSpec[] GetPropertyFilterSpec(ManagedObjectReference root,PropertySpec[] propSpecs) {
  if (typeinfo == null || typeinfo.Length == 0) {
    return null;
  }
  var selectionSpecs = buildTraversalFromDatacenterToVM();

  PropertyFilterSpec spec = new PropertyFilterSpec();
  spec.PropSet = propSpecs;
  spec.ObjectSet = new ObjectSpec[] {
    new ObjectSpec() {
      Obj = root,
      Skip = false,
      SelectSet = selectionSpecs
    }
  };

  return new PropertyFilterSpec[] { spec }
}

以下是您如何使用上述功能

// NOTE:  setting All to true will return everything for the object, setting it to false
//        and filling out the PathSet will instead only return the properties specified
//        for performance.  For example, below for the HostSystem objects, everything
//        on the object will be null except for the name and the parent members
//
var propSpecs = new[] {
  new PropertySpec() {
     All = true,
     Type = "VirtualMachine"
  },
  new PropertySpec() {
     All = false,
     Type = "HostSystem",
     PathSet = new[]{ "name", "parent" }
  }
};


VimClient vimClient = new VMware.Vim.VimClientImpl();
var serviceContent = vimClient.Connect(hostname, VMware.Vim.CommunicationProtocol.Https, null);
var userSession = vimClient.Login(un, pwd);

var propertyCollector = new PropertyCollector(vimClient, serviceContent.PropertyCollector);

var specs = GetPropertyFilterSpec(serviceContent.RootFolder,propSpecs);
ObjectContent[] objContents = propertyCollectionr.RetrieveProperties(specs);

现在解释一下。

因为 vmware 基础架构基本上是一个图,所以 TraversalSpec 描述了如何爬上该图。分配的名称是用户定义的(您想要的任何名称),但用于引用特定规范以进行递归。换句话说,它很像引用或指针。例如,VisitFolders 规范使用 selectionSpec 引用自身。这意味着它可以支持嵌套文件夹(多级,而不仅仅是 1 级)。

请注意,您可以比我走得更远(进入数据存储区等),但我不需要走那么远。

一旦你描述了如何在图表中爬行,那么你必须告诉它要返回什么属性,这就是 propertySpec 的用途。

PropertySpec 有 2 个用途。1. 它充当准过滤器,如果您没有实体的 PropertySpec,则 vmware API 将不会为它返回任何内容。如果您确实有一个 PropertySpec,那么它将只返回您要求它的属性。

因此,在上面的示例中,它将返回遍历中遇到的 VM 的所有属性,并且仅返回遍历中遇到的所有主机的名称和父属性。因为我没有为文件夹指定任何属性,所以请求将遍历文件夹,但不会为它们返回任何东西。

这是有关 vmware 层次结构的文档

https://pubs.vmware.com/vsphere-50/index.jsp?topic=%2Fcom.vmware.wssdk.pg.doc_50%2FPG_Ch4_Introduction_Inventory.6.3.html

和各种规格类型的文档

https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vmodl.query.PropertyCollector.PropertySpec.html

https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vmodl.query.PropertyCollector.SelectionSpec.html

https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vmodl.query.PropertyCollector.TraversalSpec.html


推荐阅读