]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Retrieve the list of availability zones from nova in Fn::GetAZs
authorThomas Herve <therve@gmail.com>
Tue, 30 Apr 2013 16:44:17 +0000 (18:44 +0200)
committerThomas Herve <therve@gmail.com>
Wed, 1 May 2013 10:05:05 +0000 (12:05 +0200)
Fixes: bug #1096001
Change-Id: Ie5c46ae038dff4f53ba8d722e878583044bd194c

heat/engine/parser.py
heat/engine/template.py
heat/tests/test_autoscaling.py
heat/tests/test_instance_group.py
heat/tests/test_loadbalancer.py
heat/tests/test_parser.py
heat/tests/v1_1/fakes.py

index f5d45ce7df6136e3d79abbaa3b5fd11eafad9901..81c782fc6fd8a97c8ea622a92cd0b677dca2fb80 100644 (file)
@@ -62,6 +62,8 @@ class Stack(object):
     created_time = timestamp.Timestamp(db_api.stack_get, 'created_at')
     updated_time = timestamp.Timestamp(db_api.stack_get, 'updated_at')
 
+    _zones = None
+
     def __init__(self, context, stack_name, tmpl, parameters=None,
                  stack_id=None, state=None, state_description='',
                  timeout_mins=60, resolve_data=True, disable_rollback=True):
@@ -558,14 +560,21 @@ class Stack(object):
         # TODO(asalkeld) if any of this fails we Should
         # restart the whole stack
 
+    def get_availability_zones(self):
+        if self._zones is None:
+            self._zones = [
+                zone.zoneName for zone in
+                self.clients.nova().availability_zones.list(detailed=False)]
+        return self._zones
+
     def resolve_static_data(self, snippet):
-        return resolve_static_data(self.t, self.parameters, snippet)
+        return resolve_static_data(self.t, self, self.parameters, snippet)
 
     def resolve_runtime_data(self, snippet):
         return resolve_runtime_data(self.t, self.resources, snippet)
 
 
-def resolve_static_data(template, parameters, snippet):
+def resolve_static_data(template, stack, parameters, snippet):
     '''
     Resolve static parameters, map lookups, etc. in a template.
 
@@ -573,13 +582,14 @@ def resolve_static_data(template, parameters, snippet):
 
     >>> template = Template(template_format.parse(template_path))
     >>> parameters = Parameters('stack', template, {'KeyName': 'my_key'})
-    >>> resolve_static_data(template, parameters, {'Ref': 'KeyName'})
+    >>> resolve_static_data(template, None, parameters, {'Ref': 'KeyName'})
     'my_key'
     '''
     return transform(snippet,
                      [functools.partial(template.resolve_param_refs,
                                         parameters=parameters),
-                      template.resolve_availability_zones,
+                      functools.partial(template.resolve_availability_zones,
+                                        stack=stack),
                       template.resolve_find_in_map,
                       template.reduce_joins])
 
index 31ca9ddf75e42017af49049efb6b93925c37d8c1..6078fed2f4b53ac9befc6106c55627add8ae6f60 100644 (file)
@@ -89,7 +89,7 @@ class Template(collections.Mapping):
                         handle_find_in_map, s)
 
     @staticmethod
-    def resolve_availability_zones(s):
+    def resolve_availability_zones(s, stack):
         '''
             looking for { "Fn::GetAZs" : "str" }
         '''
@@ -98,7 +98,10 @@ class Template(collections.Mapping):
                     isinstance(value, basestring))
 
         def handle_get_az(ref):
-            return ['nova']
+            if stack is None:
+                return ['nova']
+            else:
+                return stack.get_availability_zones()
 
         return _resolve(match_get_az, handle_get_az, s)
 
index a1b937f39d4ac2a6910f560552dfad89b200f11d..8a88ede531eb8d02e3fd952c7eb8b2db7e3a16ca 100644 (file)
@@ -25,10 +25,12 @@ from heat.common import template_format
 from heat.engine.resources import autoscaling as asc
 from heat.engine.resources import loadbalancer
 from heat.engine.resources import instance
+from heat.engine import clients
 from heat.engine import parser
 from heat.engine import scheduler
 from heat.engine.resource import Metadata
 from heat.openstack.common import timeutils
+from heat.tests.v1_1 import fakes
 from heat.tests.common import HeatTestCase
 from heat.tests.utils import setup_dummy_db
 
@@ -37,6 +39,9 @@ class AutoScalingTest(HeatTestCase):
     def setUp(self):
         super(AutoScalingTest, self).setUp()
         setup_dummy_db()
+        self.fc = fakes.FakeClient()
+        self.m.StubOutWithMock(clients.OpenStackClients, 'nova')
+        clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
 
     def load_template(self):
         self.path = os.path.dirname(os.path.realpath(__file__)).\
@@ -47,6 +52,7 @@ class AutoScalingTest(HeatTestCase):
         return t
 
     def parse_stack(self, t):
