@@ -0,0 +1,3205 @@
+# Licensed under the Apache License, Version 2.0 (the %22License%22); you may%0A# not use this file except in compliance with the License. You may obtain%0A# a copy of the License at%0A#%0A#      http://www.apache.org/licenses/LICENSE-2.0%0A#%0A# Unless required by applicable law or agreed to in writing, software%0A# distributed under the License is distributed on an %22AS IS%22 BASIS, WITHOUT%0A# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the%0A# License for the specific language governing permissions and limitations%0A# under the License.%0A%0Aimport six%0A%0Aimport nova.context%0Afrom nova import db%0Afrom nova import objects%0Afrom nova import test%0A%0A%0Aclass InstanceListWithServicesTestCase(test.TestCase):%0A    %22%22%22Test the scenario listing instances whose services may not have a UUID.%0A%0A    We added a UUID field to the 'services' table in Pike, so after an upgrade,%0A    we generate a UUID and save it to the service record upon access if it's an%0A    older record that does not already have a UUID.%0A%0A    Now, when we list instances through the API, the instances query is joined%0A    with the 'services' table in order to provide service-related information.%0A    The bug in Pike was that we were already inside of a 'reader' database%0A    transaction context when we tried to compile the instance list, which%0A    eventually led to an error:%0A%0A      TypeError: Can't upgrade a READER transaction to a WRITER mid-transaction%0A%0A    because we also tried to write the newly generated service UUID to the%0A    service record while still nested under the 'reader' context.%0A%0A    This test verifies that we are able to list instances joined with services%0A    even if the associated service record does not yet have a UUID.%0A    %22%22%22%0A    def setUp(self):%0A        super(InstanceListWithServicesTestCase, self).setUp()%0A        self.context = nova.context.RequestContext('fake-user', 'fake-project')%0A%0A    def test_instance_list_service_with_no_uuid(self):%0A        # Create a nova-compute service record with a host that will match the%0A        # instance's host, with no uuid. We can't do this through the%0A        # Service object because it will automatically generate a uuid.%0A        service = db.service_create(self.context, %7B'host': 'fake-host',%0A                                                   'binary': 'nova-compute'%7D)%0A        self.assertIsNone(service%5B'uuid'%5D)%0A%0A        # Create an instance whose host will match the service with no uuid%0A        inst = objects.Instance(context=self.context,%0A                                project_id=self.context.project_id,%0A                                host='fake-host')%0A        inst.create()%0A%0A        # TODO(melwitt): Remove these asserts when the bug is fixed.%0A        ex = self.assertRaises(TypeError, objects.InstanceList.get_by_filters,%0A                               self.context, %7B%7D, expected_attrs=%5B'services'%5D)%0A        self.assertIn(%22Can't upgrade a READER transaction to a WRITER %22%0A                      %22mid-transaction%22, six.text_type(ex))%0A%0A        # TODO(melwitt): Uncomment this assert when the bug is fixed.%0A        # insts = objects.InstanceList.get_by_filters(%0A        #     self.context, %7B%7D, expected_attrs=%5B'services'%5D)%0A        # self.assertEqual(1, len(insts))%0A

Add functional regression test for bug 1746509