17
from oslo_config import cfg
18
17
from oslo_utils import timeutils
21
20
from heat.common import exception
22
21
from heat.common import template_format
22
from heat.engine import resource
23
23
from heat.engine import scheduler
24
24
from heat.tests.autoscaling import inline_templates
25
25
from heat.tests import common
33
33
class TestAutoScalingPolicy(common.HeatTestCase):
35
super(TestAutoScalingPolicy, self).setUp()
36
cfg.CONF.set_default('heat_waitcondition_server_url',
37
'http://server.test:8000/v1/waitcondition')
39
35
def create_scaling_policy(self, t, stack, resource_name):
40
36
rsrc = stack[resource_name]
43
39
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
42
def test_validate_scaling_policy_ok(self):
43
t = template_format.parse(as_template)
44
t['resources']['my-policy']['properties'][
45
'scaling_adjustment'] = 33
46
t['resources']['my-policy']['properties'][
47
'adjustment_type'] = 'percent_change_in_capacity'
48
t['resources']['my-policy']['properties'][
49
'min_adjustment_step'] = 2
50
stack = utils.parse_stack(t)
51
self.assertIsNone(stack.validate())
53
def test_validate_scaling_policy_error(self):
54
t = template_format.parse(as_template)
55
t['resources']['my-policy']['properties'][
56
'scaling_adjustment'] = 1
57
t['resources']['my-policy']['properties'][
58
'adjustment_type'] = 'change_in_capacity'
59
t['resources']['my-policy']['properties'][
60
'min_adjustment_step'] = 2
61
stack = utils.parse_stack(t)
62
ex = self.assertRaises(exception.ResourcePropertyValueDependency,
64
self.assertIn('min_adjustment_step property should only '
65
'be specified for adjustment_type with '
66
'value percent_change_in_capacity.', six.text_type(ex))
46
68
def test_scaling_policy_bad_group(self):
47
69
t = template_format.parse(inline_templates.as_heat_template_bad_group)
48
70
stack = utils.parse_stack(t)
62
84
test = {'current': 'not_an_alarm'}
63
85
with mock.patch.object(pol, '_cooldown_inprogress',
64
86
side_effect=AssertionError()) as dont_call:
65
pol.handle_signal(details=test)
87
self.assertRaises(resource.NoActionRequired,
88
pol.handle_signal, details=test)
66
89
self.assertEqual([], dont_call.call_args_list)
68
91
def test_scaling_policy_cooldown_toosoon(self):
76
99
side_effect=AssertionError) as dont_call:
77
100
with mock.patch.object(pol, '_cooldown_inprogress',
78
101
return_value=True) as mock_cip:
79
pol.handle_signal(details=test)
102
self.assertRaises(resource.NoActionRequired,
103
pol.handle_signal, details=test)
80
104
mock_cip.assert_called_once_with()
81
105
self.assertEqual([], dont_call.call_args_list)
92
116
return_value=False) as mock_cip:
93
117
pol.handle_signal(details=test)
94
118
mock_cip.assert_called_once_with()
95
group.adjust.assert_called_once_with(1, 'ChangeInCapacity')
119
group.adjust.assert_called_once_with(1, 'ChangeInCapacity', None)
98
122
class TestCooldownMixin(common.HeatTestCase):
100
124
super(TestCooldownMixin, self).setUp()
101
cfg.CONF.set_default('heat_waitcondition_server_url',
102
'http://server.test:8000/v1/waitcondition')
104
126
def create_scaling_policy(self, t, stack, resource_name):
105
127
rsrc = stack[resource_name]
114
136
pol = self.create_scaling_policy(t, stack, 'my-policy')
116
138
now = timeutils.utcnow()
117
previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'}
139
previous_meta = {now.isoformat(): 'ChangeInCapacity : 1'}
118
140
self.patchobject(pol, 'metadata_get', return_value=previous_meta)
119
141
self.assertTrue(pol._cooldown_inprogress())
124
146
pol = self.create_scaling_policy(t, stack, 'my-policy')
126
148
awhile_ago = timeutils.utcnow() - datetime.timedelta(seconds=100)
127
previous_meta = {timeutils.strtime(awhile_ago): 'ChangeInCapacity : 1'}
149
previous_meta = {awhile_ago.isoformat(): 'ChangeInCapacity : 1'}
128
150
self.patchobject(pol, 'metadata_get', return_value=previous_meta)
129
151
self.assertFalse(pol._cooldown_inprogress())
139
161
pol = self.create_scaling_policy(t, stack, 'my-policy')
141
163
now = timeutils.utcnow()
142
previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'}
164
previous_meta = {now.isoformat(): 'ChangeInCapacity : 1'}
143
165
self.patchobject(pol, 'metadata_get', return_value=previous_meta)
144
166
self.assertFalse(pol._cooldown_inprogress())
155
177
pol = self.create_scaling_policy(t, stack, 'my-policy')
157
179
now = timeutils.utcnow()
158
previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'}
180
previous_meta = {now.isoformat(): 'ChangeInCapacity : 1'}
159
181
self.patchobject(pol, 'metadata_get', return_value=previous_meta)
160
182
self.assertFalse(pol._cooldown_inprogress())
164
186
stack = utils.parse_stack(t, params=as_params)
165
187
pol = self.create_scaling_policy(t, stack, 'my-policy')
167
nowish = timeutils.strtime()
189
nowish = timeutils.utcnow()
168
190
reason = 'cool as'
169
191
meta_set = self.patchobject(pol, 'metadata_set')
170
self.patchobject(timeutils, 'strtime', return_value=nowish)
192
self.patchobject(timeutils, 'utcnow', return_value=nowish)
171
193
pol._cooldown_timestamp(reason)
172
meta_set.assert_called_once_with({nowish: reason})
194
meta_set.assert_called_once_with({nowish.isoformat(): reason})
175
197
class ScalingPolicyAttrTest(common.HeatTestCase):
177
199
super(ScalingPolicyAttrTest, self).setUp()
178
cfg.CONF.set_default('heat_waitcondition_server_url',
179
'http://server.test:8000/v1/waitcondition')
180
200
t = template_format.parse(as_template)
181
stack = utils.parse_stack(t, params=as_params)
182
self.stack_name = stack.name
183
self.policy = stack['my-policy']
201
self.stack = utils.parse_stack(t, params=as_params)
202
self.stack_name = self.stack.name
203
self.policy = self.stack['my-policy']
184
204
self.assertIsNone(self.policy.validate())
185
205
scheduler.TaskRunner(self.policy.create)()
186
206
self.assertEqual((self.policy.CREATE, self.policy.COMPLETE),
187
207
self.policy.state)
189
209
def test_alarm_attribute(self):
210
self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'),
212
self.stack.clients.client_plugin('heat').get_heat_cfn_url().AndReturn(
213
'http://server.test:8000/v1')
190
215
alarm_url = self.policy.FnGetAtt('alarm_url')
192
216
base = alarm_url.split('?')[0].split('%3A')
193
217
self.assertEqual('http://server.test:8000/v1/signal/arn', base[0])
194
218
self.assertEqual('openstack', base[1])
207
231
self.assertEqual('AWSAccessKeyId', args[2].split('=')[0])
208
232
self.assertEqual('SignatureVersion', args[3].split('=')[0])
209
233
self.assertEqual('Signature', args[4].split('=')[0])
236
def test_signal_attribute(self):
237
self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'),
239
self.stack.clients.client_plugin('heat').get_heat_url().AndReturn(
240
'http://server.test:8000/v1')
243
'http://server.test:8000/v1/test_tenant_id/stacks/'
244
'%s/%s/resources/my-policy/signal' % (
245
self.stack.name, self.stack.id),
246
self.policy.FnGetAtt('signal_url'))