Search code examples
pythonopenstackopenstack-nova

Why an attribute of the class cannot be called?


I am modifying the code of openstack-nova.

After adding a RESTful api, I got this error:

eption during message handling: AttributeError: 'SchedulerReportClient' object has no attribute 'obj_to_primitive'
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server Traceback (most recent call last):
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/usr/lib/python2.7/site-packages/oslo_messaging/rpc/server.py", line 163, in _process_incoming
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     res = self.dispatcher.dispatch(message)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/usr/lib/python2.7/site-packages/oslo_messaging/rpc/dispatcher.py", line 268, in dispatch
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     return self._do_dispatch(endpoint, method, ctxt, args)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/usr/lib/python2.7/site-packages/oslo_messaging/rpc/dispatcher.py", line 195, in _do_dispatch
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     return self.serializer.serialize_entity(ctxt, result)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/rpc.py", line 130, in serialize_entity
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     return self._base.serialize_entity(context, entity)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/objects/base.py", line 237, in serialize_entity
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     entity)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/objects/base.py", line 223, in _process_iterable
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     for k, v in values.items()})
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/objects/base.py", line 223, in <dictcomp>
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     for k, v in values.items()})
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/objects/base.py", line 245, in serialize_entity
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     entity = entity.obj_to_primitive()
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server   File "/openstack/lib/python2.7/site-packages/nova/scheduler/client/__init__.py", line 37, in __run_method
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server     return getattr(self.instance, __name)(*args, **kwargs)
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server AttributeError: 'SchedulerReportClient' object has no attribute 'obj_to_primitive'
2018-08-30 23:08:10.904 1637 ERROR oslo_messaging.rpc.server 

Associated code is:

def serialize_entity(self, context, entity):
    if isinstance(entity, (tuple, list, set, dict)):
        entity = self._process_iterable(context, self.serialize_entity, entity)
    elif (hasattr(entity, 'obj_to_primitive') and callable(entity.obj_to_primitive)):
        entity = entity.obj_to_primitive()
    return entity

My question is, hasattr(entity, 'obj_to_primitive') is true, so why entity.obj_to_primitive() raises exception?


Solution

  • Look at the last line of the stack trace. You are calling the “method”, but it’s just a wrapper for a corresponding method on self.instance and it’s that getattr that’s failing. The outer attribute lookup succeeded in creating the wrapper, which made hasattr happy, and the wrapper is indeed callable.

    The hasattr test would work if the getattr(self.instance, __name) were computed when the wrapper was created. If the wrapper’s only purpose is to be called (rather than, say, having methods of its own), it could perform a callable check of its own as well. But Python gives itself to EAFP, so here we are.