Description of problem: When i use the python sdk to get storage of a host, it returns a TypeError: __init__() got multiple values for keyword argument 'context' Version-Release number of selected component (if applicable): How reproducible: Always Steps to Reproduce: 1.Make sure there is a Up host in the datacenter 2.Supposed the uuid of the host is "11111111-1111-1111-1111-111111111111" 3.Use following codes to get storage of the host: from ovirtsdk.xml import params from ovirtsdk.api import API api = API(url='127.0.0.1/api',username='admin@internal',password='password',insecure=True,persistent_auth=False) storage = api.hosts.get(id='11111111-1111-1111-1111-111111111111').storage.list() Actual results: it returns TypeError: __init__() got multiple values for keyword argument 'context' Expected results: it returns storage of the host Additional info: Traceback (most recent call last): File "test.py", line 6, in <module> storages = api.hosts.get(id='11111111-1111-1111-1111-111111111111').storage.list() File "/root/sdkforbuild/src/ovirtsdk/infrastructure/brokers.py", line 10400, in list context=self.context File "/root/sdkforbuild/src/ovirtsdk/utils/parsehelper.py", line 148, in toSubCollection new_coll.append(ParseHelper.toSubType(fromItem, toType, parent, **kwargs)) File "/root/sdkforbuild/src/ovirtsdk/utils/parsehelper.py", line 128, in toSubType return toType(parent, fromItem, **kwargs) TypeError: __init__() got multiple values for keyword argument 'context'
This happens because we have a sub collection of hosts that doesn't follow the convention of having names for collections in plural and names for entities in singular: /hosts/{host:id}/storage Note that the name is *storage* instead of *storages*. The generator of the SDK assumes this convention, and in this particular case it generates a HostStorage class for the entity that overwrites the same HostStorage class for the collection. As a result when the SDK tries to create the instance for the collection it is actually creating an instance of the entity, thus the constructor (the __init__() method of the HostStorage class) receives wrong arguments. The ideal fix for this would be to rename that collection to "storages", but we can't do that as it would break backwards compatibility. Instead of that we will need to introduce an exception in the code generator, which isn't trivial.
(In reply to Juan Hernández from comment #1) > This happens because we have a sub collection of hosts that doesn't follow > the convention of having names for collections in plural and names for > entities in singular: > > /hosts/{host:id}/storage > > Note that the name is *storage* instead of *storages*. > > The generator of the SDK assumes this convention, and in this particular > case it generates a HostStorage class for the entity that overwrites the > same HostStorage class for the collection. As a result when the SDK tries to > create the instance for the collection it is actually creating an instance > of the entity, thus the constructor (the __init__() method of the > HostStorage class) receives wrong arguments. > > The ideal fix for this would be to rename that collection to "storages", but > we can't do that as it would break backwards compatibility. Instead of that > we will need to introduce an exception in the code generator, which isn't > trivial. OK, i see. Thank you for your reply.
The proposed patch should fix the issue in the code generator. Once merged the SDK needs to be regenerated. I see that you are running the SDK from the source, so you may want to apply the patch and re-generate yourself. You can also apply the following patch to the brokers.py file: diff --git a/src/ovirtsdk/infrastructure/brokers.py b/src/ovirtsdk/infrastructure/brokers.py index e8fb278..3a4462e 100644 --- a/src/ovirtsdk/infrastructure/brokers.py +++ b/src/ovirtsdk/infrastructure/brokers.py @@ -7910,7 +7910,7 @@ class Host(params.Host, Base): self.numanodes = HostNumaNodes(self, context) self.permissions = HostPermissions(self, context) self.statistics = HostStatistics(self, context) - self.storage = HostStorage(self, context) + self.storage = HostStorages(self, context) self.tags = HostTags(self, context) def __new__(cls, host, context): @@ -9318,7 +9318,29 @@ class HostStatistics(Base): context=self.context ) -class HostStorage(Base): +class HostStorage(params.HostStorage, Base): + def __init__(self, host, storage, context): + Base.__init__(self, context) + self.parentclass = host + self.superclass = storage + + #SUB_COLLECTIONS + def __new__(cls, host, storage, context): + if storage is None: return None + obj = object.__new__(cls) + obj.__init__(host, storage, context) + return obj + + def __getProxy(self): + proxy = context.manager[self.context].get('proxy') + if proxy: + return proxy + #This may happen only if sdk was explicitly disconnected + #using .disconnect() method, but resource instance ref. is + #still available at client's code. + raise DisconnectedError + +class HostStorages(Base): def __init__(self, host , context): Base.__init__(self, context)
(In reply to Juan Hernández from comment #3) > The proposed patch should fix the issue in the code generator. Once merged > the SDK needs to be regenerated. I see that you are running the SDK from the > source, so you may want to apply the patch and re-generate yourself. You can > also apply the following patch to the brokers.py file: > > diff --git a/src/ovirtsdk/infrastructure/brokers.py > b/src/ovirtsdk/infrastructure/brokers.py > index e8fb278..3a4462e 100644 > --- a/src/ovirtsdk/infrastructure/brokers.py > +++ b/src/ovirtsdk/infrastructure/brokers.py > @@ -7910,7 +7910,7 @@ class Host(params.Host, Base): > self.numanodes = HostNumaNodes(self, context) > self.permissions = HostPermissions(self, context) > self.statistics = HostStatistics(self, context) > - self.storage = HostStorage(self, context) > + self.storage = HostStorages(self, context) > self.tags = HostTags(self, context) > > def __new__(cls, host, context): > @@ -9318,7 +9318,29 @@ class HostStatistics(Base): > context=self.context > ) > > -class HostStorage(Base): > +class HostStorage(params.HostStorage, Base): > + def __init__(self, host, storage, context): > + Base.__init__(self, context) > + self.parentclass = host > + self.superclass = storage > + > + #SUB_COLLECTIONS > + def __new__(cls, host, storage, context): > + if storage is None: return None > + obj = object.__new__(cls) > + obj.__init__(host, storage, context) > + return obj > + > + def __getProxy(self): > + proxy = context.manager[self.context].get('proxy') > + if proxy: > + return proxy > + #This may happen only if sdk was explicitly disconnected > + #using .disconnect() method, but resource instance ref. is > + #still available at client's code. > + raise DisconnectedError > + > +class HostStorages(Base): > > def __init__(self, host , context): > Base.__init__(self, context) Thank you very much. The patch works well.
The fix for the code generator has been merged, now the SDK needs to be regenerated.
Verified. sdk: ovirt-engine-sdk-python-3.5.0.5 ovirt: oVirt Engine Version: 3.5.0-0.0.master.20140821064931.gitb794d66.el6
oVirt 3.5 has been released and should include the fix for this issue.