blob: 7d702b61c08987289bc7eae11be77aa7d93bbbba [file] [log] [blame]
Justin Thalerb8807ce2018-05-25 19:16:20 -05001#!/usr/bin/python3
Justin Thalere412dc22018-01-12 16:28:24 -06002"""
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05003 Copyright 2017,2019 IBM Corporation
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004
Justin Thalere412dc22018-01-12 16:28:24 -06005 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
Justin Thalerf9aee3e2017-12-05 12:11:09 -060017import argparse
18import requests
19import getpass
20import json
21import os
22import urllib3
23import time, datetime
Justin Thalerf9aee3e2017-12-05 12:11:09 -060024import binascii
25import subprocess
26import platform
27import zipfile
Justin Thaler22b1bb52018-03-15 13:31:32 -050028import tarfile
29import tempfile
30import hashlib
Justin Thalera6b5df72018-07-16 11:10:07 -050031import re
Justin Thaler24d4efa2018-11-08 22:48:10 -060032import uuid
Ravi Tejad8be0b42020-03-18 14:31:46 -050033import ssl
34import socket
35import select
36import http.client
37from subprocess import check_output
Justin Thalerb4256672020-04-07 19:38:26 -050038import traceback
Justin Thalerf9aee3e2017-12-05 12:11:09 -060039
Ravi Tejad8be0b42020-03-18 14:31:46 -050040
41MAX_NBD_PACKET_SIZE = 131088
Matt Spinler220c3c42019-01-04 15:09:29 -060042jsonHeader = {'Content-Type' : 'application/json'}
43xAuthHeader = {}
Justin Thaler27197622019-01-23 14:42:11 -060044baseTimeout = 60
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -050045serverTypeMap = {
46 'ActiveDirectory' : 'active_directory',
47 'OpenLDAP' : 'openldap'
48 }
Matt Spinler220c3c42019-01-04 15:09:29 -060049
Ravi Tejad8be0b42020-03-18 14:31:46 -050050class NBDPipe:
51
52 def openHTTPSocket(self,args):
53
54 try:
55 _create_unverified_https_context = ssl._create_unverified_context
56 except AttributeError:
57 # Legacy Python that doesn't verify HTTPS certificates by default
58 pass
59 else:
60 # Handle target environment that doesn't support HTTPS verification
61 ssl._create_default_https_context = _create_unverified_https_context
62
63
64 token = gettoken(args)
65 self.conn = http.client.HTTPSConnection(args.host,port=443)
66 URI = "/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)+"/Actions/Oem/OpenBmc/LogEntry.DownloadLog"
67 self.conn.request("POST",URI, headers={"X-Auth-Token":token})
68
69 def openTCPSocket(self):
70 # Create a TCP/IP socket
71 self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
72 # Connect the socket to the port where the server is listening
73 server_address = ('localhost', 1043)
74 self.tcp.connect(server_address)
75
76 def waitformessage(self):
77 inputs = [self.conn.sock,self.tcp]
78 outputs = []
79 message_queues = {}
80 while True:
81 readable, writable, exceptional = select.select(
82 inputs, outputs, inputs)
83
84 for s in readable:
85 if s is self.conn.sock:
86
87 data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
88 print("<<HTTP")
Ravi Tejad8be0b42020-03-18 14:31:46 -050089 if data:
90 self.tcp.send(data)
91 else:
92 print ("BMC Closed the connection")
93 self.conn.close()
94 self.tcp.close()
95 sys.exit(1)
96 elif s is self.tcp:
97 data = self.tcp.recv(MAX_NBD_PACKET_SIZE)
98 print(">>TCP")
Ravi Tejad8be0b42020-03-18 14:31:46 -050099 if data:
100 self.conn.sock.send(data)
101 else:
102 print("NBD server closed the connection")
103 self.conn.sock.close()
104 self.tcp.close()
105 sys.exit(1)
106 for s in exceptional:
107 inputs.remove(s)
108 print("Exceptional closing the socket")
109 s.close()
110
111def getsize(host,args,session):
112 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500113 try:
114 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
115 if resp.status_code==200:
116 size = resp.json()["Oem"]["OpenBmc"]['SizeInB']
Ravi Tejad8be0b42020-03-18 14:31:46 -0500117 return size
118 else:
119 return "Failed get Size"
120 except(requests.exceptions.Timeout):
121 return connectionErrHandler(args.json, "Timeout", None)
122
123 except(requests.exceptions.ConnectionError) as err:
124 return connectionErrHandler(args.json, "ConnectionError", err)
125
126def gettoken(args):
127 mysess = requests.session()
128 resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
129 if resp.status_code == 200:
130 cookie = resp.headers['Set-Cookie']
131 match = re.search('SESSION=(\w+);', cookie)
132 return match.group(1)
133
134
135
136def get_pid(name):
137 try:
138 pid = map(int, check_output(["pidof", "-s",name]))
139 except Exception:
140 pid = 0
141
142 return pid
143
144def findThisProcess( process_name ):
145 ps = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
146 output = ps.stdout.read()
147 ps.stdout.close()
148 ps.wait()
149 pid = get_pid(process_name)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500150 return output
151
152def isThisProcessRunning( process_name ):
153 pid = get_pid(process_name)
154 if (pid == 0 ):
155 return False
156 else:
157 return True
158
159def NBDSetup(host,args,session):
160 user=os.getenv("SUDO_USER")
161 if user is None:
162 path = os.getcwd()
163 nbdServerPath = path + "/nbd-server"
Ravi Tejad8be0b42020-03-18 14:31:46 -0500164 if not os.path.exists(nbdServerPath):
165 print("Error: this program did not run as sudo!\nplease copy nbd-server to current directory and run script again")
166 exit()
167
168 if isThisProcessRunning('nbd-server') == True:
169 print("nbd-server already Running! killing the nbd-server")
170 os.system('killall nbd-server')
171
172 if (args.dumpSaveLoc is not None):
173 if(os.path.exists(args.dumpSaveLoc)):
174 print("Error: File already exists.")
175 exit()
176
177 fp= open(args.dumpSaveLoc,"w")
178 sizeInBytes = getsize(host,args,session)
179 #Round off size to mutiples of 1024
180 size = int(sizeInBytes)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500181 mod = size % 1024
182 if mod :
183 roundoff = 1024 - mod
184 size = size + roundoff
185
186 cmd = 'chmod 777 ' + args.dumpSaveLoc
187 os.system(cmd)
188
189 #Run truncate to create file with given size
190 cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
191 os.system(cmd)
192
193 if user is None:
194 cmd = './nbd-server 1043 '+ args.dumpSaveLoc
195 else:
196 cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
197 os.system(cmd)
198
199
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600200def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -0600201 """
202 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600203
Justin Thalere412dc22018-01-12 16:28:24 -0600204 @param textToColor: string, the text to be colored
205 @param color: string, used to color the text red or green
206 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600207 @return: Buffered reader containing the modified string.
208 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600209 if(sys.platform.__contains__("win")):
210 if(color == "red"):
211 os.system('color 04')
212 elif(color == "green"):
213 os.system('color 02')
214 else:
215 os.system('color') #reset to default
216 return textToColor
217 else:
218 attr = []
219 if(color == "red"):
220 attr.append('31')
221 elif(color == "green"):
222 attr.append('32')
223 else:
224 attr.append('0')
225 if bold:
226 attr.append('1')
227 else:
228 attr.append('0')
229 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
230
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600231def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -0600232 """
233 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600234
235 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -0600236 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600237 @param err: string, the text from the exception
238 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600239 if errorStr == "Timeout":
240 if not jsonFormat:
241 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
242 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500243 conerror = {}
244 conerror['CommonEventID'] = 'FQPSPIN0000M'
245 conerror['sensor']="N/A"
246 conerror['state']="N/A"
247 conerror['additionalDetails'] = "N/A"
248 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
249 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."
250 conerror['Serviceable']="Yes"
251 conerror['CallHomeCandidate']= "No"
252 conerror['Severity'] = "Critical"
253 conerror['EventType'] = "Communication Failure/Timeout"
254 conerror['VMMigrationFlag'] = "Yes"
255 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
256 conerror["timestamp"] = str(int(time.time()))
257 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
258 eventdict = {}
259 eventdict['event0'] = conerror
260 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500261 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600262 return(errorMessageStr)
263 elif errorStr == "ConnectionError":
264 if not jsonFormat:
265 return("FQPSPIN0001M: " + str(err))
266 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500267 conerror = {}
268 conerror['CommonEventID'] = 'FQPSPIN0001M'
269 conerror['sensor']="N/A"
270 conerror['state']="N/A"
271 conerror['additionalDetails'] = str(err)
272 conerror['Message']="Connection Error. View additional details for more information"
273 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
274 conerror['Serviceable']="Yes"
275 conerror['CallHomeCandidate']= "No"
276 conerror['Severity'] = "Critical"
277 conerror['EventType'] = "Communication Failure/Timeout"
278 conerror['VMMigrationFlag'] = "Yes"
279 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
280 conerror["timestamp"] = str(int(time.time()))
281 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
282 eventdict = {}
283 eventdict['event0'] = conerror
284 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500285 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600286 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500287
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600288 else:
289 return("Unknown Error: "+ str(err))
290
Justin Thalere412dc22018-01-12 16:28:24 -0600291
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600292def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600293 """
294 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600295
296 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600297 @param numcols: the total number of columns in the final output
298 @param dictForOutput: dictionary, contains the information to print to the screen
299 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600300 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600301 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600302 colWidths = []
303 for x in range(0, numCols):
304 colWidths.append(0)
305 for key in dictForOutput:
306 for x in range(0, numCols):
307 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600308
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600309 for x in range(0, numCols):
310 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600311
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600312 return colWidths
313
314def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600315 """
316 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600317
Justin Thalere412dc22018-01-12 16:28:24 -0600318 @param value: boolean, the value to convert
319 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600320 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600321 policyTable = {}
322 if(os.path.exists(pathToPolicyTable)):
323 with open(pathToPolicyTable, 'r') as stream:
324 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600325 contents =json.load(stream)
326 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600327 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600328 print(err)
329 return policyTable
330
Justin Thalere412dc22018-01-12 16:28:24 -0600331
332def boolToString(value):
333 """
334 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600335
Justin Thalere412dc22018-01-12 16:28:24 -0600336 @param value: boolean, the value to convert
337 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600338 """
Justin Thalere412dc22018-01-12 16:28:24 -0600339 if(value):
340 return "Yes"
341 else:
342 return "No"
343
Justin Thalera6b5df72018-07-16 11:10:07 -0500344def stringToInt(text):
345 """
346 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600347
Justin Thalera6b5df72018-07-16 11:10:07 -0500348 @param text: the string to try to convert to an integer
349 """
350 if text.isdigit():
351 return int(text)
352 else:
353 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600354
Justin Thalera6b5df72018-07-16 11:10:07 -0500355def naturalSort(text):
356 """
357 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600358
Justin Thalera6b5df72018-07-16 11:10:07 -0500359 @param text: the key to convert for sorting
360 @return list containing the broken up string parts by integers and strings
361 """
362 stringPartList = []
363 for c in re.split('(\d+)', text):
364 stringPartList.append(stringToInt(c))
365 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600366
Justin Thalere412dc22018-01-12 16:28:24 -0600367def tableDisplay(keylist, colNames, output):
368 """
369 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600370
Justin Thalere412dc22018-01-12 16:28:24 -0600371 @param keylist: list, keys for the output dictionary, ordered by colNames
372 @param colNames: Names for the Table of the columns
373 @param output: The dictionary of data to display
374 @return: Session object
375 """
376 colWidth = setColWidth(keylist, len(colNames), output, colNames)
377 row = ""
378 outputText = ""
379 for i in range(len(colNames)):
380 if (i != 0): row = row + "| "
381 row = row + colNames[i].ljust(colWidth[i])
382 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600383
Justin Thalera6b5df72018-07-16 11:10:07 -0500384 output_keys = list(output.keys())
385 output_keys.sort(key=naturalSort)
386 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600387 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500388 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600389 if (i != 0): row = row + "| "
390 row = row + output[key][keylist[i]].ljust(colWidth[i])
391 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600392
Justin Thalere412dc22018-01-12 16:28:24 -0600393 return outputText
394
Justin Thaler22b1bb52018-03-15 13:31:32 -0500395def checkFWactivation(host, args, session):
396 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600397 Checks the software inventory for an image that is being activated.
398
Justin Thaler22b1bb52018-03-15 13:31:32 -0500399 @return: True if an image is being activated, false is no activations are happening
400 """
401 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500402 try:
Justin Thaler27197622019-01-23 14:42:11 -0600403 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500404 except(requests.exceptions.Timeout):
405 print(connectionErrHandler(args.json, "Timeout", None))
406 return(True)
407 except(requests.exceptions.ConnectionError) as err:
408 print( connectionErrHandler(args.json, "ConnectionError", err))
409 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600410 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500411 for key in fwInfo:
412 if 'Activation' in fwInfo[key]:
413 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
414 return True
415 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600416
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500417def login(host, username, pw,jsonFormat, allowExpiredPassword):
Justin Thalere412dc22018-01-12 16:28:24 -0600418 """
419 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600420
Justin Thalere412dc22018-01-12 16:28:24 -0600421 @param host: string, the hostname or IP address of the bmc to log into
422 @param username: The user name for the bmc to log into
423 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600424 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500425 @param allowExpiredPassword: true, if the requested operation should
426 be allowed when the password is expired
Justin Thalere412dc22018-01-12 16:28:24 -0600427 @return: Session object
428 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600429 if(jsonFormat==False):
430 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600431 mysess = requests.session()
432 try:
Justin Thaler27197622019-01-23 14:42:11 -0600433 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Sunitha Harish336cda22019-07-23 02:02:52 -0500434 if r.status_code == 200:
435 cookie = r.headers['Set-Cookie']
436 match = re.search('SESSION=(\w+);', cookie)
437 if match:
438 xAuthHeader['X-Auth-Token'] = match.group(1)
439 jsonHeader.update(xAuthHeader)
440 loginMessage = json.loads(r.text)
441 if (loginMessage['status'] != "ok"):
442 print(loginMessage["data"]["description"].encode('utf-8'))
443 sys.exit(1)
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500444 if (('extendedMessage' in r.json()) and
445 ('The password for this account must be changed' in r.json()['extendedMessage'])):
446 if not allowExpiredPassword:
447 print("The password for this system has expired and must be changed"+
448 "\nsee openbmctool.py set_password --help")
449 logout(host, username, pw, mysess, jsonFormat)
450 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600451# if(sys.version_info < (3,0)):
452# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
453# if sys.version_info >= (3,0):
454# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Sunitha Harish336cda22019-07-23 02:02:52 -0500455 return mysess
456 else:
457 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600458 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500459 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600460 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500461 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600462
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600463
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600464def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600465 """
466 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600467
Justin Thalere412dc22018-01-12 16:28:24 -0600468 @param host: string, the hostname or IP address of the bmc to log out of
469 @param username: The user name for the bmc to log out of
470 @param pw: The password for the BMC to log out of
471 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600472 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
473 """
Justin Thalere412dc22018-01-12 16:28:24 -0600474 try:
Justin Thaler27197622019-01-23 14:42:11 -0600475 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600476 except(requests.exceptions.Timeout):
477 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600478
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600479 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600480 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600481 print('User ' +username + ' has been logged out')
482
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600483
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600484def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600485 """
486 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600487
Justin Thalere412dc22018-01-12 16:28:24 -0600488 @param host: string, the hostname or IP address of the bmc
489 @param args: contains additional arguments used by the fru sub command
490 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600491 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
492 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600493 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600494
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600495 #print(url)
496 #res = session.get(url, headers=httpHeader, verify=False)
497 #print(res.text)
498 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600499
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600500 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600501
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600502 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600503 try:
Justin Thaler27197622019-01-23 14:42:11 -0600504 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600505 except(requests.exceptions.Timeout):
506 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600507
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600508 sample = res.text
509# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600510#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600511# #determine column width's
512# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
513# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600514#
515# 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 -0600516# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
517# format the output
518# for key in sorted(inv_list.keys()):
519# keyParts = key.split("/")
520# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600521#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600522# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
523# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
524# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
525# if(isTTY):
526# if(inv_list[key]["is_fru"] == 1):
527# color = "green"
528# bold = True
529# else:
530# color='black'
531# bold = False
532# fruEntry = hilight(fruEntry, color, bold)
533# print (fruEntry)
534 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600535
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600536def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600537 """
538 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600539
Justin Thalere412dc22018-01-12 16:28:24 -0600540 @param host: string, the hostname or IP address of the bmc
541 @param args: contains additional arguments used by the fru sub command
542 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600543 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
544 @return returns the total fru list.
545 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600546 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600547 try:
Justin Thaler27197622019-01-23 14:42:11 -0600548 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600549 except(requests.exceptions.Timeout):
550 return(connectionErrHandler(args.json, "Timeout", None))
551
Justin Thaler3a5771b2019-01-23 14:31:52 -0600552 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600553# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600554 if res.status_code==200:
555 frulist['Hardware'] = res.json()['data']
556 else:
557 if not args.json:
558 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
559 else:
560 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600561 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600562 try:
Justin Thaler27197622019-01-23 14:42:11 -0600563 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600564 except(requests.exceptions.Timeout):
565 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600566# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600567 if res.status_code==200:
568 frulist['Software'] = res.json()['data']
569 else:
570 if not args.json():
571 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
572 else:
573 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600574 return frulist
575
Justin Thalere412dc22018-01-12 16:28:24 -0600576
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600577def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600578 """
579 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600580
Justin Thalere412dc22018-01-12 16:28:24 -0600581 @param host: string, the hostname or IP address of the bmc
582 @param args: contains additional arguments used by the fru sub command
583 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600584 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
585 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600586 if(args.items==True):
587 return fruPrint(host, args, session)
588 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600589 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600590
591
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600592
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600593def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600594 """
595 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600596
Justin Thalere412dc22018-01-12 16:28:24 -0600597 @param host: string, the hostname or IP address of the bmc
598 @param args: contains additional arguments used by the fru sub command
599 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600600 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
601 """
Justin Thalere412dc22018-01-12 16:28:24 -0600602 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600603 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600604 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600605 except(requests.exceptions.Timeout):
606 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600607# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600608 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600609 frus = {}
610 for key in frulist:
611 component = frulist[key]
612 isFru = False
613 present = False
614 func = False
615 hasSels = False
616 keyPieces = key.split('/')
617 fruName = keyPieces[-1]
618 if 'core' in fruName: #associate cores to cpus
619 fruName = keyPieces[-2] + '-' + keyPieces[-1]
620 if 'Functional' in component:
621 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600622 if 'FieldReplaceable' in component:
623 if component['FieldReplaceable'] == 1:
624 isFru = True
625 if "fan" in fruName:
626 isFru = True;
627 if component['Present'] == 1:
628 present = True
629 if component['Functional'] == 1:
630 func = True
631 if ((key + "/fault") in frulist):
632 hasSels = True;
633 if args.verbose:
634 if hasSels:
635 loglist = []
636 faults = frulist[key+"/fault"]['endpoints']
637 for item in faults:
638 loglist.append(item.split('/')[-1])
639 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
640 else:
641 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
642 else:
643 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500644 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600645 if component['Present'] ==1:
646 present = True
647 isFru = True
648 if ((key + "/fault") in frulist):
649 hasSels = True;
650 if args.verbose:
651 if hasSels:
652 loglist = []
653 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100654 for item in faults:
655 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600656 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
657 else:
658 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
659 else:
660 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
661 if not args.json:
662 if not args.verbose:
663 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
664 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
665 else:
666 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
667 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
668 return tableDisplay(keylist, colNames, frus)
669 else:
670 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600671
Justin Thalere412dc22018-01-12 16:28:24 -0600672def sensor(host, args, session):
673 """
674 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600675
Justin Thalere412dc22018-01-12 16:28:24 -0600676 @param host: string, the hostname or IP address of the bmc
677 @param args: contains additional arguments used by the sensor sub command
678 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600679 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
680 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600681 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600682 try:
Justin Thaler27197622019-01-23 14:42:11 -0600683 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600684 except(requests.exceptions.Timeout):
685 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600686
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600687 #Get OCC status
688 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600689 try:
Justin Thaler27197622019-01-23 14:42:11 -0600690 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600691 except(requests.exceptions.Timeout):
692 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600693 if not args.json:
694 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600695 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600696 output = {}
697 for key in sensors:
698 senDict = {}
699 keyparts = key.split("/")
Matt Spinler596ef742019-09-20 08:54:36 -0500700
701 # Associations like the following also show up here:
702 # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
703 # Skip them.
704 # Note: keyparts[0] = '' which is why there are 7 segments.
705 if len(keyparts) > 6:
706 continue
707
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600708 senDict['sensorName'] = keyparts[-1]
709 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600710 try:
711 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
712 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500713 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600714 if('Scale' in sensors[key]):
715 scale = 10 ** sensors[key]['Scale']
716 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600717 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500718 try:
719 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600720 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500721 if 'value' in sensors[key]:
722 senDict['value'] = sensors[key]['value']
723 else:
724 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600725 if 'Target' in sensors[key]:
726 senDict['target'] = str(sensors[key]['Target'])
727 else:
728 senDict['target'] = 'N/A'
729 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600730
Justin Thaler3a5771b2019-01-23 14:31:52 -0600731 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600732 if '/org/open_power/control/occ0' in occstatus:
733 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600734 if occ0 == 1:
735 occ0 = 'Active'
736 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600737 occ0 = 'Inactive'
738 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
739 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600740 if occ1 == 1:
741 occ1 = 'Active'
742 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600743 occ1 = 'Inactive'
744 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
745 else:
746 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
747 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
748 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600749
750 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600751 else:
752 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600753
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600754def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600755 """
756 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600757
Justin Thalere412dc22018-01-12 16:28:24 -0600758 @param host: string, the hostname or IP address of the bmc
759 @param args: contains additional arguments used by the sel sub command
760 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600761 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
762 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600763
764 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600765 try:
Justin Thaler27197622019-01-23 14:42:11 -0600766 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600767 except(requests.exceptions.Timeout):
768 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600769 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600770
771
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600772def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600773 """
774 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600775
Justin Thalere412dc22018-01-12 16:28:24 -0600776 @param eselRAW: string, the raw esel string from the bmc
777 @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 -0600778 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600779 eselParts = {}
780 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
781 #search terms contains the search term as the key and the return dictionary key as it's value
782 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500783 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600784 uniqueID = str(uuid.uuid4())
785 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500786 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600787 f.write(esel_bin)
788 errlPath = ""
789 #use the right errl file for the machine architecture
790 arch = platform.machine()
791 if(arch =='x86_64' or arch =='AMD64'):
792 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
793 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
794 elif os.path.exists('errl/x86_64/errl'):
795 errlPath = 'errl/x86_64/errl'
796 else:
797 errlPath = 'x86_64/errl'
798 elif (platform.machine()=='ppc64le'):
799 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
800 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
801 elif os.path.exists('errl/ppc64le/errl'):
802 errlPath = 'errl/ppc64le/errl'
803 else:
804 errlPath = 'ppc64le/errl'
805 else:
806 print("machine architecture not supported for parsing eSELs")
807 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600808
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600809 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500810 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600811# output = proc.communicate()[0]
812 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600813
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600814 if(hasattr(args, 'fullEsel')):
815 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600816
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600817 for i in range(0, len(lines)):
818 lineParts = lines[i].split(':')
819 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
820 for term in searchTerms:
821 if(term in lineParts[0]):
822 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
823 if lines[i+1].find(':') != -1:
824 if (len(lines[i+1].split(':')[0][1:].strip())==0):
825 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600826 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600827 if((i+1) <= len(lines)):
828 i+=1
829 else:
830 i=i-1
831 break
Justin Thaler43030422018-11-08 22:50:21 -0600832 #Append the content from the next line removing the pretty display characters
833 #Finds the first colon then starts 2 characters after, then removes all whitespace
834 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500835 if(searchTerms[term] in eselParts):
836 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
837 else:
838 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500839 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600840 else:
841 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600842
843 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600844
Justin Thalere412dc22018-01-12 16:28:24 -0600845
Matt Spinler02d0dff2018-08-29 13:19:25 -0500846def getESELSeverity(esel):
847 """
848 Finds the severity type in an eSEL from the User Header section.
849 @param esel - the eSEL data
850 @return severity - e.g. 'Critical'
851 """
852
853 # everything but 1 and 2 are Critical
854 # '1': 'recovered',
855 # '2': 'predictive',
856 # '4': 'unrecoverable',
857 # '5': 'critical',
858 # '6': 'diagnostic',
859 # '7': 'symptom'
860 severities = {
861 '1': 'Informational',
862 '2': 'Warning'
863 }
864
865 try:
866 headerPosition = esel.index('55 48') # 'UH'
867 # The severity is the last byte in the 8 byte section (a byte is ' bb')
868 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
869 type = severity[0]
870 except ValueError:
871 print("Could not find severity value in UH section in eSEL")
872 type = 'x';
873
874 return severities.get(type, 'Critical')
875
876
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600877def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600878 """
879 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600880
Justin Thalere412dc22018-01-12 16:28:24 -0600881 @param events: Dictionary containing events
882 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600883 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600884 logNumList = []
885 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600886 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600887 eventsWithTimestamp = {}
888 logNum2events = {}
889 for key in events:
890 if key == 'numAlerts': continue
891 if 'callout' in key: continue
892 timestamp = (events[key]['timestamp'])
893 if timestamp not in timestampList:
894 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
895 else:
896 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
897 #map logNumbers to the event dictionary keys
898 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600899
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600900 timestampList = list(eventsWithTimestamp.keys())
901 timestampList.sort()
902 for ts in timestampList:
903 if len(eventsWithTimestamp[ts]) > 1:
904 tmplist = eventsWithTimestamp[ts]
905 tmplist.sort()
906 logNumList = logNumList + tmplist
907 else:
908 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600909
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600910 return [logNumList, eventKeyDict]
911
Justin Thalere412dc22018-01-12 16:28:24 -0600912
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600913def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600914 """
915 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600916
Justin Thalere412dc22018-01-12 16:28:24 -0600917 @param policyTable: dictionary, the policy table entries
918 @param selEntries: dictionary, the alerts retrieved from the bmc
919 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600920 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600921 eventDict = {}
922 eventNum =""
923 count = 0
924 esel = ""
925 eselParts = {}
926 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500927 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600928
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600929 'prepare and sort the event entries'
Justin Thaler667f87c2020-04-06 16:13:12 -0500930 sels = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600931 for key in selEntries:
Justin Thaler667f87c2020-04-06 16:13:12 -0500932 if '/xyz/openbmc_project/logging/entry/' not in key: continue
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600933 if 'callout' not in key:
Justin Thaler667f87c2020-04-06 16:13:12 -0500934 sels[key] = selEntries[key]
935 sels[key]['logNum'] = key.split('/')[-1]
936 sels[key]['timestamp'] = selEntries[key]['Timestamp']
937 sortedEntries = sortSELs(sels)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600938 logNumList = sortedEntries[0]
939 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600940
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600941 for logNum in logNumList:
942 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600943 hasEsel=False
944 i2creadFail = False
945 if 'callout' in key:
946 continue
947 else:
948 messageID = str(selEntries[key]['Message'])
949 addDataPiece = selEntries[key]['AdditionalData']
950 calloutIndex = 0
951 calloutFound = False
952 for i in range(len(addDataPiece)):
953 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
954 calloutIndex = i
955 calloutFound = True
956 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
957 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
958 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500959
960 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
961
962 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
963 if (messageID + '||' + fruCallout) not in policyTable:
964 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
965 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
966 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
967 fruCallout = 'FSI'
968 else:
969 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500970 calloutFound = True
971 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
972 if not calloutFound:
973 fruCallout = 'GPIO'
974 calloutFound = True
975 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
976 if not calloutFound:
977 fruCallout = "I2C"
978 calloutFound = True
979 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
980 if not calloutFound:
981 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600982 calloutFound = True
983 if("ESEL" in addDataPiece[i]):
984 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500985 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600986 if args.devdebug:
987 eselParts = parseESEL(args, esel)
988 hasEsel=True
989 if("GPU" in addDataPiece[i]):
990 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
991 calloutFound = True
992 if("PROCEDURE" in addDataPiece[i]):
993 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
994 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600995 if("RAIL_NAME" in addDataPiece[i]):
996 calloutFound=True
997 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
998 if("INPUT_NAME" in addDataPiece[i]):
999 calloutFound=True
1000 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1001 if("SENSOR_TYPE" in addDataPiece[i]):
1002 calloutFound=True
1003 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001004
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001005 if(calloutFound):
Justin Thaler667f87c2020-04-06 16:13:12 -05001006 if fruCallout.strip() != "":
Justin Thaler22b1bb52018-03-15 13:31:32 -05001007 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -05001008
1009 # Also use the severity for hostboot errors
1010 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
1011 policyKey += '||' + eselSeverity
1012
1013 # if not in the table, fall back to the original key
1014 if policyKey not in policyTable:
1015 policyKey = policyKey.replace('||'+eselSeverity, '')
1016
Justin Thalere34c43a2018-05-25 19:37:55 -05001017 if policyKey not in policyTable:
1018 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -05001019 else:
1020 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001021 else:
1022 policyKey = messageID
1023 event = {}
1024 eventNum = str(count)
1025 if policyKey in policyTable:
1026 for pkey in policyTable[policyKey]:
1027 if(type(policyTable[policyKey][pkey])== bool):
1028 event[pkey] = boolToString(policyTable[policyKey][pkey])
1029 else:
1030 if (i2creadFail and pkey == 'Message'):
1031 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
1032 else:
1033 event[pkey] = policyTable[policyKey][pkey]
1034 event['timestamp'] = selEntries[key]['Timestamp']
1035 event['resolved'] = bool(selEntries[key]['Resolved'])
1036 if(hasEsel):
1037 if args.devdebug:
1038 event['eselParts'] = eselParts
1039 event['raweSEL'] = esel
1040 event['logNum'] = key.split('/')[-1]
1041 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001042
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001043 else:
1044 severity = str(selEntries[key]['Severity']).split('.')[-1]
1045 if severity == 'Error':
1046 severity = 'Critical'
1047 eventDict['event'+eventNum] = {}
1048 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
1049 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
1050 eventDict['event' + eventNum]['Severity'] = severity
1051 if(hasEsel):
1052 if args.devdebug:
1053 eventDict['event' +eventNum]['eselParts'] = eselParts
1054 eventDict['event' +eventNum]['raweSEL'] = esel
1055 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
1056 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001057 count += 1
1058 return eventDict
1059
1060
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001061def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -06001062 """
1063 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001064
Justin Thalere412dc22018-01-12 16:28:24 -06001065 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001066 @return:
1067 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001068 activeAlerts = []
1069 historyAlerts = []
1070 sortedEntries = sortSELs(events)
1071 logNumList = sortedEntries[0]
1072 eventKeyDict = sortedEntries[1]
1073 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
1074 if(args.devdebug):
1075 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
1076 keylist.append('eSEL')
1077 else:
1078 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
1079 for log in logNumList:
1080 selDict = {}
1081 alert = events[eventKeyDict[str(log)]]
1082 if('error' in alert):
1083 selDict['Entry'] = alert['logNum']
1084 selDict['ID'] = 'Unknown'
1085 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1086 msg = alert['error']
1087 polMsg = msg.split("policy table:")[0]
1088 msg = msg.split("policy table:")[1]
1089 msgPieces = msg.split("||")
1090 err = msgPieces[0]
1091 if(err.find("org.open_power.")!=-1):
1092 err = err.split("org.open_power.")[1]
1093 elif(err.find("xyz.openbmc_project.")!=-1):
1094 err = err.split("xyz.openbmc_project.")[1]
1095 else:
1096 err = msgPieces[0]
1097 callout = ""
1098 if len(msgPieces) >1:
1099 callout = msgPieces[1]
1100 if(callout.find("/org/open_power/")!=-1):
1101 callout = callout.split("/org/open_power/")[1]
1102 elif(callout.find("/xyz/openbmc_project/")!=-1):
1103 callout = callout.split("/xyz/openbmc_project/")[1]
1104 else:
1105 callout = msgPieces[1]
1106 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001107 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001108 selDict['Severity'] = alert['Severity']
1109 else:
1110 selDict['Entry'] = alert['logNum']
1111 selDict['ID'] = alert['CommonEventID']
1112 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001113 selDict['Message'] = alert['Message']
1114 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001115 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001116
1117
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001118 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
1119 if ('eselParts' in alert and args.devdebug):
1120 eselOutput = ""
1121 for item in eselOrder:
1122 if item in alert['eselParts']:
1123 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
1124 selDict['eSEL'] = eselOutput
1125 else:
1126 if args.devdebug:
1127 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001128
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001129 if not alert['resolved']:
1130 activeAlerts.append(selDict)
1131 else:
1132 historyAlerts.append(selDict)
1133 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001134 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
1135
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001136 output = ""
1137 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001138 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001139 output +="----Active Alerts----\n"
1140 for i in range(0, len(colNames)):
1141 if i!=0: row =row + "| "
1142 row = row + colNames[i].ljust(colWidth[i])
1143 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001144
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001145 for i in range(0,len(activeAlerts)):
1146 row = ""
1147 for j in range(len(activeAlerts[i])):
1148 if (j != 0): row = row + "| "
1149 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
1150 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001151
1152 if(len(historyAlerts)>0):
1153 row = ""
1154 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001155 for i in range(len(colNames)):
1156 if i!=0: row =row + "| "
1157 row = row + colNames[i].ljust(colWidth[i])
1158 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001159
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001160 for i in range(0, len(historyAlerts)):
1161 row = ""
1162 for j in range(len(historyAlerts[i])):
1163 if (j != 0): row = row + "| "
1164 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
1165 output += row + "\n"
1166# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001167 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001168
Justin Thalere412dc22018-01-12 16:28:24 -06001169
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001170def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001171 """
1172 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001173
Justin Thalere412dc22018-01-12 16:28:24 -06001174 @param host: string, the hostname or IP address of the bmc
1175 @param args: contains additional arguments used by the fru sub command
1176 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001177 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1178 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001179 if(args.policyTableLoc is None):
1180 if os.path.exists('policyTable.json'):
1181 ptableLoc = "policyTable.json"
1182 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1183 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1184 else:
1185 ptableLoc = 'lib/policyTable.json'
1186 else:
1187 ptableLoc = args.policyTableLoc
1188 policyTable = loadPolicyTable(ptableLoc)
1189 rawselEntries = ""
1190 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1191 if os.path.exists(args.fileloc):
1192 with open(args.fileloc, 'r') as selFile:
1193 selLines = selFile.readlines()
1194 rawselEntries = ''.join(selLines)
1195 else:
1196 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001197 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001198 else:
1199 rawselEntries = sel(host, args, session)
1200 loadFailed = False
1201 try:
1202 selEntries = json.loads(rawselEntries)
1203 except ValueError:
1204 loadFailed = True
1205 if loadFailed:
1206 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1207 #need to load json twice as original content was string escaped a second time
1208 selEntries = json.loads(json.loads(cleanSels))
1209 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001210
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001211 if 'description' in selEntries:
1212 if(args.json):
1213 return("{\n\t\"numAlerts\": 0\n}")
1214 else:
1215 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001216
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001217 else:
1218 if(len(policyTable)>0):
1219 events = parseAlerts(policyTable, selEntries, args)
1220 if(args.json):
1221 events["numAlerts"] = len(events)
1222 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1223 return retValue
1224 elif(hasattr(args, 'fullSel')):
1225 return events
1226 else:
1227 #get log numbers to order event entries sequentially
1228 return selDisplay(events, args)
1229 else:
1230 if(args.json):
1231 return selEntries
1232 else:
1233 print("error: Policy Table not found.")
1234 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001235
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001236def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001237 """
1238 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001239
Justin Thalere412dc22018-01-12 16:28:24 -06001240 @param host: string, the hostname or IP address of the bmc
1241 @param args: contains additional arguments used by the fru sub command
1242 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001243 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1244 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001245 return(sel(host, args, session))
1246
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001247
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001248def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001249 """
1250 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001251
Justin Thalere412dc22018-01-12 16:28:24 -06001252 @param host: string, the hostname or IP address of the bmc
1253 @param args: contains additional arguments used by the fru sub command
1254 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001255 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1256 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001257 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001258 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001259
Justin Thalere412dc22018-01-12 16:28:24 -06001260 try:
Justin Thaler27197622019-01-23 14:42:11 -06001261 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001262 except(requests.exceptions.Timeout):
1263 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001264 if res.status_code == 200:
1265 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1266 else:
1267 print("Unable to clear the logs, trying to clear 1 at a time")
1268 sels = json.loads(sel(host, args, session))['data']
1269 for key in sels:
1270 if 'callout' not in key:
1271 logNum = key.split('/')[-1]
1272 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1273 try:
Justin Thaler27197622019-01-23 14:42:11 -06001274 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001275 except(requests.exceptions.Timeout):
1276 return connectionErrHandler(args.json, "Timeout", None)
1277 sys.exit(1)
1278 except(requests.exceptions.ConnectionError) as err:
1279 return connectionErrHandler(args.json, "ConnectionError", err)
1280 sys.exit(1)
1281 return ('Sel clearing complete')
1282
1283def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001284 """
1285 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001286
Justin Thalere412dc22018-01-12 16:28:24 -06001287 @param host: string, the hostname or IP address of the bmc
1288 @param args: contains additional arguments used by the fru sub command
1289 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001290 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1291 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001292 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001293 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001294 try:
Justin Thaler27197622019-01-23 14:42:11 -06001295 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001296 except(requests.exceptions.Timeout):
1297 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001298 if res.status_code == 200:
1299 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1300 else:
1301 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001302
Justin Thalere412dc22018-01-12 16:28:24 -06001303def selResolveAll(host, args, session):
1304 """
1305 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001306
Justin Thalere412dc22018-01-12 16:28:24 -06001307 @param host: string, the hostname or IP address of the bmc
1308 @param args: contains additional arguments used by the fru sub command
1309 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001310 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1311 """
Justin Thalere412dc22018-01-12 16:28:24 -06001312 rawselEntries = sel(host, args, session)
1313 loadFailed = False
1314 try:
1315 selEntries = json.loads(rawselEntries)
1316 except ValueError:
1317 loadFailed = True
1318 if loadFailed:
1319 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1320 #need to load json twice as original content was string escaped a second time
1321 selEntries = json.loads(json.loads(cleanSels))
1322 selEntries = selEntries['data']
1323
1324 if 'description' in selEntries:
1325 if(args.json):
1326 return("{\n\t\"selsResolved\": 0\n}")
1327 else:
1328 return("No log entries found")
1329 else:
1330 d = vars(args)
1331 successlist = []
1332 failedlist = []
1333 for key in selEntries:
1334 if 'callout' not in key:
1335 d['selNum'] = key.split('/')[-1]
1336 resolved = selSetResolved(host,args,session)
1337 if 'Sel entry' in resolved:
1338 successlist.append(d['selNum'])
1339 else:
1340 failedlist.append(d['selNum'])
1341 output = ""
1342 successlist.sort()
1343 failedlist.sort()
1344 if len(successlist)>0:
1345 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1346 if len(failedlist)>0:
1347 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1348 return output
1349
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001350def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001351 """
1352 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001353
Justin Thalere412dc22018-01-12 16:28:24 -06001354 @param host: string, the hostname or IP address of the bmc
1355 @param args: contains additional arguments used by the fru sub command
1356 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001357 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1358 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001359 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001360 if checkFWactivation(host, args, session):
1361 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001362 print("Attempting to Power on...:")
1363 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001364 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001365 try:
Justin Thaler27197622019-01-23 14:42:11 -06001366 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001367 except(requests.exceptions.Timeout):
1368 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001369 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001370 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001371 if checkFWactivation(host, args, session):
1372 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001373 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001374 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001375 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001376 try:
Justin Thaler27197622019-01-23 14:42:11 -06001377 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001378 except(requests.exceptions.Timeout):
1379 return(connectionErrHandler(args.json, "Timeout", None))
1380 return res.text
1381 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001382 if checkFWactivation(host, args, session):
1383 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001384 print("Attempting to Power off immediately...:")
1385 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001386 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1387 try:
Justin Thaler27197622019-01-23 14:42:11 -06001388 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001389 except(requests.exceptions.Timeout):
1390 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001391 return res.text
1392 elif(args.powcmd == 'status'):
1393 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001394 try:
Justin Thaler27197622019-01-23 14:42:11 -06001395 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001396 except(requests.exceptions.Timeout):
1397 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001398 chassisState = json.loads(res.text)['data'].split('.')[-1]
1399 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001400 try:
Justin Thaler27197622019-01-23 14:42:11 -06001401 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001402 except(requests.exceptions.Timeout):
1403 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001404 hostState = json.loads(res.text)['data'].split('.')[-1]
1405 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001406 try:
Justin Thaler27197622019-01-23 14:42:11 -06001407 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001408 except(requests.exceptions.Timeout):
1409 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001410 bmcState = json.loads(res.text)['data'].split('.')[-1]
1411 if(args.json):
1412 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1413 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1414 else:
1415 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1416 else:
1417 return "Invalid chassis power command"
1418
Justin Thalere412dc22018-01-12 16:28:24 -06001419
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001420def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001421 """
1422 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001423
Justin Thalere412dc22018-01-12 16:28:24 -06001424 @param host: string, the hostname or IP address of the bmc
1425 @param args: contains additional arguments used by the fru sub command
1426 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001427 @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 -06001428 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001429 if(args.identcmd == 'on'):
1430 print("Attempting to turn identify light on...:")
1431 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001432 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001433 try:
Justin Thaler27197622019-01-23 14:42:11 -06001434 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001435 except(requests.exceptions.Timeout):
1436 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001437 return res.text
1438 elif(args.identcmd == 'off'):
1439 print("Attempting to turn identify light off...:")
1440 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001441 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001442 try:
Justin Thaler27197622019-01-23 14:42:11 -06001443 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001444 except(requests.exceptions.Timeout):
1445 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001446 return res.text
1447 elif(args.identcmd == 'status'):
1448 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001449 try:
Justin Thaler27197622019-01-23 14:42:11 -06001450 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001451 except(requests.exceptions.Timeout):
1452 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001453 status = json.loads(res.text)['data']
1454 if(args.json):
1455 return status
1456 else:
1457 if status['Asserted'] == 0:
1458 return "Identify light is off"
1459 else:
1460 return "Identify light is blinking"
1461 else:
1462 return "Invalid chassis identify command"
1463
Justin Thalere412dc22018-01-12 16:28:24 -06001464
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001465def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001466 """
1467 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001468
Justin Thalere412dc22018-01-12 16:28:24 -06001469 @param host: string, the hostname or IP address of the bmc
1470 @param args: contains additional arguments used by the fru sub command
1471 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001472 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1473 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001474 if(hasattr(args, 'powcmd')):
1475 result = chassisPower(host,args,session)
1476 elif(hasattr(args, 'identcmd')):
1477 result = chassisIdent(host, args, session)
1478 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001479 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001480 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001481
Ravi Tejad8be0b42020-03-18 14:31:46 -05001482def dumpRetrieve(host, args, session):
1483 """
1484 Downloads dump of given dump type
1485
1486 @param host: string, the hostname or IP address of the bmc
1487 @param args: contains additional arguments used by the collectServiceData sub command
1488 @param session: the active session to use
1489 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1490 """
1491 dumpType = args.dumpType
1492 if (args.dumpType=="SystemDump"):
1493 dumpResp=systemDumpRetrieve(host,args,session)
1494 elif(args.dumpType=="bmc"):
1495 dumpResp=bmcDumpRetrieve(host,args,session)
1496 return dumpResp
1497
1498def dumpList(host, args, session):
1499 """
1500 Lists dump of the given dump type
1501
1502 @param host: string, the hostname or IP address of the bmc
1503 @param args: contains additional arguments used by the collectServiceData sub command
1504 @param session: the active session to use
1505 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1506 """
1507 if (args.dumpType=="SystemDump"):
1508 dumpResp=systemDumpList(host,args,session)
1509 elif(args.dumpType=="bmc"):
1510 dumpResp=bmcDumpList(host,args,session)
1511 return dumpResp
1512
1513def dumpDelete(host, args, session):
1514 """
1515 Deletes dump of the given dump type
1516
1517 @param host: string, the hostname or IP address of the bmc
1518 @param args: contains additional arguments used by the collectServiceData sub command
1519 @param session: the active session to use
1520 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1521 """
1522 if (args.dumpType=="SystemDump"):
1523 dumpResp=systemDumpDelete(host,args,session)
1524 elif(args.dumpType=="bmc"):
1525 dumpResp=bmcDumpDelete(host,args,session)
1526 return dumpResp
1527
1528def dumpDeleteAll(host, args, session):
1529 """
1530 Deletes all dumps of the given dump type
1531
1532 @param host: string, the hostname or IP address of the bmc
1533 @param args: contains additional arguments used by the collectServiceData sub command
1534 @param session: the active session to use
1535 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1536 """
1537 if (args.dumpType=="SystemDump"):
1538 dumpResp=systemDumpDeleteAll(host,args,session)
1539 elif(args.dumpType=="bmc"):
1540 dumpResp=bmcDumpDeleteAll(host,args,session)
1541 return dumpResp
1542
1543def dumpCreate(host, args, session):
1544 """
1545 Creates dump for the given dump type
1546
1547 @param host: string, the hostname or IP address of the bmc
1548 @param args: contains additional arguments used by the collectServiceData sub command
1549 @param session: the active session to use
1550 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1551 """
1552 if (args.dumpType=="SystemDump"):
1553 dumpResp=systemDumpCreate(host,args,session)
1554 elif(args.dumpType=="bmc"):
Justin Thaler0a3e1692020-04-07 19:10:40 -05001555 dumpResp=bmcDumpCreate(host,args,session)
Ravi Tejad8be0b42020-03-18 14:31:46 -05001556 return dumpResp
1557
1558
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001559def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001560 """
1561 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001562
Justin Thalere412dc22018-01-12 16:28:24 -06001563 @param host: string, the hostname or IP address of the bmc
1564 @param args: contains additional arguments used by the collectServiceData sub command
1565 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001566 @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 -06001567 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001568 dumpNum = args.dumpNum
1569 if (args.dumpSaveLoc is not None):
1570 saveLoc = args.dumpSaveLoc
1571 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001572 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001573 url ='https://'+host+'/download/dump/' + str(dumpNum)
1574 try:
Justin Thaler27197622019-01-23 14:42:11 -06001575 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001576 if (args.dumpSaveLoc is not None):
1577 if os.path.exists(saveLoc):
1578 if saveLoc[-1] != os.path.sep:
1579 saveLoc = saveLoc + os.path.sep
1580 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001581
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001582 else:
1583 return 'Invalid save location specified'
1584 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001585 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001586
1587 with open(filename, 'wb') as f:
1588 for chunk in r.iter_content(chunk_size =1024):
1589 if chunk:
1590 f.write(chunk)
1591 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001592
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001593 except(requests.exceptions.Timeout):
1594 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001595
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001596 except(requests.exceptions.ConnectionError) as err:
1597 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001598
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001599def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001600 """
1601 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001602
Justin Thalere412dc22018-01-12 16:28:24 -06001603 @param host: string, the hostname or IP address of the bmc
1604 @param args: contains additional arguments used by the collectServiceData sub command
1605 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001606 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1607 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001608 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1609 try:
Justin Thaler27197622019-01-23 14:42:11 -06001610 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001611 dumpList = r.json()
Justin Thaler3b3c6582020-04-07 19:17:36 -05001612 formattedList = []
1613 #remove items that aren't dump entries 'entry, internal, manager endpoints'
1614 if 'data' in dumpList:
1615 for entry in dumpList['data']:
1616 if 'entry' in entry:
1617 if entry.split('/')[-1].isnumeric():
1618 formattedList.append(entry)
1619 dumpList['data']= formattedList
Justin Thaler3a5771b2019-01-23 14:31:52 -06001620 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001621 except(requests.exceptions.Timeout):
1622 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001623
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001624 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001625 return connectionErrHandler(args.json, "ConnectionError", err)
1626
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001627def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001628 """
1629 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001630
Justin Thalere412dc22018-01-12 16:28:24 -06001631 @param host: string, the hostname or IP address of the bmc
1632 @param args: contains additional arguments used by the collectServiceData sub command
1633 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001634 @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 -06001635 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001636 dumpList = []
1637 successList = []
1638 failedList = []
1639 if args.dumpNum is not None:
1640 if isinstance(args.dumpNum, list):
1641 dumpList = args.dumpNum
1642 else:
1643 dumpList.append(args.dumpNum)
1644 for dumpNum in dumpList:
1645 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1646 try:
Justin Thaler27197622019-01-23 14:42:11 -06001647 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001648 if r.status_code == 200:
1649 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001650 else:
1651 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001652 except(requests.exceptions.Timeout):
1653 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001654 except(requests.exceptions.ConnectionError) as err:
1655 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001656 output = "Successfully deleted dumps: " + ', '.join(successList)
1657 if(len(failedList)>0):
1658 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1659 return output
1660 else:
1661 return 'You must specify an entry number to delete'
1662
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001663def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001664 """
1665 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001666
Justin Thalere412dc22018-01-12 16:28:24 -06001667 @param host: string, the hostname or IP address of the bmc
1668 @param args: contains additional arguments used by the collectServiceData sub command
1669 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001670 @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 -06001671 """
1672 dumpResp = bmcDumpList(host, args, session)
1673 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1674 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001675 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001676 d = vars(args)
1677 dumpNums = []
1678 for dump in dumpList:
Alvin Wang28bd09d2019-10-28 13:23:58 +08001679 dumpNum = dump.strip().split('/')[-1]
1680 if dumpNum.isdigit():
1681 dumpNums.append(int(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001682 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001683
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001684 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001685
Justin Thalere412dc22018-01-12 16:28:24 -06001686
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001687def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001688 """
1689 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001690
Justin Thalere412dc22018-01-12 16:28:24 -06001691 @param host: string, the hostname or IP address of the bmc
1692 @param args: contains additional arguments used by the collectServiceData sub command
1693 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001694 @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 -06001695 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001696 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1697 try:
Justin Thaler27197622019-01-23 14:42:11 -06001698 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thaler2f59aea2020-04-07 19:27:01 -05001699 info = r.json()
Matt Spinlereae05b02019-01-24 12:59:34 -06001700 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001701 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001702 elif(args.json):
Justin Thaler2f59aea2020-04-07 19:27:01 -05001703 return info
1704 elif 'data' in info:
1705 if 'QuotaExceeded' in info['data']['description']:
1706 return 'BMC dump space is full. Please delete at least one existing dump entry and try again.'
1707 else:
1708 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001709 else:
Justin Thaler2f59aea2020-04-07 19:27:01 -05001710 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001711 except(requests.exceptions.Timeout):
1712 return connectionErrHandler(args.json, "Timeout", None)
1713 except(requests.exceptions.ConnectionError) as err:
1714 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001715
Justin Thaler2f59aea2020-04-07 19:27:01 -05001716
Ravi Tejad8be0b42020-03-18 14:31:46 -05001717def systemDumpRetrieve(host, args, session):
1718 """
1719 Downloads system dump
1720
1721 @param host: string, the hostname or IP address of the bmc
1722 @param args: contains additional arguments used by the collectServiceData sub command
1723 @param session: the active session to use
1724 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1725 """
1726 NBDSetup(host,args,session)
1727 pipe = NBDPipe()
1728 pipe.openHTTPSocket(args)
1729 pipe.openTCPSocket()
1730 pipe.waitformessage()
1731
1732def systemDumpList(host, args, session):
1733 """
1734 Lists system dumps
1735
1736 @param host: string, the hostname or IP address of the bmc
1737 @param args: contains additional arguments used by the collectServiceData sub command
1738 @param session: the active session to use
1739 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1740 """
1741 print("in systemDumpList")
1742 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/"+args.dumpType+"/Entries"
1743 try:
1744 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1745 dumpList = r.json()
1746 return dumpList
1747 except(requests.exceptions.Timeout):
1748 return connectionErrHandler(args.json, "Timeout", None)
1749
1750 except(requests.exceptions.ConnectionError) as err:
1751 return connectionErrHandler(args.json, "ConnectionError", err)
1752
1753
1754def systemDumpDelete(host, args, session):
1755 """
1756 Deletes system dump
1757
1758 @param host: string, the hostname or IP address of the bmc
1759 @param args: contains additional arguments used by the collectServiceData sub command
1760 @param session: the active session to use
1761 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1762 """
1763 dumpList = []
1764 successList = []
1765 failedList = []
1766 if args.dumpNum is not None:
1767 if isinstance(args.dumpNum, list):
1768 dumpList = args.dumpNum
1769 else:
1770 dumpList.append(args.dumpNum)
1771 for dumpNum in dumpList:
1772 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Entries/'+ str(dumpNum)
1773 try:
1774 r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1775 if r.status_code == 200:
1776 successList.append(str(dumpNum))
1777 else:
1778 failedList.append(str(dumpNum))
1779 except(requests.exceptions.Timeout):
1780 return connectionErrHandler(args.json, "Timeout", None)
1781 except(requests.exceptions.ConnectionError) as err:
1782 return connectionErrHandler(args.json, "ConnectionError", err)
1783 output = "Successfully deleted dumps: " + ', '.join(successList)
1784 if(len(failedList)>0):
1785 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1786 return output
1787 else:
1788 return 'You must specify an entry number to delete'
1789
1790def systemDumpDeleteAll(host, args, session):
1791 """
1792 Deletes All system dumps
1793
1794 @param host: string, the hostname or IP address of the bmc
1795 @param args: contains additional arguments used by the collectServiceData sub command
1796 @param session: the active session to use
1797 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1798 """
1799 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/LogService.ClearLog'
1800 try:
1801 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1802 if(r.status_code == 200 and not args.json):
1803 return ('Dumps successfully cleared')
1804 elif(args.json):
1805 return r.json()
1806 else:
1807 return ('Failed to clear dumps')
1808 except(requests.exceptions.Timeout):
1809 return connectionErrHandler(args.json, "Timeout", None)
1810 except(requests.exceptions.ConnectionError) as err:
1811 return connectionErrHandler(args.json, "ConnectionError", err)
1812
1813def systemDumpCreate(host, args, session):
1814 """
1815 Creates a system dump
1816
1817 @param host: string, the hostname or IP address of the bmc
1818 @param args: contains additional arguments used by the collectServiceData sub command
1819 @param session: the active session to use
1820 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1821 """
1822 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/Oem/Openbmc/LogService.CreateLog'
1823 try:
1824 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1825 if(r.status_code == 200 and not args.json):
1826 return ('Dump successfully created')
1827 elif(args.json):
1828 return r.json()
1829 else:
1830 return ('Failed to create dump')
1831 except(requests.exceptions.Timeout):
1832 return connectionErrHandler(args.json, "Timeout", None)
1833 except(requests.exceptions.ConnectionError) as err:
1834 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001835
Justin Thaler666cf342019-01-23 14:44:27 -06001836def csdDumpInitiate(host, args, session):
1837 """
1838 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001839
Justin Thaler666cf342019-01-23 14:44:27 -06001840 @param host: string, the hostname or IP address of the bmc
1841 @param args: contains additional arguments used by the collectServiceData sub command
1842 @param session: the active session to use
1843 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1844 """
1845 errorInfo = ""
1846 dumpcount = 0
1847 try:
1848 d = vars(args)
1849 d['json'] = True
1850 except Exception as e:
1851 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001852 exc_type, exc_obj, exc_tb = sys.exc_info()
1853 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1854 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1855 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001856
1857 try:
1858 for i in range(3):
1859 dumpInfo = bmcDumpList(host, args, session)
1860 if 'data' in dumpInfo:
1861 dumpcount = len(dumpInfo['data'])
1862 break
1863 else:
1864 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1865 except Exception as e:
1866 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001867 exc_type, exc_obj, exc_tb = sys.exc_info()
1868 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1869 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1870 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001871
1872 #Create a user initiated dump
Justin Thalerb4256672020-04-07 19:38:26 -05001873 dumpFailure = True
Justin Thaler666cf342019-01-23 14:44:27 -06001874 try:
1875 for i in range(3):
1876 dumpcreated = bmcDumpCreate(host, args, session)
1877 if 'message' in dumpcreated:
1878 if 'ok' in dumpcreated['message'].lower():
Justin Thalerb4256672020-04-07 19:38:26 -05001879 dumpFailure = False
Justin Thaler666cf342019-01-23 14:44:27 -06001880 break
Justin Thalerb4256672020-04-07 19:38:26 -05001881 elif 'data' in dumpcreated:
1882 if 'QuotaExceeded' in dumpcreated['data']['description']:
1883 print('Not enough dump space on the BMC to create a new dump. Please delete the oldest entry (lowest number) and rerun the collect_service_data command.')
1884 errorInfo+='Dump Space is full. No new dump was created with this collection'
1885 break
1886 else:
1887 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001888 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001889 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001890 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001891 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001892 except Exception as e:
1893 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001894 exc_type, exc_obj, exc_tb = sys.exc_info()
1895 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1896 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1897 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001898
1899 output = {}
1900 output['errors'] = errorInfo
1901 output['dumpcount'] = dumpcount
Justin Thalerb4256672020-04-07 19:38:26 -05001902 if dumpFailure: output['dumpFailure'] = True
Justin Thaler666cf342019-01-23 14:44:27 -06001903 return output
1904
1905def csdInventory(host, args,session, fileDir):
1906 """
1907 Collects the BMC inventory, retrying if necessary
1908
1909 @param host: string, the hostname or IP address of the bmc
1910 @param args: contains additional arguments used by the collectServiceData sub command
1911 @param session: the active session to use
1912 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1913 @param fileDir: string representation of the path to use for putting files created
1914 """
1915 errorInfo = "===========Inventory =============\n"
1916 output={}
1917 inventoryCollected = False
1918 try:
1919 for i in range(3):
1920 frulist = fruPrint(host, args, session)
1921 if 'Hardware' in frulist:
1922 inventoryCollected = True
1923 break
1924 else:
1925 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1926 except Exception as e:
1927 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001928 exc_type, exc_obj, exc_tb = sys.exc_info()
1929 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1930 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1931 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001932 if inventoryCollected:
1933 try:
1934 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1935 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1936 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1937 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1938 except Exception as e:
1939 print("Failed to write inventory to file.")
1940 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001941 exc_type, exc_obj, exc_tb = sys.exc_info()
1942 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1943 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1944 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001945
1946 output['errors'] = errorInfo
1947
1948 return output
1949
1950def csdSensors(host, args,session, fileDir):
1951 """
1952 Collects the BMC sensor readings, retrying if necessary
1953
1954 @param host: string, the hostname or IP address of the bmc
1955 @param args: contains additional arguments used by the collectServiceData sub command
1956 @param session: the active session to use
1957 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1958 @param fileDir: string representation of the path to use for putting files created
1959 """
1960 errorInfo = "===========Sensors =============\n"
1961 sensorsCollected = False
1962 output={}
1963 try:
1964 d = vars(args)
1965 d['json'] = False
1966 except Exception as e:
1967 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001968 exc_type, exc_obj, exc_tb = sys.exc_info()
1969 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1970 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1971 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001972
1973 try:
1974 for i in range(3):
1975 sensorReadings = sensor(host, args, session)
1976 if 'OCC0' in sensorReadings:
1977 sensorsCollected = True
1978 break
1979 else:
1980 errorInfo += sensorReadings
1981 except Exception as e:
1982 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001983 exc_type, exc_obj, exc_tb = sys.exc_info()
1984 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1985 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1986 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001987 if sensorsCollected:
1988 try:
1989 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1990 f.write(sensorReadings)
1991 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1992 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1993 except Exception as e:
1994 print("Failed to write sensor readings to file system.")
1995 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001996 exc_type, exc_obj, exc_tb = sys.exc_info()
1997 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1998 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1999 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002000
2001 output['errors'] = errorInfo
2002 return output
2003
2004def csdLEDs(host,args, session, fileDir):
2005 """
2006 Collects the BMC LED status, retrying if necessary
2007
2008 @param host: string, the hostname or IP address of the bmc
2009 @param args: contains additional arguments used by the collectServiceData sub command
2010 @param session: the active session to use
2011 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2012 @param fileDir: string representation of the path to use for putting files created
2013 """
2014 errorInfo = "===========LEDs =============\n"
2015 ledsCollected = False
2016 output={}
2017 try:
2018 d = vars(args)
2019 d['json'] = True
2020 except Exception as e:
2021 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002022 exc_type, exc_obj, exc_tb = sys.exc_info()
2023 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2024 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2025 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002026 try:
2027 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
2028 httpHeader = {'Content-Type':'application/json'}
2029 for i in range(3):
2030 try:
2031 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2032 if ledRes.status_code == 200:
2033 ledsCollected = True
2034 leds = ledRes.json()['data']
2035 break
2036 else:
2037 errorInfo += ledRes.text
2038 except(requests.exceptions.Timeout):
2039 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2040 except(requests.exceptions.ConnectionError) as err:
2041 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
Justin Thalerb4256672020-04-07 19:38:26 -05002042 exc_type, exc_obj, exc_tb = sys.exc_info()
2043 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2044 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2045 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002046 except Exception as e:
2047 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002048 exc_type, exc_obj, exc_tb = sys.exc_info()
2049 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2050 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2051 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002052
2053 if ledsCollected:
2054 try:
2055 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
2056 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2057 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
2058 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
2059 except Exception as e:
2060 print("Failed to write LED status to file system.")
2061 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002062 exc_type, exc_obj, exc_tb = sys.exc_info()
2063 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2064 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2065 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002066
2067 output['errors'] = errorInfo
2068 return output
2069
2070def csdSelShortList(host, args, session, fileDir):
2071 """
2072 Collects the BMC log entries, retrying if necessary
2073
2074 @param host: string, the hostname or IP address of the bmc
2075 @param args: contains additional arguments used by the collectServiceData sub command
2076 @param session: the active session to use
2077 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2078 @param fileDir: string representation of the path to use for putting files created
2079 """
2080 errorInfo = "===========SEL Short List =============\n"
2081 selsCollected = False
2082 output={}
2083 try:
2084 d = vars(args)
2085 d['json'] = False
2086 except Exception as e:
2087 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002088 exc_type, exc_obj, exc_tb = sys.exc_info()
2089 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2090 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2091 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002092
2093 try:
2094 for i in range(3):
2095 sels = selPrint(host,args,session)
2096 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
2097 selsCollected = True
2098 break
2099 else:
2100 errorInfo += sels + '\n'
2101 except Exception as e:
2102 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002103 exc_type, exc_obj, exc_tb = sys.exc_info()
2104 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2105 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2106 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002107
2108 if selsCollected:
2109 try:
2110 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
2111 f.write(sels)
2112 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
2113 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
2114 except Exception as e:
2115 print("Failed to write SEL short list to file system.")
2116 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002117 exc_type, exc_obj, exc_tb = sys.exc_info()
2118 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2119 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2120 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002121
2122 output['errors'] = errorInfo
2123 return output
2124
2125def csdParsedSels(host, args, session, fileDir):
2126 """
2127 Collects the BMC log entries, retrying if necessary
2128
2129 @param host: string, the hostname or IP address of the bmc
2130 @param args: contains additional arguments used by the collectServiceData sub command
2131 @param session: the active session to use
2132 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2133 @param fileDir: string representation of the path to use for putting files created
2134 """
2135 errorInfo = "===========SEL Parsed List =============\n"
2136 selsCollected = False
2137 output={}
2138 try:
2139 d = vars(args)
2140 d['json'] = True
2141 d['fullEsel'] = True
2142 except Exception as e:
2143 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002144 exc_type, exc_obj, exc_tb = sys.exc_info()
2145 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2146 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2147 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002148
2149 try:
2150 for i in range(3):
2151 parsedfullsels = json.loads(selPrint(host,args,session))
2152 if 'numAlerts' in parsedfullsels:
2153 selsCollected = True
2154 break
2155 else:
2156 errorInfo += parsedfullsels + '\n'
2157 except Exception as e:
2158 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002159 exc_type, exc_obj, exc_tb = sys.exc_info()
2160 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2161 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2162 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002163
2164 if selsCollected:
2165 try:
2166 sortedSELs = sortSELs(parsedfullsels)
2167 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
2168 for log in sortedSELs[0]:
2169 esel = ""
2170 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
2171 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
2172 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2173 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2174 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
2175 if(args.devdebug and esel != ""):
2176 f.write(parseESEL(args, esel))
2177 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
2178 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
2179 except Exception as e:
2180 print("Failed to write fully parsed SELs to file system.")
2181 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002182 exc_type, exc_obj, exc_tb = sys.exc_info()
2183 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2184 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2185 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002186
2187 output['errors'] = errorInfo
2188 return output
2189
2190def csdFullEnumeration(host, args, session, fileDir):
2191 """
2192 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
2193
2194 @param host: string, the hostname or IP address of the bmc
2195 @param args: contains additional arguments used by the collectServiceData sub command
2196 @param session: the active session to use
2197 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2198 @param fileDir: string representation of the path to use for putting files created
2199 """
2200 errorInfo = "===========BMC Full Enumeration =============\n"
2201 bmcFullCollected = False
2202 output={}
2203 try:
2204 d = vars(args)
2205 d['json'] = True
2206 except Exception as e:
2207 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002208 exc_type, exc_obj, exc_tb = sys.exc_info()
2209 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2210 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2211 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002212 try:
2213 print("Attempting to get a full BMC enumeration")
2214 url="https://"+host+"/xyz/openbmc_project/enumerate"
2215 httpHeader = {'Content-Type':'application/json'}
2216 for i in range(3):
2217 try:
2218 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
2219 if bmcRes.status_code == 200:
2220 bmcFullCollected = True
2221 fullEnumeration = bmcRes.json()
2222 break
2223 else:
2224 errorInfo += bmcRes.text
2225 except(requests.exceptions.Timeout):
2226 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2227 except(requests.exceptions.ConnectionError) as err:
2228 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
Justin Thalerb4256672020-04-07 19:38:26 -05002229 exc_type, exc_obj, exc_tb = sys.exc_info()
2230 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2231 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2232 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002233 except Exception as e:
2234 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002235 exc_type, exc_obj, exc_tb = sys.exc_info()
2236 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2237 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2238 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002239
2240 if bmcFullCollected:
2241 try:
2242 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
2243 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2244 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
2245 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
2246 except Exception as e:
2247 print("Failed to write RAW BMC data to file system.")
2248 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002249 exc_type, exc_obj, exc_tb = sys.exc_info()
2250 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2251 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2252 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002253
2254 output['errors'] = errorInfo
2255 return output
2256
2257def csdCollectAllDumps(host, args, session, fileDir):
2258 """
2259 Collects all of the bmc dump files and stores them in fileDir
2260
2261 @param host: string, the hostname or IP address of the bmc
2262 @param args: contains additional arguments used by the collectServiceData sub command
2263 @param session: the active session to use
2264 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2265 @param fileDir: string representation of the path to use for putting files created
2266 """
2267
2268 errorInfo = "===========BMC Dump Collection =============\n"
2269 dumpListCollected = False
2270 output={}
2271 dumpList = {}
2272 try:
2273 d = vars(args)
2274 d['json'] = True
2275 d['dumpSaveLoc'] = fileDir
2276 except Exception as e:
2277 errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002278 exc_type, exc_obj, exc_tb = sys.exc_info()
2279 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2280 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2281 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002282
2283 print('Collecting bmc dump files')
2284
2285 try:
2286 for i in range(3):
2287 dumpResp = bmcDumpList(host, args, session)
2288 if 'message' in dumpResp:
2289 if 'ok' in dumpResp['message'].lower():
2290 dumpList = dumpResp['data']
2291 dumpListCollected = True
2292 break
2293 else:
2294 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
2295 else:
2296 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
2297 except Exception as e:
2298 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002299 exc_type, exc_obj, exc_tb = sys.exc_info()
2300 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2301 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2302 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002303
2304 if dumpListCollected:
2305 output['fileList'] = []
2306 for dump in dumpList:
2307 try:
2308 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
2309 d['dumpNum'] = int(dump.strip().split('/')[-1])
2310 print('retrieving dump file ' + str(d['dumpNum']))
2311 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
2312 output['fileList'].append(filename)
2313 except Exception as e:
2314 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
2315 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002316 exc_type, exc_obj, exc_tb = sys.exc_info()
2317 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2318 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2319 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002320 output['errors'] = errorInfo
2321 return output
Justin Thalere412dc22018-01-12 16:28:24 -06002322
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002323def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002324 """
2325 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002326
Justin Thalere412dc22018-01-12 16:28:24 -06002327 @param host: string, the hostname or IP address of the bmc
2328 @param args: contains additional arguments used by the collectServiceData sub command
2329 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002330 @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 -06002331 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002332
Justin Thaler22b1bb52018-03-15 13:31:32 -05002333 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06002334 filelist = []
2335 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002336
Justin Thaler666cf342019-01-23 14:44:27 -06002337 #get current number of bmc dumps and create a new bmc dump
2338 dumpInitdata = csdDumpInitiate(host, args, session)
Justin Thalerb4256672020-04-07 19:38:26 -05002339 if 'dumpFailure' in dumpInitdata:
2340 return 'Collect service data is stopping due to not being able to create a new dump. No service data was collected.'
Justin Thaler666cf342019-01-23 14:44:27 -06002341 dumpcount = dumpInitdata['dumpcount']
2342 errorInfo += dumpInitdata['errors']
2343 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002344 try:
2345 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05002346 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002347 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002348
Justin Thaler666cf342019-01-23 14:44:27 -06002349 except Exception as e:
2350 print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
Justin Thalerb4256672020-04-07 19:38:26 -05002351 exc_type, exc_obj, exc_tb = sys.exc_info()
2352 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2353 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2354 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002355 return("Python exception: {eInfo}".format(eInfo = e))
2356
2357 #Collect Inventory
2358 inventoryData = csdInventory(host, args, session, myDir)
2359 if 'fileLoc' in inventoryData:
2360 filelist.append(inventoryData['fileLoc'])
2361 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002362 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06002363 sensorData = csdSensors(host,args,session,myDir)
2364 if 'fileLoc' in sensorData:
2365 filelist.append(sensorData['fileLoc'])
2366 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002367 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06002368 ledStatus = csdLEDs(host, args, session, myDir)
2369 if 'fileLoc' in ledStatus:
2370 filelist.append(ledStatus['fileLoc'])
2371 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002372
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002373 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06002374 selShort = csdSelShortList(host, args, session, myDir)
2375 if 'fileLoc' in selShort:
2376 filelist.append(selShort['fileLoc'])
2377 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002378
Justin Thaler666cf342019-01-23 14:44:27 -06002379 parsedSELs = csdParsedSels(host, args, session, myDir)
2380 if 'fileLoc' in parsedSELs:
2381 filelist.append(parsedSELs['fileLoc'])
2382 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002383
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002384 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06002385 bmcRaw = csdFullEnumeration(host, args, session, myDir)
2386 if 'fileLoc' in bmcRaw:
2387 filelist.append(bmcRaw['fileLoc'])
2388 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002389
Justin Thaler666cf342019-01-23 14:44:27 -06002390 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002391 waitingForNewDump = True
2392 count = 0;
Justin Thalerb4256672020-04-07 19:38:26 -05002393 print("Waiting for new BMC dump to finish being created. Wait time could be up to 5 minutes")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002394 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06002395 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002396 if len(dumpList) > dumpcount:
2397 waitingForNewDump = False
2398 break;
Justin Thalerb4256672020-04-07 19:38:26 -05002399 elif(count>150):
2400 print("Timed out waiting for bmc to make a new dump file. Continuing without it.")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002401 break;
2402 else:
2403 time.sleep(2)
2404 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06002405
2406 #collect all of the dump files
2407 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
2408 if 'fileList' in getBMCDumps:
2409 filelist+= getBMCDumps['fileList']
2410 errorInfo += getBMCDumps['errors']
2411
2412 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002413 try:
Justin Thaler666cf342019-01-23 14:44:27 -06002414 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
2415 f.write(errorInfo)
2416 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
2417 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002418 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06002419 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002420
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002421 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002422 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05002423 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06002424 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002425 for myfile in filelist:
2426 zf.write(myfile, os.path.basename(myfile))
2427 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06002428 print("Zip file with all collected data created and stored in: {fileInfo}".format(fileInfo=myDir+os.sep+filename))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002429 except Exception as e:
2430 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06002431 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002432
Justin Thalere412dc22018-01-12 16:28:24 -06002433
2434def healthCheck(host, args, session):
2435 """
2436 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002437
Justin Thalere412dc22018-01-12 16:28:24 -06002438 @param host: string, the hostname or IP address of the bmc
2439 @param args: contains additional arguments used by the bmc sub command
2440 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002441 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2442 """
Justin Thalere412dc22018-01-12 16:28:24 -06002443 #check fru status and get as json to easily work through
2444 d = vars(args)
2445 useJson = d['json']
2446 d['json'] = True
2447 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002448
Justin Thalere412dc22018-01-12 16:28:24 -06002449 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002450
Justin Thalere412dc22018-01-12 16:28:24 -06002451 hwStatus= "OK"
2452 performanceStatus = "OK"
2453 for key in frus:
2454 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
2455 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05002456 if("power_supply" in key or "powersupply" in key):
2457 gpuCount =0
2458 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06002459 if "gv100card" in comp:
2460 gpuCount +=1
2461 if gpuCount > 4:
2462 hwStatus = "Critical"
2463 performanceStatus="Degraded"
2464 break;
2465 elif("fan" in key):
2466 hwStatus = "Degraded"
2467 else:
2468 performanceStatus = "Degraded"
2469 if useJson:
2470 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
2471 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
2472 else:
2473 output = ("Hardware Status: " + hwStatus +
2474 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002475
2476
Justin Thalere412dc22018-01-12 16:28:24 -06002477 #SW407886: Clear the duplicate entries
2478 #collect the dups
2479 d['devdebug'] = False
2480 sels = json.loads(selPrint(host, args, session))
2481 logNums2Clr = []
2482 oldestLogNum={"logNum": "bogus" ,"key" : ""}
2483 count = 0
2484 if sels['numAlerts'] > 0:
2485 for key in sels:
2486 if "numAlerts" in key:
2487 continue
2488 try:
2489 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
2490 count += 1
2491 if count > 1:
2492 #preserve first occurrence
2493 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
2494 oldestLogNum['key']=key
2495 oldestLogNum['logNum'] = sels[key]['logNum']
2496 else:
2497 oldestLogNum['key']=key
2498 oldestLogNum['logNum'] = sels[key]['logNum']
2499 logNums2Clr.append(sels[key]['logNum'])
2500 except KeyError:
2501 continue
2502 if(count >0):
2503 logNums2Clr.remove(oldestLogNum['logNum'])
2504 #delete the dups
2505 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06002506 data = "{\"data\": [] }"
2507 for logNum in logNums2Clr:
2508 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2509 try:
Justin Thaler27197622019-01-23 14:42:11 -06002510 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002511 except(requests.exceptions.Timeout):
2512 deleteFailed = True
2513 except(requests.exceptions.ConnectionError) as err:
2514 deleteFailed = True
2515 #End of defect resolve code
2516 d['json'] = useJson
2517 return output
2518
2519
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002520
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002521def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002522 """
2523 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002524
Justin Thalere412dc22018-01-12 16:28:24 -06002525 @param host: string, the hostname or IP address of the bmc
2526 @param args: contains additional arguments used by the bmc sub command
2527 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002528 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2529 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002530 if(args.type is not None):
2531 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002532 if(args.info):
2533 return "Not implemented at this time"
2534
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002535
Justin Thalere412dc22018-01-12 16:28:24 -06002536
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002537def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002538 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002539 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2540
Justin Thalere412dc22018-01-12 16:28:24 -06002541 @param host: string, the hostname or IP address of the bmc
2542 @param args: contains additional arguments used by the bmcReset sub command
2543 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002544 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2545 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002546 if checkFWactivation(host, args, session):
2547 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002548 if(args.type == "warm"):
2549 print("\nAttempting to reboot the BMC...:")
2550 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002551 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002552 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002553 return res.text
2554 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002555 print("\nAttempting to reboot the BMC...:")
2556 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002557 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002558 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002559 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002560 else:
2561 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002562
2563def gardClear(host, args, session):
2564 """
2565 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002566
Justin Thalere412dc22018-01-12 16:28:24 -06002567 @param host: string, the hostname or IP address of the bmc
2568 @param args: contains additional arguments used by the gardClear sub command
2569 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002570 """
Justin Thalere412dc22018-01-12 16:28:24 -06002571 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002572 data = '{"data":[]}'
2573 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002574
Justin Thaler27197622019-01-23 14:42:11 -06002575 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002576 if res.status_code == 404:
2577 return "Command not supported by this firmware version"
2578 else:
2579 return res.text
2580 except(requests.exceptions.Timeout):
2581 return connectionErrHandler(args.json, "Timeout", None)
2582 except(requests.exceptions.ConnectionError) as err:
2583 return connectionErrHandler(args.json, "ConnectionError", err)
2584
2585def activateFWImage(host, args, session):
2586 """
2587 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002588
Justin Thalere412dc22018-01-12 16:28:24 -06002589 @param host: string, the hostname or IP address of the bmc
2590 @param args: contains additional arguments used by the fwflash sub command
2591 @param session: the active session to use
2592 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002593 """
Justin Thalere412dc22018-01-12 16:28:24 -06002594 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002595
Justin Thalere412dc22018-01-12 16:28:24 -06002596 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002597 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2598 try:
Justin Thaler27197622019-01-23 14:42:11 -06002599 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002600 except(requests.exceptions.Timeout):
2601 return connectionErrHandler(args.json, "Timeout", None)
2602 except(requests.exceptions.ConnectionError) as err:
2603 return connectionErrHandler(args.json, "ConnectionError", err)
2604 existingSoftware = json.loads(resp.text)['data']
2605 altVersionID = ''
2606 versionType = ''
2607 imageKey = '/xyz/openbmc_project/software/'+fwID
2608 if imageKey in existingSoftware:
2609 versionType = existingSoftware[imageKey]['Purpose']
2610 for key in existingSoftware:
2611 if imageKey == key:
2612 continue
2613 if 'Purpose' in existingSoftware[key]:
2614 if versionType == existingSoftware[key]['Purpose']:
2615 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002616
2617
2618
2619
Justin Thalere412dc22018-01-12 16:28:24 -06002620 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2621 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002622 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002623 data1 = "{\"data\": 1 }"
2624 try:
Justin Thaler27197622019-01-23 14:42:11 -06002625 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2626 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002627 except(requests.exceptions.Timeout):
2628 return connectionErrHandler(args.json, "Timeout", None)
2629 except(requests.exceptions.ConnectionError) as err:
2630 return connectionErrHandler(args.json, "ConnectionError", err)
2631 if(not args.json):
2632 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002633 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 -06002634 else:
2635 return "Firmware activation failed."
2636 else:
2637 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002638
2639def activateStatus(host, args, session):
2640 if checkFWactivation(host, args, session):
2641 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2642 else:
2643 return("No firmware activations are pending")
2644
2645def extractFWimage(path, imageType):
2646 """
2647 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002648
Justin Thaler22b1bb52018-03-15 13:31:32 -05002649 @param path: the path and file name of the firmware image
2650 @param imageType: The type of image the user is trying to flash. Host or BMC
2651 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002652 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002653 f = tempfile.TemporaryFile()
2654 tmpDir = tempfile.gettempdir()
2655 newImageID = ""
2656 if os.path.exists(path):
2657 try:
2658 imageFile = tarfile.open(path,'r')
2659 contents = imageFile.getmembers()
2660 for tf in contents:
2661 if 'MANIFEST' in tf.name:
2662 imageFile.extract(tf.name, path=tmpDir)
2663 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2664 for line in imageInfo:
2665 if 'purpose' in line:
2666 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002667 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002668 print('The specified image is not for ' + imageType)
2669 print('Please try again with the image for ' + imageType)
2670 return ""
2671 if 'version' == line.split('=')[0]:
2672 version = line.split('=')[1].strip().encode('utf-8')
2673 m = hashlib.sha512()
2674 m.update(version)
2675 newImageID = m.hexdigest()[:8]
2676 break
2677 try:
2678 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2679 except OSError:
2680 pass
2681 return newImageID
2682 except tarfile.ExtractError as e:
2683 print('Unable to extract information from the firmware file.')
2684 print('Ensure you have write access to the directory: ' + tmpDir)
2685 return newImageID
2686 except tarfile.TarError as e:
2687 print('This is not a valid firmware file.')
2688 return newImageID
2689 print("This is not a valid firmware file.")
2690 return newImageID
2691 else:
2692 print('The filename and path provided are not valid.')
2693 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002694
Justin Thaler22b1bb52018-03-15 13:31:32 -05002695def getAllFWImageIDs(fwInvDict):
2696 """
2697 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002698
Justin Thaler22b1bb52018-03-15 13:31:32 -05002699 @param fwInvDict: the dictionary to search for FW image IDs
2700 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002701 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002702 idList = []
2703 for key in fwInvDict:
2704 if 'Version' in fwInvDict[key]:
2705 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002706 return idList
2707
Justin Thalere412dc22018-01-12 16:28:24 -06002708def fwFlash(host, args, session):
2709 """
2710 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002711
Justin Thalere412dc22018-01-12 16:28:24 -06002712 @param host: string, the hostname or IP address of the bmc
2713 @param args: contains additional arguments used by the fwflash sub command
2714 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002715 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002716 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002717 if(args.type == 'bmc'):
2718 purp = 'BMC'
2719 else:
2720 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002721
2722 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002723 d['powcmd'] = 'status'
2724 powerstate = chassisPower(host, args, session)
2725 if 'Chassis Power State: On' in powerstate:
2726 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002727
Justin Thaler22b1bb52018-03-15 13:31:32 -05002728 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002729 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2730 try:
Justin Thaler27197622019-01-23 14:42:11 -06002731 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002732 except(requests.exceptions.Timeout):
2733 return connectionErrHandler(args.json, "Timeout", None)
2734 except(requests.exceptions.ConnectionError) as err:
2735 return connectionErrHandler(args.json, "ConnectionError", err)
2736 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002737
Justin Thaler22b1bb52018-03-15 13:31:32 -05002738 #Extract the tar and get information from the manifest file
2739 newversionID = extractFWimage(args.fileloc, purp)
2740 if newversionID == "":
2741 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002742
2743
Justin Thaler22b1bb52018-03-15 13:31:32 -05002744 #check if the new image is already on the bmc
2745 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002746
Justin Thaler22b1bb52018-03-15 13:31:32 -05002747 #upload the file
2748 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002749 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002750 url="https://"+host+"/upload/image"
2751 data=open(args.fileloc,'rb').read()
2752 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002753 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002754 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06002755 except(requests.exceptions.Timeout):
2756 return connectionErrHandler(args.json, "Timeout", None)
2757 except(requests.exceptions.ConnectionError) as err:
2758 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002759 if resp.status_code != 200:
2760 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002761 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002762 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002763
Justin Thaler22b1bb52018-03-15 13:31:32 -05002764 #verify bmc processed the image
2765 software ={}
2766 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002767 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2768 try:
Justin Thaler27197622019-01-23 14:42:11 -06002769 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002770 except(requests.exceptions.Timeout):
2771 return connectionErrHandler(args.json, "Timeout", None)
2772 except(requests.exceptions.ConnectionError) as err:
2773 return connectionErrHandler(args.json, "ConnectionError", err)
2774 software = json.loads(resp.text)['data']
2775 #check if bmc is done processing the new image
2776 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002777 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002778 else:
2779 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002780
Justin Thaler22b1bb52018-03-15 13:31:32 -05002781 #activate the new image
2782 print("Activating new image: "+newversionID)
2783 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002784 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002785 try:
Justin Thaler27197622019-01-23 14:42:11 -06002786 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002787 except(requests.exceptions.Timeout):
2788 return connectionErrHandler(args.json, "Timeout", None)
2789 except(requests.exceptions.ConnectionError) as err:
2790 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002791
Justin Thaler22b1bb52018-03-15 13:31:32 -05002792 #wait for the activation to complete, timeout after ~1 hour
2793 i=0
2794 while i < 360:
2795 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002796 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002797 try:
Justin Thaler27197622019-01-23 14:42:11 -06002798 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002799 except(requests.exceptions.Timeout):
2800 return connectionErrHandler(args.json, "Timeout", None)
2801 except(requests.exceptions.ConnectionError) as err:
2802 return connectionErrHandler(args.json, "ConnectionError", err)
2803 fwInfo = json.loads(resp.text)['data']
2804 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2805 print('')
2806 break
2807 else:
2808 sys.stdout.write('.')
2809 sys.stdout.flush()
2810 time.sleep(10) #check every 10 seconds
2811 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2812 else:
2813 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002814
Justin Thaler22b1bb52018-03-15 13:31:32 -05002815 d['imageID'] = newversionID
2816 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002817
Justin Thaler3d71d402018-07-24 14:35:39 -05002818def getFWInventoryAttributes(rawFWInvItem, ID):
2819 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002820 gets and lists all of the firmware in the system.
2821
Justin Thaler3d71d402018-07-24 14:35:39 -05002822 @return: returns a dictionary containing the image attributes
2823 """
2824 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2825 pendingActivation = ""
2826 if reqActivation == "None":
2827 pendingActivation = "No"
2828 else:
2829 pendingActivation = "Yes"
2830 firmwareAttr = {ID: {
2831 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2832 "Version": rawFWInvItem["Version"],
2833 "RequestedActivation": pendingActivation,
2834 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002835
Justin Thaler3d71d402018-07-24 14:35:39 -05002836 if "ExtendedVersion" in rawFWInvItem:
2837 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002838 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002839 firmwareAttr[ID]['ExtendedVersion'] = ""
2840 return firmwareAttr
2841
2842def parseFWdata(firmwareDict):
2843 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002844 creates a dictionary with parsed firmware data
2845
Justin Thaler3d71d402018-07-24 14:35:39 -05002846 @return: returns a dictionary containing the image attributes
2847 """
2848 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2849 for key in firmwareDict['data']:
2850 #check for valid endpoint
2851 if "Purpose" in firmwareDict['data'][key]:
2852 id = key.split('/')[-1]
2853 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2854 fwActivated = True
2855 else:
2856 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002857 if 'Priority' in firmwareDict['data'][key]:
2858 if firmwareDict['data'][key]['Priority'] == 0:
2859 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2860 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2861 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2862 else:
2863 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002864 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002865 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002866 emptySections = []
2867 for key in firmwareInfoDict:
2868 if len(firmwareInfoDict[key])<=0:
2869 emptySections.append(key)
2870 for key in emptySections:
2871 del firmwareInfoDict[key]
2872 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002873
Justin Thaler3d71d402018-07-24 14:35:39 -05002874def displayFWInvenory(firmwareInfoDict, args):
2875 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002876 gets and lists all of the firmware in the system.
2877
Justin Thaler3d71d402018-07-24 14:35:39 -05002878 @return: returns a string containing all of the firmware information
2879 """
2880 output = ""
2881 if not args.json:
2882 for key in firmwareInfoDict:
2883 for subkey in firmwareInfoDict[key]:
2884 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2885 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002886 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002887 colNames = ["Purpose", "Version", "ID"]
2888 keylist = ["Purpose", "Version", "ID"]
2889 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2890 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002891 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002892 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2893 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002894 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002895 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002896
Justin Thaler3d71d402018-07-24 14:35:39 -05002897 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002898 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002899 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2900 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2901 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2902 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002903 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002904 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2905 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002906 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002907 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2908 return output
2909 else:
2910 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2911
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002912def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002913 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002914 gets and lists all of the firmware in the system.
2915
Justin Thaler3d71d402018-07-24 14:35:39 -05002916 @return: returns a string containing all of the firmware information
2917 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002918 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2919 try:
Justin Thaler27197622019-01-23 14:42:11 -06002920 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002921 except(requests.exceptions.Timeout):
2922 return(connectionErrHandler(args.json, "Timeout", None))
2923 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002924
Justin Thaler3d71d402018-07-24 14:35:39 -05002925 #sort the received information
2926 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002927
Justin Thaler3d71d402018-07-24 14:35:39 -05002928 #display the information
2929 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002930
2931
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002932def deleteFWVersion(host, args, session):
2933 """
2934 deletes a firmware version on the BMC
2935
2936 @param host: string, the hostname or IP address of the BMC
2937 @param args: contains additional arguments used by the fwflash sub command
2938 @param session: the active session to use
2939 @param fwID: the unique ID of the fw version to delete
2940 """
2941 fwID = args.versionID
2942
2943 print("Deleting version: "+fwID)
2944 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002945 data = "{\"data\": [] }"
2946
2947 try:
Justin Thaler27197622019-01-23 14:42:11 -06002948 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002949 except(requests.exceptions.Timeout):
2950 return(connectionErrHandler(args.json, "Timeout", None))
2951 if res.status_code == 200:
2952 return ('The firmware version has been deleted')
2953 else:
2954 return ('Unable to delete the specified firmware version')
2955
2956
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002957def restLogging(host, args, session):
2958 """
2959 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002960
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002961 @param host: string, the hostname or IP address of the bmc
2962 @param args: contains additional arguments used by the logging sub command
2963 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002964 @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 -05002965 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002966 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002967
2968 if(args.rest_logging == 'on'):
2969 data = '{"data": 1}'
2970 elif(args.rest_logging == 'off'):
2971 data = '{"data": 0}'
2972 else:
2973 return "Invalid logging rest_api command"
2974
2975 try:
Justin Thaler27197622019-01-23 14:42:11 -06002976 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002977 except(requests.exceptions.Timeout):
2978 return(connectionErrHandler(args.json, "Timeout", None))
2979 return res.text
2980
2981
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002982def remoteLogging(host, args, session):
2983 """
2984 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002985
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002986 @param host: string, the hostname or IP address of the bmc
2987 @param args: contains additional arguments used by the logging sub command
2988 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002989 @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 -05002990 """
2991
2992 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002993
2994 try:
2995 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002996 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002997 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002998 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2999 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003000 else:
3001 return "Invalid logging remote_logging command"
3002 except(requests.exceptions.Timeout):
3003 return(connectionErrHandler(args.json, "Timeout", None))
3004 return res.text
3005
3006
3007def remoteLoggingConfig(host, args, session):
3008 """
3009 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003010
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003011 @param host: string, the hostname or IP address of the bmc
3012 @param args: contains additional arguments used by the logging sub command
3013 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003014 @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 -05003015 """
3016
3017 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003018
3019 try:
Justin Thaler27197622019-01-23 14:42:11 -06003020 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
3021 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003022 except(requests.exceptions.Timeout):
3023 return(connectionErrHandler(args.json, "Timeout", None))
3024 return res.text
3025
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003026def redfishSupportPresent(host, session):
3027 url = "https://" + host + "/redfish/v1"
3028 try:
3029 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
3030 except(requests.exceptions.Timeout):
3031 return False
3032 except(requests.exceptions.ConnectionError) as err:
3033 return False
3034 if resp.status_code != 200:
3035 return False
3036 else:
3037 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05303038
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003039def certificateUpdate(host, args, session):
3040 """
3041 Called by certificate management function. update server/client/authority certificates
3042 Example:
3043 certificate update server https -f cert.pem
3044 certificate update authority ldap -f Root-CA.pem
3045 certificate update client ldap -f cert.pem
3046 @param host: string, the hostname or IP address of the bmc
3047 @param args: contains additional arguments used by the certificate update sub command
3048 @param session: the active session to use
3049 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003050 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003051 httpHeader.update(xAuthHeader)
Brad Bishop5da038f2020-07-10 14:21:43 -04003052 data = open(args.fileloc, 'r').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003053 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003054 if redfishSupportPresent(host, session):
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003055 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3056 return "Invalid service type"
3057 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3058 return "Invalid service type"
3059 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3060 return "Invalid service type"
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003061 url = "";
3062 if(args.type.lower() == 'server'):
3063 url = "https://" + host + \
3064 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
3065 elif(args.type.lower() == 'client'):
3066 url = "https://" + host + \
3067 "/redfish/v1/AccountService/LDAP/Certificates"
3068 elif(args.type.lower() == 'authority'):
3069 url = "https://" + host + \
3070 "/redfish/v1/Managers/bmc/Truststore/Certificates"
3071 else:
3072 return "Unsupported certificate type"
3073 resp = session.post(url, headers=httpHeader, data=data,
3074 verify=False)
3075 else:
3076 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3077 args.type.lower() + "/" + args.service.lower()
3078 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003079 except(requests.exceptions.Timeout):
3080 return(connectionErrHandler(args.json, "Timeout", None))
3081 except(requests.exceptions.ConnectionError) as err:
3082 return connectionErrHandler(args.json, "ConnectionError", err)
3083 if resp.status_code != 200:
3084 print(resp.text)
3085 return "Failed to update the certificate"
3086 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003087 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003088
3089def certificateDelete(host, args, session):
3090 """
3091 Called by certificate management function to delete certificate
3092 Example:
3093 certificate delete server https
3094 certificate delete authority ldap
3095 certificate delete client ldap
3096 @param host: string, the hostname or IP address of the bmc
3097 @param args: contains additional arguments used by the certificate delete sub command
3098 @param session: the active session to use
3099 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05003100 if redfishSupportPresent(host, session):
3101 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003102 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003103 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003104 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
3105 print("Deleting certificate url=" + url)
3106 try:
3107 resp = session.delete(url, headers=httpHeader)
3108 except(requests.exceptions.Timeout):
3109 return(connectionErrHandler(args.json, "Timeout", None))
3110 except(requests.exceptions.ConnectionError) as err:
3111 return connectionErrHandler(args.json, "ConnectionError", err)
3112 if resp.status_code != 200:
3113 print(resp.text)
3114 return "Failed to delete the certificate"
3115 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05003116 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003117
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003118def certificateReplace(host, args, session):
3119 """
3120 Called by certificate management function. replace server/client/
3121 authority certificates
3122 Example:
3123 certificate replace server https -f cert.pem
3124 certificate replace authority ldap -f Root-CA.pem
3125 certificate replace client ldap -f cert.pem
3126 @param host: string, the hostname or IP address of the bmc
3127 @param args: contains additional arguments used by the certificate
3128 replace sub command
3129 @param session: the active session to use
3130 """
Brad Bishop5da038f2020-07-10 14:21:43 -04003131 cert = open(args.fileloc, 'r').read()
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003132 try:
3133 if redfishSupportPresent(host, session):
3134 httpHeader = {'Content-Type': 'application/json'}
3135 httpHeader.update(xAuthHeader)
3136 url = "";
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003137 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3138 return "Invalid service type"
3139 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3140 return "Invalid service type"
3141 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3142 return "Invalid service type"
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003143 if(args.type.lower() == 'server'):
3144 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3145 elif(args.type.lower() == 'client'):
3146 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
3147 elif(args.type.lower() == 'authority'):
3148 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3149 replaceUrl = "https://" + host + \
3150 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
3151 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
3152 "CertificateString":cert}
3153 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
3154 else:
3155 httpHeader = {'Content-Type': 'application/octet-stream'}
3156 httpHeader.update(xAuthHeader)
3157 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3158 args.type.lower() + "/" + args.service.lower()
3159 resp = session.delete(url, headers=httpHeader)
3160 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
3161 except(requests.exceptions.Timeout):
3162 return(connectionErrHandler(args.json, "Timeout", None))
3163 except(requests.exceptions.ConnectionError) as err:
3164 return connectionErrHandler(args.json, "ConnectionError", err)
3165 if resp.status_code != 200:
3166 print(resp.text)
3167 return "Failed to replace the certificate"
3168 else:
3169 print("Replace complete.")
3170 return resp.text
3171
Marri Devender Rao34646402019-07-01 05:46:03 -05003172def certificateDisplay(host, args, session):
3173 """
3174 Called by certificate management function. display server/client/
3175 authority certificates
3176 Example:
3177 certificate display server
3178 certificate display authority
3179 certificate display client
3180 @param host: string, the hostname or IP address of the bmc
3181 @param args: contains additional arguments used by the certificate
3182 display sub command
3183 @param session: the active session to use
3184 """
3185 if not redfishSupportPresent(host, session):
3186 return "Not supported";
3187
3188 httpHeader = {'Content-Type': 'application/octet-stream'}
3189 httpHeader.update(xAuthHeader)
3190 if(args.type.lower() == 'server'):
3191 url = "https://" + host + \
3192 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3193 elif(args.type.lower() == 'client'):
3194 url = "https://" + host + \
3195 "/redfish/v1/AccountService/LDAP/Certificates/1"
3196 elif(args.type.lower() == 'authority'):
3197 url = "https://" + host + \
3198 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3199 try:
3200 resp = session.get(url, headers=httpHeader, verify=False)
3201 except(requests.exceptions.Timeout):
3202 return(connectionErrHandler(args.json, "Timeout", None))
3203 except(requests.exceptions.ConnectionError) as err:
3204 return connectionErrHandler(args.json, "ConnectionError", err)
3205 if resp.status_code != 200:
3206 print(resp.text)
3207 return "Failed to display the certificate"
3208 else:
3209 print("Display complete.")
3210 return resp.text
3211
Marri Devender Raoa208ff82019-07-01 05:51:27 -05003212def certificateList(host, args, session):
3213 """
3214 Called by certificate management function.
3215 Example:
3216 certificate list
3217 @param host: string, the hostname or IP address of the bmc
3218 @param args: contains additional arguments used by the certificate
3219 list sub command
3220 @param session: the active session to use
3221 """
3222 if not redfishSupportPresent(host, session):
3223 return "Not supported";
3224
3225 httpHeader = {'Content-Type': 'application/octet-stream'}
3226 httpHeader.update(xAuthHeader)
3227 url = "https://" + host + \
3228 "/redfish/v1/CertificateService/CertificateLocations/"
3229 try:
3230 resp = session.get(url, headers=httpHeader, verify=False)
3231 except(requests.exceptions.Timeout):
3232 return(connectionErrHandler(args.json, "Timeout", None))
3233 except(requests.exceptions.ConnectionError) as err:
3234 return connectionErrHandler(args.json, "ConnectionError", err)
3235 if resp.status_code != 200:
3236 print(resp.text)
3237 return "Failed to list certificates"
3238 else:
3239 print("List certificates complete.")
3240 return resp.text
3241
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003242def certificateGenerateCSR(host, args, session):
3243 """
3244 Called by certificate management function. Generate CSR for server/
3245 client certificates
3246 Example:
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003247 certificate generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC prime256v1 cp abc.com an.com,bm.com gn sn un in
3248 certificate generatecsr client NJ w3.ibm.com US IBM IBM-UNIT NY EC prime256v1 cp abc.com an.com,bm.com gn sn un in
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003249 @param host: string, the hostname or IP address of the bmc
3250 @param args: contains additional arguments used by the certificate replace sub command
3251 @param session: the active session to use
3252 """
3253 if not redfishSupportPresent(host, session):
3254 return "Not supported";
3255
3256 httpHeader = {'Content-Type': 'application/octet-stream'}
3257 httpHeader.update(xAuthHeader)
3258 url = "";
3259 if(args.type.lower() == 'server'):
3260 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003261 usage_list = ["ServerAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003262 elif(args.type.lower() == 'client'):
3263 url = "/redfish/v1/AccountService/LDAP/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003264 usage_list = ["ClientAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003265 elif(args.type.lower() == 'authority'):
3266 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
3267 print("Generating CSR url=" + url)
3268 generateCSRUrl = "https://" + host + \
3269 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
3270 try:
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003271 alt_name_list = args.alternativeNames.split(",")
3272 data ={"CertificateCollection":{"@odata.id":url},
3273 "CommonName":args.commonName, "City":args.city,
3274 "Country":args.country, "Organization":args.organization,
3275 "OrganizationalUnit":args.organizationUnit, "State":args.state,
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003276 "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003277 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
3278 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
3279 "KeyUsage":usage_list, "Surname":args.surname,
3280 "UnstructuredName":args.unstructuredname}
3281 resp = session.post(generateCSRUrl, headers=httpHeader,
3282 json=data, verify=False)
3283 except(requests.exceptions.Timeout):
3284 return(connectionErrHandler(args.json, "Timeout", None))
3285 except(requests.exceptions.ConnectionError) as err:
3286 return connectionErrHandler(args.json, "ConnectionError", err)
3287 if resp.status_code != 200:
3288 print(resp.text)
3289 return "Failed to generate CSR"
3290 else:
3291 print("GenerateCSR complete.")
3292 return resp.text
3293
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003294def enableLDAPConfig(host, args, session):
Ratan Gupta9166cd22018-10-01 18:09:40 +05303295 """
3296 Called by the ldap function. Configures LDAP.
3297
3298 @param host: string, the hostname or IP address of the bmc
3299 @param args: contains additional arguments used by the ldap subcommand
3300 @param session: the active session to use
3301 @param args.json: boolean, if this flag is set to true, the output will
3302 be provided in json format for programmatic consumption
3303 """
3304
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003305 if(isRedfishSupport):
3306 return enableLDAP(host, args, session)
3307 else:
3308 return enableLegacyLDAP(host, args, session)
3309
3310def enableLegacyLDAP(host, args, session):
3311 """
3312 Called by the ldap function. Configures LDAP on Lagecy systems.
3313
3314 @param host: string, the hostname or IP address of the bmc
3315 @param args: contains additional arguments used by the ldap subcommand
3316 @param session: the active session to use
3317 @param args.json: boolean, if this flag is set to true, the output will
3318 be provided in json format for programmatic consumption
3319 """
3320
Ratan Gupta9166cd22018-10-01 18:09:40 +05303321 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303322 scope = {
3323 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
3324 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
3325 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
3326 }
3327
3328 serverType = {
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003329 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
3330 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303331 }
3332
3333 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
3334
3335 try:
Justin Thaler27197622019-01-23 14:42:11 -06003336 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303337 except(requests.exceptions.Timeout):
3338 return(connectionErrHandler(args.json, "Timeout", None))
3339 except(requests.exceptions.ConnectionError) as err:
3340 return connectionErrHandler(args.json, "ConnectionError", err)
3341
3342 return res.text
3343
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003344def enableLDAP(host, args, session):
3345 """
3346 Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
3347
3348 @param host: string, the hostname or IP address of the bmc
3349 @param args: contains additional arguments used by the ldap subcommand
3350 @param session: the active session to use
3351 @param args.json: boolean, if this flag is set to true, the output will
3352 be provided in json format for programmatic consumption
3353 """
3354
3355 scope = {
3356 'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
3357 'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
3358 'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
3359 }
3360
3361 serverType = {
3362 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
3363 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
3364 }
3365
3366 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3367
3368 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3369 serverTypeToBeEnabled = args.serverType
3370
3371 #If the given LDAP type is already enabled, then return
3372 if (serverTypeToBeEnabled == serverTypeEnabled):
3373 return("Server type " + serverTypeToBeEnabled + " is already enabled...")
3374
3375 try:
3376
3377 # Copy the role map from the currently enabled LDAP server type
3378 # to the newly enabled server type
3379 # Disable the currently enabled LDAP server type. Unless
3380 # it is disabled, we cannot enable a new LDAP server type
3381 if (serverTypeEnabled is not None):
3382
3383 if (serverTypeToBeEnabled != serverTypeEnabled):
3384 res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
3385
3386 data = "{\"data\": 0 }"
3387 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3388
3389 data = {"data": args.baseDN}
3390 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3391 if (res.status_code != requests.codes.ok):
3392 print("Updates to the property LDAPBaseDN failed...")
3393 return(res.text)
3394
3395 data = {"data": args.bindDN}
3396 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3397 if (res.status_code != requests.codes.ok):
3398 print("Updates to the property LDAPBindDN failed...")
3399 return(res.text)
3400
3401 data = {"data": args.bindPassword}
3402 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3403 if (res.status_code != requests.codes.ok):
3404 print("Updates to the property LDAPBindDNPassword failed...")
3405 return(res.text)
3406
3407 data = {"data": scope[args.scope]}
3408 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3409 if (res.status_code != requests.codes.ok):
3410 print("Updates to the property LDAPSearchScope failed...")
3411 return(res.text)
3412
3413 data = {"data": args.uri}
3414 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3415 if (res.status_code != requests.codes.ok):
3416 print("Updates to the property LDAPServerURI failed...")
3417 return(res.text)
3418
3419 data = {"data": args.groupAttrName}
3420 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3421 if (res.status_code != requests.codes.ok):
3422 print("Updates to the property GroupNameAttribute failed...")
3423 return(res.text)
3424
3425 data = {"data": args.userAttrName}
3426 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3427 if (res.status_code != requests.codes.ok):
3428 print("Updates to the property UserNameAttribute failed...")
3429 return(res.text)
3430
3431 #After updating the properties, enable the new server type
3432 data = "{\"data\": 1 }"
3433 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3434
3435 except(requests.exceptions.Timeout):
3436 return(connectionErrHandler(args.json, "Timeout", None))
3437 except(requests.exceptions.ConnectionError) as err:
3438 return connectionErrHandler(args.json, "ConnectionError", err)
3439 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303440
3441def disableLDAP(host, args, session):
3442 """
3443 Called by the ldap function. Deletes the LDAP Configuration.
3444
3445 @param host: string, the hostname or IP address of the bmc
3446 @param args: contains additional arguments used by the ldap subcommand
3447 @param session: the active session to use
3448 @param args.json: boolean, if this flag is set to true, the output
3449 will be provided in json format for programmatic consumption
3450 """
3451
Ratan Gupta9166cd22018-10-01 18:09:40 +05303452 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003453 if (isRedfishSupport) :
3454
3455 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3456
3457 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3458
3459 if (serverTypeEnabled is not None):
3460 #To keep the role map in sync,
3461 #If the server type being disabled has role map, then
3462 # - copy the role map to the other server type(s)
3463 for serverType in serverTypeMap.keys():
3464 if (serverType != serverTypeEnabled):
3465 res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
3466
3467 #Disable the currently enabled LDAP server type
3468 data = "{\"data\": 0 }"
3469 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3470
3471 else:
3472 return("LDAP server has not been enabled...")
3473
3474 else :
3475 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
3476 data = {"data": []}
3477 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3478
Ratan Gupta9166cd22018-10-01 18:09:40 +05303479 except(requests.exceptions.Timeout):
3480 return(connectionErrHandler(args.json, "Timeout", None))
3481 except(requests.exceptions.ConnectionError) as err:
3482 return connectionErrHandler(args.json, "ConnectionError", err)
3483
3484 return res.text
3485
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003486def enableDHCP(host, args, session):
3487
3488 """
3489 Called by the network function. Enables DHCP.
3490
3491 @param host: string, the hostname or IP address of the bmc
3492 @param args: contains additional arguments used by the ldap subcommand
3493 args.json: boolean, if this flag is set to true, the output
3494 will be provided in json format for programmatic consumption
3495 @param session: the active session to use
3496 """
3497
3498 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3499 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003500 data = "{\"data\": 1 }"
3501 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003502 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003503 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003504
3505 except(requests.exceptions.Timeout):
3506 return(connectionErrHandler(args.json, "Timeout", None))
3507 except(requests.exceptions.ConnectionError) as err:
3508 return connectionErrHandler(args.json, "ConnectionError", err)
3509 if res.status_code == 403:
3510 return "The specified Interface"+"("+args.Interface+")"+\
3511 " doesn't exist"
3512
3513 return res.text
3514
3515
3516def disableDHCP(host, args, session):
3517 """
3518 Called by the network function. Disables DHCP.
3519
3520 @param host: string, the hostname or IP address of the bmc
3521 @param args: contains additional arguments used by the ldap subcommand
3522 args.json: boolean, if this flag is set to true, the output
3523 will be provided in json format for programmatic consumption
3524 @param session: the active session to use
3525 """
3526
3527 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3528 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003529 data = "{\"data\": 0 }"
3530 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003531 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003532 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003533 except(requests.exceptions.Timeout):
3534 return(connectionErrHandler(args.json, "Timeout", None))
3535 except(requests.exceptions.ConnectionError) as err:
3536 return connectionErrHandler(args.json, "ConnectionError", err)
3537 if res.status_code == 403:
3538 return "The specified Interface"+"("+args.Interface+")"+\
3539 " doesn't exist"
3540 return res.text
3541
3542
3543def getHostname(host, args, session):
3544
3545 """
3546 Called by the network function. Prints out the Hostname.
3547
3548 @param host: string, the hostname or IP address of the bmc
3549 @param args: contains additional arguments used by the ldap subcommand
3550 args.json: boolean, if this flag is set to true, the output
3551 will be provided in json format for programmatic consumption
3552 @param session: the active session to use
3553 """
3554
3555 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003556
3557 try:
Justin Thaler27197622019-01-23 14:42:11 -06003558 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003559 except(requests.exceptions.Timeout):
3560 return(connectionErrHandler(args.json, "Timeout", None))
3561 except(requests.exceptions.ConnectionError) as err:
3562 return connectionErrHandler(args.json, "ConnectionError", err)
3563
3564 return res.text
3565
3566
3567def setHostname(host, args, session):
3568 """
3569 Called by the network function. Sets the Hostname.
3570
3571 @param host: string, the hostname or IP address of the bmc
3572 @param args: contains additional arguments used by the ldap subcommand
3573 args.json: boolean, if this flag is set to true, the output
3574 will be provided in json format for programmatic consumption
3575 @param session: the active session to use
3576 """
3577
3578 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003579
3580 data = {"data": args.HostName}
3581
3582 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003583 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003584 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003585 except(requests.exceptions.Timeout):
3586 return(connectionErrHandler(args.json, "Timeout", None))
3587 except(requests.exceptions.ConnectionError) as err:
3588 return connectionErrHandler(args.json, "ConnectionError", err)
3589
3590 return res.text
3591
3592
3593def getDomainName(host, args, session):
3594
3595 """
3596 Called by the network function. Prints out the DomainName.
3597
3598 @param host: string, the hostname or IP address of the bmc
3599 @param args: contains additional arguments used by the ldap subcommand
3600 args.json: boolean, if this flag is set to true, the output
3601 will be provided in json format for programmatic consumption
3602 @param session: the active session to use
3603 """
3604
3605 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3606 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003607
3608 try:
Justin Thaler27197622019-01-23 14:42:11 -06003609 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003610 except(requests.exceptions.Timeout):
3611 return(connectionErrHandler(args.json, "Timeout", None))
3612 except(requests.exceptions.ConnectionError) as err:
3613 return connectionErrHandler(args.json, "ConnectionError", err)
3614 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003615 return "The DomainName is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003616
3617 return res.text
3618
3619
3620def setDomainName(host, args, session):
3621 """
3622 Called by the network function. Sets the DomainName.
3623
3624 @param host: string, the hostname or IP address of the bmc
3625 @param args: contains additional arguments used by the ldap subcommand
3626 args.json: boolean, if this flag is set to true, the output
3627 will be provided in json format for programmatic consumption
3628 @param session: the active session to use
3629 """
3630
3631 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3632 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003633
3634 data = {"data": args.DomainName.split(",")}
3635
3636 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003637 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003638 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003639 except(requests.exceptions.Timeout):
3640 return(connectionErrHandler(args.json, "Timeout", None))
3641 except(requests.exceptions.ConnectionError) as err:
3642 return connectionErrHandler(args.json, "ConnectionError", err)
3643 if res.status_code == 403:
3644 return "The specified Interface"+"("+args.Interface+")"+\
3645 " doesn't exist"
3646
3647 return res.text
3648
3649
3650def getMACAddress(host, args, session):
3651
3652 """
3653 Called by the network function. Prints out the MACAddress.
3654
3655 @param host: string, the hostname or IP address of the bmc
3656 @param args: contains additional arguments used by the ldap subcommand
3657 args.json: boolean, if this flag is set to true, the output
3658 will be provided in json format for programmatic consumption
3659 @param session: the active session to use
3660 """
3661
3662 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3663 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003664
3665 try:
Justin Thaler27197622019-01-23 14:42:11 -06003666 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003667 except(requests.exceptions.Timeout):
3668 return(connectionErrHandler(args.json, "Timeout", None))
3669 except(requests.exceptions.ConnectionError) as err:
3670 return connectionErrHandler(args.json, "ConnectionError", err)
3671 if res.status_code == 404:
3672 return "The specified Interface"+"("+args.Interface+")"+\
3673 " doesn't exist"
3674
3675 return res.text
3676
3677
3678def setMACAddress(host, args, session):
3679 """
3680 Called by the network function. Sets the MACAddress.
3681
3682 @param host: string, the hostname or IP address of the bmc
3683 @param args: contains additional arguments used by the ldap subcommand
3684 args.json: boolean, if this flag is set to true, the output
3685 will be provided in json format for programmatic consumption
3686 @param session: the active session to use
3687 """
3688
3689 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3690 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003691
3692 data = {"data": args.MACAddress}
3693
3694 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003695 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003696 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003697 except(requests.exceptions.Timeout):
3698 return(connectionErrHandler(args.json, "Timeout", None))
3699 except(requests.exceptions.ConnectionError) as err:
3700 return connectionErrHandler(args.json, "ConnectionError", err)
3701 if res.status_code == 403:
3702 return "The specified Interface"+"("+args.Interface+")"+\
3703 " doesn't exist"
3704
3705 return res.text
3706
3707
3708def getDefaultGateway(host, args, session):
3709
3710 """
3711 Called by the network function. Prints out the DefaultGateway.
3712
3713 @param host: string, the hostname or IP address of the bmc
3714 @param args: contains additional arguments used by the ldap subcommand
3715 args.json: boolean, if this flag is set to true, the output
3716 will be provided in json format for programmatic consumption
3717 @param session: the active session to use
3718 """
3719
3720 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003721
3722 try:
Justin Thaler27197622019-01-23 14:42:11 -06003723 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003724 except(requests.exceptions.Timeout):
3725 return(connectionErrHandler(args.json, "Timeout", None))
3726 except(requests.exceptions.ConnectionError) as err:
3727 return connectionErrHandler(args.json, "ConnectionError", err)
3728 if res.status_code == 404:
3729 return "Failed to get Default Gateway info!!"
3730
3731 return res.text
3732
3733
3734def setDefaultGateway(host, args, session):
3735 """
3736 Called by the network function. Sets the DefaultGateway.
3737
3738 @param host: string, the hostname or IP address of the bmc
3739 @param args: contains additional arguments used by the ldap subcommand
3740 args.json: boolean, if this flag is set to true, the output
3741 will be provided in json format for programmatic consumption
3742 @param session: the active session to use
3743 """
3744
3745 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003746
3747 data = {"data": args.DefaultGW}
3748
3749 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003750 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003751 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003752 except(requests.exceptions.Timeout):
3753 return(connectionErrHandler(args.json, "Timeout", None))
3754 except(requests.exceptions.ConnectionError) as err:
3755 return connectionErrHandler(args.json, "ConnectionError", err)
3756 if res.status_code == 403:
3757 return "Failed to set Default Gateway!!"
3758
3759 return res.text
3760
3761
3762def viewNWConfig(host, args, session):
3763 """
3764 Called by the ldap function. Prints out network configured properties
3765
3766 @param host: string, the hostname or IP address of the bmc
3767 @param args: contains additional arguments used by the ldap subcommand
3768 args.json: boolean, if this flag is set to true, the output
3769 will be provided in json format for programmatic consumption
3770 @param session: the active session to use
3771 @return returns LDAP's configured properties.
3772 """
3773 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003774 try:
Justin Thaler27197622019-01-23 14:42:11 -06003775 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003776 except(requests.exceptions.Timeout):
3777 return(connectionErrHandler(args.json, "Timeout", None))
3778 except(requests.exceptions.ConnectionError) as err:
3779 return connectionErrHandler(args.json, "ConnectionError", err)
3780 except(requests.exceptions.RequestException) as err:
3781 return connectionErrHandler(args.json, "RequestException", err)
3782 if res.status_code == 404:
3783 return "LDAP server config has not been created"
3784 return res.text
3785
3786
3787def getDNS(host, args, session):
3788
3789 """
3790 Called by the network function. Prints out DNS servers on the interface
3791
3792 @param host: string, the hostname or IP address of the bmc
3793 @param args: contains additional arguments used by the ldap subcommand
3794 args.json: boolean, if this flag is set to true, the output
3795 will be provided in json format for programmatic consumption
3796 @param session: the active session to use
3797 """
3798
3799 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3800 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003801
3802 try:
Justin Thaler27197622019-01-23 14:42:11 -06003803 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003804 except(requests.exceptions.Timeout):
3805 return(connectionErrHandler(args.json, "Timeout", None))
3806 except(requests.exceptions.ConnectionError) as err:
3807 return connectionErrHandler(args.json, "ConnectionError", err)
3808 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003809 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003810
3811 return res.text
3812
3813
3814def setDNS(host, args, session):
3815 """
3816 Called by the network function. Sets DNS servers on the interface.
3817
3818 @param host: string, the hostname or IP address of the bmc
3819 @param args: contains additional arguments used by the ldap subcommand
3820 args.json: boolean, if this flag is set to true, the output
3821 will be provided in json format for programmatic consumption
3822 @param session: the active session to use
3823 """
3824
3825 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3826 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003827
3828 data = {"data": args.DNSServers.split(",")}
3829
3830 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003831 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003832 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003833 except(requests.exceptions.Timeout):
3834 return(connectionErrHandler(args.json, "Timeout", None))
3835 except(requests.exceptions.ConnectionError) as err:
3836 return connectionErrHandler(args.json, "ConnectionError", err)
3837 if res.status_code == 403:
3838 return "The specified Interface"+"("+args.Interface+")" +\
3839 " doesn't exist"
3840
3841 return res.text
3842
3843
3844def getNTP(host, args, session):
3845
3846 """
3847 Called by the network function. Prints out NTP servers on the interface
3848
3849 @param host: string, the hostname or IP address of the bmc
3850 @param args: contains additional arguments used by the ldap subcommand
3851 args.json: boolean, if this flag is set to true, the output
3852 will be provided in json format for programmatic consumption
3853 @param session: the active session to use
3854 """
3855
3856 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3857 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003858 try:
Justin Thaler27197622019-01-23 14:42:11 -06003859 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003860 except(requests.exceptions.Timeout):
3861 return(connectionErrHandler(args.json, "Timeout", None))
3862 except(requests.exceptions.ConnectionError) as err:
3863 return connectionErrHandler(args.json, "ConnectionError", err)
3864 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003865 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003866
3867 return res.text
3868
3869
3870def setNTP(host, args, session):
3871 """
3872 Called by the network function. Sets NTP servers on the interface.
3873
3874 @param host: string, the hostname or IP address of the bmc
3875 @param args: contains additional arguments used by the ldap subcommand
3876 args.json: boolean, if this flag is set to true, the output
3877 will be provided in json format for programmatic consumption
3878 @param session: the active session to use
3879 """
3880
3881 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3882 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003883
3884 data = {"data": args.NTPServers.split(",")}
3885
3886 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003887 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003888 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003889 except(requests.exceptions.Timeout):
3890 return(connectionErrHandler(args.json, "Timeout", None))
3891 except(requests.exceptions.ConnectionError) as err:
3892 return connectionErrHandler(args.json, "ConnectionError", err)
3893 if res.status_code == 403:
3894 return "The specified Interface"+"("+args.Interface+")" +\
3895 " doesn't exist"
3896
3897 return res.text
3898
3899
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003900def addIP(host, args, session):
3901 """
3902 Called by the network function. Configures IP address on given interface
3903
3904 @param host: string, the hostname or IP address of the bmc
3905 @param args: contains additional arguments used by the ldap subcommand
3906 args.json: boolean, if this flag is set to true, the output
3907 will be provided in json format for programmatic consumption
3908 @param session: the active session to use
3909 """
3910
3911 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3912 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003913 protocol = {
3914 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3915 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3916 }
3917
3918 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3919 args.gateway]}
3920
3921 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003922 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003923 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003924 except(requests.exceptions.Timeout):
3925 return(connectionErrHandler(args.json, "Timeout", None))
3926 except(requests.exceptions.ConnectionError) as err:
3927 return connectionErrHandler(args.json, "ConnectionError", err)
3928 if res.status_code == 404:
3929 return "The specified Interface" + "(" + args.Interface + ")" +\
3930 " doesn't exist"
3931
3932 return res.text
3933
3934
3935def getIP(host, args, session):
3936 """
3937 Called by the network function. Prints out IP address of given interface
3938
3939 @param host: string, the hostname or IP address of the bmc
3940 @param args: contains additional arguments used by the ldap subcommand
3941 args.json: boolean, if this flag is set to true, the output
3942 will be provided in json format for programmatic consumption
3943 @param session: the active session to use
3944 """
3945
3946 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3947 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003948 try:
Justin Thaler27197622019-01-23 14:42:11 -06003949 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003950 except(requests.exceptions.Timeout):
3951 return(connectionErrHandler(args.json, "Timeout", None))
3952 except(requests.exceptions.ConnectionError) as err:
3953 return connectionErrHandler(args.json, "ConnectionError", err)
3954 if res.status_code == 404:
3955 return "The specified Interface" + "(" + args.Interface + ")" +\
3956 " doesn't exist"
3957
3958 return res.text
3959
3960
3961def deleteIP(host, args, session):
3962 """
3963 Called by the network function. Deletes the IP address from given Interface
3964
3965 @param host: string, the hostname or IP address of the bmc
3966 @param args: contains additional arguments used by the ldap subcommand
3967 @param session: the active session to use
3968 @param args.json: boolean, if this flag is set to true, the output
3969 will be provided in json format for programmatic consumption
3970 """
3971
3972 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3973 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003974 data = {"data": []}
3975 try:
Justin Thaler27197622019-01-23 14:42:11 -06003976 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003977 except(requests.exceptions.Timeout):
3978 return(connectionErrHandler(args.json, "Timeout", None))
3979 except(requests.exceptions.ConnectionError) as err:
3980 return connectionErrHandler(args.json, "ConnectionError", err)
3981 if res.status_code == 404:
3982 return "The specified Interface" + "(" + args.Interface + ")" +\
3983 " doesn't exist"
3984 objDict = json.loads(res.text)
3985 if not objDict['data']:
3986 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003987 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003988 try:
3989 if args.address in objDict['data'][obj]['Address']:
3990 url = "https://"+host+obj+"/action/Delete"
3991 try:
3992 res = session.post(url, headers=jsonHeader, json=data,
3993 verify=False, timeout=baseTimeout)
3994 except(requests.exceptions.Timeout):
3995 return(connectionErrHandler(args.json, "Timeout", None))
3996 except(requests.exceptions.ConnectionError) as err:
3997 return connectionErrHandler(args.json, "ConnectionError", err)
3998 return res.text
3999 else:
4000 continue
4001 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05004002 continue
4003 return "No object found for address " + args.address + \
4004 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004005
4006
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004007def addVLAN(host, args, session):
4008 """
4009 Called by the network function. Creates VLAN on given interface.
4010
4011 @param host: string, the hostname or IP address of the bmc
4012 @param args: contains additional arguments used by the ldap subcommand
4013 args.json: boolean, if this flag is set to true, the output
4014 will be provided in json format for programmatic consumption
4015 @param session: the active session to use
4016 """
4017
4018 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004019
Sunitha Harish0baf6372019-07-31 03:59:03 -05004020 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004021 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004022 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004023 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004024 except(requests.exceptions.Timeout):
4025 return(connectionErrHandler(args.json, "Timeout", None))
4026 except(requests.exceptions.ConnectionError) as err:
4027 return connectionErrHandler(args.json, "ConnectionError", err)
4028 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05004029 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
4030 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004031
4032 return res.text
4033
4034
4035def deleteVLAN(host, args, session):
4036 """
4037 Called by the network function. Creates VLAN on given interface.
4038
4039 @param host: string, the hostname or IP address of the bmc
4040 @param args: contains additional arguments used by the ldap subcommand
4041 args.json: boolean, if this flag is set to true, the output
4042 will be provided in json format for programmatic consumption
4043 @param session: the active session to use
4044 """
4045
Sunitha Harish577a5032019-08-08 06:27:40 -05004046 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004047 data = {"data": []}
4048
4049 try:
Justin Thaler27197622019-01-23 14:42:11 -06004050 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004051 except(requests.exceptions.Timeout):
4052 return(connectionErrHandler(args.json, "Timeout", None))
4053 except(requests.exceptions.ConnectionError) as err:
4054 return connectionErrHandler(args.json, "ConnectionError", err)
4055 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05004056 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004057
4058 return res.text
4059
4060
4061def viewDHCPConfig(host, args, session):
4062 """
4063 Called by the network function. Shows DHCP configured Properties.
4064
4065 @param host: string, the hostname or IP address of the bmc
4066 @param args: contains additional arguments used by the ldap subcommand
4067 args.json: boolean, if this flag is set to true, the output
4068 will be provided in json format for programmatic consumption
4069 @param session: the active session to use
4070 """
4071
4072 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004073
4074 try:
Justin Thaler27197622019-01-23 14:42:11 -06004075 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004076 except(requests.exceptions.Timeout):
4077 return(connectionErrHandler(args.json, "Timeout", None))
4078 except(requests.exceptions.ConnectionError) as err:
4079 return connectionErrHandler(args.json, "ConnectionError", err)
4080
4081 return res.text
4082
4083
4084def configureDHCP(host, args, session):
4085 """
4086 Called by the network function. Configures/updates DHCP Properties.
4087
4088 @param host: string, the hostname or IP address of the bmc
4089 @param args: contains additional arguments used by the ldap subcommand
4090 args.json: boolean, if this flag is set to true, the output
4091 will be provided in json format for programmatic consumption
4092 @param session: the active session to use
4093 """
4094
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004095
4096 try:
4097 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
4098 if(args.DNSEnabled == True):
4099 data = '{"data": 1}'
4100 else:
4101 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004102 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004103 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004104 if(args.HostNameEnabled == True):
4105 data = '{"data": 1}'
4106 else:
4107 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004108 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004109 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004110 if(args.NTPEnabled == True):
4111 data = '{"data": 1}'
4112 else:
4113 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004114 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004115 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004116 if(args.SendHostNameEnabled == True):
4117 data = '{"data": 1}'
4118 else:
4119 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004120 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004121 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004122 except(requests.exceptions.Timeout):
4123 return(connectionErrHandler(args.json, "Timeout", None))
4124 except(requests.exceptions.ConnectionError) as err:
4125 return connectionErrHandler(args.json, "ConnectionError", err)
4126
4127 return res.text
4128
4129
4130def nwReset(host, args, session):
4131
4132 """
4133 Called by the network function. Resets networks setting to factory defaults.
4134
4135 @param host: string, the hostname or IP address of the bmc
4136 @param args: contains additional arguments used by the ldap subcommand
4137 args.json: boolean, if this flag is set to true, the output
4138 will be provided in json format for programmatic consumption
4139 @param session: the active session to use
4140 """
4141
4142 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004143 data = '{"data":[] }'
4144 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004145 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004146 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004147
4148 except(requests.exceptions.Timeout):
4149 return(connectionErrHandler(args.json, "Timeout", None))
4150 except(requests.exceptions.ConnectionError) as err:
4151 return connectionErrHandler(args.json, "ConnectionError", err)
4152
4153 return res.text
4154
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004155def getLDAPTypeEnabled(host,session):
4156
4157 """
4158 Called by LDAP related functions to find the LDAP server type that has been enabled.
4159 Returns None if LDAP has not been configured.
4160
4161 @param host: string, the hostname or IP address of the bmc
4162 @param session: the active session to use
4163 """
4164
4165 enabled = False
4166 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4167 for key,value in serverTypeMap.items():
4168 data = {"data": []}
4169 try:
4170 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4171 except(requests.exceptions.Timeout):
4172 print(connectionErrHandler(args.json, "Timeout", None))
4173 return
4174 except(requests.exceptions.ConnectionError) as err:
4175 print(connectionErrHandler(args.json, "ConnectionError", err))
4176 return
4177
4178 enabled = res.json()['data']
4179 if (enabled):
4180 return key
4181
4182def syncRoleMap(host,args,session,fromServerType,toServerType):
4183
4184 """
4185 Called by LDAP related functions to sync the role maps
4186 Returns False if LDAP has not been configured.
4187
4188 @param host: string, the hostname or IP address of the bmc
4189 @param session: the active session to use
4190 @param fromServerType : Server type whose role map has to be copied
4191 @param toServerType : Server type to which role map has to be copied
4192 """
4193
4194 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4195
4196 try:
4197 #Note: If the fromServerType has no role map, then
4198 #the toServerType will not have any role map.
4199
4200 #delete the privilege mapping from the toServerType and
4201 #then copy the privilege mapping from fromServerType to
4202 #toServerType.
4203 args.serverType = toServerType
4204 res = deleteAllPrivilegeMapping(host, args, session)
4205
4206 data = {"data": []}
4207 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4208 #Previously enabled server type has no role map
4209 if (res.status_code != requests.codes.ok):
4210
4211 #fromServerType has no role map; So, no need to copy
4212 #role map to toServerType.
4213 return
4214
4215 objDict = json.loads(res.text)
4216 dataDict = objDict['data']
4217 for key,value in dataDict.items():
4218 data = {"data": [value["GroupName"], value["Privilege"]]}
4219 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4220
4221 except(requests.exceptions.Timeout):
4222 return(connectionErrHandler(args.json, "Timeout", None))
4223 except(requests.exceptions.ConnectionError) as err:
4224 return connectionErrHandler(args.json, "ConnectionError", err)
4225 return res.text
4226
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004227
Ratan Guptafeee6372018-10-17 23:25:51 +05304228def createPrivilegeMapping(host, args, session):
4229 """
4230 Called by the ldap function. Creates the group and the privilege mapping.
4231
4232 @param host: string, the hostname or IP address of the bmc
4233 @param args: contains additional arguments used by the ldap subcommand
4234 @param session: the active session to use
4235 @param args.json: boolean, if this flag is set to true, the output
4236 will be provided in json format for programmatic consumption
4237 """
4238
Ratan Guptafeee6372018-10-17 23:25:51 +05304239 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004240 if (isRedfishSupport):
4241 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4242
4243 #To maintain the interface compatibility between op930 and op940, the server type has been made
4244 #optional. If the server type is not specified, then create the role-mapper for the currently
4245 #enabled server type.
4246 serverType = args.serverType
4247 if (serverType is None):
4248 serverType = getLDAPTypeEnabled(host,session)
4249 if (serverType is None):
4250 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4251
4252 data = {"data": [args.groupName,args.privilege]}
4253 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4254
4255 else:
4256 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4257 data = {"data": [args.groupName,args.privilege]}
4258 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4259
Ratan Guptafeee6372018-10-17 23:25:51 +05304260 except(requests.exceptions.Timeout):
4261 return(connectionErrHandler(args.json, "Timeout", None))
4262 except(requests.exceptions.ConnectionError) as err:
4263 return connectionErrHandler(args.json, "ConnectionError", err)
4264 return res.text
4265
4266def listPrivilegeMapping(host, args, session):
4267 """
4268 Called by the ldap function. Lists the group and the privilege mapping.
4269
4270 @param host: string, the hostname or IP address of the bmc
4271 @param args: contains additional arguments used by the ldap subcommand
4272 @param session: the active session to use
4273 @param args.json: boolean, if this flag is set to true, the output
4274 will be provided in json format for programmatic consumption
4275 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004276
4277 if (isRedfishSupport):
4278 serverType = args.serverType
4279 if (serverType is None):
4280 serverType = getLDAPTypeEnabled(host,session)
4281 if (serverType is None):
4282 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4283
4284 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4285
4286 else:
4287 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4288
Ratan Guptafeee6372018-10-17 23:25:51 +05304289 data = {"data": []}
4290
4291 try:
Justin Thaler27197622019-01-23 14:42:11 -06004292 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304293 except(requests.exceptions.Timeout):
4294 return(connectionErrHandler(args.json, "Timeout", None))
4295 except(requests.exceptions.ConnectionError) as err:
4296 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004297
Ratan Guptafeee6372018-10-17 23:25:51 +05304298 return res.text
4299
4300def deletePrivilegeMapping(host, args, session):
4301 """
4302 Called by the ldap function. Deletes the mapping associated with the group.
4303
4304 @param host: string, the hostname or IP address of the bmc
4305 @param args: contains additional arguments used by the ldap subcommand
4306 @param session: the active session to use
4307 @param args.json: boolean, if this flag is set to true, the output
4308 will be provided in json format for programmatic consumption
4309 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004310
4311 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304312 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4313 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304314 data = {"data": []}
4315
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004316 if (isRedfishSupport):
4317 if (args.serverType is None):
4318 serverType = getLDAPTypeEnabled(host,session)
4319 if (serverType is None):
4320 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4321 # search for the object having the mapping for the given group
4322 for key,value in ldapNameSpaceObjects.items():
4323 if value['GroupName'] == args.groupName:
4324 path = key
4325 break
4326
4327 if path == '':
4328 return "No privilege mapping found for this group."
4329
4330 # delete the object
4331 url = 'https://'+host+path+'/action/Delete'
4332
4333 else:
4334 # not interested in the config objet
4335 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4336
4337 # search for the object having the mapping for the given group
4338 for key,value in ldapNameSpaceObjects.items():
4339 if value['GroupName'] == args.groupName:
4340 path = key
4341 break
4342
4343 if path == '':
4344 return "No privilege mapping found for this group."
4345
4346 # delete the object
4347 url = 'https://'+host+path+'/action/delete'
4348
Ratan Guptafeee6372018-10-17 23:25:51 +05304349 try:
Justin Thaler27197622019-01-23 14:42:11 -06004350 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304351 except(requests.exceptions.Timeout):
4352 return(connectionErrHandler(args.json, "Timeout", None))
4353 except(requests.exceptions.ConnectionError) as err:
4354 return connectionErrHandler(args.json, "ConnectionError", err)
4355 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304356
Sivas SRR78835272018-11-27 05:27:19 -06004357def deleteAllPrivilegeMapping(host, args, session):
4358 """
4359 Called by the ldap function. Deletes all the privilege mapping and group defined.
4360 @param host: string, the hostname or IP address of the bmc
4361 @param args: contains additional arguments used by the ldap subcommand
4362 @param session: the active session to use
4363 @param args.json: boolean, if this flag is set to true, the output
4364 will be provided in json format for programmatic consumption
4365 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004366
Sivas SRR78835272018-11-27 05:27:19 -06004367 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4368 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4369 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004370 data = {"data": []}
4371
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004372 if (isRedfishSupport):
4373 if (args.serverType is None):
4374 serverType = getLDAPTypeEnabled(host,session)
4375 if (serverType is None):
4376 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4377
4378 else:
4379 # Remove the config object.
4380 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4381
Sivas SRR78835272018-11-27 05:27:19 -06004382 try:
4383 # search for GroupName property and delete if it is available.
4384 for path in ldapNameSpaceObjects.keys():
4385 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004386 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004387 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004388
Sivas SRR78835272018-11-27 05:27:19 -06004389 except(requests.exceptions.Timeout):
4390 return(connectionErrHandler(args.json, "Timeout", None))
4391 except(requests.exceptions.ConnectionError) as err:
4392 return connectionErrHandler(args.json, "ConnectionError", err)
4393 return res.text
4394
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004395def viewLDAPConfig(host, args, session):
4396 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004397 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004398
4399 @param host: string, the hostname or IP address of the bmc
4400 @param args: contains additional arguments used by the ldap subcommand
4401 args.json: boolean, if this flag is set to true, the output
4402 will be provided in json format for programmatic consumption
4403 @param session: the active session to use
4404 @return returns LDAP's configured properties.
4405 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004406
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004407 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004408 if (isRedfishSupport):
4409
4410 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4411
4412 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4413
4414 if (serverTypeEnabled is not None):
4415 data = {"data": []}
4416 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4417 else:
4418 return("LDAP server has not been enabled...")
4419
4420 else :
4421 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4422 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4423
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004424 except(requests.exceptions.Timeout):
4425 return(connectionErrHandler(args.json, "Timeout", None))
4426 except(requests.exceptions.ConnectionError) as err:
4427 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004428 if res.status_code == 404:
4429 return "LDAP server config has not been created"
4430 return res.text
4431
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004432def str2bool(v):
4433 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4434 return True
4435 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4436 return False
4437 else:
4438 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004439
Matt Spinler7d426c22018-09-24 14:42:07 -05004440def localUsers(host, args, session):
4441 """
4442 Enables and disables local BMC users.
4443
4444 @param host: string, the hostname or IP address of the bmc
4445 @param args: contains additional arguments used by the logging sub command
4446 @param session: the active session to use
4447 """
4448
Matt Spinler7d426c22018-09-24 14:42:07 -05004449 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4450 try:
Justin Thaler27197622019-01-23 14:42:11 -06004451 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004452 except(requests.exceptions.Timeout):
4453 return(connectionErrHandler(args.json, "Timeout", None))
4454 usersDict = json.loads(res.text)
4455
4456 if not usersDict['data']:
4457 return "No users found"
4458
4459 output = ""
4460 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004461
4462 # Skip LDAP and another non-local users
4463 if 'UserEnabled' not in usersDict['data'][user]:
4464 continue
4465
Matt Spinler7d426c22018-09-24 14:42:07 -05004466 name = user.split('/')[-1]
4467 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4468
4469 if args.local_users == "queryenabled":
4470 try:
Justin Thaler27197622019-01-23 14:42:11 -06004471 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004472 except(requests.exceptions.Timeout):
4473 return(connectionErrHandler(args.json, "Timeout", None))
4474
4475 result = json.loads(res.text)
4476 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4477
4478 elif args.local_users in ["enableall", "disableall"]:
4479 action = ""
4480 if args.local_users == "enableall":
4481 data = '{"data": true}'
4482 action = "Enabling"
4483 else:
4484 data = '{"data": false}'
4485 action = "Disabling"
4486
4487 output += "{action} {name}\n".format(action=action, name=name)
4488
4489 try:
Justin Thaler27197622019-01-23 14:42:11 -06004490 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004491 except(requests.exceptions.Timeout):
4492 return connectionErrHandler(args.json, "Timeout", None)
4493 except(requests.exceptions.ConnectionError) as err:
4494 return connectionErrHandler(args.json, "ConnectionError", err)
4495 else:
4496 return "Invalid local users argument"
4497
4498 return output
4499
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004500def setPassword(host, args, session):
4501 """
4502 Set local user password
4503 @param host: string, the hostname or IP address of the bmc
4504 @param args: contains additional arguments used by the logging sub
4505 command
4506 @param session: the active session to use
4507 @param args.json: boolean, if this flag is set to true, the output
4508 will be provided in json format for programmatic consumption
4509 @return: Session object
4510 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004511 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004512 if(isRedfishSupport):
4513 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4514 args.user
4515 data = {"Password":args.password}
4516 res = session.patch(url, headers=jsonHeader, json=data,
4517 verify=False, timeout=baseTimeout)
4518 else:
4519 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4520 "/action/SetPassword"
4521 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004522 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004523 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004524 except(requests.exceptions.Timeout):
4525 return(connectionErrHandler(args.json, "Timeout", None))
4526 except(requests.exceptions.ConnectionError) as err:
4527 return connectionErrHandler(args.json, "ConnectionError", err)
4528 except(requests.exceptions.RequestException) as err:
4529 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004530 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004531
4532def getThermalZones(host, args, session):
4533 """
4534 Get the available thermal control zones
4535 @param host: string, the hostname or IP address of the bmc
4536 @param args: contains additional arguments used to get the thermal
4537 control zones
4538 @param session: the active session to use
4539 @return: Session object
4540 """
4541 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4542
4543 try:
4544 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4545 except(requests.exceptions.Timeout):
4546 return(connectionErrHandler(args.json, "Timeout", None))
4547 except(requests.exceptions.ConnectionError) as err:
4548 return connectionErrHandler(args.json, "ConnectionError", err)
4549 except(requests.exceptions.RequestException) as err:
4550 return connectionErrHandler(args.json, "RequestException", err)
4551
4552 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004553 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004554
4555 zonesDict = json.loads(res.text)
4556 if not zonesDict['data']:
4557 return "No thermal control zones found"
4558 for zone in zonesDict['data']:
4559 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4560
4561 return "Zones: [ " + z + " ]"
4562
4563
4564def getThermalMode(host, args, session):
4565 """
4566 Get thermal control mode
4567 @param host: string, the hostname or IP address of the bmc
4568 @param args: contains additional arguments used to get the thermal
4569 control mode
4570 @param session: the active session to use
4571 @param args.zone: the zone to get the mode on
4572 @return: Session object
4573 """
4574 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4575 args.zone
4576
4577 try:
4578 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4579 except(requests.exceptions.Timeout):
4580 return(connectionErrHandler(args.json, "Timeout", None))
4581 except(requests.exceptions.ConnectionError) as err:
4582 return connectionErrHandler(args.json, "ConnectionError", err)
4583 except(requests.exceptions.RequestException) as err:
4584 return connectionErrHandler(args.json, "RequestException", err)
4585
4586 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004587 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004588
4589 propsDict = json.loads(res.text)
4590 if not propsDict['data']:
4591 return "No thermal control properties found on zone(" + args.zone + ")"
4592 curMode = "Current"
4593 supModes = "Supported"
4594 result = "\n"
4595 for prop in propsDict['data']:
4596 if (prop.casefold() == curMode.casefold()):
4597 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4598 if (prop.casefold() == supModes.casefold()):
4599 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4600 result += supModes + " Modes: [ " + s + " ]\n"
4601
4602 return result
4603
4604def setThermalMode(host, args, session):
4605 """
4606 Set thermal control mode
4607 @param host: string, the hostname or IP address of the bmc
4608 @param args: contains additional arguments used for setting the thermal
4609 control mode
4610 @param session: the active session to use
4611 @param args.zone: the zone to set the mode on
4612 @param args.mode: the mode to enable
4613 @return: Session object
4614 """
4615 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4616 args.zone + "/attr/Current"
4617
4618 # Check args.mode against supported modes using `getThermalMode` output
4619 modes = getThermalMode(host, args, session)
4620 modes = os.linesep.join([m for m in modes.splitlines() if m])
4621 modes = modes.replace("\n", ";").strip()
4622 modesDict = dict(m.split(': ') for m in modes.split(';'))
4623 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4624 if args.mode.casefold() not in \
4625 (m.casefold() for m in sModes.split(',')) or not args.mode:
4626 result = ("Unsupported mode('" + args.mode + "') given, " +
4627 "select a supported mode: \n" +
4628 getThermalMode(host, args, session))
4629 return result
4630
4631 data = '{"data":"' + args.mode + '"}'
4632 try:
4633 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4634 except(requests.exceptions.Timeout):
4635 return(connectionErrHandler(args.json, "Timeout", None))
4636 except(requests.exceptions.ConnectionError) as err:
4637 return connectionErrHandler(args.json, "ConnectionError", err)
4638 except(requests.exceptions.RequestException) as err:
4639 return connectionErrHandler(args.json, "RequestException", err)
4640
4641 if (data and res.status_code != 404):
4642 try:
4643 res = session.put(url, headers=jsonHeader,
4644 data=data, verify=False,
4645 timeout=30)
4646 except(requests.exceptions.Timeout):
4647 return(connectionErrHandler(args.json, "Timeout", None))
4648 except(requests.exceptions.ConnectionError) as err:
4649 return connectionErrHandler(args.json, "ConnectionError", err)
4650 except(requests.exceptions.RequestException) as err:
4651 return connectionErrHandler(args.json, "RequestException", err)
4652
4653 if res.status_code == 403:
4654 return "The specified thermal control zone(" + args.zone + ")" + \
4655 " does not exist"
4656
4657 return res.text
4658 else:
4659 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004660 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004661
4662
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004663def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004664 """
4665 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004666
Justin Thalere412dc22018-01-12 16:28:24 -06004667 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004668 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004669 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004670 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4671 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004672 group = parser.add_mutually_exclusive_group()
4673 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4674 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004675 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004676 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4677 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4678 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4679 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004680 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4681 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004682
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004683 #fru command
4684 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004685 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 -05004686 inv_subparser.required = True
4687 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004688 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4689 inv_print.set_defaults(func=fruPrint)
4690 #fru list [0....n]
4691 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4692 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4693 inv_list.set_defaults(func=fruList)
4694 #fru status
4695 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004696 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004697 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004698
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004699 #sensors command
4700 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004701 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 -05004702 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004703 #sensor print
4704 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4705 sens_print.set_defaults(func=sensor)
4706 #sensor list[0...n]
4707 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4708 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4709 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004710
Matthew Barth368e83c2019-02-01 13:48:25 -06004711 #thermal control commands
4712 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4713 therm_subparser=parser_therm.add_subparsers(title='subcommands', description='Thermal control actions to work with', help='Valid thermal control actions to work with', dest='command')
4714 #thermal control zones
4715 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4716 parser_thermZones.set_defaults(func=getThermalZones)
4717 #thermal control modes
4718 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4719 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4720 #get thermal control mode
4721 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4722 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4723 parser_getThermMode.set_defaults(func=getThermalMode)
4724 #set thermal control mode
4725 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4726 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4727 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4728 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004729
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004730 #sel command
4731 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004732 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 -05004733 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004734 #sel print
4735 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4736 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4737 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4738 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4739 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004740
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004741 #sel list
4742 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")
4743 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4744 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004745
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004746 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4747 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4748 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004749
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004750 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4751 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004752
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004753 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004754 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4755 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4756 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4757 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004758 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004759
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004760 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004761 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004762
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004763 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4764 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004765
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004766 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 -06004767 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 -06004768 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004769
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004770 #control the chassis identify led
4771 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4772 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4773 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004774
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004775 #collect service data
4776 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4777 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4778 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004779
Justin Thalere412dc22018-01-12 16:28:24 -06004780 #system quick health check
4781 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4782 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004783
Ravi Tejad8be0b42020-03-18 14:31:46 -05004784 #work with dumps
4785 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4786 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004787 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004788 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004789 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4790 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004791
Ravi Tejad8be0b42020-03-18 14:31:46 -05004792 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4793 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004794
Ravi Tejad8be0b42020-03-18 14:31:46 -05004795 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004796 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004797 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004798
Justin Thalere412dc22018-01-12 16:28:24 -06004799 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004800 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4801 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004802
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004803 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004804 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4805 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4806 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004807
Justin Thaler22b1bb52018-03-15 13:31:32 -05004808 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004809 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004810 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004811 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4812 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 -06004813 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.")
4814 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004815
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004816 #add alias to the bmc command
4817 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004818 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004819 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4820 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4821 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4822 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 -06004823 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004824 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004825
Justin Thalere412dc22018-01-12 16:28:24 -06004826 #gard clear
4827 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4828 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004829
Justin Thalere412dc22018-01-12 16:28:24 -06004830 #firmware_flash
4831 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4832 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 -05004833 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004834
Justin Thalere412dc22018-01-12 16:28:24 -06004835 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4836 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4837 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4838 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004839
Justin Thaler22b1bb52018-03-15 13:31:32 -05004840 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004841 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4842 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004843
Justin Thaler22b1bb52018-03-15 13:31:32 -05004844 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4845 fwActivateStatus.set_defaults(func=activateStatus)
4846
Justin Thaler3d71d402018-07-24 14:35:39 -05004847 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4848 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4849 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004850
Justin Thaler3d71d402018-07-24 14:35:39 -05004851 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4852 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4853 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004854
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004855 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4856 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4857 fwDelete.set_defaults(func=deleteFWVersion)
4858
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004859 #logging
4860 parser_logging = subparsers.add_parser("logging", help="logging controls")
4861 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004862
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004863 #turn rest api logging on/off
4864 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4865 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4866 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004867
4868 #remote logging
4869 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4870 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4871 parser_remote_logging.set_defaults(func=remoteLogging)
4872
4873 #configure remote logging
4874 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4875 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4876 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4877 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004878
4879 #certificate management
4880 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4881 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4882
4883 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4884 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4885 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4886 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4887 certUpdate.set_defaults(func=certificateUpdate)
4888
4889 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4890 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4891 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4892 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004893
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004894 certReplace = certMgmt_subproc.add_parser('replace',
4895 help="Replace the certificate")
4896 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4897 help="certificate type to replace")
4898 certReplace.add_argument('service', choices=['https', 'ldap'],
4899 help="Service to replace the certificate")
4900 certReplace.add_argument('-f', '--fileloc', required=True,
4901 help="The absolute path to the certificate file")
4902 certReplace.set_defaults(func=certificateReplace)
4903
Marri Devender Rao34646402019-07-01 05:46:03 -05004904 certDisplay = certMgmt_subproc.add_parser('display',
4905 help="Print the certificate")
4906 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4907 help="certificate type to display")
4908 certDisplay.set_defaults(func=certificateDisplay)
4909
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004910 certList = certMgmt_subproc.add_parser('list',
4911 help="Certificate list")
4912 certList.set_defaults(func=certificateList)
4913
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004914 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4915 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4916 help="Generate CSR")
4917 certGenerateCSR.add_argument('city',
4918 help="The city or locality of the organization making the request")
4919 certGenerateCSR.add_argument('commonName',
4920 help="The fully qualified domain name of the component that is being secured.")
4921 certGenerateCSR.add_argument('country',
4922 help="The country of the organization making the request")
4923 certGenerateCSR.add_argument('organization',
4924 help="The name of the organization making the request.")
4925 certGenerateCSR.add_argument('organizationUnit',
4926 help="The name of the unit or division of the organization making the request.")
4927 certGenerateCSR.add_argument('state',
4928 help="The state, province, or region of the organization making the request.")
4929 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4930 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004931 certGenerateCSR.add_argument('keyCurveId',
4932 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4933 certGenerateCSR.add_argument('contactPerson',
4934 help="The name of the user making the request")
4935 certGenerateCSR.add_argument('email',
4936 help="The email address of the contact within the organization")
4937 certGenerateCSR.add_argument('alternativeNames',
4938 help="Additional hostnames of the component that is being secured")
4939 certGenerateCSR.add_argument('givenname',
4940 help="The given name of the user making the request")
4941 certGenerateCSR.add_argument('surname',
4942 help="The surname of the user making the request")
4943 certGenerateCSR.add_argument('unstructuredname',
4944 help="he unstructured name of the subject")
4945 certGenerateCSR.add_argument('initials',
4946 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004947 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4948
Matt Spinler7d426c22018-09-24 14:42:07 -05004949 # local users
4950 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4951 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4952 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4953 parser_users.set_defaults(func=localUsers)
4954
Ratan Gupta9166cd22018-10-01 18:09:40 +05304955 #LDAP
4956 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4957 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4958
4959 #configure and enable LDAP
4960 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4961 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4962 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4963 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4964 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4965 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4966 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004967 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304968 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004969 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4970 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4971 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304972
4973 # disable LDAP
4974 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4975 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004976 # view-config
4977 parser_ldap_config = \
4978 ldap_sub.add_parser("view-config", help="prints out a list of all \
4979 LDAPS's configured properties")
4980 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304981
Ratan Guptafeee6372018-10-17 23:25:51 +05304982 #create group privilege mapping
4983 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4984 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4985 help="sub-command help", dest='command')
4986
4987 parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004988 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4989 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304990 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004991 parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-operator','priv-user','priv-callback'],required=True,help="Privilege")
Ratan Guptafeee6372018-10-17 23:25:51 +05304992 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4993
4994 #list group privilege mapping
4995 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004996 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4997 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304998 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4999
5000 #delete group privilege mapping
5001 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005002 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5003 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05305004 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
5005 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
5006
Sivas SRR78835272018-11-27 05:27:19 -06005007 #deleteAll group privilege mapping
5008 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005009 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5010 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06005011 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
5012
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06005013 # set local user password
5014 parser_set_password = subparsers.add_parser("set_password",
5015 help="Set password of local user")
5016 parser_set_password.add_argument( "-p", "--password", required=True,
5017 help="Password of local user")
5018 parser_set_password.set_defaults(func=setPassword)
5019
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005020 # network
5021 parser_nw = subparsers.add_parser("network", help="network controls")
5022 nw_sub = parser_nw.add_subparsers(title='subcommands',
5023 description='valid subcommands',
5024 help="sub-command help",
5025 dest='command')
5026
5027 # enable DHCP
5028 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
5029 help="enables the DHCP on given "
5030 "Interface")
5031 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005032 help="Name of the ethernet interface(it can"
5033 "be obtained by the "
5034 "command:network view-config)"
5035 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005036 parser_enable_dhcp.set_defaults(func=enableDHCP)
5037
5038 # disable DHCP
5039 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
5040 help="disables the DHCP on given "
5041 "Interface")
5042 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005043 help="Name of the ethernet interface(it can"
5044 "be obtained by the "
5045 "command:network view-config)"
5046 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005047 parser_disable_dhcp.set_defaults(func=disableDHCP)
5048
5049 # get HostName
5050 parser_gethostname = nw_sub.add_parser("getHostName",
5051 help="prints out HostName")
5052 parser_gethostname.set_defaults(func=getHostname)
5053
5054 # set HostName
5055 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
5056 parser_sethostname.add_argument("-H", "--HostName", required=True,
5057 help="A HostName for the BMC")
5058 parser_sethostname.set_defaults(func=setHostname)
5059
5060 # get domainname
5061 parser_getdomainname = nw_sub.add_parser("getDomainName",
5062 help="prints out DomainName of "
5063 "given Interface")
5064 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005065 help="Name of the ethernet interface(it "
5066 "can be obtained by the "
5067 "command:network view-config)"
5068 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005069 parser_getdomainname.set_defaults(func=getDomainName)
5070
5071 # set domainname
5072 parser_setdomainname = nw_sub.add_parser("setDomainName",
5073 help="sets DomainName of given "
5074 "Interface")
5075 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
5076 help="Ex: DomainName=Domain1,Domain2,...")
5077 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005078 help="Name of the ethernet interface(it "
5079 "can be obtained by the "
5080 "command:network view-config)"
5081 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005082 parser_setdomainname.set_defaults(func=setDomainName)
5083
5084 # get MACAddress
5085 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
5086 help="prints out MACAddress the "
5087 "given Interface")
5088 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005089 help="Name of the ethernet interface(it "
5090 "can be obtained by the "
5091 "command:network view-config)"
5092 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005093 parser_getmacaddress.set_defaults(func=getMACAddress)
5094
5095 # set MACAddress
5096 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
5097 help="sets MACAddress")
5098 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
5099 help="A MACAddress for the given "
5100 "Interface")
5101 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005102 help="Name of the ethernet interface(it can"
5103 "be obtained by the "
5104 "command:network view-config)"
5105 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005106 parser_setmacaddress.set_defaults(func=setMACAddress)
5107
5108 # get DefaultGW
5109 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
5110 help="prints out DefaultGateway "
5111 "the BMC")
5112 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
5113
5114 # set DefaultGW
5115 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
5116 help="sets DefaultGW")
5117 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
5118 help="A DefaultGateway for the BMC")
5119 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
5120
5121 # view network Config
5122 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
5123 "list of all network's configured "
5124 "properties")
5125 parser_ldap_config.set_defaults(func=viewNWConfig)
5126
5127 # get DNS
5128 parser_getDNS = nw_sub.add_parser("getDNS",
5129 help="prints out DNS servers on the "
5130 "given interface")
5131 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005132 help="Name of the ethernet interface(it can"
5133 "be obtained by the "
5134 "command:network view-config)"
5135 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005136 parser_getDNS.set_defaults(func=getDNS)
5137
5138 # set DNS
5139 parser_setDNS = nw_sub.add_parser("setDNS",
5140 help="sets DNS servers on the given "
5141 "interface")
5142 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5143 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5144 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005145 help="Name of the ethernet interface(it can"
5146 "be obtained by the "
5147 "command:network view-config)"
5148 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005149 parser_setDNS.set_defaults(func=setDNS)
5150
5151 # get NTP
5152 parser_getNTP = nw_sub.add_parser("getNTP",
5153 help="prints out NTP servers on the "
5154 "given interface")
5155 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005156 help="Name of the ethernet interface(it can"
5157 "be obtained by the "
5158 "command:network view-config)"
5159 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005160 parser_getNTP.set_defaults(func=getNTP)
5161
5162 # set NTP
5163 parser_setNTP = nw_sub.add_parser("setNTP",
5164 help="sets NTP servers on the given "
5165 "interface")
5166 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5167 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5168 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005169 help="Name of the ethernet interface(it can"
5170 "be obtained by the "
5171 "command:network view-config)"
5172 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005173 parser_setNTP.set_defaults(func=setNTP)
5174
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005175 # configure IP
5176 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5177 "given interface")
5178 parser_ip_config.add_argument("-a", "--address", required=True,
5179 help="IP address of given interface")
5180 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5181 help="The gateway for given interface")
5182 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5183 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005184 parser_ip_config.add_argument("-p", "--type", required=True,
5185 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005186 help="The protocol type of the given"
5187 "IP address")
5188 parser_ip_config.add_argument("-I", "--Interface", required=True,
5189 help="Name of the ethernet interface(it can"
5190 "be obtained by the "
5191 "command:network view-config)"
5192 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5193 parser_ip_config.set_defaults(func=addIP)
5194
5195 # getIP
5196 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5197 "of given interface")
5198 parser_getIP.add_argument("-I", "--Interface", required=True,
5199 help="Name of the ethernet interface(it can"
5200 "be obtained by the command:network view-config)"
5201 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5202 parser_getIP.set_defaults(func=getIP)
5203
5204 # rmIP
5205 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5206 "of given interface")
5207 parser_rmIP.add_argument("-a", "--address", required=True,
5208 help="IP address to remove form given Interface")
5209 parser_rmIP.add_argument("-I", "--Interface", required=True,
5210 help="Name of the ethernet interface(it can"
5211 "be obtained by the command:network view-config)"
5212 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5213 parser_rmIP.set_defaults(func=deleteIP)
5214
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005215 # add VLAN
5216 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5217 "on given interface with given "
5218 "VLAN Identifier")
5219 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5220 choices=['eth0', 'eth1'],
5221 help="Name of the ethernet interface")
5222 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5223 help="VLAN Identifier")
5224 parser_create_vlan.set_defaults(func=addVLAN)
5225
5226 # delete VLAN
5227 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5228 "on given interface with given "
5229 "VLAN Identifier")
5230 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5231 help="Name of the ethernet interface(it can"
5232 "be obtained by the "
5233 "command:network view-config)"
5234 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5235 parser_delete_vlan.set_defaults(func=deleteVLAN)
5236
5237 # viewDHCPConfig
5238 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5239 help="Shows DHCP configured "
5240 "Properties")
5241 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5242
5243 # configureDHCP
5244 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5245 help="Configures/updates DHCP "
5246 "Properties")
5247 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5248 required=True, help="Sets DNSEnabled property")
5249 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5250 required=True,
5251 help="Sets HostNameEnabled property")
5252 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5253 required=True,
5254 help="Sets NTPEnabled property")
5255 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5256 required=True,
5257 help="Sets SendHostNameEnabled property")
5258 parser_configDHCP.set_defaults(func=configureDHCP)
5259
5260 # network factory reset
5261 parser_nw_reset = nw_sub.add_parser("nwReset",
5262 help="Resets networks setting to "
5263 "factory defaults. "
5264 "note:Reset settings will be applied "
5265 "after BMC reboot")
5266 parser_nw_reset.set_defaults(func=nwReset)
5267
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005268 return parser
5269
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005270def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005271 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005272 main function for running the command line utility as a sub application
5273 """
5274 global toolVersion
Justin Thalerc42e4e52020-05-13 12:04:24 -05005275 toolVersion = "1.19"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005276 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005277
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005278 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005279 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005280
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005281 totTimeStart = int(round(time.time()*1000))
5282
5283 if(sys.version_info < (3,0)):
5284 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5285 if sys.version_info >= (3,0):
5286 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005287 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005288 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005289 sys.exit(0)
5290 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005291 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005292 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005293 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005294 if(hasattr(args, 'host') and hasattr(args,'user')):
5295 if (args.askpw):
5296 pw = getpass.getpass()
5297 elif(args.PW is not None):
5298 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005299 elif(args.PWenvvar):
5300 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005301 else:
5302 print("You must specify a password")
5303 sys.exit()
5304 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005305 mysess = login(args.host, args.user, pw, args.json,
5306 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005307 if(mysess == None):
5308 print("Login Failed!")
5309 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005310 if(sys.version_info < (3,0)):
5311 if isinstance(mysess, basestring):
5312 print(mysess)
5313 sys.exit(1)
5314 elif sys.version_info >= (3,0):
5315 if isinstance(mysess, str):
5316 print(mysess)
5317 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005318 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005319 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005320 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005321 output = args.func(args.host, args, mysess)
5322 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005323 if isinstance(output, dict):
5324 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5325 else:
5326 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005327 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005328 logout(args.host, args.user, pw, mysess, args.json)
5329 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005330 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5331 print("loginTime: " + str(logintimeStop - logintimeStart))
5332 print("command Time: " + str(commandTimeStop - commandTimeStart))
5333 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005334 print("usage:\n"
5335 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5336 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005337 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005338 "\t{fru,sensors,sel,chassis,collect_service_data, \
5339 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005340 "\t...\n" +
5341 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005342 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005343
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005344if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005345 """
5346 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005347
5348 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005349 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005350
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005351 isTTY = sys.stdout.isatty()
5352 assert sys.version_info >= (2,7)
5353 main()