blob: c097484e7ff2f2ed3faca0acba5b5a3ac2e6f451 [file] [log] [blame]
Justin Thalerb8807ce2018-05-25 19:16:20 -05001#!/usr/bin/python3
Justin Thalere412dc22018-01-12 16:28:24 -06002"""
3 Copyright 2017 IBM Corporation
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004
Justin Thalere412dc22018-01-12 16:28:24 -06005 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
Justin Thalerf9aee3e2017-12-05 12:11:09 -060017import argparse
18import requests
19import getpass
20import json
21import os
22import urllib3
23import time, datetime
Justin Thalerf9aee3e2017-12-05 12:11:09 -060024import binascii
25import subprocess
26import platform
27import zipfile
Justin Thaler22b1bb52018-03-15 13:31:32 -050028import tarfile
29import tempfile
30import hashlib
Justin Thalera6b5df72018-07-16 11:10:07 -050031import re
Justin Thaler24d4efa2018-11-08 22:48:10 -060032import uuid
Justin Thalerf9aee3e2017-12-05 12:11:09 -060033
Matt Spinler220c3c42019-01-04 15:09:29 -060034jsonHeader = {'Content-Type' : 'application/json'}
35xAuthHeader = {}
36
Justin Thalerf9aee3e2017-12-05 12:11:09 -060037def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -060038 """
39 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060040
Justin Thalere412dc22018-01-12 16:28:24 -060041 @param textToColor: string, the text to be colored
42 @param color: string, used to color the text red or green
43 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060044 @return: Buffered reader containing the modified string.
45 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -060046 if(sys.platform.__contains__("win")):
47 if(color == "red"):
48 os.system('color 04')
49 elif(color == "green"):
50 os.system('color 02')
51 else:
52 os.system('color') #reset to default
53 return textToColor
54 else:
55 attr = []
56 if(color == "red"):
57 attr.append('31')
58 elif(color == "green"):
59 attr.append('32')
60 else:
61 attr.append('0')
62 if bold:
63 attr.append('1')
64 else:
65 attr.append('0')
66 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
67
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060068
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'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -060099
Justin Thaler115bca72018-05-25 19:29:08 -0500100 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600101 return(errorMessageStr)
102 elif errorStr == "ConnectionError":
103 if not jsonFormat:
104 return("FQPSPIN0001M: " + str(err))
105 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500106 conerror = {}
107 conerror['CommonEventID'] = 'FQPSPIN0001M'
108 conerror['sensor']="N/A"
109 conerror['state']="N/A"
110 conerror['additionalDetails'] = str(err)
111 conerror['Message']="Connection Error. View additional details for more information"
112 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
113 conerror['Serviceable']="Yes"
114 conerror['CallHomeCandidate']= "No"
115 conerror['Severity'] = "Critical"
116 conerror['EventType'] = "Communication Failure/Timeout"
117 conerror['VMMigrationFlag'] = "Yes"
118 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
119 conerror["timestamp"] = str(int(time.time()))
120 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
121 eventdict = {}
122 eventdict['event0'] = conerror
123 eventdict['numAlerts'] = '1'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600124
Justin Thaler115bca72018-05-25 19:29:08 -0500125 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600126 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500127
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600128 else:
129 return("Unknown Error: "+ str(err))
130
Justin Thalere412dc22018-01-12 16:28:24 -0600131
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600132def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600133 """
134 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600135
136 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600137 @param numcols: the total number of columns in the final output
138 @param dictForOutput: dictionary, contains the information to print to the screen
139 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600140 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600141 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600142 colWidths = []
143 for x in range(0, numCols):
144 colWidths.append(0)
145 for key in dictForOutput:
146 for x in range(0, numCols):
147 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600148
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600149 for x in range(0, numCols):
150 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600151
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600152 return colWidths
153
154def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600155 """
156 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600157
Justin Thalere412dc22018-01-12 16:28:24 -0600158 @param value: boolean, the value to convert
159 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600160 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600161 policyTable = {}
162 if(os.path.exists(pathToPolicyTable)):
163 with open(pathToPolicyTable, 'r') as stream:
164 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600165 contents =json.load(stream)
166 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600167 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600168 print(err)
169 return policyTable
170
Justin Thalere412dc22018-01-12 16:28:24 -0600171
172def boolToString(value):
173 """
174 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600175
Justin Thalere412dc22018-01-12 16:28:24 -0600176 @param value: boolean, the value to convert
177 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600178 """
Justin Thalere412dc22018-01-12 16:28:24 -0600179 if(value):
180 return "Yes"
181 else:
182 return "No"
183
Justin Thalera6b5df72018-07-16 11:10:07 -0500184def stringToInt(text):
185 """
186 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600187
Justin Thalera6b5df72018-07-16 11:10:07 -0500188 @param text: the string to try to convert to an integer
189 """
190 if text.isdigit():
191 return int(text)
192 else:
193 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600194
Justin Thalera6b5df72018-07-16 11:10:07 -0500195def naturalSort(text):
196 """
197 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600198
Justin Thalera6b5df72018-07-16 11:10:07 -0500199 @param text: the key to convert for sorting
200 @return list containing the broken up string parts by integers and strings
201 """
202 stringPartList = []
203 for c in re.split('(\d+)', text):
204 stringPartList.append(stringToInt(c))
205 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600206
Justin Thalere412dc22018-01-12 16:28:24 -0600207def tableDisplay(keylist, colNames, output):
208 """
209 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600210
Justin Thalere412dc22018-01-12 16:28:24 -0600211 @param keylist: list, keys for the output dictionary, ordered by colNames
212 @param colNames: Names for the Table of the columns
213 @param output: The dictionary of data to display
214 @return: Session object
215 """
216 colWidth = setColWidth(keylist, len(colNames), output, colNames)
217 row = ""
218 outputText = ""
219 for i in range(len(colNames)):
220 if (i != 0): row = row + "| "
221 row = row + colNames[i].ljust(colWidth[i])
222 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600223
Justin Thalera6b5df72018-07-16 11:10:07 -0500224 output_keys = list(output.keys())
225 output_keys.sort(key=naturalSort)
226 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600227 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500228 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600229 if (i != 0): row = row + "| "
230 row = row + output[key][keylist[i]].ljust(colWidth[i])
231 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600232
Justin Thalere412dc22018-01-12 16:28:24 -0600233 return outputText
234
Justin Thaler22b1bb52018-03-15 13:31:32 -0500235def checkFWactivation(host, args, session):
236 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600237 Checks the software inventory for an image that is being activated.
238
Justin Thaler22b1bb52018-03-15 13:31:32 -0500239 @return: True if an image is being activated, false is no activations are happening
240 """
241 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500242 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600243 resp = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500244 except(requests.exceptions.Timeout):
245 print(connectionErrHandler(args.json, "Timeout", None))
246 return(True)
247 except(requests.exceptions.ConnectionError) as err:
248 print( connectionErrHandler(args.json, "ConnectionError", err))
249 return True
250 fwInfo = json.loads(resp.text)['data']
251 for key in fwInfo:
252 if 'Activation' in fwInfo[key]:
253 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
254 return True
255 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600256
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600257def login(host, username, pw,jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600258 """
259 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600260
Justin Thalere412dc22018-01-12 16:28:24 -0600261 @param host: string, the hostname or IP address of the bmc to log into
262 @param username: The user name for the bmc to log into
263 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600264 @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 -0600265 @return: Session object
266 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600267 if(jsonFormat==False):
268 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600269 mysess = requests.session()
270 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600271 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=30)
272
273 cookie = r.headers['Set-Cookie']
274 match = re.search('SESSION=(\w+);', cookie)
275 if match:
276 xAuthHeader['X-Auth-Token'] = match.group(1)
277 jsonHeader.update(xAuthHeader)
278
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600279 loginMessage = json.loads(r.text)
280 if (loginMessage['status'] != "ok"):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600281 print(loginMessage["data"]["description"].encode('utf-8'))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600282 sys.exit(1)
283# if(sys.version_info < (3,0)):
284# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
285# if sys.version_info >= (3,0):
286# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
287 return mysess
288 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500289 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600290 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500291 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600292
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600293
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600294def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600295 """
296 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600297
Justin Thalere412dc22018-01-12 16:28:24 -0600298 @param host: string, the hostname or IP address of the bmc to log out of
299 @param username: The user name for the bmc to log out of
300 @param pw: The password for the BMC to log out of
301 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600302 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
303 """
Justin Thalere412dc22018-01-12 16:28:24 -0600304 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600305 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=10)
Justin Thalere412dc22018-01-12 16:28:24 -0600306 except(requests.exceptions.Timeout):
307 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600308
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600309 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600310 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600311 print('User ' +username + ' has been logged out')
312
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600313
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600314def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600315 """
316 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600317
Justin Thalere412dc22018-01-12 16:28:24 -0600318 @param host: string, the hostname or IP address of the bmc
319 @param args: contains additional arguments used by the fru sub command
320 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600321 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
322 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600323 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600324
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600325 #print(url)
326 #res = session.get(url, headers=httpHeader, verify=False)
327 #print(res.text)
328 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600329
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600330 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600331
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600332 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600333 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600334 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Justin Thalere412dc22018-01-12 16:28:24 -0600335 except(requests.exceptions.Timeout):
336 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600337
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600338 sample = res.text
339# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600340#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600341# #determine column width's
342# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
343# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600344#
345# 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 -0600346# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
347# format the output
348# for key in sorted(inv_list.keys()):
349# keyParts = key.split("/")
350# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600351#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600352# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
353# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
354# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
355# if(isTTY):
356# if(inv_list[key]["is_fru"] == 1):
357# color = "green"
358# bold = True
359# else:
360# color='black'
361# bold = False
362# fruEntry = hilight(fruEntry, color, bold)
363# print (fruEntry)
364 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600365
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600366def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600367 """
368 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600369
Justin Thalere412dc22018-01-12 16:28:24 -0600370 @param host: string, the hostname or IP address of the bmc
371 @param args: contains additional arguments used by the fru sub command
372 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600373 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
374 @return returns the total fru list.
375 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600376 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600377 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600378 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Justin Thalere412dc22018-01-12 16:28:24 -0600379 except(requests.exceptions.Timeout):
380 return(connectionErrHandler(args.json, "Timeout", None))
381
382
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600383# print(res.text)
384 frulist = res.text
385 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600386 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600387 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Justin Thalere412dc22018-01-12 16:28:24 -0600388 except(requests.exceptions.Timeout):
389 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600390# print(res.text)
391 frulist = frulist +"\n" + res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600392
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600393 return frulist
394
Justin Thalere412dc22018-01-12 16:28:24 -0600395
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600396def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600397 """
398 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600399
Justin Thalere412dc22018-01-12 16:28:24 -0600400 @param host: string, the hostname or IP address of the bmc
401 @param args: contains additional arguments used by the fru sub command
402 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600403 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
404 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600405 if(args.items==True):
406 return fruPrint(host, args, session)
407 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600408 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600409
410
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600411
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600412def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600413 """
414 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600415
Justin Thalere412dc22018-01-12 16:28:24 -0600416 @param host: string, the hostname or IP address of the bmc
417 @param args: contains additional arguments used by the fru sub command
418 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600419 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
420 """
Justin Thalere412dc22018-01-12 16:28:24 -0600421 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600422 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600423 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600424 except(requests.exceptions.Timeout):
425 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600426# print(res.text)
Justin Thalere412dc22018-01-12 16:28:24 -0600427 frulist = json.loads(res.text)['data']
428 frus = {}
429 for key in frulist:
430 component = frulist[key]
431 isFru = False
432 present = False
433 func = False
434 hasSels = False
435 keyPieces = key.split('/')
436 fruName = keyPieces[-1]
437 if 'core' in fruName: #associate cores to cpus
438 fruName = keyPieces[-2] + '-' + keyPieces[-1]
439 if 'Functional' in component:
440 if('Present' in component):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600441
Justin Thalere412dc22018-01-12 16:28:24 -0600442 if 'FieldReplaceable' in component:
443 if component['FieldReplaceable'] == 1:
444 isFru = True
445 if "fan" in fruName:
446 isFru = True;
447 if component['Present'] == 1:
448 present = True
449 if component['Functional'] == 1:
450 func = True
451 if ((key + "/fault") in frulist):
452 hasSels = True;
453 if args.verbose:
454 if hasSels:
455 loglist = []
456 faults = frulist[key+"/fault"]['endpoints']
457 for item in faults:
458 loglist.append(item.split('/')[-1])
459 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
460 else:
461 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
462 else:
463 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500464 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600465 if component['Present'] ==1:
466 present = True
467 isFru = True
468 if ((key + "/fault") in frulist):
469 hasSels = True;
470 if args.verbose:
471 if hasSels:
472 loglist = []
473 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100474 for item in faults:
475 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600476 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
477 else:
478 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
479 else:
480 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
481 if not args.json:
482 if not args.verbose:
483 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
484 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
485 else:
486 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
487 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
488 return tableDisplay(keylist, colNames, frus)
489 else:
490 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600491
Justin Thalere412dc22018-01-12 16:28:24 -0600492def sensor(host, args, session):
493 """
494 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600495
Justin Thalere412dc22018-01-12 16:28:24 -0600496 @param host: string, the hostname or IP address of the bmc
497 @param args: contains additional arguments used by the sensor sub command
498 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600499 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
500 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600501 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600502 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600503 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -0600504 except(requests.exceptions.Timeout):
505 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600506
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600507 #Get OCC status
508 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600509 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600510 occres = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -0600511 except(requests.exceptions.Timeout):
512 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600513 if not args.json:
514 colNames = ['sensor', 'type', 'units', 'value', 'target']
515 sensors = json.loads(res.text)["data"]
516 output = {}
517 for key in sensors:
518 senDict = {}
519 keyparts = key.split("/")
520 senDict['sensorName'] = keyparts[-1]
521 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600522 try:
523 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
524 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500525 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600526 if('Scale' in sensors[key]):
527 scale = 10 ** sensors[key]['Scale']
528 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600529 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500530 try:
531 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600532 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500533 if 'value' in sensors[key]:
534 senDict['value'] = sensors[key]['value']
535 else:
536 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600537 if 'Target' in sensors[key]:
538 senDict['target'] = str(sensors[key]['Target'])
539 else:
540 senDict['target'] = 'N/A'
541 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600542
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600543 occstatus = json.loads(occres.text)["data"]
544 if '/org/open_power/control/occ0' in occstatus:
545 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600546 if occ0 == 1:
547 occ0 = 'Active'
548 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600549 occ0 = 'Inactive'
550 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
551 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600552 if occ1 == 1:
553 occ1 = 'Active'
554 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600555 occ1 = 'Inactive'
556 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
557 else:
558 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
559 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
560 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600561
562 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600563 else:
564 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600565
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600566def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600567 """
568 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600569
Justin Thalere412dc22018-01-12 16:28:24 -0600570 @param host: string, the hostname or IP address of the bmc
571 @param args: contains additional arguments used by the sel sub command
572 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600573 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
574 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600575
576 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600577 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600578 res = session.get(url, headers=jsonHeader, verify=False, timeout=60)
Justin Thalere412dc22018-01-12 16:28:24 -0600579 except(requests.exceptions.Timeout):
580 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600581 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600582
583
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600584def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600585 """
586 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600587
Justin Thalere412dc22018-01-12 16:28:24 -0600588 @param eselRAW: string, the raw esel string from the bmc
589 @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 -0600590 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600591 eselParts = {}
592 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
593 #search terms contains the search term as the key and the return dictionary key as it's value
594 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500595 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600596 uniqueID = str(uuid.uuid4())
597 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500598 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600599 f.write(esel_bin)
600 errlPath = ""
601 #use the right errl file for the machine architecture
602 arch = platform.machine()
603 if(arch =='x86_64' or arch =='AMD64'):
604 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
605 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
606 elif os.path.exists('errl/x86_64/errl'):
607 errlPath = 'errl/x86_64/errl'
608 else:
609 errlPath = 'x86_64/errl'
610 elif (platform.machine()=='ppc64le'):
611 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
612 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
613 elif os.path.exists('errl/ppc64le/errl'):
614 errlPath = 'errl/ppc64le/errl'
615 else:
616 errlPath = 'ppc64le/errl'
617 else:
618 print("machine architecture not supported for parsing eSELs")
619 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600620
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600621 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500622 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600623# output = proc.communicate()[0]
624 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600625
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600626 if(hasattr(args, 'fullEsel')):
627 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600628
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600629 for i in range(0, len(lines)):
630 lineParts = lines[i].split(':')
631 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
632 for term in searchTerms:
633 if(term in lineParts[0]):
634 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
635 if lines[i+1].find(':') != -1:
636 if (len(lines[i+1].split(':')[0][1:].strip())==0):
637 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600638 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600639 if((i+1) <= len(lines)):
640 i+=1
641 else:
642 i=i-1
643 break
Justin Thaler43030422018-11-08 22:50:21 -0600644 #Append the content from the next line removing the pretty display characters
645 #Finds the first colon then starts 2 characters after, then removes all whitespace
646 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500647 if(searchTerms[term] in eselParts):
648 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
649 else:
650 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500651 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600652 else:
653 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600654
655 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600656
Justin Thalere412dc22018-01-12 16:28:24 -0600657
Matt Spinler02d0dff2018-08-29 13:19:25 -0500658def getESELSeverity(esel):
659 """
660 Finds the severity type in an eSEL from the User Header section.
661 @param esel - the eSEL data
662 @return severity - e.g. 'Critical'
663 """
664
665 # everything but 1 and 2 are Critical
666 # '1': 'recovered',
667 # '2': 'predictive',
668 # '4': 'unrecoverable',
669 # '5': 'critical',
670 # '6': 'diagnostic',
671 # '7': 'symptom'
672 severities = {
673 '1': 'Informational',
674 '2': 'Warning'
675 }
676
677 try:
678 headerPosition = esel.index('55 48') # 'UH'
679 # The severity is the last byte in the 8 byte section (a byte is ' bb')
680 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
681 type = severity[0]
682 except ValueError:
683 print("Could not find severity value in UH section in eSEL")
684 type = 'x';
685
686 return severities.get(type, 'Critical')
687
688
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600689def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600690 """
691 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600692
Justin Thalere412dc22018-01-12 16:28:24 -0600693 @param events: Dictionary containing events
694 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600695 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600696 logNumList = []
697 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600698 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600699 eventsWithTimestamp = {}
700 logNum2events = {}
701 for key in events:
702 if key == 'numAlerts': continue
703 if 'callout' in key: continue
704 timestamp = (events[key]['timestamp'])
705 if timestamp not in timestampList:
706 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
707 else:
708 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
709 #map logNumbers to the event dictionary keys
710 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600711
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600712 timestampList = list(eventsWithTimestamp.keys())
713 timestampList.sort()
714 for ts in timestampList:
715 if len(eventsWithTimestamp[ts]) > 1:
716 tmplist = eventsWithTimestamp[ts]
717 tmplist.sort()
718 logNumList = logNumList + tmplist
719 else:
720 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600721
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600722 return [logNumList, eventKeyDict]
723
Justin Thalere412dc22018-01-12 16:28:24 -0600724
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600725def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600726 """
727 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600728
Justin Thalere412dc22018-01-12 16:28:24 -0600729 @param policyTable: dictionary, the policy table entries
730 @param selEntries: dictionary, the alerts retrieved from the bmc
731 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600732 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600733 eventDict = {}
734 eventNum =""
735 count = 0
736 esel = ""
737 eselParts = {}
738 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500739 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600740
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600741 'prepare and sort the event entries'
742 for key in selEntries:
743 if 'callout' not in key:
744 selEntries[key]['logNum'] = key.split('/')[-1]
745 selEntries[key]['timestamp'] = selEntries[key]['Timestamp']
746 sortedEntries = sortSELs(selEntries)
747 logNumList = sortedEntries[0]
748 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600749
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600750 for logNum in logNumList:
751 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600752 hasEsel=False
753 i2creadFail = False
754 if 'callout' in key:
755 continue
756 else:
757 messageID = str(selEntries[key]['Message'])
758 addDataPiece = selEntries[key]['AdditionalData']
759 calloutIndex = 0
760 calloutFound = False
761 for i in range(len(addDataPiece)):
762 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
763 calloutIndex = i
764 calloutFound = True
765 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
766 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
767 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500768
769 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
770
771 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
772 if (messageID + '||' + fruCallout) not in policyTable:
773 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
774 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
775 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
776 fruCallout = 'FSI'
777 else:
778 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500779 calloutFound = True
780 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
781 if not calloutFound:
782 fruCallout = 'GPIO'
783 calloutFound = True
784 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
785 if not calloutFound:
786 fruCallout = "I2C"
787 calloutFound = True
788 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
789 if not calloutFound:
790 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600791 calloutFound = True
792 if("ESEL" in addDataPiece[i]):
793 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500794 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600795 if args.devdebug:
796 eselParts = parseESEL(args, esel)
797 hasEsel=True
798 if("GPU" in addDataPiece[i]):
799 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
800 calloutFound = True
801 if("PROCEDURE" in addDataPiece[i]):
802 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
803 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600804 if("RAIL_NAME" in addDataPiece[i]):
805 calloutFound=True
806 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
807 if("INPUT_NAME" in addDataPiece[i]):
808 calloutFound=True
809 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
810 if("SENSOR_TYPE" in addDataPiece[i]):
811 calloutFound=True
812 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600813
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600814 if(calloutFound):
Justin Thaler22b1bb52018-03-15 13:31:32 -0500815 if fruCallout != "":
816 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -0500817
818 # Also use the severity for hostboot errors
819 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
820 policyKey += '||' + eselSeverity
821
822 # if not in the table, fall back to the original key
823 if policyKey not in policyTable:
824 policyKey = policyKey.replace('||'+eselSeverity, '')
825
Justin Thalere34c43a2018-05-25 19:37:55 -0500826 if policyKey not in policyTable:
827 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -0500828 else:
829 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600830 else:
831 policyKey = messageID
832 event = {}
833 eventNum = str(count)
834 if policyKey in policyTable:
835 for pkey in policyTable[policyKey]:
836 if(type(policyTable[policyKey][pkey])== bool):
837 event[pkey] = boolToString(policyTable[policyKey][pkey])
838 else:
839 if (i2creadFail and pkey == 'Message'):
840 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
841 else:
842 event[pkey] = policyTable[policyKey][pkey]
843 event['timestamp'] = selEntries[key]['Timestamp']
844 event['resolved'] = bool(selEntries[key]['Resolved'])
845 if(hasEsel):
846 if args.devdebug:
847 event['eselParts'] = eselParts
848 event['raweSEL'] = esel
849 event['logNum'] = key.split('/')[-1]
850 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600851
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600852 else:
853 severity = str(selEntries[key]['Severity']).split('.')[-1]
854 if severity == 'Error':
855 severity = 'Critical'
856 eventDict['event'+eventNum] = {}
857 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
858 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
859 eventDict['event' + eventNum]['Severity'] = severity
860 if(hasEsel):
861 if args.devdebug:
862 eventDict['event' +eventNum]['eselParts'] = eselParts
863 eventDict['event' +eventNum]['raweSEL'] = esel
864 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
865 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600866 count += 1
867 return eventDict
868
869
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600870def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600871 """
872 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600873
Justin Thalere412dc22018-01-12 16:28:24 -0600874 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600875 @return:
876 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600877 activeAlerts = []
878 historyAlerts = []
879 sortedEntries = sortSELs(events)
880 logNumList = sortedEntries[0]
881 eventKeyDict = sortedEntries[1]
882 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
883 if(args.devdebug):
884 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
885 keylist.append('eSEL')
886 else:
887 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
888 for log in logNumList:
889 selDict = {}
890 alert = events[eventKeyDict[str(log)]]
891 if('error' in alert):
892 selDict['Entry'] = alert['logNum']
893 selDict['ID'] = 'Unknown'
894 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
895 msg = alert['error']
896 polMsg = msg.split("policy table:")[0]
897 msg = msg.split("policy table:")[1]
898 msgPieces = msg.split("||")
899 err = msgPieces[0]
900 if(err.find("org.open_power.")!=-1):
901 err = err.split("org.open_power.")[1]
902 elif(err.find("xyz.openbmc_project.")!=-1):
903 err = err.split("xyz.openbmc_project.")[1]
904 else:
905 err = msgPieces[0]
906 callout = ""
907 if len(msgPieces) >1:
908 callout = msgPieces[1]
909 if(callout.find("/org/open_power/")!=-1):
910 callout = callout.split("/org/open_power/")[1]
911 elif(callout.find("/xyz/openbmc_project/")!=-1):
912 callout = callout.split("/xyz/openbmc_project/")[1]
913 else:
914 callout = msgPieces[1]
915 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600916 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600917 selDict['Severity'] = alert['Severity']
918 else:
919 selDict['Entry'] = alert['logNum']
920 selDict['ID'] = alert['CommonEventID']
921 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600922 selDict['Message'] = alert['Message']
923 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600924 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600925
926
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600927 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
928 if ('eselParts' in alert and args.devdebug):
929 eselOutput = ""
930 for item in eselOrder:
931 if item in alert['eselParts']:
932 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
933 selDict['eSEL'] = eselOutput
934 else:
935 if args.devdebug:
936 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600937
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600938 if not alert['resolved']:
939 activeAlerts.append(selDict)
940 else:
941 historyAlerts.append(selDict)
942 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600943 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
944
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600945 output = ""
946 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600947 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600948 output +="----Active Alerts----\n"
949 for i in range(0, len(colNames)):
950 if i!=0: row =row + "| "
951 row = row + colNames[i].ljust(colWidth[i])
952 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600953
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600954 for i in range(0,len(activeAlerts)):
955 row = ""
956 for j in range(len(activeAlerts[i])):
957 if (j != 0): row = row + "| "
958 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
959 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600960
961 if(len(historyAlerts)>0):
962 row = ""
963 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600964 for i in range(len(colNames)):
965 if i!=0: row =row + "| "
966 row = row + colNames[i].ljust(colWidth[i])
967 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600968
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600969 for i in range(0, len(historyAlerts)):
970 row = ""
971 for j in range(len(historyAlerts[i])):
972 if (j != 0): row = row + "| "
973 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
974 output += row + "\n"
975# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600976 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600977
Justin Thalere412dc22018-01-12 16:28:24 -0600978
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600979def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600980 """
981 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600982
Justin Thalere412dc22018-01-12 16:28:24 -0600983 @param host: string, the hostname or IP address of the bmc
984 @param args: contains additional arguments used by the fru sub command
985 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600986 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
987 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600988 if(args.policyTableLoc is None):
989 if os.path.exists('policyTable.json'):
990 ptableLoc = "policyTable.json"
991 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
992 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
993 else:
994 ptableLoc = 'lib/policyTable.json'
995 else:
996 ptableLoc = args.policyTableLoc
997 policyTable = loadPolicyTable(ptableLoc)
998 rawselEntries = ""
999 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1000 if os.path.exists(args.fileloc):
1001 with open(args.fileloc, 'r') as selFile:
1002 selLines = selFile.readlines()
1003 rawselEntries = ''.join(selLines)
1004 else:
1005 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001006 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001007 else:
1008 rawselEntries = sel(host, args, session)
1009 loadFailed = False
1010 try:
1011 selEntries = json.loads(rawselEntries)
1012 except ValueError:
1013 loadFailed = True
1014 if loadFailed:
1015 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1016 #need to load json twice as original content was string escaped a second time
1017 selEntries = json.loads(json.loads(cleanSels))
1018 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001019
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001020 if 'description' in selEntries:
1021 if(args.json):
1022 return("{\n\t\"numAlerts\": 0\n}")
1023 else:
1024 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001025
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001026 else:
1027 if(len(policyTable)>0):
1028 events = parseAlerts(policyTable, selEntries, args)
1029 if(args.json):
1030 events["numAlerts"] = len(events)
1031 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1032 return retValue
1033 elif(hasattr(args, 'fullSel')):
1034 return events
1035 else:
1036 #get log numbers to order event entries sequentially
1037 return selDisplay(events, args)
1038 else:
1039 if(args.json):
1040 return selEntries
1041 else:
1042 print("error: Policy Table not found.")
1043 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001044
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001045def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001046 """
1047 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001048
Justin Thalere412dc22018-01-12 16:28:24 -06001049 @param host: string, the hostname or IP address of the bmc
1050 @param args: contains additional arguments used by the fru sub command
1051 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001052 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1053 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001054 return(sel(host, args, session))
1055
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001056
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001057def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001058 """
1059 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001060
Justin Thalere412dc22018-01-12 16:28:24 -06001061 @param host: string, the hostname or IP address of the bmc
1062 @param args: contains additional arguments used by the fru sub command
1063 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001064 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1065 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001066 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001067 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001068
Justin Thalere412dc22018-01-12 16:28:24 -06001069 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001070 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001071 except(requests.exceptions.Timeout):
1072 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001073 if res.status_code == 200:
1074 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1075 else:
1076 print("Unable to clear the logs, trying to clear 1 at a time")
1077 sels = json.loads(sel(host, args, session))['data']
1078 for key in sels:
1079 if 'callout' not in key:
1080 logNum = key.split('/')[-1]
1081 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1082 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001083 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001084 except(requests.exceptions.Timeout):
1085 return connectionErrHandler(args.json, "Timeout", None)
1086 sys.exit(1)
1087 except(requests.exceptions.ConnectionError) as err:
1088 return connectionErrHandler(args.json, "ConnectionError", err)
1089 sys.exit(1)
1090 return ('Sel clearing complete')
1091
1092def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001093 """
1094 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001095
Justin Thalere412dc22018-01-12 16:28:24 -06001096 @param host: string, the hostname or IP address of the bmc
1097 @param args: contains additional arguments used by the fru sub command
1098 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001099 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1100 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001101 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001102 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001103 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001104 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001105 except(requests.exceptions.Timeout):
1106 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001107 if res.status_code == 200:
1108 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1109 else:
1110 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001111
Justin Thalere412dc22018-01-12 16:28:24 -06001112def selResolveAll(host, args, session):
1113 """
1114 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001115
Justin Thalere412dc22018-01-12 16:28:24 -06001116 @param host: string, the hostname or IP address of the bmc
1117 @param args: contains additional arguments used by the fru sub command
1118 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001119 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1120 """
Justin Thalere412dc22018-01-12 16:28:24 -06001121 rawselEntries = sel(host, args, session)
1122 loadFailed = False
1123 try:
1124 selEntries = json.loads(rawselEntries)
1125 except ValueError:
1126 loadFailed = True
1127 if loadFailed:
1128 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1129 #need to load json twice as original content was string escaped a second time
1130 selEntries = json.loads(json.loads(cleanSels))
1131 selEntries = selEntries['data']
1132
1133 if 'description' in selEntries:
1134 if(args.json):
1135 return("{\n\t\"selsResolved\": 0\n}")
1136 else:
1137 return("No log entries found")
1138 else:
1139 d = vars(args)
1140 successlist = []
1141 failedlist = []
1142 for key in selEntries:
1143 if 'callout' not in key:
1144 d['selNum'] = key.split('/')[-1]
1145 resolved = selSetResolved(host,args,session)
1146 if 'Sel entry' in resolved:
1147 successlist.append(d['selNum'])
1148 else:
1149 failedlist.append(d['selNum'])
1150 output = ""
1151 successlist.sort()
1152 failedlist.sort()
1153 if len(successlist)>0:
1154 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1155 if len(failedlist)>0:
1156 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1157 return output
1158
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001159def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001160 """
1161 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001162
Justin Thalere412dc22018-01-12 16:28:24 -06001163 @param host: string, the hostname or IP address of the bmc
1164 @param args: contains additional arguments used by the fru sub command
1165 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001166 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1167 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001168 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001169 if checkFWactivation(host, args, session):
1170 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001171 print("Attempting to Power on...:")
1172 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001173 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001174 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001175 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001176 except(requests.exceptions.Timeout):
1177 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001178 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001179 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001180 if checkFWactivation(host, args, session):
1181 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001182 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001183 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001184 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001185 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001186 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001187 except(requests.exceptions.Timeout):
1188 return(connectionErrHandler(args.json, "Timeout", None))
1189 return res.text
1190 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001191 if checkFWactivation(host, args, session):
1192 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001193 print("Attempting to Power off immediately...:")
1194 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001195 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1196 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001197 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001198 except(requests.exceptions.Timeout):
1199 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001200 return res.text
1201 elif(args.powcmd == 'status'):
1202 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001203 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001204 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001205 except(requests.exceptions.Timeout):
1206 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001207 chassisState = json.loads(res.text)['data'].split('.')[-1]
1208 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001209 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001210 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001211 except(requests.exceptions.Timeout):
1212 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001213 hostState = json.loads(res.text)['data'].split('.')[-1]
1214 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001215 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001216 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001217 except(requests.exceptions.Timeout):
1218 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001219 bmcState = json.loads(res.text)['data'].split('.')[-1]
1220 if(args.json):
1221 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1222 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1223 else:
1224 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1225 else:
1226 return "Invalid chassis power command"
1227
Justin Thalere412dc22018-01-12 16:28:24 -06001228
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001229def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001230 """
1231 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001232
Justin Thalere412dc22018-01-12 16:28:24 -06001233 @param host: string, the hostname or IP address of the bmc
1234 @param args: contains additional arguments used by the fru sub command
1235 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001236 @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 -06001237 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001238 if(args.identcmd == 'on'):
1239 print("Attempting to turn identify light on...:")
1240 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001241 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001242 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001243 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001244 except(requests.exceptions.Timeout):
1245 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001246 return res.text
1247 elif(args.identcmd == 'off'):
1248 print("Attempting to turn identify light off...:")
1249 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001250 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001251 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001252 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
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 == 'status'):
1257 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001258 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001259 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001260 except(requests.exceptions.Timeout):
1261 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001262 status = json.loads(res.text)['data']
1263 if(args.json):
1264 return status
1265 else:
1266 if status['Asserted'] == 0:
1267 return "Identify light is off"
1268 else:
1269 return "Identify light is blinking"
1270 else:
1271 return "Invalid chassis identify command"
1272
Justin Thalere412dc22018-01-12 16:28:24 -06001273
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001274def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001275 """
1276 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001277
Justin Thalere412dc22018-01-12 16:28:24 -06001278 @param host: string, the hostname or IP address of the bmc
1279 @param args: contains additional arguments used by the fru sub command
1280 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001281 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1282 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001283 if(hasattr(args, 'powcmd')):
1284 result = chassisPower(host,args,session)
1285 elif(hasattr(args, 'identcmd')):
1286 result = chassisIdent(host, args, session)
1287 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001288 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001289 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001290
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001291def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001292 """
1293 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001294
Justin Thalere412dc22018-01-12 16:28:24 -06001295 @param host: string, the hostname or IP address of the bmc
1296 @param args: contains additional arguments used by the collectServiceData sub command
1297 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001298 @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 -06001299 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001300 dumpNum = args.dumpNum
1301 if (args.dumpSaveLoc is not None):
1302 saveLoc = args.dumpSaveLoc
1303 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001304 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001305 url ='https://'+host+'/download/dump/' + str(dumpNum)
1306 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001307 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=30)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001308 if (args.dumpSaveLoc is not None):
1309 if os.path.exists(saveLoc):
1310 if saveLoc[-1] != os.path.sep:
1311 saveLoc = saveLoc + os.path.sep
1312 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001313
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001314 else:
1315 return 'Invalid save location specified'
1316 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001317 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001318
1319 with open(filename, 'wb') as f:
1320 for chunk in r.iter_content(chunk_size =1024):
1321 if chunk:
1322 f.write(chunk)
1323 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001324
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001325 except(requests.exceptions.Timeout):
1326 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001327
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001328 except(requests.exceptions.ConnectionError) as err:
1329 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001330
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001331def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001332 """
1333 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001334
Justin Thalere412dc22018-01-12 16:28:24 -06001335 @param host: string, the hostname or IP address of the bmc
1336 @param args: contains additional arguments used by the collectServiceData sub command
1337 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001338 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1339 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001340 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1341 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001342 r = session.get(url, headers=jsonHeader, verify=False, timeout=20)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001343 dumpList = json.loads(r.text)
1344 return r.text
1345 except(requests.exceptions.Timeout):
1346 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001347
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001348 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001349 return connectionErrHandler(args.json, "ConnectionError", err)
1350
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001351def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001352 """
1353 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001354
Justin Thalere412dc22018-01-12 16:28:24 -06001355 @param host: string, the hostname or IP address of the bmc
1356 @param args: contains additional arguments used by the collectServiceData sub command
1357 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001358 @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 -06001359 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001360 dumpList = []
1361 successList = []
1362 failedList = []
1363 if args.dumpNum is not None:
1364 if isinstance(args.dumpNum, list):
1365 dumpList = args.dumpNum
1366 else:
1367 dumpList.append(args.dumpNum)
1368 for dumpNum in dumpList:
1369 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1370 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001371 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=30)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001372 if r.status_code == 200:
1373 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001374 else:
1375 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001376 except(requests.exceptions.Timeout):
1377 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001378 except(requests.exceptions.ConnectionError) as err:
1379 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001380 output = "Successfully deleted dumps: " + ', '.join(successList)
1381 if(len(failedList)>0):
1382 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1383 return output
1384 else:
1385 return 'You must specify an entry number to delete'
1386
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001387def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001388 """
1389 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001390
Justin Thalere412dc22018-01-12 16:28:24 -06001391 @param host: string, the hostname or IP address of the bmc
1392 @param args: contains additional arguments used by the collectServiceData sub command
1393 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001394 @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 -06001395 """
1396 dumpResp = bmcDumpList(host, args, session)
1397 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1398 return dumpResp
1399 dumpList = json.loads(dumpResp)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001400 d = vars(args)
1401 dumpNums = []
1402 for dump in dumpList:
1403 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1404 dumpNums.append(int(dump.strip().split('/')[-1]))
1405 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001406
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001407 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001408
Justin Thalere412dc22018-01-12 16:28:24 -06001409
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001410def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001411 """
1412 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001413
Justin Thalere412dc22018-01-12 16:28:24 -06001414 @param host: string, the hostname or IP address of the bmc
1415 @param args: contains additional arguments used by the collectServiceData sub command
1416 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001417 @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 -06001418 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001419 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1420 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001421 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=30)
Matt Spinlereae05b02019-01-24 12:59:34 -06001422 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001423 return ('Dump successfully created')
1424 else:
1425 return ('Failed to create dump')
1426 except(requests.exceptions.Timeout):
1427 return connectionErrHandler(args.json, "Timeout", None)
1428 except(requests.exceptions.ConnectionError) as err:
1429 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001430
1431
1432
Justin Thalere412dc22018-01-12 16:28:24 -06001433
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001434def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001435 """
1436 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001437
Justin Thalere412dc22018-01-12 16:28:24 -06001438 @param host: string, the hostname or IP address of the bmc
1439 @param args: contains additional arguments used by the collectServiceData sub command
1440 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001441 @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 -06001442 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001443
Justin Thaler22b1bb52018-03-15 13:31:32 -05001444 global toolVersion
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001445 #create a bmc dump
1446 dumpcount = len(json.loads(bmcDumpList(host, args, session))['data'])
1447 try:
1448 dumpcreated = bmcDumpCreate(host, args, session)
1449 except Exception as e:
1450 print('failed to create a bmc dump')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001451
1452
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001453 #Collect Inventory
1454 try:
1455 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05001456 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001457 os.makedirs(myDir)
1458 filelist = []
1459 frulist = fruPrint(host, args, session)
1460 with open(myDir +'/inventory.txt', 'w') as f:
1461 f.write(frulist)
1462 print("Inventory collected and stored in " + myDir + "/inventory.txt")
1463 filelist.append(myDir+'/inventory.txt')
1464 except Exception as e:
1465 print("Failed to collect inventory")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001466
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001467 #Read all the sensor and OCC status
1468 try:
1469 sensorReadings = sensor(host, args, session)
1470 with open(myDir +'/sensorReadings.txt', 'w') as f:
1471 f.write(sensorReadings)
1472 print("Sensor readings collected and stored in " +myDir + "/sensorReadings.txt")
1473 filelist.append(myDir+'/sensorReadings.txt')
1474 except Exception as e:
1475 print("Failed to collect sensor readings")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001476
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001477 #Collect all of the LEDs status
1478 try:
1479 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
Matt Spinler220c3c42019-01-04 15:09:29 -06001480 leds = session.get(url, headers=jsonHeader, verify=False, timeout=20)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001481 with open(myDir +'/ledStatus.txt', 'w') as f:
1482 f.write(leds.text)
1483 print("System LED status collected and stored in "+myDir +"/ledStatus.txt")
1484 filelist.append(myDir+'/ledStatus.txt')
1485 except Exception as e:
1486 print("Failed to collect LED status")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001487
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001488 #Collect the bmc logs
1489 try:
1490 sels = selPrint(host,args,session)
1491 with open(myDir +'/SELshortlist.txt', 'w') as f:
1492 f.write(str(sels))
1493 print("sel short list collected and stored in "+myDir +"/SELshortlist.txt")
1494 filelist.append(myDir+'/SELshortlist.txt')
1495 time.sleep(2)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001496
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001497 d = vars(args)
1498 d['json'] = True
1499 d['fullSel'] = True
1500 parsedfullsels = json.loads(selPrint(host, args, session))
1501 d['fullEsel'] = True
1502 sortedSELs = sortSELs(parsedfullsels)
1503 with open(myDir +'/parsedSELs.txt', 'w') as f:
1504 for log in sortedSELs[0]:
1505 esel = ""
1506 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1507 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001508 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
1509 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001510 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
1511 if(args.devdebug and esel != ""):
1512 f.write(parseESEL(args, esel))
1513 print("fully parsed sels collected and stored in "+myDir +"/parsedSELs.txt")
1514 filelist.append(myDir+'/parsedSELs.txt')
1515 except Exception as e:
1516 print("Failed to collect system event logs")
1517 print(e)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001518
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001519 #collect RAW bmc enumeration
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001520 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001521 url="https://"+host+"/xyz/openbmc_project/enumerate"
1522 print("Attempting to get a full BMC enumeration")
Matt Spinler220c3c42019-01-04 15:09:29 -06001523 fullDump = session.get(url, headers=jsonHeader, verify=False, timeout=120)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001524 with open(myDir +'/bmcFullRaw.txt', 'w') as f:
1525 f.write(fullDump.text)
1526 print("RAW BMC data collected and saved into "+myDir +"/bmcFullRaw.txt")
1527 filelist.append(myDir+'/bmcFullRaw.txt')
1528 except Exception as e:
1529 print("Failed to collect bmc full enumeration")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001530
1531 #collect the dump files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001532 waitingForNewDump = True
1533 count = 0;
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001534 while(waitingForNewDump):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001535 dumpList = json.loads(bmcDumpList(host, args, session))['data']
1536 if len(dumpList) > dumpcount:
1537 waitingForNewDump = False
1538 break;
1539 elif(count>30):
1540 print("Timed out waiting for bmc to make a new dump file. Dump space may be full.")
1541 break;
1542 else:
1543 time.sleep(2)
1544 count += 1
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001545 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001546 print('Collecting bmc dump files')
1547 d['dumpSaveLoc'] = myDir
1548 dumpList = json.loads(bmcDumpList(host, args, session))['data']
1549 for dump in dumpList:
1550 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
1551 d['dumpNum'] = int(dump.strip().split('/')[-1])
1552 print('retrieving dump file ' + str(d['dumpNum']))
1553 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
1554 filelist.append(filename)
1555 time.sleep(2)
1556 except Exception as e:
1557 print("Failed to collect bmc dump files")
1558 print(e)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001559
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001560 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001561 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05001562 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001563 zf = zipfile.ZipFile(myDir+'/' + filename, 'w')
1564 for myfile in filelist:
1565 zf.write(myfile, os.path.basename(myfile))
1566 zf.close()
1567 except Exception as e:
1568 print("Failed to create zip file with collected information")
1569 return "data collection complete"
1570
Justin Thalere412dc22018-01-12 16:28:24 -06001571
1572def healthCheck(host, args, session):
1573 """
1574 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001575
Justin Thalere412dc22018-01-12 16:28:24 -06001576 @param host: string, the hostname or IP address of the bmc
1577 @param args: contains additional arguments used by the bmc sub command
1578 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001579 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1580 """
Justin Thalere412dc22018-01-12 16:28:24 -06001581 #check fru status and get as json to easily work through
1582 d = vars(args)
1583 useJson = d['json']
1584 d['json'] = True
1585 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001586
Justin Thalere412dc22018-01-12 16:28:24 -06001587 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001588
Justin Thalere412dc22018-01-12 16:28:24 -06001589 hwStatus= "OK"
1590 performanceStatus = "OK"
1591 for key in frus:
1592 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
1593 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05001594 if("power_supply" in key or "powersupply" in key):
1595 gpuCount =0
1596 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06001597 if "gv100card" in comp:
1598 gpuCount +=1
1599 if gpuCount > 4:
1600 hwStatus = "Critical"
1601 performanceStatus="Degraded"
1602 break;
1603 elif("fan" in key):
1604 hwStatus = "Degraded"
1605 else:
1606 performanceStatus = "Degraded"
1607 if useJson:
1608 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
1609 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1610 else:
1611 output = ("Hardware Status: " + hwStatus +
1612 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001613
1614
Justin Thalere412dc22018-01-12 16:28:24 -06001615 #SW407886: Clear the duplicate entries
1616 #collect the dups
1617 d['devdebug'] = False
1618 sels = json.loads(selPrint(host, args, session))
1619 logNums2Clr = []
1620 oldestLogNum={"logNum": "bogus" ,"key" : ""}
1621 count = 0
1622 if sels['numAlerts'] > 0:
1623 for key in sels:
1624 if "numAlerts" in key:
1625 continue
1626 try:
1627 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
1628 count += 1
1629 if count > 1:
1630 #preserve first occurrence
1631 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
1632 oldestLogNum['key']=key
1633 oldestLogNum['logNum'] = sels[key]['logNum']
1634 else:
1635 oldestLogNum['key']=key
1636 oldestLogNum['logNum'] = sels[key]['logNum']
1637 logNums2Clr.append(sels[key]['logNum'])
1638 except KeyError:
1639 continue
1640 if(count >0):
1641 logNums2Clr.remove(oldestLogNum['logNum'])
1642 #delete the dups
1643 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06001644 data = "{\"data\": [] }"
1645 for logNum in logNums2Clr:
1646 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1647 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001648 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001649 except(requests.exceptions.Timeout):
1650 deleteFailed = True
1651 except(requests.exceptions.ConnectionError) as err:
1652 deleteFailed = True
1653 #End of defect resolve code
1654 d['json'] = useJson
1655 return output
1656
1657
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001658
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001659def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001660 """
1661 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001662
Justin Thalere412dc22018-01-12 16:28:24 -06001663 @param host: string, the hostname or IP address of the bmc
1664 @param args: contains additional arguments used by the bmc sub command
1665 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001666 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1667 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001668 if(args.type is not None):
1669 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06001670 if(args.info):
1671 return "Not implemented at this time"
1672
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001673
Justin Thalere412dc22018-01-12 16:28:24 -06001674
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001675def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001676 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001677 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
1678
Justin Thalere412dc22018-01-12 16:28:24 -06001679 @param host: string, the hostname or IP address of the bmc
1680 @param args: contains additional arguments used by the bmcReset sub command
1681 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001682 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1683 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001684 if checkFWactivation(host, args, session):
1685 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001686 if(args.type == "warm"):
1687 print("\nAttempting to reboot the BMC...:")
1688 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001689 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Matt Spinler220c3c42019-01-04 15:09:29 -06001690 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=20)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001691 return res.text
1692 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06001693 print("\nAttempting to reboot the BMC...:")
1694 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001695 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Matt Spinler220c3c42019-01-04 15:09:29 -06001696 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=20)
Justin Thalere412dc22018-01-12 16:28:24 -06001697 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001698 else:
1699 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06001700
1701def gardClear(host, args, session):
1702 """
1703 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001704
Justin Thalere412dc22018-01-12 16:28:24 -06001705 @param host: string, the hostname or IP address of the bmc
1706 @param args: contains additional arguments used by the gardClear sub command
1707 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001708 """
Justin Thalere412dc22018-01-12 16:28:24 -06001709 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06001710 data = '{"data":[]}'
1711 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001712
Matt Spinler220c3c42019-01-04 15:09:29 -06001713 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001714 if res.status_code == 404:
1715 return "Command not supported by this firmware version"
1716 else:
1717 return res.text
1718 except(requests.exceptions.Timeout):
1719 return connectionErrHandler(args.json, "Timeout", None)
1720 except(requests.exceptions.ConnectionError) as err:
1721 return connectionErrHandler(args.json, "ConnectionError", err)
1722
1723def activateFWImage(host, args, session):
1724 """
1725 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001726
Justin Thalere412dc22018-01-12 16:28:24 -06001727 @param host: string, the hostname or IP address of the bmc
1728 @param args: contains additional arguments used by the fwflash sub command
1729 @param session: the active session to use
1730 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001731 """
Justin Thalere412dc22018-01-12 16:28:24 -06001732 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001733
Justin Thalere412dc22018-01-12 16:28:24 -06001734 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06001735 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1736 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001737 resp = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001738 except(requests.exceptions.Timeout):
1739 return connectionErrHandler(args.json, "Timeout", None)
1740 except(requests.exceptions.ConnectionError) as err:
1741 return connectionErrHandler(args.json, "ConnectionError", err)
1742 existingSoftware = json.loads(resp.text)['data']
1743 altVersionID = ''
1744 versionType = ''
1745 imageKey = '/xyz/openbmc_project/software/'+fwID
1746 if imageKey in existingSoftware:
1747 versionType = existingSoftware[imageKey]['Purpose']
1748 for key in existingSoftware:
1749 if imageKey == key:
1750 continue
1751 if 'Purpose' in existingSoftware[key]:
1752 if versionType == existingSoftware[key]['Purpose']:
1753 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001754
1755
1756
1757
Justin Thalere412dc22018-01-12 16:28:24 -06001758 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
1759 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001760 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06001761 data1 = "{\"data\": 1 }"
1762 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001763 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
1764 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001765 except(requests.exceptions.Timeout):
1766 return connectionErrHandler(args.json, "Timeout", None)
1767 except(requests.exceptions.ConnectionError) as err:
1768 return connectionErrHandler(args.json, "ConnectionError", err)
1769 if(not args.json):
1770 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001771 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 -06001772 else:
1773 return "Firmware activation failed."
1774 else:
1775 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05001776
1777def activateStatus(host, args, session):
1778 if checkFWactivation(host, args, session):
1779 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
1780 else:
1781 return("No firmware activations are pending")
1782
1783def extractFWimage(path, imageType):
1784 """
1785 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001786
Justin Thaler22b1bb52018-03-15 13:31:32 -05001787 @param path: the path and file name of the firmware image
1788 @param imageType: The type of image the user is trying to flash. Host or BMC
1789 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001790 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001791 f = tempfile.TemporaryFile()
1792 tmpDir = tempfile.gettempdir()
1793 newImageID = ""
1794 if os.path.exists(path):
1795 try:
1796 imageFile = tarfile.open(path,'r')
1797 contents = imageFile.getmembers()
1798 for tf in contents:
1799 if 'MANIFEST' in tf.name:
1800 imageFile.extract(tf.name, path=tmpDir)
1801 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
1802 for line in imageInfo:
1803 if 'purpose' in line:
1804 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001805 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001806 print('The specified image is not for ' + imageType)
1807 print('Please try again with the image for ' + imageType)
1808 return ""
1809 if 'version' == line.split('=')[0]:
1810 version = line.split('=')[1].strip().encode('utf-8')
1811 m = hashlib.sha512()
1812 m.update(version)
1813 newImageID = m.hexdigest()[:8]
1814 break
1815 try:
1816 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
1817 except OSError:
1818 pass
1819 return newImageID
1820 except tarfile.ExtractError as e:
1821 print('Unable to extract information from the firmware file.')
1822 print('Ensure you have write access to the directory: ' + tmpDir)
1823 return newImageID
1824 except tarfile.TarError as e:
1825 print('This is not a valid firmware file.')
1826 return newImageID
1827 print("This is not a valid firmware file.")
1828 return newImageID
1829 else:
1830 print('The filename and path provided are not valid.')
1831 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001832
Justin Thaler22b1bb52018-03-15 13:31:32 -05001833def getAllFWImageIDs(fwInvDict):
1834 """
1835 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001836
Justin Thaler22b1bb52018-03-15 13:31:32 -05001837 @param fwInvDict: the dictionary to search for FW image IDs
1838 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001839 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001840 idList = []
1841 for key in fwInvDict:
1842 if 'Version' in fwInvDict[key]:
1843 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001844 return idList
1845
Justin Thalere412dc22018-01-12 16:28:24 -06001846def fwFlash(host, args, session):
1847 """
1848 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001849
Justin Thalere412dc22018-01-12 16:28:24 -06001850 @param host: string, the hostname or IP address of the bmc
1851 @param args: contains additional arguments used by the fwflash sub command
1852 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001853 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05001854 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06001855 if(args.type == 'bmc'):
1856 purp = 'BMC'
1857 else:
1858 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001859
1860 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05001861 d['powcmd'] = 'status'
1862 powerstate = chassisPower(host, args, session)
1863 if 'Chassis Power State: On' in powerstate:
1864 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001865
Justin Thaler22b1bb52018-03-15 13:31:32 -05001866 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06001867 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1868 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001869 resp = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thalere412dc22018-01-12 16:28:24 -06001870 except(requests.exceptions.Timeout):
1871 return connectionErrHandler(args.json, "Timeout", None)
1872 except(requests.exceptions.ConnectionError) as err:
1873 return connectionErrHandler(args.json, "ConnectionError", err)
1874 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001875
Justin Thaler22b1bb52018-03-15 13:31:32 -05001876 #Extract the tar and get information from the manifest file
1877 newversionID = extractFWimage(args.fileloc, purp)
1878 if newversionID == "":
1879 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001880
1881
Justin Thaler22b1bb52018-03-15 13:31:32 -05001882 #check if the new image is already on the bmc
1883 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001884
Justin Thaler22b1bb52018-03-15 13:31:32 -05001885 #upload the file
1886 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06001887 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001888 url="https://"+host+"/upload/image"
1889 data=open(args.fileloc,'rb').read()
1890 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06001891 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001892 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06001893 except(requests.exceptions.Timeout):
1894 return connectionErrHandler(args.json, "Timeout", None)
1895 except(requests.exceptions.ConnectionError) as err:
1896 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001897 if resp.status_code != 200:
1898 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06001899 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001900 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001901
Justin Thaler22b1bb52018-03-15 13:31:32 -05001902 #verify bmc processed the image
1903 software ={}
1904 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001905 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
1906 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001907 resp = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001908 except(requests.exceptions.Timeout):
1909 return connectionErrHandler(args.json, "Timeout", None)
1910 except(requests.exceptions.ConnectionError) as err:
1911 return connectionErrHandler(args.json, "ConnectionError", err)
1912 software = json.loads(resp.text)['data']
1913 #check if bmc is done processing the new image
1914 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06001915 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05001916 else:
1917 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001918
Justin Thaler22b1bb52018-03-15 13:31:32 -05001919 #activate the new image
1920 print("Activating new image: "+newversionID)
1921 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001922 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05001923 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001924 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001925 except(requests.exceptions.Timeout):
1926 return connectionErrHandler(args.json, "Timeout", None)
1927 except(requests.exceptions.ConnectionError) as err:
1928 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001929
Justin Thaler22b1bb52018-03-15 13:31:32 -05001930 #wait for the activation to complete, timeout after ~1 hour
1931 i=0
1932 while i < 360:
1933 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001934 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05001935 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06001936 resp = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Justin Thaler22b1bb52018-03-15 13:31:32 -05001937 except(requests.exceptions.Timeout):
1938 return connectionErrHandler(args.json, "Timeout", None)
1939 except(requests.exceptions.ConnectionError) as err:
1940 return connectionErrHandler(args.json, "ConnectionError", err)
1941 fwInfo = json.loads(resp.text)['data']
1942 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
1943 print('')
1944 break
1945 else:
1946 sys.stdout.write('.')
1947 sys.stdout.flush()
1948 time.sleep(10) #check every 10 seconds
1949 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
1950 else:
1951 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001952
Justin Thaler22b1bb52018-03-15 13:31:32 -05001953 d['imageID'] = newversionID
1954 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06001955
Justin Thaler3d71d402018-07-24 14:35:39 -05001956def getFWInventoryAttributes(rawFWInvItem, ID):
1957 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001958 gets and lists all of the firmware in the system.
1959
Justin Thaler3d71d402018-07-24 14:35:39 -05001960 @return: returns a dictionary containing the image attributes
1961 """
1962 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
1963 pendingActivation = ""
1964 if reqActivation == "None":
1965 pendingActivation = "No"
1966 else:
1967 pendingActivation = "Yes"
1968 firmwareAttr = {ID: {
1969 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
1970 "Version": rawFWInvItem["Version"],
1971 "RequestedActivation": pendingActivation,
1972 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001973
Justin Thaler3d71d402018-07-24 14:35:39 -05001974 if "ExtendedVersion" in rawFWInvItem:
1975 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001976 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05001977 firmwareAttr[ID]['ExtendedVersion'] = ""
1978 return firmwareAttr
1979
1980def parseFWdata(firmwareDict):
1981 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001982 creates a dictionary with parsed firmware data
1983
Justin Thaler3d71d402018-07-24 14:35:39 -05001984 @return: returns a dictionary containing the image attributes
1985 """
1986 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
1987 for key in firmwareDict['data']:
1988 #check for valid endpoint
1989 if "Purpose" in firmwareDict['data'][key]:
1990 id = key.split('/')[-1]
1991 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
1992 fwActivated = True
1993 else:
1994 fwActivated = False
1995 if firmwareDict['data'][key]['Priority'] == 0:
1996 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
1997 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
1998 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
1999 else:
2000 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2001 emptySections = []
2002 for key in firmwareInfoDict:
2003 if len(firmwareInfoDict[key])<=0:
2004 emptySections.append(key)
2005 for key in emptySections:
2006 del firmwareInfoDict[key]
2007 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002008
Justin Thaler3d71d402018-07-24 14:35:39 -05002009def displayFWInvenory(firmwareInfoDict, args):
2010 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002011 gets and lists all of the firmware in the system.
2012
Justin Thaler3d71d402018-07-24 14:35:39 -05002013 @return: returns a string containing all of the firmware information
2014 """
2015 output = ""
2016 if not args.json:
2017 for key in firmwareInfoDict:
2018 for subkey in firmwareInfoDict[key]:
2019 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2020 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002021 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002022 colNames = ["Purpose", "Version", "ID"]
2023 keylist = ["Purpose", "Version", "ID"]
2024 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2025 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002026 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002027 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2028 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002029 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002030 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002031
Justin Thaler3d71d402018-07-24 14:35:39 -05002032 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002033 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002034 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2035 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2036 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2037 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002038 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002039 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2040 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002041 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002042 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2043 return output
2044 else:
2045 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2046
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002047def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002048 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002049 gets and lists all of the firmware in the system.
2050
Justin Thaler3d71d402018-07-24 14:35:39 -05002051 @return: returns a string containing all of the firmware information
2052 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002053 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2054 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002055 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Justin Thaler3d71d402018-07-24 14:35:39 -05002056 except(requests.exceptions.Timeout):
2057 return(connectionErrHandler(args.json, "Timeout", None))
2058 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002059
Justin Thaler3d71d402018-07-24 14:35:39 -05002060 #sort the received information
2061 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002062
Justin Thaler3d71d402018-07-24 14:35:39 -05002063 #display the information
2064 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002065
2066
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002067def deleteFWVersion(host, args, session):
2068 """
2069 deletes a firmware version on the BMC
2070
2071 @param host: string, the hostname or IP address of the BMC
2072 @param args: contains additional arguments used by the fwflash sub command
2073 @param session: the active session to use
2074 @param fwID: the unique ID of the fw version to delete
2075 """
2076 fwID = args.versionID
2077
2078 print("Deleting version: "+fwID)
2079 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002080 data = "{\"data\": [] }"
2081
2082 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002083 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002084 except(requests.exceptions.Timeout):
2085 return(connectionErrHandler(args.json, "Timeout", None))
2086 if res.status_code == 200:
2087 return ('The firmware version has been deleted')
2088 else:
2089 return ('Unable to delete the specified firmware version')
2090
2091
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002092def restLogging(host, args, session):
2093 """
2094 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002095
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002096 @param host: string, the hostname or IP address of the bmc
2097 @param args: contains additional arguments used by the logging sub command
2098 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002099 @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 -05002100 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002101 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002102
2103 if(args.rest_logging == 'on'):
2104 data = '{"data": 1}'
2105 elif(args.rest_logging == 'off'):
2106 data = '{"data": 0}'
2107 else:
2108 return "Invalid logging rest_api command"
2109
2110 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002111 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002112 except(requests.exceptions.Timeout):
2113 return(connectionErrHandler(args.json, "Timeout", None))
2114 return res.text
2115
2116
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002117def remoteLogging(host, args, session):
2118 """
2119 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002120
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002121 @param host: string, the hostname or IP address of the bmc
2122 @param args: contains additional arguments used by the logging sub command
2123 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002124 @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 -05002125 """
2126
2127 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002128
2129 try:
2130 if(args.remote_logging == 'view'):
Matt Spinler220c3c42019-01-04 15:09:29 -06002131 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002132 elif(args.remote_logging == 'disable'):
Matt Spinler220c3c42019-01-04 15:09:29 -06002133 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=30)
2134 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=30)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002135 else:
2136 return "Invalid logging remote_logging command"
2137 except(requests.exceptions.Timeout):
2138 return(connectionErrHandler(args.json, "Timeout", None))
2139 return res.text
2140
2141
2142def remoteLoggingConfig(host, args, session):
2143 """
2144 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002145
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002146 @param host: string, the hostname or IP address of the bmc
2147 @param args: contains additional arguments used by the logging sub command
2148 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002149 @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 -05002150 """
2151
2152 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002153
2154 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002155 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=30)
2156 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=30)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002157 except(requests.exceptions.Timeout):
2158 return(connectionErrHandler(args.json, "Timeout", None))
2159 return res.text
2160
Ratan Gupta9166cd22018-10-01 18:09:40 +05302161
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002162def certificateUpdate(host, args, session):
2163 """
2164 Called by certificate management function. update server/client/authority certificates
2165 Example:
2166 certificate update server https -f cert.pem
2167 certificate update authority ldap -f Root-CA.pem
2168 certificate update client ldap -f cert.pem
2169 @param host: string, the hostname or IP address of the bmc
2170 @param args: contains additional arguments used by the certificate update sub command
2171 @param session: the active session to use
2172 """
2173
2174 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002175 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002176 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2177 data = open(args.fileloc, 'rb').read()
2178 print("Updating certificate url=" + url)
2179 try:
2180 resp = session.put(url, headers=httpHeader, data=data, verify=False)
2181 except(requests.exceptions.Timeout):
2182 return(connectionErrHandler(args.json, "Timeout", None))
2183 except(requests.exceptions.ConnectionError) as err:
2184 return connectionErrHandler(args.json, "ConnectionError", err)
2185 if resp.status_code != 200:
2186 print(resp.text)
2187 return "Failed to update the certificate"
2188 else:
2189 print("Update complete.")
2190
2191
2192def certificateDelete(host, args, session):
2193 """
2194 Called by certificate management function to delete certificate
2195 Example:
2196 certificate delete server https
2197 certificate delete authority ldap
2198 certificate delete client ldap
2199 @param host: string, the hostname or IP address of the bmc
2200 @param args: contains additional arguments used by the certificate delete sub command
2201 @param session: the active session to use
2202 """
2203
2204 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002205 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002206 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2207 print("Deleting certificate url=" + url)
2208 try:
2209 resp = session.delete(url, headers=httpHeader)
2210 except(requests.exceptions.Timeout):
2211 return(connectionErrHandler(args.json, "Timeout", None))
2212 except(requests.exceptions.ConnectionError) as err:
2213 return connectionErrHandler(args.json, "ConnectionError", err)
2214 if resp.status_code != 200:
2215 print(resp.text)
2216 return "Failed to delete the certificate"
2217 else:
2218 print("Delete complete.")
2219
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002220
Ratan Gupta9166cd22018-10-01 18:09:40 +05302221def enableLDAP(host, args, session):
2222 """
2223 Called by the ldap function. Configures LDAP.
2224
2225 @param host: string, the hostname or IP address of the bmc
2226 @param args: contains additional arguments used by the ldap subcommand
2227 @param session: the active session to use
2228 @param args.json: boolean, if this flag is set to true, the output will
2229 be provided in json format for programmatic consumption
2230 """
2231
2232 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302233 scope = {
2234 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
2235 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
2236 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
2237 }
2238
2239 serverType = {
2240 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
2241 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
2242 }
2243
2244 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
2245
2246 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002247 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=30)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302248 except(requests.exceptions.Timeout):
2249 return(connectionErrHandler(args.json, "Timeout", None))
2250 except(requests.exceptions.ConnectionError) as err:
2251 return connectionErrHandler(args.json, "ConnectionError", err)
2252
2253 return res.text
2254
2255
2256def disableLDAP(host, args, session):
2257 """
2258 Called by the ldap function. Deletes the LDAP Configuration.
2259
2260 @param host: string, the hostname or IP address of the bmc
2261 @param args: contains additional arguments used by the ldap subcommand
2262 @param session: the active session to use
2263 @param args.json: boolean, if this flag is set to true, the output
2264 will be provided in json format for programmatic consumption
2265 """
2266
2267 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
Ratan Gupta9166cd22018-10-01 18:09:40 +05302268 data = {"data": []}
2269
2270 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002271 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=30)
Ratan Gupta9166cd22018-10-01 18:09:40 +05302272 except(requests.exceptions.Timeout):
2273 return(connectionErrHandler(args.json, "Timeout", None))
2274 except(requests.exceptions.ConnectionError) as err:
2275 return connectionErrHandler(args.json, "ConnectionError", err)
2276
2277 return res.text
2278
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002279
2280def enableDHCP(host, args, session):
2281
2282 """
2283 Called by the network function. Enables DHCP.
2284
2285 @param host: string, the hostname or IP address of the bmc
2286 @param args: contains additional arguments used by the ldap subcommand
2287 args.json: boolean, if this flag is set to true, the output
2288 will be provided in json format for programmatic consumption
2289 @param session: the active session to use
2290 """
2291
2292 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2293 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002294 data = "{\"data\": 1 }"
2295 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002296 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002297 timeout=30)
2298
2299 except(requests.exceptions.Timeout):
2300 return(connectionErrHandler(args.json, "Timeout", None))
2301 except(requests.exceptions.ConnectionError) as err:
2302 return connectionErrHandler(args.json, "ConnectionError", err)
2303 if res.status_code == 403:
2304 return "The specified Interface"+"("+args.Interface+")"+\
2305 " doesn't exist"
2306
2307 return res.text
2308
2309
2310def disableDHCP(host, args, session):
2311 """
2312 Called by the network function. Disables DHCP.
2313
2314 @param host: string, the hostname or IP address of the bmc
2315 @param args: contains additional arguments used by the ldap subcommand
2316 args.json: boolean, if this flag is set to true, the output
2317 will be provided in json format for programmatic consumption
2318 @param session: the active session to use
2319 """
2320
2321 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2322 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002323 data = "{\"data\": 0 }"
2324 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002325 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002326 timeout=30)
2327 except(requests.exceptions.Timeout):
2328 return(connectionErrHandler(args.json, "Timeout", None))
2329 except(requests.exceptions.ConnectionError) as err:
2330 return connectionErrHandler(args.json, "ConnectionError", err)
2331 if res.status_code == 403:
2332 return "The specified Interface"+"("+args.Interface+")"+\
2333 " doesn't exist"
2334 return res.text
2335
2336
2337def getHostname(host, args, session):
2338
2339 """
2340 Called by the network function. Prints out the Hostname.
2341
2342 @param host: string, the hostname or IP address of the bmc
2343 @param args: contains additional arguments used by the ldap subcommand
2344 args.json: boolean, if this flag is set to true, the output
2345 will be provided in json format for programmatic consumption
2346 @param session: the active session to use
2347 """
2348
2349 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002350
2351 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002352 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002353 except(requests.exceptions.Timeout):
2354 return(connectionErrHandler(args.json, "Timeout", None))
2355 except(requests.exceptions.ConnectionError) as err:
2356 return connectionErrHandler(args.json, "ConnectionError", err)
2357
2358 return res.text
2359
2360
2361def setHostname(host, args, session):
2362 """
2363 Called by the network function. Sets the Hostname.
2364
2365 @param host: string, the hostname or IP address of the bmc
2366 @param args: contains additional arguments used by the ldap subcommand
2367 args.json: boolean, if this flag is set to true, the output
2368 will be provided in json format for programmatic consumption
2369 @param session: the active session to use
2370 """
2371
2372 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002373
2374 data = {"data": args.HostName}
2375
2376 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002377 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002378 timeout=30)
2379 except(requests.exceptions.Timeout):
2380 return(connectionErrHandler(args.json, "Timeout", None))
2381 except(requests.exceptions.ConnectionError) as err:
2382 return connectionErrHandler(args.json, "ConnectionError", err)
2383
2384 return res.text
2385
2386
2387def getDomainName(host, args, session):
2388
2389 """
2390 Called by the network function. Prints out the DomainName.
2391
2392 @param host: string, the hostname or IP address of the bmc
2393 @param args: contains additional arguments used by the ldap subcommand
2394 args.json: boolean, if this flag is set to true, the output
2395 will be provided in json format for programmatic consumption
2396 @param session: the active session to use
2397 """
2398
2399 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2400 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002401
2402 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002403 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002404 except(requests.exceptions.Timeout):
2405 return(connectionErrHandler(args.json, "Timeout", None))
2406 except(requests.exceptions.ConnectionError) as err:
2407 return connectionErrHandler(args.json, "ConnectionError", err)
2408 if res.status_code == 404:
2409 return "The specified Interface"+"("+args.Interface+")"+\
2410 " doesn't exist"
2411
2412 return res.text
2413
2414
2415def setDomainName(host, args, session):
2416 """
2417 Called by the network function. Sets the DomainName.
2418
2419 @param host: string, the hostname or IP address of the bmc
2420 @param args: contains additional arguments used by the ldap subcommand
2421 args.json: boolean, if this flag is set to true, the output
2422 will be provided in json format for programmatic consumption
2423 @param session: the active session to use
2424 """
2425
2426 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2427 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002428
2429 data = {"data": args.DomainName.split(",")}
2430
2431 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002432 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002433 timeout=30)
2434 except(requests.exceptions.Timeout):
2435 return(connectionErrHandler(args.json, "Timeout", None))
2436 except(requests.exceptions.ConnectionError) as err:
2437 return connectionErrHandler(args.json, "ConnectionError", err)
2438 if res.status_code == 403:
2439 return "The specified Interface"+"("+args.Interface+")"+\
2440 " doesn't exist"
2441
2442 return res.text
2443
2444
2445def getMACAddress(host, args, session):
2446
2447 """
2448 Called by the network function. Prints out the MACAddress.
2449
2450 @param host: string, the hostname or IP address of the bmc
2451 @param args: contains additional arguments used by the ldap subcommand
2452 args.json: boolean, if this flag is set to true, the output
2453 will be provided in json format for programmatic consumption
2454 @param session: the active session to use
2455 """
2456
2457 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2458 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002459
2460 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002461 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002462 except(requests.exceptions.Timeout):
2463 return(connectionErrHandler(args.json, "Timeout", None))
2464 except(requests.exceptions.ConnectionError) as err:
2465 return connectionErrHandler(args.json, "ConnectionError", err)
2466 if res.status_code == 404:
2467 return "The specified Interface"+"("+args.Interface+")"+\
2468 " doesn't exist"
2469
2470 return res.text
2471
2472
2473def setMACAddress(host, args, session):
2474 """
2475 Called by the network function. Sets the MACAddress.
2476
2477 @param host: string, the hostname or IP address of the bmc
2478 @param args: contains additional arguments used by the ldap subcommand
2479 args.json: boolean, if this flag is set to true, the output
2480 will be provided in json format for programmatic consumption
2481 @param session: the active session to use
2482 """
2483
2484 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
2485 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002486
2487 data = {"data": args.MACAddress}
2488
2489 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002490 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002491 timeout=30)
2492 except(requests.exceptions.Timeout):
2493 return(connectionErrHandler(args.json, "Timeout", None))
2494 except(requests.exceptions.ConnectionError) as err:
2495 return connectionErrHandler(args.json, "ConnectionError", err)
2496 if res.status_code == 403:
2497 return "The specified Interface"+"("+args.Interface+")"+\
2498 " doesn't exist"
2499
2500 return res.text
2501
2502
2503def getDefaultGateway(host, args, session):
2504
2505 """
2506 Called by the network function. Prints out the DefaultGateway.
2507
2508 @param host: string, the hostname or IP address of the bmc
2509 @param args: contains additional arguments used by the ldap subcommand
2510 args.json: boolean, if this flag is set to true, the output
2511 will be provided in json format for programmatic consumption
2512 @param session: the active session to use
2513 """
2514
2515 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002516
2517 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002518 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002519 except(requests.exceptions.Timeout):
2520 return(connectionErrHandler(args.json, "Timeout", None))
2521 except(requests.exceptions.ConnectionError) as err:
2522 return connectionErrHandler(args.json, "ConnectionError", err)
2523 if res.status_code == 404:
2524 return "Failed to get Default Gateway info!!"
2525
2526 return res.text
2527
2528
2529def setDefaultGateway(host, args, session):
2530 """
2531 Called by the network function. Sets the DefaultGateway.
2532
2533 @param host: string, the hostname or IP address of the bmc
2534 @param args: contains additional arguments used by the ldap subcommand
2535 args.json: boolean, if this flag is set to true, the output
2536 will be provided in json format for programmatic consumption
2537 @param session: the active session to use
2538 """
2539
2540 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002541
2542 data = {"data": args.DefaultGW}
2543
2544 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002545 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002546 timeout=30)
2547 except(requests.exceptions.Timeout):
2548 return(connectionErrHandler(args.json, "Timeout", None))
2549 except(requests.exceptions.ConnectionError) as err:
2550 return connectionErrHandler(args.json, "ConnectionError", err)
2551 if res.status_code == 403:
2552 return "Failed to set Default Gateway!!"
2553
2554 return res.text
2555
2556
2557def viewNWConfig(host, args, session):
2558 """
2559 Called by the ldap function. Prints out network configured properties
2560
2561 @param host: string, the hostname or IP address of the bmc
2562 @param args: contains additional arguments used by the ldap subcommand
2563 args.json: boolean, if this flag is set to true, the output
2564 will be provided in json format for programmatic consumption
2565 @param session: the active session to use
2566 @return returns LDAP's configured properties.
2567 """
2568 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002569 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002570 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002571 except(requests.exceptions.Timeout):
2572 return(connectionErrHandler(args.json, "Timeout", None))
2573 except(requests.exceptions.ConnectionError) as err:
2574 return connectionErrHandler(args.json, "ConnectionError", err)
2575 except(requests.exceptions.RequestException) as err:
2576 return connectionErrHandler(args.json, "RequestException", err)
2577 if res.status_code == 404:
2578 return "LDAP server config has not been created"
2579 return res.text
2580
2581
2582def getDNS(host, args, session):
2583
2584 """
2585 Called by the network function. Prints out DNS servers on the interface
2586
2587 @param host: string, the hostname or IP address of the bmc
2588 @param args: contains additional arguments used by the ldap subcommand
2589 args.json: boolean, if this flag is set to true, the output
2590 will be provided in json format for programmatic consumption
2591 @param session: the active session to use
2592 """
2593
2594 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2595 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002596
2597 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002598 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002599 except(requests.exceptions.Timeout):
2600 return(connectionErrHandler(args.json, "Timeout", None))
2601 except(requests.exceptions.ConnectionError) as err:
2602 return connectionErrHandler(args.json, "ConnectionError", err)
2603 if res.status_code == 404:
2604 return "The specified Interface"+"("+args.Interface+")" + \
2605 " doesn't exist"
2606
2607 return res.text
2608
2609
2610def setDNS(host, args, session):
2611 """
2612 Called by the network function. Sets DNS servers on the interface.
2613
2614 @param host: string, the hostname or IP address of the bmc
2615 @param args: contains additional arguments used by the ldap subcommand
2616 args.json: boolean, if this flag is set to true, the output
2617 will be provided in json format for programmatic consumption
2618 @param session: the active session to use
2619 """
2620
2621 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2622 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002623
2624 data = {"data": args.DNSServers.split(",")}
2625
2626 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002627 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002628 timeout=30)
2629 except(requests.exceptions.Timeout):
2630 return(connectionErrHandler(args.json, "Timeout", None))
2631 except(requests.exceptions.ConnectionError) as err:
2632 return connectionErrHandler(args.json, "ConnectionError", err)
2633 if res.status_code == 403:
2634 return "The specified Interface"+"("+args.Interface+")" +\
2635 " doesn't exist"
2636
2637 return res.text
2638
2639
2640def getNTP(host, args, session):
2641
2642 """
2643 Called by the network function. Prints out NTP servers on the interface
2644
2645 @param host: string, the hostname or IP address of the bmc
2646 @param args: contains additional arguments used by the ldap subcommand
2647 args.json: boolean, if this flag is set to true, the output
2648 will be provided in json format for programmatic consumption
2649 @param session: the active session to use
2650 """
2651
2652 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2653 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002654
2655 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002656 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002657 except(requests.exceptions.Timeout):
2658 return(connectionErrHandler(args.json, "Timeout", None))
2659 except(requests.exceptions.ConnectionError) as err:
2660 return connectionErrHandler(args.json, "ConnectionError", err)
2661 if res.status_code == 404:
2662 return "The specified Interface"+"("+args.Interface+")" + \
2663 " doesn't exist"
2664
2665 return res.text
2666
2667
2668def setNTP(host, args, session):
2669 """
2670 Called by the network function. Sets NTP servers on the interface.
2671
2672 @param host: string, the hostname or IP address of the bmc
2673 @param args: contains additional arguments used by the ldap subcommand
2674 args.json: boolean, if this flag is set to true, the output
2675 will be provided in json format for programmatic consumption
2676 @param session: the active session to use
2677 """
2678
2679 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2680 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002681
2682 data = {"data": args.NTPServers.split(",")}
2683
2684 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002685 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06002686 timeout=30)
2687 except(requests.exceptions.Timeout):
2688 return(connectionErrHandler(args.json, "Timeout", None))
2689 except(requests.exceptions.ConnectionError) as err:
2690 return connectionErrHandler(args.json, "ConnectionError", err)
2691 if res.status_code == 403:
2692 return "The specified Interface"+"("+args.Interface+")" +\
2693 " doesn't exist"
2694
2695 return res.text
2696
2697
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002698def addIP(host, args, session):
2699 """
2700 Called by the network function. Configures IP address on given interface
2701
2702 @param host: string, the hostname or IP address of the bmc
2703 @param args: contains additional arguments used by the ldap subcommand
2704 args.json: boolean, if this flag is set to true, the output
2705 will be provided in json format for programmatic consumption
2706 @param session: the active session to use
2707 """
2708
2709 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
2710 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002711 protocol = {
2712 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
2713 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
2714 }
2715
2716 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
2717 args.gateway]}
2718
2719 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002720 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002721 timeout=30)
2722 except(requests.exceptions.Timeout):
2723 return(connectionErrHandler(args.json, "Timeout", None))
2724 except(requests.exceptions.ConnectionError) as err:
2725 return connectionErrHandler(args.json, "ConnectionError", err)
2726 if res.status_code == 404:
2727 return "The specified Interface" + "(" + args.Interface + ")" +\
2728 " doesn't exist"
2729
2730 return res.text
2731
2732
2733def getIP(host, args, session):
2734 """
2735 Called by the network function. Prints out IP address of given interface
2736
2737 @param host: string, the hostname or IP address of the bmc
2738 @param args: contains additional arguments used by the ldap subcommand
2739 args.json: boolean, if this flag is set to true, the output
2740 will be provided in json format for programmatic consumption
2741 @param session: the active session to use
2742 """
2743
2744 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
2745 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002746 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002747 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002748 except(requests.exceptions.Timeout):
2749 return(connectionErrHandler(args.json, "Timeout", None))
2750 except(requests.exceptions.ConnectionError) as err:
2751 return connectionErrHandler(args.json, "ConnectionError", err)
2752 if res.status_code == 404:
2753 return "The specified Interface" + "(" + args.Interface + ")" +\
2754 " doesn't exist"
2755
2756 return res.text
2757
2758
2759def deleteIP(host, args, session):
2760 """
2761 Called by the network function. Deletes the IP address from given Interface
2762
2763 @param host: string, the hostname or IP address of the bmc
2764 @param args: contains additional arguments used by the ldap subcommand
2765 @param session: the active session to use
2766 @param args.json: boolean, if this flag is set to true, the output
2767 will be provided in json format for programmatic consumption
2768 """
2769
2770 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
2771 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002772 data = {"data": []}
2773 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002774 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002775 except(requests.exceptions.Timeout):
2776 return(connectionErrHandler(args.json, "Timeout", None))
2777 except(requests.exceptions.ConnectionError) as err:
2778 return connectionErrHandler(args.json, "ConnectionError", err)
2779 if res.status_code == 404:
2780 return "The specified Interface" + "(" + args.Interface + ")" +\
2781 " doesn't exist"
2782 objDict = json.loads(res.text)
2783 if not objDict['data']:
2784 return "No object found for given address on given Interface"
2785
2786 for obj in objDict['data']:
2787 if args.address in objDict['data'][obj]['Address']:
2788 url = "https://"+host+obj+"/action/delete"
2789 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002790 res = session.post(url, headers=jsonHeader, json=data,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06002791 verify=False, timeout=30)
2792 except(requests.exceptions.Timeout):
2793 return(connectionErrHandler(args.json, "Timeout", None))
2794 except(requests.exceptions.ConnectionError) as err:
2795 return connectionErrHandler(args.json, "ConnectionError", err)
2796 return res.text
2797 else:
2798 continue
2799 return "No object found for given address on given Interface"
2800
2801
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002802def addVLAN(host, args, session):
2803 """
2804 Called by the network function. Creates VLAN on given interface.
2805
2806 @param host: string, the hostname or IP address of the bmc
2807 @param args: contains additional arguments used by the ldap subcommand
2808 args.json: boolean, if this flag is set to true, the output
2809 will be provided in json format for programmatic consumption
2810 @param session: the active session to use
2811 """
2812
2813 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002814
2815 data = {"data": [args.Interface,args.Identifier]}
2816
2817 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002818 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002819 timeout=30)
2820 except(requests.exceptions.Timeout):
2821 return(connectionErrHandler(args.json, "Timeout", None))
2822 except(requests.exceptions.ConnectionError) as err:
2823 return connectionErrHandler(args.json, "ConnectionError", err)
2824 if res.status_code == 400:
2825 return "The specified Interface" + "(" + args.Interface + ")" +\
2826 " doesn't exist"
2827
2828 return res.text
2829
2830
2831def deleteVLAN(host, args, session):
2832 """
2833 Called by the network function. Creates VLAN on given interface.
2834
2835 @param host: string, the hostname or IP address of the bmc
2836 @param args: contains additional arguments used by the ldap subcommand
2837 args.json: boolean, if this flag is set to true, the output
2838 will be provided in json format for programmatic consumption
2839 @param session: the active session to use
2840 """
2841
2842 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002843 data = {"data": []}
2844
2845 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002846 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=30)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002847 except(requests.exceptions.Timeout):
2848 return(connectionErrHandler(args.json, "Timeout", None))
2849 except(requests.exceptions.ConnectionError) as err:
2850 return connectionErrHandler(args.json, "ConnectionError", err)
2851 if res.status_code == 404:
2852 return "The specified VLAN"+"("+args.Interface+"_"+args.Identifier\
2853 +")" +" doesn't exist"
2854
2855 return res.text
2856
2857
2858def viewDHCPConfig(host, args, session):
2859 """
2860 Called by the network function. Shows DHCP configured Properties.
2861
2862 @param host: string, the hostname or IP address of the bmc
2863 @param args: contains additional arguments used by the ldap subcommand
2864 args.json: boolean, if this flag is set to true, the output
2865 will be provided in json format for programmatic consumption
2866 @param session: the active session to use
2867 """
2868
2869 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002870
2871 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002872 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002873 except(requests.exceptions.Timeout):
2874 return(connectionErrHandler(args.json, "Timeout", None))
2875 except(requests.exceptions.ConnectionError) as err:
2876 return connectionErrHandler(args.json, "ConnectionError", err)
2877
2878 return res.text
2879
2880
2881def configureDHCP(host, args, session):
2882 """
2883 Called by the network function. Configures/updates DHCP Properties.
2884
2885 @param host: string, the hostname or IP address of the bmc
2886 @param args: contains additional arguments used by the ldap subcommand
2887 args.json: boolean, if this flag is set to true, the output
2888 will be provided in json format for programmatic consumption
2889 @param session: the active session to use
2890 """
2891
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002892
2893 try:
2894 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
2895 if(args.DNSEnabled == True):
2896 data = '{"data": 1}'
2897 else:
2898 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002899 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002900 data=data, verify=False, timeout=30)
2901 if(args.HostNameEnabled == True):
2902 data = '{"data": 1}'
2903 else:
2904 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002905 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002906 data=data, verify=False, timeout=30)
2907 if(args.NTPEnabled == True):
2908 data = '{"data": 1}'
2909 else:
2910 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002911 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002912 data=data, verify=False, timeout=30)
2913 if(args.SendHostNameEnabled == True):
2914 data = '{"data": 1}'
2915 else:
2916 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06002917 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002918 data=data, verify=False, timeout=30)
2919 except(requests.exceptions.Timeout):
2920 return(connectionErrHandler(args.json, "Timeout", None))
2921 except(requests.exceptions.ConnectionError) as err:
2922 return connectionErrHandler(args.json, "ConnectionError", err)
2923
2924 return res.text
2925
2926
2927def nwReset(host, args, session):
2928
2929 """
2930 Called by the network function. Resets networks setting to factory defaults.
2931
2932 @param host: string, the hostname or IP address of the bmc
2933 @param args: contains additional arguments used by the ldap subcommand
2934 args.json: boolean, if this flag is set to true, the output
2935 will be provided in json format for programmatic consumption
2936 @param session: the active session to use
2937 """
2938
2939 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002940 data = '{"data":[] }'
2941 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002942 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06002943 timeout=30)
2944
2945 except(requests.exceptions.Timeout):
2946 return(connectionErrHandler(args.json, "Timeout", None))
2947 except(requests.exceptions.ConnectionError) as err:
2948 return connectionErrHandler(args.json, "ConnectionError", err)
2949
2950 return res.text
2951
2952
Ratan Guptafeee6372018-10-17 23:25:51 +05302953def createPrivilegeMapping(host, args, session):
2954 """
2955 Called by the ldap function. Creates the group and the privilege mapping.
2956
2957 @param host: string, the hostname or IP address of the bmc
2958 @param args: contains additional arguments used by the ldap subcommand
2959 @param session: the active session to use
2960 @param args.json: boolean, if this flag is set to true, the output
2961 will be provided in json format for programmatic consumption
2962 """
2963
2964 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
Ratan Guptafeee6372018-10-17 23:25:51 +05302965
2966 data = {"data": [args.groupName,args.privilege]}
2967
2968 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002969 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=30)
Ratan Guptafeee6372018-10-17 23:25:51 +05302970 except(requests.exceptions.Timeout):
2971 return(connectionErrHandler(args.json, "Timeout", None))
2972 except(requests.exceptions.ConnectionError) as err:
2973 return connectionErrHandler(args.json, "ConnectionError", err)
2974 return res.text
2975
2976def listPrivilegeMapping(host, args, session):
2977 """
2978 Called by the ldap function. Lists the group and the privilege mapping.
2979
2980 @param host: string, the hostname or IP address of the bmc
2981 @param args: contains additional arguments used by the ldap subcommand
2982 @param session: the active session to use
2983 @param args.json: boolean, if this flag is set to true, the output
2984 will be provided in json format for programmatic consumption
2985 """
2986 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
Ratan Guptafeee6372018-10-17 23:25:51 +05302987 data = {"data": []}
2988
2989 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06002990 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=30)
Ratan Guptafeee6372018-10-17 23:25:51 +05302991 except(requests.exceptions.Timeout):
2992 return(connectionErrHandler(args.json, "Timeout", None))
2993 except(requests.exceptions.ConnectionError) as err:
2994 return connectionErrHandler(args.json, "ConnectionError", err)
2995 return res.text
2996
2997def deletePrivilegeMapping(host, args, session):
2998 """
2999 Called by the ldap function. Deletes the mapping associated with the group.
3000
3001 @param host: string, the hostname or IP address of the bmc
3002 @param args: contains additional arguments used by the ldap subcommand
3003 @param session: the active session to use
3004 @param args.json: boolean, if this flag is set to true, the output
3005 will be provided in json format for programmatic consumption
3006 """
3007 (ldapNameSpaceObjects) = listPrivilegeMapping(host, args, session)
3008 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3009 path = ''
3010
3011 # not interested in the config objet
3012 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
3013
3014 # search for the object having the mapping for the given group
3015 for key,value in ldapNameSpaceObjects.items():
3016 if value['GroupName'] == args.groupName:
3017 path = key
3018 break
3019
3020 if path == '':
3021 return "No privilege mapping found for this group."
3022
3023 # delete the object
3024 url = 'https://'+host+path+'/action/delete'
Ratan Guptafeee6372018-10-17 23:25:51 +05303025 data = {"data": []}
3026
3027 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003028 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=30)
Ratan Guptafeee6372018-10-17 23:25:51 +05303029 except(requests.exceptions.Timeout):
3030 return(connectionErrHandler(args.json, "Timeout", None))
3031 except(requests.exceptions.ConnectionError) as err:
3032 return connectionErrHandler(args.json, "ConnectionError", err)
3033 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303034
Sivas SRR78835272018-11-27 05:27:19 -06003035def deleteAllPrivilegeMapping(host, args, session):
3036 """
3037 Called by the ldap function. Deletes all the privilege mapping and group defined.
3038 @param host: string, the hostname or IP address of the bmc
3039 @param args: contains additional arguments used by the ldap subcommand
3040 @param session: the active session to use
3041 @param args.json: boolean, if this flag is set to true, the output
3042 will be provided in json format for programmatic consumption
3043 """
3044 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
3045 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
3046 path = ''
3047
3048 # Remove the config object.
3049 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
Sivas SRR78835272018-11-27 05:27:19 -06003050 data = {"data": []}
3051
3052 try:
3053 # search for GroupName property and delete if it is available.
3054 for path in ldapNameSpaceObjects.keys():
3055 # delete the object
3056 url = 'https://'+host+path+'/action/delete'
Matt Spinler220c3c42019-01-04 15:09:29 -06003057 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=30)
Sivas SRR78835272018-11-27 05:27:19 -06003058 except(requests.exceptions.Timeout):
3059 return(connectionErrHandler(args.json, "Timeout", None))
3060 except(requests.exceptions.ConnectionError) as err:
3061 return connectionErrHandler(args.json, "ConnectionError", err)
3062 return res.text
3063
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003064def viewLDAPConfig(host, args, session):
3065 """
3066 Called by the ldap function. Prints out LDAP's configured properties
3067
3068 @param host: string, the hostname or IP address of the bmc
3069 @param args: contains additional arguments used by the ldap subcommand
3070 args.json: boolean, if this flag is set to true, the output
3071 will be provided in json format for programmatic consumption
3072 @param session: the active session to use
3073 @return returns LDAP's configured properties.
3074 """
3075 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003076 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003077 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003078 except(requests.exceptions.Timeout):
3079 return(connectionErrHandler(args.json, "Timeout", None))
3080 except(requests.exceptions.ConnectionError) as err:
3081 return connectionErrHandler(args.json, "ConnectionError", err)
3082 except(requests.exceptions.RequestException) as err:
3083 return connectionErrHandler(args.json, "RequestException", err)
3084 if res.status_code == 404:
3085 return "LDAP server config has not been created"
3086 return res.text
3087
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003088def str2bool(v):
3089 if v.lower() in ('yes', 'true', 't', 'y', '1'):
3090 return True
3091 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
3092 return False
3093 else:
3094 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003095
Matt Spinler7d426c22018-09-24 14:42:07 -05003096def localUsers(host, args, session):
3097 """
3098 Enables and disables local BMC users.
3099
3100 @param host: string, the hostname or IP address of the bmc
3101 @param args: contains additional arguments used by the logging sub command
3102 @param session: the active session to use
3103 """
3104
Matt Spinler7d426c22018-09-24 14:42:07 -05003105 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
3106 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003107 res = session.get(url, headers=jsonHeader, verify=False, timeout=40)
Matt Spinler7d426c22018-09-24 14:42:07 -05003108 except(requests.exceptions.Timeout):
3109 return(connectionErrHandler(args.json, "Timeout", None))
3110 usersDict = json.loads(res.text)
3111
3112 if not usersDict['data']:
3113 return "No users found"
3114
3115 output = ""
3116 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05003117
3118 # Skip LDAP and another non-local users
3119 if 'UserEnabled' not in usersDict['data'][user]:
3120 continue
3121
Matt Spinler7d426c22018-09-24 14:42:07 -05003122 name = user.split('/')[-1]
3123 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
3124
3125 if args.local_users == "queryenabled":
3126 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003127 res = session.get(url, headers=jsonHeader,verify=False, timeout=30)
Matt Spinler7d426c22018-09-24 14:42:07 -05003128 except(requests.exceptions.Timeout):
3129 return(connectionErrHandler(args.json, "Timeout", None))
3130
3131 result = json.loads(res.text)
3132 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
3133
3134 elif args.local_users in ["enableall", "disableall"]:
3135 action = ""
3136 if args.local_users == "enableall":
3137 data = '{"data": true}'
3138 action = "Enabling"
3139 else:
3140 data = '{"data": false}'
3141 action = "Disabling"
3142
3143 output += "{action} {name}\n".format(action=action, name=name)
3144
3145 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003146 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=30)
Matt Spinler7d426c22018-09-24 14:42:07 -05003147 except(requests.exceptions.Timeout):
3148 return connectionErrHandler(args.json, "Timeout", None)
3149 except(requests.exceptions.ConnectionError) as err:
3150 return connectionErrHandler(args.json, "ConnectionError", err)
3151 else:
3152 return "Invalid local users argument"
3153
3154 return output
3155
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003156def setPassword(host, args, session):
3157 """
3158 Set local user password
3159 @param host: string, the hostname or IP address of the bmc
3160 @param args: contains additional arguments used by the logging sub
3161 command
3162 @param session: the active session to use
3163 @param args.json: boolean, if this flag is set to true, the output
3164 will be provided in json format for programmatic consumption
3165 @return: Session object
3166 """
3167 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
3168 "/action/SetPassword"
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003169 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003170 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003171 json={"data": [args.password]}, verify=False,
3172 timeout=30)
3173 except(requests.exceptions.Timeout):
3174 return(connectionErrHandler(args.json, "Timeout", None))
3175 except(requests.exceptions.ConnectionError) as err:
3176 return connectionErrHandler(args.json, "ConnectionError", err)
3177 except(requests.exceptions.RequestException) as err:
3178 return connectionErrHandler(args.json, "RequestException", err)
3179 return res.text
3180
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003181def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06003182 """
3183 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003184
Justin Thalere412dc22018-01-12 16:28:24 -06003185 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003186 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003187 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06003188 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
3189 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003190 group = parser.add_mutually_exclusive_group()
3191 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
3192 group.add_argument("-P", "--PW", help='Provide the password in-line')
3193 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
3194 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
3195 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
3196 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06003197 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
3198 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003199
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003200 #fru command
3201 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06003202 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 -05003203 inv_subparser.required = True
3204 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003205 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
3206 inv_print.set_defaults(func=fruPrint)
3207 #fru list [0....n]
3208 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3209 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
3210 inv_list.set_defaults(func=fruList)
3211 #fru status
3212 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06003213 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003214 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003215
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003216 #sensors command
3217 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06003218 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 -05003219 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003220 #sensor print
3221 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
3222 sens_print.set_defaults(func=sensor)
3223 #sensor list[0...n]
3224 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
3225 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
3226 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003227
3228
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003229 #sel command
3230 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06003231 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 -05003232 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003233 #sel print
3234 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
3235 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3236 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
3237 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
3238 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003239
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003240 #sel list
3241 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")
3242 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
3243 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003244
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003245 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
3246 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
3247 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003248
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003249 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
3250 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003251
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003252 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06003253 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
3254 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
3255 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
3256 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003257 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003258
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003259 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06003260 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003261
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003262 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
3263 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003264
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003265 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 -06003266 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 -06003267 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003268
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003269 #control the chassis identify led
3270 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
3271 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
3272 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003273
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003274 #collect service data
3275 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
3276 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
3277 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003278
Justin Thalere412dc22018-01-12 16:28:24 -06003279 #system quick health check
3280 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
3281 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003282
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003283 #work with bmc dumps
3284 parser_bmcdump = subparsers.add_parser("dump", help="Work with bmc dump files")
Justin Thalere412dc22018-01-12 16:28:24 -06003285 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05003286 bmcDump_sub.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003287 dump_Create = bmcDump_sub.add_parser('create', help="Create a bmc dump")
3288 dump_Create.set_defaults(func=bmcDumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003289
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003290 dump_list = bmcDump_sub.add_parser('list', help="list all bmc dump files")
3291 dump_list.set_defaults(func=bmcDumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003292
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003293 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete bmc dump files")
3294 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003295 parserdumpdelete.set_defaults(func=bmcDumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003296
Justin Thalere412dc22018-01-12 16:28:24 -06003297 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003298 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all bmc dump files')
3299 deleteAllDumps.set_defaults(func=bmcDumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003300
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003301 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
3302 parser_dumpretrieve.add_argument("dumpNum", type=int, help="The Dump entry to delete")
3303 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file")
3304 parser_dumpretrieve.set_defaults(func=bmcDumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003305
Justin Thaler22b1bb52018-03-15 13:31:32 -05003306 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003307 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06003308 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003309 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
3310 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 -06003311 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.")
3312 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003313
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003314 #add alias to the bmc command
3315 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06003316 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003317 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
3318 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
3319 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
3320 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 -06003321 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003322 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003323
Justin Thalere412dc22018-01-12 16:28:24 -06003324 #gard clear
3325 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
3326 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003327
Justin Thalere412dc22018-01-12 16:28:24 -06003328 #firmware_flash
3329 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
3330 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 -05003331 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003332
Justin Thalere412dc22018-01-12 16:28:24 -06003333 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
3334 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
3335 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
3336 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003337
Justin Thaler22b1bb52018-03-15 13:31:32 -05003338 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06003339 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
3340 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003341
Justin Thaler22b1bb52018-03-15 13:31:32 -05003342 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
3343 fwActivateStatus.set_defaults(func=activateStatus)
3344
Justin Thaler3d71d402018-07-24 14:35:39 -05003345 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
3346 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3347 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003348
Justin Thaler3d71d402018-07-24 14:35:39 -05003349 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
3350 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3351 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003352
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06003353 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
3354 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
3355 fwDelete.set_defaults(func=deleteFWVersion)
3356
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003357 #logging
3358 parser_logging = subparsers.add_parser("logging", help="logging controls")
3359 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003360
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003361 #turn rest api logging on/off
3362 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
3363 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
3364 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003365
3366 #remote logging
3367 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
3368 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
3369 parser_remote_logging.set_defaults(func=remoteLogging)
3370
3371 #configure remote logging
3372 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
3373 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
3374 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
3375 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003376
3377 #certificate management
3378 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
3379 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
3380
3381 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
3382 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
3383 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
3384 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
3385 certUpdate.set_defaults(func=certificateUpdate)
3386
3387 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
3388 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
3389 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
3390 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003391
Matt Spinler7d426c22018-09-24 14:42:07 -05003392 # local users
3393 parser_users = subparsers.add_parser("local_users", help="Work with local users")
3394 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
3395 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
3396 parser_users.set_defaults(func=localUsers)
3397
Ratan Gupta9166cd22018-10-01 18:09:40 +05303398 #LDAP
3399 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
3400 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
3401
3402 #configure and enable LDAP
3403 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
3404 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
3405 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
3406 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
3407 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
3408 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
3409 help='Specifies the search scope:subtree, one level or base object.')
3410 parser_ldap_config.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
3411 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
3412 parser_ldap_config.set_defaults(func=enableLDAP)
3413
3414 # disable LDAP
3415 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
3416 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06003417 # view-config
3418 parser_ldap_config = \
3419 ldap_sub.add_parser("view-config", help="prints out a list of all \
3420 LDAPS's configured properties")
3421 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303422
Ratan Guptafeee6372018-10-17 23:25:51 +05303423 #create group privilege mapping
3424 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
3425 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
3426 help="sub-command help", dest='command')
3427
3428 parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
3429 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
3430 parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-user'],required=True,help="Privilege")
3431 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
3432
3433 #list group privilege mapping
3434 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
3435 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
3436
3437 #delete group privilege mapping
3438 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
3439 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
3440 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
3441
Sivas SRR78835272018-11-27 05:27:19 -06003442 #deleteAll group privilege mapping
3443 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
3444 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
3445
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06003446 # set local user password
3447 parser_set_password = subparsers.add_parser("set_password",
3448 help="Set password of local user")
3449 parser_set_password.add_argument( "-p", "--password", required=True,
3450 help="Password of local user")
3451 parser_set_password.set_defaults(func=setPassword)
3452
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003453 # network
3454 parser_nw = subparsers.add_parser("network", help="network controls")
3455 nw_sub = parser_nw.add_subparsers(title='subcommands',
3456 description='valid subcommands',
3457 help="sub-command help",
3458 dest='command')
3459
3460 # enable DHCP
3461 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
3462 help="enables the DHCP on given "
3463 "Interface")
3464 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003465 help="Name of the ethernet interface(it can"
3466 "be obtained by the "
3467 "command:network view-config)"
3468 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003469 parser_enable_dhcp.set_defaults(func=enableDHCP)
3470
3471 # disable DHCP
3472 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
3473 help="disables the DHCP on given "
3474 "Interface")
3475 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003476 help="Name of the ethernet interface(it can"
3477 "be obtained by the "
3478 "command:network view-config)"
3479 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003480 parser_disable_dhcp.set_defaults(func=disableDHCP)
3481
3482 # get HostName
3483 parser_gethostname = nw_sub.add_parser("getHostName",
3484 help="prints out HostName")
3485 parser_gethostname.set_defaults(func=getHostname)
3486
3487 # set HostName
3488 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
3489 parser_sethostname.add_argument("-H", "--HostName", required=True,
3490 help="A HostName for the BMC")
3491 parser_sethostname.set_defaults(func=setHostname)
3492
3493 # get domainname
3494 parser_getdomainname = nw_sub.add_parser("getDomainName",
3495 help="prints out DomainName of "
3496 "given Interface")
3497 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003498 help="Name of the ethernet interface(it "
3499 "can be obtained by the "
3500 "command:network view-config)"
3501 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003502 parser_getdomainname.set_defaults(func=getDomainName)
3503
3504 # set domainname
3505 parser_setdomainname = nw_sub.add_parser("setDomainName",
3506 help="sets DomainName of given "
3507 "Interface")
3508 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
3509 help="Ex: DomainName=Domain1,Domain2,...")
3510 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003511 help="Name of the ethernet interface(it "
3512 "can be obtained by the "
3513 "command:network view-config)"
3514 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003515 parser_setdomainname.set_defaults(func=setDomainName)
3516
3517 # get MACAddress
3518 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
3519 help="prints out MACAddress the "
3520 "given Interface")
3521 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003522 help="Name of the ethernet interface(it "
3523 "can be obtained by the "
3524 "command:network view-config)"
3525 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003526 parser_getmacaddress.set_defaults(func=getMACAddress)
3527
3528 # set MACAddress
3529 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
3530 help="sets MACAddress")
3531 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
3532 help="A MACAddress for the given "
3533 "Interface")
3534 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003535 help="Name of the ethernet interface(it can"
3536 "be obtained by the "
3537 "command:network view-config)"
3538 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003539 parser_setmacaddress.set_defaults(func=setMACAddress)
3540
3541 # get DefaultGW
3542 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
3543 help="prints out DefaultGateway "
3544 "the BMC")
3545 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
3546
3547 # set DefaultGW
3548 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
3549 help="sets DefaultGW")
3550 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
3551 help="A DefaultGateway for the BMC")
3552 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
3553
3554 # view network Config
3555 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
3556 "list of all network's configured "
3557 "properties")
3558 parser_ldap_config.set_defaults(func=viewNWConfig)
3559
3560 # get DNS
3561 parser_getDNS = nw_sub.add_parser("getDNS",
3562 help="prints out DNS servers on the "
3563 "given interface")
3564 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003565 help="Name of the ethernet interface(it can"
3566 "be obtained by the "
3567 "command:network view-config)"
3568 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003569 parser_getDNS.set_defaults(func=getDNS)
3570
3571 # set DNS
3572 parser_setDNS = nw_sub.add_parser("setDNS",
3573 help="sets DNS servers on the given "
3574 "interface")
3575 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
3576 help="Ex: DNSSERVERS=DNS1,DNS2,...")
3577 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003578 help="Name of the ethernet interface(it can"
3579 "be obtained by the "
3580 "command:network view-config)"
3581 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003582 parser_setDNS.set_defaults(func=setDNS)
3583
3584 # get NTP
3585 parser_getNTP = nw_sub.add_parser("getNTP",
3586 help="prints out NTP servers on the "
3587 "given interface")
3588 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003589 help="Name of the ethernet interface(it can"
3590 "be obtained by the "
3591 "command:network view-config)"
3592 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003593 parser_getNTP.set_defaults(func=getNTP)
3594
3595 # set NTP
3596 parser_setNTP = nw_sub.add_parser("setNTP",
3597 help="sets NTP servers on the given "
3598 "interface")
3599 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
3600 help="Ex: NTPSERVERS=NTP1,NTP2,...")
3601 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003602 help="Name of the ethernet interface(it can"
3603 "be obtained by the "
3604 "command:network view-config)"
3605 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003606 parser_setNTP.set_defaults(func=setNTP)
3607
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003608 # configure IP
3609 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
3610 "given interface")
3611 parser_ip_config.add_argument("-a", "--address", required=True,
3612 help="IP address of given interface")
3613 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
3614 help="The gateway for given interface")
3615 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
3616 help="The prefixLength of IP address")
3617 parser_ip_config.add_argument("-p", "--type", choices=['ipv4', 'ipv6'],
3618 help="The protocol type of the given"
3619 "IP address")
3620 parser_ip_config.add_argument("-I", "--Interface", required=True,
3621 help="Name of the ethernet interface(it can"
3622 "be obtained by the "
3623 "command:network view-config)"
3624 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3625 parser_ip_config.set_defaults(func=addIP)
3626
3627 # getIP
3628 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
3629 "of given interface")
3630 parser_getIP.add_argument("-I", "--Interface", required=True,
3631 help="Name of the ethernet interface(it can"
3632 "be obtained by the command:network view-config)"
3633 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3634 parser_getIP.set_defaults(func=getIP)
3635
3636 # rmIP
3637 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
3638 "of given interface")
3639 parser_rmIP.add_argument("-a", "--address", required=True,
3640 help="IP address to remove form given Interface")
3641 parser_rmIP.add_argument("-I", "--Interface", required=True,
3642 help="Name of the ethernet interface(it can"
3643 "be obtained by the command:network view-config)"
3644 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3645 parser_rmIP.set_defaults(func=deleteIP)
3646
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003647 # add VLAN
3648 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
3649 "on given interface with given "
3650 "VLAN Identifier")
3651 parser_create_vlan.add_argument("-I", "--Interface", required=True,
3652 choices=['eth0', 'eth1'],
3653 help="Name of the ethernet interface")
3654 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
3655 help="VLAN Identifier")
3656 parser_create_vlan.set_defaults(func=addVLAN)
3657
3658 # delete VLAN
3659 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
3660 "on given interface with given "
3661 "VLAN Identifier")
3662 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
3663 help="Name of the ethernet interface(it can"
3664 "be obtained by the "
3665 "command:network view-config)"
3666 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
3667 parser_delete_vlan.set_defaults(func=deleteVLAN)
3668
3669 # viewDHCPConfig
3670 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
3671 help="Shows DHCP configured "
3672 "Properties")
3673 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
3674
3675 # configureDHCP
3676 parser_configDHCP = nw_sub.add_parser("configureDHCP",
3677 help="Configures/updates DHCP "
3678 "Properties")
3679 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
3680 required=True, help="Sets DNSEnabled property")
3681 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
3682 required=True,
3683 help="Sets HostNameEnabled property")
3684 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
3685 required=True,
3686 help="Sets NTPEnabled property")
3687 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
3688 required=True,
3689 help="Sets SendHostNameEnabled property")
3690 parser_configDHCP.set_defaults(func=configureDHCP)
3691
3692 # network factory reset
3693 parser_nw_reset = nw_sub.add_parser("nwReset",
3694 help="Resets networks setting to "
3695 "factory defaults. "
3696 "note:Reset settings will be applied "
3697 "after BMC reboot")
3698 parser_nw_reset.set_defaults(func=nwReset)
3699
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003700 return parser
3701
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003702def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06003703 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003704 main function for running the command line utility as a sub application
3705 """
3706 global toolVersion
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06003707 toolVersion = "1.11"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003708 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003709 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003710
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003711 totTimeStart = int(round(time.time()*1000))
3712
3713 if(sys.version_info < (3,0)):
3714 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
3715 if sys.version_info >= (3,0):
3716 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06003717 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05003718 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06003719 sys.exit(0)
3720 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003721 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06003722 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003723 else:
Justin Thalere412dc22018-01-12 16:28:24 -06003724 if(hasattr(args, 'host') and hasattr(args,'user')):
3725 if (args.askpw):
3726 pw = getpass.getpass()
3727 elif(args.PW is not None):
3728 pw = args.PW
3729 else:
3730 print("You must specify a password")
3731 sys.exit()
3732 logintimeStart = int(round(time.time()*1000))
3733 mysess = login(args.host, args.user, pw, args.json)
Justin Thalera9415b42018-05-25 19:40:13 -05003734 if(sys.version_info < (3,0)):
3735 if isinstance(mysess, basestring):
3736 print(mysess)
3737 sys.exit(1)
3738 elif sys.version_info >= (3,0):
3739 if isinstance(mysess, str):
3740 print(mysess)
3741 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06003742 logintimeStop = int(round(time.time()*1000))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003743
3744 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06003745 output = args.func(args.host, args, mysess)
3746 commandTimeStop = int(round(time.time()*1000))
3747 print(output)
3748 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003749 logout(args.host, args.user, pw, mysess, args.json)
3750 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06003751 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
3752 print("loginTime: " + str(logintimeStop - logintimeStart))
3753 print("command Time: " + str(commandTimeStop - commandTimeStart))
3754 else:
3755 print("usage: openbmctool.py [-h] -H HOST -U USER [-A | -P PW] [-j]\n" +
3756 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05003757 "\t{fru,sensors,sel,chassis,collect_service_data, \
3758 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06003759 "\t...\n" +
3760 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003761 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003762
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003763if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06003764 """
3765 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003766
3767 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003768 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003769
Justin Thalerf9aee3e2017-12-05 12:11:09 -06003770 isTTY = sys.stdout.isatty()
3771 assert sys.version_info >= (2,7)
3772 main()