blob: 025cae71d509e44950d64ec82b0cdd2af3b97ab8 [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:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003644 return "Failed to set Domain Name"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003645
3646 return res.text
3647
3648
3649def getMACAddress(host, args, session):
3650
3651 """
3652 Called by the network function. Prints out the MACAddress.
3653
3654 @param host: string, the hostname or IP address of the bmc
3655 @param args: contains additional arguments used by the ldap subcommand
3656 args.json: boolean, if this flag is set to true, the output
3657 will be provided in json format for programmatic consumption
3658 @param session: the active session to use
3659 """
3660
3661 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3662 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003663
3664 try:
Justin Thaler27197622019-01-23 14:42:11 -06003665 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003666 except(requests.exceptions.Timeout):
3667 return(connectionErrHandler(args.json, "Timeout", None))
3668 except(requests.exceptions.ConnectionError) as err:
3669 return connectionErrHandler(args.json, "ConnectionError", err)
3670 if res.status_code == 404:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003671 return "Failed to get MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003672
3673 return res.text
3674
3675
3676def setMACAddress(host, args, session):
3677 """
3678 Called by the network function. Sets the MACAddress.
3679
3680 @param host: string, the hostname or IP address of the bmc
3681 @param args: contains additional arguments used by the ldap subcommand
3682 args.json: boolean, if this flag is set to true, the output
3683 will be provided in json format for programmatic consumption
3684 @param session: the active session to use
3685 """
3686
3687 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3688 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003689
3690 data = {"data": args.MACAddress}
3691
3692 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003693 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003694 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003695 except(requests.exceptions.Timeout):
3696 return(connectionErrHandler(args.json, "Timeout", None))
3697 except(requests.exceptions.ConnectionError) as err:
3698 return connectionErrHandler(args.json, "ConnectionError", err)
3699 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003700 return "Failed to set MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003701
3702 return res.text
3703
3704
3705def getDefaultGateway(host, args, session):
3706
3707 """
3708 Called by the network function. Prints out the DefaultGateway.
3709
3710 @param host: string, the hostname or IP address of the bmc
3711 @param args: contains additional arguments used by the ldap subcommand
3712 args.json: boolean, if this flag is set to true, the output
3713 will be provided in json format for programmatic consumption
3714 @param session: the active session to use
3715 """
3716
3717 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003718
3719 try:
Justin Thaler27197622019-01-23 14:42:11 -06003720 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003721 except(requests.exceptions.Timeout):
3722 return(connectionErrHandler(args.json, "Timeout", None))
3723 except(requests.exceptions.ConnectionError) as err:
3724 return connectionErrHandler(args.json, "ConnectionError", err)
3725 if res.status_code == 404:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003726 return "Failed to get Default Gateway info"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003727
3728 return res.text
3729
3730
3731def setDefaultGateway(host, args, session):
3732 """
3733 Called by the network function. Sets the DefaultGateway.
3734
3735 @param host: string, the hostname or IP address of the bmc
3736 @param args: contains additional arguments used by the ldap subcommand
3737 args.json: boolean, if this flag is set to true, the output
3738 will be provided in json format for programmatic consumption
3739 @param session: the active session to use
3740 """
3741
3742 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003743
3744 data = {"data": args.DefaultGW}
3745
3746 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003747 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003748 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003749 except(requests.exceptions.Timeout):
3750 return(connectionErrHandler(args.json, "Timeout", None))
3751 except(requests.exceptions.ConnectionError) as err:
3752 return connectionErrHandler(args.json, "ConnectionError", err)
3753 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003754 return "Failed to set Default Gateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003755
3756 return res.text
3757
3758
3759def viewNWConfig(host, args, session):
3760 """
3761 Called by the ldap function. Prints out network configured properties
3762
3763 @param host: string, the hostname or IP address of the bmc
3764 @param args: contains additional arguments used by the ldap subcommand
3765 args.json: boolean, if this flag is set to true, the output
3766 will be provided in json format for programmatic consumption
3767 @param session: the active session to use
3768 @return returns LDAP's configured properties.
3769 """
3770 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003771 try:
Justin Thaler27197622019-01-23 14:42:11 -06003772 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003773 except(requests.exceptions.Timeout):
3774 return(connectionErrHandler(args.json, "Timeout", None))
3775 except(requests.exceptions.ConnectionError) as err:
3776 return connectionErrHandler(args.json, "ConnectionError", err)
3777 except(requests.exceptions.RequestException) as err:
3778 return connectionErrHandler(args.json, "RequestException", err)
3779 if res.status_code == 404:
3780 return "LDAP server config has not been created"
3781 return res.text
3782
3783
3784def getDNS(host, args, session):
3785
3786 """
3787 Called by the network function. Prints out DNS servers on the interface
3788
3789 @param host: string, the hostname or IP address of the bmc
3790 @param args: contains additional arguments used by the ldap subcommand
3791 args.json: boolean, if this flag is set to true, the output
3792 will be provided in json format for programmatic consumption
3793 @param session: the active session to use
3794 """
3795
3796 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3797 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003798
3799 try:
Justin Thaler27197622019-01-23 14:42:11 -06003800 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003801 except(requests.exceptions.Timeout):
3802 return(connectionErrHandler(args.json, "Timeout", None))
3803 except(requests.exceptions.ConnectionError) as err:
3804 return connectionErrHandler(args.json, "ConnectionError", err)
3805 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003806 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003807
3808 return res.text
3809
3810
3811def setDNS(host, args, session):
3812 """
3813 Called by the network function. Sets DNS servers on the interface.
3814
3815 @param host: string, the hostname or IP address of the bmc
3816 @param args: contains additional arguments used by the ldap subcommand
3817 args.json: boolean, if this flag is set to true, the output
3818 will be provided in json format for programmatic consumption
3819 @param session: the active session to use
3820 """
3821
3822 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3823 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003824
3825 data = {"data": args.DNSServers.split(",")}
3826
3827 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003828 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003829 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003830 except(requests.exceptions.Timeout):
3831 return(connectionErrHandler(args.json, "Timeout", None))
3832 except(requests.exceptions.ConnectionError) as err:
3833 return connectionErrHandler(args.json, "ConnectionError", err)
3834 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003835 return "Failed to set DNS"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003836
3837 return res.text
3838
3839
3840def getNTP(host, args, session):
3841
3842 """
3843 Called by the network function. Prints out NTP servers on the interface
3844
3845 @param host: string, the hostname or IP address of the bmc
3846 @param args: contains additional arguments used by the ldap subcommand
3847 args.json: boolean, if this flag is set to true, the output
3848 will be provided in json format for programmatic consumption
3849 @param session: the active session to use
3850 """
3851
3852 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3853 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003854 try:
Justin Thaler27197622019-01-23 14:42:11 -06003855 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003856 except(requests.exceptions.Timeout):
3857 return(connectionErrHandler(args.json, "Timeout", None))
3858 except(requests.exceptions.ConnectionError) as err:
3859 return connectionErrHandler(args.json, "ConnectionError", err)
3860 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003861 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003862
3863 return res.text
3864
3865
3866def setNTP(host, args, session):
3867 """
3868 Called by the network function. Sets NTP servers on the interface.
3869
3870 @param host: string, the hostname or IP address of the bmc
3871 @param args: contains additional arguments used by the ldap subcommand
3872 args.json: boolean, if this flag is set to true, the output
3873 will be provided in json format for programmatic consumption
3874 @param session: the active session to use
3875 """
3876
3877 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3878 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003879
3880 data = {"data": args.NTPServers.split(",")}
3881
3882 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003883 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003884 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003885 except(requests.exceptions.Timeout):
3886 return(connectionErrHandler(args.json, "Timeout", None))
3887 except(requests.exceptions.ConnectionError) as err:
3888 return connectionErrHandler(args.json, "ConnectionError", err)
3889 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003890 return "Failed to set NTP"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003891
3892 return res.text
3893
3894
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003895def addIP(host, args, session):
3896 """
3897 Called by the network function. Configures IP address on given interface
3898
3899 @param host: string, the hostname or IP address of the bmc
3900 @param args: contains additional arguments used by the ldap subcommand
3901 args.json: boolean, if this flag is set to true, the output
3902 will be provided in json format for programmatic consumption
3903 @param session: the active session to use
3904 """
3905
3906 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3907 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003908 protocol = {
3909 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3910 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3911 }
3912
3913 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3914 args.gateway]}
3915
3916 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003917 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003918 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003919 except(requests.exceptions.Timeout):
3920 return(connectionErrHandler(args.json, "Timeout", None))
3921 except(requests.exceptions.ConnectionError) as err:
3922 return connectionErrHandler(args.json, "ConnectionError", err)
3923 if res.status_code == 404:
3924 return "The specified Interface" + "(" + args.Interface + ")" +\
3925 " doesn't exist"
3926
3927 return res.text
3928
3929
3930def getIP(host, args, session):
3931 """
3932 Called by the network function. Prints out IP address of given interface
3933
3934 @param host: string, the hostname or IP address of the bmc
3935 @param args: contains additional arguments used by the ldap subcommand
3936 args.json: boolean, if this flag is set to true, the output
3937 will be provided in json format for programmatic consumption
3938 @param session: the active session to use
3939 """
3940
3941 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3942 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003943 try:
Justin Thaler27197622019-01-23 14:42:11 -06003944 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003945 except(requests.exceptions.Timeout):
3946 return(connectionErrHandler(args.json, "Timeout", None))
3947 except(requests.exceptions.ConnectionError) as err:
3948 return connectionErrHandler(args.json, "ConnectionError", err)
3949 if res.status_code == 404:
3950 return "The specified Interface" + "(" + args.Interface + ")" +\
3951 " doesn't exist"
3952
3953 return res.text
3954
3955
3956def deleteIP(host, args, session):
3957 """
3958 Called by the network function. Deletes the IP address from given Interface
3959
3960 @param host: string, the hostname or IP address of the bmc
3961 @param args: contains additional arguments used by the ldap subcommand
3962 @param session: the active session to use
3963 @param args.json: boolean, if this flag is set to true, the output
3964 will be provided in json format for programmatic consumption
3965 """
3966
3967 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3968 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003969 data = {"data": []}
3970 try:
Justin Thaler27197622019-01-23 14:42:11 -06003971 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003972 except(requests.exceptions.Timeout):
3973 return(connectionErrHandler(args.json, "Timeout", None))
3974 except(requests.exceptions.ConnectionError) as err:
3975 return connectionErrHandler(args.json, "ConnectionError", err)
3976 if res.status_code == 404:
3977 return "The specified Interface" + "(" + args.Interface + ")" +\
3978 " doesn't exist"
3979 objDict = json.loads(res.text)
3980 if not objDict['data']:
3981 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003982 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003983 try:
3984 if args.address in objDict['data'][obj]['Address']:
3985 url = "https://"+host+obj+"/action/Delete"
3986 try:
3987 res = session.post(url, headers=jsonHeader, json=data,
3988 verify=False, timeout=baseTimeout)
3989 except(requests.exceptions.Timeout):
3990 return(connectionErrHandler(args.json, "Timeout", None))
3991 except(requests.exceptions.ConnectionError) as err:
3992 return connectionErrHandler(args.json, "ConnectionError", err)
3993 return res.text
3994 else:
3995 continue
3996 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003997 continue
3998 return "No object found for address " + args.address + \
3999 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004000
4001
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004002def addVLAN(host, args, session):
4003 """
4004 Called by the network function. Creates VLAN on given interface.
4005
4006 @param host: string, the hostname or IP address of the bmc
4007 @param args: contains additional arguments used by the ldap subcommand
4008 args.json: boolean, if this flag is set to true, the output
4009 will be provided in json format for programmatic consumption
4010 @param session: the active session to use
4011 """
4012
4013 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004014
Sunitha Harish0baf6372019-07-31 03:59:03 -05004015 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004016 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004017 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004018 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004019 except(requests.exceptions.Timeout):
4020 return(connectionErrHandler(args.json, "Timeout", None))
4021 except(requests.exceptions.ConnectionError) as err:
4022 return connectionErrHandler(args.json, "ConnectionError", err)
4023 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05004024 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
4025 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004026
4027 return res.text
4028
4029
4030def deleteVLAN(host, args, session):
4031 """
4032 Called by the network function. Creates VLAN on given interface.
4033
4034 @param host: string, the hostname or IP address of the bmc
4035 @param args: contains additional arguments used by the ldap subcommand
4036 args.json: boolean, if this flag is set to true, the output
4037 will be provided in json format for programmatic consumption
4038 @param session: the active session to use
4039 """
4040
Sunitha Harish577a5032019-08-08 06:27:40 -05004041 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004042 data = {"data": []}
4043
4044 try:
Justin Thaler27197622019-01-23 14:42:11 -06004045 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004046 except(requests.exceptions.Timeout):
4047 return(connectionErrHandler(args.json, "Timeout", None))
4048 except(requests.exceptions.ConnectionError) as err:
4049 return connectionErrHandler(args.json, "ConnectionError", err)
4050 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05004051 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004052
4053 return res.text
4054
4055
4056def viewDHCPConfig(host, args, session):
4057 """
4058 Called by the network function. Shows DHCP configured Properties.
4059
4060 @param host: string, the hostname or IP address of the bmc
4061 @param args: contains additional arguments used by the ldap subcommand
4062 args.json: boolean, if this flag is set to true, the output
4063 will be provided in json format for programmatic consumption
4064 @param session: the active session to use
4065 """
4066
4067 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004068
4069 try:
Justin Thaler27197622019-01-23 14:42:11 -06004070 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004071 except(requests.exceptions.Timeout):
4072 return(connectionErrHandler(args.json, "Timeout", None))
4073 except(requests.exceptions.ConnectionError) as err:
4074 return connectionErrHandler(args.json, "ConnectionError", err)
4075
4076 return res.text
4077
4078
4079def configureDHCP(host, args, session):
4080 """
4081 Called by the network function. Configures/updates DHCP Properties.
4082
4083 @param host: string, the hostname or IP address of the bmc
4084 @param args: contains additional arguments used by the ldap subcommand
4085 args.json: boolean, if this flag is set to true, the output
4086 will be provided in json format for programmatic consumption
4087 @param session: the active session to use
4088 """
4089
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004090
4091 try:
4092 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
4093 if(args.DNSEnabled == True):
4094 data = '{"data": 1}'
4095 else:
4096 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004097 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004098 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004099 if(args.HostNameEnabled == True):
4100 data = '{"data": 1}'
4101 else:
4102 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004103 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004104 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004105 if(args.NTPEnabled == True):
4106 data = '{"data": 1}'
4107 else:
4108 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004109 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004110 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004111 if(args.SendHostNameEnabled == True):
4112 data = '{"data": 1}'
4113 else:
4114 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004115 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004116 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004117 except(requests.exceptions.Timeout):
4118 return(connectionErrHandler(args.json, "Timeout", None))
4119 except(requests.exceptions.ConnectionError) as err:
4120 return connectionErrHandler(args.json, "ConnectionError", err)
4121
4122 return res.text
4123
4124
4125def nwReset(host, args, session):
4126
4127 """
4128 Called by the network function. Resets networks setting to factory defaults.
4129
4130 @param host: string, the hostname or IP address of the bmc
4131 @param args: contains additional arguments used by the ldap subcommand
4132 args.json: boolean, if this flag is set to true, the output
4133 will be provided in json format for programmatic consumption
4134 @param session: the active session to use
4135 """
4136
4137 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004138 data = '{"data":[] }'
4139 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004140 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004141 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004142
4143 except(requests.exceptions.Timeout):
4144 return(connectionErrHandler(args.json, "Timeout", None))
4145 except(requests.exceptions.ConnectionError) as err:
4146 return connectionErrHandler(args.json, "ConnectionError", err)
4147
4148 return res.text
4149
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004150def getLDAPTypeEnabled(host,session):
4151
4152 """
4153 Called by LDAP related functions to find the LDAP server type that has been enabled.
4154 Returns None if LDAP has not been configured.
4155
4156 @param host: string, the hostname or IP address of the bmc
4157 @param session: the active session to use
4158 """
4159
4160 enabled = False
4161 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4162 for key,value in serverTypeMap.items():
4163 data = {"data": []}
4164 try:
4165 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4166 except(requests.exceptions.Timeout):
4167 print(connectionErrHandler(args.json, "Timeout", None))
4168 return
4169 except(requests.exceptions.ConnectionError) as err:
4170 print(connectionErrHandler(args.json, "ConnectionError", err))
4171 return
4172
4173 enabled = res.json()['data']
4174 if (enabled):
4175 return key
4176
4177def syncRoleMap(host,args,session,fromServerType,toServerType):
4178
4179 """
4180 Called by LDAP related functions to sync the role maps
4181 Returns False if LDAP has not been configured.
4182
4183 @param host: string, the hostname or IP address of the bmc
4184 @param session: the active session to use
4185 @param fromServerType : Server type whose role map has to be copied
4186 @param toServerType : Server type to which role map has to be copied
4187 """
4188
4189 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4190
4191 try:
4192 #Note: If the fromServerType has no role map, then
4193 #the toServerType will not have any role map.
4194
4195 #delete the privilege mapping from the toServerType and
4196 #then copy the privilege mapping from fromServerType to
4197 #toServerType.
4198 args.serverType = toServerType
4199 res = deleteAllPrivilegeMapping(host, args, session)
4200
4201 data = {"data": []}
4202 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4203 #Previously enabled server type has no role map
4204 if (res.status_code != requests.codes.ok):
4205
4206 #fromServerType has no role map; So, no need to copy
4207 #role map to toServerType.
4208 return
4209
4210 objDict = json.loads(res.text)
4211 dataDict = objDict['data']
4212 for key,value in dataDict.items():
4213 data = {"data": [value["GroupName"], value["Privilege"]]}
4214 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4215
4216 except(requests.exceptions.Timeout):
4217 return(connectionErrHandler(args.json, "Timeout", None))
4218 except(requests.exceptions.ConnectionError) as err:
4219 return connectionErrHandler(args.json, "ConnectionError", err)
4220 return res.text
4221
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004222
Ratan Guptafeee6372018-10-17 23:25:51 +05304223def createPrivilegeMapping(host, args, session):
4224 """
4225 Called by the ldap function. Creates the group and the privilege mapping.
4226
4227 @param host: string, the hostname or IP address of the bmc
4228 @param args: contains additional arguments used by the ldap subcommand
4229 @param session: the active session to use
4230 @param args.json: boolean, if this flag is set to true, the output
4231 will be provided in json format for programmatic consumption
4232 """
4233
Ratan Guptafeee6372018-10-17 23:25:51 +05304234 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004235 if (isRedfishSupport):
4236 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4237
4238 #To maintain the interface compatibility between op930 and op940, the server type has been made
4239 #optional. If the server type is not specified, then create the role-mapper for the currently
4240 #enabled server type.
4241 serverType = args.serverType
4242 if (serverType is None):
4243 serverType = getLDAPTypeEnabled(host,session)
4244 if (serverType is None):
4245 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4246
4247 data = {"data": [args.groupName,args.privilege]}
4248 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4249
4250 else:
4251 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4252 data = {"data": [args.groupName,args.privilege]}
4253 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4254
Ratan Guptafeee6372018-10-17 23:25:51 +05304255 except(requests.exceptions.Timeout):
4256 return(connectionErrHandler(args.json, "Timeout", None))
4257 except(requests.exceptions.ConnectionError) as err:
4258 return connectionErrHandler(args.json, "ConnectionError", err)
4259 return res.text
4260
4261def listPrivilegeMapping(host, args, session):
4262 """
4263 Called by the ldap function. Lists the group and the privilege mapping.
4264
4265 @param host: string, the hostname or IP address of the bmc
4266 @param args: contains additional arguments used by the ldap subcommand
4267 @param session: the active session to use
4268 @param args.json: boolean, if this flag is set to true, the output
4269 will be provided in json format for programmatic consumption
4270 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004271
4272 if (isRedfishSupport):
4273 serverType = args.serverType
4274 if (serverType is None):
4275 serverType = getLDAPTypeEnabled(host,session)
4276 if (serverType is None):
4277 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4278
4279 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4280
4281 else:
4282 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4283
Ratan Guptafeee6372018-10-17 23:25:51 +05304284 data = {"data": []}
4285
4286 try:
Justin Thaler27197622019-01-23 14:42:11 -06004287 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304288 except(requests.exceptions.Timeout):
4289 return(connectionErrHandler(args.json, "Timeout", None))
4290 except(requests.exceptions.ConnectionError) as err:
4291 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004292
Ratan Guptafeee6372018-10-17 23:25:51 +05304293 return res.text
4294
4295def deletePrivilegeMapping(host, args, session):
4296 """
4297 Called by the ldap function. Deletes the mapping associated with the group.
4298
4299 @param host: string, the hostname or IP address of the bmc
4300 @param args: contains additional arguments used by the ldap subcommand
4301 @param session: the active session to use
4302 @param args.json: boolean, if this flag is set to true, the output
4303 will be provided in json format for programmatic consumption
4304 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004305
4306 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304307 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4308 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304309 data = {"data": []}
4310
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004311 if (isRedfishSupport):
4312 if (args.serverType is None):
4313 serverType = getLDAPTypeEnabled(host,session)
4314 if (serverType is None):
4315 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4316 # search for the object having the mapping for the given group
4317 for key,value in ldapNameSpaceObjects.items():
4318 if value['GroupName'] == args.groupName:
4319 path = key
4320 break
4321
4322 if path == '':
4323 return "No privilege mapping found for this group."
4324
4325 # delete the object
4326 url = 'https://'+host+path+'/action/Delete'
4327
4328 else:
4329 # not interested in the config objet
4330 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4331
4332 # search for the object having the mapping for the given group
4333 for key,value in ldapNameSpaceObjects.items():
4334 if value['GroupName'] == args.groupName:
4335 path = key
4336 break
4337
4338 if path == '':
4339 return "No privilege mapping found for this group."
4340
4341 # delete the object
4342 url = 'https://'+host+path+'/action/delete'
4343
Ratan Guptafeee6372018-10-17 23:25:51 +05304344 try:
Justin Thaler27197622019-01-23 14:42:11 -06004345 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304346 except(requests.exceptions.Timeout):
4347 return(connectionErrHandler(args.json, "Timeout", None))
4348 except(requests.exceptions.ConnectionError) as err:
4349 return connectionErrHandler(args.json, "ConnectionError", err)
4350 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304351
Sivas SRR78835272018-11-27 05:27:19 -06004352def deleteAllPrivilegeMapping(host, args, session):
4353 """
4354 Called by the ldap function. Deletes all the privilege mapping and group defined.
4355 @param host: string, the hostname or IP address of the bmc
4356 @param args: contains additional arguments used by the ldap subcommand
4357 @param session: the active session to use
4358 @param args.json: boolean, if this flag is set to true, the output
4359 will be provided in json format for programmatic consumption
4360 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004361
Sivas SRR78835272018-11-27 05:27:19 -06004362 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4363 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4364 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004365 data = {"data": []}
4366
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004367 if (isRedfishSupport):
4368 if (args.serverType is None):
4369 serverType = getLDAPTypeEnabled(host,session)
4370 if (serverType is None):
4371 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4372
4373 else:
4374 # Remove the config object.
4375 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4376
Sivas SRR78835272018-11-27 05:27:19 -06004377 try:
4378 # search for GroupName property and delete if it is available.
4379 for path in ldapNameSpaceObjects.keys():
4380 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004381 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004382 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004383
Sivas SRR78835272018-11-27 05:27:19 -06004384 except(requests.exceptions.Timeout):
4385 return(connectionErrHandler(args.json, "Timeout", None))
4386 except(requests.exceptions.ConnectionError) as err:
4387 return connectionErrHandler(args.json, "ConnectionError", err)
4388 return res.text
4389
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004390def viewLDAPConfig(host, args, session):
4391 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004392 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004393
4394 @param host: string, the hostname or IP address of the bmc
4395 @param args: contains additional arguments used by the ldap subcommand
4396 args.json: boolean, if this flag is set to true, the output
4397 will be provided in json format for programmatic consumption
4398 @param session: the active session to use
4399 @return returns LDAP's configured properties.
4400 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004401
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004402 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004403 if (isRedfishSupport):
4404
4405 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4406
4407 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4408
4409 if (serverTypeEnabled is not None):
4410 data = {"data": []}
4411 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4412 else:
4413 return("LDAP server has not been enabled...")
4414
4415 else :
4416 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4417 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4418
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004419 except(requests.exceptions.Timeout):
4420 return(connectionErrHandler(args.json, "Timeout", None))
4421 except(requests.exceptions.ConnectionError) as err:
4422 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004423 if res.status_code == 404:
4424 return "LDAP server config has not been created"
4425 return res.text
4426
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004427def str2bool(v):
4428 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4429 return True
4430 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4431 return False
4432 else:
4433 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004434
Matt Spinler7d426c22018-09-24 14:42:07 -05004435def localUsers(host, args, session):
4436 """
4437 Enables and disables local BMC users.
4438
4439 @param host: string, the hostname or IP address of the bmc
4440 @param args: contains additional arguments used by the logging sub command
4441 @param session: the active session to use
4442 """
4443
Matt Spinler7d426c22018-09-24 14:42:07 -05004444 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4445 try:
Justin Thaler27197622019-01-23 14:42:11 -06004446 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004447 except(requests.exceptions.Timeout):
4448 return(connectionErrHandler(args.json, "Timeout", None))
4449 usersDict = json.loads(res.text)
4450
4451 if not usersDict['data']:
4452 return "No users found"
4453
4454 output = ""
4455 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004456
4457 # Skip LDAP and another non-local users
4458 if 'UserEnabled' not in usersDict['data'][user]:
4459 continue
4460
Matt Spinler7d426c22018-09-24 14:42:07 -05004461 name = user.split('/')[-1]
4462 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4463
4464 if args.local_users == "queryenabled":
4465 try:
Justin Thaler27197622019-01-23 14:42:11 -06004466 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004467 except(requests.exceptions.Timeout):
4468 return(connectionErrHandler(args.json, "Timeout", None))
4469
4470 result = json.loads(res.text)
4471 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4472
4473 elif args.local_users in ["enableall", "disableall"]:
4474 action = ""
4475 if args.local_users == "enableall":
4476 data = '{"data": true}'
4477 action = "Enabling"
4478 else:
4479 data = '{"data": false}'
4480 action = "Disabling"
4481
4482 output += "{action} {name}\n".format(action=action, name=name)
4483
4484 try:
Justin Thaler27197622019-01-23 14:42:11 -06004485 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004486 except(requests.exceptions.Timeout):
4487 return connectionErrHandler(args.json, "Timeout", None)
4488 except(requests.exceptions.ConnectionError) as err:
4489 return connectionErrHandler(args.json, "ConnectionError", err)
4490 else:
4491 return "Invalid local users argument"
4492
4493 return output
4494
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004495def setPassword(host, args, session):
4496 """
4497 Set local user password
4498 @param host: string, the hostname or IP address of the bmc
4499 @param args: contains additional arguments used by the logging sub
4500 command
4501 @param session: the active session to use
4502 @param args.json: boolean, if this flag is set to true, the output
4503 will be provided in json format for programmatic consumption
4504 @return: Session object
4505 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004506 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004507 if(isRedfishSupport):
4508 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4509 args.user
4510 data = {"Password":args.password}
4511 res = session.patch(url, headers=jsonHeader, json=data,
4512 verify=False, timeout=baseTimeout)
4513 else:
4514 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4515 "/action/SetPassword"
4516 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004517 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004518 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004519 except(requests.exceptions.Timeout):
4520 return(connectionErrHandler(args.json, "Timeout", None))
4521 except(requests.exceptions.ConnectionError) as err:
4522 return connectionErrHandler(args.json, "ConnectionError", err)
4523 except(requests.exceptions.RequestException) as err:
4524 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004525 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004526
4527def getThermalZones(host, args, session):
4528 """
4529 Get the available thermal control zones
4530 @param host: string, the hostname or IP address of the bmc
4531 @param args: contains additional arguments used to get the thermal
4532 control zones
4533 @param session: the active session to use
4534 @return: Session object
4535 """
4536 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4537
4538 try:
4539 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4540 except(requests.exceptions.Timeout):
4541 return(connectionErrHandler(args.json, "Timeout", None))
4542 except(requests.exceptions.ConnectionError) as err:
4543 return connectionErrHandler(args.json, "ConnectionError", err)
4544 except(requests.exceptions.RequestException) as err:
4545 return connectionErrHandler(args.json, "RequestException", err)
4546
4547 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004548 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004549
4550 zonesDict = json.loads(res.text)
4551 if not zonesDict['data']:
4552 return "No thermal control zones found"
4553 for zone in zonesDict['data']:
4554 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4555
4556 return "Zones: [ " + z + " ]"
4557
4558
4559def getThermalMode(host, args, session):
4560 """
4561 Get thermal control mode
4562 @param host: string, the hostname or IP address of the bmc
4563 @param args: contains additional arguments used to get the thermal
4564 control mode
4565 @param session: the active session to use
4566 @param args.zone: the zone to get the mode on
4567 @return: Session object
4568 """
4569 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4570 args.zone
4571
4572 try:
4573 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4574 except(requests.exceptions.Timeout):
4575 return(connectionErrHandler(args.json, "Timeout", None))
4576 except(requests.exceptions.ConnectionError) as err:
4577 return connectionErrHandler(args.json, "ConnectionError", err)
4578 except(requests.exceptions.RequestException) as err:
4579 return connectionErrHandler(args.json, "RequestException", err)
4580
4581 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004582 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004583
4584 propsDict = json.loads(res.text)
4585 if not propsDict['data']:
4586 return "No thermal control properties found on zone(" + args.zone + ")"
4587 curMode = "Current"
4588 supModes = "Supported"
4589 result = "\n"
4590 for prop in propsDict['data']:
4591 if (prop.casefold() == curMode.casefold()):
4592 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4593 if (prop.casefold() == supModes.casefold()):
4594 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4595 result += supModes + " Modes: [ " + s + " ]\n"
4596
4597 return result
4598
4599def setThermalMode(host, args, session):
4600 """
4601 Set thermal control mode
4602 @param host: string, the hostname or IP address of the bmc
4603 @param args: contains additional arguments used for setting the thermal
4604 control mode
4605 @param session: the active session to use
4606 @param args.zone: the zone to set the mode on
4607 @param args.mode: the mode to enable
4608 @return: Session object
4609 """
4610 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4611 args.zone + "/attr/Current"
4612
4613 # Check args.mode against supported modes using `getThermalMode` output
4614 modes = getThermalMode(host, args, session)
4615 modes = os.linesep.join([m for m in modes.splitlines() if m])
4616 modes = modes.replace("\n", ";").strip()
4617 modesDict = dict(m.split(': ') for m in modes.split(';'))
4618 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4619 if args.mode.casefold() not in \
4620 (m.casefold() for m in sModes.split(',')) or not args.mode:
4621 result = ("Unsupported mode('" + args.mode + "') given, " +
4622 "select a supported mode: \n" +
4623 getThermalMode(host, args, session))
4624 return result
4625
4626 data = '{"data":"' + args.mode + '"}'
4627 try:
4628 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4629 except(requests.exceptions.Timeout):
4630 return(connectionErrHandler(args.json, "Timeout", None))
4631 except(requests.exceptions.ConnectionError) as err:
4632 return connectionErrHandler(args.json, "ConnectionError", err)
4633 except(requests.exceptions.RequestException) as err:
4634 return connectionErrHandler(args.json, "RequestException", err)
4635
4636 if (data and res.status_code != 404):
4637 try:
4638 res = session.put(url, headers=jsonHeader,
4639 data=data, verify=False,
4640 timeout=30)
4641 except(requests.exceptions.Timeout):
4642 return(connectionErrHandler(args.json, "Timeout", None))
4643 except(requests.exceptions.ConnectionError) as err:
4644 return connectionErrHandler(args.json, "ConnectionError", err)
4645 except(requests.exceptions.RequestException) as err:
4646 return connectionErrHandler(args.json, "RequestException", err)
4647
4648 if res.status_code == 403:
4649 return "The specified thermal control zone(" + args.zone + ")" + \
4650 " does not exist"
4651
4652 return res.text
4653 else:
4654 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004655 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004656
4657
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004658def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004659 """
4660 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004661
Justin Thalere412dc22018-01-12 16:28:24 -06004662 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004663 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004664 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004665 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4666 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004667 group = parser.add_mutually_exclusive_group()
4668 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4669 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004670 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004671 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4672 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4673 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4674 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004675 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4676 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004677
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004678 #fru command
4679 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004680 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 -05004681 inv_subparser.required = True
4682 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004683 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4684 inv_print.set_defaults(func=fruPrint)
4685 #fru list [0....n]
4686 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4687 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4688 inv_list.set_defaults(func=fruList)
4689 #fru status
4690 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004691 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004692 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004693
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004694 #sensors command
4695 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004696 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 -05004697 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004698 #sensor print
4699 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4700 sens_print.set_defaults(func=sensor)
4701 #sensor list[0...n]
4702 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4703 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4704 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004705
Matthew Barth368e83c2019-02-01 13:48:25 -06004706 #thermal control commands
4707 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4708 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')
4709 #thermal control zones
4710 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4711 parser_thermZones.set_defaults(func=getThermalZones)
4712 #thermal control modes
4713 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4714 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4715 #get thermal control mode
4716 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4717 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4718 parser_getThermMode.set_defaults(func=getThermalMode)
4719 #set thermal control mode
4720 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4721 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4722 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4723 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004724
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004725 #sel command
4726 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004727 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 -05004728 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004729 #sel print
4730 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4731 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4732 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4733 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4734 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004735
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004736 #sel list
4737 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")
4738 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4739 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004740
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004741 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4742 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4743 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004744
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004745 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4746 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004747
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004748 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004749 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4750 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4751 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4752 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004753 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004754
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004755 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004756 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004757
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004758 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4759 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004760
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004761 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 -06004762 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 -06004763 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004764
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004765 #control the chassis identify led
4766 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4767 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4768 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004769
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004770 #collect service data
4771 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4772 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4773 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004774
Justin Thalere412dc22018-01-12 16:28:24 -06004775 #system quick health check
4776 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4777 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004778
Ravi Tejad8be0b42020-03-18 14:31:46 -05004779 #work with dumps
4780 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4781 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004782 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004783 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004784 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4785 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004786
Ravi Tejad8be0b42020-03-18 14:31:46 -05004787 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4788 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004789
Ravi Tejad8be0b42020-03-18 14:31:46 -05004790 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004791 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004792 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004793
Justin Thalere412dc22018-01-12 16:28:24 -06004794 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004795 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4796 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004797
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004798 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004799 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4800 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4801 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004802
Justin Thaler22b1bb52018-03-15 13:31:32 -05004803 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004804 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004805 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004806 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4807 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 -06004808 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.")
4809 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004810
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004811 #add alias to the bmc command
4812 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004813 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004814 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4815 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4816 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4817 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 -06004818 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004819 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004820
Justin Thalere412dc22018-01-12 16:28:24 -06004821 #gard clear
4822 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4823 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004824
Justin Thalere412dc22018-01-12 16:28:24 -06004825 #firmware_flash
4826 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4827 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 -05004828 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004829
Justin Thalere412dc22018-01-12 16:28:24 -06004830 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4831 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4832 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4833 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004834
Justin Thaler22b1bb52018-03-15 13:31:32 -05004835 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004836 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4837 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004838
Justin Thaler22b1bb52018-03-15 13:31:32 -05004839 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4840 fwActivateStatus.set_defaults(func=activateStatus)
4841
Justin Thaler3d71d402018-07-24 14:35:39 -05004842 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4843 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4844 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004845
Justin Thaler3d71d402018-07-24 14:35:39 -05004846 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4847 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4848 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004849
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004850 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4851 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4852 fwDelete.set_defaults(func=deleteFWVersion)
4853
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004854 #logging
4855 parser_logging = subparsers.add_parser("logging", help="logging controls")
4856 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004857
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004858 #turn rest api logging on/off
4859 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4860 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4861 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004862
4863 #remote logging
4864 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4865 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4866 parser_remote_logging.set_defaults(func=remoteLogging)
4867
4868 #configure remote logging
4869 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4870 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4871 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4872 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004873
4874 #certificate management
4875 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4876 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4877
4878 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4879 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4880 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4881 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4882 certUpdate.set_defaults(func=certificateUpdate)
4883
4884 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4885 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4886 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4887 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004888
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004889 certReplace = certMgmt_subproc.add_parser('replace',
4890 help="Replace the certificate")
4891 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4892 help="certificate type to replace")
4893 certReplace.add_argument('service', choices=['https', 'ldap'],
4894 help="Service to replace the certificate")
4895 certReplace.add_argument('-f', '--fileloc', required=True,
4896 help="The absolute path to the certificate file")
4897 certReplace.set_defaults(func=certificateReplace)
4898
Marri Devender Rao34646402019-07-01 05:46:03 -05004899 certDisplay = certMgmt_subproc.add_parser('display',
4900 help="Print the certificate")
4901 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4902 help="certificate type to display")
4903 certDisplay.set_defaults(func=certificateDisplay)
4904
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004905 certList = certMgmt_subproc.add_parser('list',
4906 help="Certificate list")
4907 certList.set_defaults(func=certificateList)
4908
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004909 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4910 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4911 help="Generate CSR")
4912 certGenerateCSR.add_argument('city',
4913 help="The city or locality of the organization making the request")
4914 certGenerateCSR.add_argument('commonName',
4915 help="The fully qualified domain name of the component that is being secured.")
4916 certGenerateCSR.add_argument('country',
4917 help="The country of the organization making the request")
4918 certGenerateCSR.add_argument('organization',
4919 help="The name of the organization making the request.")
4920 certGenerateCSR.add_argument('organizationUnit',
4921 help="The name of the unit or division of the organization making the request.")
4922 certGenerateCSR.add_argument('state',
4923 help="The state, province, or region of the organization making the request.")
4924 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4925 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004926 certGenerateCSR.add_argument('keyCurveId',
4927 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4928 certGenerateCSR.add_argument('contactPerson',
4929 help="The name of the user making the request")
4930 certGenerateCSR.add_argument('email',
4931 help="The email address of the contact within the organization")
4932 certGenerateCSR.add_argument('alternativeNames',
4933 help="Additional hostnames of the component that is being secured")
4934 certGenerateCSR.add_argument('givenname',
4935 help="The given name of the user making the request")
4936 certGenerateCSR.add_argument('surname',
4937 help="The surname of the user making the request")
4938 certGenerateCSR.add_argument('unstructuredname',
4939 help="he unstructured name of the subject")
4940 certGenerateCSR.add_argument('initials',
4941 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004942 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4943
Matt Spinler7d426c22018-09-24 14:42:07 -05004944 # local users
4945 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4946 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4947 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4948 parser_users.set_defaults(func=localUsers)
4949
Ratan Gupta9166cd22018-10-01 18:09:40 +05304950 #LDAP
4951 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4952 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4953
4954 #configure and enable LDAP
4955 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4956 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4957 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4958 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4959 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4960 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4961 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004962 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304963 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004964 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4965 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4966 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304967
4968 # disable LDAP
4969 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4970 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004971 # view-config
4972 parser_ldap_config = \
4973 ldap_sub.add_parser("view-config", help="prints out a list of all \
4974 LDAPS's configured properties")
4975 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304976
Ratan Guptafeee6372018-10-17 23:25:51 +05304977 #create group privilege mapping
4978 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4979 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4980 help="sub-command help", dest='command')
4981
4982 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 -05004983 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4984 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304985 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004986 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 +05304987 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4988
4989 #list group privilege mapping
4990 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004991 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4992 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304993 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4994
4995 #delete group privilege mapping
4996 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004997 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4998 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304999 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
5000 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
5001
Sivas SRR78835272018-11-27 05:27:19 -06005002 #deleteAll group privilege mapping
5003 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005004 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5005 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06005006 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
5007
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06005008 # set local user password
5009 parser_set_password = subparsers.add_parser("set_password",
5010 help="Set password of local user")
5011 parser_set_password.add_argument( "-p", "--password", required=True,
5012 help="Password of local user")
5013 parser_set_password.set_defaults(func=setPassword)
5014
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005015 # network
5016 parser_nw = subparsers.add_parser("network", help="network controls")
5017 nw_sub = parser_nw.add_subparsers(title='subcommands',
5018 description='valid subcommands',
5019 help="sub-command help",
5020 dest='command')
5021
5022 # enable DHCP
5023 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
5024 help="enables the DHCP on given "
5025 "Interface")
5026 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005027 help="Name of the ethernet interface(it can"
5028 "be obtained by the "
5029 "command:network view-config)"
5030 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005031 parser_enable_dhcp.set_defaults(func=enableDHCP)
5032
5033 # disable DHCP
5034 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
5035 help="disables the DHCP on given "
5036 "Interface")
5037 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005038 help="Name of the ethernet interface(it can"
5039 "be obtained by the "
5040 "command:network view-config)"
5041 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005042 parser_disable_dhcp.set_defaults(func=disableDHCP)
5043
5044 # get HostName
5045 parser_gethostname = nw_sub.add_parser("getHostName",
5046 help="prints out HostName")
5047 parser_gethostname.set_defaults(func=getHostname)
5048
5049 # set HostName
5050 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
5051 parser_sethostname.add_argument("-H", "--HostName", required=True,
5052 help="A HostName for the BMC")
5053 parser_sethostname.set_defaults(func=setHostname)
5054
5055 # get domainname
5056 parser_getdomainname = nw_sub.add_parser("getDomainName",
5057 help="prints out DomainName of "
5058 "given Interface")
5059 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005060 help="Name of the ethernet interface(it "
5061 "can be obtained by the "
5062 "command:network view-config)"
5063 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005064 parser_getdomainname.set_defaults(func=getDomainName)
5065
5066 # set domainname
5067 parser_setdomainname = nw_sub.add_parser("setDomainName",
5068 help="sets DomainName of given "
5069 "Interface")
5070 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
5071 help="Ex: DomainName=Domain1,Domain2,...")
5072 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005073 help="Name of the ethernet interface(it "
5074 "can be obtained by the "
5075 "command:network view-config)"
5076 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005077 parser_setdomainname.set_defaults(func=setDomainName)
5078
5079 # get MACAddress
5080 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
5081 help="prints out MACAddress the "
5082 "given Interface")
5083 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005084 help="Name of the ethernet interface(it "
5085 "can be obtained by the "
5086 "command:network view-config)"
5087 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005088 parser_getmacaddress.set_defaults(func=getMACAddress)
5089
5090 # set MACAddress
5091 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
5092 help="sets MACAddress")
5093 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
5094 help="A MACAddress for the given "
5095 "Interface")
5096 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005097 help="Name of the ethernet interface(it can"
5098 "be obtained by the "
5099 "command:network view-config)"
5100 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005101 parser_setmacaddress.set_defaults(func=setMACAddress)
5102
5103 # get DefaultGW
5104 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
5105 help="prints out DefaultGateway "
5106 "the BMC")
5107 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
5108
5109 # set DefaultGW
5110 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
5111 help="sets DefaultGW")
5112 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
5113 help="A DefaultGateway for the BMC")
5114 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
5115
5116 # view network Config
5117 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
5118 "list of all network's configured "
5119 "properties")
5120 parser_ldap_config.set_defaults(func=viewNWConfig)
5121
5122 # get DNS
5123 parser_getDNS = nw_sub.add_parser("getDNS",
5124 help="prints out DNS servers on the "
5125 "given interface")
5126 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005127 help="Name of the ethernet interface(it can"
5128 "be obtained by the "
5129 "command:network view-config)"
5130 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005131 parser_getDNS.set_defaults(func=getDNS)
5132
5133 # set DNS
5134 parser_setDNS = nw_sub.add_parser("setDNS",
5135 help="sets DNS servers on the given "
5136 "interface")
5137 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5138 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5139 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005140 help="Name of the ethernet interface(it can"
5141 "be obtained by the "
5142 "command:network view-config)"
5143 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005144 parser_setDNS.set_defaults(func=setDNS)
5145
5146 # get NTP
5147 parser_getNTP = nw_sub.add_parser("getNTP",
5148 help="prints out NTP servers on the "
5149 "given interface")
5150 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005151 help="Name of the ethernet interface(it can"
5152 "be obtained by the "
5153 "command:network view-config)"
5154 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005155 parser_getNTP.set_defaults(func=getNTP)
5156
5157 # set NTP
5158 parser_setNTP = nw_sub.add_parser("setNTP",
5159 help="sets NTP servers on the given "
5160 "interface")
5161 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5162 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5163 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005164 help="Name of the ethernet interface(it can"
5165 "be obtained by the "
5166 "command:network view-config)"
5167 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005168 parser_setNTP.set_defaults(func=setNTP)
5169
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005170 # configure IP
5171 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5172 "given interface")
5173 parser_ip_config.add_argument("-a", "--address", required=True,
5174 help="IP address of given interface")
5175 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5176 help="The gateway for given interface")
5177 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5178 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005179 parser_ip_config.add_argument("-p", "--type", required=True,
5180 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005181 help="The protocol type of the given"
5182 "IP address")
5183 parser_ip_config.add_argument("-I", "--Interface", required=True,
5184 help="Name of the ethernet interface(it can"
5185 "be obtained by the "
5186 "command:network view-config)"
5187 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5188 parser_ip_config.set_defaults(func=addIP)
5189
5190 # getIP
5191 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5192 "of given interface")
5193 parser_getIP.add_argument("-I", "--Interface", required=True,
5194 help="Name of the ethernet interface(it can"
5195 "be obtained by the command:network view-config)"
5196 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5197 parser_getIP.set_defaults(func=getIP)
5198
5199 # rmIP
5200 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5201 "of given interface")
5202 parser_rmIP.add_argument("-a", "--address", required=True,
5203 help="IP address to remove form given Interface")
5204 parser_rmIP.add_argument("-I", "--Interface", required=True,
5205 help="Name of the ethernet interface(it can"
5206 "be obtained by the command:network view-config)"
5207 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5208 parser_rmIP.set_defaults(func=deleteIP)
5209
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005210 # add VLAN
5211 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5212 "on given interface with given "
5213 "VLAN Identifier")
5214 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5215 choices=['eth0', 'eth1'],
5216 help="Name of the ethernet interface")
5217 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5218 help="VLAN Identifier")
5219 parser_create_vlan.set_defaults(func=addVLAN)
5220
5221 # delete VLAN
5222 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5223 "on given interface with given "
5224 "VLAN Identifier")
5225 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5226 help="Name of the ethernet interface(it can"
5227 "be obtained by the "
5228 "command:network view-config)"
5229 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5230 parser_delete_vlan.set_defaults(func=deleteVLAN)
5231
5232 # viewDHCPConfig
5233 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5234 help="Shows DHCP configured "
5235 "Properties")
5236 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5237
5238 # configureDHCP
5239 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5240 help="Configures/updates DHCP "
5241 "Properties")
5242 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5243 required=True, help="Sets DNSEnabled property")
5244 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5245 required=True,
5246 help="Sets HostNameEnabled property")
5247 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5248 required=True,
5249 help="Sets NTPEnabled property")
5250 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5251 required=True,
5252 help="Sets SendHostNameEnabled property")
5253 parser_configDHCP.set_defaults(func=configureDHCP)
5254
5255 # network factory reset
5256 parser_nw_reset = nw_sub.add_parser("nwReset",
5257 help="Resets networks setting to "
5258 "factory defaults. "
5259 "note:Reset settings will be applied "
5260 "after BMC reboot")
5261 parser_nw_reset.set_defaults(func=nwReset)
5262
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005263 return parser
5264
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005265def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005266 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005267 main function for running the command line utility as a sub application
5268 """
5269 global toolVersion
Justin Thalerc42e4e52020-05-13 12:04:24 -05005270 toolVersion = "1.19"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005271 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005272
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005273 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005274 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005275
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005276 totTimeStart = int(round(time.time()*1000))
5277
5278 if(sys.version_info < (3,0)):
5279 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5280 if sys.version_info >= (3,0):
5281 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005282 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005283 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005284 sys.exit(0)
5285 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005286 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005287 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005288 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005289 if(hasattr(args, 'host') and hasattr(args,'user')):
5290 if (args.askpw):
5291 pw = getpass.getpass()
5292 elif(args.PW is not None):
5293 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005294 elif(args.PWenvvar):
5295 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005296 else:
5297 print("You must specify a password")
5298 sys.exit()
5299 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005300 mysess = login(args.host, args.user, pw, args.json,
5301 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005302 if(mysess == None):
5303 print("Login Failed!")
5304 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005305 if(sys.version_info < (3,0)):
5306 if isinstance(mysess, basestring):
5307 print(mysess)
5308 sys.exit(1)
5309 elif sys.version_info >= (3,0):
5310 if isinstance(mysess, str):
5311 print(mysess)
5312 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005313 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005314 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005315 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005316 output = args.func(args.host, args, mysess)
5317 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005318 if isinstance(output, dict):
5319 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5320 else:
5321 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005322 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005323 logout(args.host, args.user, pw, mysess, args.json)
5324 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005325 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5326 print("loginTime: " + str(logintimeStop - logintimeStart))
5327 print("command Time: " + str(commandTimeStop - commandTimeStart))
5328 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005329 print("usage:\n"
5330 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5331 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005332 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005333 "\t{fru,sensors,sel,chassis,collect_service_data, \
5334 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005335 "\t...\n" +
5336 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005337 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005338
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005339if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005340 """
5341 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005342
5343 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005344 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005345
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005346 isTTY = sys.stdout.isatty()
5347 assert sys.version_info >= (2,7)
5348 main()