Included OpenStack integration tests.
[osm/MON.git] / osm_mon / test / integration / test_notify_alarm.py
1 # Copyright 2017 Intel Research and Development Ireland Limited
2 # *************************************************************
3
4 # This file is part of OSM Monitoring module
5 # All Rights Reserved to Intel Corporation
6
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
10
11 # http://www.apache.org/licenses/LICENSE-2.0
12
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
17 # under the License.
18
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
21 ##
22 """Tests for all common OpenStack methods."""
23
24 import json
25
26 import logging
27
28 import socket
29
30 from BaseHTTPServer import BaseHTTPRequestHandler
31 from BaseHTTPServer import HTTPServer
32
33 from threading import Thread
34
35 from osm_mon.core.message_bus.producer import KafkaProducer
36
37 import mock
38
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
42 from osm_mon.plugins.OpenStack.settings import Config
43
44 import requests
45
46 log = logging.getLogger(__name__)
47
48 # Create an instance of the common openstack class, producer and consumer
49 openstack_auth = Common()
50
51 # Mock a valid get_response for alarm details
52 valid_get_resp = '{"gnocchi_resources_threshold_rule":\
53 {"resource_id": "my_resource_id"}}'
54
55
56 class MockResponse(object):
57 """Mock a response class for generating responses."""
58
59 def __init__(self, text):
60 """Initialise a mock response with a text attribute."""
61 self.text = text
62
63
64 class MockNotifierHandler(BaseHTTPRequestHandler):
65 """Mock the NotifierHandler class for testing purposes."""
66
67 def _set_headers(self):
68 """Set the headers for a request."""
69 self.send_response(200)
70 self.send_header('Content-type', 'text/html')
71 self.end_headers()
72
73 def do_GET(self):
74 """Mock functionality for GET request."""
75 # self.send_response(requests.codes.ok)
76 self._set_headers()
77 pass
78
79 def do_POST(self):
80 """Mock functionality for a POST request."""
81 self._set_headers()
82 content_length = int(self.headers['Content-Length'])
83 post_data = self.rfile.read(content_length)
84 self.notify_alarm(json.loads(post_data))
85
86 def notify_alarm(self, values):
87 """Mock the notify_alarm functionality to generate a valid response."""
88 config = Config.instance()
89 config.read_environ("aodh")
90 self._alarming = Alarming()
91 self._common = Common()
92 self._response = OpenStack_Response()
93 self._producer = KafkaProducer('alarm_response')
94 alarm_id = values['alarm_id']
95
96 auth_token = self._common._authenticate()
97 endpoint = self._common.get_endpoint("alarming")
98
99 # If authenticated generate and send response message
100 if (auth_token is not None and endpoint is not None):
101 url = "{}/v2/alarms/%s".format(endpoint) % alarm_id
102
103 # Get the resource_id of the triggered alarm and the date
104 result = self._common._perform_request(
105 url, auth_token, req_type="get")
106 alarm_details = json.loads(result.text)
107 gnocchi_rule = alarm_details['gnocchi_resources_threshold_rule']
108 resource_id = gnocchi_rule['resource_id']
109 # Mock a date for testing purposes
110 a_date = "dd-mm-yyyy 00:00"
111
112 # Process an alarm notification if resource_id is valid
113 if resource_id is not None:
114 # Try generate and send response
115 try:
116 resp_message = self._response.generate_response(
117 'notify_alarm', a_id=alarm_id,
118 r_id=resource_id,
119 sev=values['severity'], date=a_date,
120 state=values['current'], vim_type="OpenStack")
121 self._producer.notify_alarm(
122 'notify_alarm', resp_message, 'alarm_response')
123 except Exception:
124 pass
125
126
127 def get_free_port():
128 """Function to get a free port to run the test webserver on."""
129 s = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM)
130 s.bind(('localhost', 0))
131 address, port = s.getsockname()
132 s.close()
133 return port
134
135
136 # Create the webserver, port and run it on its own thread
137 mock_server_port = get_free_port()
138 mock_server = HTTPServer(('localhost', mock_server_port), MockNotifierHandler)
139 mock_server_thread = Thread(target=mock_server.serve_forever)
140 mock_server_thread.setDaemon(True)
141 mock_server_thread.start()
142
143
144 def test_do_get():
145 """Integration test for get request on notifier webserver."""
146 url = 'http://localhost:{port}/users'.format(port=mock_server_port)
147
148 # Send a request to the mock API server and store the response.
149 response = requests.get(url)
150
151 # Confirm that the request-response cycle completed successfully.
152 assert response.ok
153
154
155 @mock.patch.object(KafkaProducer, "notify_alarm")
156 @mock.patch.object(OpenStack_Response, "generate_response")
157 @mock.patch.object(Common, "_perform_request")
158 @mock.patch.object(Common, "get_endpoint")
159 @mock.patch.object(Common, "_authenticate")
160 def test_post_notify_alarm(auth, endpoint, perf_req, resp, notify):
161 """Integration test for notify_alarm."""
162 url = 'http://localhost:{port}/users'.format(port=mock_server_port)
163 payload = {"severity": "critical",
164 "alarm_name": "my_alarm",
165 "current": "current_state",
166 "alarm_id": "my_alarm_id",
167 "reason": "Threshold has been broken",
168 "reason_data": {"count": 1,
169 "most_recent": "null",
170 "type": "threshold",
171 "disposition": "unknown"},
172 "previous": "previous_state"}
173
174 # Mock authenticate and request response for testing
175 auth.return_value = "my_auth_token"
176 endpoint.return_value = "my_endpoint"
177 perf_req.return_value = MockResponse(valid_get_resp)
178
179 # Generate a post reqest for testing
180 requests.post(url, json.dumps(payload))
181
182 # A response message is generated with the following details
183 resp.assert_called_with(
184 "notify_alarm", a_id="my_alarm_id", r_id="my_resource_id",
185 sev="critical", date='dd-mm-yyyy 00:00', state="current_state",
186 vim_type="OpenStack")
187
188 # Reponse message is sent back to the SO via MON's producer
189 notify.assert_called_with("notify_alarm", mock.ANY, "alarm_response")