[openstack-dev] [Nova][vmware] A new VMwareAPISession

Gary Kotton gkotton at vmware.com
Thu Feb 6 12:07:35 UTC 2014


On 2/6/14 1:58 PM, "Matthew Booth" <mbooth at redhat.com> wrote:
>On 06/02/14 11:24, Gary Kotton wrote:
>> Hi,
>> Thanks for the detailed mail. For the first step of moving the code into
>> OSLO we are trying to be as conservative as possible (similar to the
>>fork
>> lift of the scheduler code). That is, we are taking working code and
>> moving it to the common library, not doing any rewrites and using the
>>same
>> functionality and flows. Once that is in and stable then we should start
>> to work on making it more robust.
>>In moving the code to oslo there's going to be some donkey work required
>to find all current uses of the code and fix them up. I'm proposing this
>change now because it would be a great opportunity to do that donkey
>work just once.

The work has already been done - https://review.openstack.org/#/c/70175/
This also has a +1 from the minesweeper which means that the API's are
working correctly.
>>Also notice that the actual usage of the proposed API is very similar to
>the old one. The donkey work would essentially amount to:
>>* Change all instances of vim.Method(object, args) in vim_util to
>vim.call(object, Method, args)
>>* Change all instances of session._call_method(vim_util, 'method', args)
>everywhere to vim_util.method(session, args)
>>Note that the changes are mechanical, and you're going to have to touch
>it for the move to oslo anyway.
>>Also note that the proposed API would, at least in the first instance,
>be substantially a cut and paste of existing code.
>>Incidentally the code that was copied is
>> not Nova's but Cinders. When the Cinder driver was being posted the team
>> made a considerable amount of improvements to the driver.
>>I've read it. It's certainly much prettier python, but the design is the
>same as the Nova driver.
>>> The reason that the _call_method is used is that this deals with session
>> failures and has support for retries etc. Please see
>>>>https://urldefense.proofpoint.com/v1/url?u=https://review.openstack.org/%
>>23/c/61555/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=eH0pxTUZo8NPZyF6hgoMQu%
>>2BfDtysg45MkPhCZFxPEq8%3D%0A&m=co4zzllM3r0kGeYRL5kq9xJgzPe0T9gSqW%2B2XOJ%
>>2FTKY%3D%0A&s=3efe43037653b6caff24d2d253f566c1a1defa1fe4f0a902f57a17bf1bf
>>d2311.
>>That's one of the explicit design goals of the proposed API. Notice that
>mistakes like this are no longer possible, as the call() method does
>session management and retries, and there is no other exposed interface
>to make remote API calls.
>>> I certainly agree that we can improve the code moving forwards. I think
>> that the first priority should get a working version in OSLO. Once it is
>> up and running then we should certain start addressing issues that you
>> have raised.
>>I think it's almost no additional work to fix it at this stage, given
>that the code is being refactored anyway and it will require donkey work
>in the driver to match up with it. If we wait until later it becomes a
>whole additional task.
>>Matt
>>> Thanks
>> Gary
>>>>>> On 2/6/14 12:43 PM, "Matthew Booth" <mbooth at redhat.com> wrote:
>>>>> There's currently an effort to create a common internal API to the
>>> vSphere/ESX API:
>>>>>>>>>https://urldefense.proofpoint.com/v1/url?u=https://blueprints.launchpad.
>>>ne
>>>>>>t/oslo/%2Bspec/vmware-api&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=eH0pxTUZ
>>>o8
>>>>>>NPZyF6hgoMQu%2BfDtysg45MkPhCZFxPEq8%3D%0A&m=8nIWvYjr1NVyVpYg3ZwDiG5VZAeq
>>>Sk
>>>>>>w8MPwOPQ4k8zs%3D%0A&s=facc68779808dd3d6fb45fbb9a7addb9c8f392421bfe850a99
>>>41
>>> ec732195d641
>>>>>> I see there's some code already in place which essentially copies
>>>what's
>>> currently in Nova. Having spent some time digging in this code
>>>recently,
>>> I would take the opportunity of this refactor to fix a few design
>>>issues
>>> in the current code, which has an 'organic' feel to it.
>>>>>> The current code has 2 main objects:
>>>>>> * driver.VMwareAPISession
>>>>>> This object creates a Vim object and manages a session in it. It
>>> provides _call_method(), which calls a method in an external module and
>>> retries it if it failed because of a bad session. _call_method has also
>>> had shoehorned into it the ability to make direct Vim calls.
>>>>>> * vim.Vim
>>>>>> This object creates a connection to vSphere/ESX and provides an API to
>>> make remote calls.
>>>>>> Here are 2 typical uses of the API, both taken from vmops.py:
>>>>>> ---
>>> hardware_devices = self._session._call_method(vim_util,
>>> "get_dynamic_property", vm_ref,
>>> "VirtualMachine", "config.hardware.device")
>>> ---
>>>>>> This is using _call_method() to wrap:
>>>>>> vim_util.get_dynamic_property(vm_ref, "VirtualMachine,
>>> "config.hardware.device")
>>>>>> vim_util.get_dynamic_property() does an amount of work and creates a
>>> number of objects before ultimately calling:
>>>>>> return vim.RetrievePropertiesEx(...)
>>>>>> Note that in the event that this call fails, for example due to a
>>> session timeout or a network error, the entire function will be
>>> needlessly re-executed.
>>>>>> ---
>>> reconfig_task = self._session._call_method(
>>> self._session._get_vim(),
>>> "ReconfigVM_Task", vm_ref,
>>> spec=vmdk_attach_config_spec)
>>> self._session._wait_for_task(instance_uuid, reconfig_task)
>>> ---
>>>>>> This is using _call_method() to wrap:
>>>>>> reconfig_task = vim.ReconfigVM_Task(
>>> vm_ref, spec=vmdk_attach_config_spec)
>>> wait_for_task(reconfig_task) [1]
>>>>>> Things wrong with both of the above:
>>> * It obfuscates the intention.
>>> * It makes backtraces confusing.
>>> * It's possible to forget to use _call_method() and it will still work,
>>> resulting in uncaught intermittent faults.
>>>>>> Additionally, the choice of the separation of driver.VMwareAPISession
>>> and vim.Vim results in several confused messes. In particular, notice
>>> how the fault checker called by vim_request_handler can raise
>>> FAULT_NOT_AUTHENTICATED, which then has to be caught and rechecked by
>>> the driver because the required context isn't available in Vim.
>>>>>> As somebody who has come to this code recently, I can also attest that
>>> the varying uses of _call_method with a module or a vim object, and the
>>> fact that it isn't used at all in some places, is highly confusing to
>>> anybody who isn't intimately familiar with the driver.
>>>>>> There's also a subtle point to do with the Vim object's use of
>>> __getattr__ to syntactically sugar remote API calls: it can lead to
>>> non-obvious behaviour. An example of this is
>>>>>>https://urldefense.proofpoint.com/v1/url?u=https://bugs.launchpad.net/no
>>>va
>>>>>>/%2Bbug/1275773&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=eH0pxTUZo8NPZyF6hg
>>>oM
>>>>>>Qu%2BfDtysg45MkPhCZFxPEq8%3D%0A&m=8nIWvYjr1NVyVpYg3ZwDiG5VZAeqSkw8MPwOPQ
>>>4k
>>>>>>8zs%3D%0A&s=db08b5e7f320ff7df857d33a65fbe96e61783518e4e4ae2a65020b12bd51
>>>51
>>> a1, where the use of a Vim
>>> object in boolean context to test for None[2] resulted in an attempt to
>>> make a remote API call '__nonzero__'. Another example is
>>>>>>https://urldefense.proofpoint.com/v1/url?u=https://review.openstack.org/
>>>%2
>>>>>>3/c/69652/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=eH0pxTUZo8NPZyF6hgoMQu%
>>>2B
>>>>>>fDtysg45MkPhCZFxPEq8%3D%0A&m=8nIWvYjr1NVyVpYg3ZwDiG5VZAeqSkw8MPwOPQ4k8zs
>>>%3
>>> D%0A&s=5a9b7e98691181391abe0366d40b066f01ac68ae3231d10a3711f2c54287dca6
>>> where the indirection, combined
>>> with my next point about object orientedness, disguised a syntactically
>>> incorrect call which wasn't being covered by a test.
>>>>>> The syntactic sugar isn't even working in our favour, as it doesn't
>>> model the remote API. The vSphere API is very much object oriented,
>>>with
>>> methods being properties of the managed object they are being called on
>>> (e.g. a PropertyCollector or SessionManager). With that in mind, a
>>> python programmer would expect to do something like:
>>>>>> propertyCollector.RetrievePropertiesEx(<args>)
>>>>>> However, what we actually do is:
>>>>>> vim.RetrievePropertiesEx(propertyCollector, <args>)
>>>>>> With all of the above in mind, I would replace both VMwareAPISession
>>>and
>>> Vim with a single new class called VIM (not to be confused with the old
>>> one).
>>>>>> class VIM(object):
>>> def __init__(self, host_ip=CONF.vmware.host_ip,
>>> username=CONF.vmware.host_username,
>>> password=CONF.vmware.host_password,
>>> retry_count=CONF.vmware.api_retry_count,
>>> scheme="https"):
>>> # This same arguments as to the old VMwareAPISession
>>> # Create a suds client and log in
>>>>>> def get_service_object():
>>> # Return a service object using the suds client
>>>>>> def call(object, method, *args, **kwargs):
>>> # Ditch __getattr__(). No unexpected remote API calls.
>>> # call() always takes the same first 2 arguments.
>>> #
>>> # call() will do session management, and retry the call if it fails.
>>> # It will also create a new suds client if necessary, for example
>>> # in the event of a network error. Note that it will only retry a
>>> # single api call, not a whole function.
>>> #
>>> # All remote API calls outside the VIM object will use this method.
>>> #
>>> # Fault checking lives here.
>>>>>> def _call_no_session(object, method, *args, **kwargs):
>>> # In doing session management itself, there are certain calls which
>>> # it doesn't make sense to wrap in session management (e.g. Login).
>>> # This method should not be used outside the VIM object itself.
>>> # call() will be a wrapper round this method.
>>>>>> def wait_for_task(task):
>>> # Block until completion of a task
>>> # N.B. We could potentially make this automatic in call(), as we
>>> # currently always wait for completion of tasks. call() would then
>>> # return the result of the task.
>>>>>> With this change, all calls in vim_util would be updated to use
>>> VIM.call(), the same as all other code. In this way, session retries
>>> would be automatic and confined to just the remote API call.
>>>>>> Incidentally, I can cut/paste this to the blueprint if that's a better
>>> place for this kind of discussion.
>>>>>> Matt
>>>>>> [1] Note that the first argument to the current _wait_for_task() isn't
>>> actually used.
>>>>>> [2] PEP8 recommends against this, btw.
>>> -- 
>>> Matthew Booth, RHCA, RHCSS
>>> Red Hat Engineering, Virtualisation Team
>>>>>> GPG ID: D33C3490
>>> GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
>>>>>> _______________________________________________
>>> OpenStack-dev mailing list
>>> OpenStack-dev at lists.openstack.org
>>>>>>https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cg
>>>i-
>>>>>>bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r
>>>=e
>>>>>>H0pxTUZo8NPZyF6hgoMQu%2BfDtysg45MkPhCZFxPEq8%3D%0A&m=8nIWvYjr1NVyVpYg3Zw
>>>Di
>>>>>>G5VZAeqSkw8MPwOPQ4k8zs%3D%0A&s=84e7db6622831d91bbbefc376aa524bf9c231412f
>>>56
>>> 86eb02f10ba386df76d0e
>>>>>> _______________________________________________
>> OpenStack-dev mailing list
>> OpenStack-dev at lists.openstack.org
>>>>https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi
>>-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r
>>=eH0pxTUZo8NPZyF6hgoMQu%2BfDtysg45MkPhCZFxPEq8%3D%0A&m=co4zzllM3r0kGeYRL5
>>kq9xJgzPe0T9gSqW%2B2XOJ%2FTKY%3D%0A&s=42623707260a67a0f10ba942de955d96167
>>4bd36f1b8a7d2dbdef6bffe4fb987
>>>>>-- 
>Matthew Booth, RHCA, RHCSS
>Red Hat Engineering, Virtualisation Team
>>GPG ID: D33C3490
>GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490



More information about the OpenStack-dev mailing list

AltStyle によって変換されたページ (->オリジナル) /