blob: 78f4d442b6dc9dfede26ae1db353e7016e65d140 [file] [log] [blame]
Thiyagarajan Subramanie84935d2020-04-23 17:45:44 +05301#!/usr/bin/python
2
3"""
4Copyright 2018-present Open Networking Foundation
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17"""
18
19"""
20:Description: Module for fetching OLT information.
21
22 This module is used to fetch OLT software and hardware information.
23 The OLT software information includes Operating system, OS Version,
24 and ONIE version.
25 The hardware information includes OLT Serial Number, OLT Hardware Model,
26 Vendor ID, OLT Hardware Part Number and In-band interfaces MAC addresses.
27
28 The gathered information will be output to the screen as a json string.
29 When passed through a JSON processor (like jq) the output would look
30 like below(sample output, the keys remain same and values change based on
31 OLT model and binary versions)
32 {
33 "hardware_information": {
34 "vendor": "Accton",
35 "hw_part_number": "FN1EC0816400Z",
36 "hw_version": "0.0.0.3",
37 "inband_interface": "34:12:78:56:01:00",
38 "hw_model": "ASXvOLT16-O-AC-F",
39 "serial_number": "EC1729003537"
40 },
41 "software_information": {
42 "onie_version": "2017.02.00.06",
43 "os_version": "3.7.10",
44 "os_name": "OpenNetworkLinux",
45 "openolt_version": "2.0.0",
46 "bal_version": "2.6.0.1"
47 }
48 }
49
50 This script exits with exit code 0 in case of success and 1 in case of failure.
51"""
52
53import os
54import re
55import json
56import syslog
57import yaml
58
59# dictionary containing OLT information with hardware_information and
60# software_information as keys and holds the respective data values
61OLT_INFORMATION = {}
62
63# Path where BAL libraries, configuration files, bal_core_dist
64# and openolt binaries are located.
65BRCM_DIR = '/broadcom'
66
67# Path to vlan config file
68VLAN_CONFIG_FILE = BRCM_DIR+"/vlan.config"
69
70# Operating system name which is running at OLT.
71# By default Open Network Linux (ONL) is used as operating
72# system at OLT
73OS_NAME = 'OpenNetworkLinux'
74
75# BAL library version running at OLT
76
77# openOLT version from OLT when available
78OPENOLT_VERSION = " "
79
80# in-band interface incase of device asgvolt64
81ETH_1 = 'eth1'
82
83# in-band interface incase of device asfvolt16
84ETH_2 = 'eth2'
85
86# Constants for the name of the keys in the JSON being printed
87VENDOR = "vendor"
88SERIAL_NUMBER = "serial_number"
89HARDWARE_MODEL = "hw_model"
90HARDWARE_PART_NUMBER = "hw_part_number"
91HARDWARE_VERSION = "hw_version"
92OPERATING_SYSTEM = "os_name"
93OPERATING_SYSTEM_VERSION = "os_version"
94ONIE_VERSION = "onie_version"
95SOFTWARE_INFORMATION = "software_information"
96HARDWARE_INFORMATION = "hardware_information"
97INBAND_INTERFACE = "inband_interface"
98BAL_VER = "bal_version"
99OPENOLT_VER = "openolt_version"
100OLT_MODEL=None
101ASX_16 = "ASXvOLT16"
102ASG_64 = "ASGvOLT64"
103
104# log to syslog
105syslog.openlog(facility=syslog.LOG_SYSLOG)
106
107def get_olt_board_name():
108 """
109 Reads the bal package name
110
111 This function fetchs bal package whether asfvolt16 or asgvolt64
112
113 :return : packge names if successful and None in case of failure.
114 :rtype : tuple of package name in case of success, else None in case of failure.
115 """
116
117 try:
118 OLT_MODEL = os.popen("cat /sys/devices/virtual/dmi/id/board_name").read().strip("\n")
119 syslog.syslog(syslog.LOG_INFO, "successfully-read-olt-board-name")
120 return OLT_MODEL
121 except (IOError, NameError) as exception:
122 syslog.syslog(syslog.LOG_ERR, "error-executing-command-{}".format(exception))
123 return None
124
125
126def retreive_vlan_id():
127 """
128 Retrieves VLAN ids of in-band interfaces.
129
130 This function fetchs vlan ids from OLT /broadcom/bal_config.ini file.
131
132 :return : vlan id of in-band interface if successfull and None in case of failure.
133 :rtype : integer(valid vlan_id) in case of success, else None in case of failure.
134 """
135
136 eth_vlan = None
137
138 # retrieving vlan ids based on the below two keys in bal_config.ini
139 asf16_vlan = 'asfvolt16_vlan_id_eth2'
140 asg64_vlan = 'asgvolt64_vlan_id_eth1'
141 olt_model=get_olt_board_name()
142 try:
143 if os.path.exists(VLAN_CONFIG_FILE):
144 with open(VLAN_CONFIG_FILE, "r") as file_descriptor:
145 lines = file_descriptor.readlines()
146 for line in lines:
147 if olt_model == ASX_16:
148 if re.search(asf16_vlan, line):
149 eth_vlan = int(line.split('=')[1].strip())
150 else if olt_model == ASG_64:
151 if re.search(asg64_vlan, line):
152 eth_vlan = int(line.split('=')[1].strip())
153 else:
154 syslog.syslog(syslog.LOG_ERR, "{}-file-does-not-exist".format(VLAN_CONFIG_FILE))
155 return None, None
156 except(EnvironmentError, re.error) as exception:
157 syslog.syslog(syslog.LOG_ERR, "error-retreving-vlan-ids-{}".format(exception))
158 return None, None
159
160 if eth_vlan > 4094 or eth_vlan < 1:
161 syslog.syslog(syslog.LOG_ERR, "vlan-id-not-in-range-{}-{}".format(eth_vlan, eth_vlan_2))
162 return None, None
163
164 return eth_vlan
165
166
167def get_olt_basic_info():
168 """
169 Fetch OLT basic information
170
171 This function retireves OLT's basic information using the command 'onlpdump -s'
172
173 :return: OLT's basic info in case of success and None in case of failure
174 :rtype: json if success and None if failure
175 """
176 # fetch OLT basic information
177 try:
178 olt_info = os.popen('onlpdump -s').read()
179 out = yaml.dump(yaml.load(olt_info)['System Information'])
180 json_data = json.dumps(yaml.load(out))
181 data = json.loads(json_data)
182 except (IOError, TypeError, ValueError, yaml.YAMLError, yaml.MarkedYAMLError) as exception:
183 syslog.syslog(syslog.LOG_ERR, "error-fetching-olt-information-{}".format(exception))
184 return None
185 return data
186
187def get_bal_openolt_version():
188 """
189 Fetch bal and openolt version
190
191 This function retireves OLT's basic information using the command 'onlpdump -s'
192
193 :return : bal and openolt version if successfull and None in case of failure.
194 :rtype : tuple of bal and opneolt version in case of success, else None in case of failure.
195 """
196 try:
197 os.chdir('/')
198 os.environ["LD_LIBRARY_PATH"] = "."
199 version_string = os.popen("./broadcom/openolt --version").read()
200 version_tuple = tuple(version_string.split("\n"))
201 openolt_v = version_tuple[0].split(":")
202 OPENOLT_VERSION = openolt_v[1].split(" ")
203 bal_v = version_tuple[1].split(":")
204 BAL_VERSION = bal_v[1].split(" ")
205 return OPENOLT_VERSION[1], BAL_VERSION[1]
206 except (IOError, NameError) as exception:
207 syslog.syslog(syslog.LOG_ERR, "error-executing-command-{}".format(exception))
208 return None, None
209
210
211def fetch_olt_info():
212 """
213 Gather OLT software and hardware information.
214
215 This function gather OLT information and returns OLT
216 software and hardware information.
217
218 :return: OLT's software and hardware information in case of successful execution
219 and returns None in case of failure
220 :rtype: JSON string in case of success and None in case of failure.
221 """
222
223 hw_facts = {}
224 sw_facts = {}
225
226 # fetch olt basic information
227 data = get_olt_basic_info()
228 if data is None:
229 return None
230
231 olt_model=get_olt_board_name()
232 # retrieving VLAN ids of in-band interfaces
233 vlan = retreive_vlan_id()
234 try:
235 if vlan is not None:
236 # Retreiving MAC address for in-band interfaces
237 if olt_model == ASX_16:
238 macaddr = os.popen("ifconfig " + ETH_2 + "." + str(vlan) +
239 " | grep -Po 'HWaddr " + r"\K.*$'").read().strip()
240 else if olt_model == ASG_64:
241 macaddr = os.popen("ifconfig " + ETH_1 + "." + str(vlan) +
242 " | grep -Po 'HWaddr " + r"\K.*$'").read().strip()
243 else:
244 return None
245
246 # get the operating system version details from olt
247 operating_sys = os.popen("uname -a").read()
248 os_tuple = tuple(operating_sys.split(" "))
249 os_and_version = os_tuple[2].split("-")
250 os_version = os_and_version[0]
251 except (IOError, NameError) as exception:
252 syslog.syslog(syslog.LOG_ERR, "error-executing-command-{}".format(exception))
253 return None
254
255 openolt_v, bal_v = get_bal_openolt_version()
256
257 # adding OLT hardware details to dictionary
258 try:
259 # adding OLT's in-band interfaces mac addresses
260 hw_facts[INBAND_INTERFACE] = macaddr
261 hw_facts[VENDOR] = data.get("Manufacturer", "")
262 hw_facts[SERIAL_NUMBER] = data.get("Serial Number", "")
263 hw_facts[HARDWARE_MODEL] = data.get("Product Name", "")
264 hw_facts[HARDWARE_PART_NUMBER] = data.get("Part Number", "")
265 hw_facts[HARDWARE_VERSION] = data.get("Diag Version", "")
266
267 # adding OLT software details to dictionary
268 sw_facts[OPERATING_SYSTEM] = OS_NAME
269 sw_facts[OPERATING_SYSTEM_VERSION] = os_version
270 sw_facts[ONIE_VERSION] = data.get('ONIE Version', "")
271 sw_facts[BAL_VER] = bal_v
272 sw_facts[OPENOLT_VER] = openolt_v
273
274 # adding OLT hardware and software information to OLT_INFORMATION dictionary
275 OLT_INFORMATION[SOFTWARE_INFORMATION] = sw_facts
276 OLT_INFORMATION[HARDWARE_INFORMATION] = hw_facts
277
278 # converting OLT information to json object
279 olt_json_string = json.dumps(OLT_INFORMATION)
280
281 except (TypeError, NameError) as exception:
282 syslog.syslog(syslog.LOG_ERR, "error-serializing-to-json-data-{}".format(exception))
283 return None
284
285 return olt_json_string
286
287
288if __name__ == "__main__":
289 str_data = fetch_olt_info()
290 if str_data is not None:
291 print(str_data)
292 syslog.syslog(syslog.LOG_INFO, "successfull-execution-printing-OLT-information")
293 exit(0)
294 else:
295 print("error-occurred-exiting")
296 syslog.syslog(syslog.LOG_ERR, "error-occurred-exiting")
297 exit(1)