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