1 # -*- coding: utf-8 -*-
3 # Copyright 2018 Whitestack, LLC
4 # *************************************************************
6 # This file is part of OSM Monitoring module
7 # All Rights Reserved to Whitestack, LLC
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact: bdiaz@whitestack.com or glavado@whitestack.com
26 from unittest
import TestCase
, mock
28 from osm_policy_module
.autoscaling
.service
import AutoscalingService
29 from osm_policy_module
.common
.common_db_client
import CommonDbClient
30 from osm_policy_module
.common
.lcm_client
import LcmClient
31 from osm_policy_module
.common
.mon_client
import MonClient
32 from osm_policy_module
.core
.config
import Config
33 from osm_policy_module
.core
.database
import ScalingAlarmRepository
36 @mock.patch
.object(LcmClient
, "__init__", lambda *args
, **kwargs
: None)
37 @mock.patch
.object(MonClient
, "__init__", lambda *args
, **kwargs
: None)
38 @mock.patch
.object(CommonDbClient
, "__init__", lambda *args
, **kwargs
: None)
39 class TestAutoscalingService(TestCase
):
42 self
.config
= Config()
43 self
.loop
= asyncio
.new_event_loop()
45 @mock.patch
.object(ScalingAlarmRepository
, 'get')
46 @mock.patch('osm_policy_module.core.database.db')
47 def test_update_alarm_status(self
, database
, get_alarm
):
48 mock_alarm
= mock
.Mock()
49 mock_alarm
.last_status
= 'insufficient_data'
50 get_alarm
.return_value
= mock_alarm
52 service
= AutoscalingService(self
.config
)
53 self
.loop
.run_until_complete(service
.update_alarm_status('test_uuid', 'alarm'))
54 self
.assertEqual(mock_alarm
.last_status
, 'alarm')
55 mock_alarm
.save
.assert_called_with()
57 service
= AutoscalingService(self
.config
)
58 self
.loop
.run_until_complete(service
.update_alarm_status('test_uuid', 'ok'))
59 self
.assertEqual(mock_alarm
.last_status
, 'ok')
60 mock_alarm
.save
.assert_called_with()
62 service
= AutoscalingService(self
.config
)
63 self
.loop
.run_until_complete(service
.update_alarm_status('test_uuid', 'insufficient_data'))
64 self
.assertEqual(mock_alarm
.last_status
, 'insufficient_data')
65 mock_alarm
.save
.assert_called_with()
67 @mock.patch
.object(ScalingAlarmRepository
, 'list')
68 @mock.patch
.object(ScalingAlarmRepository
, 'get')
69 @mock.patch('osm_policy_module.core.database.db')
70 def test_evaluate_policy_not_enabled(self
, database
, get_alarm
, list_alarms
):
71 mock_alarm
= mock
.Mock()
72 mock_alarm
.scaling_criteria
.scaling_policy
.enabled
= False
73 get_alarm
.return_value
= mock_alarm
75 service
= AutoscalingService(self
.config
)
76 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
77 list_alarms
.assert_not_called()
79 @mock.patch
.object(ScalingAlarmRepository
, 'list')
80 @mock.patch
.object(ScalingAlarmRepository
, 'get')
81 @mock.patch
.object(LcmClient
, 'scale')
82 @mock.patch('osm_policy_module.core.database.db')
83 def test_evaluate_policy_scale_in_and_equal(self
, database
, scale
, get_alarm
, list_alarms
):
85 Tests scale in with AND operation, both alarms triggered
87 future
= asyncio
.Future(loop
=self
.loop
)
88 future
.set_result('mock')
89 scale
.return_value
= future
91 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='AND')
92 get_alarm
.return_value
= mock_alarm
94 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='AND')
96 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
98 service
= AutoscalingService(self
.config
)
99 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
100 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_in')
102 @mock.patch
.object(ScalingAlarmRepository
, 'list')
103 @mock.patch
.object(ScalingAlarmRepository
, 'get')
104 @mock.patch
.object(LcmClient
, 'scale')
105 @mock.patch('osm_policy_module.core.database.db')
106 def test_evaluate_policy_scale_in_and_diff(self
, database
, scale
, get_alarm
, list_alarms
):
108 Tests scale in with AND operation, only one alarm triggered.
110 future
= asyncio
.Future(loop
=self
.loop
)
111 future
.set_result('mock')
112 scale
.return_value
= future
114 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='AND')
115 get_alarm
.return_value
= mock_alarm
117 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='ok', enabled
=True, scale_in_op
='OR')
119 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
121 service
= AutoscalingService(self
.config
)
122 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
123 scale
.assert_not_called()
125 @mock.patch
.object(ScalingAlarmRepository
, 'list')
126 @mock.patch
.object(ScalingAlarmRepository
, 'get')
127 @mock.patch
.object(LcmClient
, 'scale')
128 @mock.patch('osm_policy_module.core.database.db')
129 def test_evaluate_policy_scale_in_or_equal(self
, database
, scale
, get_alarm
, list_alarms
):
131 Tests scale in with OR operation, both alarms triggered
133 future
= asyncio
.Future(loop
=self
.loop
)
134 future
.set_result('mock')
135 scale
.return_value
= future
137 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='OR')
138 get_alarm
.return_value
= mock_alarm
140 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='OR')
142 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
144 service
= AutoscalingService(self
.config
)
145 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
146 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_in')
148 @mock.patch
.object(ScalingAlarmRepository
, 'list')
149 @mock.patch
.object(ScalingAlarmRepository
, 'get')
150 @mock.patch
.object(LcmClient
, 'scale')
151 @mock.patch('osm_policy_module.core.database.db')
152 def test_evaluate_policy_scale_in_or_diff(self
, database
, scale
, get_alarm
, list_alarms
):
154 Tests scale in with OR operation, only one alarm triggered
156 future
= asyncio
.Future(loop
=self
.loop
)
157 future
.set_result('mock')
158 scale
.return_value
= future
160 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='alarm', enabled
=True, scale_in_op
='OR')
161 get_alarm
.return_value
= mock_alarm
163 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_in', last_status
='ok', enabled
=True, scale_in_op
='OR')
165 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
167 service
= AutoscalingService(self
.config
)
168 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
169 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_in')
171 @mock.patch
.object(ScalingAlarmRepository
, 'list')
172 @mock.patch
.object(ScalingAlarmRepository
, 'get')
173 @mock.patch
.object(LcmClient
, 'scale')
174 @mock.patch('osm_policy_module.core.database.db')
175 def test_evaluate_policy_scale_out_and_equal(self
, database
, scale
, get_alarm
, list_alarms
):
177 Tests scale out with AND operation, both alarms triggered
179 future
= asyncio
.Future(loop
=self
.loop
)
180 future
.set_result('mock')
181 scale
.return_value
= future
183 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='AND')
184 get_alarm
.return_value
= mock_alarm
186 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='AND')
188 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
190 service
= AutoscalingService(self
.config
)
191 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
192 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_out')
194 @mock.patch
.object(ScalingAlarmRepository
, 'list')
195 @mock.patch
.object(ScalingAlarmRepository
, 'get')
196 @mock.patch
.object(LcmClient
, 'scale')
197 @mock.patch('osm_policy_module.core.database.db')
198 def test_evaluate_policy_scale_out_and_diff(self
, database
, scale
, get_alarm
, list_alarms
):
200 Tests scale out with AND operation, only one alarm triggered.
202 future
= asyncio
.Future(loop
=self
.loop
)
203 future
.set_result('mock')
204 scale
.return_value
= future
206 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='AND')
207 get_alarm
.return_value
= mock_alarm
209 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='ok', enabled
=True, scale_out_op
='OR')
211 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
213 service
= AutoscalingService(self
.config
)
214 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
215 scale
.assert_not_called()
217 @mock.patch
.object(ScalingAlarmRepository
, 'list')
218 @mock.patch
.object(ScalingAlarmRepository
, 'get')
219 @mock.patch
.object(LcmClient
, 'scale')
220 @mock.patch('osm_policy_module.core.database.db')
221 def test_evaluate_policy_scale_out_or_equal(self
, database
, scale
, get_alarm
, list_alarms
):
223 Tests scale out with OR operation, both alarms triggered
225 future
= asyncio
.Future(loop
=self
.loop
)
226 future
.set_result('mock')
227 scale
.return_value
= future
229 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='OR')
230 get_alarm
.return_value
= mock_alarm
232 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='OR')
234 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
236 service
= AutoscalingService(self
.config
)
237 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
238 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_out')
240 @mock.patch
.object(ScalingAlarmRepository
, 'list')
241 @mock.patch
.object(ScalingAlarmRepository
, 'get')
242 @mock.patch
.object(LcmClient
, 'scale')
243 @mock.patch('osm_policy_module.core.database.db')
244 def test_evaluate_policy_scale_out_or_diff(self
, database
, scale
, get_alarm
, list_alarms
):
246 Tests scale out with OR operation, only one alarm triggered
248 future
= asyncio
.Future(loop
=self
.loop
)
249 future
.set_result('mock')
250 scale
.return_value
= future
252 mock_alarm
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='alarm', enabled
=True, scale_out_op
='OR')
253 get_alarm
.return_value
= mock_alarm
255 mock_alarm_2
= self
._build
_mock
_alarm
(action
='scale_out', last_status
='ok', enabled
=True, scale_out_op
='OR')
257 list_alarms
.return_value
= [mock_alarm
, mock_alarm_2
]
259 service
= AutoscalingService(self
.config
)
260 self
.loop
.run_until_complete(service
.evaluate_policy('test_uuid'))
261 scale
.assert_called_with('test_nsr_id', 'test_group', '1', 'scale_out')
263 def _build_mock_alarm(self
,
266 last_scale
=datetime
.datetime
.min,
271 mock_alarm
= mock
.Mock()
272 mock_alarm
.action
= action
273 mock_alarm
.last_status
= last_status
274 mock_alarm
.vnf_member_index
= '1'
275 mock_alarm
.scaling_criteria
.scaling_policy
.last_scale
= last_scale
276 mock_alarm
.scaling_criteria
.scaling_policy
.cooldown_time
= cooldown_time
277 mock_alarm
.scaling_criteria
.scaling_policy
.enabled
= enabled
278 mock_alarm
.scaling_criteria
.scaling_policy
.scale_in_operation
= scale_in_op
279 mock_alarm
.scaling_criteria
.scaling_policy
.scale_out_operation
= scale_out_op
280 mock_alarm
.scaling_criteria
.scaling_policy
.scaling_group
.nsr_id
= 'test_nsr_id'
281 mock_alarm
.scaling_criteria
.scaling_policy
.scaling_group
.name
= 'test_group'