有什么方法可以通过 vSphere API 进行批处理吗?
Is there any way to do batch via vSphere API?
我正在使用 vSphere API 检索 vCenter 中的所有虚拟机。但是,我没有找到任何官方文档或代码示例提及带有 batching/paging 的请求。我的代码如下:
VimClient client = new VimClient();
client.Connect(host, CommunicationProtocol.Https, 443);
client.Login(userName, password);
IList<EntityViewBase> vms = client.FindEntityViews(typeof(VirtualMachine), null, null, null);
查看了ReSharper反编译后的源码。有趣的是,有一个可为空的参数"beginEntity";但无法指定要检索的实体数。完全没有希望他们可以支持批处理吗?
public List<EntityViewBase> FindEntityViews(Type viewType, ManagedObjectReference beginEntity, NameValueCollection filter, string[] properties)
{
IList<ViewBase> viewBaseList = (IList<ViewBase>) null;
ManagedObjectReference beginEntity1 = beginEntity ?? this._serviceContent.RootFolder;
string[] strArray = (string[]) null;
if (filter != null && filter.Count > 0)
{
string[] propertyList = new string[filter.Count];
filter.AllKeys.CopyTo((Array) propertyList, 0);
strArray = VimClient.ValidatePropertyPathList(viewType, propertyList);
}
ObjectContent[] objectContentArray = new PropertyCollector(this, this._serviceContent.PropertyCollector).RetrieveProperties(new PropertyFilterSpec[1]
{
EntityViewBase.GetSearchFilterSpec(this, beginEntity1, new PropertySpec()
{
All = new bool?(false),
Type = viewType.Name,
PathSet = strArray
})
});
List<ManagedObjectReference> managedObjectReferenceList = new List<ManagedObjectReference>();
if (objectContentArray != null)
{
foreach (ObjectContent objectContent in objectContentArray)
{
if (beginEntity == null || !objectContent.Obj.Value.Equals(beginEntity.Value) || !objectContent.Obj.Type.Equals(beginEntity.Type))
{
if (filter != null && filter.Count > 0)
{
DynamicProperty[] propSet = objectContent.PropSet;
if (propSet != null)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
foreach (DynamicProperty dynamicProperty in propSet)
dictionary.Add(dynamicProperty.Name, dynamicProperty.Val);
if (dictionary.Count > 0 && VimClient.MatchProperyList(filter, viewType, (IDictionary<string, object>) dictionary))
managedObjectReferenceList.Add(objectContent.Obj);
}
}
else
managedObjectReferenceList.Add(objectContent.Obj);
}
}
}
if (managedObjectReferenceList.Count > 0)
viewBaseList = (IList<ViewBase>) this.GetViewsByMorefs((IEnumerable<ManagedObjectReference>) managedObjectReferenceList, properties);
List<EntityViewBase> entityViewBaseList = (List<EntityViewBase>) null;
if (viewBaseList != null)
{
entityViewBaseList = new List<EntityViewBase>();
foreach (ViewBase viewBase in (IEnumerable<ViewBase>) viewBaseList)
{
EntityViewBase entityViewBase = viewBase as EntityViewBase;
entityViewBaseList.Add(entityViewBase);
}
}
return entityViewBaseList;
}
public List<ViewBase> GetViewsByMorefs(IEnumerable<ManagedObjectReference> moRefs, params string[] properties)
{
Dictionary<string, PropertyFilterSpec> propertyFilterSpecList = new Dictionary<string, PropertyFilterSpec>();
foreach (ManagedObjectReference moRef in moRefs)
{
if (propertyFilterSpecList.ContainsKey(moRef.Type.ToLower()))
{
PropertyFilterSpec propertyFilterSpec = propertyFilterSpecList[moRef.Type.ToLower()];
propertyFilterSpec.ObjectSet = new List<ObjectSpec>((IEnumerable<ObjectSpec>) propertyFilterSpec.ObjectSet)
{
new ObjectSpec() { Obj = moRef }
}.ToArray();
}
else
{
PropertyFilterSpec resultPropertyFilterSpec;
Dictionary<string, List<string>> currentAllowedPropertyPath;
DynamicPropertyFilterSpecGenerator.Generate(moRef, properties, out resultPropertyFilterSpec, out currentAllowedPropertyPath);
propertyFilterSpecList.Add(moRef.Type.ToLower(), resultPropertyFilterSpec);
}
}
PropertyFilterSpec[] propertyFilterSpecArray = new PropertyFilterSpec[propertyFilterSpecList.Values.Count];
propertyFilterSpecList.Values.CopyTo(propertyFilterSpecArray, 0);
ObjectContent[] objectContent = new PropertyCollector(this, this._serviceContent.PropertyCollector).RetrieveProperties(propertyFilterSpecArray);
List<ViewBase> viewsByMorefs = this.GetViewsByMorefs(moRefs, objectContent, propertyFilterSpecList);
return viewsByMorefs;
}
private List<ViewBase> GetViewsByMorefs(IEnumerable<ManagedObjectReference> moRefs, ObjectContent[] objectContent, Dictionary<string, PropertyFilterSpec> propertyFilterSpecList)
{
List<ViewBase> viewBaseList = new List<ViewBase>();
List<string> stringList = new List<string>();
foreach (ManagedObjectReference moRef in moRefs)
stringList.Add(moRef.Value);
Dictionary<string, ObjectContent> objectContentList = new Dictionary<string, ObjectContent>();
foreach (ObjectContent objectContent1 in objectContent)
objectContentList.Add(objectContent1.Obj.Value, objectContent1);
Dictionary<string, ViewBase> generatedManagedObjectList = new Dictionary<string, ViewBase>();
foreach (ObjectContent objectContent1 in objectContent)
{
if (stringList.Contains(objectContent1.Obj.Value))
{
ConstructorInfo constructor = ViewBase.GetViewType(objectContent1.Obj.Type).GetConstructor(new Type[2]
{
typeof (VimClient),
typeof (ManagedObjectReference)
});
if (constructor != null)
{
ViewBase currentObject = (ViewBase) constructor.Invoke(new object[2]
{
(object) this,
(object) objectContent1.Obj
});
ViewBase.SetViewData(currentObject, (string) null, (Dictionary<string, List<string>>) null, objectContentList, generatedManagedObjectList);
viewBaseList.Add(currentObject);
}
}
}
return viewBaseList;
}
我不知道实现此目的的直接方法。
但是,您发布的第二个代码片段(反编译的 FindEntityViews
)显示了对 VMware Property Collector
's method retrieveProperties
. If you use retrievePropertiesEx
then you can provide it with a max count and then call continueRetrievePropertiesEx
.
的使用
但请注意,根据我的经验,vSphere API 非常强大,因此除非您有数千台 VM,否则您可能会发现不需要分页(除非您有其他考虑,当然)。
这是我最终如何实现批处理的代码片段。
VimClient vimClient = new VimClient();
vimClient.Connect(host, CommunicationProtocol.Https, 443);
vimClient.Login(userName, password);
string token = string.Empty;
while (true)
{
// Construct the property collector
PropertyCollector propertyCollector = new PropertyCollector(vimClient, vimClient.ServiceContent.PropertyCollector);
// Retrieve a batch of objects
RetrieveResult result;
if (!string.IsNullOrWhiteSpace(token))
result = propertyCollector.ContinueRetrievePropertiesEx(token);
else
{
result = propertyCollector.RetrievePropertiesEx(new[]
{
EntityViewBase.GetSearchFilterSpec(vimClient, vimClient.ServiceContent.RootFolder, new PropertySpec
{
All = false,
Type = typeof(VirtualMachine),
PathSet = null
})
}, new RetrieveOptions { MaxObjects = 100 });
}
// Exit early if no entities retrieved
if (null == result || 0 == result.Objects.Length)
break;
// Get the MoRefs of retrieval result
List<ManagedObjectReference> objectMoRefList = result.Objects.Select(o => o.Obj).ToList();
// Retrieve the properties of objects
List <EntityViewBase> entityList = vimClient.GetViewsByMorefs(objectMoRefList)?.Select(viewBase => viewBase as EntityViewBase).ToList();
// Return the objects and batch retrieval token
token = new BatchRetrievalToken(result.Token)
entityList.ForEach(e => yield return e);
}
我正在使用 vSphere API 检索 vCenter 中的所有虚拟机。但是,我没有找到任何官方文档或代码示例提及带有 batching/paging 的请求。我的代码如下:
VimClient client = new VimClient();
client.Connect(host, CommunicationProtocol.Https, 443);
client.Login(userName, password);
IList<EntityViewBase> vms = client.FindEntityViews(typeof(VirtualMachine), null, null, null);
查看了ReSharper反编译后的源码。有趣的是,有一个可为空的参数"beginEntity";但无法指定要检索的实体数。完全没有希望他们可以支持批处理吗?
public List<EntityViewBase> FindEntityViews(Type viewType, ManagedObjectReference beginEntity, NameValueCollection filter, string[] properties)
{
IList<ViewBase> viewBaseList = (IList<ViewBase>) null;
ManagedObjectReference beginEntity1 = beginEntity ?? this._serviceContent.RootFolder;
string[] strArray = (string[]) null;
if (filter != null && filter.Count > 0)
{
string[] propertyList = new string[filter.Count];
filter.AllKeys.CopyTo((Array) propertyList, 0);
strArray = VimClient.ValidatePropertyPathList(viewType, propertyList);
}
ObjectContent[] objectContentArray = new PropertyCollector(this, this._serviceContent.PropertyCollector).RetrieveProperties(new PropertyFilterSpec[1]
{
EntityViewBase.GetSearchFilterSpec(this, beginEntity1, new PropertySpec()
{
All = new bool?(false),
Type = viewType.Name,
PathSet = strArray
})
});
List<ManagedObjectReference> managedObjectReferenceList = new List<ManagedObjectReference>();
if (objectContentArray != null)
{
foreach (ObjectContent objectContent in objectContentArray)
{
if (beginEntity == null || !objectContent.Obj.Value.Equals(beginEntity.Value) || !objectContent.Obj.Type.Equals(beginEntity.Type))
{
if (filter != null && filter.Count > 0)
{
DynamicProperty[] propSet = objectContent.PropSet;
if (propSet != null)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
foreach (DynamicProperty dynamicProperty in propSet)
dictionary.Add(dynamicProperty.Name, dynamicProperty.Val);
if (dictionary.Count > 0 && VimClient.MatchProperyList(filter, viewType, (IDictionary<string, object>) dictionary))
managedObjectReferenceList.Add(objectContent.Obj);
}
}
else
managedObjectReferenceList.Add(objectContent.Obj);
}
}
}
if (managedObjectReferenceList.Count > 0)
viewBaseList = (IList<ViewBase>) this.GetViewsByMorefs((IEnumerable<ManagedObjectReference>) managedObjectReferenceList, properties);
List<EntityViewBase> entityViewBaseList = (List<EntityViewBase>) null;
if (viewBaseList != null)
{
entityViewBaseList = new List<EntityViewBase>();
foreach (ViewBase viewBase in (IEnumerable<ViewBase>) viewBaseList)
{
EntityViewBase entityViewBase = viewBase as EntityViewBase;
entityViewBaseList.Add(entityViewBase);
}
}
return entityViewBaseList;
}
public List<ViewBase> GetViewsByMorefs(IEnumerable<ManagedObjectReference> moRefs, params string[] properties)
{
Dictionary<string, PropertyFilterSpec> propertyFilterSpecList = new Dictionary<string, PropertyFilterSpec>();
foreach (ManagedObjectReference moRef in moRefs)
{
if (propertyFilterSpecList.ContainsKey(moRef.Type.ToLower()))
{
PropertyFilterSpec propertyFilterSpec = propertyFilterSpecList[moRef.Type.ToLower()];
propertyFilterSpec.ObjectSet = new List<ObjectSpec>((IEnumerable<ObjectSpec>) propertyFilterSpec.ObjectSet)
{
new ObjectSpec() { Obj = moRef }
}.ToArray();
}
else
{
PropertyFilterSpec resultPropertyFilterSpec;
Dictionary<string, List<string>> currentAllowedPropertyPath;
DynamicPropertyFilterSpecGenerator.Generate(moRef, properties, out resultPropertyFilterSpec, out currentAllowedPropertyPath);
propertyFilterSpecList.Add(moRef.Type.ToLower(), resultPropertyFilterSpec);
}
}
PropertyFilterSpec[] propertyFilterSpecArray = new PropertyFilterSpec[propertyFilterSpecList.Values.Count];
propertyFilterSpecList.Values.CopyTo(propertyFilterSpecArray, 0);
ObjectContent[] objectContent = new PropertyCollector(this, this._serviceContent.PropertyCollector).RetrieveProperties(propertyFilterSpecArray);
List<ViewBase> viewsByMorefs = this.GetViewsByMorefs(moRefs, objectContent, propertyFilterSpecList);
return viewsByMorefs;
}
private List<ViewBase> GetViewsByMorefs(IEnumerable<ManagedObjectReference> moRefs, ObjectContent[] objectContent, Dictionary<string, PropertyFilterSpec> propertyFilterSpecList)
{
List<ViewBase> viewBaseList = new List<ViewBase>();
List<string> stringList = new List<string>();
foreach (ManagedObjectReference moRef in moRefs)
stringList.Add(moRef.Value);
Dictionary<string, ObjectContent> objectContentList = new Dictionary<string, ObjectContent>();
foreach (ObjectContent objectContent1 in objectContent)
objectContentList.Add(objectContent1.Obj.Value, objectContent1);
Dictionary<string, ViewBase> generatedManagedObjectList = new Dictionary<string, ViewBase>();
foreach (ObjectContent objectContent1 in objectContent)
{
if (stringList.Contains(objectContent1.Obj.Value))
{
ConstructorInfo constructor = ViewBase.GetViewType(objectContent1.Obj.Type).GetConstructor(new Type[2]
{
typeof (VimClient),
typeof (ManagedObjectReference)
});
if (constructor != null)
{
ViewBase currentObject = (ViewBase) constructor.Invoke(new object[2]
{
(object) this,
(object) objectContent1.Obj
});
ViewBase.SetViewData(currentObject, (string) null, (Dictionary<string, List<string>>) null, objectContentList, generatedManagedObjectList);
viewBaseList.Add(currentObject);
}
}
}
return viewBaseList;
}
我不知道实现此目的的直接方法。
但是,您发布的第二个代码片段(反编译的 FindEntityViews
)显示了对 VMware Property Collector
's method retrieveProperties
. If you use retrievePropertiesEx
then you can provide it with a max count and then call continueRetrievePropertiesEx
.
但请注意,根据我的经验,vSphere API 非常强大,因此除非您有数千台 VM,否则您可能会发现不需要分页(除非您有其他考虑,当然)。
这是我最终如何实现批处理的代码片段。
VimClient vimClient = new VimClient();
vimClient.Connect(host, CommunicationProtocol.Https, 443);
vimClient.Login(userName, password);
string token = string.Empty;
while (true)
{
// Construct the property collector
PropertyCollector propertyCollector = new PropertyCollector(vimClient, vimClient.ServiceContent.PropertyCollector);
// Retrieve a batch of objects
RetrieveResult result;
if (!string.IsNullOrWhiteSpace(token))
result = propertyCollector.ContinueRetrievePropertiesEx(token);
else
{
result = propertyCollector.RetrievePropertiesEx(new[]
{
EntityViewBase.GetSearchFilterSpec(vimClient, vimClient.ServiceContent.RootFolder, new PropertySpec
{
All = false,
Type = typeof(VirtualMachine),
PathSet = null
})
}, new RetrieveOptions { MaxObjects = 100 });
}
// Exit early if no entities retrieved
if (null == result || 0 == result.Objects.Length)
break;
// Get the MoRefs of retrieval result
List<ManagedObjectReference> objectMoRefList = result.Objects.Select(o => o.Obj).ToList();
// Retrieve the properties of objects
List <EntityViewBase> entityList = vimClient.GetViewsByMorefs(objectMoRefList)?.Select(viewBase => viewBase as EntityViewBase).ToList();
// Return the objects and batch retrieval token
token = new BatchRetrievalToken(result.Token)
entityList.ForEach(e => yield return e);
}