+        self.m.ReplayAll()
         ctx = context.RequestContext.from_dict({
             'tenant': 'test_tenant',
             'username': 'test_username',
index 0d6764b98fb7d3620e755b7191272b8efde3a802..c6bc46b6c624182defe8863af83b4995571b81cb 100644 (file)
@@ -25,6 +25,7 @@ from heat.common import template_format
 from heat.engine.resources import autoscaling as asc
 from heat.engine.resources import instance
 from heat.engine.resources import loadbalancer
+from heat.engine import clients
 from heat.engine import parser
 from heat.engine import scheduler
 from heat.tests.common import HeatTestCase
@@ -37,6 +38,8 @@ class InstanceGroupTest(HeatTestCase):
         self.fc = fakes.FakeClient()
         self.m.StubOutWithMock(loadbalancer.LoadBalancer, 'reload')
         setup_dummy_db()
+        self.m.StubOutWithMock(clients.OpenStackClients, 'nova')
+        clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
 
     def load_template(self):
         self.path = os.path.dirname(os.path.realpath(__file__)).\
@@ -47,6 +50,7 @@ class InstanceGroupTest(HeatTestCase):
         return t
 
     def parse_stack(self, t):
+        self.m.ReplayAll()
         ctx = context.RequestContext.from_dict({
             'tenant': 'test_tenant',
             'username': 'test_username',
index af17b9d266768bc929f3fc50e0a57b5f49257487..35f9782f269a062717ee09692fb79bc375206940 100644 (file)
@@ -22,6 +22,7 @@ from heat.common import exception
 from heat.common import config
 from heat.common import context
 from heat.common import template_format
+from heat.engine import clients
 from heat.engine import parser
 from heat.engine import scheduler
 from heat.engine.resources import instance
@@ -50,8 +51,7 @@ class LoadBalancerTest(HeatTestCase):
         super(LoadBalancerTest, self).setUp()
         config.register_engine_opts()
         self.fc = fakes.FakeClient()
-        self.m.StubOutWithMock(lb.LoadBalancer, 'nova')
-        self.m.StubOutWithMock(instance.Instance, 'nova')
+        self.m.StubOutWithMock(clients.OpenStackClients, 'nova')
         self.m.StubOutWithMock(self.fc.servers, 'create')
         self.m.StubOutWithMock(Metadata, '__set__')
         self.fkc = test_fakes.FakeKeystoneClient(
@@ -96,8 +96,9 @@ class LoadBalancerTest(HeatTestCase):
         self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
         wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fkc)
 
-        lb.LoadBalancer.nova().AndReturn(self.fc)
-        instance.Instance.nova().MultipleTimes().AndReturn(self.fc)
+        clients.OpenStackClients.nova(
+            "compute").MultipleTimes().AndReturn(self.fc)
+        clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
         self.fc.servers.create(
             flavor=2, image=745, key_name='test',
             meta=None, nics=None, name=u'test_stack.LoadBalancer.LB_instance',
@@ -107,8 +108,6 @@ class LoadBalancerTest(HeatTestCase):
         Metadata.__set__(mox.IgnoreArg(),
                          mox.IgnoreArg()).MultipleTimes().AndReturn(None)
 
-        lb.LoadBalancer.nova().MultipleTimes().AndReturn(self.fc)
-
         self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status')
         wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
         self.m.ReplayAll()
index 1b1d6775f5cecf8b9a035c7700eaf346dc120395..08e316855bc64e191c2dce26310f197e427fc389 100644 (file)
@@ -18,6 +18,7 @@ import uuid
 from heat.common import context
 from heat.common import exception
 from heat.common import template_format
+from heat.engine import clients
 from heat.engine import resource
 from heat.engine import parser
 from heat.engine import parameters
@@ -25,6 +26,7 @@ from heat.engine import template
 
 from heat.tests.common import HeatTestCase
 from heat.tests.utils import setup_dummy_db
+from heat.tests.v1_1 import fakes
 from heat.tests.utils import stack_delete_after
 from heat.tests import generic_resource as generic_rsrc
 
@@ -280,6 +282,23 @@ class TemplateTest(HeatTestCase):
         self.assertRaises(TypeError, parser.Template.resolve_base64,
                           dict_snippet)
 
+    def test_get_azs(self):
+        snippet = {"Fn::GetAZs": ""}
+        self.assertEqual(
+            parser.Template.resolve_availability_zones(snippet, None),
+            ["nova"])
+
+    def test_get_azs_with_stack(self):
+        snippet = {"Fn::GetAZs": ""}
+        stack = parser.Stack(None, 'test_stack', parser.Template({}))
+        self.m.StubOutWithMock(clients.OpenStackClients, 'nova')
+        fc = fakes.FakeClient()
+        clients.OpenStackClients.nova().MultipleTimes().AndReturn(fc)
+        self.m.ReplayAll()
+        self.assertEqual(
+            parser.Template.resolve_availability_zones(snippet, stack),
+            ["nova1"])
+
 
 class StackTest(HeatTestCase):
     def setUp(self):
index 9fdf5fc99b37ff04ca759c822c084b5814e93e56..cbccab1518d7f34e636c83ba00ab7ed51adfc561 100644 (file)
@@ -821,3 +821,6 @@ class FakeHTTPClient(base_client.HTTPClient):
         result = {'host': 'dummy'}
         result.update(body)
         return (200, result)
+
+    def get_os_availability_zone(self, *kw):
+        return (200, {"availabilityZoneInfo": [{'zoneName': 'nova1'}]})