Add API to get the entity inventory path

This new API provides the inventory path for a given entity reference.
Currently, the Nova transfer of images feature fails if the datacenter
is located in folders. This API has to be called prior to any HTTP
access to datastores.

Change-Id: I14066601816584689fb955927496d250ed825dc2
This commit is contained in:
Arnaud Legendre 2014-09-18 12:30:14 -07:00 committed by Arnaud Legendre
parent def85dd151
commit 264e428b4f
2 changed files with 89 additions and 0 deletions

View File

@ -423,3 +423,50 @@ def get_vc_version(session):
:return: vCenter version
"""
return session.vim.service_content.about.version
def get_inventory_path(vim, entity_ref, max_objects=100):
"""Get the inventory path of a managed entity.
:param vim: Vim object
:param entity_ref: managed entity reference
:param max_objects: maximum number of objects that should be returned in
a single call
:return: inventory path of the entity_ref
"""
client_factory = vim.client.factory
property_collector = vim.service_content.propertyCollector
prop_spec = build_property_spec(client_factory, 'ManagedEntity',
['name', 'parent'])
select_set = build_selection_spec(client_factory, 'ParentTraversalSpec')
select_set = build_traversal_spec(
client_factory, 'ParentTraversalSpec', 'ManagedEntity', 'parent',
False, [select_set])
obj_spec = build_object_spec(client_factory, entity_ref, select_set)
prop_filter_spec = build_property_filter_spec(client_factory,
[prop_spec], [obj_spec])
options = client_factory.create('ns0:RetrieveOptions')
options.maxObjects = max_objects
retrieve_result = vim.RetrievePropertiesEx(
property_collector,
specSet=[prop_filter_spec],
options=options)
entity_name = None
propSet = None
path = ""
while retrieve_result:
for obj in retrieve_result.objects:
if hasattr(obj, 'propSet'):
propSet = obj.propSet
if len(propSet) >= 1 and not entity_name:
entity_name = propSet[0].val
elif len(propSet) >= 1:
path = '%s/%s' % (propSet[0].val, path)
retrieve_result = continue_retrieval(vim, retrieve_result)
# NOTE(arnaud): slice to exclude the root folder from the result.
if propSet is not None and len(propSet) > 0:
path = path[len(propSet[0].val):]
if entity_name is None:
entity_name = ""
return '%s%s' % (path, entity_name)

View File

@ -17,6 +17,8 @@
Unit tests for VMware API utility module.
"""
import collections
import mock
from oslo.vmware import vim_util
@ -319,3 +321,43 @@ class VimUtilTest(base.TestCase):
session.vim.service_content.about.version = expected_version
version = vim_util.get_vc_version(session)
self.assertEqual(expected_version, version)
def test_get_inventory_path_folders(self):
ObjectContent = collections.namedtuple('ObjectContent', ['propSet'])
DynamicProperty = collections.namedtuple('Property', ['name', 'val'])
obj1 = ObjectContent(propSet=[
DynamicProperty(name='Datacenter', val='dc-1'),
])
obj2 = ObjectContent(propSet=[
DynamicProperty(name='Datacenter', val='folder-2'),
])
obj3 = ObjectContent(propSet=[
DynamicProperty(name='Datacenter', val='folder-1'),
])
objects = ['foo', 'bar', obj1, obj2, obj3]
result = mock.sentinel.objects
result.objects = objects
session = mock.Mock()
session.vim.RetrievePropertiesEx = mock.Mock()
session.vim.RetrievePropertiesEx.return_value = result
entity = mock.Mock()
inv_path = vim_util.get_inventory_path(session.vim, entity, 100)
self.assertEqual('/folder-2/dc-1', inv_path)
def test_get_inventory_path_no_folder(self):
ObjectContent = collections.namedtuple('ObjectContent', ['propSet'])
DynamicProperty = collections.namedtuple('Property', ['name', 'val'])
obj1 = ObjectContent(propSet=[
DynamicProperty(name='Datacenter', val='dc-1'),
])
objects = ['foo', 'bar', obj1]
result = mock.sentinel.objects
result.objects = objects
session = mock.Mock()
session.vim.RetrievePropertiesEx = mock.Mock()
session.vim.RetrievePropertiesEx.return_value = result
entity = mock.Mock()
inv_path = vim_util.get_inventory_path(session.vim, entity, 100)
self.assertEqual('dc-1', inv_path)