blob: 4af8c1c87c7ed89ee8cda20fb5c4c64e2c854114 [file] [log] [blame]
Justin Thalerb8807ce2018-05-25 19:16:20 -05001#!/usr/bin/python3
Justin Thalere412dc22018-01-12 16:28:24 -06002"""
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05003 Copyright 2017,2019 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)
Sunitha Harish336cda22019-07-23 02:02:52 -0500270 if r.status_code == 200:
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)
276 loginMessage = json.loads(r.text)
277 if (loginMessage['status'] != "ok"):
278 print(loginMessage["data"]["description"].encode('utf-8'))
279 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600280# 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)
Sunitha Harish336cda22019-07-23 02:02:52 -0500284 return mysess
285 else:
286 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600287 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500288 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600289 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500290 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600291
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600292
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600293def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600294 """
295 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600296
Justin Thalere412dc22018-01-12 16:28:24 -0600297 @param host: string, the hostname or IP address of the bmc to log out of
298 @param username: The user name for the bmc to log out of
299 @param pw: The password for the BMC to log out of
300 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600301 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
302 """
Justin Thalere412dc22018-01-12 16:28:24 -0600303 try:
Justin Thaler27197622019-01-23 14:42:11 -0600304 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600305 except(requests.exceptions.Timeout):
306 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600307
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600308 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600309 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600310 print('User ' +username + ' has been logged out')
311
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600312
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600313def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600314 """
315 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600316
Justin Thalere412dc22018-01-12 16:28:24 -0600317 @param host: string, the hostname or IP address of the bmc
318 @param args: contains additional arguments used by the fru sub command
319 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600320 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
321 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600322 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600323
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600324 #print(url)
325 #res = session.get(url, headers=httpHeader, verify=False)
326 #print(res.text)
327 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600328
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600329 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600330
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600331 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600332 try:
Justin Thaler27197622019-01-23 14:42:11 -0600333 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600334 except(requests.exceptions.Timeout):
335 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600336
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600337 sample = res.text
338# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600339#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600340# #determine column width's
341# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
342# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600343#
344# 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 -0600345# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
346# format the output
347# for key in sorted(inv_list.keys()):
348# keyParts = key.split("/")
349# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600350#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600351# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
352# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
353# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
354# if(isTTY):
355# if(inv_list[key]["is_fru"] == 1):
356# color = "green"
357# bold = True
358# else:
359# color='black'
360# bold = False
361# fruEntry = hilight(fruEntry, color, bold)
362# print (fruEntry)
363 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600364
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600365def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600366 """
367 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600368
Justin Thalere412dc22018-01-12 16:28:24 -0600369 @param host: string, the hostname or IP address of the bmc
370 @param args: contains additional arguments used by the fru sub command
371 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600372 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
373 @return returns the total fru list.
374 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600375 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600376 try:
Justin Thaler27197622019-01-23 14:42:11 -0600377 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600378 except(requests.exceptions.Timeout):
379 return(connectionErrHandler(args.json, "Timeout", None))
380
Justin Thaler3a5771b2019-01-23 14:31:52 -0600381 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600382# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600383 if res.status_code==200:
384 frulist['Hardware'] = res.json()['data']
385 else:
386 if not args.json:
387 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
388 else:
389 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600390 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600391 try:
Justin Thaler27197622019-01-23 14:42:11 -0600392 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600393 except(requests.exceptions.Timeout):
394 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600395# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600396 if res.status_code==200:
397 frulist['Software'] = res.json()['data']
398 else:
399 if not args.json():
400 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
401 else:
402 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600403 return frulist
404
Justin Thalere412dc22018-01-12 16:28:24 -0600405
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600406def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600407 """
408 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600409
Justin Thalere412dc22018-01-12 16:28:24 -0600410 @param host: string, the hostname or IP address of the bmc
411 @param args: contains additional arguments used by the fru sub command
412 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600413 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
414 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600415 if(args.items==True):
416 return fruPrint(host, args, session)
417 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600418 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600419
420
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600421
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600422def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600423 """
424 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600425
Justin Thalere412dc22018-01-12 16:28:24 -0600426 @param host: string, the hostname or IP address of the bmc
427 @param args: contains additional arguments used by the fru sub command
428 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600429 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
430 """
Justin Thalere412dc22018-01-12 16:28:24 -0600431 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600432 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600433 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600434 except(requests.exceptions.Timeout):
435 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600436# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600437 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600438 frus = {}
439 for key in frulist:
440 component = frulist[key]
441 isFru = False
442 present = False
443 func = False
444 hasSels = False
445 keyPieces = key.split('/')
446 fruName = keyPieces[-1]
447 if 'core' in fruName: #associate cores to cpus
448 fruName = keyPieces[-2] + '-' + keyPieces[-1]
449 if 'Functional' in component:
450 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600451 if 'FieldReplaceable' in component:
452 if component['FieldReplaceable'] == 1:
453 isFru = True
454 if "fan" in fruName:
455 isFru = True;
456 if component['Present'] == 1:
457 present = True
458 if component['Functional'] == 1:
459 func = True
460 if ((key + "/fault") in frulist):
461 hasSels = True;
462 if args.verbose:
463 if hasSels:
464 loglist = []
465 faults = frulist[key+"/fault"]['endpoints']
466 for item in faults:
467 loglist.append(item.split('/')[-1])
468 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
469 else:
470 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
471 else:
472 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500473 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600474 if component['Present'] ==1:
475 present = True
476 isFru = True
477 if ((key + "/fault") in frulist):
478 hasSels = True;
479 if args.verbose:
480 if hasSels:
481 loglist = []
482 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100483 for item in faults:
484 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600485 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
486 else:
487 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
488 else:
489 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
490 if not args.json:
491 if not args.verbose:
492 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
493 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
494 else:
495 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
496 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
497 return tableDisplay(keylist, colNames, frus)
498 else:
499 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600500
Justin Thalere412dc22018-01-12 16:28:24 -0600501def sensor(host, args, session):
502 """
503 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600504
Justin Thalere412dc22018-01-12 16:28:24 -0600505 @param host: string, the hostname or IP address of the bmc
506 @param args: contains additional arguments used by the sensor sub command
507 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600508 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
509 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600510 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600511 try:
Justin Thaler27197622019-01-23 14:42:11 -0600512 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600513 except(requests.exceptions.Timeout):
514 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600515
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600516 #Get OCC status
517 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600518 try:
Justin Thaler27197622019-01-23 14:42:11 -0600519 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600520 except(requests.exceptions.Timeout):
521 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600522 if not args.json:
523 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600524 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600525 output = {}
526 for key in sensors:
527 senDict = {}
528 keyparts = key.split("/")
529 senDict['sensorName'] = keyparts[-1]
530 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600531 try:
532 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
533 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500534 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600535 if('Scale' in sensors[key]):
536 scale = 10 ** sensors[key]['Scale']
537 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600538 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500539 try:
540 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600541 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500542 if 'value' in sensors[key]:
543 senDict['value'] = sensors[key]['value']
544 else:
545 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600546 if 'Target' in sensors[key]:
547 senDict['target'] = str(sensors[key]['Target'])
548 else:
549 senDict['target'] = 'N/A'
550 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600551
Justin Thaler3a5771b2019-01-23 14:31:52 -0600552 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600553 if '/org/open_power/control/occ0' in occstatus:
554 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600555 if occ0 == 1:
556 occ0 = 'Active'
557 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600558 occ0 = 'Inactive'
559 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
560 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600561 if occ1 == 1:
562 occ1 = 'Active'
563 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600564 occ1 = 'Inactive'
565 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
566 else:
567 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
568 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
569 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600570
571 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600572 else:
573 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600574
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600575def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600576 """
577 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600578
Justin Thalere412dc22018-01-12 16:28:24 -0600579 @param host: string, the hostname or IP address of the bmc
580 @param args: contains additional arguments used by the sel sub command
581 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600582 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
583 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600584
585 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600586 try:
Justin Thaler27197622019-01-23 14:42:11 -0600587 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600588 except(requests.exceptions.Timeout):
589 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600590 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600591
592
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600593def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600594 """
595 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600596
Justin Thalere412dc22018-01-12 16:28:24 -0600597 @param eselRAW: string, the raw esel string from the bmc
598 @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 -0600599 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600600 eselParts = {}
601 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
602 #search terms contains the search term as the key and the return dictionary key as it's value
603 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500604 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600605 uniqueID = str(uuid.uuid4())
606 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500607 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600608 f.write(esel_bin)
609 errlPath = ""
610 #use the right errl file for the machine architecture
611 arch = platform.machine()
612 if(arch =='x86_64' or arch =='AMD64'):
613 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
614 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
615 elif os.path.exists('errl/x86_64/errl'):
616 errlPath = 'errl/x86_64/errl'
617 else:
618 errlPath = 'x86_64/errl'
619 elif (platform.machine()=='ppc64le'):
620 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
621 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
622 elif os.path.exists('errl/ppc64le/errl'):
623 errlPath = 'errl/ppc64le/errl'
624 else:
625 errlPath = 'ppc64le/errl'
626 else:
627 print("machine architecture not supported for parsing eSELs")
628 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600629
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600630 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500631 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600632# output = proc.communicate()[0]
633 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600634
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600635 if(hasattr(args, 'fullEsel')):
636 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600637
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600638 for i in range(0, len(lines)):
639 lineParts = lines[i].split(':')
640 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
641 for term in searchTerms:
642 if(term in lineParts[0]):
643 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
644 if lines[i+1].find(':') != -1:
645 if (len(lines[i+1].split(':')[0][1:].strip())==0):
646 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600647 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600648 if((i+1) <= len(lines)):
649 i+=1
650 else:
651 i=i-1
652 break
Justin Thaler43030422018-11-08 22:50:21 -0600653 #Append the content from the next line removing the pretty display characters
654 #Finds the first colon then starts 2 characters after, then removes all whitespace
655 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500656 if(searchTerms[term] in eselParts):
657 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
658 else:
659 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500660 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600661 else:
662 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600663
664 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600665
Justin Thalere412dc22018-01-12 16:28:24 -0600666
Matt Spinler02d0dff2018-08-29 13:19:25 -0500667def getESELSeverity(esel):
668 """
669 Finds the severity type in an eSEL from the User Header section.
670 @param esel - the eSEL data
671 @return severity - e.g. 'Critical'
672 """
673
674 # everything but 1 and 2 are Critical
675 # '1': 'recovered',
676 # '2': 'predictive',
677 # '4': 'unrecoverable',
678 # '5': 'critical',
679 # '6': 'diagnostic',
680 # '7': 'symptom'
681 severities = {
682 '1': 'Informational',
683 '2': 'Warning'
684 }
685
686 try:
687 headerPosition = esel.index('55 48') # 'UH'
688 # The severity is the last byte in the 8 byte section (a byte is ' bb')
689 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
690 type = severity[0]
691 except ValueError:
692 print("Could not find severity value in UH section in eSEL")
693 type = 'x';
694
695 return severities.get(type, 'Critical')
696
697
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600698def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600699 """
700 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600701
Justin Thalere412dc22018-01-12 16:28:24 -0600702 @param events: Dictionary containing events
703 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600704 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600705 logNumList = []
706 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600707 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600708 eventsWithTimestamp = {}
709 logNum2events = {}
710 for key in events:
711 if key == 'numAlerts': continue
712 if 'callout' in key: continue
713 timestamp = (events[key]['timestamp'])
714 if timestamp not in timestampList:
715 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
716 else:
717 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
718 #map logNumbers to the event dictionary keys
719 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600720
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600721 timestampList = list(eventsWithTimestamp.keys())
722 timestampList.sort()
723 for ts in timestampList:
724 if len(eventsWithTimestamp[ts]) > 1:
725 tmplist = eventsWithTimestamp[ts]
726 tmplist.sort()
727 logNumList = logNumList + tmplist
728 else:
729 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600730
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600731 return [logNumList, eventKeyDict]
732
Justin Thalere412dc22018-01-12 16:28:24 -0600733
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600734def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600735 """
736 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600737
Justin Thalere412dc22018-01-12 16:28:24 -0600738 @param policyTable: dictionary, the policy table entries
739 @param selEntries: dictionary, the alerts retrieved from the bmc
740 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600741 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600742 eventDict = {}
743 eventNum =""
744 count = 0
745 esel = ""
746 eselParts = {}
747 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500748 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600749
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600750 'prepare and sort the event entries'
751 for key in selEntries:
752 if 'callout' not in key:
753 selEntries[key]['logNum'] = key.split('/')[-1]
754 selEntries[key]['timestamp'] = selEntries[key]['Timestamp']
755 sortedEntries = sortSELs(selEntries)
756 logNumList = sortedEntries[0]
757 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600758
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600759 for logNum in logNumList:
760 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600761 hasEsel=False
762 i2creadFail = False
763 if 'callout' in key:
764 continue
765 else:
766 messageID = str(selEntries[key]['Message'])
767 addDataPiece = selEntries[key]['AdditionalData']
768 calloutIndex = 0
769 calloutFound = False
770 for i in range(len(addDataPiece)):
771 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
772 calloutIndex = i
773 calloutFound = True
774 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
775 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
776 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500777
778 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
779
780 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
781 if (messageID + '||' + fruCallout) not in policyTable:
782 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
783 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
784 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
785 fruCallout = 'FSI'
786 else:
787 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500788 calloutFound = True
789 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
790 if not calloutFound:
791 fruCallout = 'GPIO'
792 calloutFound = True
793 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
794 if not calloutFound:
795 fruCallout = "I2C"
796 calloutFound = True
797 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
798 if not calloutFound:
799 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600800 calloutFound = True
801 if("ESEL" in addDataPiece[i]):
802 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500803 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600804 if args.devdebug:
805 eselParts = parseESEL(args, esel)
806 hasEsel=True
807 if("GPU" in addDataPiece[i]):
808 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
809 calloutFound = True
810 if("PROCEDURE" in addDataPiece[i]):
811 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
812 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600813 if("RAIL_NAME" in addDataPiece[i]):
814 calloutFound=True
815 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
816 if("INPUT_NAME" in addDataPiece[i]):
817 calloutFound=True
818 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
819 if("SENSOR_TYPE" in addDataPiece[i]):
820 calloutFound=True
821 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600822
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600823 if(calloutFound):
Justin Thaler22b1bb52018-03-15 13:31:32 -0500824 if fruCallout != "":
825 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -0500826
827 # Also use the severity for hostboot errors
828 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
829 policyKey += '||' + eselSeverity
830
831 # if not in the table, fall back to the original key
832 if policyKey not in policyTable:
833 policyKey = policyKey.replace('||'+eselSeverity, '')
834
Justin Thalere34c43a2018-05-25 19:37:55 -0500835 if policyKey not in policyTable:
836 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -0500837 else:
838 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600839 else:
840 policyKey = messageID
841 event = {}
842 eventNum = str(count)
843 if policyKey in policyTable:
844 for pkey in policyTable[policyKey]:
845 if(type(policyTable[policyKey][pkey])== bool):
846 event[pkey] = boolToString(policyTable[policyKey][pkey])
847 else:
848 if (i2creadFail and pkey == 'Message'):
849 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
850 else:
851 event[pkey] = policyTable[policyKey][pkey]
852 event['timestamp'] = selEntries[key]['Timestamp']
853 event['resolved'] = bool(selEntries[key]['Resolved'])
854 if(hasEsel):
855 if args.devdebug:
856 event['eselParts'] = eselParts
857 event['raweSEL'] = esel
858 event['logNum'] = key.split('/')[-1]
859 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600860
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600861 else:
862 severity = str(selEntries[key]['Severity']).split('.')[-1]
863 if severity == 'Error':
864 severity = 'Critical'
865 eventDict['event'+eventNum] = {}
866 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
867 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
868 eventDict['event' + eventNum]['Severity'] = severity
869 if(hasEsel):
870 if args.devdebug:
871 eventDict['event' +eventNum]['eselParts'] = eselParts
872 eventDict['event' +eventNum]['raweSEL'] = esel
873 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
874 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600875 count += 1
876 return eventDict
877
878
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600879def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600880 """
881 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600882
Justin Thalere412dc22018-01-12 16:28:24 -0600883 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600884 @return:
885 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600886 activeAlerts = []
887 historyAlerts = []
888 sortedEntries = sortSELs(events)
889 logNumList = sortedEntries[0]
890 eventKeyDict = sortedEntries[1]
891 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
892 if(args.devdebug):
893 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
894 keylist.append('eSEL')
895 else:
896 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
897 for log in logNumList:
898 selDict = {}
899 alert = events[eventKeyDict[str(log)]]
900 if('error' in alert):
901 selDict['Entry'] = alert['logNum']
902 selDict['ID'] = 'Unknown'
903 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
904 msg = alert['error']
905 polMsg = msg.split("policy table:")[0]
906 msg = msg.split("policy table:")[1]
907 msgPieces = msg.split("||")
908 err = msgPieces[0]
909 if(err.find("org.open_power.")!=-1):
910 err = err.split("org.open_power.")[1]
911 elif(err.find("xyz.openbmc_project.")!=-1):
912 err = err.split("xyz.openbmc_project.")[1]
913 else:
914 err = msgPieces[0]
915 callout = ""
916 if len(msgPieces) >1:
917 callout = msgPieces[1]
918 if(callout.find("/org/open_power/")!=-1):
919 callout = callout.split("/org/open_power/")[1]
920 elif(callout.find("/xyz/openbmc_project/")!=-1):
921 callout = callout.split("/xyz/openbmc_project/")[1]
922 else:
923 callout = msgPieces[1]
924 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600925 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600926 selDict['Severity'] = alert['Severity']
927 else:
928 selDict['Entry'] = alert['logNum']
929 selDict['ID'] = alert['CommonEventID']
930 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600931 selDict['Message'] = alert['Message']
932 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600933 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600934
935
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600936 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
937 if ('eselParts' in alert and args.devdebug):
938 eselOutput = ""
939 for item in eselOrder:
940 if item in alert['eselParts']:
941 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
942 selDict['eSEL'] = eselOutput
943 else:
944 if args.devdebug:
945 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600946
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600947 if not alert['resolved']:
948 activeAlerts.append(selDict)
949 else:
950 historyAlerts.append(selDict)
951 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600952 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
953
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600954 output = ""
955 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600956 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600957 output +="----Active Alerts----\n"
958 for i in range(0, len(colNames)):
959 if i!=0: row =row + "| "
960 row = row + colNames[i].ljust(colWidth[i])
961 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600962
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600963 for i in range(0,len(activeAlerts)):
964 row = ""
965 for j in range(len(activeAlerts[i])):
966 if (j != 0): row = row + "| "
967 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
968 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600969
970 if(len(historyAlerts)>0):
971 row = ""
972 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600973 for i in range(len(colNames)):
974 if i!=0: row =row + "| "
975 row = row + colNames[i].ljust(colWidth[i])
976 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600977
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600978 for i in range(0, len(historyAlerts)):
979 row = ""
980 for j in range(len(historyAlerts[i])):
981 if (j != 0): row = row + "| "
982 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
983 output += row + "\n"
984# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600985 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600986
Justin Thalere412dc22018-01-12 16:28:24 -0600987
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600988def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600989 """
990 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600991
Justin Thalere412dc22018-01-12 16:28:24 -0600992 @param host: string, the hostname or IP address of the bmc
993 @param args: contains additional arguments used by the fru sub command
994 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600995 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
996 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600997 if(args.policyTableLoc is None):
998 if os.path.exists('policyTable.json'):
999 ptableLoc = "policyTable.json"
1000 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1001 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1002 else:
1003 ptableLoc = 'lib/policyTable.json'
1004 else:
1005 ptableLoc = args.policyTableLoc
1006 policyTable = loadPolicyTable(ptableLoc)
1007 rawselEntries = ""
1008 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1009 if os.path.exists(args.fileloc):
1010 with open(args.fileloc, 'r') as selFile:
1011 selLines = selFile.readlines()
1012 rawselEntries = ''.join(selLines)
1013 else:
1014 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001015 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001016 else:
1017 rawselEntries = sel(host, args, session)
1018 loadFailed = False
1019 try:
1020 selEntries = json.loads(rawselEntries)
1021 except ValueError:
1022 loadFailed = True
1023 if loadFailed:
1024 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1025 #need to load json twice as original content was string escaped a second time
1026 selEntries = json.loads(json.loads(cleanSels))
1027 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001028
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001029 if 'description' in selEntries:
1030 if(args.json):
1031 return("{\n\t\"numAlerts\": 0\n}")
1032 else:
1033 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001034
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001035 else:
1036 if(len(policyTable)>0):
1037 events = parseAlerts(policyTable, selEntries, args)
1038 if(args.json):
1039 events["numAlerts"] = len(events)
1040 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1041 return retValue
1042 elif(hasattr(args, 'fullSel')):
1043 return events
1044 else:
1045 #get log numbers to order event entries sequentially
1046 return selDisplay(events, args)
1047 else:
1048 if(args.json):
1049 return selEntries
1050 else:
1051 print("error: Policy Table not found.")
1052 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001053
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001054def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001055 """
1056 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001057
Justin Thalere412dc22018-01-12 16:28:24 -06001058 @param host: string, the hostname or IP address of the bmc
1059 @param args: contains additional arguments used by the fru sub command
1060 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001061 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1062 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001063 return(sel(host, args, session))
1064
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001065
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001066def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001067 """
1068 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001069
Justin Thalere412dc22018-01-12 16:28:24 -06001070 @param host: string, the hostname or IP address of the bmc
1071 @param args: contains additional arguments used by the fru sub command
1072 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001073 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1074 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001075 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001076 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001077
Justin Thalere412dc22018-01-12 16:28:24 -06001078 try:
Justin Thaler27197622019-01-23 14:42:11 -06001079 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001080 except(requests.exceptions.Timeout):
1081 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001082 if res.status_code == 200:
1083 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1084 else:
1085 print("Unable to clear the logs, trying to clear 1 at a time")
1086 sels = json.loads(sel(host, args, session))['data']
1087 for key in sels:
1088 if 'callout' not in key:
1089 logNum = key.split('/')[-1]
1090 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1091 try:
Justin Thaler27197622019-01-23 14:42:11 -06001092 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001093 except(requests.exceptions.Timeout):
1094 return connectionErrHandler(args.json, "Timeout", None)
1095 sys.exit(1)
1096 except(requests.exceptions.ConnectionError) as err:
1097 return connectionErrHandler(args.json, "ConnectionError", err)
1098 sys.exit(1)
1099 return ('Sel clearing complete')
1100
1101def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001102 """
1103 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001104
Justin Thalere412dc22018-01-12 16:28:24 -06001105 @param host: string, the hostname or IP address of the bmc
1106 @param args: contains additional arguments used by the fru sub command
1107 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001108 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1109 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001110 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001111 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001112 try:
Justin Thaler27197622019-01-23 14:42:11 -06001113 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001114 except(requests.exceptions.Timeout):
1115 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001116 if res.status_code == 200:
1117 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1118 else:
1119 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001120
Justin Thalere412dc22018-01-12 16:28:24 -06001121def selResolveAll(host, args, session):
1122 """
1123 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001124
Justin Thalere412dc22018-01-12 16:28:24 -06001125 @param host: string, the hostname or IP address of the bmc
1126 @param args: contains additional arguments used by the fru sub command
1127 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001128 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1129 """
Justin Thalere412dc22018-01-12 16:28:24 -06001130 rawselEntries = sel(host, args, session)
1131 loadFailed = False
1132 try:
1133 selEntries = json.loads(rawselEntries)
1134 except ValueError:
1135 loadFailed = True
1136 if loadFailed:
1137 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1138 #need to load json twice as original content was string escaped a second time
1139 selEntries = json.loads(json.loads(cleanSels))
1140 selEntries = selEntries['data']
1141
1142 if 'description' in selEntries:
1143 if(args.json):
1144 return("{\n\t\"selsResolved\": 0\n}")
1145 else:
1146 return("No log entries found")
1147 else:
1148 d = vars(args)
1149 successlist = []
1150 failedlist = []
1151 for key in selEntries:
1152 if 'callout' not in key:
1153 d['selNum'] = key.split('/')[-1]
1154 resolved = selSetResolved(host,args,session)
1155 if 'Sel entry' in resolved:
1156 successlist.append(d['selNum'])
1157 else:
1158 failedlist.append(d['selNum'])
1159 output = ""
1160 successlist.sort()
1161 failedlist.sort()
1162 if len(successlist)>0:
1163 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1164 if len(failedlist)>0:
1165 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1166 return output
1167
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001168def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001169 """
1170 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001171
Justin Thalere412dc22018-01-12 16:28:24 -06001172 @param host: string, the hostname or IP address of the bmc
1173 @param args: contains additional arguments used by the fru sub command
1174 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001175 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1176 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001177 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001178 if checkFWactivation(host, args, session):
1179 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001180 print("Attempting to Power on...:")
1181 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001182 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001183 try:
Justin Thaler27197622019-01-23 14:42:11 -06001184 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001185 except(requests.exceptions.Timeout):
1186 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001187 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001188 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001189 if checkFWactivation(host, args, session):
1190 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001191 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001192 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001193 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001194 try:
Justin Thaler27197622019-01-23 14:42:11 -06001195 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001196 except(requests.exceptions.Timeout):
1197 return(connectionErrHandler(args.json, "Timeout", None))
1198 return res.text
1199 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001200 if checkFWactivation(host, args, session):
1201 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001202 print("Attempting to Power off immediately...:")
1203 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001204 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1205 try:
Justin Thaler27197622019-01-23 14:42:11 -06001206 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001207 except(requests.exceptions.Timeout):
1208 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001209 return res.text
1210 elif(args.powcmd == 'status'):
1211 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001212 try:
Justin Thaler27197622019-01-23 14:42:11 -06001213 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001214 except(requests.exceptions.Timeout):
1215 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001216 chassisState = json.loads(res.text)['data'].split('.')[-1]
1217 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001218 try:
Justin Thaler27197622019-01-23 14:42:11 -06001219 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001220 except(requests.exceptions.Timeout):
1221 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001222 hostState = json.loads(res.text)['data'].split('.')[-1]
1223 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001224 try:
Justin Thaler27197622019-01-23 14:42:11 -06001225 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001226 except(requests.exceptions.Timeout):
1227 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001228 bmcState = json.loads(res.text)['data'].split('.')[-1]
1229 if(args.json):
1230 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1231 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1232 else:
1233 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1234 else:
1235 return "Invalid chassis power command"
1236
Justin Thalere412dc22018-01-12 16:28:24 -06001237
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001238def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001239 """
1240 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001241
Justin Thalere412dc22018-01-12 16:28:24 -06001242 @param host: string, the hostname or IP address of the bmc
1243 @param args: contains additional arguments used by the fru sub command
1244 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001245 @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 -06001246 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001247 if(args.identcmd == 'on'):
1248 print("Attempting to turn identify light on...:")
1249 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001250 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001251 try:
Justin Thaler27197622019-01-23 14:42:11 -06001252 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001253 except(requests.exceptions.Timeout):
1254 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001255 return res.text
1256 elif(args.identcmd == 'off'):
1257 print("Attempting to turn identify light off...:")
1258 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001259 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001260 try:
Justin Thaler27197622019-01-23 14:42:11 -06001261 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001262 except(requests.exceptions.Timeout):
1263 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001264 return res.text
1265 elif(args.identcmd == 'status'):
1266 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001267 try:
Justin Thaler27197622019-01-23 14:42:11 -06001268 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001269 except(requests.exceptions.Timeout):
1270 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001271 status = json.loads(res.text)['data']
1272 if(args.json):
1273 return status
1274 else:
1275 if status['Asserted'] == 0:
1276 return "Identify light is off"
1277 else:
1278 return "Identify light is blinking"
1279 else:
1280 return "Invalid chassis identify command"
1281
Justin Thalere412dc22018-01-12 16:28:24 -06001282
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001283def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001284 """
1285 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001286
Justin Thalere412dc22018-01-12 16:28:24 -06001287 @param host: string, the hostname or IP address of the bmc
1288 @param args: contains additional arguments used by the fru sub command
1289 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001290 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1291 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001292 if(hasattr(args, 'powcmd')):
1293 result = chassisPower(host,args,session)
1294 elif(hasattr(args, 'identcmd')):
1295 result = chassisIdent(host, args, session)
1296 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001297 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001298 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001299
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001300def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001301 """
1302 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001303
Justin Thalere412dc22018-01-12 16:28:24 -06001304 @param host: string, the hostname or IP address of the bmc
1305 @param args: contains additional arguments used by the collectServiceData sub command
1306 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001307 @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 -06001308 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001309 dumpNum = args.dumpNum
1310 if (args.dumpSaveLoc is not None):
1311 saveLoc = args.dumpSaveLoc
1312 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001313 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001314 url ='https://'+host+'/download/dump/' + str(dumpNum)
1315 try:
Justin Thaler27197622019-01-23 14:42:11 -06001316 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001317 if (args.dumpSaveLoc is not None):
1318 if os.path.exists(saveLoc):
1319 if saveLoc[-1] != os.path.sep:
1320 saveLoc = saveLoc + os.path.sep
1321 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001322
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001323 else:
1324 return 'Invalid save location specified'
1325 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001326 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001327
1328 with open(filename, 'wb') as f:
1329 for chunk in r.iter_content(chunk_size =1024):
1330 if chunk:
1331 f.write(chunk)
1332 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001333
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001334 except(requests.exceptions.Timeout):
1335 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001336
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001337 except(requests.exceptions.ConnectionError) as err:
1338 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001339
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001340def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001341 """
1342 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001343
Justin Thalere412dc22018-01-12 16:28:24 -06001344 @param host: string, the hostname or IP address of the bmc
1345 @param args: contains additional arguments used by the collectServiceData sub command
1346 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001347 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1348 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001349 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1350 try:
Justin Thaler27197622019-01-23 14:42:11 -06001351 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001352 dumpList = r.json()
1353 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001354 except(requests.exceptions.Timeout):
1355 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001356
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001357 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001358 return connectionErrHandler(args.json, "ConnectionError", err)
1359
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001360def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001361 """
1362 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001363
Justin Thalere412dc22018-01-12 16:28:24 -06001364 @param host: string, the hostname or IP address of the bmc
1365 @param args: contains additional arguments used by the collectServiceData sub command
1366 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001367 @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 -06001368 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001369 dumpList = []
1370 successList = []
1371 failedList = []
1372 if args.dumpNum is not None:
1373 if isinstance(args.dumpNum, list):
1374 dumpList = args.dumpNum
1375 else:
1376 dumpList.append(args.dumpNum)
1377 for dumpNum in dumpList:
1378 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1379 try:
Justin Thaler27197622019-01-23 14:42:11 -06001380 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001381 if r.status_code == 200:
1382 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001383 else:
1384 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001385 except(requests.exceptions.Timeout):
1386 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001387 except(requests.exceptions.ConnectionError) as err:
1388 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001389 output = "Successfully deleted dumps: " + ', '.join(successList)
1390 if(len(failedList)>0):
1391 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1392 return output
1393 else:
1394 return 'You must specify an entry number to delete'
1395
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001396def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001397 """
1398 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001399
Justin Thalere412dc22018-01-12 16:28:24 -06001400 @param host: string, the hostname or IP address of the bmc
1401 @param args: contains additional arguments used by the collectServiceData sub command
1402 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001403 @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 -06001404 """
1405 dumpResp = bmcDumpList(host, args, session)
1406 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1407 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001408 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001409 d = vars(args)
1410 dumpNums = []
1411 for dump in dumpList:
1412 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1413 dumpNums.append(int(dump.strip().split('/')[-1]))
1414 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001415
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001416 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001417
Justin Thalere412dc22018-01-12 16:28:24 -06001418
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001419def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001420 """
1421 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001422
Justin Thalere412dc22018-01-12 16:28:24 -06001423 @param host: string, the hostname or IP address of the bmc
1424 @param args: contains additional arguments used by the collectServiceData sub command
1425 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001426 @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 -06001427 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001428 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1429 try:
Justin Thaler27197622019-01-23 14:42:11 -06001430 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Matt Spinlereae05b02019-01-24 12:59:34 -06001431 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001432 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001433 elif(args.json):
1434 return r.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001435 else:
1436 return ('Failed to create dump')
1437 except(requests.exceptions.Timeout):
1438 return connectionErrHandler(args.json, "Timeout", None)
1439 except(requests.exceptions.ConnectionError) as err:
1440 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001441
1442
Justin Thaler666cf342019-01-23 14:44:27 -06001443def csdDumpInitiate(host, args, session):
1444 """
1445 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001446
Justin Thaler666cf342019-01-23 14:44:27 -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
1450 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1451 """
1452 errorInfo = ""
1453 dumpcount = 0
1454 try:
1455 d = vars(args)
1456 d['json'] = True
1457 except Exception as e:
1458 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
1459
1460 try:
1461 for i in range(3):
1462 dumpInfo = bmcDumpList(host, args, session)
1463 if 'data' in dumpInfo:
1464 dumpcount = len(dumpInfo['data'])
1465 break
1466 else:
1467 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1468 except Exception as e:
1469 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
1470
1471 #Create a user initiated dump
1472 try:
1473 for i in range(3):
1474 dumpcreated = bmcDumpCreate(host, args, session)
1475 if 'message' in dumpcreated:
1476 if 'ok' in dumpcreated['message'].lower():
1477 break
1478 else:
1479 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1480 else:
1481 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1482 except Exception as e:
1483 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
1484
1485 output = {}
1486 output['errors'] = errorInfo
1487 output['dumpcount'] = dumpcount
1488 return output
1489
1490def csdInventory(host, args,session, fileDir):
1491 """
1492 Collects the BMC inventory, retrying if necessary
1493
1494 @param host: string, the hostname or IP address of the bmc
1495 @param args: contains additional arguments used by the collectServiceData sub command
1496 @param session: the active session to use
1497 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1498 @param fileDir: string representation of the path to use for putting files created
1499 """
1500 errorInfo = "===========Inventory =============\n"
1501 output={}
1502 inventoryCollected = False
1503 try:
1504 for i in range(3):
1505 frulist = fruPrint(host, args, session)
1506 if 'Hardware' in frulist:
1507 inventoryCollected = True
1508 break
1509 else:
1510 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1511 except Exception as e:
1512 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
1513 if inventoryCollected:
1514 try:
1515 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1516 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1517 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1518 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1519 except Exception as e:
1520 print("Failed to write inventory to file.")
1521 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
1522
1523 output['errors'] = errorInfo
1524
1525 return output
1526
1527def csdSensors(host, args,session, fileDir):
1528 """
1529 Collects the BMC sensor readings, retrying if necessary
1530
1531 @param host: string, the hostname or IP address of the bmc
1532 @param args: contains additional arguments used by the collectServiceData sub command
1533 @param session: the active session to use
1534 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1535 @param fileDir: string representation of the path to use for putting files created
1536 """
1537 errorInfo = "===========Sensors =============\n"
1538 sensorsCollected = False
1539 output={}
1540 try:
1541 d = vars(args)
1542 d['json'] = False
1543 except Exception as e:
1544 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1545
1546 try:
1547 for i in range(3):
1548 sensorReadings = sensor(host, args, session)
1549 if 'OCC0' in sensorReadings:
1550 sensorsCollected = True
1551 break
1552 else:
1553 errorInfo += sensorReadings
1554 except Exception as e:
1555 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
1556 if sensorsCollected:
1557 try:
1558 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1559 f.write(sensorReadings)
1560 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1561 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1562 except Exception as e:
1563 print("Failed to write sensor readings to file system.")
1564 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
1565
1566 output['errors'] = errorInfo
1567 return output
1568
1569def csdLEDs(host,args, session, fileDir):
1570 """
1571 Collects the BMC LED status, retrying if necessary
1572
1573 @param host: string, the hostname or IP address of the bmc
1574 @param args: contains additional arguments used by the collectServiceData sub command
1575 @param session: the active session to use
1576 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1577 @param fileDir: string representation of the path to use for putting files created
1578 """
1579 errorInfo = "===========LEDs =============\n"
1580 ledsCollected = False
1581 output={}
1582 try:
1583 d = vars(args)
1584 d['json'] = True
1585 except Exception as e:
1586 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1587 try:
1588 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
1589 httpHeader = {'Content-Type':'application/json'}
1590 for i in range(3):
1591 try:
1592 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1593 if ledRes.status_code == 200:
1594 ledsCollected = True
1595 leds = ledRes.json()['data']
1596 break
1597 else:
1598 errorInfo += ledRes.text
1599 except(requests.exceptions.Timeout):
1600 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1601 except(requests.exceptions.ConnectionError) as err:
1602 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1603 except Exception as e:
1604 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
1605
1606 if ledsCollected:
1607 try:
1608 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
1609 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1610 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
1611 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
1612 except Exception as e:
1613 print("Failed to write LED status to file system.")
1614 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
1615
1616 output['errors'] = errorInfo
1617 return output
1618
1619def csdSelShortList(host, args, session, fileDir):
1620 """
1621 Collects the BMC log entries, retrying if necessary
1622
1623 @param host: string, the hostname or IP address of the bmc
1624 @param args: contains additional arguments used by the collectServiceData sub command
1625 @param session: the active session to use
1626 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1627 @param fileDir: string representation of the path to use for putting files created
1628 """
1629 errorInfo = "===========SEL Short List =============\n"
1630 selsCollected = False
1631 output={}
1632 try:
1633 d = vars(args)
1634 d['json'] = False
1635 except Exception as e:
1636 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1637
1638 try:
1639 for i in range(3):
1640 sels = selPrint(host,args,session)
1641 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
1642 selsCollected = True
1643 break
1644 else:
1645 errorInfo += sels + '\n'
1646 except Exception as e:
1647 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
1648
1649 if selsCollected:
1650 try:
1651 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
1652 f.write(sels)
1653 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
1654 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
1655 except Exception as e:
1656 print("Failed to write SEL short list to file system.")
1657 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
1658
1659 output['errors'] = errorInfo
1660 return output
1661
1662def csdParsedSels(host, args, session, fileDir):
1663 """
1664 Collects the BMC log entries, retrying if necessary
1665
1666 @param host: string, the hostname or IP address of the bmc
1667 @param args: contains additional arguments used by the collectServiceData sub command
1668 @param session: the active session to use
1669 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1670 @param fileDir: string representation of the path to use for putting files created
1671 """
1672 errorInfo = "===========SEL Parsed List =============\n"
1673 selsCollected = False
1674 output={}
1675 try:
1676 d = vars(args)
1677 d['json'] = True
1678 d['fullEsel'] = True
1679 except Exception as e:
1680 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
1681
1682 try:
1683 for i in range(3):
1684 parsedfullsels = json.loads(selPrint(host,args,session))
1685 if 'numAlerts' in parsedfullsels:
1686 selsCollected = True
1687 break
1688 else:
1689 errorInfo += parsedfullsels + '\n'
1690 except Exception as e:
1691 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
1692
1693 if selsCollected:
1694 try:
1695 sortedSELs = sortSELs(parsedfullsels)
1696 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
1697 for log in sortedSELs[0]:
1698 esel = ""
1699 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1700 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
1701 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
1702 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
1703 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
1704 if(args.devdebug and esel != ""):
1705 f.write(parseESEL(args, esel))
1706 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
1707 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
1708 except Exception as e:
1709 print("Failed to write fully parsed SELs to file system.")
1710 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
1711
1712 output['errors'] = errorInfo
1713 return output
1714
1715def csdFullEnumeration(host, args, session, fileDir):
1716 """
1717 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
1718
1719 @param host: string, the hostname or IP address of the bmc
1720 @param args: contains additional arguments used by the collectServiceData sub command
1721 @param session: the active session to use
1722 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1723 @param fileDir: string representation of the path to use for putting files created
1724 """
1725 errorInfo = "===========BMC Full Enumeration =============\n"
1726 bmcFullCollected = False
1727 output={}
1728 try:
1729 d = vars(args)
1730 d['json'] = True
1731 except Exception as e:
1732 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1733 try:
1734 print("Attempting to get a full BMC enumeration")
1735 url="https://"+host+"/xyz/openbmc_project/enumerate"
1736 httpHeader = {'Content-Type':'application/json'}
1737 for i in range(3):
1738 try:
1739 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
1740 if bmcRes.status_code == 200:
1741 bmcFullCollected = True
1742 fullEnumeration = bmcRes.json()
1743 break
1744 else:
1745 errorInfo += bmcRes.text
1746 except(requests.exceptions.Timeout):
1747 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1748 except(requests.exceptions.ConnectionError) as err:
1749 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1750 except Exception as e:
1751 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
1752
1753 if bmcFullCollected:
1754 try:
1755 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
1756 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1757 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
1758 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
1759 except Exception as e:
1760 print("Failed to write RAW BMC data to file system.")
1761 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
1762
1763 output['errors'] = errorInfo
1764 return output
1765
1766def csdCollectAllDumps(host, args, session, fileDir):
1767 """
1768 Collects all of the bmc dump files and stores them in fileDir
1769
1770 @param host: string, the hostname or IP address of the bmc
1771 @param args: contains additional arguments used by the collectServiceData sub command
1772 @param session: the active session to use
1773 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1774 @param fileDir: string representation of the path to use for putting files created
1775 """
1776
1777 errorInfo = "===========BMC Dump Collection =============\n"
1778 dumpListCollected = False
1779 output={}
1780 dumpList = {}
1781 try:
1782 d = vars(args)
1783 d['json'] = True
1784 d['dumpSaveLoc'] = fileDir
1785 except Exception as e:
1786 errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
1787
1788 print('Collecting bmc dump files')
1789
1790 try:
1791 for i in range(3):
1792 dumpResp = bmcDumpList(host, args, session)
1793 if 'message' in dumpResp:
1794 if 'ok' in dumpResp['message'].lower():
1795 dumpList = dumpResp['data']
1796 dumpListCollected = True
1797 break
1798 else:
1799 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
1800 else:
1801 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
1802 except Exception as e:
1803 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
1804
1805 if dumpListCollected:
1806 output['fileList'] = []
1807 for dump in dumpList:
1808 try:
1809 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1810 d['dumpNum'] = int(dump.strip().split('/')[-1])
1811 print('retrieving dump file ' + str(d['dumpNum']))
1812 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
1813 output['fileList'].append(filename)
1814 except Exception as e:
1815 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
1816 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
1817 output['errors'] = errorInfo
1818 return output
Justin Thalere412dc22018-01-12 16:28:24 -06001819
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001820def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001821 """
1822 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001823
Justin Thalere412dc22018-01-12 16:28:24 -06001824 @param host: string, the hostname or IP address of the bmc
1825 @param args: contains additional arguments used by the collectServiceData sub command
1826 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001827 @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 -06001828 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001829
Justin Thaler22b1bb52018-03-15 13:31:32 -05001830 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06001831 filelist = []
1832 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001833
Justin Thaler666cf342019-01-23 14:44:27 -06001834 #get current number of bmc dumps and create a new bmc dump
1835 dumpInitdata = csdDumpInitiate(host, args, session)
1836 dumpcount = dumpInitdata['dumpcount']
1837 errorInfo += dumpInitdata['errors']
1838 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001839 try:
1840 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05001841 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001842 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001843
Justin Thaler666cf342019-01-23 14:44:27 -06001844 except Exception as e:
1845 print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
1846 return("Python exception: {eInfo}".format(eInfo = e))
1847
1848 #Collect Inventory
1849 inventoryData = csdInventory(host, args, session, myDir)
1850 if 'fileLoc' in inventoryData:
1851 filelist.append(inventoryData['fileLoc'])
1852 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001853 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06001854 sensorData = csdSensors(host,args,session,myDir)
1855 if 'fileLoc' in sensorData:
1856 filelist.append(sensorData['fileLoc'])
1857 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001858 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06001859 ledStatus = csdLEDs(host, args, session, myDir)
1860 if 'fileLoc' in ledStatus:
1861 filelist.append(ledStatus['fileLoc'])
1862 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001863
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001864 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06001865 selShort = csdSelShortList(host, args, session, myDir)
1866 if 'fileLoc' in selShort:
1867 filelist.append(selShort['fileLoc'])
1868 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001869
Justin Thaler666cf342019-01-23 14:44:27 -06001870 parsedSELs = csdParsedSels(host, args, session, myDir)
1871 if 'fileLoc' in parsedSELs:
1872 filelist.append(parsedSELs['fileLoc'])
1873 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001874
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001875 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06001876 bmcRaw = csdFullEnumeration(host, args, session, myDir)
1877 if 'fileLoc' in bmcRaw:
1878 filelist.append(bmcRaw['fileLoc'])
1879 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001880
Justin Thaler666cf342019-01-23 14:44:27 -06001881 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001882 waitingForNewDump = True
1883 count = 0;
Justin Thaler666cf342019-01-23 14:44:27 -06001884 print("Waiting for new BMC dump to finish being created.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001885 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06001886 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001887 if len(dumpList) > dumpcount:
1888 waitingForNewDump = False
1889 break;
1890 elif(count>30):
1891 print("Timed out waiting for bmc to make a new dump file. Dump space may be full.")
1892 break;
1893 else:
1894 time.sleep(2)
1895 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06001896
1897 #collect all of the dump files
1898 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
1899 if 'fileList' in getBMCDumps:
1900 filelist+= getBMCDumps['fileList']
1901 errorInfo += getBMCDumps['errors']
1902
1903 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001904 try:
Justin Thaler666cf342019-01-23 14:44:27 -06001905 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
1906 f.write(errorInfo)
1907 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
1908 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001909 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06001910 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001911
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001912 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001913 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05001914 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06001915 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001916 for myfile in filelist:
1917 zf.write(myfile, os.path.basename(myfile))
1918 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06001919 print("Zip file with all collected data created and stored in: {fileInfo}".format(fileInfo=myDir+os.sep+filename))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001920 except Exception as e:
1921 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06001922 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001923
Justin Thalere412dc22018-01-12 16:28:24 -06001924
1925def healthCheck(host, args, session):
1926 """
1927 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001928
Justin Thalere412dc22018-01-12 16:28:24 -06001929 @param host: string, the hostname or IP address of the bmc
1930 @param args: contains additional arguments used by the bmc sub command
1931 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001932 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1933 """
Justin Thalere412dc22018-01-12 16:28:24 -06001934 #check fru status and get as json to easily work through
1935 d = vars(args)
1936 useJson = d['json']
1937 d['json'] = True
1938 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001939
Justin Thalere412dc22018-01-12 16:28:24 -06001940 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001941
Justin Thalere412dc22018-01-12 16:28:24 -06001942 hwStatus= "OK"
1943 performanceStatus = "OK"
1944 for key in frus:
1945 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
1946 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05001947 if("power_supply" in key or "powersupply" in key):
1948 gpuCount =0
1949 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06001950 if "gv100card" in comp:
1951 gpuCount +=1
1952 if gpuCount > 4:
1953 hwStatus = "Critical"
1954 performanceStatus="Degraded"
1955 break;
1956 elif("fan" in key):
1957 hwStatus = "Degraded"
1958 else:
1959 performanceStatus = "Degraded"
1960 if useJson:
1961 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
1962 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1963 else:
1964 output = ("Hardware Status: " + hwStatus +
1965 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001966
1967
Justin Thalere412dc22018-01-12 16:28:24 -06001968 #SW407886: Clear the duplicate entries
1969 #collect the dups
1970 d['devdebug'] = False
1971 sels = json.loads(selPrint(host, args, session))
1972 logNums2Clr = []
1973 oldestLogNum={"logNum": "bogus" ,"key" : ""}
1974 count = 0
1975 if sels['numAlerts'] > 0:
1976 for key in sels:
1977 if "numAlerts" in key:
1978 continue
1979 try:
1980 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
1981 count += 1
1982 if count > 1:
1983 #preserve first occurrence
1984 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
1985 oldestLogNum['key']=key
1986 oldestLogNum['logNum'] = sels[key]['logNum']
1987 else:
1988 oldestLogNum['key']=key
1989 oldestLogNum['logNum'] = sels[key]['logNum']
1990 logNums2Clr.append(sels[key]['logNum'])
1991 except KeyError:
1992 continue
1993 if(count >0):
1994 logNums2Clr.remove(oldestLogNum['logNum'])
1995 #delete the dups
1996 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06001997 data = "{\"data\": [] }"
1998 for logNum in logNums2Clr:
1999 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2000 try:
Justin Thaler27197622019-01-23 14:42:11 -06002001 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002002 except(requests.exceptions.Timeout):
2003 deleteFailed = True
2004 except(requests.exceptions.ConnectionError) as err:
2005 deleteFailed = True
2006 #End of defect resolve code
2007 d['json'] = useJson
2008 return output
2009
2010
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002011
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002012def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002013 """
2014 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002015
Justin Thalere412dc22018-01-12 16:28:24 -06002016 @param host: string, the hostname or IP address of the bmc
2017 @param args: contains additional arguments used by the bmc sub command
2018 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002019 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2020 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002021 if(args.type is not None):
2022 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002023 if(args.info):
2024 return "Not implemented at this time"
2025
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002026
Justin Thalere412dc22018-01-12 16:28:24 -06002027
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002028def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002029 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002030 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2031
Justin Thalere412dc22018-01-12 16:28:24 -06002032 @param host: string, the hostname or IP address of the bmc
2033 @param args: contains additional arguments used by the bmcReset sub command
2034 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002035 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2036 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002037 if checkFWactivation(host, args, session):
2038 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002039 if(args.type == "warm"):
2040 print("\nAttempting to reboot the BMC...:")
2041 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002042 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002043 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002044 return res.text
2045 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002046 print("\nAttempting to reboot the BMC...:")
2047 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002048 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002049 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002050 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002051 else:
2052 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002053
2054def gardClear(host, args, session):
2055 """
2056 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002057
Justin Thalere412dc22018-01-12 16:28:24 -06002058 @param host: string, the hostname or IP address of the bmc
2059 @param args: contains additional arguments used by the gardClear sub command
2060 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002061 """
Justin Thalere412dc22018-01-12 16:28:24 -06002062 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002063 data = '{"data":[]}'
2064 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002065
Justin Thaler27197622019-01-23 14:42:11 -06002066 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002067 if res.status_code == 404:
2068 return "Command not supported by this firmware version"
2069 else:
2070 return res.text
2071 except(requests.exceptions.Timeout):
2072 return connectionErrHandler(args.json, "Timeout", None)
2073 except(requests.exceptions.ConnectionError) as err:
2074 return connectionErrHandler(args.json, "ConnectionError", err)
2075
2076def activateFWImage(host, args, session):
2077 """
2078 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002079
Justin Thalere412dc22018-01-12 16:28:24 -06002080 @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 image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002084 """
Justin Thalere412dc22018-01-12 16:28:24 -06002085 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002086
Justin Thalere412dc22018-01-12 16:28:24 -06002087 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002088 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2089 try:
Justin Thaler27197622019-01-23 14:42:11 -06002090 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002091 except(requests.exceptions.Timeout):
2092 return connectionErrHandler(args.json, "Timeout", None)
2093 except(requests.exceptions.ConnectionError) as err:
2094 return connectionErrHandler(args.json, "ConnectionError", err)
2095 existingSoftware = json.loads(resp.text)['data']
2096 altVersionID = ''
2097 versionType = ''
2098 imageKey = '/xyz/openbmc_project/software/'+fwID
2099 if imageKey in existingSoftware:
2100 versionType = existingSoftware[imageKey]['Purpose']
2101 for key in existingSoftware:
2102 if imageKey == key:
2103 continue
2104 if 'Purpose' in existingSoftware[key]:
2105 if versionType == existingSoftware[key]['Purpose']:
2106 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002107
2108
2109
2110
Justin Thalere412dc22018-01-12 16:28:24 -06002111 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2112 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002113 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002114 data1 = "{\"data\": 1 }"
2115 try:
Justin Thaler27197622019-01-23 14:42:11 -06002116 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2117 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002118 except(requests.exceptions.Timeout):
2119 return connectionErrHandler(args.json, "Timeout", None)
2120 except(requests.exceptions.ConnectionError) as err:
2121 return connectionErrHandler(args.json, "ConnectionError", err)
2122 if(not args.json):
2123 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002124 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 -06002125 else:
2126 return "Firmware activation failed."
2127 else:
2128 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002129
2130def activateStatus(host, args, session):
2131 if checkFWactivation(host, args, session):
2132 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2133 else:
2134 return("No firmware activations are pending")
2135
2136def extractFWimage(path, imageType):
2137 """
2138 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002139
Justin Thaler22b1bb52018-03-15 13:31:32 -05002140 @param path: the path and file name of the firmware image
2141 @param imageType: The type of image the user is trying to flash. Host or BMC
2142 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002143 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002144 f = tempfile.TemporaryFile()
2145 tmpDir = tempfile.gettempdir()
2146 newImageID = ""
2147 if os.path.exists(path):
2148 try:
2149 imageFile = tarfile.open(path,'r')
2150 contents = imageFile.getmembers()
2151 for tf in contents:
2152 if 'MANIFEST' in tf.name:
2153 imageFile.extract(tf.name, path=tmpDir)
2154 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2155 for line in imageInfo:
2156 if 'purpose' in line:
2157 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002158 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002159 print('The specified image is not for ' + imageType)
2160 print('Please try again with the image for ' + imageType)
2161 return ""
2162 if 'version' == line.split('=')[0]:
2163 version = line.split('=')[1].strip().encode('utf-8')
2164 m = hashlib.sha512()
2165 m.update(version)
2166 newImageID = m.hexdigest()[:8]
2167 break
2168 try:
2169 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2170 except OSError:
2171 pass
2172 return newImageID
2173 except tarfile.ExtractError as e:
2174 print('Unable to extract information from the firmware file.')
2175 print('Ensure you have write access to the directory: ' + tmpDir)
2176 return newImageID
2177 except tarfile.TarError as e:
2178 print('This is not a valid firmware file.')
2179 return newImageID
2180 print("This is not a valid firmware file.")
2181 return newImageID
2182 else:
2183 print('The filename and path provided are not valid.')
2184 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002185
Justin Thaler22b1bb52018-03-15 13:31:32 -05002186def getAllFWImageIDs(fwInvDict):
2187 """
2188 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002189
Justin Thaler22b1bb52018-03-15 13:31:32 -05002190 @param fwInvDict: the dictionary to search for FW image IDs
2191 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002192 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002193 idList = []
2194 for key in fwInvDict:
2195 if 'Version' in fwInvDict[key]:
2196 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002197 return idList
2198
Justin Thalere412dc22018-01-12 16:28:24 -06002199def fwFlash(host, args, session):
2200 """
2201 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002202
Justin Thalere412dc22018-01-12 16:28:24 -06002203 @param host: string, the hostname or IP address of the bmc
2204 @param args: contains additional arguments used by the fwflash sub command
2205 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002206 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002207 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002208 if(args.type == 'bmc'):
2209 purp = 'BMC'
2210 else:
2211 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002212
2213 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002214 d['powcmd'] = 'status'
2215 powerstate = chassisPower(host, args, session)
2216 if 'Chassis Power State: On' in powerstate:
2217 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002218
Justin Thaler22b1bb52018-03-15 13:31:32 -05002219 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002220 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2221 try:
Justin Thaler27197622019-01-23 14:42:11 -06002222 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002223 except(requests.exceptions.Timeout):
2224 return connectionErrHandler(args.json, "Timeout", None)
2225 except(requests.exceptions.ConnectionError) as err:
2226 return connectionErrHandler(args.json, "ConnectionError", err)
2227 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002228
Justin Thaler22b1bb52018-03-15 13:31:32 -05002229 #Extract the tar and get information from the manifest file
2230 newversionID = extractFWimage(args.fileloc, purp)
2231 if newversionID == "":
2232 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002233
2234
Justin Thaler22b1bb52018-03-15 13:31:32 -05002235 #check if the new image is already on the bmc
2236 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002237
Justin Thaler22b1bb52018-03-15 13:31:32 -05002238 #upload the file
2239 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002240 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002241 url="https://"+host+"/upload/image"
2242 data=open(args.fileloc,'rb').read()
2243 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002244 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002245 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06002246 except(requests.exceptions.Timeout):
2247 return connectionErrHandler(args.json, "Timeout", None)
2248 except(requests.exceptions.ConnectionError) as err:
2249 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002250 if resp.status_code != 200:
2251 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002252 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002253 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002254
Justin Thaler22b1bb52018-03-15 13:31:32 -05002255 #verify bmc processed the image
2256 software ={}
2257 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002258 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2259 try:
Justin Thaler27197622019-01-23 14:42:11 -06002260 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002261 except(requests.exceptions.Timeout):
2262 return connectionErrHandler(args.json, "Timeout", None)
2263 except(requests.exceptions.ConnectionError) as err:
2264 return connectionErrHandler(args.json, "ConnectionError", err)
2265 software = json.loads(resp.text)['data']
2266 #check if bmc is done processing the new image
2267 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002268 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002269 else:
2270 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002271
Justin Thaler22b1bb52018-03-15 13:31:32 -05002272 #activate the new image
2273 print("Activating new image: "+newversionID)
2274 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002275 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002276 try:
Justin Thaler27197622019-01-23 14:42:11 -06002277 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002278 except(requests.exceptions.Timeout):
2279 return connectionErrHandler(args.json, "Timeout", None)
2280 except(requests.exceptions.ConnectionError) as err:
2281 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002282
Justin Thaler22b1bb52018-03-15 13:31:32 -05002283 #wait for the activation to complete, timeout after ~1 hour
2284 i=0
2285 while i < 360:
2286 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002287 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002288 try:
Justin Thaler27197622019-01-23 14:42:11 -06002289 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002290 except(requests.exceptions.Timeout):
2291 return connectionErrHandler(args.json, "Timeout", None)
2292 except(requests.exceptions.ConnectionError) as err:
2293 return connectionErrHandler(args.json, "ConnectionError", err)
2294 fwInfo = json.loads(resp.text)['data']
2295 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2296 print('')
2297 break
2298 else:
2299 sys.stdout.write('.')
2300 sys.stdout.flush()
2301 time.sleep(10) #check every 10 seconds
2302 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2303 else:
2304 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002305
Justin Thaler22b1bb52018-03-15 13:31:32 -05002306 d['imageID'] = newversionID
2307 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002308
Justin Thaler3d71d402018-07-24 14:35:39 -05002309def getFWInventoryAttributes(rawFWInvItem, ID):
2310 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002311 gets and lists all of the firmware in the system.
2312
Justin Thaler3d71d402018-07-24 14:35:39 -05002313 @return: returns a dictionary containing the image attributes
2314 """
2315 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2316 pendingActivation = ""
2317 if reqActivation == "None":
2318 pendingActivation = "No"
2319 else:
2320 pendingActivation = "Yes"
2321 firmwareAttr = {ID: {
2322 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2323 "Version": rawFWInvItem["Version"],
2324 "RequestedActivation": pendingActivation,
2325 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002326
Justin Thaler3d71d402018-07-24 14:35:39 -05002327 if "ExtendedVersion" in rawFWInvItem:
2328 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002329 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002330 firmwareAttr[ID]['ExtendedVersion'] = ""
2331 return firmwareAttr
2332
2333def parseFWdata(firmwareDict):
2334 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002335 creates a dictionary with parsed firmware data
2336
Justin Thaler3d71d402018-07-24 14:35:39 -05002337 @return: returns a dictionary containing the image attributes
2338 """
2339 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2340 for key in firmwareDict['data']:
2341 #check for valid endpoint
2342 if "Purpose" in firmwareDict['data'][key]:
2343 id = key.split('/')[-1]
2344 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2345 fwActivated = True
2346 else:
2347 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002348 if 'Priority' in firmwareDict['data'][key]:
2349 if firmwareDict['data'][key]['Priority'] == 0:
2350 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2351 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2352 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2353 else:
2354 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002355 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002356 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002357 emptySections = []
2358 for key in firmwareInfoDict:
2359 if len(firmwareInfoDict[key])<=0:
2360 emptySections.append(key)
2361 for key in emptySections:
2362 del firmwareInfoDict[key]
2363 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002364
Justin Thaler3d71d402018-07-24 14:35:39 -05002365def displayFWInvenory(firmwareInfoDict, args):
2366 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002367 gets and lists all of the firmware in the system.
2368
Justin Thaler3d71d402018-07-24 14:35:39 -05002369 @return: returns a string containing all of the firmware information
2370 """
2371 output = ""
2372 if not args.json:
2373 for key in firmwareInfoDict:
2374 for subkey in firmwareInfoDict[key]:
2375 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2376 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002377 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002378 colNames = ["Purpose", "Version", "ID"]
2379 keylist = ["Purpose", "Version", "ID"]
2380 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2381 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002382 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002383 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2384 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002385 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002386 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002387
Justin Thaler3d71d402018-07-24 14:35:39 -05002388 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002389 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002390 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2391 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2392 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2393 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002394 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002395 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2396 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002397 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002398 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2399 return output
2400 else:
2401 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2402
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002403def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002404 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002405 gets and lists all of the firmware in the system.
2406
Justin Thaler3d71d402018-07-24 14:35:39 -05002407 @return: returns a string containing all of the firmware information
2408 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002409 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2410 try:
Justin Thaler27197622019-01-23 14:42:11 -06002411 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002412 except(requests.exceptions.Timeout):
2413 return(connectionErrHandler(args.json, "Timeout", None))
2414 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002415
Justin Thaler3d71d402018-07-24 14:35:39 -05002416 #sort the received information
2417 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002418
Justin Thaler3d71d402018-07-24 14:35:39 -05002419 #display the information
2420 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002421
2422
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002423def deleteFWVersion(host, args, session):
2424 """
2425 deletes a firmware version on the BMC
2426
2427 @param host: string, the hostname or IP address of the BMC
2428 @param args: contains additional arguments used by the fwflash sub command
2429 @param session: the active session to use
2430 @param fwID: the unique ID of the fw version to delete
2431 """
2432 fwID = args.versionID
2433
2434 print("Deleting version: "+fwID)
2435 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002436 data = "{\"data\": [] }"
2437
2438 try:
Justin Thaler27197622019-01-23 14:42:11 -06002439 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002440 except(requests.exceptions.Timeout):
2441 return(connectionErrHandler(args.json, "Timeout", None))
2442 if res.status_code == 200:
2443 return ('The firmware version has been deleted')
2444 else:
2445 return ('Unable to delete the specified firmware version')
2446
2447
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002448def restLogging(host, args, session):
2449 """
2450 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002451
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002452 @param host: string, the hostname or IP address of the bmc
2453 @param args: contains additional arguments used by the logging sub command
2454 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002455 @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 -05002456 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002457 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002458
2459 if(args.rest_logging == 'on'):
2460 data = '{"data": 1}'
2461 elif(args.rest_logging == 'off'):
2462 data = '{"data": 0}'
2463 else:
2464 return "Invalid logging rest_api command"
2465
2466 try:
Justin Thaler27197622019-01-23 14:42:11 -06002467 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002468 except(requests.exceptions.Timeout):
2469 return(connectionErrHandler(args.json, "Timeout", None))
2470 return res.text
2471
2472
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002473def remoteLogging(host, args, session):
2474 """
2475 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002476
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002477 @param host: string, the hostname or IP address of the bmc
2478 @param args: contains additional arguments used by the logging sub command
2479 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002480 @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 -05002481 """
2482
2483 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002484
2485 try:
2486 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002487 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002488 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002489 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2490 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002491 else:
2492 return "Invalid logging remote_logging command"
2493 except(requests.exceptions.Timeout):
2494 return(connectionErrHandler(args.json, "Timeout", None))
2495 return res.text
2496
2497
2498def remoteLoggingConfig(host, args, session):
2499 """
2500 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002501
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002502 @param host: string, the hostname or IP address of the bmc
2503 @param args: contains additional arguments used by the logging sub command
2504 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002505 @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 -05002506 """
2507
2508 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002509
2510 try:
Justin Thaler27197622019-01-23 14:42:11 -06002511 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
2512 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002513 except(requests.exceptions.Timeout):
2514 return(connectionErrHandler(args.json, "Timeout", None))
2515 return res.text
2516
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002517def redfishSupportPresent(host, session):
2518 url = "https://" + host + "/redfish/v1"
2519 try:
2520 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2521 except(requests.exceptions.Timeout):
2522 return False
2523 except(requests.exceptions.ConnectionError) as err:
2524 return False
2525 if resp.status_code != 200:
2526 return False
2527 else:
2528 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05302529
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002530def certificateUpdate(host, args, session):
2531 """
2532 Called by certificate management function. update server/client/authority certificates
2533 Example:
2534 certificate update server https -f cert.pem
2535 certificate update authority ldap -f Root-CA.pem
2536 certificate update client ldap -f cert.pem
2537 @param host: string, the hostname or IP address of the bmc
2538 @param args: contains additional arguments used by the certificate update sub command
2539 @param session: the active session to use
2540 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002541 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002542 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002543 data = open(args.fileloc, 'rb').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002544 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002545 if redfishSupportPresent(host, session):
2546 url = "";
2547 if(args.type.lower() == 'server'):
2548 url = "https://" + host + \
2549 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
2550 elif(args.type.lower() == 'client'):
2551 url = "https://" + host + \
2552 "/redfish/v1/AccountService/LDAP/Certificates"
2553 elif(args.type.lower() == 'authority'):
2554 url = "https://" + host + \
2555 "/redfish/v1/Managers/bmc/Truststore/Certificates"
2556 else:
2557 return "Unsupported certificate type"
2558 resp = session.post(url, headers=httpHeader, data=data,
2559 verify=False)
2560 else:
2561 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
2562 args.type.lower() + "/" + args.service.lower()
2563 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002564 except(requests.exceptions.Timeout):
2565 return(connectionErrHandler(args.json, "Timeout", None))
2566 except(requests.exceptions.ConnectionError) as err:
2567 return connectionErrHandler(args.json, "ConnectionError", err)
2568 if resp.status_code != 200:
2569 print(resp.text)
2570 return "Failed to update the certificate"
2571 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002572 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002573
2574def certificateDelete(host, args, session):
2575 """
2576 Called by certificate management function to delete certificate
2577 Example:
2578 certificate delete server https
2579 certificate delete authority ldap
2580 certificate delete client ldap
2581 @param host: string, the hostname or IP address of the bmc
2582 @param args: contains additional arguments used by the certificate delete sub command
2583 @param session: the active session to use
2584 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05002585 if redfishSupportPresent(host, session):
2586 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002587 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002588 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002589 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2590 print("Deleting certificate url=" + url)
2591 try:
2592 resp = session.delete(url, headers=httpHeader)
2593 except(requests.exceptions.Timeout):
2594 return(connectionErrHandler(args.json, "Timeout", None))
2595 except(requests.exceptions.ConnectionError) as err:
2596 return connectionErrHandler(args.json, "ConnectionError", err)
2597 if resp.status_code != 200:
2598 print(resp.text)
2599 return "Failed to delete the certificate"
2600 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05002601 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002602
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05002603def certificateReplace(host, args, session):
2604 """
2605 Called by certificate management function. replace server/client/
2606 authority certificates
2607 Example:
2608 certificate replace server https -f cert.pem
2609 certificate replace authority ldap -f Root-CA.pem
2610 certificate replace client ldap -f cert.pem
2611 @param host: string, the hostname or IP address of the bmc
2612 @param args: contains additional arguments used by the certificate
2613 replace sub command
2614 @param session: the active session to use
2615 """
2616 cert = open(args.fileloc, 'rb').read()
2617 try:
2618 if redfishSupportPresent(host, session):
2619 httpHeader = {'Content-Type': 'application/json'}
2620 httpHeader.update(xAuthHeader)
2621 url = "";
2622 if(args.type.lower() == 'server'):
2623 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
2624 elif(args.type.lower() == 'client'):
2625 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
2626 elif(args.type.lower() == 'authority'):
2627 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
2628 replaceUrl = "https://" + host + \
2629 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
2630 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
2631 "CertificateString":cert}
2632 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
2633 else:
2634 httpHeader = {'Content-Type': 'application/octet-stream'}
2635 httpHeader.update(xAuthHeader)
2636 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
2637 args.type.lower() + "/" + args.service.lower()
2638 resp = session.delete(url, headers=httpHeader)
2639 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
2640 except(requests.exceptions.Timeout):
2641 return(connectionErrHandler(args.json, "Timeout", None))
2642 except(requests.exceptions.ConnectionError) as err:
2643 return connectionErrHandler(args.json, "ConnectionError", err)
2644 if resp.status_code != 200:
2645 print(resp.text)
2646 return "Failed to replace the certificate"
2647 else:
2648 print("Replace complete.")
2649 return resp.text
2650
Marri Devender Rao34646402019-07-01 05:46:03 -05002651def certificateDisplay(host, args, session):
2652 """
2653 Called by certificate management function. display server/client/
2654 authority certificates
2655 Example:
2656 certificate display server
2657 certificate display authority
2658 certificate display client
2659 @param host: string, the hostname or IP address of the bmc
2660 @param args: contains additional arguments used by the certificate
2661 display sub command
2662 @param session: the active session to use
2663 """
2664 if not redfishSupportPresent(host, session):
2665 return "Not supported";
2666
2667 httpHeader = {'Content-Type': 'application/octet-stream'}
2668 httpHeader.update(xAuthHeader)
2669 if(args.type.lower() == 'server'):
2670 url = "https://" + host + \
2671 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
2672 elif(args.type.lower() == 'client'):
2673 url = "https://" + host + \
2674 "/redfish/v1/AccountService/LDAP/Certificates/1"
2675 elif(args.type.lower() == 'authority'):
2676 url = "https://" + host + \
2677 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
2678 try:
2679 resp = session.get(url, headers=httpHeader, verify=False)
2680 except(requests.exceptions.Timeout):
2681 return(connectionErrHandler(args.json, "Timeout", None))
2682 except(requests.exceptions.ConnectionError) as err:
2683 return connectionErrHandler(args.json, "ConnectionError", err)
2684 if resp.status_code != 200:
2685 print(resp.text)
2686 return "Failed to display the certificate"
2687 else:
2688 print("Display complete.")
2689 return resp.text
2690
Marri Devender Raoa208ff82019-07-01 05:51:27 -05002691def certificateList(host, args, session):
2692 """
2693 Called by certificate management function.
2694 Example:
2695 certificate list
2696 @param host: string, the hostname or IP address of the bmc
2697 @param args: contains additional arguments used by the certificate
2698 list sub command
2699 @param session: the active session to use
2700 """
2701 if not redfishSupportPresent(host, session):
2702 return "Not supported";
2703
2704 httpHeader = {'Content-Type': 'application/octet-stream'}
2705 httpHeader.update(xAuthHeader)
2706 url = "https://" + host + \
2707 "/redfish/v1/CertificateService/CertificateLocations/"
2708 try:
2709 resp = session.get(url, headers=httpHeader, verify=False)
2710 except(requests.exceptions.Timeout):
2711 return(connectionErrHandler(args.json, "Timeout", None))
2712 except(requests.exceptions.ConnectionError) as err:
2713 return connectionErrHandler(args.json, "ConnectionError", err)
2714 if resp.status_code != 200:
2715 print(resp.text)
2716 return "Failed to list certificates"
2717 else:
2718 print("List certificates complete.")
2719 return resp.text
2720
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05002721def certificateGenerateCSR(host, args, session):
2722 """
2723 Called by certificate management function. Generate CSR for server/
2724 client certificates
2725 Example:
2726 certificate generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning
2727 certificate generatecsr client NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning
2728 @param host: string, the hostname or IP address of the bmc
2729 @param args: contains additional arguments used by the certificate replace sub command
2730 @param session: the active session to use
2731 """
2732 if not redfishSupportPresent(host, session):
2733 return "Not supported";
2734
2735 httpHeader = {'Content-Type': 'application/octet-stream'}
2736 httpHeader.update(xAuthHeader)
2737 url = "";
2738 if(args.type.lower() == 'server'):
2739 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
2740 elif(args.type.lower() == 'client'):
2741 url = "/redfish/v1/AccountService/LDAP/Certificates/"
2742 elif(args.type.lower() == 'authority'):
2743 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
2744 print("Generating CSR url=" + url)
2745 generateCSRUrl = "https://" + host + \
2746 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
2747 try:
2748 usage_list = args.keyUsage.split(",")
2749 alt_name_list = args.alternativeNames.split(",")
2750 data ={"CertificateCollection":{"@odata.id":url},
2751 "CommonName":args.commonName, "City":args.city,
2752 "Country":args.country, "Organization":args.organization,
2753 "OrganizationalUnit":args.organizationUnit, "State":args.state,
2754 "KeyPairAlgorithm":args.keyPairAlgorithm,
2755 "KeyBitLength":int(args.keyBitLength), "KeyCurveId":args.keyCurveId,
2756 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
2757 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
2758 "KeyUsage":usage_list, "Surname":args.surname,
2759 "UnstructuredName":args.unstructuredname}
2760 resp = session.post(generateCSRUrl, headers=httpHeader,
2761 json=data, verify=False)
2762 except(requests.exceptions.Timeout):
2763 return(connectionErrHandler(args.json, "Timeout", None))
2764 except(requests.exceptions.ConnectionError) as err:
2765 return connectionErrHandler(args.json, "ConnectionError", err)
2766 if resp.status_code != 200:
2767 print(resp.text)
2768 return "Failed to generate CSR"
2769 else:
2770 print("GenerateCSR complete.")
2771 return resp.text
2772
Ratan Gupta9166cd22018-10-01 18:09:40 +05302773def enableLDAP(host, args, session):
2774 """
2775 Called by the ldap function. Configures LDAP.
2776
2777 @param host: string, the hostname or IP address of the bmc
2778 @param args: contains additional arguments used by the ldap subcommand
2779 @param session: the active session to use
2780 @param args.json: boolean, if this flag is set to true, the output will
2781 be provided in json format for programmatic consumption
2782 """
2783
2784 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302785 scope = {
2786 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
2787 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
2788 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
2789 }
2790
2791 serverType = {
2792 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
2793 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
2794 }
2795
2796 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
2797
2798 try:
Justin Thaler27197622019-01-23 14:42:11 -06002799 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302800 except(requests.exceptions.Timeout):
2801 return(connectionErrHandler(args.json, "Timeout", None))
2802 except(requests.exceptions.ConnectionError) as err:
2803 return connectionErrHandler(args.json, "ConnectionError", err)
2804
2805 return res.text
2806
2807
2808def disableLDAP(host, args, session):
2809 """
2810 Called by the ldap function. Deletes the LDAP Configuration.
2811
2812 @param host: string, the hostname or IP address of the bmc
2813 @param args: contains additional arguments used by the ldap subcommand
2814 @param session: the active session to use
2815 @param args.json: boolean, if this flag is set to true, the output
2816 will be provided in json format for programmatic consumption
2817 """
2818
2819 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302820 data = {"data": []}
2821
2822 try:
Justin Thaler27197622019-01-23 14:42:11 -06002823 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302824 except(requests.exceptions.Timeout):
2825 return(connectionErrHandler(args.json, "Timeout", None))
2826 except(requests.exceptions.ConnectionError) as err:
2827 return connectionErrHandler(args.json, "ConnectionError", err)
2828
2829 return res.text
2830
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002831
2832def enableDHCP(host, args, session):
2833
2834 """
2835 Called by the network function. Enables DHCP.
2836
2837 @param host: string, the hostname or IP address of the bmc
2838 @param args: contains additional arguments used by the ldap subcommand
2839 args.json: boolean, if this flag is set to true, the output
2840 will be provided in json format for programmatic consumption
2841 @param session: the active session to use
2842 """
2843
2844 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2845 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002846 data = "{\"data\": 1 }"
2847 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002848 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002849 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002850
2851 except(requests.exceptions.Timeout):
2852 return(connectionErrHandler(args.json, "Timeout", None))
2853 except(requests.exceptions.ConnectionError) as err:
2854 return connectionErrHandler(args.json, "ConnectionError", err)
2855 if res.status_code == 403:
2856 return "The specified Interface"+"("+args.Interface+")"+\
2857 " doesn't exist"
2858
2859 return res.text
2860
2861
2862def disableDHCP(host, args, session):
2863 """
2864 Called by the network function. Disables DHCP.
2865
2866 @param host: string, the hostname or IP address of the bmc
2867 @param args: contains additional arguments used by the ldap subcommand
2868 args.json: boolean, if this flag is set to true, the output
2869 will be provided in json format for programmatic consumption
2870 @param session: the active session to use
2871 """
2872
2873 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2874 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002875 data = "{\"data\": 0 }"
2876 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002877 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002878 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002879 except(requests.exceptions.Timeout):
2880 return(connectionErrHandler(args.json, "Timeout", None))
2881 except(requests.exceptions.ConnectionError) as err:
2882 return connectionErrHandler(args.json, "ConnectionError", err)
2883 if res.status_code == 403:
2884 return "The specified Interface"+"("+args.Interface+")"+\
2885 " doesn't exist"
2886 return res.text
2887
2888
2889def getHostname(host, args, session):
2890
2891 """
2892 Called by the network function. Prints out the Hostname.
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
2901 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002902
2903 try:
Justin Thaler27197622019-01-23 14:42:11 -06002904 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002905 except(requests.exceptions.Timeout):
2906 return(connectionErrHandler(args.json, "Timeout", None))
2907 except(requests.exceptions.ConnectionError) as err:
2908 return connectionErrHandler(args.json, "ConnectionError", err)
2909
2910 return res.text
2911
2912
2913def setHostname(host, args, session):
2914 """
2915 Called by the network function. Sets the Hostname.
2916
2917 @param host: string, the hostname or IP address of the bmc
2918 @param args: contains additional arguments used by the ldap subcommand
2919 args.json: boolean, if this flag is set to true, the output
2920 will be provided in json format for programmatic consumption
2921 @param session: the active session to use
2922 """
2923
2924 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002925
2926 data = {"data": args.HostName}
2927
2928 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002929 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002930 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002931 except(requests.exceptions.Timeout):
2932 return(connectionErrHandler(args.json, "Timeout", None))
2933 except(requests.exceptions.ConnectionError) as err:
2934 return connectionErrHandler(args.json, "ConnectionError", err)
2935
2936 return res.text
2937
2938
2939def getDomainName(host, args, session):
2940
2941 """
2942 Called by the network function. Prints out the DomainName.
2943
2944 @param host: string, the hostname or IP address of the bmc
2945 @param args: contains additional arguments used by the ldap subcommand
2946 args.json: boolean, if this flag is set to true, the output
2947 will be provided in json format for programmatic consumption
2948 @param session: the active session to use
2949 """
2950
2951 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2952 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002953
2954 try:
Justin Thaler27197622019-01-23 14:42:11 -06002955 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002956 except(requests.exceptions.Timeout):
2957 return(connectionErrHandler(args.json, "Timeout", None))
2958 except(requests.exceptions.ConnectionError) as err:
2959 return connectionErrHandler(args.json, "ConnectionError", err)
2960 if res.status_code == 404:
2961 return "The specified Interface"+"("+args.Interface+")"+\
2962 " doesn't exist"
2963
2964 return res.text
2965
2966
2967def setDomainName(host, args, session):
2968 """
2969 Called by the network function. Sets the DomainName.
2970
2971 @param host: string, the hostname or IP address of the bmc
2972 @param args: contains additional arguments used by the ldap subcommand
2973 args.json: boolean, if this flag is set to true, the output
2974 will be provided in json format for programmatic consumption
2975 @param session: the active session to use
2976 """
2977
2978 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2979 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002980
2981 data = {"data": args.DomainName.split(",")}
2982
2983 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002984 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06002985 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002986 except(requests.exceptions.Timeout):
2987 return(connectionErrHandler(args.json, "Timeout", None))
2988 except(requests.exceptions.ConnectionError) as err:
2989 return connectionErrHandler(args.json, "ConnectionError", err)
2990 if res.status_code == 403:
2991 return "The specified Interface"+"("+args.Interface+")"+\
2992 " doesn't exist"
2993
2994 return res.text
2995
2996
2997def getMACAddress(host, args, session):
2998
2999 """
3000 Called by the network function. Prints out the MACAddress.
3001
3002 @param host: string, the hostname or IP address of the bmc
3003 @param args: contains additional arguments used by the ldap subcommand
3004 args.json: boolean, if this flag is set to true, the output
3005 will be provided in json format for programmatic consumption
3006 @param session: the active session to use
3007 """
3008
3009 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3010 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003011
3012 try:
Justin Thaler27197622019-01-23 14:42:11 -06003013 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003014 except(requests.exceptions.Timeout):
3015 return(connectionErrHandler(args.json, "Timeout", None))
3016 except(requests.exceptions.ConnectionError) as err:
3017 return connectionErrHandler(args.json, "ConnectionError", err)
3018 if res.status_code == 404:
3019 return "The specified Interface"+"("+args.Interface+")"+\
3020 " doesn't exist"
3021
3022 return res.text
3023
3024
3025def setMACAddress(host, args, session):
3026 """
3027 Called by the network function. Sets the MACAddress.
3028
3029 @param host: string, the hostname or IP address of the bmc
3030 @param args: contains additional arguments used by the ldap subcommand
3031 args.json: boolean, if this flag is set to true, the output
3032 will be provided in json format for programmatic consumption
3033 @param session: the active session to use
3034 """
3035
3036 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3037 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003038
3039 data = {"data": args.MACAddress}
3040
3041 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003042 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003043 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003044 except(requests.exceptions.Timeout):
3045 return(connectionErrHandler(args.json, "Timeout", None))
3046 except(requests.exceptions.ConnectionError) as err:
3047 return connectionErrHandler(args.json, "ConnectionError", err)
3048 if res.status_code == 403:
3049 return "The specified Interface"+"("+args.Interface+")"+\
3050 " doesn't exist"
3051
3052 return res.text
3053
3054
3055def getDefaultGateway(host, args, session):
3056
3057 """
3058 Called by the network function. Prints out the DefaultGateway.
3059
3060 @param host: string, the hostname or IP address of the bmc
3061 @param args: contains additional arguments used by the ldap subcommand
3062 args.json: boolean, if this flag is set to true, the output
3063 will be provided in json format for programmatic consumption
3064 @param session: the active session to use
3065 """
3066
3067 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003068
3069 try:
Justin Thaler27197622019-01-23 14:42:11 -06003070 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003071 except(requests.exceptions.Timeout):
3072 return(connectionErrHandler(args.json, "Timeout", None))
3073 except(requests.exceptions.ConnectionError) as err:
3074 return connectionErrHandler(args.json, "ConnectionError", err)
3075 if res.status_code == 404:
3076 return "Failed to get Default Gateway info!!"
3077
3078 return res.text
3079
3080
3081def setDefaultGateway(host, args, session):
3082 """
3083 Called by the network function. Sets the DefaultGateway.
3084
3085 @param host: string, the hostname or IP address of the bmc
3086 @param args: contains additional arguments used by the ldap subcommand
3087 args.json: boolean, if this flag is set to true, the output
3088 will be provided in json format for programmatic consumption
3089 @param session: the active session to use
3090 """
3091
3092 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003093
3094 data = {"data": args.DefaultGW}
3095
3096 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003097 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003098 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003099 except(requests.exceptions.Timeout):
3100 return(connectionErrHandler(args.json, "Timeout", None))
3101 except(requests.exceptions.ConnectionError) as err:
3102 return connectionErrHandler(args.json, "ConnectionError", err)
3103 if res.status_code == 403:
3104 return "Failed to set Default Gateway!!"
3105
3106 return res.text
3107
3108
3109def viewNWConfig(host, args, session):
3110 """
3111 Called by the ldap function. Prints out network configured properties
3112
3113 @param host: string, the hostname or IP address of the bmc
3114 @param args: contains additional arguments used by the ldap subcommand
3115 args.json: boolean, if this flag is set to true, the output
3116 will be provided in json format for programmatic consumption
3117 @param session: the active session to use
3118 @return returns LDAP's configured properties.
3119 """
3120 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003121 try:
Justin Thaler27197622019-01-23 14:42:11 -06003122 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003123 except(requests.exceptions.Timeout):
3124 return(connectionErrHandler(args.json, "Timeout", None))
3125 except(requests.exceptions.ConnectionError) as err:
3126 return connectionErrHandler(args.json, "ConnectionError", err)
3127 except(requests.exceptions.RequestException) as err:
3128 return connectionErrHandler(args.json, "RequestException", err)
3129 if res.status_code == 404:
3130 return "LDAP server config has not been created"
3131 return res.text
3132
3133
3134def getDNS(host, args, session):
3135
3136 """
3137 Called by the network function. Prints out DNS servers on the interface
3138
3139 @param host: string, the hostname or IP address of the bmc
3140 @param args: contains additional arguments used by the ldap subcommand
3141 args.json: boolean, if this flag is set to true, the output
3142 will be provided in json format for programmatic consumption
3143 @param session: the active session to use
3144 """
3145
3146 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3147 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003148
3149 try:
Justin Thaler27197622019-01-23 14:42:11 -06003150 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003151 except(requests.exceptions.Timeout):
3152 return(connectionErrHandler(args.json, "Timeout", None))
3153 except(requests.exceptions.ConnectionError) as err:
3154 return connectionErrHandler(args.json, "ConnectionError", err)
3155 if res.status_code == 404:
3156 return "The specified Interface"+"("+args.Interface+")" + \
3157 " doesn't exist"
3158
3159 return res.text
3160
3161
3162def setDNS(host, args, session):
3163 """
3164 Called by the network function. Sets DNS servers on the interface.
3165
3166 @param host: string, the hostname or IP address of the bmc
3167 @param args: contains additional arguments used by the ldap subcommand
3168 args.json: boolean, if this flag is set to true, the output
3169 will be provided in json format for programmatic consumption
3170 @param session: the active session to use
3171 """
3172
3173 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3174 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003175
3176 data = {"data": args.DNSServers.split(",")}
3177
3178 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003179 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003180 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003181 except(requests.exceptions.Timeout):
3182 return(connectionErrHandler(args.json, "Timeout", None))
3183 except(requests.exceptions.ConnectionError) as err:
3184 return connectionErrHandler(args.json, "ConnectionError", err)
3185 if res.status_code == 403:
3186 return "The specified Interface"+"("+args.Interface+")" +\
3187 " doesn't exist"
3188
3189 return res.text
3190
3191
3192def getNTP(host, args, session):
3193
3194 """
3195 Called by the network function. Prints out NTP servers on the interface
3196
3197 @param host: string, the hostname or IP address of the bmc
3198 @param args: contains additional arguments used by the ldap subcommand
3199 args.json: boolean, if this flag is set to true, the output
3200 will be provided in json format for programmatic consumption
3201 @param session: the active session to use
3202 """
3203
3204 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3205 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003206
3207 try:
Justin Thaler27197622019-01-23 14:42:11 -06003208 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003209 except(requests.exceptions.Timeout):
3210 return(connectionErrHandler(args.json, "Timeout", None))
3211 except(requests.exceptions.ConnectionError) as err:
3212 return connectionErrHandler(args.json, "ConnectionError", err)
3213 if res.status_code == 404:
3214 return "The specified Interface"+"("+args.Interface+")" + \
3215 " doesn't exist"
3216
3217 return res.text
3218
3219
3220def setNTP(host, args, session):
3221 """
3222 Called by the network function. Sets NTP servers on the interface.
3223
3224 @param host: string, the hostname or IP address of the bmc
3225 @param args: contains additional arguments used by the ldap subcommand
3226 args.json: boolean, if this flag is set to true, the output
3227 will be provided in json format for programmatic consumption
3228 @param session: the active session to use
3229 """
3230
3231 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3232 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003233
3234 data = {"data": args.NTPServers.split(",")}
3235
3236 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003237 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003238 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003239 except(requests.exceptions.Timeout):
3240 return(connectionErrHandler(args.json, "Timeout", None))
3241 except(requests.exceptions.ConnectionError) as err:
3242 return connectionErrHandler(args.json, "ConnectionError", err)
3243 if res.status_code == 403:
3244 return "The specified Interface"+"("+args.Interface+")" +\
3245 " doesn't exist"
3246
3247 return res.text
3248
3249
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003250def addIP(host, args, session):
3251 """
3252 Called by the network function. Configures IP address on given interface
3253
3254 @param host: string, the hostname or IP address of the bmc
3255 @param args: contains additional arguments used by the ldap subcommand
3256 args.json: boolean, if this flag is set to true, the output
3257 will be provided in json format for programmatic consumption
3258 @param session: the active session to use
3259 """
3260
3261 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3262 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003263 protocol = {
3264 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3265 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3266 }
3267
3268 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3269 args.gateway]}
3270
3271 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003272 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003273 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003274 except(requests.exceptions.Timeout):
3275 return(connectionErrHandler(args.json, "Timeout", None))
3276 except(requests.exceptions.ConnectionError) as err:
3277 return connectionErrHandler(args.json, "ConnectionError", err)
3278 if res.status_code == 404:
3279 return "The specified Interface" + "(" + args.Interface + ")" +\
3280 " doesn't exist"
3281
3282 return res.text
3283
3284
3285def getIP(host, args, session):
3286 """
3287 Called by the network function. Prints out IP address of given interface
3288
3289 @param host: string, the hostname or IP address of the bmc
3290 @param args: contains additional arguments used by the ldap subcommand
3291 args.json: boolean, if this flag is set to true, the output
3292 will be provided in json format for programmatic consumption
3293 @param session: the active session to use
3294 """
3295
3296 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3297 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003298 try:
Justin Thaler27197622019-01-23 14:42:11 -06003299 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003300 except(requests.exceptions.Timeout):
3301 return(connectionErrHandler(args.json, "Timeout", None))
3302 except(requests.exceptions.ConnectionError) as err:
3303 return connectionErrHandler(args.json, "ConnectionError", err)
3304 if res.status_code == 404:
3305 return "The specified Interface" + "(" + args.Interface + ")" +\
3306 " doesn't exist"
3307
3308 return res.text
3309
3310
3311def deleteIP(host, args, session):
3312 """
3313 Called by the network function. Deletes the IP address from given Interface
3314
3315 @param host: string, the hostname or IP address of the bmc
3316 @param args: contains additional arguments used by the ldap subcommand
3317 @param session: the active session to use
3318 @param args.json: boolean, if this flag is set to true, the output
3319 will be provided in json format for programmatic consumption
3320 """
3321
3322 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3323 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003324 data = {"data": []}
3325 try:
Justin Thaler27197622019-01-23 14:42:11 -06003326 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003327 except(requests.exceptions.Timeout):
3328 return(connectionErrHandler(args.json, "Timeout", None))
3329 except(requests.exceptions.ConnectionError) as err:
3330 return connectionErrHandler(args.json, "ConnectionError", err)
3331 if res.status_code == 404:
3332 return "The specified Interface" + "(" + args.Interface + ")" +\
3333 " doesn't exist"
3334 objDict = json.loads(res.text)
3335 if not objDict['data']:
3336 return "No object found for given address on given Interface"
3337
3338 for obj in objDict['data']:
3339 if args.address in objDict['data'][obj]['Address']:
3340 url = "https://"+host+obj+"/action/delete"
3341 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003342 res = session.post(url, headers=jsonHeader, json=data,
Justin Thaler27197622019-01-23 14:42:11 -06003343 verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003344 except(requests.exceptions.Timeout):
3345 return(connectionErrHandler(args.json, "Timeout", None))
3346 except(requests.exceptions.ConnectionError) as err:
3347 return connectionErrHandler(args.json, "ConnectionError", err)
3348 return res.text
3349 else:
3350 continue
3351 return "No object found for given address on given Interface"
3352
3353
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003354def addVLAN(host, args, session):
3355 """
3356 Called by the network function. Creates VLAN on given interface.
3357
3358 @param host: string, the hostname or IP address of the bmc
3359 @param args: contains additional arguments used by the ldap subcommand
3360 args.json: boolean, if this flag is set to true, the output
3361 will be provided in json format for programmatic consumption
3362 @param session: the active session to use
3363 """
3364
3365 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003366
3367 data = {"data": [args.Interface,args.Identifier]}
3368
3369 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003370 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003371 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003372 except(requests.exceptions.Timeout):
3373 return(connectionErrHandler(args.json, "Timeout", None))
3374 except(requests.exceptions.ConnectionError) as err:
3375 return connectionErrHandler(args.json, "ConnectionError", err)
3376 if res.status_code == 400:
3377 return "The specified Interface" + "(" + args.Interface + ")" +\
3378 " doesn't exist"
3379
3380 return res.text
3381
3382
3383def deleteVLAN(host, args, session):
3384 """
3385 Called by the network function. Creates VLAN on given interface.
3386
3387 @param host: string, the hostname or IP address of the bmc
3388 @param args: contains additional arguments used by the ldap subcommand
3389 args.json: boolean, if this flag is set to true, the output
3390 will be provided in json format for programmatic consumption
3391 @param session: the active session to use
3392 """
3393
3394 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003395 data = {"data": []}
3396
3397 try:
Justin Thaler27197622019-01-23 14:42:11 -06003398 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003399 except(requests.exceptions.Timeout):
3400 return(connectionErrHandler(args.json, "Timeout", None))
3401 except(requests.exceptions.ConnectionError) as err:
3402 return connectionErrHandler(args.json, "ConnectionError", err)
3403 if res.status_code == 404:
3404 return "The specified VLAN"+"("+args.Interface+"_"+args.Identifier\
3405 +")" +" doesn't exist"
3406
3407 return res.text
3408
3409
3410def viewDHCPConfig(host, args, session):
3411 """
3412 Called by the network function. Shows DHCP configured Properties.
3413
3414 @param host: string, the hostname or IP address of the bmc
3415 @param args: contains additional arguments used by the ldap subcommand
3416 args.json: boolean, if this flag is set to true, the output
3417 will be provided in json format for programmatic consumption
3418 @param session: the active session to use
3419 """
3420
3421 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003422
3423 try:
Justin Thaler27197622019-01-23 14:42:11 -06003424 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003425 except(requests.exceptions.Timeout):
3426 return(connectionErrHandler(args.json, "Timeout", None))
3427 except(requests.exceptions.ConnectionError) as err:
3428 return connectionErrHandler(args.json, "ConnectionError", err)
3429
3430 return res.text
3431
3432
3433def configureDHCP(host, args, session):
3434 """
3435 Called by the network function. Configures/updates DHCP Properties.
3436
3437 @param host: string, the hostname or IP address of the bmc
3438 @param args: contains additional arguments used by the ldap subcommand
3439 args.json: boolean, if this flag is set to true, the output
3440 will be provided in json format for programmatic consumption
3441 @param session: the active session to use
3442 """
3443
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003444
3445 try:
3446 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
3447 if(args.DNSEnabled == True):
3448 data = '{"data": 1}'
3449 else:
3450 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003451 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003452 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003453 if(args.HostNameEnabled == True):
3454 data = '{"data": 1}'
3455 else:
3456 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003457 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003458 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003459 if(args.NTPEnabled == True):
3460 data = '{"data": 1}'
3461 else:
3462 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003463 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003464 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003465 if(args.SendHostNameEnabled == True):
3466 data = '{"data": 1}'
3467 else:
3468 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003469 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003470 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003471 except(requests.exceptions.Timeout):
3472 return(connectionErrHandler(args.json, "Timeout", None))
3473 except(requests.exceptions.ConnectionError) as err:
3474 return connectionErrHandler(args.json, "ConnectionError", err)
3475
3476 return res.text
3477
3478
3479def nwReset(host, args, session):
3480
3481 """
3482 Called by the network function. Resets networks setting to factory defaults.
3483
3484 @param host: string, the hostname or IP address of the bmc
3485 @param args: contains additional arguments used by the ldap subcommand
3486 args.json: boolean, if this flag is set to true, the output
3487 will be provided in json format for programmatic consumption
3488 @param session: the active session to use
3489 """
3490
3491 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003492 data = '{"data":[] }'
3493 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003494 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003495 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003496
3497 except(requests.exceptions.Timeout):
3498 return(connectionErrHandler(args.json, "Timeout", None))
3499 except(requests.exceptions.ConnectionError) as err:
3500 return connectionErrHandler(args.json, "ConnectionError", err)
3501
3502 return res.text
3503
3504
Ratan Guptafeee6372018-10-17 23:25:51 +05303505def createPrivilegeMapping(host, args, session):
3506 """
3507 Called by the ldap function. Creates the group and the privilege mapping.
3508
3509 @param host: string, the hostname or IP address of the bmc
3510 @param args: contains additional arguments used by the ldap subcommand
3511 @param session: the active session to use
3512 @param args.json: boolean, if this flag is set to true, the output
3513 will be provided in json format for programmatic consumption
3514 """
3515
3516 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
Ratan Guptafeee6372018-10-17 23:25:51 +05303517
3518 data = {"data": [args.groupName,args.privilege]}
3519
3520 try:
Justin Thaler27197622019-01-23 14:42:11 -06003521 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05303522 except(requests.exceptions.Timeout):
3523 return(connectionErrHandler(args.json, "Timeout", None))
3524 except(requests.exceptions.ConnectionError) as err:
3525 return connectionErrHandler(args.json, "ConnectionError", err)
3526 return res.text
3527
3528def listPrivilegeMapping(host, args, session):
3529 """
3530 Called by the ldap function. Lists the group and the privilege mapping.
3531
3532 @param host: string, the hostname or IP address of the bmc
3533 @param args: contains additional arguments used by the ldap subcommand
3534 @param session: the active session to use
3535 @param args.json: boolean, if this flag is set to true, the output
3536 will be provided in json format for programmatic consumption
3537 """
3538 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
Ratan Guptafeee6372018-10-17 23:25:51 +05303539 data = {"data": []}
3540
3541 try:
Justin Thaler27197622019-01-23 14:42:11 -06003542 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05303543 except(requests.exceptions.Timeout):
3544 return(connectionErrHandler(args.json, "Timeout", None))
3545 except(requests.exceptions.ConnectionError) as err:
3546 return connectionErrHandler(args.json, "ConnectionError", err)
3547 return res.text
3548
3549def deletePrivilegeMapping(host, args, session):
3550 """
3551 Called by the ldap function. Deletes the mapping associated with the group.
3552
3553 @param host: string, the hostname or IP address of the bmc
3554 @param args: contains additional arguments used by the ldap subcommand
3555 @param session: the active session to use
3556 @param args.json: boolean, if this flag is set to true, the output
3557 will be provided in json format for programmatic consumption
3558 """
3559 (ldapNameSpaceObjects) = listPrivilegeMapping(host, args, session)
3560 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3561 path = ''
3562
3563 # not interested in the config objet
3564 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
3565
3566 # search for the object having the mapping for the given group
3567 for key,value in ldapNameSpaceObjects.items():
3568 if value['GroupName'] == args.groupName:
3569 path = key
3570 break
3571
3572 if path == '':
3573 return "No privilege mapping found for this group."
3574
3575 # delete the object
3576 url = 'https://'+host+path+'/action/delete'
Ratan Guptafeee6372018-10-17 23:25:51 +05303577 data = {"data": []}
3578
3579 try:
Justin Thaler27197622019-01-23 14:42:11 -06003580 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05303581 except(requests.exceptions.Timeout):
3582 return(connectionErrHandler(args.json, "Timeout", None))
3583 except(requests.exceptions.ConnectionError) as err:
3584 return connectionErrHandler(args.json, "ConnectionError", err)
3585 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303586
Sivas SRR78835272018-11-27 05:27:19 -06003587def deleteAllPrivilegeMapping(host, args, session):
3588 """
3589 Called by the ldap function. Deletes all the privilege mapping and group defined.
3590 @param host: string, the hostname or IP address of the bmc
3591 @param args: contains additional arguments used by the ldap subcommand
3592 @param session: the active session to use
3593 @param args.json: boolean, if this flag is set to true, the output
3594 will be provided in json format for programmatic consumption
3595 """
3596 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
3597 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3598 path = ''
3599
3600 # Remove the config object.
3601 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
Sivas SRR78835272018-11-27 05:27:19 -06003602 data = {"data": []}
3603
3604 try:
3605 # search for GroupName property and delete if it is available.
3606 for path in ldapNameSpaceObjects.keys():
3607 # delete the object
3608 url = 'https://'+host+path+'/action/delete'
Justin Thaler27197622019-01-23 14:42:11 -06003609 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Sivas SRR78835272018-11-27 05:27:19 -06003610 except(requests.exceptions.Timeout):
3611 return(connectionErrHandler(args.json, "Timeout", None))
3612 except(requests.exceptions.ConnectionError) as err:
3613 return connectionErrHandler(args.json, "ConnectionError", err)
3614 return res.text
3615
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003616def viewLDAPConfig(host, args, session):
3617 """
3618 Called by the ldap function. Prints out LDAP's configured properties
3619
3620 @param host: string, the hostname or IP address of the bmc
3621 @param args: contains additional arguments used by the ldap subcommand
3622 args.json: boolean, if this flag is set to true, the output
3623 will be provided in json format for programmatic consumption
3624 @param session: the active session to use
3625 @return returns LDAP's configured properties.
3626 """
3627 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003628 try:
Justin Thaler27197622019-01-23 14:42:11 -06003629 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003630 except(requests.exceptions.Timeout):
3631 return(connectionErrHandler(args.json, "Timeout", None))
3632 except(requests.exceptions.ConnectionError) as err:
3633 return connectionErrHandler(args.json, "ConnectionError", err)
3634 except(requests.exceptions.RequestException) as err:
3635 return connectionErrHandler(args.json, "RequestException", err)
3636 if res.status_code == 404:
3637 return "LDAP server config has not been created"
3638 return res.text
3639
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003640def str2bool(v):
3641 if v.lower() in ('yes', 'true', 't', 'y', '1'):
3642 return True
3643 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
3644 return False
3645 else:
3646 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003647
Matt Spinler7d426c22018-09-24 14:42:07 -05003648def localUsers(host, args, session):
3649 """
3650 Enables and disables local BMC users.
3651
3652 @param host: string, the hostname or IP address of the bmc
3653 @param args: contains additional arguments used by the logging sub command
3654 @param session: the active session to use
3655 """
3656
Matt Spinler7d426c22018-09-24 14:42:07 -05003657 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
3658 try:
Justin Thaler27197622019-01-23 14:42:11 -06003659 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003660 except(requests.exceptions.Timeout):
3661 return(connectionErrHandler(args.json, "Timeout", None))
3662 usersDict = json.loads(res.text)
3663
3664 if not usersDict['data']:
3665 return "No users found"
3666
3667 output = ""
3668 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05003669
3670 # Skip LDAP and another non-local users
3671 if 'UserEnabled' not in usersDict['data'][user]:
3672 continue
3673
Matt Spinler7d426c22018-09-24 14:42:07 -05003674 name = user.split('/')[-1]
3675 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
3676
3677 if args.local_users == "queryenabled":
3678 try:
Justin Thaler27197622019-01-23 14:42:11 -06003679 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003680 except(requests.exceptions.Timeout):
3681 return(connectionErrHandler(args.json, "Timeout", None))
3682
3683 result = json.loads(res.text)
3684 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
3685
3686 elif args.local_users in ["enableall", "disableall"]:
3687 action = ""
3688 if args.local_users == "enableall":
3689 data = '{"data": true}'
3690 action = "Enabling"
3691 else:
3692 data = '{"data": false}'
3693 action = "Disabling"
3694
3695 output += "{action} {name}\n".format(action=action, name=name)
3696
3697 try:
Justin Thaler27197622019-01-23 14:42:11 -06003698 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05003699 except(requests.exceptions.Timeout):
3700 return connectionErrHandler(args.json, "Timeout", None)
3701 except(requests.exceptions.ConnectionError) as err:
3702 return connectionErrHandler(args.json, "ConnectionError", err)
3703 else:
3704 return "Invalid local users argument"
3705
3706 return output
3707
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003708def setPassword(host, args, session):
3709 """
3710 Set local user password
3711 @param host: string, the hostname or IP address of the bmc
3712 @param args: contains additional arguments used by the logging sub
3713 command
3714 @param session: the active session to use
3715 @param args.json: boolean, if this flag is set to true, the output
3716 will be provided in json format for programmatic consumption
3717 @return: Session object
3718 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003719 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05003720 if(isRedfishSupport):
3721 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
3722 args.user
3723 data = {"Password":args.password}
3724 res = session.patch(url, headers=jsonHeader, json=data,
3725 verify=False, timeout=baseTimeout)
3726 else:
3727 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
3728 "/action/SetPassword"
3729 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003730 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003731 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003732 except(requests.exceptions.Timeout):
3733 return(connectionErrHandler(args.json, "Timeout", None))
3734 except(requests.exceptions.ConnectionError) as err:
3735 return connectionErrHandler(args.json, "ConnectionError", err)
3736 except(requests.exceptions.RequestException) as err:
3737 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05003738 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06003739
3740def getThermalZones(host, args, session):
3741 """
3742 Get the available thermal control zones
3743 @param host: string, the hostname or IP address of the bmc
3744 @param args: contains additional arguments used to get the thermal
3745 control zones
3746 @param session: the active session to use
3747 @return: Session object
3748 """
3749 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
3750
3751 try:
3752 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
3753 except(requests.exceptions.Timeout):
3754 return(connectionErrHandler(args.json, "Timeout", None))
3755 except(requests.exceptions.ConnectionError) as err:
3756 return connectionErrHandler(args.json, "ConnectionError", err)
3757 except(requests.exceptions.RequestException) as err:
3758 return connectionErrHandler(args.json, "RequestException", err)
3759
3760 if (res.status_code == 404):
3761 return "No thermal control zones found or system is in a" + \
3762 " powered off state"
3763
3764 zonesDict = json.loads(res.text)
3765 if not zonesDict['data']:
3766 return "No thermal control zones found"
3767 for zone in zonesDict['data']:
3768 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
3769
3770 return "Zones: [ " + z + " ]"
3771
3772
3773def getThermalMode(host, args, session):
3774 """
3775 Get thermal control mode
3776 @param host: string, the hostname or IP address of the bmc
3777 @param args: contains additional arguments used to get the thermal
3778 control mode
3779 @param session: the active session to use
3780 @param args.zone: the zone to get the mode on
3781 @return: Session object
3782 """
3783 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
3784 args.zone
3785
3786 try:
3787 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
3788 except(requests.exceptions.Timeout):
3789 return(connectionErrHandler(args.json, "Timeout", None))
3790 except(requests.exceptions.ConnectionError) as err:
3791 return connectionErrHandler(args.json, "ConnectionError", err)
3792 except(requests.exceptions.RequestException) as err:
3793 return connectionErrHandler(args.json, "RequestException", err)
3794
3795 if (res.status_code == 404):
3796 return "Thermal control zone(" + args.zone + ") not found or" + \
3797 " system is in a powered off state"
3798
3799 propsDict = json.loads(res.text)
3800 if not propsDict['data']:
3801 return "No thermal control properties found on zone(" + args.zone + ")"
3802 curMode = "Current"
3803 supModes = "Supported"
3804 result = "\n"
3805 for prop in propsDict['data']:
3806 if (prop.casefold() == curMode.casefold()):
3807 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
3808 if (prop.casefold() == supModes.casefold()):
3809 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
3810 result += supModes + " Modes: [ " + s + " ]\n"
3811
3812 return result
3813
3814def setThermalMode(host, args, session):
3815 """
3816 Set thermal control mode
3817 @param host: string, the hostname or IP address of the bmc
3818 @param args: contains additional arguments used for setting the thermal
3819 control mode
3820 @param session: the active session to use
3821 @param args.zone: the zone to set the mode on
3822 @param args.mode: the mode to enable
3823 @return: Session object
3824 """
3825 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
3826 args.zone + "/attr/Current"
3827
3828 # Check args.mode against supported modes using `getThermalMode` output
3829 modes = getThermalMode(host, args, session)
3830 modes = os.linesep.join([m for m in modes.splitlines() if m])
3831 modes = modes.replace("\n", ";").strip()
3832 modesDict = dict(m.split(': ') for m in modes.split(';'))
3833 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
3834 if args.mode.casefold() not in \
3835 (m.casefold() for m in sModes.split(',')) or not args.mode:
3836 result = ("Unsupported mode('" + args.mode + "') given, " +
3837 "select a supported mode: \n" +
3838 getThermalMode(host, args, session))
3839 return result
3840
3841 data = '{"data":"' + args.mode + '"}'
3842 try:
3843 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
3844 except(requests.exceptions.Timeout):
3845 return(connectionErrHandler(args.json, "Timeout", None))
3846 except(requests.exceptions.ConnectionError) as err:
3847 return connectionErrHandler(args.json, "ConnectionError", err)
3848 except(requests.exceptions.RequestException) as err:
3849 return connectionErrHandler(args.json, "RequestException", err)
3850
3851 if (data and res.status_code != 404):
3852 try:
3853 res = session.put(url, headers=jsonHeader,
3854 data=data, verify=False,
3855 timeout=30)
3856 except(requests.exceptions.Timeout):
3857 return(connectionErrHandler(args.json, "Timeout", None))
3858 except(requests.exceptions.ConnectionError) as err:
3859 return connectionErrHandler(args.json, "ConnectionError", err)
3860 except(requests.exceptions.RequestException) as err:
3861 return connectionErrHandler(args.json, "RequestException", err)
3862
3863 if res.status_code == 403:
3864 return "The specified thermal control zone(" + args.zone + ")" + \
3865 " does not exist"
3866
3867 return res.text
3868 else:
3869 return "Setting thermal control mode(" + args.mode + ")" + \
3870 " not supported or operation not available(system powered off?)"
3871
3872
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003873def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06003874 """
3875 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003876
Justin Thalere412dc22018-01-12 16:28:24 -06003877 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003878 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003879 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06003880 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
3881 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003882 group = parser.add_mutually_exclusive_group()
3883 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
3884 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05003885 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003886 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
3887 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
3888 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
3889 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06003890 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
3891 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003892
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003893 #fru command
3894 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06003895 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 -05003896 inv_subparser.required = True
3897 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003898 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
3899 inv_print.set_defaults(func=fruPrint)
3900 #fru list [0....n]
3901 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3902 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3903 inv_list.set_defaults(func=fruList)
3904 #fru status
3905 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06003906 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003907 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003908
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003909 #sensors command
3910 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06003911 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 -05003912 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003913 #sensor print
3914 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
3915 sens_print.set_defaults(func=sensor)
3916 #sensor list[0...n]
3917 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
3918 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
3919 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003920
Matthew Barth368e83c2019-02-01 13:48:25 -06003921 #thermal control commands
3922 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
3923 therm_subparser=parser_therm.add_subparsers(title='subcommands', description='Thermal control actions to work with', help='Valid thermal control actions to work with', dest='command')
3924 #thermal control zones
3925 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
3926 parser_thermZones.set_defaults(func=getThermalZones)
3927 #thermal control modes
3928 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
3929 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
3930 #get thermal control mode
3931 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
3932 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
3933 parser_getThermMode.set_defaults(func=getThermalMode)
3934 #set thermal control mode
3935 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
3936 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
3937 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
3938 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003939
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003940 #sel command
3941 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06003942 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 -05003943 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003944 #sel print
3945 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
3946 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3947 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
3948 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
3949 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003950
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003951 #sel list
3952 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")
3953 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
3954 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003955
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003956 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
3957 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
3958 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003959
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003960 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
3961 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003962
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003963 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06003964 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
3965 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
3966 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
3967 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003968 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003969
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003970 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06003971 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003972
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003973 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
3974 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003975
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003976 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 -06003977 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 -06003978 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003979
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003980 #control the chassis identify led
3981 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
3982 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
3983 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003984
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003985 #collect service data
3986 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
3987 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3988 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003989
Justin Thalere412dc22018-01-12 16:28:24 -06003990 #system quick health check
3991 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
3992 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003993
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003994 #work with bmc dumps
3995 parser_bmcdump = subparsers.add_parser("dump", help="Work with bmc dump files")
Justin Thalere412dc22018-01-12 16:28:24 -06003996 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003997 bmcDump_sub.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003998 dump_Create = bmcDump_sub.add_parser('create', help="Create a bmc dump")
3999 dump_Create.set_defaults(func=bmcDumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004000
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004001 dump_list = bmcDump_sub.add_parser('list', help="list all bmc dump files")
4002 dump_list.set_defaults(func=bmcDumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004003
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004004 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete bmc dump files")
4005 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004006 parserdumpdelete.set_defaults(func=bmcDumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004007
Justin Thalere412dc22018-01-12 16:28:24 -06004008 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004009 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all bmc dump files')
4010 deleteAllDumps.set_defaults(func=bmcDumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004011
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004012 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
4013 parser_dumpretrieve.add_argument("dumpNum", type=int, help="The Dump entry to delete")
4014 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file")
4015 parser_dumpretrieve.set_defaults(func=bmcDumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004016
Justin Thaler22b1bb52018-03-15 13:31:32 -05004017 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004018 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004019 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004020 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4021 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 -06004022 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.")
4023 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004024
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004025 #add alias to the bmc command
4026 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004027 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004028 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4029 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4030 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4031 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 -06004032 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004033 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004034
Justin Thalere412dc22018-01-12 16:28:24 -06004035 #gard clear
4036 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4037 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004038
Justin Thalere412dc22018-01-12 16:28:24 -06004039 #firmware_flash
4040 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4041 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 -05004042 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004043
Justin Thalere412dc22018-01-12 16:28:24 -06004044 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4045 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4046 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4047 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004048
Justin Thaler22b1bb52018-03-15 13:31:32 -05004049 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004050 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4051 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004052
Justin Thaler22b1bb52018-03-15 13:31:32 -05004053 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4054 fwActivateStatus.set_defaults(func=activateStatus)
4055
Justin Thaler3d71d402018-07-24 14:35:39 -05004056 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4057 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4058 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004059
Justin Thaler3d71d402018-07-24 14:35:39 -05004060 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4061 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4062 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004063
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004064 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4065 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4066 fwDelete.set_defaults(func=deleteFWVersion)
4067
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004068 #logging
4069 parser_logging = subparsers.add_parser("logging", help="logging controls")
4070 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004071
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004072 #turn rest api logging on/off
4073 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4074 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4075 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004076
4077 #remote logging
4078 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4079 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4080 parser_remote_logging.set_defaults(func=remoteLogging)
4081
4082 #configure remote logging
4083 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4084 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4085 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4086 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004087
4088 #certificate management
4089 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4090 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4091
4092 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4093 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4094 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4095 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4096 certUpdate.set_defaults(func=certificateUpdate)
4097
4098 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4099 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4100 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4101 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004102
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004103 certReplace = certMgmt_subproc.add_parser('replace',
4104 help="Replace the certificate")
4105 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4106 help="certificate type to replace")
4107 certReplace.add_argument('service', choices=['https', 'ldap'],
4108 help="Service to replace the certificate")
4109 certReplace.add_argument('-f', '--fileloc', required=True,
4110 help="The absolute path to the certificate file")
4111 certReplace.set_defaults(func=certificateReplace)
4112
Marri Devender Rao34646402019-07-01 05:46:03 -05004113 certDisplay = certMgmt_subproc.add_parser('display',
4114 help="Print the certificate")
4115 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4116 help="certificate type to display")
4117 certDisplay.set_defaults(func=certificateDisplay)
4118
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004119 certList = certMgmt_subproc.add_parser('list',
4120 help="Certificate list")
4121 certList.set_defaults(func=certificateList)
4122
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004123 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4124 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4125 help="Generate CSR")
4126 certGenerateCSR.add_argument('city',
4127 help="The city or locality of the organization making the request")
4128 certGenerateCSR.add_argument('commonName',
4129 help="The fully qualified domain name of the component that is being secured.")
4130 certGenerateCSR.add_argument('country',
4131 help="The country of the organization making the request")
4132 certGenerateCSR.add_argument('organization',
4133 help="The name of the organization making the request.")
4134 certGenerateCSR.add_argument('organizationUnit',
4135 help="The name of the unit or division of the organization making the request.")
4136 certGenerateCSR.add_argument('state',
4137 help="The state, province, or region of the organization making the request.")
4138 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4139 help="The type of key pair for use with signing algorithms.")
4140 certGenerateCSR.add_argument('keyBitLength', choices=['2048'],
4141 help="The length of the key in bits, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4142 certGenerateCSR.add_argument('keyCurveId',
4143 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4144 certGenerateCSR.add_argument('contactPerson',
4145 help="The name of the user making the request")
4146 certGenerateCSR.add_argument('email',
4147 help="The email address of the contact within the organization")
4148 certGenerateCSR.add_argument('alternativeNames',
4149 help="Additional hostnames of the component that is being secured")
4150 certGenerateCSR.add_argument('givenname',
4151 help="The given name of the user making the request")
4152 certGenerateCSR.add_argument('surname',
4153 help="The surname of the user making the request")
4154 certGenerateCSR.add_argument('unstructuredname',
4155 help="he unstructured name of the subject")
4156 certGenerateCSR.add_argument('initials',
4157 help="The initials of the user making the request")
4158 certGenerateCSR.add_argument('keyUsage', help="The usage of the key contained in the certificate")
4159
4160 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4161
Matt Spinler7d426c22018-09-24 14:42:07 -05004162 # local users
4163 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4164 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4165 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4166 parser_users.set_defaults(func=localUsers)
4167
Ratan Gupta9166cd22018-10-01 18:09:40 +05304168 #LDAP
4169 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4170 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4171
4172 #configure and enable LDAP
4173 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4174 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4175 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4176 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4177 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4178 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4179 help='Specifies the search scope:subtree, one level or base object.')
4180 parser_ldap_config.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4181 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
4182 parser_ldap_config.set_defaults(func=enableLDAP)
4183
4184 # disable LDAP
4185 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4186 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004187 # view-config
4188 parser_ldap_config = \
4189 ldap_sub.add_parser("view-config", help="prints out a list of all \
4190 LDAPS's configured properties")
4191 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304192
Ratan Guptafeee6372018-10-17 23:25:51 +05304193 #create group privilege mapping
4194 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4195 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4196 help="sub-command help", dest='command')
4197
4198 parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
4199 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
4200 parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-user'],required=True,help="Privilege")
4201 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4202
4203 #list group privilege mapping
4204 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
4205 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4206
4207 #delete group privilege mapping
4208 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
4209 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
4210 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
4211
Sivas SRR78835272018-11-27 05:27:19 -06004212 #deleteAll group privilege mapping
4213 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
4214 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
4215
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004216 # set local user password
4217 parser_set_password = subparsers.add_parser("set_password",
4218 help="Set password of local user")
4219 parser_set_password.add_argument( "-p", "--password", required=True,
4220 help="Password of local user")
4221 parser_set_password.set_defaults(func=setPassword)
4222
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004223 # network
4224 parser_nw = subparsers.add_parser("network", help="network controls")
4225 nw_sub = parser_nw.add_subparsers(title='subcommands',
4226 description='valid subcommands',
4227 help="sub-command help",
4228 dest='command')
4229
4230 # enable DHCP
4231 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
4232 help="enables the DHCP on given "
4233 "Interface")
4234 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004235 help="Name of the ethernet interface(it can"
4236 "be obtained by the "
4237 "command:network view-config)"
4238 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004239 parser_enable_dhcp.set_defaults(func=enableDHCP)
4240
4241 # disable DHCP
4242 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
4243 help="disables the DHCP on given "
4244 "Interface")
4245 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004246 help="Name of the ethernet interface(it can"
4247 "be obtained by the "
4248 "command:network view-config)"
4249 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004250 parser_disable_dhcp.set_defaults(func=disableDHCP)
4251
4252 # get HostName
4253 parser_gethostname = nw_sub.add_parser("getHostName",
4254 help="prints out HostName")
4255 parser_gethostname.set_defaults(func=getHostname)
4256
4257 # set HostName
4258 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
4259 parser_sethostname.add_argument("-H", "--HostName", required=True,
4260 help="A HostName for the BMC")
4261 parser_sethostname.set_defaults(func=setHostname)
4262
4263 # get domainname
4264 parser_getdomainname = nw_sub.add_parser("getDomainName",
4265 help="prints out DomainName of "
4266 "given Interface")
4267 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004268 help="Name of the ethernet interface(it "
4269 "can be obtained by the "
4270 "command:network view-config)"
4271 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004272 parser_getdomainname.set_defaults(func=getDomainName)
4273
4274 # set domainname
4275 parser_setdomainname = nw_sub.add_parser("setDomainName",
4276 help="sets DomainName of given "
4277 "Interface")
4278 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
4279 help="Ex: DomainName=Domain1,Domain2,...")
4280 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004281 help="Name of the ethernet interface(it "
4282 "can be obtained by the "
4283 "command:network view-config)"
4284 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004285 parser_setdomainname.set_defaults(func=setDomainName)
4286
4287 # get MACAddress
4288 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
4289 help="prints out MACAddress the "
4290 "given Interface")
4291 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004292 help="Name of the ethernet interface(it "
4293 "can be obtained by the "
4294 "command:network view-config)"
4295 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004296 parser_getmacaddress.set_defaults(func=getMACAddress)
4297
4298 # set MACAddress
4299 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
4300 help="sets MACAddress")
4301 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
4302 help="A MACAddress for the given "
4303 "Interface")
4304 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004305 help="Name of the ethernet interface(it can"
4306 "be obtained by the "
4307 "command:network view-config)"
4308 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004309 parser_setmacaddress.set_defaults(func=setMACAddress)
4310
4311 # get DefaultGW
4312 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
4313 help="prints out DefaultGateway "
4314 "the BMC")
4315 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
4316
4317 # set DefaultGW
4318 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
4319 help="sets DefaultGW")
4320 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
4321 help="A DefaultGateway for the BMC")
4322 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
4323
4324 # view network Config
4325 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
4326 "list of all network's configured "
4327 "properties")
4328 parser_ldap_config.set_defaults(func=viewNWConfig)
4329
4330 # get DNS
4331 parser_getDNS = nw_sub.add_parser("getDNS",
4332 help="prints out DNS servers on the "
4333 "given interface")
4334 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004335 help="Name of the ethernet interface(it can"
4336 "be obtained by the "
4337 "command:network view-config)"
4338 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004339 parser_getDNS.set_defaults(func=getDNS)
4340
4341 # set DNS
4342 parser_setDNS = nw_sub.add_parser("setDNS",
4343 help="sets DNS servers on the given "
4344 "interface")
4345 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
4346 help="Ex: DNSSERVERS=DNS1,DNS2,...")
4347 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004348 help="Name of the ethernet interface(it can"
4349 "be obtained by the "
4350 "command:network view-config)"
4351 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004352 parser_setDNS.set_defaults(func=setDNS)
4353
4354 # get NTP
4355 parser_getNTP = nw_sub.add_parser("getNTP",
4356 help="prints out NTP servers on the "
4357 "given interface")
4358 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004359 help="Name of the ethernet interface(it can"
4360 "be obtained by the "
4361 "command:network view-config)"
4362 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004363 parser_getNTP.set_defaults(func=getNTP)
4364
4365 # set NTP
4366 parser_setNTP = nw_sub.add_parser("setNTP",
4367 help="sets NTP servers on the given "
4368 "interface")
4369 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
4370 help="Ex: NTPSERVERS=NTP1,NTP2,...")
4371 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004372 help="Name of the ethernet interface(it can"
4373 "be obtained by the "
4374 "command:network view-config)"
4375 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004376 parser_setNTP.set_defaults(func=setNTP)
4377
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004378 # configure IP
4379 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
4380 "given interface")
4381 parser_ip_config.add_argument("-a", "--address", required=True,
4382 help="IP address of given interface")
4383 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
4384 help="The gateway for given interface")
4385 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
4386 help="The prefixLength of IP address")
4387 parser_ip_config.add_argument("-p", "--type", choices=['ipv4', 'ipv6'],
4388 help="The protocol type of the given"
4389 "IP address")
4390 parser_ip_config.add_argument("-I", "--Interface", required=True,
4391 help="Name of the ethernet interface(it can"
4392 "be obtained by the "
4393 "command:network view-config)"
4394 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
4395 parser_ip_config.set_defaults(func=addIP)
4396
4397 # getIP
4398 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
4399 "of given interface")
4400 parser_getIP.add_argument("-I", "--Interface", required=True,
4401 help="Name of the ethernet interface(it can"
4402 "be obtained by the command:network view-config)"
4403 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
4404 parser_getIP.set_defaults(func=getIP)
4405
4406 # rmIP
4407 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
4408 "of given interface")
4409 parser_rmIP.add_argument("-a", "--address", required=True,
4410 help="IP address to remove form given Interface")
4411 parser_rmIP.add_argument("-I", "--Interface", required=True,
4412 help="Name of the ethernet interface(it can"
4413 "be obtained by the command:network view-config)"
4414 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
4415 parser_rmIP.set_defaults(func=deleteIP)
4416
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004417 # add VLAN
4418 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
4419 "on given interface with given "
4420 "VLAN Identifier")
4421 parser_create_vlan.add_argument("-I", "--Interface", required=True,
4422 choices=['eth0', 'eth1'],
4423 help="Name of the ethernet interface")
4424 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
4425 help="VLAN Identifier")
4426 parser_create_vlan.set_defaults(func=addVLAN)
4427
4428 # delete VLAN
4429 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
4430 "on given interface with given "
4431 "VLAN Identifier")
4432 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
4433 help="Name of the ethernet interface(it can"
4434 "be obtained by the "
4435 "command:network view-config)"
4436 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
4437 parser_delete_vlan.set_defaults(func=deleteVLAN)
4438
4439 # viewDHCPConfig
4440 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
4441 help="Shows DHCP configured "
4442 "Properties")
4443 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
4444
4445 # configureDHCP
4446 parser_configDHCP = nw_sub.add_parser("configureDHCP",
4447 help="Configures/updates DHCP "
4448 "Properties")
4449 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
4450 required=True, help="Sets DNSEnabled property")
4451 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
4452 required=True,
4453 help="Sets HostNameEnabled property")
4454 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
4455 required=True,
4456 help="Sets NTPEnabled property")
4457 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
4458 required=True,
4459 help="Sets SendHostNameEnabled property")
4460 parser_configDHCP.set_defaults(func=configureDHCP)
4461
4462 # network factory reset
4463 parser_nw_reset = nw_sub.add_parser("nwReset",
4464 help="Resets networks setting to "
4465 "factory defaults. "
4466 "note:Reset settings will be applied "
4467 "after BMC reboot")
4468 parser_nw_reset.set_defaults(func=nwReset)
4469
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004470 return parser
4471
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004472def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06004473 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004474 main function for running the command line utility as a sub application
4475 """
4476 global toolVersion
Marri Devender Rao82590dc2019-06-06 04:54:22 -05004477 toolVersion = "1.15"
Sunitha Harishc99faba2019-07-19 06:55:22 -05004478 global isRedfishSupport
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004479 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004480 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004481
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004482 totTimeStart = int(round(time.time()*1000))
4483
4484 if(sys.version_info < (3,0)):
4485 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
4486 if sys.version_info >= (3,0):
4487 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06004488 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05004489 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06004490 sys.exit(0)
4491 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004492 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06004493 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004494 else:
Justin Thalere412dc22018-01-12 16:28:24 -06004495 if(hasattr(args, 'host') and hasattr(args,'user')):
4496 if (args.askpw):
4497 pw = getpass.getpass()
4498 elif(args.PW is not None):
4499 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004500 elif(args.PWenvvar):
4501 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06004502 else:
4503 print("You must specify a password")
4504 sys.exit()
4505 logintimeStart = int(round(time.time()*1000))
4506 mysess = login(args.host, args.user, pw, args.json)
Sunitha Harish336cda22019-07-23 02:02:52 -05004507 if(mysess == None):
4508 print("Login Failed!")
4509 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05004510 if(sys.version_info < (3,0)):
4511 if isinstance(mysess, basestring):
4512 print(mysess)
4513 sys.exit(1)
4514 elif sys.version_info >= (3,0):
4515 if isinstance(mysess, str):
4516 print(mysess)
4517 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06004518 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05004519 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004520 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06004521 output = args.func(args.host, args, mysess)
4522 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05004523 if isinstance(output, dict):
4524 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
4525 else:
4526 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06004527 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004528 logout(args.host, args.user, pw, mysess, args.json)
4529 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06004530 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
4531 print("loginTime: " + str(logintimeStop - logintimeStart))
4532 print("command Time: " + str(commandTimeStop - commandTimeStart))
4533 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004534 print("usage:\n"
4535 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
4536 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06004537 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004538 "\t{fru,sensors,sel,chassis,collect_service_data, \
4539 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06004540 "\t...\n" +
4541 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004542 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004543
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004544if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06004545 """
4546 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004547
4548 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004549 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004550
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004551 isTTY = sys.stdout.isatty()
4552 assert sys.version_info >= (2,7)
4553 main()