1 # Copyright 2017 Intel Research and Development Ireland Limited
2 # *************************************************************
4 # This file is part of OSM Monitoring module
5 # All Rights Reserved to Intel Corporation
7 # Licensed under the Apache License, Version 2.0 (the "License"); you may
8 # not use this file except in compliance with the License. You may obtain
9 # a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 # License for the specific language governing permissions and limitations
19 # For those usages not covered by the Apache License, Version 2.0 please
20 # contact: helena.mcgough@intel.com or adrian.hoban@intel.com
22 """Tests for all common OpenStack methods."""
25 from __future__
import unicode_literals
30 from threading
import Thread
34 from six
.moves
.BaseHTTPServer
import BaseHTTPRequestHandler
35 from six
.moves
.BaseHTTPServer
import HTTPServer
37 from osm_mon
.core
.message_bus
.producer
import KafkaProducer
38 from osm_mon
.core
.settings
import Config
39 from osm_mon
.plugins
.OpenStack
.Aodh
.alarming
import Alarming
40 from osm_mon
.plugins
.OpenStack
.common
import Common
41 from osm_mon
.plugins
.OpenStack
.response
import OpenStack_Response
43 log
= logging
.getLogger(__name__
)
45 # Create an instance of the common openstack class, producer and consumer
46 openstack_auth
= Common()
48 # Mock a valid get_response for alarm details
49 valid_get_resp
= '{"gnocchi_resources_threshold_rule":\
50 {"resource_id": "my_resource_id"}}'
53 class MockResponse(object):
54 """Mock a response class for generating responses."""
56 def __init__(self
, text
):
57 """Initialise a mock response with a text attribute."""
61 class MockNotifierHandler(BaseHTTPRequestHandler
):
62 """Mock the NotifierHandler class for testing purposes."""
64 def _set_headers(self
):
65 """Set the headers for a request."""
66 self
.send_response(200)
67 self
.send_header('Content-type', 'text/html')
71 """Mock functionality for GET request."""
72 # self.send_response(requests.codes.ok)
77 """Mock functionality for a POST request."""
79 content_length
= int(self
.headers
['Content-Length'])
80 post_data
= self
.rfile
.read(content_length
)
82 post_data
= post_data
.decode()
83 except AttributeError:
85 self
.notify_alarm(json
.loads(post_data
))
87 def notify_alarm(self
, values
):
88 """Mock the notify_alarm functionality to generate a valid response."""
89 config
= Config
.instance()
91 self
._alarming
= Alarming()
92 self
._common
= Common()
93 self
._response
= OpenStack_Response()
94 self
._producer
= KafkaProducer('alarm_response')
95 alarm_id
= values
['alarm_id']
97 auth_token
= Common
.get_auth_token('test_id')
98 endpoint
= Common
.get_endpoint('alarming', 'test_id')
100 # If authenticated generate and send response message
101 if auth_token
is not None and endpoint
is not None:
102 url
= "{}/v2/alarms/%s".format(endpoint
) % alarm_id
104 # Get the resource_id of the triggered alarm and the date
105 result
= Common
.perform_request(
106 url
, auth_token
, req_type
="get")
107 alarm_details
= json
.loads(result
.text
)
108 gnocchi_rule
= alarm_details
['gnocchi_resources_threshold_rule']
109 resource_id
= gnocchi_rule
['resource_id']
110 # Mock a date for testing purposes
111 a_date
= "dd-mm-yyyy 00:00"
113 # Process an alarm notification if resource_id is valid
114 if resource_id
is not None:
115 # Try generate and send response
117 resp_message
= self
._response
.generate_response(
118 'notify_alarm', a_id
=alarm_id
,
120 sev
=values
['severity'], date
=a_date
,
121 state
=values
['current'], vim_type
="OpenStack")
122 self
._producer
.publish_alarm_response(
123 'notify_alarm', resp_message
)
129 """Function to get a free port to run the test webserver on."""
130 s
= socket
.socket(socket
.AF_INET
, type=socket
.SOCK_STREAM
)
131 s
.bind(('localhost', 0))
132 address
, port
= s
.getsockname()
137 # Create the webserver, port and run it on its own thread
138 mock_server_port
= get_free_port()
139 mock_server
= HTTPServer(('localhost', mock_server_port
), MockNotifierHandler
)
140 mock_server_thread
= Thread(target
=mock_server
.serve_forever
)
141 mock_server_thread
.setDaemon(True)
142 mock_server_thread
.start()
146 """Integration test for get request on notifier webserver."""
147 url
= 'http://localhost:{port}/users'.format(port
=mock_server_port
)
149 # Send a request to the mock API server and store the response.
150 response
= requests
.get(url
)
152 # Confirm that the request-response cycle completed successfully.
156 class AlarmNotificationTest(unittest
.TestCase
):
157 @mock.patch
.object(KafkaProducer
, "publish_alarm_response")
158 @mock.patch
.object(OpenStack_Response
, "generate_response")
159 @mock.patch
.object(Common
, "perform_request")
160 @mock.patch
.object(Common
, "get_endpoint")
161 @mock.patch
.object(Common
, "get_auth_token")
162 def test_post_notify_alarm(self
, auth
, endpoint
, perf_req
, resp
, notify
):
163 """Integration test for notify_alarm."""
164 url
= 'http://localhost:{port}/users'.format(port
=mock_server_port
)
165 payload
= {"severity": "critical",
166 "alarm_name": "my_alarm",
167 "current": "current_state",
168 "alarm_id": "my_alarm_id",
169 "reason": "Threshold has been broken",
170 "reason_data": {"count": 1,
171 "most_recent": "null",
173 "disposition": "unknown"},
174 "previous": "previous_state"}
176 # Mock authenticate and request response for testing
177 auth
.return_value
= "my_auth_token"
178 endpoint
.return_value
= "my_endpoint"
179 perf_req
.return_value
= MockResponse(valid_get_resp
)
181 # Generate a post request for testing
182 response
= requests
.post(url
, json
.dumps(payload
))
183 self
.assertEqual(response
.status_code
, 200)
184 # A response message is generated with the following details
185 resp
.assert_called_with(
186 "notify_alarm", a_id
="my_alarm_id", r_id
="my_resource_id",
187 sev
="critical", date
='dd-mm-yyyy 00:00', state
="current_state",
188 vim_type
="OpenStack")
190 # Response message is sent back to the SO via MON's producer
191 notify
.assert_called_with("notify_alarm", mock
.ANY
)