blob: 7f7f015fc502885e527d25c3c6e141a6977ee84a [file] [log] [blame]
Stephane Barbarie52198b92017-03-02 13:44:46 -05001from unittest import main
2from common.utils.consulhelpers import get_endpoint_from_consul
Richard Jankowski87289342018-04-19 13:59:10 -04003from tests.itests.test_utils import get_pod_ip, \
Stephane Barbariecc6b2e62017-03-02 14:35:55 -05004 run_long_running_command_with_timeout
Stephane Barbarie52198b92017-03-02 13:44:46 -05005from tests.itests.voltha.rest_base import RestBase
6from google.protobuf.json_format import MessageToDict
7from voltha.protos.device_pb2 import Device
8import simplejson, jsonschema
9import re
Richard Jankowski87289342018-04-19 13:59:10 -040010from tests.itests.orch_environment import get_orch_environment
11from testconfig import config
Stephane Barbarie52198b92017-03-02 13:44:46 -050012
13# ~~~~~~~ Common variables ~~~~~~~
14
15LOCAL_CONSUL = "localhost:8500"
Richard Jankowski87289342018-04-19 13:59:10 -040016ENV_DOCKER_COMPOSE = 'docker-compose'
17ENV_K8S_SINGLE_NODE = 'k8s-single-node'
18
19orch_env = ENV_DOCKER_COMPOSE
20if 'test_parameters' in config and 'orch_env' in config['test_parameters']:
21 orch_env = config['test_parameters']['orch_env']
22print 'orchestration-environment: %s' % orch_env
Stephane Barbarie52198b92017-03-02 13:44:46 -050023
24COMMANDS = dict(
25 kafka_client_run="kafkacat -b {} -L",
Stephane Barbariee37300e2017-06-08 11:22:16 -040026 kafka_client_send_msg='echo hello | kafkacat -b {} -P -t voltha.alarms -c 1',
27 kafka_client_alarm_check="kafkacat -o end -b {} -C -t voltha.alarms -c 2",
Stephane Barbarie52198b92017-03-02 13:44:46 -050028)
29
30ALARM_SCHEMA = {
31 "type": "object",
32 "properties": {
33 "id": {"type": "string"},
34 "type": {"type": "string"},
35 "category": {"type": "string"},
36 "state": {"type": "string"},
37 "severity": {"type": "string"},
38 "resource_id": {"type": "string"},
39 "raised_ts": {"type": "number"},
40 "reported_ts": {"type": "number"},
41 "changed_ts": {"type": "number"},
42 "description": {"type": "string"},
43 "context": {
44 "type": "object",
45 "additionalProperties": {"type": "string"}
46 }
47 }
48}
49
50
Stephane Barbariecc6b2e62017-03-02 14:35:55 -050051# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stephane Barbarie52198b92017-03-02 13:44:46 -050052
53
54class VolthaAlarmEventTests(RestBase):
Richard Jankowski87289342018-04-19 13:59:10 -040055 # Get endpoint info
56 if orch_env == ENV_K8S_SINGLE_NODE:
57 rest_endpoint = get_pod_ip('voltha') + ':8443'
58 kafka_endpoint = get_pod_ip('kafka')
59 else:
60 rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'voltha-envoy-8443')
61 kafka_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'kafka')
Stephane Barbarie52198b92017-03-02 13:44:46 -050062
63 # Construct the base_url
ubuntuc5c83d72017-07-01 17:57:19 -070064 base_url = 'https://' + rest_endpoint
Stephane Barbarie52198b92017-03-02 13:44:46 -050065
Stephane Barbarie52198b92017-03-02 13:44:46 -050066 # ~~~~~~~~~~~~ Tests ~~~~~~~~~~~~
67
Stephane Barbariee37300e2017-06-08 11:22:16 -040068 def test_1_alarm_topic_exists(self):
69 # Produce a message to ensure that the topic exists
70 cmd = COMMANDS['kafka_client_send_msg'].format(self.kafka_endpoint)
71 run_long_running_command_with_timeout(cmd, 5)
72
Stephane Barbarie52198b92017-03-02 13:44:46 -050073 # We want to make sure that the topic is available on the system
74 expected_pattern = ['voltha.alarms']
75
76 # Start the kafka client to retrieve details on topics
77 cmd = COMMANDS['kafka_client_run'].format(self.kafka_endpoint)
78 kafka_client_output = run_long_running_command_with_timeout(cmd, 20)
79
80 # Loop through the kafka client output to find the topic
81 found = False
82 for out in kafka_client_output:
83 if all(ep in out for ep in expected_pattern):
84 found = True
85 break
86
Stephane Barbariecc6b2e62017-03-02 14:35:55 -050087 self.assertTrue(found,
88 'Failed to find topic {}'.format(expected_pattern))
Stephane Barbarie52198b92017-03-02 13:44:46 -050089
Stephane Barbariee37300e2017-06-08 11:22:16 -040090 def test_2_alarm_generated_by_adapter(self):
Stephane Barbarie52198b92017-03-02 13:44:46 -050091 # Verify that REST calls can be made
92 self.verify_rest()
93
94 # Create a new device
95 device = self.add_device()
96
97 # Activate the new device
98 self.activate_device(device['id'])
99
100 # The simulated olt device should start generating alarms periodically
101 alarm = self.get_alarm_event(device['id'])
102
103 # Make sure that the schema is valid
104 self.validate_alarm_event_schema(alarm)
105
106 # Validate the constructed alarm id
107 self.verify_alarm_event_id(device['id'], alarm['id'])
108
109 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110
111 # Make sure the Voltha REST interface is available
112 def verify_rest(self):
113 self.get('/api/v1')
114
115 # Create a new simulated device
116 def add_device(self):
117 device = Device(
118 type='simulated_olt',
Richard Jankowski87289342018-04-19 13:59:10 -0400119 mac_address='00:00:00:00:00:01'
Stephane Barbarie52198b92017-03-02 13:44:46 -0500120 )
Stephane Barbariecd51f992017-09-07 16:37:02 -0400121 device = self.post('/api/v1/devices', MessageToDict(device),
122 expected_http_code=200)
Stephane Barbarie52198b92017-03-02 13:44:46 -0500123 return device
124
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500125 # Active the simulated device.
126 # This will trigger the simulation of random alarms
Stephane Barbarie52198b92017-03-02 13:44:46 -0500127 def activate_device(self, device_id):
Stephane Barbariecd51f992017-09-07 16:37:02 -0400128 path = '/api/v1/devices/{}'.format(device_id)
129 self.post(path + '/enable', expected_http_code=200)
Stephane Barbarie52198b92017-03-02 13:44:46 -0500130 device = self.get(path)
131 self.assertEqual(device['admin_state'], 'ENABLED')
132
133 # Retrieve a sample alarm for a specific device
134 def get_alarm_event(self, device_id):
135 cmd = COMMANDS['kafka_client_alarm_check'].format(self.kafka_endpoint)
Stephane Barbariee37300e2017-06-08 11:22:16 -0400136 kafka_client_output = run_long_running_command_with_timeout(cmd, 30)
Stephane Barbarie52198b92017-03-02 13:44:46 -0500137
138 # Verify the kafka client output
139 found = False
Stephane Barbariee37300e2017-06-08 11:22:16 -0400140 alarm_data = None
Stephane Barbarie52198b92017-03-02 13:44:46 -0500141
142 for out in kafka_client_output:
Stephane Barbariee37300e2017-06-08 11:22:16 -0400143 # Catch any error that might occur while reading the kafka messages
144 try:
145 alarm_data = simplejson.loads(out)
146 print alarm_data
Stephane Barbarie52198b92017-03-02 13:44:46 -0500147
Stephane Barbariee37300e2017-06-08 11:22:16 -0400148 if not alarm_data or 'resource_id' not in alarm_data:
149 continue
150 elif alarm_data['resource_id'] == device_id:
151 found = True
152 break
Stephane Barbarie52198b92017-03-02 13:44:46 -0500153
Stephane Barbariee37300e2017-06-08 11:22:16 -0400154 except Exception as e:
Stephane Barbarie52198b92017-03-02 13:44:46 -0500155 continue
Stephane Barbarie52198b92017-03-02 13:44:46 -0500156
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500157 self.assertTrue(
158 found,
159 'Failed to find kafka alarm with device id:{}'.format(device_id))
Stephane Barbarie52198b92017-03-02 13:44:46 -0500160
Stephane Barbariee37300e2017-06-08 11:22:16 -0400161 return alarm_data
Stephane Barbarie52198b92017-03-02 13:44:46 -0500162
163 # Verify that the alarm follows the proper schema structure
164 def validate_alarm_event_schema(self, alarm):
165 try:
166 jsonschema.validate(alarm, ALARM_SCHEMA)
167 except Exception as e:
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500168 self.assertTrue(
169 False, 'Validation failed for alarm : {}'.format(e.message))
Stephane Barbarie52198b92017-03-02 13:44:46 -0500170
171 # Verify that alarm identifier based on the format generated by default.
172 def verify_alarm_event_id(self, device_id, alarm_id):
173 prefix = re.findall(r"(voltha)\.(\w+)\.(\w+)", alarm_id)
174
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500175 self.assertEqual(
176 len(prefix), 1,
177 'Failed to parse the alarm id: {}'.format(alarm_id))
178 self.assertEqual(
179 len(prefix[0]), 3,
180 'Expected id format: voltha.<adapter name>.<device id>')
181 self.assertEqual(
182 prefix[0][0], 'voltha',
183 'Expected id format: voltha.<adapter name>.<device id>')
184 self.assertEqual(
185 prefix[0][1], 'simulated_olt',
186 'Expected id format: voltha.<adapter name>.<device id>')
187 self.assertEqual(
188 prefix[0][2], device_id,
189 'Expected id format: voltha.<adapter name>.<device id>')
Stephane Barbarie52198b92017-03-02 13:44:46 -0500190
191
192if __name__ == '__main__':
193 main()