diff --git a/heat/engine/resources/instance.py b/heat/engine/resources/instance.py index c7ed05bdd..820141cee 100644 --- a/heat/engine/resources/instance.py +++ b/heat/engine/resources/instance.py @@ -434,10 +434,26 @@ class Instance(resource.Resource): return self.ipaddress or '0.0.0.0' + def _availability_zone(self): + ''' + Return Server's Availability Zone, fetching it from Nova if necessary. + ''' + availability_zone = self.properties[self.AVAILABILITY_ZONE] + if availability_zone is None: + try: + server = self.nova().servers.get(self.resource_id) + availability_zone = getattr(server, + 'OS-EXT-AZ:availability_zone') + except Exception as e: + self.client_plugin().ignore_not_found(e) + return + + return availability_zone + def _resolve_attribute(self, name): res = None if name == self.AVAILABILITY_ZONE_ATTR: - res = self.properties[self.AVAILABILITY_ZONE] + res = self._availability_zone() elif name in self.ATTRIBUTES[1:]: res = self._ipaddress() diff --git a/heat/tests/test_instance.py b/heat/tests/test_instance.py index 49a38ad6f..92698c362 100644 --- a/heat/tests/test_instance.py +++ b/heat/tests/test_instance.py @@ -148,10 +148,13 @@ class InstancesTest(HeatTestCase): self.assertTrue(instance.id > 0) expected_ip = return_server.networks['public'][0] + expected_az = getattr(return_server, 'OS-EXT-AZ:availability_zone') + self.assertEqual(expected_ip, instance.FnGetAtt('PublicIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PublicDnsName')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateDnsName')) + self.assertEqual(expected_az, instance.FnGetAtt('AvailabilityZone')) self.m.VerifyAll() @@ -163,10 +166,13 @@ class InstancesTest(HeatTestCase): self.assertTrue(instance.id > 0) expected_ip = return_server.networks['public'][0] + expected_az = getattr(return_server, 'OS-EXT-AZ:availability_zone') + self.assertEqual(expected_ip, instance.FnGetAtt('PublicIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PublicDnsName')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateDnsName')) + self.assertEqual(expected_az, instance.FnGetAtt('AvailabilityZone')) self.m.VerifyAll() @@ -329,13 +335,28 @@ class InstancesTest(HeatTestCase): self.assertTrue(instance.id > 0) expected_ip = return_server.networks['public'][0] + expected_az = getattr(return_server, 'OS-EXT-AZ:availability_zone') + self.assertEqual(expected_ip, instance.FnGetAtt('PublicIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateIp')) self.assertEqual(expected_ip, instance.FnGetAtt('PublicDnsName')) self.assertEqual(expected_ip, instance.FnGetAtt('PrivateDnsName')) + self.assertEqual(expected_az, instance.FnGetAtt('AvailabilityZone')) self.m.VerifyAll() + def test_instance_create_resolve_az_attribute(self): + return_server = self.fc.servers.list()[1] + instance = self._setup_test_instance(return_server, + 'create_resolve_az_attribute') + self.m.ReplayAll() + scheduler.TaskRunner(instance.create)() + expected_az = getattr(return_server, 'OS-EXT-AZ:availability_zone') + actual_az = instance._availability_zone() + + self.assertEqual(expected_az, actual_az) + self.m.VerifyAll() + def test_instance_create_image_name_err(self): stack_name = 'test_instance_create_image_name_err_stack' (tmpl, stack) = self._setup_test_stack(stack_name) diff --git a/heat/tests/test_volume.py b/heat/tests/test_volume.py index d514182ab..80519b999 100644 --- a/heat/tests/test_volume.py +++ b/heat/tests/test_volume.py @@ -219,11 +219,14 @@ class VolumeTest(BaseVolumeTest): nova.NovaClientPlugin._create().AndReturn(self.fc) self.m.StubOutWithMock(instance.Instance, 'handle_create') self.m.StubOutWithMock(instance.Instance, 'check_create_complete') + self.m.StubOutWithMock(instance.Instance, '_resolve_attribute') self.m.StubOutWithMock(vol.VolumeAttachment, 'handle_create') self.m.StubOutWithMock(vol.VolumeAttachment, 'check_create_complete') instance.Instance.handle_create().AndReturn(None) instance.Instance.check_create_complete(None).AndReturn(True) + instance.Instance._resolve_attribute( + 'AvailabilityZone').MultipleTimes().AndReturn(None) cinder.CinderClientPlugin._create().AndReturn( self.cinder_fc) self.stub_ImageConstraint_validate() diff --git a/heat/tests/v1_1/fakes.py b/heat/tests/v1_1/fakes.py index 900b342e9..bed671177 100644 --- a/heat/tests/v1_1/fakes.py +++ b/heat/tests/v1_1/fakes.py @@ -109,6 +109,7 @@ class FakeHTTPClient(base_client.HTTPClient): "Image Version": "2.1"}}, {"id": "5678", "name": "sample-server2", + "OS-EXT-AZ:availability_zone": "nova2", "OS-EXT-SRV-ATTR:instance_name": "sample-server2", "image": {"id": 2, "name": "sample image"}, @@ -163,6 +164,7 @@ class FakeHTTPClient(base_client.HTTPClient): "name": "sample-server3", "OS-EXT-SRV-ATTR:instance_name": "sample-server3", + "OS-EXT-AZ:availability_zone": "nova3", "image": {"id": 3, "name": "sample image"}, "flavor": {"id": 3, "name": "m1.large"}, "hostId": "9e107d9d372bb6826bd81d3542a419d6",