blob: 83be40b500e929eab0870e7e88ac23d3d0603274 [file] [log] [blame]
Justin Thalerb8807ce2018-05-25 19:16:20 -05001#!/usr/bin/python3
Justin Thalere412dc22018-01-12 16:28:24 -06002"""
3 Copyright 2017 IBM Corporation
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004
Justin Thalere412dc22018-01-12 16:28:24 -06005 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
Justin Thalerf9aee3e2017-12-05 12:11:09 -060017import argparse
18import requests
19import getpass
20import json
21import os
22import urllib3
23import time, datetime
Justin Thalerf9aee3e2017-12-05 12:11:09 -060024import binascii
25import subprocess
26import platform
27import zipfile
Justin Thaler22b1bb52018-03-15 13:31:32 -050028import tarfile
29import tempfile
30import hashlib
Justin Thalera6b5df72018-07-16 11:10:07 -050031import re
Justin Thaler24d4efa2018-11-08 22:48:10 -060032import uuid
Justin Thalerf9aee3e2017-12-05 12:11:09 -060033
Matt Spinler220c3c42019-01-04 15:09:29 -060034jsonHeader = {'Content-Type' : 'application/json'}
35xAuthHeader = {}
Justin Thaler27197622019-01-23 14:42:11 -060036baseTimeout = 60
Matt Spinler220c3c42019-01-04 15:09:29 -060037
Justin Thalerf9aee3e2017-12-05 12:11:09 -060038def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -060039 """
40 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060041
Justin Thalere412dc22018-01-12 16:28:24 -060042 @param textToColor: string, the text to be colored
43 @param color: string, used to color the text red or green
44 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060045 @return: Buffered reader containing the modified string.
46 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -060047 if(sys.platform.__contains__("win")):
48 if(color == "red"):
49 os.system('color 04')
50 elif(color == "green"):
51 os.system('color 02')
52 else:
53 os.system('color') #reset to default
54 return textToColor
55 else:
56 attr = []
57 if(color == "red"):
58 attr.append('31')
59 elif(color == "green"):
60 attr.append('32')
61 else:
62 attr.append('0')
63 if bold:
64 attr.append('1')
65 else:
66 attr.append('0')
67 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
68
Justin Thalerf9aee3e2017-12-05 12:11:09 -060069def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -060070 """
71 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060072
73 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -060074 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060075 @param err: string, the text from the exception
76 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -060077 if errorStr == "Timeout":
78 if not jsonFormat:
79 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
80 else:
Justin Thaler115bca72018-05-25 19:29:08 -050081 conerror = {}
82 conerror['CommonEventID'] = 'FQPSPIN0000M'
83 conerror['sensor']="N/A"
84 conerror['state']="N/A"
85 conerror['additionalDetails'] = "N/A"
86 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
87 conerror['LengthyDescription'] = "While trying to establish a connection with the specified BMC, the BMC failed to respond in adequate time. Verify the BMC is functioning properly, and the network connectivity to the BMC is stable."
88 conerror['Serviceable']="Yes"
89 conerror['CallHomeCandidate']= "No"
90 conerror['Severity'] = "Critical"
91 conerror['EventType'] = "Communication Failure/Timeout"
92 conerror['VMMigrationFlag'] = "Yes"
93 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
94 conerror["timestamp"] = str(int(time.time()))
95 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
96 eventdict = {}
97 eventdict['event0'] = conerror
98 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -050099 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600100 return(errorMessageStr)
101 elif errorStr == "ConnectionError":
102 if not jsonFormat:
103 return("FQPSPIN0001M: " + str(err))
104 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500105 conerror = {}
106 conerror['CommonEventID'] = 'FQPSPIN0001M'
107 conerror['sensor']="N/A"
108 conerror['state']="N/A"
109 conerror['additionalDetails'] = str(err)
110 conerror['Message']="Connection Error. View additional details for more information"
111 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
112 conerror['Serviceable']="Yes"
113 conerror['CallHomeCandidate']= "No"
114 conerror['Severity'] = "Critical"
115 conerror['EventType'] = "Communication Failure/Timeout"
116 conerror['VMMigrationFlag'] = "Yes"
117 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
118 conerror["timestamp"] = str(int(time.time()))
119 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
120 eventdict = {}
121 eventdict['event0'] = conerror
122 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500123 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600124 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500125
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600126 else:
127 return("Unknown Error: "+ str(err))
128
Justin Thalere412dc22018-01-12 16:28:24 -0600129
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600130def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600131 """
132 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600133
134 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600135 @param numcols: the total number of columns in the final output
136 @param dictForOutput: dictionary, contains the information to print to the screen
137 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600138 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600139 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600140 colWidths = []
141 for x in range(0, numCols):
142 colWidths.append(0)
143 for key in dictForOutput:
144 for x in range(0, numCols):
145 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600146
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600147 for x in range(0, numCols):
148 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600149
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600150 return colWidths
151
152def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600153 """
154 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600155
Justin Thalere412dc22018-01-12 16:28:24 -0600156 @param value: boolean, the value to convert
157 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600158 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600159 policyTable = {}
160 if(os.path.exists(pathToPolicyTable)):
161 with open(pathToPolicyTable, 'r') as stream:
162 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600163 contents =json.load(stream)
164 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600165 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600166 print(err)
167 return policyTable
168
Justin Thalere412dc22018-01-12 16:28:24 -0600169
170def boolToString(value):
171 """
172 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600173
Justin Thalere412dc22018-01-12 16:28:24 -0600174 @param value: boolean, the value to convert
175 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600176 """
Justin Thalere412dc22018-01-12 16:28:24 -0600177 if(value):
178 return "Yes"
179 else:
180 return "No"
181
Justin Thalera6b5df72018-07-16 11:10:07 -0500182def stringToInt(text):
183 """
184 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600185
Justin Thalera6b5df72018-07-16 11:10:07 -0500186 @param text: the string to try to convert to an integer
187 """
188 if text.isdigit():
189 return int(text)
190 else:
191 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600192
Justin Thalera6b5df72018-07-16 11:10:07 -0500193def naturalSort(text):
194 """
195 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600196
Justin Thalera6b5df72018-07-16 11:10:07 -0500197 @param text: the key to convert for sorting
198 @return list containing the broken up string parts by integers and strings
199 """
200 stringPartList = []
201 for c in re.split('(\d+)', text):
202 stringPartList.append(stringToInt(c))
203 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600204
Justin Thalere412dc22018-01-12 16:28:24 -0600205def tableDisplay(keylist, colNames, output):
206 """
207 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600208
Justin Thalere412dc22018-01-12 16:28:24 -0600209 @param keylist: list, keys for the output dictionary, ordered by colNames
210 @param colNames: Names for the Table of the columns
211 @param output: The dictionary of data to display
212 @return: Session object
213 """
214 colWidth = setColWidth(keylist, len(colNames), output, colNames)
215 row = ""
216 outputText = ""
217 for i in range(len(colNames)):
218 if (i != 0): row = row + "| "
219 row = row + colNames[i].ljust(colWidth[i])
220 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600221
Justin Thalera6b5df72018-07-16 11:10:07 -0500222 output_keys = list(output.keys())
223 output_keys.sort(key=naturalSort)
224 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600225 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500226 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600227 if (i != 0): row = row + "| "
228 row = row + output[key][keylist[i]].ljust(colWidth[i])
229 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600230
Justin Thalere412dc22018-01-12 16:28:24 -0600231 return outputText
232
Justin Thaler22b1bb52018-03-15 13:31:32 -0500233def checkFWactivation(host, args, session):
234 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600235 Checks the software inventory for an image that is being activated.
236
Justin Thaler22b1bb52018-03-15 13:31:32 -0500237 @return: True if an image is being activated, false is no activations are happening
238 """
239 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500240 try:
Justin Thaler27197622019-01-23 14:42:11 -0600241 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500242 except(requests.exceptions.Timeout):
243 print(connectionErrHandler(args.json, "Timeout", None))
244 return(True)
245 except(requests.exceptions.ConnectionError) as err:
246 print( connectionErrHandler(args.json, "ConnectionError", err))
247 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600248 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500249 for key in fwInfo:
250 if 'Activation' in fwInfo[key]:
251 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
252 return True
253 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600254
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600255def login(host, username, pw,jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600256 """
257 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600258
Justin Thalere412dc22018-01-12 16:28:24 -0600259 @param host: string, the hostname or IP address of the bmc to log into
260 @param username: The user name for the bmc to log into
261 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600262 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
Justin Thalere412dc22018-01-12 16:28:24 -0600263 @return: Session object
264 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600265 if(jsonFormat==False):
266 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600267 mysess = requests.session()
268 try:
Justin Thaler27197622019-01-23 14:42:11 -0600269 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Matt Spinler220c3c42019-01-04 15:09:29 -0600270
271 cookie = r.headers['Set-Cookie']
272 match = re.search('SESSION=(\w+);', cookie)
273 if match:
274 xAuthHeader['X-Auth-Token'] = match.group(1)
275 jsonHeader.update(xAuthHeader)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600276 loginMessage = json.loads(r.text)
277 if (loginMessage['status'] != "ok"):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600278 print(loginMessage["data"]["description"].encode('utf-8'))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600279 sys.exit(1)
280# if(sys.version_info < (3,0)):
281# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
282# if sys.version_info >= (3,0):
283# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
284 return mysess
285 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500286 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600287 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500288 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600289
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600290
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600291def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600292 """
293 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600294
Justin Thalere412dc22018-01-12 16:28:24 -0600295 @param host: string, the hostname or IP address of the bmc to log out of
296 @param username: The user name for the bmc to log out of
297 @param pw: The password for the BMC to log out of
298 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600299 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
300 """
Justin Thalere412dc22018-01-12 16:28:24 -0600301 try:
Justin Thaler27197622019-01-23 14:42:11 -0600302 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600303 except(requests.exceptions.Timeout):
304 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600305
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600306 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600307 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600308 print('User ' +username + ' has been logged out')
309
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600310
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600311def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600312 """
313 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600314
Justin Thalere412dc22018-01-12 16:28:24 -0600315 @param host: string, the hostname or IP address of the bmc
316 @param args: contains additional arguments used by the fru sub command
317 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600318 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
319 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600320 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600321
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600322 #print(url)
323 #res = session.get(url, headers=httpHeader, verify=False)
324 #print(res.text)
325 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600326
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600327 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600328
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600329 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600330 try:
Justin Thaler27197622019-01-23 14:42:11 -0600331 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600332 except(requests.exceptions.Timeout):
333 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600334
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600335 sample = res.text
336# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600337#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600338# #determine column width's
339# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
340# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600341#
342# print("FRU Name".ljust(colWidths[0])+ "FRU Type".ljust(colWidths[1]) + "Has Fault".ljust(colWidths[2]) + "Is FRU".ljust(colWidths[3])+
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600343# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
344# format the output
345# for key in sorted(inv_list.keys()):
346# keyParts = key.split("/")
347# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600348#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600349# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
350# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
351# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
352# if(isTTY):
353# if(inv_list[key]["is_fru"] == 1):
354# color = "green"
355# bold = True
356# else:
357# color='black'
358# bold = False
359# fruEntry = hilight(fruEntry, color, bold)
360# print (fruEntry)
361 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600362
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600363def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600364 """
365 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600366
Justin Thalere412dc22018-01-12 16:28:24 -0600367 @param host: string, the hostname or IP address of the bmc
368 @param args: contains additional arguments used by the fru sub command
369 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600370 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
371 @return returns the total fru list.
372 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600373 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600374 try:
Justin Thaler27197622019-01-23 14:42:11 -0600375 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600376 except(requests.exceptions.Timeout):
377 return(connectionErrHandler(args.json, "Timeout", None))
378
Justin Thaler3a5771b2019-01-23 14:31:52 -0600379 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600380# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600381 if res.status_code==200:
382 frulist['Hardware'] = res.json()['data']
383 else:
384 if not args.json:
385 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
386 else:
387 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600388 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600389 try:
Justin Thaler27197622019-01-23 14:42:11 -0600390 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600391 except(requests.exceptions.Timeout):
392 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600393# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600394 if res.status_code==200:
395 frulist['Software'] = res.json()['data']
396 else:
397 if not args.json():
398 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
399 else:
400 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600401 return frulist
402
Justin Thalere412dc22018-01-12 16:28:24 -0600403
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600404def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600405 """
406 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600407
Justin Thalere412dc22018-01-12 16:28:24 -0600408 @param host: string, the hostname or IP address of the bmc
409 @param args: contains additional arguments used by the fru sub command
410 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600411 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
412 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600413 if(args.items==True):
414 return fruPrint(host, args, session)
415 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600416 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600417
418
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600419
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600420def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600421 """
422 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600423
Justin Thalere412dc22018-01-12 16:28:24 -0600424 @param host: string, the hostname or IP address of the bmc
425 @param args: contains additional arguments used by the fru sub command
426 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600427 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
428 """
Justin Thalere412dc22018-01-12 16:28:24 -0600429 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600430 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600431 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600432 except(requests.exceptions.Timeout):
433 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600434# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600435 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600436 frus = {}
437 for key in frulist:
438 component = frulist[key]
439 isFru = False
440 present = False
441 func = False
442 hasSels = False
443 keyPieces = key.split('/')
444 fruName = keyPieces[-1]
445 if 'core' in fruName: #associate cores to cpus
446 fruName = keyPieces[-2] + '-' + keyPieces[-1]
447 if 'Functional' in component:
448 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600449 if 'FieldReplaceable' in component:
450 if component['FieldReplaceable'] == 1:
451 isFru = True
452 if "fan" in fruName:
453 isFru = True;
454 if component['Present'] == 1:
455 present = True
456 if component['Functional'] == 1:
457 func = True
458 if ((key + "/fault") in frulist):
459 hasSels = True;
460 if args.verbose:
461 if hasSels:
462 loglist = []
463 faults = frulist[key+"/fault"]['endpoints']
464 for item in faults:
465 loglist.append(item.split('/')[-1])
466 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
467 else:
468 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
469 else:
470 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500471 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600472 if component['Present'] ==1:
473 present = True
474 isFru = True
475 if ((key + "/fault") in frulist):
476 hasSels = True;
477 if args.verbose:
478 if hasSels:
479 loglist = []
480 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100481 for item in faults:
482 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600483 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
484 else:
485 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
486 else:
487 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
488 if not args.json:
489 if not args.verbose:
490 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
491 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
492 else:
493 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
494 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
495 return tableDisplay(keylist, colNames, frus)
496 else:
497 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600498
Justin Thalere412dc22018-01-12 16:28:24 -0600499def sensor(host, args, session):
500 """
501 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600502
Justin Thalere412dc22018-01-12 16:28:24 -0600503 @param host: string, the hostname or IP address of the bmc
504 @param args: contains additional arguments used by the sensor sub command
505 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600506 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
507 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600508 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600509 try:
Justin Thaler27197622019-01-23 14:42:11 -0600510 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600511 except(requests.exceptions.Timeout):
512 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600513
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600514 #Get OCC status
515 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600516 try:
Justin Thaler27197622019-01-23 14:42:11 -0600517 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600518 except(requests.exceptions.Timeout):
519 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600520 if not args.json:
521 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600522 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600523 output = {}
524 for key in sensors:
525 senDict = {}
526 keyparts = key.split("/")
527 senDict['sensorName'] = keyparts[-1]
528 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600529 try:
530 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
531 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500532 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600533 if('Scale' in sensors[key]):
534 scale = 10 ** sensors[key]['Scale']
535 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600536 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500537 try:
538 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600539 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500540 if 'value' in sensors[key]:
541 senDict['value'] = sensors[key]['value']
542 else:
543 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600544 if 'Target' in sensors[key]:
545 senDict['target'] = str(sensors[key]['Target'])
546 else:
547 senDict['target'] = 'N/A'
548 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600549
Justin Thaler3a5771b2019-01-23 14:31:52 -0600550 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600551 if '/org/open_power/control/occ0' in occstatus:
552 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600553 if occ0 == 1:
554 occ0 = 'Active'
555 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600556 occ0 = 'Inactive'
557 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
558 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600559 if occ1 == 1:
560 occ1 = 'Active'
561 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600562 occ1 = 'Inactive'
563 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
564 else:
565 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
566 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
567 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600568
569 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600570 else:
571 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600572
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600573def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600574 """
575 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600576
Justin Thalere412dc22018-01-12 16:28:24 -0600577 @param host: string, the hostname or IP address of the bmc
578 @param args: contains additional arguments used by the sel sub command
579 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600580 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
581 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600582
583 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600584 try:
Justin Thaler27197622019-01-23 14:42:11 -0600585 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600586 except(requests.exceptions.Timeout):
587 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600588 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600589
590
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600591def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600592 """
593 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600594
Justin Thalere412dc22018-01-12 16:28:24 -0600595 @param eselRAW: string, the raw esel string from the bmc
596 @return: A dictionary containing the quick snapshot data unless args.fullEsel is listed then a full PEL log is returned
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600597 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600598 eselParts = {}
599 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
600 #search terms contains the search term as the key and the return dictionary key as it's value
601 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500602 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600603 uniqueID = str(uuid.uuid4())
604 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500605 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600606 f.write(esel_bin)
607 errlPath = ""
608 #use the right errl file for the machine architecture
609 arch = platform.machine()
610 if(arch =='x86_64' or arch =='AMD64'):
611 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
612 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
613 elif os.path.exists('errl/x86_64/errl'):
614 errlPath = 'errl/x86_64/errl'
615 else:
616 errlPath = 'x86_64/errl'
617 elif (platform.machine()=='ppc64le'):
618 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
619 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
620 elif os.path.exists('errl/ppc64le/errl'):
621 errlPath = 'errl/ppc64le/errl'
622 else:
623 errlPath = 'ppc64le/errl'
624 else:
625 print("machine architecture not supported for parsing eSELs")
626 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600627
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600628 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500629 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600630# output = proc.communicate()[0]
631 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600632
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600633 if(hasattr(args, 'fullEsel')):
634 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600635
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600636 for i in range(0, len(lines)):
637 lineParts = lines[i].split(':')
638 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
639 for term in searchTerms:
640 if(term in lineParts[0]):
641 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
642 if lines[i+1].find(':') != -1:
643 if (len(lines[i+1].split(':')[0][1:].strip())==0):
644 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600645 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600646 if((i+1) <= len(lines)):
647 i+=1
648 else:
649 i=i-1
650 break
Justin Thaler43030422018-11-08 22:50:21 -0600651 #Append the content from the next line removing the pretty display characters
652 #Finds the first colon then starts 2 characters after, then removes all whitespace
653 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500654 if(searchTerms[term] in eselParts):
655 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
656 else:
657 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500658 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600659 else:
660 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600661
662 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600663
Justin Thalere412dc22018-01-12 16:28:24 -0600664
Matt Spinler02d0dff2018-08-29 13:19:25 -0500665def getESELSeverity(esel):
666 """
667 Finds the severity type in an eSEL from the User Header section.
668 @param esel - the eSEL data
669 @return severity - e.g. 'Critical'
670 """
671
672 # everything but 1 and 2 are Critical
673 # '1': 'recovered',
674 # '2': 'predictive',
675 # '4': 'unrecoverable',
676 # '5': 'critical',
677 # '6': 'diagnostic',
678 # '7': 'symptom'
679 severities = {
680 '1': 'Informational',
681 '2': 'Warning'
682 }
683
684 try:
685 headerPosition = esel.index('55 48') # 'UH'
686 # The severity is the last byte in the 8 byte section (a byte is ' bb')
687 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
688 type = severity[0]
689 except ValueError:
690 print("Could not find severity value in UH section in eSEL")
691 type = 'x';
692
693 return severities.get(type, 'Critical')
694
695
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600696def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600697 """
698 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600699
Justin Thalere412dc22018-01-12 16:28:24 -0600700 @param events: Dictionary containing events
701 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600702 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600703 logNumList = []
704 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600705 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600706 eventsWithTimestamp = {}
707 logNum2events = {}
708 for key in events:
709 if key == 'numAlerts': continue
710 if 'callout' in key: continue
711 timestamp = (events[key]['timestamp'])
712 if timestamp not in timestampList:
713 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
714 else:
715 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
716 #map logNumbers to the event dictionary keys
717 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600718
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600719 timestampList = list(eventsWithTimestamp.keys())
720 timestampList.sort()
721 for ts in timestampList:
722 if len(eventsWithTimestamp[ts]) > 1:
723 tmplist = eventsWithTimestamp[ts]
724 tmplist.sort()
725 logNumList = logNumList + tmplist
726 else:
727 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600728
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600729 return [logNumList, eventKeyDict]
730
Justin Thalere412dc22018-01-12 16:28:24 -0600731
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600732def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600733 """
734 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600735
Justin Thalere412dc22018-01-12 16:28:24 -0600736 @param policyTable: dictionary, the policy table entries
737 @param selEntries: dictionary, the alerts retrieved from the bmc
738 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600739 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600740 eventDict = {}
741 eventNum =""
742 count = 0
743 esel = ""
744 eselParts = {}
745 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500746 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600747
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600748 'prepare and sort the event entries'
749 for key in selEntries:
750 if 'callout' not in key:
751 selEntries[key]['logNum'] = key.split('/')[-1]
752 selEntries[key]['timestamp'] = selEntries[key]['Timestamp']
753 sortedEntries = sortSELs(selEntries)
754 logNumList = sortedEntries[0]
755 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600756
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600757 for logNum in logNumList:
758 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600759 hasEsel=False
760 i2creadFail = False
761 if 'callout' in key:
762 continue
763 else:
764 messageID = str(selEntries[key]['Message'])
765 addDataPiece = selEntries[key]['AdditionalData']
766 calloutIndex = 0
767 calloutFound = False
768 for i in range(len(addDataPiece)):
769 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
770 calloutIndex = i
771 calloutFound = True
772 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
773 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
774 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500775
776 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
777
778 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
779 if (messageID + '||' + fruCallout) not in policyTable:
780 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
781 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
782 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
783 fruCallout = 'FSI'
784 else:
785 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500786 calloutFound = True
787 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
788 if not calloutFound:
789 fruCallout = 'GPIO'
790 calloutFound = True
791 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
792 if not calloutFound:
793 fruCallout = "I2C"
794 calloutFound = True
795 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
796 if not calloutFound:
797 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600798 calloutFound = True
799 if("ESEL" in addDataPiece[i]):
800 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500801 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600802 if args.devdebug:
803 eselParts = parseESEL(args, esel)
804 hasEsel=True
805 if("GPU" in addDataPiece[i]):
806 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
807 calloutFound = True
808 if("PROCEDURE" in addDataPiece[i]):
809 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
810 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600811 if("RAIL_NAME" in addDataPiece[i]):
812 calloutFound=True
813 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
814 if("INPUT_NAME" in addDataPiece[i]):
815 calloutFound=True
816 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
817 if("SENSOR_TYPE" in addDataPiece[i]):
818 calloutFound=True
819 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600820
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600821 if(calloutFound):
Justin Thaler22b1bb52018-03-15 13:31:32 -0500822 if fruCallout != "":
823 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -0500824
825 # Also use the severity for hostboot errors
826 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
827 policyKey += '||' + eselSeverity
828
829 # if not in the table, fall back to the original key
830 if policyKey not in policyTable:
831 policyKey = policyKey.replace('||'+eselSeverity, '')
832
Justin Thalere34c43a2018-05-25 19:37:55 -0500833 if policyKey not in policyTable:
834 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -0500835 else:
836 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600837 else:
838 policyKey = messageID
839 event = {}
840 eventNum = str(count)
841 if policyKey in policyTable:
842 for pkey in policyTable[policyKey]:
843 if(type(policyTable[policyKey][pkey])== bool):
844 event[pkey] = boolToString(policyTable[policyKey][pkey])
845 else:
846 if (i2creadFail and pkey == 'Message'):
847 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
848 else:
849 event[pkey] = policyTable[policyKey][pkey]
850 event['timestamp'] = selEntries[key]['Timestamp']
851 event['resolved'] = bool(selEntries[key]['Resolved'])
852 if(hasEsel):
853 if args.devdebug:
854 event['eselParts'] = eselParts
855 event['raweSEL'] = esel
856 event['logNum'] = key.split('/')[-1]
857 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600858
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600859 else:
860 severity = str(selEntries[key]['Severity']).split('.')[-1]
861 if severity == 'Error':
862 severity = 'Critical'
863 eventDict['event'+eventNum] = {}
864 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
865 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
866 eventDict['event' + eventNum]['Severity'] = severity
867 if(hasEsel):
868 if args.devdebug:
869 eventDict['event' +eventNum]['eselParts'] = eselParts
870 eventDict['event' +eventNum]['raweSEL'] = esel
871 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
872 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600873 count += 1
874 return eventDict
875
876
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600877def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600878 """
879 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600880
Justin Thalere412dc22018-01-12 16:28:24 -0600881 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600882 @return:
883 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600884 activeAlerts = []
885 historyAlerts = []
886 sortedEntries = sortSELs(events)
887 logNumList = sortedEntries[0]
888 eventKeyDict = sortedEntries[1]
889 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
890 if(args.devdebug):
891 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
892 keylist.append('eSEL')
893 else:
894 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
895 for log in logNumList:
896 selDict = {}
897 alert = events[eventKeyDict[str(log)]]
898 if('error' in alert):
899 selDict['Entry'] = alert['logNum']
900 selDict['ID'] = 'Unknown'
901 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
902 msg = alert['error']
903 polMsg = msg.split("policy table:")[0]
904 msg = msg.split("policy table:")[1]
905 msgPieces = msg.split("||")
906 err = msgPieces[0]
907 if(err.find("org.open_power.")!=-1):
908 err = err.split("org.open_power.")[1]
909 elif(err.find("xyz.openbmc_project.")!=-1):
910 err = err.split("xyz.openbmc_project.")[1]
911 else:
912 err = msgPieces[0]
913 callout = ""
914 if len(msgPieces) >1:
915 callout = msgPieces[1]
916 if(callout.find("/org/open_power/")!=-1):
917 callout = callout.split("/org/open_power/")[1]
918 elif(callout.find("/xyz/openbmc_project/")!=-1):
919 callout = callout.split("/xyz/openbmc_project/")[1]
920 else:
921 callout = msgPieces[1]
922 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600923 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600924 selDict['Severity'] = alert['Severity']
925 else:
926 selDict['Entry'] = alert['logNum']
927 selDict['ID'] = alert['CommonEventID']
928 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600929 selDict['Message'] = alert['Message']
930 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600931 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600932
933
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600934 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
935 if ('eselParts' in alert and args.devdebug):
936 eselOutput = ""
937 for item in eselOrder:
938 if item in alert['eselParts']:
939 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
940 selDict['eSEL'] = eselOutput
941 else:
942 if args.devdebug:
943 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600944
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600945 if not alert['resolved']:
946 activeAlerts.append(selDict)
947 else:
948 historyAlerts.append(selDict)
949 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600950 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
951
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600952 output = ""
953 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600954 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600955 output +="----Active Alerts----\n"
956 for i in range(0, len(colNames)):
957 if i!=0: row =row + "| "
958 row = row + colNames[i].ljust(colWidth[i])
959 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600960
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600961 for i in range(0,len(activeAlerts)):
962 row = ""
963 for j in range(len(activeAlerts[i])):
964 if (j != 0): row = row + "| "
965 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
966 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600967
968 if(len(historyAlerts)>0):
969 row = ""
970 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600971 for i in range(len(colNames)):
972 if i!=0: row =row + "| "
973 row = row + colNames[i].ljust(colWidth[i])
974 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600975
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600976 for i in range(0, len(historyAlerts)):
977 row = ""
978 for j in range(len(historyAlerts[i])):
979 if (j != 0): row = row + "| "
980 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
981 output += row + "\n"
982# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600983 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600984
Justin Thalere412dc22018-01-12 16:28:24 -0600985
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600986def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600987 """
988 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600989
Justin Thalere412dc22018-01-12 16:28:24 -0600990 @param host: string, the hostname or IP address of the bmc
991 @param args: contains additional arguments used by the fru sub command
992 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600993 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
994 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600995 if(args.policyTableLoc is None):
996 if os.path.exists('policyTable.json'):
997 ptableLoc = "policyTable.json"
998 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
999 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1000 else:
1001 ptableLoc = 'lib/policyTable.json'
1002 else:
1003 ptableLoc = args.policyTableLoc
1004 policyTable = loadPolicyTable(ptableLoc)
1005 rawselEntries = ""
1006 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1007 if os.path.exists(args.fileloc):
1008 with open(args.fileloc, 'r') as selFile:
1009 selLines = selFile.readlines()
1010 rawselEntries = ''.join(selLines)
1011 else:
1012 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001013 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001014 else:
1015 rawselEntries = sel(host, args, session)
1016 loadFailed = False
1017 try:
1018 selEntries = json.loads(rawselEntries)
1019 except ValueError:
1020 loadFailed = True
1021 if loadFailed:
1022 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1023 #need to load json twice as original content was string escaped a second time
1024 selEntries = json.loads(json.loads(cleanSels))
1025 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001026
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001027 if 'description' in selEntries:
1028 if(args.json):
1029 return("{\n\t\"numAlerts\": 0\n}")
1030 else:
1031 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001032
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001033 else:
1034 if(len(policyTable)>0):
1035 events = parseAlerts(policyTable, selEntries, args)
1036 if(args.json):
1037 events["numAlerts"] = len(events)
1038 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1039 return retValue
1040 elif(hasattr(args, 'fullSel')):
1041 return events
1042 else:
1043 #get log numbers to order event entries sequentially
1044 return selDisplay(events, args)
1045 else:
1046 if(args.json):
1047 return selEntries
1048 else:
1049 print("error: Policy Table not found.")
1050 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001051
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001052def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001053 """
1054 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001055
Justin Thalere412dc22018-01-12 16:28:24 -06001056 @param host: string, the hostname or IP address of the bmc
1057 @param args: contains additional arguments used by the fru sub command
1058 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001059 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1060 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001061 return(sel(host, args, session))
1062
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001063
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001064def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001065 """
1066 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001067
Justin Thalere412dc22018-01-12 16:28:24 -06001068 @param host: string, the hostname or IP address of the bmc
1069 @param args: contains additional arguments used by the fru sub command
1070 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001071 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1072 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001073 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001074 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001075
Justin Thalere412dc22018-01-12 16:28:24 -06001076 try:
Justin Thaler27197622019-01-23 14:42:11 -06001077 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001078 except(requests.exceptions.Timeout):
1079 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001080 if res.status_code == 200:
1081 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1082 else:
1083 print("Unable to clear the logs, trying to clear 1 at a time")
1084 sels = json.loads(sel(host, args, session))['data']
1085 for key in sels:
1086 if 'callout' not in key:
1087 logNum = key.split('/')[-1]
1088 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1089 try:
Justin Thaler27197622019-01-23 14:42:11 -06001090 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001091 except(requests.exceptions.Timeout):
1092 return connectionErrHandler(args.json, "Timeout", None)
1093 sys.exit(1)
1094 except(requests.exceptions.ConnectionError) as err:
1095 return connectionErrHandler(args.json, "ConnectionError", err)
1096 sys.exit(1)
1097 return ('Sel clearing complete')
1098
1099def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001100 """
1101 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001102
Justin Thalere412dc22018-01-12 16:28:24 -06001103 @param host: string, the hostname or IP address of the bmc
1104 @param args: contains additional arguments used by the fru sub command
1105 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001106 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1107 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001108 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001109 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001110 try:
Justin Thaler27197622019-01-23 14:42:11 -06001111 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001112 except(requests.exceptions.Timeout):
1113 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001114 if res.status_code == 200:
1115 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1116 else:
1117 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001118
Justin Thalere412dc22018-01-12 16:28:24 -06001119def selResolveAll(host, args, session):
1120 """
1121 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001122
Justin Thalere412dc22018-01-12 16:28:24 -06001123 @param host: string, the hostname or IP address of the bmc
1124 @param args: contains additional arguments used by the fru sub command
1125 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001126 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1127 """
Justin Thalere412dc22018-01-12 16:28:24 -06001128 rawselEntries = sel(host, args, session)
1129 loadFailed = False
1130 try:
1131 selEntries = json.loads(rawselEntries)
1132 except ValueError:
1133 loadFailed = True
1134 if loadFailed:
1135 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1136 #need to load json twice as original content was string escaped a second time
1137 selEntries = json.loads(json.loads(cleanSels))
1138 selEntries = selEntries['data']
1139
1140 if 'description' in selEntries:
1141 if(args.json):
1142 return("{\n\t\"selsResolved\": 0\n}")
1143 else:
1144 return("No log entries found")
1145 else:
1146 d = vars(args)
1147 successlist = []
1148 failedlist = []
1149 for key in selEntries:
1150 if 'callout' not in key:
1151 d['selNum'] = key.split('/')[-1]
1152 resolved = selSetResolved(host,args,session)
1153 if 'Sel entry' in resolved:
1154 successlist.append(d['selNum'])
1155 else:
1156 failedlist.append(d['selNum'])
1157 output = ""
1158 successlist.sort()
1159 failedlist.sort()
1160 if len(successlist)>0:
1161 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1162 if len(failedlist)>0:
1163 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1164 return output
1165
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001166def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001167 """
1168 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001169
Justin Thalere412dc22018-01-12 16:28:24 -06001170 @param host: string, the hostname or IP address of the bmc
1171 @param args: contains additional arguments used by the fru sub command
1172 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001173 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1174 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001175 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001176 if checkFWactivation(host, args, session):
1177 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001178 print("Attempting to Power on...:")
1179 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001180 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001181 try:
Justin Thaler27197622019-01-23 14:42:11 -06001182 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001183 except(requests.exceptions.Timeout):
1184 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001185 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001186 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001187 if checkFWactivation(host, args, session):
1188 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001189 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001190 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001191 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001192 try:
Justin Thaler27197622019-01-23 14:42:11 -06001193 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001194 except(requests.exceptions.Timeout):
1195 return(connectionErrHandler(args.json, "Timeout", None))
1196 return res.text
1197 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001198 if checkFWactivation(host, args, session):
1199 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001200 print("Attempting to Power off immediately...:")
1201 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001202 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1203 try:
Justin Thaler27197622019-01-23 14:42:11 -06001204 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001205 except(requests.exceptions.Timeout):
1206 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001207 return res.text
1208 elif(args.powcmd == 'status'):
1209 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001210 try:
Justin Thaler27197622019-01-23 14:42:11 -06001211 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001212 except(requests.exceptions.Timeout):
1213 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001214 chassisState = json.loads(res.text)['data'].split('.')[-1]
1215 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001216 try:
Justin Thaler27197622019-01-23 14:42:11 -06001217 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001218 except(requests.exceptions.Timeout):
1219 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001220 hostState = json.loads(res.text)['data'].split('.')[-1]
1221 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001222 try:
Justin Thaler27197622019-01-23 14:42:11 -06001223 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001224 except(requests.exceptions.Timeout):
1225 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001226 bmcState = json.loads(res.text)['data'].split('.')[-1]
1227 if(args.json):
1228 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1229 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1230 else:
1231 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1232 else:
1233 return "Invalid chassis power command"
1234
Justin Thalere412dc22018-01-12 16:28:24 -06001235
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001236def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001237 """
1238 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001239
Justin Thalere412dc22018-01-12 16:28:24 -06001240 @param host: string, the hostname or IP address of the bmc
1241 @param args: contains additional arguments used by the fru sub command
1242 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001243 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001244 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001245 if(args.identcmd == 'on'):
1246 print("Attempting to turn identify light on...:")
1247 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001248 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001249 try:
Justin Thaler27197622019-01-23 14:42:11 -06001250 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001251 except(requests.exceptions.Timeout):
1252 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001253 return res.text
1254 elif(args.identcmd == 'off'):
1255 print("Attempting to turn identify light off...:")
1256 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001257 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001258 try:
Justin Thaler27197622019-01-23 14:42:11 -06001259 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001260 except(requests.exceptions.Timeout):
1261 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001262 return res.text
1263 elif(args.identcmd == 'status'):
1264 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001265 try:
Justin Thaler27197622019-01-23 14:42:11 -06001266 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001267 except(requests.exceptions.Timeout):
1268 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001269 status = json.loads(res.text)['data']
1270 if(args.json):
1271 return status
1272 else:
1273 if status['Asserted'] == 0:
1274 return "Identify light is off"
1275 else:
1276 return "Identify light is blinking"
1277 else:
1278 return "Invalid chassis identify command"
1279
Justin Thalere412dc22018-01-12 16:28:24 -06001280
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001281def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001282 """
1283 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001284
Justin Thalere412dc22018-01-12 16:28:24 -06001285 @param host: string, the hostname or IP address of the bmc
1286 @param args: contains additional arguments used by the fru sub command
1287 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001288 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1289 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001290 if(hasattr(args, 'powcmd')):
1291 result = chassisPower(host,args,session)
1292 elif(hasattr(args, 'identcmd')):
1293 result = chassisIdent(host, args, session)
1294 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001295 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001296 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001297
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001298def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001299 """
1300 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001301
Justin Thalere412dc22018-01-12 16:28:24 -06001302 @param host: string, the hostname or IP address of the bmc
1303 @param args: contains additional arguments used by the collectServiceData sub command
1304 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001305 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001306 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001307 dumpNum = args.dumpNum
1308 if (args.dumpSaveLoc is not None):
1309 saveLoc = args.dumpSaveLoc
1310 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001311 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001312 url ='https://'+host+'/download/dump/' + str(dumpNum)
1313 try:
Justin Thaler27197622019-01-23 14:42:11 -06001314 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001315 if (args.dumpSaveLoc is not None):
1316 if os.path.exists(saveLoc):
1317 if saveLoc[-1] != os.path.sep:
1318 saveLoc = saveLoc + os.path.sep
1319 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001320
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001321 else:
1322 return 'Invalid save location specified'
1323 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001324 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001325
1326 with open(filename, 'wb') as f:
1327 for chunk in r.iter_content(chunk_size =1024):
1328 if chunk:
1329 f.write(chunk)
1330 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001331
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001332 except(requests.exceptions.Timeout):
1333 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001334
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001335 except(requests.exceptions.ConnectionError) as err:
1336 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001337
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001338def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001339 """
1340 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001341
Justin Thalere412dc22018-01-12 16:28:24 -06001342 @param host: string, the hostname or IP address of the bmc
1343 @param args: contains additional arguments used by the collectServiceData sub command
1344 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001345 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1346 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001347 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1348 try:
Justin Thaler27197622019-01-23 14:42:11 -06001349 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001350 dumpList = r.json()
1351 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001352 except(requests.exceptions.Timeout):
1353 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001354
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001355 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001356 return connectionErrHandler(args.json, "ConnectionError", err)
1357
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001358def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001359 """
1360 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001361
Justin Thalere412dc22018-01-12 16:28:24 -06001362 @param host: string, the hostname or IP address of the bmc
1363 @param args: contains additional arguments used by the collectServiceData sub command
1364 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001365 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001366 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001367 dumpList = []
1368 successList = []
1369 failedList = []
1370 if args.dumpNum is not None:
1371 if isinstance(args.dumpNum, list):
1372 dumpList = args.dumpNum
1373 else:
1374 dumpList.append(args.dumpNum)
1375 for dumpNum in dumpList:
1376 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1377 try:
Justin Thaler27197622019-01-23 14:42:11 -06001378 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001379 if r.status_code == 200:
1380 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001381 else:
1382 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001383 except(requests.exceptions.Timeout):
1384 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001385 except(requests.exceptions.ConnectionError) as err:
1386 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001387 output = "Successfully deleted dumps: " + ', '.join(successList)
1388 if(len(failedList)>0):
1389 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1390 return output
1391 else:
1392 return 'You must specify an entry number to delete'
1393
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001394def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001395 """
1396 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001397
Justin Thalere412dc22018-01-12 16:28:24 -06001398 @param host: string, the hostname or IP address of the bmc
1399 @param args: contains additional arguments used by the collectServiceData sub command
1400 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001401 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001402 """
1403 dumpResp = bmcDumpList(host, args, session)
1404 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1405 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001406 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001407 d = vars(args)
1408 dumpNums = []
1409 for dump in dumpList:
1410 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1411 dumpNums.append(int(dump.strip().split('/')[-1]))
1412 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001413
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001414 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001415
Justin Thalere412dc22018-01-12 16:28:24 -06001416
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001417def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001418 """
1419 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001420
Justin Thalere412dc22018-01-12 16:28:24 -06001421 @param host: string, the hostname or IP address of the bmc
1422 @param args: contains additional arguments used by the collectServiceData sub command
1423 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001424 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001425 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001426 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1427 try:
Justin Thaler27197622019-01-23 14:42:11 -06001428 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Matt Spinlereae05b02019-01-24 12:59:34 -06001429 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001430 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001431 elif(args.json):
1432 return r.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001433 else:
1434 return ('Failed to create dump')
1435 except(requests.exceptions.Timeout):
1436 return connectionErrHandler(args.json, "Timeout", None)
1437 except(requests.exceptions.ConnectionError) as err:
1438 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001439
1440
1441
Justin Thalere412dc22018-01-12 16:28:24 -06001442
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001443def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001444 """
1445 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001446
Justin Thalere412dc22018-01-12 16:28:24 -06001447 @param host: string, the hostname or IP address of the bmc
1448 @param args: contains additional arguments used by the collectServiceData sub command
1449 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001450 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Justin Thalere412dc22018-01-12 16:28:24 -06001451 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001452
Justin Thaler22b1bb52018-03-15 13:31:32 -05001453 global toolVersion
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001454 #create a bmc dump
1455 dumpcount = len(json.loads(bmcDumpList(host, args, session))['data'])
1456 try:
1457 dumpcreated = bmcDumpCreate(host, args, session)
1458 except Exception as e:
1459 print('failed to create a bmc dump')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001460
1461
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001462 #Collect Inventory
1463 try:
1464 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05001465 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001466 os.makedirs(myDir)
1467 filelist = []
1468 frulist = fruPrint(host, args, session)
1469 with open(myDir +'/inventory.txt', 'w') as f:
1470 f.write(frulist)
1471 print("Inventory collected and stored in " + myDir + "/inventory.txt")
1472 filelist.append(myDir+'/inventory.txt')
1473 except Exception as e:
1474 print("Failed to collect inventory")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001475
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001476 #Read all the sensor and OCC status
1477 try:
1478 sensorReadings = sensor(host, args, session)
1479 with open(myDir +'/sensorReadings.txt', 'w') as f:
1480 f.write(sensorReadings)
1481 print("Sensor readings collected and stored in " +myDir + "/sensorReadings.txt")
1482 filelist.append(myDir+'/sensorReadings.txt')
1483 except Exception as e:
1484 print("Failed to collect sensor readings")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001485
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001486 #Collect all of the LEDs status
1487 try:
1488 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
Justin Thaler27197622019-01-23 14:42:11 -06001489 leds = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001490 with open(myDir +'/ledStatus.txt', 'w') as f:
1491 f.write(leds.text)
1492 print("System LED status collected and stored in "+myDir +"/ledStatus.txt")
1493 filelist.append(myDir+'/ledStatus.txt')
1494 except Exception as e:
1495 print("Failed to collect LED status")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001496
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001497 #Collect the bmc logs
1498 try:
1499 sels = selPrint(host,args,session)
1500 with open(myDir +'/SELshortlist.txt', 'w') as f:
1501 f.write(str(sels))
1502 print("sel short list collected and stored in "+myDir +"/SELshortlist.txt")
1503 filelist.append(myDir+'/SELshortlist.txt')
1504 time.sleep(2)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001505
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001506 d = vars(args)
1507 d['json'] = True
1508 d['fullSel'] = True
1509 parsedfullsels = json.loads(selPrint(host, args, session))
1510 d['fullEsel'] = True
1511 sortedSELs = sortSELs(parsedfullsels)
1512 with open(myDir +'/parsedSELs.txt', 'w') as f:
1513 for log in sortedSELs[0]:
1514 esel = ""
1515 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1516 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001517 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
1518 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001519 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
1520 if(args.devdebug and esel != ""):
1521 f.write(parseESEL(args, esel))
1522 print("fully parsed sels collected and stored in "+myDir +"/parsedSELs.txt")
1523 filelist.append(myDir+'/parsedSELs.txt')
1524 except Exception as e:
1525 print("Failed to collect system event logs")
1526 print(e)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001527
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001528 #collect RAW bmc enumeration
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001529 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001530 url="https://"+host+"/xyz/openbmc_project/enumerate"
1531 print("Attempting to get a full BMC enumeration")
Matt Spinler220c3c42019-01-04 15:09:29 -06001532 fullDump = session.get(url, headers=jsonHeader, verify=False, timeout=120)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001533 with open(myDir +'/bmcFullRaw.txt', 'w') as f:
1534 f.write(fullDump.text)
1535 print("RAW BMC data collected and saved into "+myDir +"/bmcFullRaw.txt")
1536 filelist.append(myDir+'/bmcFullRaw.txt')
1537 except Exception as e:
1538 print("Failed to collect bmc full enumeration")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001539
1540 #collect the dump files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001541 waitingForNewDump = True
1542 count = 0;
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001543 while(waitingForNewDump):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001544 dumpList = json.loads(bmcDumpList(host, args, session))['data']
1545 if len(dumpList) > dumpcount:
1546 waitingForNewDump = False
1547 break;
1548 elif(count>30):
1549 print("Timed out waiting for bmc to make a new dump file. Dump space may be full.")
1550 break;
1551 else:
1552 time.sleep(2)
1553 count += 1
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001554 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001555 print('Collecting bmc dump files')
1556 d['dumpSaveLoc'] = myDir
1557 dumpList = json.loads(bmcDumpList(host, args, session))['data']
1558 for dump in dumpList:
1559 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1560 d['dumpNum'] = int(dump.strip().split('/')[-1])
1561 print('retrieving dump file ' + str(d['dumpNum']))
1562 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
1563 filelist.append(filename)
1564 time.sleep(2)
1565 except Exception as e:
1566 print("Failed to collect bmc dump files")
1567 print(e)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001568
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001569 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001570 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05001571 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001572 zf = zipfile.ZipFile(myDir+'/' + filename, 'w')
1573 for myfile in filelist:
1574 zf.write(myfile, os.path.basename(myfile))
1575 zf.close()
1576 except Exception as e:
1577 print("Failed to create zip file with collected information")
1578 return "data collection complete"
1579
Justin Thalere412dc22018-01-12 16:28:24 -06001580
1581def healthCheck(host, args, session):
1582 """
1583 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001584
Justin Thalere412dc22018-01-12 16:28:24 -06001585 @param host: string, the hostname or IP address of the bmc
1586 @param args: contains additional arguments used by the bmc sub command
1587 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001588 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1589 """
Justin Thalere412dc22018-01-12 16:28:24 -06001590 #check fru status and get as json to easily work through
1591 d = vars(args)
1592 useJson = d['json']
1593 d['json'] = True
1594 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001595
Justin Thalere412dc22018-01-12 16:28:24 -06001596 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001597
Justin Thalere412dc22018-01-12 16:28:24 -06001598 hwStatus= "OK"
1599 performanceStatus = "OK"
1600 for key in frus:
1601 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
1602 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05001603 if("power_supply" in key or "powersupply" in key):
1604 gpuCount =0
1605 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06001606 if "gv100card" in comp:
1607 gpuCount +=1
1608 if gpuCount > 4:
1609 hwStatus = "Critical"
1610 performanceStatus="Degraded"
1611 break;
1612 elif("fan" in key):
1613 hwStatus = "Degraded"
1614 else:
1615 performanceStatus = "Degraded"
1616 if useJson:
1617 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
1618 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1619 else:
1620 output = ("Hardware Status: " + hwStatus +
1621 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001622
1623
Justin Thalere412dc22018-01-12 16:28:24 -06001624 #SW407886: Clear the duplicate entries
1625 #collect the dups
1626 d['devdebug'] = False
1627 sels = json.loads(selPrint(host, args, session))
1628 logNums2Clr = []
1629 oldestLogNum={"logNum": "bogus" ,"key" : ""}
1630 count = 0
1631 if sels['numAlerts'] > 0:
1632 for key in sels:
1633 if "numAlerts" in key:
1634 continue
1635 try:
1636 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
1637 count += 1
1638 if count > 1:
1639 #preserve first occurrence
1640 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
1641 oldestLogNum['key']=key
1642 oldestLogNum['logNum'] = sels[key]['logNum']
1643 else:
1644 oldestLogNum['key']=key
1645 oldestLogNum['logNum'] = sels[key]['logNum']
1646 logNums2Clr.append(sels[key]['logNum'])
1647 except KeyError:
1648 continue
1649 if(count >0):
1650 logNums2Clr.remove(oldestLogNum['logNum'])
1651 #delete the dups
1652 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06001653 data = "{\"data\": [] }"
1654 for logNum in logNums2Clr:
1655 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1656 try:
Justin Thaler27197622019-01-23 14:42:11 -06001657 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001658 except(requests.exceptions.Timeout):
1659 deleteFailed = True
1660 except(requests.exceptions.ConnectionError) as err:
1661 deleteFailed = True
1662 #End of defect resolve code
1663 d['json'] = useJson
1664 return output
1665
1666
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001667
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001668def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001669 """
1670 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001671
Justin Thalere412dc22018-01-12 16:28:24 -06001672 @param host: string, the hostname or IP address of the bmc
1673 @param args: contains additional arguments used by the bmc sub command
1674 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001675 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1676 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001677 if(args.type is not None):
1678 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06001679 if(args.info):
1680 return "Not implemented at this time"
1681
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001682
Justin Thalere412dc22018-01-12 16:28:24 -06001683
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001684def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001685 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001686 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
1687
Justin Thalere412dc22018-01-12 16:28:24 -06001688 @param host: string, the hostname or IP address of the bmc
1689 @param args: contains additional arguments used by the bmcReset sub command
1690 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001691 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1692 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001693 if checkFWactivation(host, args, session):
1694 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001695 if(args.type == "warm"):
1696 print("\nAttempting to reboot the BMC...:")
1697 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001698 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06001699 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001700 return res.text
1701 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06001702 print("\nAttempting to reboot the BMC...:")
1703 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001704 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06001705 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001706 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001707 else:
1708 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06001709
1710def gardClear(host, args, session):
1711 """
1712 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001713
Justin Thalere412dc22018-01-12 16:28:24 -06001714 @param host: string, the hostname or IP address of the bmc
1715 @param args: contains additional arguments used by the gardClear sub command
1716 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001717 """
Justin Thalere412dc22018-01-12 16:28:24 -06001718 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06001719 data = '{"data":[]}'
1720 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001721
Justin Thaler27197622019-01-23 14:42:11 -06001722 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001723 if res.status_code == 404:
1724 return "Command not supported by this firmware version"
1725 else:
1726 return res.text
1727 except(requests.exceptions.Timeout):
1728 return connectionErrHandler(args.json, "Timeout", None)
1729 except(requests.exceptions.ConnectionError) as err:
1730 return connectionErrHandler(args.json, "ConnectionError", err)
1731
1732def activateFWImage(host, args, session):
1733 """
1734 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001735
Justin Thalere412dc22018-01-12 16:28:24 -06001736 @param host: string, the hostname or IP address of the bmc
1737 @param args: contains additional arguments used by the fwflash sub command
1738 @param session: the active session to use
1739 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001740 """
Justin Thalere412dc22018-01-12 16:28:24 -06001741 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001742
Justin Thalere412dc22018-01-12 16:28:24 -06001743 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06001744 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1745 try:
Justin Thaler27197622019-01-23 14:42:11 -06001746 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001747 except(requests.exceptions.Timeout):
1748 return connectionErrHandler(args.json, "Timeout", None)
1749 except(requests.exceptions.ConnectionError) as err:
1750 return connectionErrHandler(args.json, "ConnectionError", err)
1751 existingSoftware = json.loads(resp.text)['data']
1752 altVersionID = ''
1753 versionType = ''
1754 imageKey = '/xyz/openbmc_project/software/'+fwID
1755 if imageKey in existingSoftware:
1756 versionType = existingSoftware[imageKey]['Purpose']
1757 for key in existingSoftware:
1758 if imageKey == key:
1759 continue
1760 if 'Purpose' in existingSoftware[key]:
1761 if versionType == existingSoftware[key]['Purpose']:
1762 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001763
1764
1765
1766
Justin Thalere412dc22018-01-12 16:28:24 -06001767 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
1768 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001769 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06001770 data1 = "{\"data\": 1 }"
1771 try:
Justin Thaler27197622019-01-23 14:42:11 -06001772 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
1773 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001774 except(requests.exceptions.Timeout):
1775 return connectionErrHandler(args.json, "Timeout", None)
1776 except(requests.exceptions.ConnectionError) as err:
1777 return connectionErrHandler(args.json, "ConnectionError", err)
1778 if(not args.json):
1779 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001780 return 'Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. '
Justin Thalere412dc22018-01-12 16:28:24 -06001781 else:
1782 return "Firmware activation failed."
1783 else:
1784 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05001785
1786def activateStatus(host, args, session):
1787 if checkFWactivation(host, args, session):
1788 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
1789 else:
1790 return("No firmware activations are pending")
1791
1792def extractFWimage(path, imageType):
1793 """
1794 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001795
Justin Thaler22b1bb52018-03-15 13:31:32 -05001796 @param path: the path and file name of the firmware image
1797 @param imageType: The type of image the user is trying to flash. Host or BMC
1798 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001799 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001800 f = tempfile.TemporaryFile()
1801 tmpDir = tempfile.gettempdir()
1802 newImageID = ""
1803 if os.path.exists(path):
1804 try:
1805 imageFile = tarfile.open(path,'r')
1806 contents = imageFile.getmembers()
1807 for tf in contents:
1808 if 'MANIFEST' in tf.name:
1809 imageFile.extract(tf.name, path=tmpDir)
1810 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
1811 for line in imageInfo:
1812 if 'purpose' in line:
1813 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001814 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001815 print('The specified image is not for ' + imageType)
1816 print('Please try again with the image for ' + imageType)
1817 return ""
1818 if 'version' == line.split('=')[0]:
1819 version = line.split('=')[1].strip().encode('utf-8')
1820 m = hashlib.sha512()
1821 m.update(version)
1822 newImageID = m.hexdigest()[:8]
1823 break
1824 try:
1825 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
1826 except OSError:
1827 pass
1828 return newImageID
1829 except tarfile.ExtractError as e:
1830 print('Unable to extract information from the firmware file.')
1831 print('Ensure you have write access to the directory: ' + tmpDir)
1832 return newImageID
1833 except tarfile.TarError as e:
1834 print('This is not a valid firmware file.')
1835 return newImageID
1836 print("This is not a valid firmware file.")
1837 return newImageID
1838 else:
1839 print('The filename and path provided are not valid.')
1840 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001841
Justin Thaler22b1bb52018-03-15 13:31:32 -05001842def getAllFWImageIDs(fwInvDict):
1843 """
1844 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001845
Justin Thaler22b1bb52018-03-15 13:31:32 -05001846 @param fwInvDict: the dictionary to search for FW image IDs
1847 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001848 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001849 idList = []
1850 for key in fwInvDict:
1851 if 'Version' in fwInvDict[key]:
1852 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001853 return idList
1854
Justin Thalere412dc22018-01-12 16:28:24 -06001855def fwFlash(host, args, session):
1856 """
1857 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001858
Justin Thalere412dc22018-01-12 16:28:24 -06001859 @param host: string, the hostname or IP address of the bmc
1860 @param args: contains additional arguments used by the fwflash sub command
1861 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001862 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001863 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06001864 if(args.type == 'bmc'):
1865 purp = 'BMC'
1866 else:
1867 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001868
1869 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05001870 d['powcmd'] = 'status'
1871 powerstate = chassisPower(host, args, session)
1872 if 'Chassis Power State: On' in powerstate:
1873 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001874
Justin Thaler22b1bb52018-03-15 13:31:32 -05001875 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06001876 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1877 try:
Justin Thaler27197622019-01-23 14:42:11 -06001878 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001879 except(requests.exceptions.Timeout):
1880 return connectionErrHandler(args.json, "Timeout", None)
1881 except(requests.exceptions.ConnectionError) as err:
1882 return connectionErrHandler(args.json, "ConnectionError", err)
1883 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001884
Justin Thaler22b1bb52018-03-15 13:31:32 -05001885 #Extract the tar and get information from the manifest file
1886 newversionID = extractFWimage(args.fileloc, purp)
1887 if newversionID == "":
1888 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001889
1890
Justin Thaler22b1bb52018-03-15 13:31:32 -05001891 #check if the new image is already on the bmc
1892 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001893
Justin Thaler22b1bb52018-03-15 13:31:32 -05001894 #upload the file
1895 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06001896 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001897 url="https://"+host+"/upload/image"
1898 data=open(args.fileloc,'rb').read()
1899 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06001900 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001901 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06001902 except(requests.exceptions.Timeout):
1903 return connectionErrHandler(args.json, "Timeout", None)
1904 except(requests.exceptions.ConnectionError) as err:
1905 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001906 if resp.status_code != 200:
1907 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06001908 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001909 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001910
Justin Thaler22b1bb52018-03-15 13:31:32 -05001911 #verify bmc processed the image
1912 software ={}
1913 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001914 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1915 try:
Justin Thaler27197622019-01-23 14:42:11 -06001916 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001917 except(requests.exceptions.Timeout):
1918 return connectionErrHandler(args.json, "Timeout", None)
1919 except(requests.exceptions.ConnectionError) as err:
1920 return connectionErrHandler(args.json, "ConnectionError", err)
1921 software = json.loads(resp.text)['data']
1922 #check if bmc is done processing the new image
1923 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06001924 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05001925 else:
1926 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001927
Justin Thaler22b1bb52018-03-15 13:31:32 -05001928 #activate the new image
1929 print("Activating new image: "+newversionID)
1930 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001931 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05001932 try:
Justin Thaler27197622019-01-23 14:42:11 -06001933 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001934 except(requests.exceptions.Timeout):
1935 return connectionErrHandler(args.json, "Timeout", None)
1936 except(requests.exceptions.ConnectionError) as err:
1937 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001938
Justin Thaler22b1bb52018-03-15 13:31:32 -05001939 #wait for the activation to complete, timeout after ~1 hour
1940 i=0
1941 while i < 360:
1942 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001943 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05001944 try:
Justin Thaler27197622019-01-23 14:42:11 -06001945 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001946 except(requests.exceptions.Timeout):
1947 return connectionErrHandler(args.json, "Timeout", None)
1948 except(requests.exceptions.ConnectionError) as err:
1949 return connectionErrHandler(args.json, "ConnectionError", err)
1950 fwInfo = json.loads(resp.text)['data']
1951 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
1952 print('')
1953 break
1954 else:
1955 sys.stdout.write('.')
1956 sys.stdout.flush()
1957 time.sleep(10) #check every 10 seconds
1958 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
1959 else:
1960 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001961
Justin Thaler22b1bb52018-03-15 13:31:32 -05001962 d['imageID'] = newversionID
1963 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06001964
Justin Thaler3d71d402018-07-24 14:35:39 -05001965def getFWInventoryAttributes(rawFWInvItem, ID):
1966 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001967 gets and lists all of the firmware in the system.
1968
Justin Thaler3d71d402018-07-24 14:35:39 -05001969 @return: returns a dictionary containing the image attributes
1970 """
1971 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
1972 pendingActivation = ""
1973 if reqActivation == "None":
1974 pendingActivation = "No"
1975 else:
1976 pendingActivation = "Yes"
1977 firmwareAttr = {ID: {
1978 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
1979 "Version": rawFWInvItem["Version"],
1980 "RequestedActivation": pendingActivation,
1981 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001982
Justin Thaler3d71d402018-07-24 14:35:39 -05001983 if "ExtendedVersion" in rawFWInvItem:
1984 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001985 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05001986 firmwareAttr[ID]['ExtendedVersion'] = ""
1987 return firmwareAttr
1988
1989def parseFWdata(firmwareDict):
1990 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001991 creates a dictionary with parsed firmware data
1992
Justin Thaler3d71d402018-07-24 14:35:39 -05001993 @return: returns a dictionary containing the image attributes
1994 """
1995 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
1996 for key in firmwareDict['data']:
1997 #check for valid endpoint
1998 if "Purpose" in firmwareDict['data'][key]:
1999 id = key.split('/')[-1]
2000 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2001 fwActivated = True
2002 else:
2003 fwActivated = False
2004 if firmwareDict['data'][key]['Priority'] == 0:
2005 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2006 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2007 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2008 else:
2009 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2010 emptySections = []
2011 for key in firmwareInfoDict:
2012 if len(firmwareInfoDict[key])<=0:
2013 emptySections.append(key)
2014 for key in emptySections:
2015 del firmwareInfoDict[key]
2016 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002017
Justin Thaler3d71d402018-07-24 14:35:39 -05002018def displayFWInvenory(firmwareInfoDict, args):
2019 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002020 gets and lists all of the firmware in the system.
2021
Justin Thaler3d71d402018-07-24 14:35:39 -05002022 @return: returns a string containing all of the firmware information
2023 """
2024 output = ""
2025 if not args.json:
2026 for key in firmwareInfoDict:
2027 for subkey in firmwareInfoDict[key]:
2028 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2029 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002030 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002031 colNames = ["Purpose", "Version", "ID"]
2032 keylist = ["Purpose", "Version", "ID"]
2033 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2034 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002035 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002036 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2037 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002038 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002039 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002040
Justin Thaler3d71d402018-07-24 14:35:39 -05002041 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002042 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002043 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2044 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2045 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2046 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002047 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002048 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2049 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002050 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002051 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2052 return output
2053 else:
2054 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2055
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002056def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002057 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002058 gets and lists all of the firmware in the system.
2059
Justin Thaler3d71d402018-07-24 14:35:39 -05002060 @return: returns a string containing all of the firmware information
2061 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002062 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2063 try:
Justin Thaler27197622019-01-23 14:42:11 -06002064 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002065 except(requests.exceptions.Timeout):
2066 return(connectionErrHandler(args.json, "Timeout", None))
2067 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002068
Justin Thaler3d71d402018-07-24 14:35:39 -05002069 #sort the received information
2070 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002071
Justin Thaler3d71d402018-07-24 14:35:39 -05002072 #display the information
2073 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002074
2075
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002076def deleteFWVersion(host, args, session):
2077 """
2078 deletes a firmware version on the BMC
2079
2080 @param host: string, the hostname or IP address of the BMC
2081 @param args: contains additional arguments used by the fwflash sub command
2082 @param session: the active session to use
2083 @param fwID: the unique ID of the fw version to delete
2084 """
2085 fwID = args.versionID
2086
2087 print("Deleting version: "+fwID)
2088 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002089 data = "{\"data\": [] }"
2090
2091 try:
Justin Thaler27197622019-01-23 14:42:11 -06002092 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002093 except(requests.exceptions.Timeout):
2094 return(connectionErrHandler(args.json, "Timeout", None))
2095 if res.status_code == 200:
2096 return ('The firmware version has been deleted')
2097 else:
2098 return ('Unable to delete the specified firmware version')
2099
2100
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002101def restLogging(host, args, session):
2102 """
2103 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002104
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002105 @param host: string, the hostname or IP address of the bmc
2106 @param args: contains additional arguments used by the logging sub command
2107 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002108 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002109 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002110 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002111
2112 if(args.rest_logging == 'on'):
2113 data = '{"data": 1}'
2114 elif(args.rest_logging == 'off'):
2115 data = '{"data": 0}'
2116 else:
2117 return "Invalid logging rest_api command"
2118
2119 try:
Justin Thaler27197622019-01-23 14:42:11 -06002120 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002121 except(requests.exceptions.Timeout):
2122 return(connectionErrHandler(args.json, "Timeout", None))
2123 return res.text
2124
2125
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002126def remoteLogging(host, args, session):
2127 """
2128 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002129
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002130 @param host: string, the hostname or IP address of the bmc
2131 @param args: contains additional arguments used by the logging sub command
2132 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002133 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002134 """
2135
2136 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002137
2138 try:
2139 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002140 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002141 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002142 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2143 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002144 else:
2145 return "Invalid logging remote_logging command"
2146 except(requests.exceptions.Timeout):
2147 return(connectionErrHandler(args.json, "Timeout", None))
2148 return res.text
2149
2150
2151def remoteLoggingConfig(host, args, session):
2152 """
2153 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002154
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002155 @param host: string, the hostname or IP address of the bmc
2156 @param args: contains additional arguments used by the logging sub command
2157 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002158 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002159 """
2160
2161 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002162
2163 try:
Justin Thaler27197622019-01-23 14:42:11 -06002164 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
2165 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002166 except(requests.exceptions.Timeout):
2167 return(connectionErrHandler(args.json, "Timeout", None))
2168 return res.text
2169
Ratan Gupta9166cd22018-10-01 18:09:40 +05302170
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002171def certificateUpdate(host, args, session):
2172 """
2173 Called by certificate management function. update server/client/authority certificates
2174 Example:
2175 certificate update server https -f cert.pem
2176 certificate update authority ldap -f Root-CA.pem
2177 certificate update client ldap -f cert.pem
2178 @param host: string, the hostname or IP address of the bmc
2179 @param args: contains additional arguments used by the certificate update sub command
2180 @param session: the active session to use
2181 """
2182
2183 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002184 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002185 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2186 data = open(args.fileloc, 'rb').read()
2187 print("Updating certificate url=" + url)
2188 try:
2189 resp = session.put(url, headers=httpHeader, data=data, verify=False)
2190 except(requests.exceptions.Timeout):
2191 return(connectionErrHandler(args.json, "Timeout", None))
2192 except(requests.exceptions.ConnectionError) as err:
2193 return connectionErrHandler(args.json, "ConnectionError", err)
2194 if resp.status_code != 200:
2195 print(resp.text)
2196 return "Failed to update the certificate"
2197 else:
2198 print("Update complete.")
2199
2200
2201def certificateDelete(host, args, session):
2202 """
2203 Called by certificate management function to delete certificate
2204 Example:
2205 certificate delete server https
2206 certificate delete authority ldap
2207 certificate delete client ldap
2208 @param host: string, the hostname or IP address of the bmc
2209 @param args: contains additional arguments used by the certificate delete sub command
2210 @param session: the active session to use
2211 """
2212
2213 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002214 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002215 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2216 print("Deleting certificate url=" + url)
2217 try:
2218 resp = session.delete(url, headers=httpHeader)
2219 except(requests.exceptions.Timeout):
2220 return(connectionErrHandler(args.json, "Timeout", None))
2221 except(requests.exceptions.ConnectionError) as err:
2222 return connectionErrHandler(args.json, "ConnectionError", err)
2223 if resp.status_code != 200:
2224 print(resp.text)
2225 return "Failed to delete the certificate"
2226 else:
2227 print("Delete complete.")
2228
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002229
Ratan Gupta9166cd22018-10-01 18:09:40 +05302230def enableLDAP(host, args, session):
2231 """
2232 Called by the ldap function. Configures LDAP.
2233
2234 @param host: string, the hostname or IP address of the bmc
2235 @param args: contains additional arguments used by the ldap subcommand
2236 @param session: the active session to use
2237 @param args.json: boolean, if this flag is set to true, the output will
2238 be provided in json format for programmatic consumption
2239 """
2240
2241 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302242 scope = {
2243 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
2244 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
2245 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
2246 }
2247
2248 serverType = {
2249 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
2250 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
2251 }
2252
2253 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
2254
2255 try:
Justin Thaler27197622019-01-23 14:42:11 -06002256 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302257 except(requests.exceptions.Timeout):
2258 return(connectionErrHandler(args.json, "Timeout", None))
2259 except(requests.exceptions.ConnectionError) as err:
2260 return connectionErrHandler(args.json, "ConnectionError", err)
2261
2262 return res.text
2263
2264
2265def disableLDAP(host, args, session):
2266 """
2267 Called by the ldap function. Deletes the LDAP Configuration.
2268
2269 @param host: string, the hostname or IP address of the bmc
2270 @param args: contains additional arguments used by the ldap subcommand
2271 @param session: the active session to use
2272 @param args.json: boolean, if this flag is set to true, the output
2273 will be provided in json format for programmatic consumption
2274 """
2275
2276 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302277 data = {"data": []}
2278
2279 try:
Justin Thaler27197622019-01-23 14:42:11 -06002280 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302281 except(requests.exceptions.Timeout):
2282 return(connectionErrHandler(args.json, "Timeout", None))
2283 except(requests.exceptions.ConnectionError) as err:
2284 return connectionErrHandler(args.json, "ConnectionError", err)
2285
2286 return res.text
2287
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002288
2289def enableDHCP(host, args, session):
2290
2291 """
2292 Called by the network function. Enables DHCP.
2293
2294 @param host: string, the hostname or IP address of the bmc
2295 @param args: contains additional arguments used by the ldap subcommand
2296 args.json: boolean, if this flag is set to true, the output
2297 will be provided in json format for programmatic consumption
2298 @param session: the active session to use
2299 """
2300
2301 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2302 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002303 data = "{\"data\": 1 }"
2304 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002305 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002306 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002307
2308 except(requests.exceptions.Timeout):
2309 return(connectionErrHandler(args.json, "Timeout", None))
2310 except(requests.exceptions.ConnectionError) as err:
2311 return connectionErrHandler(args.json, "ConnectionError", err)
2312 if res.status_code == 403:
2313 return "The specified Interface"+"("+args.Interface+")"+\
2314 " doesn't exist"
2315
2316 return res.text
2317
2318
2319def disableDHCP(host, args, session):
2320 """
2321 Called by the network function. Disables DHCP.
2322
2323 @param host: string, the hostname or IP address of the bmc
2324 @param args: contains additional arguments used by the ldap subcommand
2325 args.json: boolean, if this flag is set to true, the output
2326 will be provided in json format for programmatic consumption
2327 @param session: the active session to use
2328 """
2329
2330 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2331 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002332 data = "{\"data\": 0 }"
2333 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002334 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002335 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002336 except(requests.exceptions.Timeout):
2337 return(connectionErrHandler(args.json, "Timeout", None))
2338 except(requests.exceptions.ConnectionError) as err:
2339 return connectionErrHandler(args.json, "ConnectionError", err)
2340 if res.status_code == 403:
2341 return "The specified Interface"+"("+args.Interface+")"+\
2342 " doesn't exist"
2343 return res.text
2344
2345
2346def getHostname(host, args, session):
2347
2348 """
2349 Called by the network function. Prints out the Hostname.
2350
2351 @param host: string, the hostname or IP address of the bmc
2352 @param args: contains additional arguments used by the ldap subcommand
2353 args.json: boolean, if this flag is set to true, the output
2354 will be provided in json format for programmatic consumption
2355 @param session: the active session to use
2356 """
2357
2358 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002359
2360 try:
Justin Thaler27197622019-01-23 14:42:11 -06002361 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002362 except(requests.exceptions.Timeout):
2363 return(connectionErrHandler(args.json, "Timeout", None))
2364 except(requests.exceptions.ConnectionError) as err:
2365 return connectionErrHandler(args.json, "ConnectionError", err)
2366
2367 return res.text
2368
2369
2370def setHostname(host, args, session):
2371 """
2372 Called by the network function. Sets the Hostname.
2373
2374 @param host: string, the hostname or IP address of the bmc
2375 @param args: contains additional arguments used by the ldap subcommand
2376 args.json: boolean, if this flag is set to true, the output
2377 will be provided in json format for programmatic consumption
2378 @param session: the active session to use
2379 """
2380
2381 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002382
2383 data = {"data": args.HostName}
2384
2385 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002386 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002387 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002388 except(requests.exceptions.Timeout):
2389 return(connectionErrHandler(args.json, "Timeout", None))
2390 except(requests.exceptions.ConnectionError) as err:
2391 return connectionErrHandler(args.json, "ConnectionError", err)
2392
2393 return res.text
2394
2395
2396def getDomainName(host, args, session):
2397
2398 """
2399 Called by the network function. Prints out the DomainName.
2400
2401 @param host: string, the hostname or IP address of the bmc
2402 @param args: contains additional arguments used by the ldap subcommand
2403 args.json: boolean, if this flag is set to true, the output
2404 will be provided in json format for programmatic consumption
2405 @param session: the active session to use
2406 """
2407
2408 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2409 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002410
2411 try:
Justin Thaler27197622019-01-23 14:42:11 -06002412 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002413 except(requests.exceptions.Timeout):
2414 return(connectionErrHandler(args.json, "Timeout", None))
2415 except(requests.exceptions.ConnectionError) as err:
2416 return connectionErrHandler(args.json, "ConnectionError", err)
2417 if res.status_code == 404:
2418 return "The specified Interface"+"("+args.Interface+")"+\
2419 " doesn't exist"
2420
2421 return res.text
2422
2423
2424def setDomainName(host, args, session):
2425 """
2426 Called by the network function. Sets the DomainName.
2427
2428 @param host: string, the hostname or IP address of the bmc
2429 @param args: contains additional arguments used by the ldap subcommand
2430 args.json: boolean, if this flag is set to true, the output
2431 will be provided in json format for programmatic consumption
2432 @param session: the active session to use
2433 """
2434
2435 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2436 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002437
2438 data = {"data": args.DomainName.split(",")}
2439
2440 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002441 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002442 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002443 except(requests.exceptions.Timeout):
2444 return(connectionErrHandler(args.json, "Timeout", None))
2445 except(requests.exceptions.ConnectionError) as err:
2446 return connectionErrHandler(args.json, "ConnectionError", err)
2447 if res.status_code == 403:
2448 return "The specified Interface"+"("+args.Interface+")"+\
2449 " doesn't exist"
2450
2451 return res.text
2452
2453
2454def getMACAddress(host, args, session):
2455
2456 """
2457 Called by the network function. Prints out the MACAddress.
2458
2459 @param host: string, the hostname or IP address of the bmc
2460 @param args: contains additional arguments used by the ldap subcommand
2461 args.json: boolean, if this flag is set to true, the output
2462 will be provided in json format for programmatic consumption
2463 @param session: the active session to use
2464 """
2465
2466 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2467 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002468
2469 try:
Justin Thaler27197622019-01-23 14:42:11 -06002470 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002471 except(requests.exceptions.Timeout):
2472 return(connectionErrHandler(args.json, "Timeout", None))
2473 except(requests.exceptions.ConnectionError) as err:
2474 return connectionErrHandler(args.json, "ConnectionError", err)
2475 if res.status_code == 404:
2476 return "The specified Interface"+"("+args.Interface+")"+\
2477 " doesn't exist"
2478
2479 return res.text
2480
2481
2482def setMACAddress(host, args, session):
2483 """
2484 Called by the network function. Sets the MACAddress.
2485
2486 @param host: string, the hostname or IP address of the bmc
2487 @param args: contains additional arguments used by the ldap subcommand
2488 args.json: boolean, if this flag is set to true, the output
2489 will be provided in json format for programmatic consumption
2490 @param session: the active session to use
2491 """
2492
2493 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2494 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002495
2496 data = {"data": args.MACAddress}
2497
2498 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002499 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002500 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002501 except(requests.exceptions.Timeout):
2502 return(connectionErrHandler(args.json, "Timeout", None))
2503 except(requests.exceptions.ConnectionError) as err:
2504 return connectionErrHandler(args.json, "ConnectionError", err)
2505 if res.status_code == 403:
2506 return "The specified Interface"+"("+args.Interface+")"+\
2507 " doesn't exist"
2508
2509 return res.text
2510
2511
2512def getDefaultGateway(host, args, session):
2513
2514 """
2515 Called by the network function. Prints out the DefaultGateway.
2516
2517 @param host: string, the hostname or IP address of the bmc
2518 @param args: contains additional arguments used by the ldap subcommand
2519 args.json: boolean, if this flag is set to true, the output
2520 will be provided in json format for programmatic consumption
2521 @param session: the active session to use
2522 """
2523
2524 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002525
2526 try:
Justin Thaler27197622019-01-23 14:42:11 -06002527 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002528 except(requests.exceptions.Timeout):
2529 return(connectionErrHandler(args.json, "Timeout", None))
2530 except(requests.exceptions.ConnectionError) as err:
2531 return connectionErrHandler(args.json, "ConnectionError", err)
2532 if res.status_code == 404:
2533 return "Failed to get Default Gateway info!!"
2534
2535 return res.text
2536
2537
2538def setDefaultGateway(host, args, session):
2539 """
2540 Called by the network function. Sets the DefaultGateway.
2541
2542 @param host: string, the hostname or IP address of the bmc
2543 @param args: contains additional arguments used by the ldap subcommand
2544 args.json: boolean, if this flag is set to true, the output
2545 will be provided in json format for programmatic consumption
2546 @param session: the active session to use
2547 """
2548
2549 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002550
2551 data = {"data": args.DefaultGW}
2552
2553 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002554 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002555 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002556 except(requests.exceptions.Timeout):
2557 return(connectionErrHandler(args.json, "Timeout", None))
2558 except(requests.exceptions.ConnectionError) as err:
2559 return connectionErrHandler(args.json, "ConnectionError", err)
2560 if res.status_code == 403:
2561 return "Failed to set Default Gateway!!"
2562
2563 return res.text
2564
2565
2566def viewNWConfig(host, args, session):
2567 """
2568 Called by the ldap function. Prints out network configured properties
2569
2570 @param host: string, the hostname or IP address of the bmc
2571 @param args: contains additional arguments used by the ldap subcommand
2572 args.json: boolean, if this flag is set to true, the output
2573 will be provided in json format for programmatic consumption
2574 @param session: the active session to use
2575 @return returns LDAP's configured properties.
2576 """
2577 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002578 try:
Justin Thaler27197622019-01-23 14:42:11 -06002579 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002580 except(requests.exceptions.Timeout):
2581 return(connectionErrHandler(args.json, "Timeout", None))
2582 except(requests.exceptions.ConnectionError) as err:
2583 return connectionErrHandler(args.json, "ConnectionError", err)
2584 except(requests.exceptions.RequestException) as err:
2585 return connectionErrHandler(args.json, "RequestException", err)
2586 if res.status_code == 404:
2587 return "LDAP server config has not been created"
2588 return res.text
2589
2590
2591def getDNS(host, args, session):
2592
2593 """
2594 Called by the network function. Prints out DNS servers on the interface
2595
2596 @param host: string, the hostname or IP address of the bmc
2597 @param args: contains additional arguments used by the ldap subcommand
2598 args.json: boolean, if this flag is set to true, the output
2599 will be provided in json format for programmatic consumption
2600 @param session: the active session to use
2601 """
2602
2603 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2604 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002605
2606 try:
Justin Thaler27197622019-01-23 14:42:11 -06002607 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002608 except(requests.exceptions.Timeout):
2609 return(connectionErrHandler(args.json, "Timeout", None))
2610 except(requests.exceptions.ConnectionError) as err:
2611 return connectionErrHandler(args.json, "ConnectionError", err)
2612 if res.status_code == 404:
2613 return "The specified Interface"+"("+args.Interface+")" + \
2614 " doesn't exist"
2615
2616 return res.text
2617
2618
2619def setDNS(host, args, session):
2620 """
2621 Called by the network function. Sets DNS servers on the interface.
2622
2623 @param host: string, the hostname or IP address of the bmc
2624 @param args: contains additional arguments used by the ldap subcommand
2625 args.json: boolean, if this flag is set to true, the output
2626 will be provided in json format for programmatic consumption
2627 @param session: the active session to use
2628 """
2629
2630 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2631 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002632
2633 data = {"data": args.DNSServers.split(",")}
2634
2635 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002636 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002637 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002638 except(requests.exceptions.Timeout):
2639 return(connectionErrHandler(args.json, "Timeout", None))
2640 except(requests.exceptions.ConnectionError) as err:
2641 return connectionErrHandler(args.json, "ConnectionError", err)
2642 if res.status_code == 403:
2643 return "The specified Interface"+"("+args.Interface+")" +\
2644 " doesn't exist"
2645
2646 return res.text
2647
2648
2649def getNTP(host, args, session):
2650
2651 """
2652 Called by the network function. Prints out NTP servers on the interface
2653
2654 @param host: string, the hostname or IP address of the bmc
2655 @param args: contains additional arguments used by the ldap subcommand
2656 args.json: boolean, if this flag is set to true, the output
2657 will be provided in json format for programmatic consumption
2658 @param session: the active session to use
2659 """
2660
2661 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2662 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002663
2664 try:
Justin Thaler27197622019-01-23 14:42:11 -06002665 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002666 except(requests.exceptions.Timeout):
2667 return(connectionErrHandler(args.json, "Timeout", None))
2668 except(requests.exceptions.ConnectionError) as err:
2669 return connectionErrHandler(args.json, "ConnectionError", err)
2670 if res.status_code == 404:
2671 return "The specified Interface"+"("+args.Interface+")" + \
2672 " doesn't exist"
2673
2674 return res.text
2675
2676
2677def setNTP(host, args, session):
2678 """
2679 Called by the network function. Sets NTP servers on the interface.
2680
2681 @param host: string, the hostname or IP address of the bmc
2682 @param args: contains additional arguments used by the ldap subcommand
2683 args.json: boolean, if this flag is set to true, the output
2684 will be provided in json format for programmatic consumption
2685 @param session: the active session to use
2686 """
2687
2688 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2689 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002690
2691 data = {"data": args.NTPServers.split(",")}
2692
2693 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002694 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002695 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002696 except(requests.exceptions.Timeout):
2697 return(connectionErrHandler(args.json, "Timeout", None))
2698 except(requests.exceptions.ConnectionError) as err:
2699 return connectionErrHandler(args.json, "ConnectionError", err)
2700 if res.status_code == 403:
2701 return "The specified Interface"+"("+args.Interface+")" +\
2702 " doesn't exist"
2703
2704 return res.text
2705
2706
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002707def addIP(host, args, session):
2708 """
2709 Called by the network function. Configures IP address on given interface
2710
2711 @param host: string, the hostname or IP address of the bmc
2712 @param args: contains additional arguments used by the ldap subcommand
2713 args.json: boolean, if this flag is set to true, the output
2714 will be provided in json format for programmatic consumption
2715 @param session: the active session to use
2716 """
2717
2718 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2719 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002720 protocol = {
2721 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
2722 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
2723 }
2724
2725 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
2726 args.gateway]}
2727
2728 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002729 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002730 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002731 except(requests.exceptions.Timeout):
2732 return(connectionErrHandler(args.json, "Timeout", None))
2733 except(requests.exceptions.ConnectionError) as err:
2734 return connectionErrHandler(args.json, "ConnectionError", err)
2735 if res.status_code == 404:
2736 return "The specified Interface" + "(" + args.Interface + ")" +\
2737 " doesn't exist"
2738
2739 return res.text
2740
2741
2742def getIP(host, args, session):
2743 """
2744 Called by the network function. Prints out IP address of given interface
2745
2746 @param host: string, the hostname or IP address of the bmc
2747 @param args: contains additional arguments used by the ldap subcommand
2748 args.json: boolean, if this flag is set to true, the output
2749 will be provided in json format for programmatic consumption
2750 @param session: the active session to use
2751 """
2752
2753 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
2754 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002755 try:
Justin Thaler27197622019-01-23 14:42:11 -06002756 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002757 except(requests.exceptions.Timeout):
2758 return(connectionErrHandler(args.json, "Timeout", None))
2759 except(requests.exceptions.ConnectionError) as err:
2760 return connectionErrHandler(args.json, "ConnectionError", err)
2761 if res.status_code == 404:
2762 return "The specified Interface" + "(" + args.Interface + ")" +\
2763 " doesn't exist"
2764
2765 return res.text
2766
2767
2768def deleteIP(host, args, session):
2769 """
2770 Called by the network function. Deletes the IP address from given Interface
2771
2772 @param host: string, the hostname or IP address of the bmc
2773 @param args: contains additional arguments used by the ldap subcommand
2774 @param session: the active session to use
2775 @param args.json: boolean, if this flag is set to true, the output
2776 will be provided in json format for programmatic consumption
2777 """
2778
2779 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
2780 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002781 data = {"data": []}
2782 try:
Justin Thaler27197622019-01-23 14:42:11 -06002783 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002784 except(requests.exceptions.Timeout):
2785 return(connectionErrHandler(args.json, "Timeout", None))
2786 except(requests.exceptions.ConnectionError) as err:
2787 return connectionErrHandler(args.json, "ConnectionError", err)
2788 if res.status_code == 404:
2789 return "The specified Interface" + "(" + args.Interface + ")" +\
2790 " doesn't exist"
2791 objDict = json.loads(res.text)
2792 if not objDict['data']:
2793 return "No object found for given address on given Interface"
2794
2795 for obj in objDict['data']:
2796 if args.address in objDict['data'][obj]['Address']:
2797 url = "https://"+host+obj+"/action/delete"
2798 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002799 res = session.post(url, headers=jsonHeader, json=data,
Justin Thaler27197622019-01-23 14:42:11 -06002800 verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002801 except(requests.exceptions.Timeout):
2802 return(connectionErrHandler(args.json, "Timeout", None))
2803 except(requests.exceptions.ConnectionError) as err:
2804 return connectionErrHandler(args.json, "ConnectionError", err)
2805 return res.text
2806 else:
2807 continue
2808 return "No object found for given address on given Interface"
2809
2810
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002811def addVLAN(host, args, session):
2812 """
2813 Called by the network function. Creates VLAN on given interface.
2814
2815 @param host: string, the hostname or IP address of the bmc
2816 @param args: contains additional arguments used by the ldap subcommand
2817 args.json: boolean, if this flag is set to true, the output
2818 will be provided in json format for programmatic consumption
2819 @param session: the active session to use
2820 """
2821
2822 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002823
2824 data = {"data": [args.Interface,args.Identifier]}
2825
2826 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002827 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002828 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002829 except(requests.exceptions.Timeout):
2830 return(connectionErrHandler(args.json, "Timeout", None))
2831 except(requests.exceptions.ConnectionError) as err:
2832 return connectionErrHandler(args.json, "ConnectionError", err)
2833 if res.status_code == 400:
2834 return "The specified Interface" + "(" + args.Interface + ")" +\
2835 " doesn't exist"
2836
2837 return res.text
2838
2839
2840def deleteVLAN(host, args, session):
2841 """
2842 Called by the network function. Creates VLAN on given interface.
2843
2844 @param host: string, the hostname or IP address of the bmc
2845 @param args: contains additional arguments used by the ldap subcommand
2846 args.json: boolean, if this flag is set to true, the output
2847 will be provided in json format for programmatic consumption
2848 @param session: the active session to use
2849 """
2850
2851 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002852 data = {"data": []}
2853
2854 try:
Justin Thaler27197622019-01-23 14:42:11 -06002855 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002856 except(requests.exceptions.Timeout):
2857 return(connectionErrHandler(args.json, "Timeout", None))
2858 except(requests.exceptions.ConnectionError) as err:
2859 return connectionErrHandler(args.json, "ConnectionError", err)
2860 if res.status_code == 404:
2861 return "The specified VLAN"+"("+args.Interface+"_"+args.Identifier\
2862 +")" +" doesn't exist"
2863
2864 return res.text
2865
2866
2867def viewDHCPConfig(host, args, session):
2868 """
2869 Called by the network function. Shows DHCP configured Properties.
2870
2871 @param host: string, the hostname or IP address of the bmc
2872 @param args: contains additional arguments used by the ldap subcommand
2873 args.json: boolean, if this flag is set to true, the output
2874 will be provided in json format for programmatic consumption
2875 @param session: the active session to use
2876 """
2877
2878 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002879
2880 try:
Justin Thaler27197622019-01-23 14:42:11 -06002881 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002882 except(requests.exceptions.Timeout):
2883 return(connectionErrHandler(args.json, "Timeout", None))
2884 except(requests.exceptions.ConnectionError) as err:
2885 return connectionErrHandler(args.json, "ConnectionError", err)
2886
2887 return res.text
2888
2889
2890def configureDHCP(host, args, session):
2891 """
2892 Called by the network function. Configures/updates DHCP Properties.
2893
2894 @param host: string, the hostname or IP address of the bmc
2895 @param args: contains additional arguments used by the ldap subcommand
2896 args.json: boolean, if this flag is set to true, the output
2897 will be provided in json format for programmatic consumption
2898 @param session: the active session to use
2899 """
2900
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002901
2902 try:
2903 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
2904 if(args.DNSEnabled == True):
2905 data = '{"data": 1}'
2906 else:
2907 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002908 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06002909 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002910 if(args.HostNameEnabled == True):
2911 data = '{"data": 1}'
2912 else:
2913 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002914 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06002915 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002916 if(args.NTPEnabled == True):
2917 data = '{"data": 1}'
2918 else:
2919 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002920 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06002921 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002922 if(args.SendHostNameEnabled == True):
2923 data = '{"data": 1}'
2924 else:
2925 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002926 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06002927 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002928 except(requests.exceptions.Timeout):
2929 return(connectionErrHandler(args.json, "Timeout", None))
2930 except(requests.exceptions.ConnectionError) as err:
2931 return connectionErrHandler(args.json, "ConnectionError", err)
2932
2933 return res.text
2934
2935
2936def nwReset(host, args, session):
2937
2938 """
2939 Called by the network function. Resets networks setting to factory defaults.
2940
2941 @param host: string, the hostname or IP address of the bmc
2942 @param args: contains additional arguments used by the ldap subcommand
2943 args.json: boolean, if this flag is set to true, the output
2944 will be provided in json format for programmatic consumption
2945 @param session: the active session to use
2946 """
2947
2948 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002949 data = '{"data":[] }'
2950 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002951 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002952 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002953
2954 except(requests.exceptions.Timeout):
2955 return(connectionErrHandler(args.json, "Timeout", None))
2956 except(requests.exceptions.ConnectionError) as err:
2957 return connectionErrHandler(args.json, "ConnectionError", err)
2958
2959 return res.text
2960
2961
Ratan Guptafeee6372018-10-17 23:25:51 +05302962def createPrivilegeMapping(host, args, session):
2963 """
2964 Called by the ldap function. Creates the group and the privilege mapping.
2965
2966 @param host: string, the hostname or IP address of the bmc
2967 @param args: contains additional arguments used by the ldap subcommand
2968 @param session: the active session to use
2969 @param args.json: boolean, if this flag is set to true, the output
2970 will be provided in json format for programmatic consumption
2971 """
2972
2973 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
Ratan Guptafeee6372018-10-17 23:25:51 +05302974
2975 data = {"data": [args.groupName,args.privilege]}
2976
2977 try:
Justin Thaler27197622019-01-23 14:42:11 -06002978 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05302979 except(requests.exceptions.Timeout):
2980 return(connectionErrHandler(args.json, "Timeout", None))
2981 except(requests.exceptions.ConnectionError) as err:
2982 return connectionErrHandler(args.json, "ConnectionError", err)
2983 return res.text
2984
2985def listPrivilegeMapping(host, args, session):
2986 """
2987 Called by the ldap function. Lists the group and the privilege mapping.
2988
2989 @param host: string, the hostname or IP address of the bmc
2990 @param args: contains additional arguments used by the ldap subcommand
2991 @param session: the active session to use
2992 @param args.json: boolean, if this flag is set to true, the output
2993 will be provided in json format for programmatic consumption
2994 """
2995 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
Ratan Guptafeee6372018-10-17 23:25:51 +05302996 data = {"data": []}
2997
2998 try:
Justin Thaler27197622019-01-23 14:42:11 -06002999 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05303000 except(requests.exceptions.Timeout):
3001 return(connectionErrHandler(args.json, "Timeout", None))
3002 except(requests.exceptions.ConnectionError) as err:
3003 return connectionErrHandler(args.json, "ConnectionError", err)
3004 return res.text
3005
3006def deletePrivilegeMapping(host, args, session):
3007 """
3008 Called by the ldap function. Deletes the mapping associated with the group.
3009
3010 @param host: string, the hostname or IP address of the bmc
3011 @param args: contains additional arguments used by the ldap subcommand
3012 @param session: the active session to use
3013 @param args.json: boolean, if this flag is set to true, the output
3014 will be provided in json format for programmatic consumption
3015 """
3016 (ldapNameSpaceObjects) = listPrivilegeMapping(host, args, session)
3017 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3018 path = ''
3019
3020 # not interested in the config objet
3021 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
3022
3023 # search for the object having the mapping for the given group
3024 for key,value in ldapNameSpaceObjects.items():
3025 if value['GroupName'] == args.groupName:
3026 path = key
3027 break
3028
3029 if path == '':
3030 return "No privilege mapping found for this group."
3031
3032 # delete the object
3033 url = 'https://'+host+path+'/action/delete'
Ratan Guptafeee6372018-10-17 23:25:51 +05303034 data = {"data": []}
3035
3036 try:
Justin Thaler27197622019-01-23 14:42:11 -06003037 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05303038 except(requests.exceptions.Timeout):
3039 return(connectionErrHandler(args.json, "Timeout", None))
3040 except(requests.exceptions.ConnectionError) as err:
3041 return connectionErrHandler(args.json, "ConnectionError", err)
3042 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303043
Sivas SRR78835272018-11-27 05:27:19 -06003044def deleteAllPrivilegeMapping(host, args, session):
3045 """
3046 Called by the ldap function. Deletes all the privilege mapping and group defined.
3047 @param host: string, the hostname or IP address of the bmc
3048 @param args: contains additional arguments used by the ldap subcommand
3049 @param session: the active session to use
3050 @param args.json: boolean, if this flag is set to true, the output
3051 will be provided in json format for programmatic consumption
3052 """
3053 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
3054 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3055 path = ''
3056
3057 # Remove the config object.
3058 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
Sivas SRR78835272018-11-27 05:27:19 -06003059 data = {"data": []}
3060
3061 try:
3062 # search for GroupName property and delete if it is available.
3063 for path in ldapNameSpaceObjects.keys():
3064 # delete the object
3065 url = 'https://'+host+path+'/action/delete'
Justin Thaler27197622019-01-23 14:42:11 -06003066 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Sivas SRR78835272018-11-27 05:27:19 -06003067 except(requests.exceptions.Timeout):
3068 return(connectionErrHandler(args.json, "Timeout", None))
3069 except(requests.exceptions.ConnectionError) as err:
3070 return connectionErrHandler(args.json, "ConnectionError", err)
3071 return res.text
3072
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003073def viewLDAPConfig(host, args, session):
3074 """
3075 Called by the ldap function. Prints out LDAP's configured properties
3076
3077 @param host: string, the hostname or IP address of the bmc
3078 @param args: contains additional arguments used by the ldap subcommand
3079 args.json: boolean, if this flag is set to true, the output
3080 will be provided in json format for programmatic consumption
3081 @param session: the active session to use
3082 @return returns LDAP's configured properties.
3083 """
3084 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003085 try:
Justin Thaler27197622019-01-23 14:42:11 -06003086 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003087 except(requests.exceptions.Timeout):
3088 return(connectionErrHandler(args.json, "Timeout", None))
3089 except(requests.exceptions.ConnectionError) as err:
3090 return connectionErrHandler(args.json, "ConnectionError", err)
3091 except(requests.exceptions.RequestException) as err:
3092 return connectionErrHandler(args.json, "RequestException", err)
3093 if res.status_code == 404:
3094 return "LDAP server config has not been created"
3095 return res.text
3096
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003097def str2bool(v):
3098 if v.lower() in ('yes', 'true', 't', 'y', '1'):
3099 return True
3100 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
3101 return False
3102 else:
3103 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003104
Matt Spinler7d426c22018-09-24 14:42:07 -05003105def localUsers(host, args, session):
3106 """
3107 Enables and disables local BMC users.
3108
3109 @param host: string, the hostname or IP address of the bmc
3110 @param args: contains additional arguments used by the logging sub command
3111 @param session: the active session to use
3112 """
3113
Matt Spinler7d426c22018-09-24 14:42:07 -05003114 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
3115 try:
Justin Thaler27197622019-01-23 14:42:11 -06003116 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003117 except(requests.exceptions.Timeout):
3118 return(connectionErrHandler(args.json, "Timeout", None))
3119 usersDict = json.loads(res.text)
3120
3121 if not usersDict['data']:
3122 return "No users found"
3123
3124 output = ""
3125 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05003126
3127 # Skip LDAP and another non-local users
3128 if 'UserEnabled' not in usersDict['data'][user]:
3129 continue
3130
Matt Spinler7d426c22018-09-24 14:42:07 -05003131 name = user.split('/')[-1]
3132 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
3133
3134 if args.local_users == "queryenabled":
3135 try:
Justin Thaler27197622019-01-23 14:42:11 -06003136 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003137 except(requests.exceptions.Timeout):
3138 return(connectionErrHandler(args.json, "Timeout", None))
3139
3140 result = json.loads(res.text)
3141 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
3142
3143 elif args.local_users in ["enableall", "disableall"]:
3144 action = ""
3145 if args.local_users == "enableall":
3146 data = '{"data": true}'
3147 action = "Enabling"
3148 else:
3149 data = '{"data": false}'
3150 action = "Disabling"
3151
3152 output += "{action} {name}\n".format(action=action, name=name)
3153
3154 try:
Justin Thaler27197622019-01-23 14:42:11 -06003155 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003156 except(requests.exceptions.Timeout):
3157 return connectionErrHandler(args.json, "Timeout", None)
3158 except(requests.exceptions.ConnectionError) as err:
3159 return connectionErrHandler(args.json, "ConnectionError", err)
3160 else:
3161 return "Invalid local users argument"
3162
3163 return output
3164
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003165def setPassword(host, args, session):
3166 """
3167 Set local user password
3168 @param host: string, the hostname or IP address of the bmc
3169 @param args: contains additional arguments used by the logging sub
3170 command
3171 @param session: the active session to use
3172 @param args.json: boolean, if this flag is set to true, the output
3173 will be provided in json format for programmatic consumption
3174 @return: Session object
3175 """
3176 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
3177 "/action/SetPassword"
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003178 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003179 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003180 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003181 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003182 except(requests.exceptions.Timeout):
3183 return(connectionErrHandler(args.json, "Timeout", None))
3184 except(requests.exceptions.ConnectionError) as err:
3185 return connectionErrHandler(args.json, "ConnectionError", err)
3186 except(requests.exceptions.RequestException) as err:
3187 return connectionErrHandler(args.json, "RequestException", err)
3188 return res.text
3189
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003190def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06003191 """
3192 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003193
Justin Thalere412dc22018-01-12 16:28:24 -06003194 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003195 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003196 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06003197 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
3198 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003199 group = parser.add_mutually_exclusive_group()
3200 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
3201 group.add_argument("-P", "--PW", help='Provide the password in-line')
3202 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
3203 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
3204 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
3205 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06003206 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
3207 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003208
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003209 #fru command
3210 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06003211 inv_subparser = parser_inv.add_subparsers(title='subcommands', description='valid inventory actions', help="valid inventory actions", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003212 inv_subparser.required = True
3213 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003214 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
3215 inv_print.set_defaults(func=fruPrint)
3216 #fru list [0....n]
3217 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3218 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3219 inv_list.set_defaults(func=fruList)
3220 #fru status
3221 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06003222 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003223 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003224
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003225 #sensors command
3226 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06003227 sens_subparser=parser_sens.add_subparsers(title='subcommands', description='valid sensor actions', help='valid sensor actions', dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003228 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003229 #sensor print
3230 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
3231 sens_print.set_defaults(func=sensor)
3232 #sensor list[0...n]
3233 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
3234 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
3235 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003236
3237
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003238 #sel command
3239 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06003240 sel_subparser = parser_sel.add_subparsers(title='subcommands', description='valid SEL actions', help = 'valid SEL actions', dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003241 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003242 #sel print
3243 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
3244 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3245 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
3246 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
3247 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003248
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003249 #sel list
3250 sel_list = sel_subparser.add_parser("list", help="Lists all SELs in the platform. Specifying a specific number will pull all the details for that individual SEL")
3251 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
3252 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003253
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003254 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
3255 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
3256 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003257
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003258 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
3259 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003260
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003261 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06003262 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
3263 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
3264 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
3265 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003266 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003267
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003268 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06003269 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003270
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003271 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
3272 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003273
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003274 parser_chasPower = chas_sub.add_parser("power", help="Turn the chassis on or off, check the power state")
Justin Thalere412dc22018-01-12 16:28:24 -06003275 parser_chasPower.add_argument('powcmd', choices=['on','softoff', 'hardoff', 'status'], help='The value for the power command. on, off, or status')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003276 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003277
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003278 #control the chassis identify led
3279 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
3280 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
3281 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003282
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003283 #collect service data
3284 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
3285 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3286 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003287
Justin Thalere412dc22018-01-12 16:28:24 -06003288 #system quick health check
3289 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
3290 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003291
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003292 #work with bmc dumps
3293 parser_bmcdump = subparsers.add_parser("dump", help="Work with bmc dump files")
Justin Thalere412dc22018-01-12 16:28:24 -06003294 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003295 bmcDump_sub.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003296 dump_Create = bmcDump_sub.add_parser('create', help="Create a bmc dump")
3297 dump_Create.set_defaults(func=bmcDumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003298
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003299 dump_list = bmcDump_sub.add_parser('list', help="list all bmc dump files")
3300 dump_list.set_defaults(func=bmcDumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003301
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003302 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete bmc dump files")
3303 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003304 parserdumpdelete.set_defaults(func=bmcDumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003305
Justin Thalere412dc22018-01-12 16:28:24 -06003306 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003307 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all bmc dump files')
3308 deleteAllDumps.set_defaults(func=bmcDumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003309
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003310 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
3311 parser_dumpretrieve.add_argument("dumpNum", type=int, help="The Dump entry to delete")
3312 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file")
3313 parser_dumpretrieve.set_defaults(func=bmcDumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003314
Justin Thaler22b1bb52018-03-15 13:31:32 -05003315 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003316 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06003317 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003318 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
3319 parser_BMCReset.add_argument('type', choices=['warm','cold'], help="Warm: Reboot the BMC, Cold: CLEAR config and reboot bmc")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003320 parser_bmc.add_argument('info', action='store_true', help="Displays information about the BMC hardware, including device revision, firmware revision, IPMI version supported, manufacturer ID, and information on additional device support.")
3321 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003322
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003323 #add alias to the bmc command
3324 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06003325 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003326 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
3327 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
3328 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
3329 parser_mc.add_argument('info', action='store_true', help="Displays information about the BMC hardware, including device revision, firmware revision, IPMI version supported, manufacturer ID, and information on additional device support.")
Justin Thalere412dc22018-01-12 16:28:24 -06003330 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003331 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003332
Justin Thalere412dc22018-01-12 16:28:24 -06003333 #gard clear
3334 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
3335 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003336
Justin Thalere412dc22018-01-12 16:28:24 -06003337 #firmware_flash
3338 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
3339 fwflash_subproc = parser_fw.add_subparsers(title='subcommands', description='valid firmware commands', help='sub-command help', dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003340 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003341
Justin Thalere412dc22018-01-12 16:28:24 -06003342 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
3343 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
3344 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
3345 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003346
Justin Thaler22b1bb52018-03-15 13:31:32 -05003347 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06003348 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
3349 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003350
Justin Thaler22b1bb52018-03-15 13:31:32 -05003351 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
3352 fwActivateStatus.set_defaults(func=activateStatus)
3353
Justin Thaler3d71d402018-07-24 14:35:39 -05003354 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
3355 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3356 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003357
Justin Thaler3d71d402018-07-24 14:35:39 -05003358 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
3359 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3360 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003361
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06003362 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
3363 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
3364 fwDelete.set_defaults(func=deleteFWVersion)
3365
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003366 #logging
3367 parser_logging = subparsers.add_parser("logging", help="logging controls")
3368 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003369
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003370 #turn rest api logging on/off
3371 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
3372 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
3373 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003374
3375 #remote logging
3376 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
3377 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
3378 parser_remote_logging.set_defaults(func=remoteLogging)
3379
3380 #configure remote logging
3381 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
3382 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
3383 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
3384 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003385
3386 #certificate management
3387 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
3388 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
3389
3390 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
3391 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
3392 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
3393 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
3394 certUpdate.set_defaults(func=certificateUpdate)
3395
3396 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
3397 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
3398 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
3399 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003400
Matt Spinler7d426c22018-09-24 14:42:07 -05003401 # local users
3402 parser_users = subparsers.add_parser("local_users", help="Work with local users")
3403 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
3404 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3405 parser_users.set_defaults(func=localUsers)
3406
Ratan Gupta9166cd22018-10-01 18:09:40 +05303407 #LDAP
3408 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
3409 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
3410
3411 #configure and enable LDAP
3412 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
3413 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
3414 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
3415 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
3416 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
3417 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
3418 help='Specifies the search scope:subtree, one level or base object.')
3419 parser_ldap_config.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
3420 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
3421 parser_ldap_config.set_defaults(func=enableLDAP)
3422
3423 # disable LDAP
3424 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
3425 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003426 # view-config
3427 parser_ldap_config = \
3428 ldap_sub.add_parser("view-config", help="prints out a list of all \
3429 LDAPS's configured properties")
3430 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303431
Ratan Guptafeee6372018-10-17 23:25:51 +05303432 #create group privilege mapping
3433 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
3434 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
3435 help="sub-command help", dest='command')
3436
3437 parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
3438 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
3439 parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-user'],required=True,help="Privilege")
3440 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
3441
3442 #list group privilege mapping
3443 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
3444 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
3445
3446 #delete group privilege mapping
3447 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
3448 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
3449 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
3450
Sivas SRR78835272018-11-27 05:27:19 -06003451 #deleteAll group privilege mapping
3452 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
3453 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
3454
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003455 # set local user password
3456 parser_set_password = subparsers.add_parser("set_password",
3457 help="Set password of local user")
3458 parser_set_password.add_argument( "-p", "--password", required=True,
3459 help="Password of local user")
3460 parser_set_password.set_defaults(func=setPassword)
3461
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003462 # network
3463 parser_nw = subparsers.add_parser("network", help="network controls")
3464 nw_sub = parser_nw.add_subparsers(title='subcommands',
3465 description='valid subcommands',
3466 help="sub-command help",
3467 dest='command')
3468
3469 # enable DHCP
3470 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
3471 help="enables the DHCP on given "
3472 "Interface")
3473 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003474 help="Name of the ethernet interface(it can"
3475 "be obtained by the "
3476 "command:network view-config)"
3477 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003478 parser_enable_dhcp.set_defaults(func=enableDHCP)
3479
3480 # disable DHCP
3481 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
3482 help="disables the DHCP on given "
3483 "Interface")
3484 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003485 help="Name of the ethernet interface(it can"
3486 "be obtained by the "
3487 "command:network view-config)"
3488 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003489 parser_disable_dhcp.set_defaults(func=disableDHCP)
3490
3491 # get HostName
3492 parser_gethostname = nw_sub.add_parser("getHostName",
3493 help="prints out HostName")
3494 parser_gethostname.set_defaults(func=getHostname)
3495
3496 # set HostName
3497 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
3498 parser_sethostname.add_argument("-H", "--HostName", required=True,
3499 help="A HostName for the BMC")
3500 parser_sethostname.set_defaults(func=setHostname)
3501
3502 # get domainname
3503 parser_getdomainname = nw_sub.add_parser("getDomainName",
3504 help="prints out DomainName of "
3505 "given Interface")
3506 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003507 help="Name of the ethernet interface(it "
3508 "can be obtained by the "
3509 "command:network view-config)"
3510 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003511 parser_getdomainname.set_defaults(func=getDomainName)
3512
3513 # set domainname
3514 parser_setdomainname = nw_sub.add_parser("setDomainName",
3515 help="sets DomainName of given "
3516 "Interface")
3517 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
3518 help="Ex: DomainName=Domain1,Domain2,...")
3519 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003520 help="Name of the ethernet interface(it "
3521 "can be obtained by the "
3522 "command:network view-config)"
3523 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003524 parser_setdomainname.set_defaults(func=setDomainName)
3525
3526 # get MACAddress
3527 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
3528 help="prints out MACAddress the "
3529 "given Interface")
3530 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003531 help="Name of the ethernet interface(it "
3532 "can be obtained by the "
3533 "command:network view-config)"
3534 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003535 parser_getmacaddress.set_defaults(func=getMACAddress)
3536
3537 # set MACAddress
3538 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
3539 help="sets MACAddress")
3540 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
3541 help="A MACAddress for the given "
3542 "Interface")
3543 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003544 help="Name of the ethernet interface(it can"
3545 "be obtained by the "
3546 "command:network view-config)"
3547 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003548 parser_setmacaddress.set_defaults(func=setMACAddress)
3549
3550 # get DefaultGW
3551 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
3552 help="prints out DefaultGateway "
3553 "the BMC")
3554 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
3555
3556 # set DefaultGW
3557 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
3558 help="sets DefaultGW")
3559 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
3560 help="A DefaultGateway for the BMC")
3561 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
3562
3563 # view network Config
3564 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
3565 "list of all network's configured "
3566 "properties")
3567 parser_ldap_config.set_defaults(func=viewNWConfig)
3568
3569 # get DNS
3570 parser_getDNS = nw_sub.add_parser("getDNS",
3571 help="prints out DNS servers on the "
3572 "given interface")
3573 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003574 help="Name of the ethernet interface(it can"
3575 "be obtained by the "
3576 "command:network view-config)"
3577 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003578 parser_getDNS.set_defaults(func=getDNS)
3579
3580 # set DNS
3581 parser_setDNS = nw_sub.add_parser("setDNS",
3582 help="sets DNS servers on the given "
3583 "interface")
3584 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
3585 help="Ex: DNSSERVERS=DNS1,DNS2,...")
3586 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003587 help="Name of the ethernet interface(it can"
3588 "be obtained by the "
3589 "command:network view-config)"
3590 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003591 parser_setDNS.set_defaults(func=setDNS)
3592
3593 # get NTP
3594 parser_getNTP = nw_sub.add_parser("getNTP",
3595 help="prints out NTP servers on the "
3596 "given interface")
3597 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003598 help="Name of the ethernet interface(it can"
3599 "be obtained by the "
3600 "command:network view-config)"
3601 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003602 parser_getNTP.set_defaults(func=getNTP)
3603
3604 # set NTP
3605 parser_setNTP = nw_sub.add_parser("setNTP",
3606 help="sets NTP servers on the given "
3607 "interface")
3608 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
3609 help="Ex: NTPSERVERS=NTP1,NTP2,...")
3610 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003611 help="Name of the ethernet interface(it can"
3612 "be obtained by the "
3613 "command:network view-config)"
3614 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003615 parser_setNTP.set_defaults(func=setNTP)
3616
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003617 # configure IP
3618 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
3619 "given interface")
3620 parser_ip_config.add_argument("-a", "--address", required=True,
3621 help="IP address of given interface")
3622 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
3623 help="The gateway for given interface")
3624 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
3625 help="The prefixLength of IP address")
3626 parser_ip_config.add_argument("-p", "--type", choices=['ipv4', 'ipv6'],
3627 help="The protocol type of the given"
3628 "IP address")
3629 parser_ip_config.add_argument("-I", "--Interface", required=True,
3630 help="Name of the ethernet interface(it can"
3631 "be obtained by the "
3632 "command:network view-config)"
3633 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3634 parser_ip_config.set_defaults(func=addIP)
3635
3636 # getIP
3637 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
3638 "of given interface")
3639 parser_getIP.add_argument("-I", "--Interface", required=True,
3640 help="Name of the ethernet interface(it can"
3641 "be obtained by the command:network view-config)"
3642 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3643 parser_getIP.set_defaults(func=getIP)
3644
3645 # rmIP
3646 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
3647 "of given interface")
3648 parser_rmIP.add_argument("-a", "--address", required=True,
3649 help="IP address to remove form given Interface")
3650 parser_rmIP.add_argument("-I", "--Interface", required=True,
3651 help="Name of the ethernet interface(it can"
3652 "be obtained by the command:network view-config)"
3653 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3654 parser_rmIP.set_defaults(func=deleteIP)
3655
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003656 # add VLAN
3657 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
3658 "on given interface with given "
3659 "VLAN Identifier")
3660 parser_create_vlan.add_argument("-I", "--Interface", required=True,
3661 choices=['eth0', 'eth1'],
3662 help="Name of the ethernet interface")
3663 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
3664 help="VLAN Identifier")
3665 parser_create_vlan.set_defaults(func=addVLAN)
3666
3667 # delete VLAN
3668 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
3669 "on given interface with given "
3670 "VLAN Identifier")
3671 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
3672 help="Name of the ethernet interface(it can"
3673 "be obtained by the "
3674 "command:network view-config)"
3675 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3676 parser_delete_vlan.set_defaults(func=deleteVLAN)
3677
3678 # viewDHCPConfig
3679 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
3680 help="Shows DHCP configured "
3681 "Properties")
3682 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
3683
3684 # configureDHCP
3685 parser_configDHCP = nw_sub.add_parser("configureDHCP",
3686 help="Configures/updates DHCP "
3687 "Properties")
3688 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
3689 required=True, help="Sets DNSEnabled property")
3690 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
3691 required=True,
3692 help="Sets HostNameEnabled property")
3693 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
3694 required=True,
3695 help="Sets NTPEnabled property")
3696 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
3697 required=True,
3698 help="Sets SendHostNameEnabled property")
3699 parser_configDHCP.set_defaults(func=configureDHCP)
3700
3701 # network factory reset
3702 parser_nw_reset = nw_sub.add_parser("nwReset",
3703 help="Resets networks setting to "
3704 "factory defaults. "
3705 "note:Reset settings will be applied "
3706 "after BMC reboot")
3707 parser_nw_reset.set_defaults(func=nwReset)
3708
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003709 return parser
3710
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003711def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06003712 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003713 main function for running the command line utility as a sub application
3714 """
3715 global toolVersion
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06003716 toolVersion = "1.11"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003717 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003718 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003719
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003720 totTimeStart = int(round(time.time()*1000))
3721
3722 if(sys.version_info < (3,0)):
3723 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
3724 if sys.version_info >= (3,0):
3725 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06003726 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05003727 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06003728 sys.exit(0)
3729 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003730 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06003731 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003732 else:
Justin Thalere412dc22018-01-12 16:28:24 -06003733 if(hasattr(args, 'host') and hasattr(args,'user')):
3734 if (args.askpw):
3735 pw = getpass.getpass()
3736 elif(args.PW is not None):
3737 pw = args.PW
3738 else:
3739 print("You must specify a password")
3740 sys.exit()
3741 logintimeStart = int(round(time.time()*1000))
3742 mysess = login(args.host, args.user, pw, args.json)
Justin Thalera9415b42018-05-25 19:40:13 -05003743 if(sys.version_info < (3,0)):
3744 if isinstance(mysess, basestring):
3745 print(mysess)
3746 sys.exit(1)
3747 elif sys.version_info >= (3,0):
3748 if isinstance(mysess, str):
3749 print(mysess)
3750 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06003751 logintimeStop = int(round(time.time()*1000))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003752
3753 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06003754 output = args.func(args.host, args, mysess)
3755 commandTimeStop = int(round(time.time()*1000))
3756 print(output)
3757 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003758 logout(args.host, args.user, pw, mysess, args.json)
3759 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06003760 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
3761 print("loginTime: " + str(logintimeStop - logintimeStart))
3762 print("command Time: " + str(commandTimeStop - commandTimeStart))
3763 else:
3764 print("usage: openbmctool.py [-h] -H HOST -U USER [-A | -P PW] [-j]\n" +
3765 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003766 "\t{fru,sensors,sel,chassis,collect_service_data, \
3767 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06003768 "\t...\n" +
3769 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003770 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003771
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003772if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06003773 """
3774 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003775
3776 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003777 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003778
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003779 isTTY = sys.stdout.isatty()
3780 assert sys.version_info >= (2,7)
3781 main()