Going to add a detailed explanation of what's going on here, now that I've traced through all of it.
We get a request to list instances from the API and by default that will do a join with the 'services' table to return service-related information with instances:
Then, in the object code, we call the _get_by_filters_impl method (notice it's decorated with '@db.select_db_reader_mode', which will start the database transaction context tracking):
Which will generate a uuid if one isn't present and attempt to save it, which will fail with "TypeError: Can't upgrade a READER transaction to a WRITER mid-transaction" because we're still nested under the '@db.select_db_reader_mode' decorator from the InstanceList._get_by_filters_impl method:
This problem doesn't exist past Pike because the implementation in compute/api was changed to call the instance_list.get_instance_objects_sorted API instead:
Going to add a detailed explanation of what's going on here, now that I've traced through all of it.
We get a request to list instances from the API and by default that will do a join with the 'services' table to return service-related information with instances:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/api/ openstack/ compute/ servers. py#L298
Then, in the compute/api, we go to list the instances across cells:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/compute/ api.py# L2463
Which will call _get_instances_ by_filters per cell:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/compute/ api.py# L2561
Which will call objects. InstanceList. get_by_ filters to do the database query:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/compute/ api.py# L2593
Then, in the object code, we call the _get_by_ filters_ impl method (notice it's decorated with '@db.select_ db_reader_ mode', which will start the database transaction context tracking):
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/objects/ instance. py#L1222
And nested inside of that database transaction context tracking is a call to _make_instance_ list:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/objects/ instance. py#L1235
Which calls _from_db_object for each returned instance (joined with 'services' in this case):
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/objects/ instance. py#L1197
Which will construct a ServiceList of Service objects:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/objects/ instance. py#L446
Which will call Service. _from_db_ object as the objects are being created:
https:/ /github. com/openstack/ oslo.versionedo bjects/ blob/c86c6ed/ oslo_versionedo bjects/ base.py# L1120
Which will generate a uuid if one isn't present and attempt to save it, which will fail with "TypeError: Can't upgrade a READER transaction to a WRITER mid-transaction" because we're still nested under the '@db.select_ db_reader_ mode' decorator from the InstanceList. _get_by_ filters_ impl method:
https:/ /github. com/openstack/ nova/blob/ 9465d1c/ nova/objects/ service. py#L243
------- ------- ------- ------- --
This problem doesn't exist past Pike because the implementation in compute/api was changed to call the instance_ list.get_ instance_ objects_ sorted API instead:
https:/ /github. com/openstack/ nova/blob/ stable/ queens/ nova/compute/ api.py# L2460
And that API has exited the previous database transaction context manager before it goes to call _make_instance_ list:
https:/ /github. com/openstack/ nova/blob/ stable/ queens/ nova/compute/ instance_ list.py# L105