blob: 00d3e6034fc8a2862dba0c2cb66ee05ecdd7d9e5 [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)
Ravi Tejabef8da42020-07-14 23:01:51 -050066
67 uri = "/redfish/v1/Systems/system/LogServices/Dump/attachment/"+args.dumpNum
68
69 self.conn.request("GET",uri, headers={"X-Auth-Token":token})
Ravi Tejad8be0b42020-03-18 14:31:46 -050070
71 def openTCPSocket(self):
72 # Create a TCP/IP socket
73 self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
74 # Connect the socket to the port where the server is listening
75 server_address = ('localhost', 1043)
76 self.tcp.connect(server_address)
77
78 def waitformessage(self):
79 inputs = [self.conn.sock,self.tcp]
80 outputs = []
81 message_queues = {}
82 while True:
83 readable, writable, exceptional = select.select(
84 inputs, outputs, inputs)
85
86 for s in readable:
87 if s is self.conn.sock:
88
89 data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
90 print("<<HTTP")
Ravi Tejad8be0b42020-03-18 14:31:46 -050091 if data:
92 self.tcp.send(data)
93 else:
94 print ("BMC Closed the connection")
95 self.conn.close()
96 self.tcp.close()
97 sys.exit(1)
98 elif s is self.tcp:
99 data = self.tcp.recv(MAX_NBD_PACKET_SIZE)
100 print(">>TCP")
Ravi Tejad8be0b42020-03-18 14:31:46 -0500101 if data:
102 self.conn.sock.send(data)
103 else:
104 print("NBD server closed the connection")
105 self.conn.sock.close()
106 self.tcp.close()
107 sys.exit(1)
108 for s in exceptional:
109 inputs.remove(s)
110 print("Exceptional closing the socket")
111 s.close()
112
113def getsize(host,args,session):
Ravi Tejabef8da42020-07-14 23:01:51 -0500114 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/Dump/Entries/"+str(args.dumpNum)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500115 try:
116 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
117 if resp.status_code==200:
Ravi Tejabef8da42020-07-14 23:01:51 -0500118 size = resp.json()["Oem"]["OpenBmc"]['AdditionalDataSizeBytes']
Ravi Tejad8be0b42020-03-18 14:31:46 -0500119 return size
120 else:
121 return "Failed get Size"
122 except(requests.exceptions.Timeout):
123 return connectionErrHandler(args.json, "Timeout", None)
124
125 except(requests.exceptions.ConnectionError) as err:
126 return connectionErrHandler(args.json, "ConnectionError", err)
127
128def gettoken(args):
129 mysess = requests.session()
130 resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
131 if resp.status_code == 200:
132 cookie = resp.headers['Set-Cookie']
133 match = re.search('SESSION=(\w+);', cookie)
134 return match.group(1)
135
136
137
138def get_pid(name):
139 try:
140 pid = map(int, check_output(["pidof", "-s",name]))
141 except Exception:
142 pid = 0
143
144 return pid
145
146def findThisProcess( process_name ):
147 ps = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
148 output = ps.stdout.read()
149 ps.stdout.close()
150 ps.wait()
151 pid = get_pid(process_name)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500152 return output
153
154def isThisProcessRunning( process_name ):
155 pid = get_pid(process_name)
156 if (pid == 0 ):
157 return False
158 else:
159 return True
160
161def NBDSetup(host,args,session):
162 user=os.getenv("SUDO_USER")
163 if user is None:
164 path = os.getcwd()
165 nbdServerPath = path + "/nbd-server"
Ravi Tejad8be0b42020-03-18 14:31:46 -0500166 if not os.path.exists(nbdServerPath):
167 print("Error: this program did not run as sudo!\nplease copy nbd-server to current directory and run script again")
168 exit()
169
170 if isThisProcessRunning('nbd-server') == True:
171 print("nbd-server already Running! killing the nbd-server")
172 os.system('killall nbd-server')
173
174 if (args.dumpSaveLoc is not None):
175 if(os.path.exists(args.dumpSaveLoc)):
176 print("Error: File already exists.")
177 exit()
178
179 fp= open(args.dumpSaveLoc,"w")
180 sizeInBytes = getsize(host,args,session)
181 #Round off size to mutiples of 1024
182 size = int(sizeInBytes)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500183 mod = size % 1024
184 if mod :
185 roundoff = 1024 - mod
186 size = size + roundoff
187
188 cmd = 'chmod 777 ' + args.dumpSaveLoc
189 os.system(cmd)
190
191 #Run truncate to create file with given size
192 cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
193 os.system(cmd)
194
195 if user is None:
196 cmd = './nbd-server 1043 '+ args.dumpSaveLoc
197 else:
198 cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
199 os.system(cmd)
200
201
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600202def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -0600203 """
204 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600205
Justin Thalere412dc22018-01-12 16:28:24 -0600206 @param textToColor: string, the text to be colored
207 @param color: string, used to color the text red or green
208 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600209 @return: Buffered reader containing the modified string.
210 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600211 if(sys.platform.__contains__("win")):
212 if(color == "red"):
213 os.system('color 04')
214 elif(color == "green"):
215 os.system('color 02')
216 else:
217 os.system('color') #reset to default
218 return textToColor
219 else:
220 attr = []
221 if(color == "red"):
222 attr.append('31')
223 elif(color == "green"):
224 attr.append('32')
225 else:
226 attr.append('0')
227 if bold:
228 attr.append('1')
229 else:
230 attr.append('0')
231 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
232
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600233def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -0600234 """
235 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600236
237 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -0600238 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600239 @param err: string, the text from the exception
240 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600241 if errorStr == "Timeout":
242 if not jsonFormat:
243 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
244 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500245 conerror = {}
246 conerror['CommonEventID'] = 'FQPSPIN0000M'
247 conerror['sensor']="N/A"
248 conerror['state']="N/A"
249 conerror['additionalDetails'] = "N/A"
250 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
251 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."
252 conerror['Serviceable']="Yes"
253 conerror['CallHomeCandidate']= "No"
254 conerror['Severity'] = "Critical"
255 conerror['EventType'] = "Communication Failure/Timeout"
256 conerror['VMMigrationFlag'] = "Yes"
257 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
258 conerror["timestamp"] = str(int(time.time()))
259 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
260 eventdict = {}
261 eventdict['event0'] = conerror
262 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500263 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600264 return(errorMessageStr)
265 elif errorStr == "ConnectionError":
266 if not jsonFormat:
267 return("FQPSPIN0001M: " + str(err))
268 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500269 conerror = {}
270 conerror['CommonEventID'] = 'FQPSPIN0001M'
271 conerror['sensor']="N/A"
272 conerror['state']="N/A"
273 conerror['additionalDetails'] = str(err)
274 conerror['Message']="Connection Error. View additional details for more information"
275 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
276 conerror['Serviceable']="Yes"
277 conerror['CallHomeCandidate']= "No"
278 conerror['Severity'] = "Critical"
279 conerror['EventType'] = "Communication Failure/Timeout"
280 conerror['VMMigrationFlag'] = "Yes"
281 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
282 conerror["timestamp"] = str(int(time.time()))
283 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
284 eventdict = {}
285 eventdict['event0'] = conerror
286 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500287 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600288 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500289
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600290 else:
291 return("Unknown Error: "+ str(err))
292
Justin Thalere412dc22018-01-12 16:28:24 -0600293
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600294def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600295 """
296 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600297
298 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600299 @param numcols: the total number of columns in the final output
300 @param dictForOutput: dictionary, contains the information to print to the screen
301 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600302 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600303 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600304 colWidths = []
305 for x in range(0, numCols):
306 colWidths.append(0)
307 for key in dictForOutput:
308 for x in range(0, numCols):
309 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600310
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600311 for x in range(0, numCols):
312 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600313
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600314 return colWidths
315
316def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600317 """
318 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600319
Justin Thalere412dc22018-01-12 16:28:24 -0600320 @param value: boolean, the value to convert
321 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600322 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600323 policyTable = {}
324 if(os.path.exists(pathToPolicyTable)):
325 with open(pathToPolicyTable, 'r') as stream:
326 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600327 contents =json.load(stream)
328 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600329 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600330 print(err)
331 return policyTable
332
Justin Thalere412dc22018-01-12 16:28:24 -0600333
334def boolToString(value):
335 """
336 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600337
Justin Thalere412dc22018-01-12 16:28:24 -0600338 @param value: boolean, the value to convert
339 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600340 """
Justin Thalere412dc22018-01-12 16:28:24 -0600341 if(value):
342 return "Yes"
343 else:
344 return "No"
345
Justin Thalera6b5df72018-07-16 11:10:07 -0500346def stringToInt(text):
347 """
348 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600349
Justin Thalera6b5df72018-07-16 11:10:07 -0500350 @param text: the string to try to convert to an integer
351 """
352 if text.isdigit():
353 return int(text)
354 else:
355 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600356
Justin Thalera6b5df72018-07-16 11:10:07 -0500357def naturalSort(text):
358 """
359 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600360
Justin Thalera6b5df72018-07-16 11:10:07 -0500361 @param text: the key to convert for sorting
362 @return list containing the broken up string parts by integers and strings
363 """
364 stringPartList = []
365 for c in re.split('(\d+)', text):
366 stringPartList.append(stringToInt(c))
367 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600368
Justin Thalere412dc22018-01-12 16:28:24 -0600369def tableDisplay(keylist, colNames, output):
370 """
371 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600372
Justin Thalere412dc22018-01-12 16:28:24 -0600373 @param keylist: list, keys for the output dictionary, ordered by colNames
374 @param colNames: Names for the Table of the columns
375 @param output: The dictionary of data to display
376 @return: Session object
377 """
378 colWidth = setColWidth(keylist, len(colNames), output, colNames)
379 row = ""
380 outputText = ""
381 for i in range(len(colNames)):
382 if (i != 0): row = row + "| "
383 row = row + colNames[i].ljust(colWidth[i])
384 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600385
Justin Thalera6b5df72018-07-16 11:10:07 -0500386 output_keys = list(output.keys())
387 output_keys.sort(key=naturalSort)
388 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600389 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500390 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600391 if (i != 0): row = row + "| "
392 row = row + output[key][keylist[i]].ljust(colWidth[i])
393 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600394
Justin Thalere412dc22018-01-12 16:28:24 -0600395 return outputText
396
Justin Thaler22b1bb52018-03-15 13:31:32 -0500397def checkFWactivation(host, args, session):
398 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600399 Checks the software inventory for an image that is being activated.
400
Justin Thaler22b1bb52018-03-15 13:31:32 -0500401 @return: True if an image is being activated, false is no activations are happening
402 """
403 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500404 try:
Justin Thaler27197622019-01-23 14:42:11 -0600405 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500406 except(requests.exceptions.Timeout):
407 print(connectionErrHandler(args.json, "Timeout", None))
408 return(True)
409 except(requests.exceptions.ConnectionError) as err:
410 print( connectionErrHandler(args.json, "ConnectionError", err))
411 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600412 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500413 for key in fwInfo:
414 if 'Activation' in fwInfo[key]:
415 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
416 return True
417 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600418
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500419def login(host, username, pw,jsonFormat, allowExpiredPassword):
Justin Thalere412dc22018-01-12 16:28:24 -0600420 """
421 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600422
Justin Thalere412dc22018-01-12 16:28:24 -0600423 @param host: string, the hostname or IP address of the bmc to log into
424 @param username: The user name for the bmc to log into
425 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600426 @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 -0500427 @param allowExpiredPassword: true, if the requested operation should
428 be allowed when the password is expired
Justin Thalere412dc22018-01-12 16:28:24 -0600429 @return: Session object
430 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600431 if(jsonFormat==False):
432 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600433 mysess = requests.session()
434 try:
Justin Thaler27197622019-01-23 14:42:11 -0600435 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Sunitha Harish336cda22019-07-23 02:02:52 -0500436 if r.status_code == 200:
437 cookie = r.headers['Set-Cookie']
438 match = re.search('SESSION=(\w+);', cookie)
439 if match:
440 xAuthHeader['X-Auth-Token'] = match.group(1)
441 jsonHeader.update(xAuthHeader)
442 loginMessage = json.loads(r.text)
443 if (loginMessage['status'] != "ok"):
444 print(loginMessage["data"]["description"].encode('utf-8'))
445 sys.exit(1)
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500446 if (('extendedMessage' in r.json()) and
447 ('The password for this account must be changed' in r.json()['extendedMessage'])):
448 if not allowExpiredPassword:
449 print("The password for this system has expired and must be changed"+
450 "\nsee openbmctool.py set_password --help")
451 logout(host, username, pw, mysess, jsonFormat)
452 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600453# if(sys.version_info < (3,0)):
454# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
455# if sys.version_info >= (3,0):
456# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Sunitha Harish336cda22019-07-23 02:02:52 -0500457 return mysess
458 else:
459 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600460 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500461 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600462 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500463 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600464
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600465
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600466def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600467 """
468 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600469
Justin Thalere412dc22018-01-12 16:28:24 -0600470 @param host: string, the hostname or IP address of the bmc to log out of
471 @param username: The user name for the bmc to log out of
472 @param pw: The password for the BMC to log out of
473 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600474 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
475 """
Justin Thalere412dc22018-01-12 16:28:24 -0600476 try:
Justin Thaler27197622019-01-23 14:42:11 -0600477 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600478 except(requests.exceptions.Timeout):
479 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600480
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600481 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600482 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600483 print('User ' +username + ' has been logged out')
484
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600485
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600486def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600487 """
488 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600489
Justin Thalere412dc22018-01-12 16:28:24 -0600490 @param host: string, the hostname or IP address of the bmc
491 @param args: contains additional arguments used by the fru sub command
492 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600493 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
494 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600495 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600496
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600497 #print(url)
498 #res = session.get(url, headers=httpHeader, verify=False)
499 #print(res.text)
500 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600501
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600502 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600503
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600504 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600505 try:
Justin Thaler27197622019-01-23 14:42:11 -0600506 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600507 except(requests.exceptions.Timeout):
508 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600509
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600510 sample = res.text
511# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600512#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600513# #determine column width's
514# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
515# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600516#
517# 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 -0600518# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
519# format the output
520# for key in sorted(inv_list.keys()):
521# keyParts = key.split("/")
522# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600523#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600524# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
525# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
526# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
527# if(isTTY):
528# if(inv_list[key]["is_fru"] == 1):
529# color = "green"
530# bold = True
531# else:
532# color='black'
533# bold = False
534# fruEntry = hilight(fruEntry, color, bold)
535# print (fruEntry)
536 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600537
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600538def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600539 """
540 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600541
Justin Thalere412dc22018-01-12 16:28:24 -0600542 @param host: string, the hostname or IP address of the bmc
543 @param args: contains additional arguments used by the fru sub command
544 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600545 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
546 @return returns the total fru list.
547 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600548 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600549 try:
Justin Thaler27197622019-01-23 14:42:11 -0600550 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600551 except(requests.exceptions.Timeout):
552 return(connectionErrHandler(args.json, "Timeout", None))
553
Justin Thaler3a5771b2019-01-23 14:31:52 -0600554 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600555# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600556 if res.status_code==200:
557 frulist['Hardware'] = res.json()['data']
558 else:
559 if not args.json:
560 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
561 else:
562 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600563 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600564 try:
Justin Thaler27197622019-01-23 14:42:11 -0600565 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600566 except(requests.exceptions.Timeout):
567 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600568# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600569 if res.status_code==200:
570 frulist['Software'] = res.json()['data']
571 else:
572 if not args.json():
573 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
574 else:
575 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600576 return frulist
577
Justin Thalere412dc22018-01-12 16:28:24 -0600578
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600579def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600580 """
581 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600582
Justin Thalere412dc22018-01-12 16:28:24 -0600583 @param host: string, the hostname or IP address of the bmc
584 @param args: contains additional arguments used by the fru sub command
585 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600586 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
587 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600588 if(args.items==True):
589 return fruPrint(host, args, session)
590 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600591 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600592
593
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600594
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600595def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600596 """
597 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600598
Justin Thalere412dc22018-01-12 16:28:24 -0600599 @param host: string, the hostname or IP address of the bmc
600 @param args: contains additional arguments used by the fru sub command
601 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600602 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
603 """
Justin Thalere412dc22018-01-12 16:28:24 -0600604 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600605 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600606 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600607 except(requests.exceptions.Timeout):
608 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600609# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600610 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600611 frus = {}
612 for key in frulist:
613 component = frulist[key]
614 isFru = False
615 present = False
616 func = False
617 hasSels = False
618 keyPieces = key.split('/')
619 fruName = keyPieces[-1]
620 if 'core' in fruName: #associate cores to cpus
621 fruName = keyPieces[-2] + '-' + keyPieces[-1]
622 if 'Functional' in component:
623 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600624 if 'FieldReplaceable' in component:
625 if component['FieldReplaceable'] == 1:
626 isFru = True
627 if "fan" in fruName:
628 isFru = True;
629 if component['Present'] == 1:
630 present = True
631 if component['Functional'] == 1:
632 func = True
633 if ((key + "/fault") in frulist):
634 hasSels = True;
635 if args.verbose:
636 if hasSels:
637 loglist = []
638 faults = frulist[key+"/fault"]['endpoints']
639 for item in faults:
640 loglist.append(item.split('/')[-1])
641 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
642 else:
643 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
644 else:
645 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500646 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600647 if component['Present'] ==1:
648 present = True
649 isFru = True
650 if ((key + "/fault") in frulist):
651 hasSels = True;
652 if args.verbose:
653 if hasSels:
654 loglist = []
655 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100656 for item in faults:
657 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600658 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
659 else:
660 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
661 else:
662 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
663 if not args.json:
664 if not args.verbose:
665 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
666 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
667 else:
668 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
669 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
670 return tableDisplay(keylist, colNames, frus)
671 else:
672 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600673
Justin Thalere412dc22018-01-12 16:28:24 -0600674def sensor(host, args, session):
675 """
676 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600677
Justin Thalere412dc22018-01-12 16:28:24 -0600678 @param host: string, the hostname or IP address of the bmc
679 @param args: contains additional arguments used by the sensor sub command
680 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600681 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
682 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600683 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600684 try:
Justin Thaler27197622019-01-23 14:42:11 -0600685 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600686 except(requests.exceptions.Timeout):
687 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600688
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600689 #Get OCC status
690 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600691 try:
Justin Thaler27197622019-01-23 14:42:11 -0600692 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600693 except(requests.exceptions.Timeout):
694 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600695 if not args.json:
696 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600697 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600698 output = {}
699 for key in sensors:
700 senDict = {}
701 keyparts = key.split("/")
Matt Spinler596ef742019-09-20 08:54:36 -0500702
703 # Associations like the following also show up here:
704 # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
705 # Skip them.
706 # Note: keyparts[0] = '' which is why there are 7 segments.
707 if len(keyparts) > 6:
708 continue
709
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600710 senDict['sensorName'] = keyparts[-1]
711 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600712 try:
713 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
714 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500715 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600716 if('Scale' in sensors[key]):
717 scale = 10 ** sensors[key]['Scale']
718 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600719 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500720 try:
721 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600722 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500723 if 'value' in sensors[key]:
724 senDict['value'] = sensors[key]['value']
725 else:
726 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600727 if 'Target' in sensors[key]:
728 senDict['target'] = str(sensors[key]['Target'])
729 else:
730 senDict['target'] = 'N/A'
731 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600732
Justin Thaler3a5771b2019-01-23 14:31:52 -0600733 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600734 if '/org/open_power/control/occ0' in occstatus:
735 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600736 if occ0 == 1:
737 occ0 = 'Active'
738 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600739 occ0 = 'Inactive'
740 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
741 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600742 if occ1 == 1:
743 occ1 = 'Active'
744 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600745 occ1 = 'Inactive'
746 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
747 else:
748 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
749 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
750 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600751
752 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600753 else:
754 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600755
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600756def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600757 """
758 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600759
Justin Thalere412dc22018-01-12 16:28:24 -0600760 @param host: string, the hostname or IP address of the bmc
761 @param args: contains additional arguments used by the sel sub command
762 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600763 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
764 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600765
766 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600767 try:
Justin Thaler27197622019-01-23 14:42:11 -0600768 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600769 except(requests.exceptions.Timeout):
770 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600771 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600772
773
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600774def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600775 """
776 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600777
Justin Thalere412dc22018-01-12 16:28:24 -0600778 @param eselRAW: string, the raw esel string from the bmc
779 @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 -0600780 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600781 eselParts = {}
782 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
783 #search terms contains the search term as the key and the return dictionary key as it's value
784 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500785 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600786 uniqueID = str(uuid.uuid4())
787 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500788 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600789 f.write(esel_bin)
790 errlPath = ""
791 #use the right errl file for the machine architecture
792 arch = platform.machine()
793 if(arch =='x86_64' or arch =='AMD64'):
794 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
795 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
796 elif os.path.exists('errl/x86_64/errl'):
797 errlPath = 'errl/x86_64/errl'
798 else:
799 errlPath = 'x86_64/errl'
800 elif (platform.machine()=='ppc64le'):
801 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
802 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
803 elif os.path.exists('errl/ppc64le/errl'):
804 errlPath = 'errl/ppc64le/errl'
805 else:
806 errlPath = 'ppc64le/errl'
807 else:
808 print("machine architecture not supported for parsing eSELs")
809 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600810
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600811 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500812 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600813# output = proc.communicate()[0]
814 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600815
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600816 if(hasattr(args, 'fullEsel')):
817 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600818
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600819 for i in range(0, len(lines)):
820 lineParts = lines[i].split(':')
821 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
822 for term in searchTerms:
823 if(term in lineParts[0]):
824 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
825 if lines[i+1].find(':') != -1:
826 if (len(lines[i+1].split(':')[0][1:].strip())==0):
827 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600828 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600829 if((i+1) <= len(lines)):
830 i+=1
831 else:
832 i=i-1
833 break
Justin Thaler43030422018-11-08 22:50:21 -0600834 #Append the content from the next line removing the pretty display characters
835 #Finds the first colon then starts 2 characters after, then removes all whitespace
836 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500837 if(searchTerms[term] in eselParts):
838 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
839 else:
840 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500841 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600842 else:
843 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600844
845 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600846
Justin Thalere412dc22018-01-12 16:28:24 -0600847
Matt Spinler02d0dff2018-08-29 13:19:25 -0500848def getESELSeverity(esel):
849 """
850 Finds the severity type in an eSEL from the User Header section.
851 @param esel - the eSEL data
852 @return severity - e.g. 'Critical'
853 """
854
855 # everything but 1 and 2 are Critical
856 # '1': 'recovered',
857 # '2': 'predictive',
858 # '4': 'unrecoverable',
859 # '5': 'critical',
860 # '6': 'diagnostic',
861 # '7': 'symptom'
862 severities = {
863 '1': 'Informational',
864 '2': 'Warning'
865 }
866
867 try:
868 headerPosition = esel.index('55 48') # 'UH'
869 # The severity is the last byte in the 8 byte section (a byte is ' bb')
870 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
871 type = severity[0]
872 except ValueError:
873 print("Could not find severity value in UH section in eSEL")
874 type = 'x';
875
876 return severities.get(type, 'Critical')
877
878
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600879def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600880 """
881 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600882
Justin Thalere412dc22018-01-12 16:28:24 -0600883 @param events: Dictionary containing events
884 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600885 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600886 logNumList = []
887 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600888 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600889 eventsWithTimestamp = {}
890 logNum2events = {}
891 for key in events:
892 if key == 'numAlerts': continue
893 if 'callout' in key: continue
894 timestamp = (events[key]['timestamp'])
895 if timestamp not in timestampList:
896 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
897 else:
898 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
899 #map logNumbers to the event dictionary keys
900 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600901
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600902 timestampList = list(eventsWithTimestamp.keys())
903 timestampList.sort()
904 for ts in timestampList:
905 if len(eventsWithTimestamp[ts]) > 1:
906 tmplist = eventsWithTimestamp[ts]
907 tmplist.sort()
908 logNumList = logNumList + tmplist
909 else:
910 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600911
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600912 return [logNumList, eventKeyDict]
913
Justin Thalere412dc22018-01-12 16:28:24 -0600914
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600915def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600916 """
917 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600918
Justin Thalere412dc22018-01-12 16:28:24 -0600919 @param policyTable: dictionary, the policy table entries
920 @param selEntries: dictionary, the alerts retrieved from the bmc
921 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600922 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600923 eventDict = {}
924 eventNum =""
925 count = 0
926 esel = ""
927 eselParts = {}
928 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500929 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600930
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600931 'prepare and sort the event entries'
Justin Thaler667f87c2020-04-06 16:13:12 -0500932 sels = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600933 for key in selEntries:
Justin Thaler667f87c2020-04-06 16:13:12 -0500934 if '/xyz/openbmc_project/logging/entry/' not in key: continue
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600935 if 'callout' not in key:
Justin Thaler667f87c2020-04-06 16:13:12 -0500936 sels[key] = selEntries[key]
937 sels[key]['logNum'] = key.split('/')[-1]
938 sels[key]['timestamp'] = selEntries[key]['Timestamp']
939 sortedEntries = sortSELs(sels)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600940 logNumList = sortedEntries[0]
941 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600942
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600943 for logNum in logNumList:
944 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600945 hasEsel=False
946 i2creadFail = False
947 if 'callout' in key:
948 continue
949 else:
950 messageID = str(selEntries[key]['Message'])
951 addDataPiece = selEntries[key]['AdditionalData']
952 calloutIndex = 0
953 calloutFound = False
954 for i in range(len(addDataPiece)):
955 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
956 calloutIndex = i
957 calloutFound = True
958 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
959 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
960 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500961
962 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
963
964 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
965 if (messageID + '||' + fruCallout) not in policyTable:
966 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
967 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
968 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
969 fruCallout = 'FSI'
970 else:
971 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500972 calloutFound = True
973 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
974 if not calloutFound:
975 fruCallout = 'GPIO'
976 calloutFound = True
977 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
978 if not calloutFound:
979 fruCallout = "I2C"
980 calloutFound = True
981 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
982 if not calloutFound:
983 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600984 calloutFound = True
985 if("ESEL" in addDataPiece[i]):
986 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500987 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600988 if args.devdebug:
989 eselParts = parseESEL(args, esel)
990 hasEsel=True
991 if("GPU" in addDataPiece[i]):
992 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
993 calloutFound = True
994 if("PROCEDURE" in addDataPiece[i]):
995 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
996 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600997 if("RAIL_NAME" in addDataPiece[i]):
998 calloutFound=True
999 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1000 if("INPUT_NAME" in addDataPiece[i]):
1001 calloutFound=True
1002 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1003 if("SENSOR_TYPE" in addDataPiece[i]):
1004 calloutFound=True
1005 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001006
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001007 if(calloutFound):
Justin Thaler667f87c2020-04-06 16:13:12 -05001008 if fruCallout.strip() != "":
Justin Thaler22b1bb52018-03-15 13:31:32 -05001009 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -05001010
1011 # Also use the severity for hostboot errors
1012 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
1013 policyKey += '||' + eselSeverity
1014
1015 # if not in the table, fall back to the original key
1016 if policyKey not in policyTable:
1017 policyKey = policyKey.replace('||'+eselSeverity, '')
1018
Justin Thalere34c43a2018-05-25 19:37:55 -05001019 if policyKey not in policyTable:
1020 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -05001021 else:
1022 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001023 else:
1024 policyKey = messageID
1025 event = {}
1026 eventNum = str(count)
1027 if policyKey in policyTable:
1028 for pkey in policyTable[policyKey]:
1029 if(type(policyTable[policyKey][pkey])== bool):
1030 event[pkey] = boolToString(policyTable[policyKey][pkey])
1031 else:
1032 if (i2creadFail and pkey == 'Message'):
1033 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
1034 else:
1035 event[pkey] = policyTable[policyKey][pkey]
1036 event['timestamp'] = selEntries[key]['Timestamp']
1037 event['resolved'] = bool(selEntries[key]['Resolved'])
1038 if(hasEsel):
1039 if args.devdebug:
1040 event['eselParts'] = eselParts
1041 event['raweSEL'] = esel
1042 event['logNum'] = key.split('/')[-1]
1043 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001044
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001045 else:
1046 severity = str(selEntries[key]['Severity']).split('.')[-1]
1047 if severity == 'Error':
1048 severity = 'Critical'
1049 eventDict['event'+eventNum] = {}
1050 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
1051 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
1052 eventDict['event' + eventNum]['Severity'] = severity
1053 if(hasEsel):
1054 if args.devdebug:
1055 eventDict['event' +eventNum]['eselParts'] = eselParts
1056 eventDict['event' +eventNum]['raweSEL'] = esel
1057 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
1058 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001059 count += 1
1060 return eventDict
1061
1062
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001063def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -06001064 """
1065 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001066
Justin Thalere412dc22018-01-12 16:28:24 -06001067 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001068 @return:
1069 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001070 activeAlerts = []
1071 historyAlerts = []
1072 sortedEntries = sortSELs(events)
1073 logNumList = sortedEntries[0]
1074 eventKeyDict = sortedEntries[1]
1075 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
1076 if(args.devdebug):
1077 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
1078 keylist.append('eSEL')
1079 else:
1080 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
1081 for log in logNumList:
1082 selDict = {}
1083 alert = events[eventKeyDict[str(log)]]
1084 if('error' in alert):
1085 selDict['Entry'] = alert['logNum']
1086 selDict['ID'] = 'Unknown'
1087 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1088 msg = alert['error']
1089 polMsg = msg.split("policy table:")[0]
1090 msg = msg.split("policy table:")[1]
1091 msgPieces = msg.split("||")
1092 err = msgPieces[0]
1093 if(err.find("org.open_power.")!=-1):
1094 err = err.split("org.open_power.")[1]
1095 elif(err.find("xyz.openbmc_project.")!=-1):
1096 err = err.split("xyz.openbmc_project.")[1]
1097 else:
1098 err = msgPieces[0]
1099 callout = ""
1100 if len(msgPieces) >1:
1101 callout = msgPieces[1]
1102 if(callout.find("/org/open_power/")!=-1):
1103 callout = callout.split("/org/open_power/")[1]
1104 elif(callout.find("/xyz/openbmc_project/")!=-1):
1105 callout = callout.split("/xyz/openbmc_project/")[1]
1106 else:
1107 callout = msgPieces[1]
1108 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001109 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001110 selDict['Severity'] = alert['Severity']
1111 else:
1112 selDict['Entry'] = alert['logNum']
1113 selDict['ID'] = alert['CommonEventID']
1114 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001115 selDict['Message'] = alert['Message']
1116 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001117 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001118
1119
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001120 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
1121 if ('eselParts' in alert and args.devdebug):
1122 eselOutput = ""
1123 for item in eselOrder:
1124 if item in alert['eselParts']:
1125 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
1126 selDict['eSEL'] = eselOutput
1127 else:
1128 if args.devdebug:
1129 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001130
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001131 if not alert['resolved']:
1132 activeAlerts.append(selDict)
1133 else:
1134 historyAlerts.append(selDict)
1135 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001136 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
1137
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001138 output = ""
1139 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001140 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001141 output +="----Active Alerts----\n"
1142 for i in range(0, len(colNames)):
1143 if i!=0: row =row + "| "
1144 row = row + colNames[i].ljust(colWidth[i])
1145 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001146
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001147 for i in range(0,len(activeAlerts)):
1148 row = ""
1149 for j in range(len(activeAlerts[i])):
1150 if (j != 0): row = row + "| "
1151 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
1152 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001153
1154 if(len(historyAlerts)>0):
1155 row = ""
1156 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001157 for i in range(len(colNames)):
1158 if i!=0: row =row + "| "
1159 row = row + colNames[i].ljust(colWidth[i])
1160 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001161
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001162 for i in range(0, len(historyAlerts)):
1163 row = ""
1164 for j in range(len(historyAlerts[i])):
1165 if (j != 0): row = row + "| "
1166 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
1167 output += row + "\n"
1168# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001169 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001170
Justin Thalere412dc22018-01-12 16:28:24 -06001171
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001172def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001173 """
1174 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001175
Justin Thalere412dc22018-01-12 16:28:24 -06001176 @param host: string, the hostname or IP address of the bmc
1177 @param args: contains additional arguments used by the fru sub command
1178 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001179 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1180 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001181 if(args.policyTableLoc is None):
1182 if os.path.exists('policyTable.json'):
1183 ptableLoc = "policyTable.json"
1184 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1185 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1186 else:
1187 ptableLoc = 'lib/policyTable.json'
1188 else:
1189 ptableLoc = args.policyTableLoc
1190 policyTable = loadPolicyTable(ptableLoc)
1191 rawselEntries = ""
1192 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1193 if os.path.exists(args.fileloc):
1194 with open(args.fileloc, 'r') as selFile:
1195 selLines = selFile.readlines()
1196 rawselEntries = ''.join(selLines)
1197 else:
1198 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001199 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001200 else:
1201 rawselEntries = sel(host, args, session)
1202 loadFailed = False
1203 try:
1204 selEntries = json.loads(rawselEntries)
1205 except ValueError:
1206 loadFailed = True
1207 if loadFailed:
1208 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1209 #need to load json twice as original content was string escaped a second time
1210 selEntries = json.loads(json.loads(cleanSels))
1211 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001212
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001213 if 'description' in selEntries:
1214 if(args.json):
1215 return("{\n\t\"numAlerts\": 0\n}")
1216 else:
1217 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001218
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001219 else:
1220 if(len(policyTable)>0):
1221 events = parseAlerts(policyTable, selEntries, args)
1222 if(args.json):
1223 events["numAlerts"] = len(events)
1224 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1225 return retValue
1226 elif(hasattr(args, 'fullSel')):
1227 return events
1228 else:
1229 #get log numbers to order event entries sequentially
1230 return selDisplay(events, args)
1231 else:
1232 if(args.json):
1233 return selEntries
1234 else:
1235 print("error: Policy Table not found.")
1236 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001237
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001238def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001239 """
1240 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001241
Justin Thalere412dc22018-01-12 16:28:24 -06001242 @param host: string, the hostname or IP address of the bmc
1243 @param args: contains additional arguments used by the fru sub command
1244 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001245 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1246 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001247 return(sel(host, args, session))
1248
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001249
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001250def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001251 """
1252 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001253
Justin Thalere412dc22018-01-12 16:28:24 -06001254 @param host: string, the hostname or IP address of the bmc
1255 @param args: contains additional arguments used by the fru sub command
1256 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001257 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1258 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001259 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001260 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001261
Justin Thalere412dc22018-01-12 16:28:24 -06001262 try:
Justin Thaler27197622019-01-23 14:42:11 -06001263 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001264 except(requests.exceptions.Timeout):
1265 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001266 if res.status_code == 200:
1267 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1268 else:
1269 print("Unable to clear the logs, trying to clear 1 at a time")
1270 sels = json.loads(sel(host, args, session))['data']
1271 for key in sels:
1272 if 'callout' not in key:
1273 logNum = key.split('/')[-1]
1274 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1275 try:
Justin Thaler27197622019-01-23 14:42:11 -06001276 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001277 except(requests.exceptions.Timeout):
1278 return connectionErrHandler(args.json, "Timeout", None)
1279 sys.exit(1)
1280 except(requests.exceptions.ConnectionError) as err:
1281 return connectionErrHandler(args.json, "ConnectionError", err)
1282 sys.exit(1)
1283 return ('Sel clearing complete')
1284
1285def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001286 """
1287 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001288
Justin Thalere412dc22018-01-12 16:28:24 -06001289 @param host: string, the hostname or IP address of the bmc
1290 @param args: contains additional arguments used by the fru sub command
1291 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001292 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1293 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001294 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001295 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001296 try:
Justin Thaler27197622019-01-23 14:42:11 -06001297 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001298 except(requests.exceptions.Timeout):
1299 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001300 if res.status_code == 200:
1301 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1302 else:
1303 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001304
Justin Thalere412dc22018-01-12 16:28:24 -06001305def selResolveAll(host, args, session):
1306 """
1307 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001308
Justin Thalere412dc22018-01-12 16:28:24 -06001309 @param host: string, the hostname or IP address of the bmc
1310 @param args: contains additional arguments used by the fru sub command
1311 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001312 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1313 """
Justin Thalere412dc22018-01-12 16:28:24 -06001314 rawselEntries = sel(host, args, session)
1315 loadFailed = False
1316 try:
1317 selEntries = json.loads(rawselEntries)
1318 except ValueError:
1319 loadFailed = True
1320 if loadFailed:
1321 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1322 #need to load json twice as original content was string escaped a second time
1323 selEntries = json.loads(json.loads(cleanSels))
1324 selEntries = selEntries['data']
1325
1326 if 'description' in selEntries:
1327 if(args.json):
1328 return("{\n\t\"selsResolved\": 0\n}")
1329 else:
1330 return("No log entries found")
1331 else:
1332 d = vars(args)
1333 successlist = []
1334 failedlist = []
1335 for key in selEntries:
1336 if 'callout' not in key:
1337 d['selNum'] = key.split('/')[-1]
1338 resolved = selSetResolved(host,args,session)
1339 if 'Sel entry' in resolved:
1340 successlist.append(d['selNum'])
1341 else:
1342 failedlist.append(d['selNum'])
1343 output = ""
1344 successlist.sort()
1345 failedlist.sort()
1346 if len(successlist)>0:
1347 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1348 if len(failedlist)>0:
1349 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1350 return output
1351
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001352def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001353 """
1354 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001355
Justin Thalere412dc22018-01-12 16:28:24 -06001356 @param host: string, the hostname or IP address of the bmc
1357 @param args: contains additional arguments used by the fru sub command
1358 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001359 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1360 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001361 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001362 if checkFWactivation(host, args, session):
1363 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001364 print("Attempting to Power on...:")
1365 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001366 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001367 try:
Justin Thaler27197622019-01-23 14:42:11 -06001368 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001369 except(requests.exceptions.Timeout):
1370 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001371 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001372 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001373 if checkFWactivation(host, args, session):
1374 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001375 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001376 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001377 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001378 try:
Justin Thaler27197622019-01-23 14:42:11 -06001379 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001380 except(requests.exceptions.Timeout):
1381 return(connectionErrHandler(args.json, "Timeout", None))
1382 return res.text
1383 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001384 if checkFWactivation(host, args, session):
1385 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001386 print("Attempting to Power off immediately...:")
1387 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001388 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1389 try:
Justin Thaler27197622019-01-23 14:42:11 -06001390 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001391 except(requests.exceptions.Timeout):
1392 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001393 return res.text
1394 elif(args.powcmd == 'status'):
1395 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001396 try:
Justin Thaler27197622019-01-23 14:42:11 -06001397 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001398 except(requests.exceptions.Timeout):
1399 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001400 chassisState = json.loads(res.text)['data'].split('.')[-1]
1401 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001402 try:
Justin Thaler27197622019-01-23 14:42:11 -06001403 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001404 except(requests.exceptions.Timeout):
1405 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001406 hostState = json.loads(res.text)['data'].split('.')[-1]
1407 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001408 try:
Justin Thaler27197622019-01-23 14:42:11 -06001409 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001410 except(requests.exceptions.Timeout):
1411 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001412 bmcState = json.loads(res.text)['data'].split('.')[-1]
1413 if(args.json):
1414 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1415 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1416 else:
1417 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1418 else:
1419 return "Invalid chassis power command"
1420
Justin Thalere412dc22018-01-12 16:28:24 -06001421
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001422def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001423 """
1424 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001425
Justin Thalere412dc22018-01-12 16:28:24 -06001426 @param host: string, the hostname or IP address of the bmc
1427 @param args: contains additional arguments used by the fru sub command
1428 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001429 @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 -06001430 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001431 if(args.identcmd == 'on'):
1432 print("Attempting to turn identify light on...:")
1433 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001434 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001435 try:
Justin Thaler27197622019-01-23 14:42:11 -06001436 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001437 except(requests.exceptions.Timeout):
1438 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001439 return res.text
1440 elif(args.identcmd == 'off'):
1441 print("Attempting to turn identify light off...:")
1442 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001443 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001444 try:
Justin Thaler27197622019-01-23 14:42:11 -06001445 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001446 except(requests.exceptions.Timeout):
1447 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001448 return res.text
1449 elif(args.identcmd == 'status'):
1450 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001451 try:
Justin Thaler27197622019-01-23 14:42:11 -06001452 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001453 except(requests.exceptions.Timeout):
1454 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001455 status = json.loads(res.text)['data']
1456 if(args.json):
1457 return status
1458 else:
1459 if status['Asserted'] == 0:
1460 return "Identify light is off"
1461 else:
1462 return "Identify light is blinking"
1463 else:
1464 return "Invalid chassis identify command"
1465
Justin Thalere412dc22018-01-12 16:28:24 -06001466
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001467def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001468 """
1469 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001470
Justin Thalere412dc22018-01-12 16:28:24 -06001471 @param host: string, the hostname or IP address of the bmc
1472 @param args: contains additional arguments used by the fru sub command
1473 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001474 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1475 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001476 if(hasattr(args, 'powcmd')):
1477 result = chassisPower(host,args,session)
1478 elif(hasattr(args, 'identcmd')):
1479 result = chassisIdent(host, args, session)
1480 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001481 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001482 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001483
Ravi Tejad8be0b42020-03-18 14:31:46 -05001484def dumpRetrieve(host, args, session):
1485 """
1486 Downloads dump of given dump type
1487
1488 @param host: string, the hostname or IP address of the bmc
1489 @param args: contains additional arguments used by the collectServiceData sub command
1490 @param session: the active session to use
1491 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1492 """
1493 dumpType = args.dumpType
1494 if (args.dumpType=="SystemDump"):
1495 dumpResp=systemDumpRetrieve(host,args,session)
1496 elif(args.dumpType=="bmc"):
1497 dumpResp=bmcDumpRetrieve(host,args,session)
1498 return dumpResp
1499
1500def dumpList(host, args, session):
1501 """
1502 Lists dump of the given dump type
1503
1504 @param host: string, the hostname or IP address of the bmc
1505 @param args: contains additional arguments used by the collectServiceData sub command
1506 @param session: the active session to use
1507 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1508 """
1509 if (args.dumpType=="SystemDump"):
1510 dumpResp=systemDumpList(host,args,session)
1511 elif(args.dumpType=="bmc"):
1512 dumpResp=bmcDumpList(host,args,session)
1513 return dumpResp
1514
1515def dumpDelete(host, args, session):
1516 """
1517 Deletes dump of the given dump type
1518
1519 @param host: string, the hostname or IP address of the bmc
1520 @param args: contains additional arguments used by the collectServiceData sub command
1521 @param session: the active session to use
1522 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1523 """
1524 if (args.dumpType=="SystemDump"):
1525 dumpResp=systemDumpDelete(host,args,session)
1526 elif(args.dumpType=="bmc"):
1527 dumpResp=bmcDumpDelete(host,args,session)
1528 return dumpResp
1529
1530def dumpDeleteAll(host, args, session):
1531 """
1532 Deletes all dumps of the given dump type
1533
1534 @param host: string, the hostname or IP address of the bmc
1535 @param args: contains additional arguments used by the collectServiceData sub command
1536 @param session: the active session to use
1537 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1538 """
1539 if (args.dumpType=="SystemDump"):
1540 dumpResp=systemDumpDeleteAll(host,args,session)
1541 elif(args.dumpType=="bmc"):
1542 dumpResp=bmcDumpDeleteAll(host,args,session)
1543 return dumpResp
1544
1545def dumpCreate(host, args, session):
1546 """
1547 Creates dump for the given dump type
1548
1549 @param host: string, the hostname or IP address of the bmc
1550 @param args: contains additional arguments used by the collectServiceData sub command
1551 @param session: the active session to use
1552 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1553 """
1554 if (args.dumpType=="SystemDump"):
1555 dumpResp=systemDumpCreate(host,args,session)
1556 elif(args.dumpType=="bmc"):
Justin Thaler0a3e1692020-04-07 19:10:40 -05001557 dumpResp=bmcDumpCreate(host,args,session)
Ravi Tejad8be0b42020-03-18 14:31:46 -05001558 return dumpResp
1559
1560
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001561def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001562 """
1563 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001564
Justin Thalere412dc22018-01-12 16:28:24 -06001565 @param host: string, the hostname or IP address of the bmc
1566 @param args: contains additional arguments used by the collectServiceData sub command
1567 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001568 @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 -06001569 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001570 dumpNum = args.dumpNum
1571 if (args.dumpSaveLoc is not None):
1572 saveLoc = args.dumpSaveLoc
1573 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001574 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001575 url ='https://'+host+'/download/dump/' + str(dumpNum)
1576 try:
Justin Thaler27197622019-01-23 14:42:11 -06001577 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001578 if (args.dumpSaveLoc is not None):
1579 if os.path.exists(saveLoc):
1580 if saveLoc[-1] != os.path.sep:
1581 saveLoc = saveLoc + os.path.sep
1582 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001583
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001584 else:
1585 return 'Invalid save location specified'
1586 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001587 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001588
1589 with open(filename, 'wb') as f:
1590 for chunk in r.iter_content(chunk_size =1024):
1591 if chunk:
1592 f.write(chunk)
1593 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001594
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001595 except(requests.exceptions.Timeout):
1596 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001597
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001598 except(requests.exceptions.ConnectionError) as err:
1599 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001600
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001601def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001602 """
1603 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001604
Justin Thalere412dc22018-01-12 16:28:24 -06001605 @param host: string, the hostname or IP address of the bmc
1606 @param args: contains additional arguments used by the collectServiceData sub command
1607 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001608 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1609 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001610 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1611 try:
Justin Thaler27197622019-01-23 14:42:11 -06001612 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001613 dumpList = r.json()
Justin Thaler3b3c6582020-04-07 19:17:36 -05001614 formattedList = []
1615 #remove items that aren't dump entries 'entry, internal, manager endpoints'
1616 if 'data' in dumpList:
1617 for entry in dumpList['data']:
1618 if 'entry' in entry:
1619 if entry.split('/')[-1].isnumeric():
1620 formattedList.append(entry)
1621 dumpList['data']= formattedList
Justin Thaler3a5771b2019-01-23 14:31:52 -06001622 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001623 except(requests.exceptions.Timeout):
1624 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001625
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001626 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001627 return connectionErrHandler(args.json, "ConnectionError", err)
1628
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001629def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001630 """
1631 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001632
Justin Thalere412dc22018-01-12 16:28:24 -06001633 @param host: string, the hostname or IP address of the bmc
1634 @param args: contains additional arguments used by the collectServiceData sub command
1635 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001636 @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 -06001637 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001638 dumpList = []
1639 successList = []
1640 failedList = []
1641 if args.dumpNum is not None:
1642 if isinstance(args.dumpNum, list):
1643 dumpList = args.dumpNum
1644 else:
1645 dumpList.append(args.dumpNum)
1646 for dumpNum in dumpList:
1647 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1648 try:
Justin Thaler27197622019-01-23 14:42:11 -06001649 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001650 if r.status_code == 200:
1651 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001652 else:
1653 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001654 except(requests.exceptions.Timeout):
1655 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001656 except(requests.exceptions.ConnectionError) as err:
1657 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001658 output = "Successfully deleted dumps: " + ', '.join(successList)
1659 if(len(failedList)>0):
1660 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1661 return output
1662 else:
1663 return 'You must specify an entry number to delete'
1664
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001665def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001666 """
1667 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001668
Justin Thalere412dc22018-01-12 16:28:24 -06001669 @param host: string, the hostname or IP address of the bmc
1670 @param args: contains additional arguments used by the collectServiceData sub command
1671 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001672 @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 -06001673 """
1674 dumpResp = bmcDumpList(host, args, session)
1675 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1676 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001677 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001678 d = vars(args)
1679 dumpNums = []
1680 for dump in dumpList:
Alvin Wang28bd09d2019-10-28 13:23:58 +08001681 dumpNum = dump.strip().split('/')[-1]
1682 if dumpNum.isdigit():
1683 dumpNums.append(int(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001684 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001685
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001686 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001687
Justin Thalere412dc22018-01-12 16:28:24 -06001688
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001689def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001690 """
1691 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001692
Justin Thalere412dc22018-01-12 16:28:24 -06001693 @param host: string, the hostname or IP address of the bmc
1694 @param args: contains additional arguments used by the collectServiceData sub command
1695 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001696 @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 -06001697 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001698 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1699 try:
Justin Thaler27197622019-01-23 14:42:11 -06001700 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thaler2f59aea2020-04-07 19:27:01 -05001701 info = r.json()
Matt Spinlereae05b02019-01-24 12:59:34 -06001702 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001703 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001704 elif(args.json):
Justin Thaler2f59aea2020-04-07 19:27:01 -05001705 return info
1706 elif 'data' in info:
1707 if 'QuotaExceeded' in info['data']['description']:
1708 return 'BMC dump space is full. Please delete at least one existing dump entry and try again.'
1709 else:
1710 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001711 else:
Justin Thaler2f59aea2020-04-07 19:27:01 -05001712 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001713 except(requests.exceptions.Timeout):
1714 return connectionErrHandler(args.json, "Timeout", None)
1715 except(requests.exceptions.ConnectionError) as err:
1716 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001717
Justin Thaler2f59aea2020-04-07 19:27:01 -05001718
Ravi Tejad8be0b42020-03-18 14:31:46 -05001719def systemDumpRetrieve(host, args, session):
1720 """
1721 Downloads system dump
1722
1723 @param host: string, the hostname or IP address of the bmc
1724 @param args: contains additional arguments used by the collectServiceData sub command
1725 @param session: the active session to use
1726 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1727 """
1728 NBDSetup(host,args,session)
1729 pipe = NBDPipe()
1730 pipe.openHTTPSocket(args)
1731 pipe.openTCPSocket()
1732 pipe.waitformessage()
1733
1734def systemDumpList(host, args, session):
1735 """
1736 Lists system dumps
1737
1738 @param host: string, the hostname or IP address of the bmc
1739 @param args: contains additional arguments used by the collectServiceData sub command
1740 @param session: the active session to use
1741 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1742 """
Ravi Tejabef8da42020-07-14 23:01:51 -05001743 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/Dump/Entries"
Ravi Tejad8be0b42020-03-18 14:31:46 -05001744 try:
1745 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1746 dumpList = r.json()
1747 return dumpList
1748 except(requests.exceptions.Timeout):
1749 return connectionErrHandler(args.json, "Timeout", None)
1750
1751 except(requests.exceptions.ConnectionError) as err:
1752 return connectionErrHandler(args.json, "ConnectionError", err)
1753
1754
1755def systemDumpDelete(host, args, session):
1756 """
1757 Deletes system dump
1758
1759 @param host: string, the hostname or IP address of the bmc
1760 @param args: contains additional arguments used by the collectServiceData sub command
1761 @param session: the active session to use
1762 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1763 """
1764 dumpList = []
1765 successList = []
1766 failedList = []
1767 if args.dumpNum is not None:
1768 if isinstance(args.dumpNum, list):
1769 dumpList = args.dumpNum
1770 else:
1771 dumpList.append(args.dumpNum)
1772 for dumpNum in dumpList:
Ravi Tejabef8da42020-07-14 23:01:51 -05001773 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Entries/'+ str(dumpNum)
Ravi Tejad8be0b42020-03-18 14:31:46 -05001774 try:
1775 r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1776 if r.status_code == 200:
1777 successList.append(str(dumpNum))
1778 else:
1779 failedList.append(str(dumpNum))
1780 except(requests.exceptions.Timeout):
1781 return connectionErrHandler(args.json, "Timeout", None)
1782 except(requests.exceptions.ConnectionError) as err:
1783 return connectionErrHandler(args.json, "ConnectionError", err)
1784 output = "Successfully deleted dumps: " + ', '.join(successList)
1785 if(len(failedList)>0):
1786 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1787 return output
1788 else:
1789 return 'You must specify an entry number to delete'
1790
1791def systemDumpDeleteAll(host, args, session):
1792 """
1793 Deletes All system dumps
1794
1795 @param host: string, the hostname or IP address of the bmc
1796 @param args: contains additional arguments used by the collectServiceData sub command
1797 @param session: the active session to use
1798 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1799 """
Ravi Tejabef8da42020-07-14 23:01:51 -05001800 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog'
Ravi Tejad8be0b42020-03-18 14:31:46 -05001801 try:
1802 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1803 if(r.status_code == 200 and not args.json):
1804 return ('Dumps successfully cleared')
1805 elif(args.json):
1806 return r.json()
1807 else:
1808 return ('Failed to clear dumps')
1809 except(requests.exceptions.Timeout):
1810 return connectionErrHandler(args.json, "Timeout", None)
1811 except(requests.exceptions.ConnectionError) as err:
1812 return connectionErrHandler(args.json, "ConnectionError", err)
1813
1814def systemDumpCreate(host, args, session):
1815 """
1816 Creates a system dump
1817
1818 @param host: string, the hostname or IP address of the bmc
1819 @param args: contains additional arguments used by the collectServiceData sub command
1820 @param session: the active session to use
1821 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1822 """
Ravi Tejabef8da42020-07-14 23:01:51 -05001823 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Actions/Oem/OemLogService.CollectDiagnosticData'
Ravi Tejad8be0b42020-03-18 14:31:46 -05001824 try:
1825 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Ravi Tejabef8da42020-07-14 23:01:51 -05001826 if(r.status_code == 200):
Ravi Tejad8be0b42020-03-18 14:31:46 -05001827 return r.json()
1828 else:
1829 return ('Failed to create dump')
1830 except(requests.exceptions.Timeout):
1831 return connectionErrHandler(args.json, "Timeout", None)
1832 except(requests.exceptions.ConnectionError) as err:
1833 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001834
Justin Thaler666cf342019-01-23 14:44:27 -06001835def csdDumpInitiate(host, args, session):
1836 """
1837 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001838
Justin Thaler666cf342019-01-23 14:44:27 -06001839 @param host: string, the hostname or IP address of the bmc
1840 @param args: contains additional arguments used by the collectServiceData sub command
1841 @param session: the active session to use
1842 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1843 """
1844 errorInfo = ""
1845 dumpcount = 0
1846 try:
1847 d = vars(args)
1848 d['json'] = True
1849 except Exception as e:
1850 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001851 exc_type, exc_obj, exc_tb = sys.exc_info()
1852 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1853 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1854 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001855
1856 try:
1857 for i in range(3):
1858 dumpInfo = bmcDumpList(host, args, session)
1859 if 'data' in dumpInfo:
1860 dumpcount = len(dumpInfo['data'])
1861 break
1862 else:
1863 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1864 except Exception as e:
1865 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001866 exc_type, exc_obj, exc_tb = sys.exc_info()
1867 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1868 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1869 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001870
1871 #Create a user initiated dump
Justin Thalerb4256672020-04-07 19:38:26 -05001872 dumpFailure = True
Justin Thaler666cf342019-01-23 14:44:27 -06001873 try:
1874 for i in range(3):
1875 dumpcreated = bmcDumpCreate(host, args, session)
1876 if 'message' in dumpcreated:
1877 if 'ok' in dumpcreated['message'].lower():
Justin Thalerb4256672020-04-07 19:38:26 -05001878 dumpFailure = False
Justin Thaler666cf342019-01-23 14:44:27 -06001879 break
Justin Thalerb4256672020-04-07 19:38:26 -05001880 elif 'data' in dumpcreated:
1881 if 'QuotaExceeded' in dumpcreated['data']['description']:
1882 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.')
1883 errorInfo+='Dump Space is full. No new dump was created with this collection'
1884 break
1885 else:
1886 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001887 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001888 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001889 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001890 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001891 except Exception as e:
1892 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001893 exc_type, exc_obj, exc_tb = sys.exc_info()
1894 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1895 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1896 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001897
1898 output = {}
1899 output['errors'] = errorInfo
1900 output['dumpcount'] = dumpcount
Justin Thalerb4256672020-04-07 19:38:26 -05001901 if dumpFailure: output['dumpFailure'] = True
Justin Thaler666cf342019-01-23 14:44:27 -06001902 return output
1903
1904def csdInventory(host, args,session, fileDir):
1905 """
1906 Collects the BMC inventory, retrying if necessary
1907
1908 @param host: string, the hostname or IP address of the bmc
1909 @param args: contains additional arguments used by the collectServiceData sub command
1910 @param session: the active session to use
1911 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1912 @param fileDir: string representation of the path to use for putting files created
1913 """
1914 errorInfo = "===========Inventory =============\n"
1915 output={}
1916 inventoryCollected = False
1917 try:
1918 for i in range(3):
1919 frulist = fruPrint(host, args, session)
1920 if 'Hardware' in frulist:
1921 inventoryCollected = True
1922 break
1923 else:
1924 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1925 except Exception as e:
1926 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001927 exc_type, exc_obj, exc_tb = sys.exc_info()
1928 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1929 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1930 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001931 if inventoryCollected:
1932 try:
1933 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1934 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1935 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1936 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1937 except Exception as e:
1938 print("Failed to write inventory to file.")
1939 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001940 exc_type, exc_obj, exc_tb = sys.exc_info()
1941 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1942 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1943 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001944
1945 output['errors'] = errorInfo
1946
1947 return output
1948
1949def csdSensors(host, args,session, fileDir):
1950 """
1951 Collects the BMC sensor readings, retrying if necessary
1952
1953 @param host: string, the hostname or IP address of the bmc
1954 @param args: contains additional arguments used by the collectServiceData sub command
1955 @param session: the active session to use
1956 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1957 @param fileDir: string representation of the path to use for putting files created
1958 """
1959 errorInfo = "===========Sensors =============\n"
1960 sensorsCollected = False
1961 output={}
1962 try:
1963 d = vars(args)
1964 d['json'] = False
1965 except Exception as e:
1966 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001967 exc_type, exc_obj, exc_tb = sys.exc_info()
1968 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1969 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1970 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001971
1972 try:
1973 for i in range(3):
1974 sensorReadings = sensor(host, args, session)
1975 if 'OCC0' in sensorReadings:
1976 sensorsCollected = True
1977 break
1978 else:
1979 errorInfo += sensorReadings
1980 except Exception as e:
1981 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001982 exc_type, exc_obj, exc_tb = sys.exc_info()
1983 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1984 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1985 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001986 if sensorsCollected:
1987 try:
1988 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1989 f.write(sensorReadings)
1990 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1991 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1992 except Exception as e:
1993 print("Failed to write sensor readings to file system.")
1994 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001995 exc_type, exc_obj, exc_tb = sys.exc_info()
1996 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1997 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1998 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001999
2000 output['errors'] = errorInfo
2001 return output
2002
2003def csdLEDs(host,args, session, fileDir):
2004 """
2005 Collects the BMC LED status, retrying if necessary
2006
2007 @param host: string, the hostname or IP address of the bmc
2008 @param args: contains additional arguments used by the collectServiceData sub command
2009 @param session: the active session to use
2010 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2011 @param fileDir: string representation of the path to use for putting files created
2012 """
2013 errorInfo = "===========LEDs =============\n"
2014 ledsCollected = False
2015 output={}
2016 try:
2017 d = vars(args)
2018 d['json'] = True
2019 except Exception as e:
2020 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002021 exc_type, exc_obj, exc_tb = sys.exc_info()
2022 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2023 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2024 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002025 try:
2026 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
2027 httpHeader = {'Content-Type':'application/json'}
2028 for i in range(3):
2029 try:
2030 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2031 if ledRes.status_code == 200:
2032 ledsCollected = True
2033 leds = ledRes.json()['data']
2034 break
2035 else:
2036 errorInfo += ledRes.text
2037 except(requests.exceptions.Timeout):
2038 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2039 except(requests.exceptions.ConnectionError) as err:
2040 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 -05002041 exc_type, exc_obj, exc_tb = sys.exc_info()
2042 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2043 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2044 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002045 except Exception as e:
2046 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002047 exc_type, exc_obj, exc_tb = sys.exc_info()
2048 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2049 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2050 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002051
2052 if ledsCollected:
2053 try:
2054 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
2055 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2056 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
2057 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
2058 except Exception as e:
2059 print("Failed to write LED status to file system.")
2060 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002061 exc_type, exc_obj, exc_tb = sys.exc_info()
2062 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2063 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2064 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002065
2066 output['errors'] = errorInfo
2067 return output
2068
2069def csdSelShortList(host, args, session, fileDir):
2070 """
2071 Collects the BMC log entries, retrying if necessary
2072
2073 @param host: string, the hostname or IP address of the bmc
2074 @param args: contains additional arguments used by the collectServiceData sub command
2075 @param session: the active session to use
2076 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2077 @param fileDir: string representation of the path to use for putting files created
2078 """
2079 errorInfo = "===========SEL Short List =============\n"
2080 selsCollected = False
2081 output={}
2082 try:
2083 d = vars(args)
2084 d['json'] = False
2085 except Exception as e:
2086 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002087 exc_type, exc_obj, exc_tb = sys.exc_info()
2088 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2089 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2090 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002091
2092 try:
2093 for i in range(3):
2094 sels = selPrint(host,args,session)
2095 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
2096 selsCollected = True
2097 break
2098 else:
2099 errorInfo += sels + '\n'
2100 except Exception as e:
2101 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002102 exc_type, exc_obj, exc_tb = sys.exc_info()
2103 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2104 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2105 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002106
2107 if selsCollected:
2108 try:
2109 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
2110 f.write(sels)
2111 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
2112 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
2113 except Exception as e:
2114 print("Failed to write SEL short list to file system.")
2115 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002116 exc_type, exc_obj, exc_tb = sys.exc_info()
2117 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2118 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2119 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002120
2121 output['errors'] = errorInfo
2122 return output
2123
2124def csdParsedSels(host, args, session, fileDir):
2125 """
2126 Collects the BMC log entries, retrying if necessary
2127
2128 @param host: string, the hostname or IP address of the bmc
2129 @param args: contains additional arguments used by the collectServiceData sub command
2130 @param session: the active session to use
2131 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2132 @param fileDir: string representation of the path to use for putting files created
2133 """
2134 errorInfo = "===========SEL Parsed List =============\n"
2135 selsCollected = False
2136 output={}
2137 try:
2138 d = vars(args)
2139 d['json'] = True
2140 d['fullEsel'] = True
2141 except Exception as e:
2142 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002143 exc_type, exc_obj, exc_tb = sys.exc_info()
2144 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2145 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2146 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002147
2148 try:
2149 for i in range(3):
2150 parsedfullsels = json.loads(selPrint(host,args,session))
2151 if 'numAlerts' in parsedfullsels:
2152 selsCollected = True
2153 break
2154 else:
2155 errorInfo += parsedfullsels + '\n'
2156 except Exception as e:
2157 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002158 exc_type, exc_obj, exc_tb = sys.exc_info()
2159 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2160 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2161 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002162
2163 if selsCollected:
2164 try:
2165 sortedSELs = sortSELs(parsedfullsels)
2166 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
2167 for log in sortedSELs[0]:
2168 esel = ""
2169 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
2170 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
2171 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2172 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2173 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
2174 if(args.devdebug and esel != ""):
2175 f.write(parseESEL(args, esel))
2176 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
2177 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
2178 except Exception as e:
2179 print("Failed to write fully parsed SELs to file system.")
2180 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002181 exc_type, exc_obj, exc_tb = sys.exc_info()
2182 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2183 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2184 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002185
2186 output['errors'] = errorInfo
2187 return output
2188
2189def csdFullEnumeration(host, args, session, fileDir):
2190 """
2191 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
2192
2193 @param host: string, the hostname or IP address of the bmc
2194 @param args: contains additional arguments used by the collectServiceData sub command
2195 @param session: the active session to use
2196 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2197 @param fileDir: string representation of the path to use for putting files created
2198 """
2199 errorInfo = "===========BMC Full Enumeration =============\n"
2200 bmcFullCollected = False
2201 output={}
2202 try:
2203 d = vars(args)
2204 d['json'] = True
2205 except Exception as e:
2206 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002207 exc_type, exc_obj, exc_tb = sys.exc_info()
2208 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2209 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2210 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002211 try:
2212 print("Attempting to get a full BMC enumeration")
2213 url="https://"+host+"/xyz/openbmc_project/enumerate"
2214 httpHeader = {'Content-Type':'application/json'}
2215 for i in range(3):
2216 try:
2217 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
2218 if bmcRes.status_code == 200:
2219 bmcFullCollected = True
2220 fullEnumeration = bmcRes.json()
2221 break
2222 else:
2223 errorInfo += bmcRes.text
2224 except(requests.exceptions.Timeout):
2225 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2226 except(requests.exceptions.ConnectionError) as err:
2227 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 -05002228 exc_type, exc_obj, exc_tb = sys.exc_info()
2229 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2230 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2231 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002232 except Exception as e:
2233 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002234 exc_type, exc_obj, exc_tb = sys.exc_info()
2235 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2236 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2237 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002238
2239 if bmcFullCollected:
2240 try:
2241 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
2242 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2243 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
2244 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
2245 except Exception as e:
2246 print("Failed to write RAW BMC data to file system.")
2247 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002248 exc_type, exc_obj, exc_tb = sys.exc_info()
2249 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2250 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2251 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002252
2253 output['errors'] = errorInfo
2254 return output
2255
2256def csdCollectAllDumps(host, args, session, fileDir):
2257 """
2258 Collects all of the bmc dump files and stores them in fileDir
2259
2260 @param host: string, the hostname or IP address of the bmc
2261 @param args: contains additional arguments used by the collectServiceData sub command
2262 @param session: the active session to use
2263 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2264 @param fileDir: string representation of the path to use for putting files created
2265 """
2266
2267 errorInfo = "===========BMC Dump Collection =============\n"
2268 dumpListCollected = False
2269 output={}
2270 dumpList = {}
2271 try:
2272 d = vars(args)
2273 d['json'] = True
2274 d['dumpSaveLoc'] = fileDir
2275 except Exception as e:
2276 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 -05002277 exc_type, exc_obj, exc_tb = sys.exc_info()
2278 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2279 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2280 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002281
2282 print('Collecting bmc dump files')
2283
2284 try:
2285 for i in range(3):
2286 dumpResp = bmcDumpList(host, args, session)
2287 if 'message' in dumpResp:
2288 if 'ok' in dumpResp['message'].lower():
2289 dumpList = dumpResp['data']
2290 dumpListCollected = True
2291 break
2292 else:
2293 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
2294 else:
2295 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
2296 except Exception as e:
2297 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002298 exc_type, exc_obj, exc_tb = sys.exc_info()
2299 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2300 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2301 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002302
2303 if dumpListCollected:
2304 output['fileList'] = []
2305 for dump in dumpList:
2306 try:
2307 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
2308 d['dumpNum'] = int(dump.strip().split('/')[-1])
2309 print('retrieving dump file ' + str(d['dumpNum']))
2310 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
2311 output['fileList'].append(filename)
2312 except Exception as e:
2313 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
2314 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002315 exc_type, exc_obj, exc_tb = sys.exc_info()
2316 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2317 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2318 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002319 output['errors'] = errorInfo
2320 return output
Justin Thalere412dc22018-01-12 16:28:24 -06002321
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002322def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002323 """
2324 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002325
Justin Thalere412dc22018-01-12 16:28:24 -06002326 @param host: string, the hostname or IP address of the bmc
2327 @param args: contains additional arguments used by the collectServiceData sub command
2328 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002329 @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 -06002330 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002331
Justin Thaler22b1bb52018-03-15 13:31:32 -05002332 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06002333 filelist = []
2334 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002335
Justin Thaler666cf342019-01-23 14:44:27 -06002336 #get current number of bmc dumps and create a new bmc dump
2337 dumpInitdata = csdDumpInitiate(host, args, session)
Justin Thalerb4256672020-04-07 19:38:26 -05002338 if 'dumpFailure' in dumpInitdata:
2339 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 -06002340 dumpcount = dumpInitdata['dumpcount']
2341 errorInfo += dumpInitdata['errors']
2342 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002343 try:
2344 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05002345 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002346 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002347
Justin Thaler666cf342019-01-23 14:44:27 -06002348 except Exception as e:
2349 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 -05002350 exc_type, exc_obj, exc_tb = sys.exc_info()
2351 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2352 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2353 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002354 return("Python exception: {eInfo}".format(eInfo = e))
2355
2356 #Collect Inventory
2357 inventoryData = csdInventory(host, args, session, myDir)
2358 if 'fileLoc' in inventoryData:
2359 filelist.append(inventoryData['fileLoc'])
2360 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002361 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06002362 sensorData = csdSensors(host,args,session,myDir)
2363 if 'fileLoc' in sensorData:
2364 filelist.append(sensorData['fileLoc'])
2365 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002366 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06002367 ledStatus = csdLEDs(host, args, session, myDir)
2368 if 'fileLoc' in ledStatus:
2369 filelist.append(ledStatus['fileLoc'])
2370 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002371
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002372 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06002373 selShort = csdSelShortList(host, args, session, myDir)
2374 if 'fileLoc' in selShort:
2375 filelist.append(selShort['fileLoc'])
2376 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002377
Justin Thaler666cf342019-01-23 14:44:27 -06002378 parsedSELs = csdParsedSels(host, args, session, myDir)
2379 if 'fileLoc' in parsedSELs:
2380 filelist.append(parsedSELs['fileLoc'])
2381 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002382
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002383 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06002384 bmcRaw = csdFullEnumeration(host, args, session, myDir)
2385 if 'fileLoc' in bmcRaw:
2386 filelist.append(bmcRaw['fileLoc'])
2387 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002388
Justin Thaler666cf342019-01-23 14:44:27 -06002389 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002390 waitingForNewDump = True
2391 count = 0;
Justin Thalerb4256672020-04-07 19:38:26 -05002392 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 -06002393 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06002394 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002395 if len(dumpList) > dumpcount:
2396 waitingForNewDump = False
2397 break;
Justin Thalerb4256672020-04-07 19:38:26 -05002398 elif(count>150):
2399 print("Timed out waiting for bmc to make a new dump file. Continuing without it.")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002400 break;
2401 else:
2402 time.sleep(2)
2403 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06002404
2405 #collect all of the dump files
2406 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
2407 if 'fileList' in getBMCDumps:
2408 filelist+= getBMCDumps['fileList']
2409 errorInfo += getBMCDumps['errors']
2410
2411 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002412 try:
Justin Thaler666cf342019-01-23 14:44:27 -06002413 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
2414 f.write(errorInfo)
2415 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
2416 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002417 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06002418 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002419
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002420 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002421 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05002422 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06002423 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002424 for myfile in filelist:
2425 zf.write(myfile, os.path.basename(myfile))
2426 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06002427 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 -06002428 except Exception as e:
2429 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06002430 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002431
Justin Thalere412dc22018-01-12 16:28:24 -06002432
2433def healthCheck(host, args, session):
2434 """
2435 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002436
Justin Thalere412dc22018-01-12 16:28:24 -06002437 @param host: string, the hostname or IP address of the bmc
2438 @param args: contains additional arguments used by the bmc sub command
2439 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002440 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2441 """
Justin Thalere412dc22018-01-12 16:28:24 -06002442 #check fru status and get as json to easily work through
2443 d = vars(args)
2444 useJson = d['json']
2445 d['json'] = True
2446 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002447
Justin Thalere412dc22018-01-12 16:28:24 -06002448 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002449
Justin Thalere412dc22018-01-12 16:28:24 -06002450 hwStatus= "OK"
2451 performanceStatus = "OK"
2452 for key in frus:
2453 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
2454 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05002455 if("power_supply" in key or "powersupply" in key):
2456 gpuCount =0
2457 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06002458 if "gv100card" in comp:
2459 gpuCount +=1
2460 if gpuCount > 4:
2461 hwStatus = "Critical"
2462 performanceStatus="Degraded"
2463 break;
2464 elif("fan" in key):
2465 hwStatus = "Degraded"
2466 else:
2467 performanceStatus = "Degraded"
2468 if useJson:
2469 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
2470 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
2471 else:
2472 output = ("Hardware Status: " + hwStatus +
2473 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002474
2475
Justin Thalere412dc22018-01-12 16:28:24 -06002476 #SW407886: Clear the duplicate entries
2477 #collect the dups
2478 d['devdebug'] = False
2479 sels = json.loads(selPrint(host, args, session))
2480 logNums2Clr = []
2481 oldestLogNum={"logNum": "bogus" ,"key" : ""}
2482 count = 0
2483 if sels['numAlerts'] > 0:
2484 for key in sels:
2485 if "numAlerts" in key:
2486 continue
2487 try:
2488 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
2489 count += 1
2490 if count > 1:
2491 #preserve first occurrence
2492 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
2493 oldestLogNum['key']=key
2494 oldestLogNum['logNum'] = sels[key]['logNum']
2495 else:
2496 oldestLogNum['key']=key
2497 oldestLogNum['logNum'] = sels[key]['logNum']
2498 logNums2Clr.append(sels[key]['logNum'])
2499 except KeyError:
2500 continue
2501 if(count >0):
2502 logNums2Clr.remove(oldestLogNum['logNum'])
2503 #delete the dups
2504 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06002505 data = "{\"data\": [] }"
2506 for logNum in logNums2Clr:
2507 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2508 try:
Justin Thaler27197622019-01-23 14:42:11 -06002509 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002510 except(requests.exceptions.Timeout):
2511 deleteFailed = True
2512 except(requests.exceptions.ConnectionError) as err:
2513 deleteFailed = True
2514 #End of defect resolve code
2515 d['json'] = useJson
2516 return output
2517
2518
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002519
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002520def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002521 """
2522 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002523
Justin Thalere412dc22018-01-12 16:28:24 -06002524 @param host: string, the hostname or IP address of the bmc
2525 @param args: contains additional arguments used by the bmc sub command
2526 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002527 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2528 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002529 if(args.type is not None):
2530 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002531 if(args.info):
2532 return "Not implemented at this time"
2533
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002534
Justin Thalere412dc22018-01-12 16:28:24 -06002535
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002536def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002537 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002538 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2539
Justin Thalere412dc22018-01-12 16:28:24 -06002540 @param host: string, the hostname or IP address of the bmc
2541 @param args: contains additional arguments used by the bmcReset sub command
2542 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002543 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2544 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002545 if checkFWactivation(host, args, session):
2546 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002547 if(args.type == "warm"):
2548 print("\nAttempting to reboot the BMC...:")
2549 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002550 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002551 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002552 return res.text
2553 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002554 print("\nAttempting to reboot the BMC...:")
2555 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002556 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002557 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002558 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002559 else:
2560 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002561
2562def gardClear(host, args, session):
2563 """
2564 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002565
Justin Thalere412dc22018-01-12 16:28:24 -06002566 @param host: string, the hostname or IP address of the bmc
2567 @param args: contains additional arguments used by the gardClear sub command
2568 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002569 """
Justin Thalere412dc22018-01-12 16:28:24 -06002570 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002571 data = '{"data":[]}'
2572 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002573
Justin Thaler27197622019-01-23 14:42:11 -06002574 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002575 if res.status_code == 404:
2576 return "Command not supported by this firmware version"
2577 else:
2578 return res.text
2579 except(requests.exceptions.Timeout):
2580 return connectionErrHandler(args.json, "Timeout", None)
2581 except(requests.exceptions.ConnectionError) as err:
2582 return connectionErrHandler(args.json, "ConnectionError", err)
2583
2584def activateFWImage(host, args, session):
2585 """
2586 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002587
Justin Thalere412dc22018-01-12 16:28:24 -06002588 @param host: string, the hostname or IP address of the bmc
2589 @param args: contains additional arguments used by the fwflash sub command
2590 @param session: the active session to use
2591 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002592 """
Justin Thalere412dc22018-01-12 16:28:24 -06002593 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002594
Justin Thalere412dc22018-01-12 16:28:24 -06002595 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002596 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2597 try:
Justin Thaler27197622019-01-23 14:42:11 -06002598 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002599 except(requests.exceptions.Timeout):
2600 return connectionErrHandler(args.json, "Timeout", None)
2601 except(requests.exceptions.ConnectionError) as err:
2602 return connectionErrHandler(args.json, "ConnectionError", err)
2603 existingSoftware = json.loads(resp.text)['data']
2604 altVersionID = ''
2605 versionType = ''
2606 imageKey = '/xyz/openbmc_project/software/'+fwID
2607 if imageKey in existingSoftware:
2608 versionType = existingSoftware[imageKey]['Purpose']
2609 for key in existingSoftware:
2610 if imageKey == key:
2611 continue
2612 if 'Purpose' in existingSoftware[key]:
2613 if versionType == existingSoftware[key]['Purpose']:
2614 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002615
2616
2617
2618
Justin Thalere412dc22018-01-12 16:28:24 -06002619 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2620 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002621 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002622 data1 = "{\"data\": 1 }"
2623 try:
Justin Thaler27197622019-01-23 14:42:11 -06002624 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2625 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002626 except(requests.exceptions.Timeout):
2627 return connectionErrHandler(args.json, "Timeout", None)
2628 except(requests.exceptions.ConnectionError) as err:
2629 return connectionErrHandler(args.json, "ConnectionError", err)
2630 if(not args.json):
2631 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002632 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 -06002633 else:
2634 return "Firmware activation failed."
2635 else:
2636 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002637
2638def activateStatus(host, args, session):
2639 if checkFWactivation(host, args, session):
2640 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2641 else:
2642 return("No firmware activations are pending")
2643
2644def extractFWimage(path, imageType):
2645 """
2646 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002647
Justin Thaler22b1bb52018-03-15 13:31:32 -05002648 @param path: the path and file name of the firmware image
2649 @param imageType: The type of image the user is trying to flash. Host or BMC
2650 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002651 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002652 f = tempfile.TemporaryFile()
2653 tmpDir = tempfile.gettempdir()
2654 newImageID = ""
2655 if os.path.exists(path):
2656 try:
2657 imageFile = tarfile.open(path,'r')
2658 contents = imageFile.getmembers()
2659 for tf in contents:
2660 if 'MANIFEST' in tf.name:
2661 imageFile.extract(tf.name, path=tmpDir)
2662 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2663 for line in imageInfo:
2664 if 'purpose' in line:
2665 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002666 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002667 print('The specified image is not for ' + imageType)
2668 print('Please try again with the image for ' + imageType)
2669 return ""
2670 if 'version' == line.split('=')[0]:
2671 version = line.split('=')[1].strip().encode('utf-8')
2672 m = hashlib.sha512()
2673 m.update(version)
2674 newImageID = m.hexdigest()[:8]
2675 break
2676 try:
2677 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2678 except OSError:
2679 pass
2680 return newImageID
2681 except tarfile.ExtractError as e:
2682 print('Unable to extract information from the firmware file.')
2683 print('Ensure you have write access to the directory: ' + tmpDir)
2684 return newImageID
2685 except tarfile.TarError as e:
2686 print('This is not a valid firmware file.')
2687 return newImageID
2688 print("This is not a valid firmware file.")
2689 return newImageID
2690 else:
2691 print('The filename and path provided are not valid.')
2692 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002693
Justin Thaler22b1bb52018-03-15 13:31:32 -05002694def getAllFWImageIDs(fwInvDict):
2695 """
2696 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002697
Justin Thaler22b1bb52018-03-15 13:31:32 -05002698 @param fwInvDict: the dictionary to search for FW image IDs
2699 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002700 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002701 idList = []
2702 for key in fwInvDict:
2703 if 'Version' in fwInvDict[key]:
2704 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002705 return idList
2706
Justin Thalere412dc22018-01-12 16:28:24 -06002707def fwFlash(host, args, session):
2708 """
2709 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002710
Justin Thalere412dc22018-01-12 16:28:24 -06002711 @param host: string, the hostname or IP address of the bmc
2712 @param args: contains additional arguments used by the fwflash sub command
2713 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002714 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002715 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002716 if(args.type == 'bmc'):
2717 purp = 'BMC'
2718 else:
2719 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002720
2721 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002722 d['powcmd'] = 'status'
2723 powerstate = chassisPower(host, args, session)
2724 if 'Chassis Power State: On' in powerstate:
2725 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002726
Justin Thaler22b1bb52018-03-15 13:31:32 -05002727 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002728 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2729 try:
Justin Thaler27197622019-01-23 14:42:11 -06002730 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002731 except(requests.exceptions.Timeout):
2732 return connectionErrHandler(args.json, "Timeout", None)
2733 except(requests.exceptions.ConnectionError) as err:
2734 return connectionErrHandler(args.json, "ConnectionError", err)
2735 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002736
Justin Thaler22b1bb52018-03-15 13:31:32 -05002737 #Extract the tar and get information from the manifest file
2738 newversionID = extractFWimage(args.fileloc, purp)
2739 if newversionID == "":
2740 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002741
2742
Justin Thaler22b1bb52018-03-15 13:31:32 -05002743 #check if the new image is already on the bmc
2744 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002745
Justin Thaler22b1bb52018-03-15 13:31:32 -05002746 #upload the file
2747 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002748 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002749 url="https://"+host+"/upload/image"
2750 data=open(args.fileloc,'rb').read()
2751 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002752 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002753 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06002754 except(requests.exceptions.Timeout):
2755 return connectionErrHandler(args.json, "Timeout", None)
2756 except(requests.exceptions.ConnectionError) as err:
2757 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002758 if resp.status_code != 200:
2759 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002760 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002761 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002762
Justin Thaler22b1bb52018-03-15 13:31:32 -05002763 #verify bmc processed the image
2764 software ={}
2765 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002766 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2767 try:
Justin Thaler27197622019-01-23 14:42:11 -06002768 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002769 except(requests.exceptions.Timeout):
2770 return connectionErrHandler(args.json, "Timeout", None)
2771 except(requests.exceptions.ConnectionError) as err:
2772 return connectionErrHandler(args.json, "ConnectionError", err)
2773 software = json.loads(resp.text)['data']
2774 #check if bmc is done processing the new image
2775 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002776 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002777 else:
2778 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002779
Justin Thaler22b1bb52018-03-15 13:31:32 -05002780 #activate the new image
2781 print("Activating new image: "+newversionID)
2782 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002783 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002784 try:
Justin Thaler27197622019-01-23 14:42:11 -06002785 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002786 except(requests.exceptions.Timeout):
2787 return connectionErrHandler(args.json, "Timeout", None)
2788 except(requests.exceptions.ConnectionError) as err:
2789 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002790
Justin Thaler22b1bb52018-03-15 13:31:32 -05002791 #wait for the activation to complete, timeout after ~1 hour
2792 i=0
2793 while i < 360:
2794 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002795 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002796 try:
Justin Thaler27197622019-01-23 14:42:11 -06002797 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002798 except(requests.exceptions.Timeout):
2799 return connectionErrHandler(args.json, "Timeout", None)
2800 except(requests.exceptions.ConnectionError) as err:
2801 return connectionErrHandler(args.json, "ConnectionError", err)
2802 fwInfo = json.loads(resp.text)['data']
2803 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2804 print('')
2805 break
2806 else:
2807 sys.stdout.write('.')
2808 sys.stdout.flush()
2809 time.sleep(10) #check every 10 seconds
2810 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2811 else:
2812 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002813
Justin Thaler22b1bb52018-03-15 13:31:32 -05002814 d['imageID'] = newversionID
2815 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002816
Justin Thaler3d71d402018-07-24 14:35:39 -05002817def getFWInventoryAttributes(rawFWInvItem, ID):
2818 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002819 gets and lists all of the firmware in the system.
2820
Justin Thaler3d71d402018-07-24 14:35:39 -05002821 @return: returns a dictionary containing the image attributes
2822 """
2823 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2824 pendingActivation = ""
2825 if reqActivation == "None":
2826 pendingActivation = "No"
2827 else:
2828 pendingActivation = "Yes"
2829 firmwareAttr = {ID: {
2830 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2831 "Version": rawFWInvItem["Version"],
2832 "RequestedActivation": pendingActivation,
2833 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002834
Justin Thaler3d71d402018-07-24 14:35:39 -05002835 if "ExtendedVersion" in rawFWInvItem:
2836 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002837 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002838 firmwareAttr[ID]['ExtendedVersion'] = ""
2839 return firmwareAttr
2840
2841def parseFWdata(firmwareDict):
2842 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002843 creates a dictionary with parsed firmware data
2844
Justin Thaler3d71d402018-07-24 14:35:39 -05002845 @return: returns a dictionary containing the image attributes
2846 """
2847 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2848 for key in firmwareDict['data']:
2849 #check for valid endpoint
2850 if "Purpose" in firmwareDict['data'][key]:
2851 id = key.split('/')[-1]
2852 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2853 fwActivated = True
2854 else:
2855 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002856 if 'Priority' in firmwareDict['data'][key]:
2857 if firmwareDict['data'][key]['Priority'] == 0:
2858 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2859 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2860 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2861 else:
2862 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002863 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002864 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002865 emptySections = []
2866 for key in firmwareInfoDict:
2867 if len(firmwareInfoDict[key])<=0:
2868 emptySections.append(key)
2869 for key in emptySections:
2870 del firmwareInfoDict[key]
2871 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002872
Justin Thaler3d71d402018-07-24 14:35:39 -05002873def displayFWInvenory(firmwareInfoDict, args):
2874 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002875 gets and lists all of the firmware in the system.
2876
Justin Thaler3d71d402018-07-24 14:35:39 -05002877 @return: returns a string containing all of the firmware information
2878 """
2879 output = ""
2880 if not args.json:
2881 for key in firmwareInfoDict:
2882 for subkey in firmwareInfoDict[key]:
2883 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2884 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002885 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002886 colNames = ["Purpose", "Version", "ID"]
2887 keylist = ["Purpose", "Version", "ID"]
2888 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2889 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002890 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002891 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2892 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002893 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002894 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002895
Justin Thaler3d71d402018-07-24 14:35:39 -05002896 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002897 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002898 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2899 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2900 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2901 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002902 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002903 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2904 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002905 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002906 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2907 return output
2908 else:
2909 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2910
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002911def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002912 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002913 gets and lists all of the firmware in the system.
2914
Justin Thaler3d71d402018-07-24 14:35:39 -05002915 @return: returns a string containing all of the firmware information
2916 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002917 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2918 try:
Justin Thaler27197622019-01-23 14:42:11 -06002919 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002920 except(requests.exceptions.Timeout):
2921 return(connectionErrHandler(args.json, "Timeout", None))
2922 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002923
Justin Thaler3d71d402018-07-24 14:35:39 -05002924 #sort the received information
2925 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002926
Justin Thaler3d71d402018-07-24 14:35:39 -05002927 #display the information
2928 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002929
2930
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002931def deleteFWVersion(host, args, session):
2932 """
2933 deletes a firmware version on the BMC
2934
2935 @param host: string, the hostname or IP address of the BMC
2936 @param args: contains additional arguments used by the fwflash sub command
2937 @param session: the active session to use
2938 @param fwID: the unique ID of the fw version to delete
2939 """
2940 fwID = args.versionID
2941
2942 print("Deleting version: "+fwID)
2943 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002944 data = "{\"data\": [] }"
2945
2946 try:
Justin Thaler27197622019-01-23 14:42:11 -06002947 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002948 except(requests.exceptions.Timeout):
2949 return(connectionErrHandler(args.json, "Timeout", None))
2950 if res.status_code == 200:
2951 return ('The firmware version has been deleted')
2952 else:
2953 return ('Unable to delete the specified firmware version')
2954
2955
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002956def restLogging(host, args, session):
2957 """
2958 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002959
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002960 @param host: string, the hostname or IP address of the bmc
2961 @param args: contains additional arguments used by the logging sub command
2962 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002963 @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 -05002964 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002965 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002966
2967 if(args.rest_logging == 'on'):
2968 data = '{"data": 1}'
2969 elif(args.rest_logging == 'off'):
2970 data = '{"data": 0}'
2971 else:
2972 return "Invalid logging rest_api command"
2973
2974 try:
Justin Thaler27197622019-01-23 14:42:11 -06002975 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002976 except(requests.exceptions.Timeout):
2977 return(connectionErrHandler(args.json, "Timeout", None))
2978 return res.text
2979
2980
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002981def remoteLogging(host, args, session):
2982 """
2983 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002984
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002985 @param host: string, the hostname or IP address of the bmc
2986 @param args: contains additional arguments used by the logging sub command
2987 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002988 @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 -05002989 """
2990
2991 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002992
2993 try:
2994 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002995 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002996 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002997 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2998 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002999 else:
3000 return "Invalid logging remote_logging command"
3001 except(requests.exceptions.Timeout):
3002 return(connectionErrHandler(args.json, "Timeout", None))
3003 return res.text
3004
3005
3006def remoteLoggingConfig(host, args, session):
3007 """
3008 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003009
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003010 @param host: string, the hostname or IP address of the bmc
3011 @param args: contains additional arguments used by the logging sub command
3012 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003013 @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 -05003014 """
3015
3016 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003017
3018 try:
Justin Thaler27197622019-01-23 14:42:11 -06003019 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
3020 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003021 except(requests.exceptions.Timeout):
3022 return(connectionErrHandler(args.json, "Timeout", None))
3023 return res.text
3024
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003025def redfishSupportPresent(host, session):
3026 url = "https://" + host + "/redfish/v1"
3027 try:
3028 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
3029 except(requests.exceptions.Timeout):
3030 return False
3031 except(requests.exceptions.ConnectionError) as err:
3032 return False
3033 if resp.status_code != 200:
3034 return False
3035 else:
3036 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05303037
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003038def certificateUpdate(host, args, session):
3039 """
3040 Called by certificate management function. update server/client/authority certificates
3041 Example:
3042 certificate update server https -f cert.pem
3043 certificate update authority ldap -f Root-CA.pem
3044 certificate update client ldap -f cert.pem
3045 @param host: string, the hostname or IP address of the bmc
3046 @param args: contains additional arguments used by the certificate update sub command
3047 @param session: the active session to use
3048 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003049 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003050 httpHeader.update(xAuthHeader)
Brad Bishop5da038f2020-07-10 14:21:43 -04003051 data = open(args.fileloc, 'r').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003052 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003053 if redfishSupportPresent(host, session):
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003054 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3055 return "Invalid service type"
3056 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3057 return "Invalid service type"
3058 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3059 return "Invalid service type"
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003060 url = "";
3061 if(args.type.lower() == 'server'):
3062 url = "https://" + host + \
3063 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
3064 elif(args.type.lower() == 'client'):
3065 url = "https://" + host + \
3066 "/redfish/v1/AccountService/LDAP/Certificates"
3067 elif(args.type.lower() == 'authority'):
3068 url = "https://" + host + \
3069 "/redfish/v1/Managers/bmc/Truststore/Certificates"
3070 else:
3071 return "Unsupported certificate type"
3072 resp = session.post(url, headers=httpHeader, data=data,
3073 verify=False)
3074 else:
3075 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3076 args.type.lower() + "/" + args.service.lower()
3077 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003078 except(requests.exceptions.Timeout):
3079 return(connectionErrHandler(args.json, "Timeout", None))
3080 except(requests.exceptions.ConnectionError) as err:
3081 return connectionErrHandler(args.json, "ConnectionError", err)
3082 if resp.status_code != 200:
3083 print(resp.text)
3084 return "Failed to update the certificate"
3085 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003086 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003087
3088def certificateDelete(host, args, session):
3089 """
3090 Called by certificate management function to delete certificate
3091 Example:
3092 certificate delete server https
3093 certificate delete authority ldap
3094 certificate delete client ldap
3095 @param host: string, the hostname or IP address of the bmc
3096 @param args: contains additional arguments used by the certificate delete sub command
3097 @param session: the active session to use
3098 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05003099 if redfishSupportPresent(host, session):
3100 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003101 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003102 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003103 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
3104 print("Deleting certificate url=" + url)
3105 try:
3106 resp = session.delete(url, headers=httpHeader)
3107 except(requests.exceptions.Timeout):
3108 return(connectionErrHandler(args.json, "Timeout", None))
3109 except(requests.exceptions.ConnectionError) as err:
3110 return connectionErrHandler(args.json, "ConnectionError", err)
3111 if resp.status_code != 200:
3112 print(resp.text)
3113 return "Failed to delete the certificate"
3114 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05003115 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003116
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003117def certificateReplace(host, args, session):
3118 """
3119 Called by certificate management function. replace server/client/
3120 authority certificates
3121 Example:
3122 certificate replace server https -f cert.pem
3123 certificate replace authority ldap -f Root-CA.pem
3124 certificate replace client ldap -f cert.pem
3125 @param host: string, the hostname or IP address of the bmc
3126 @param args: contains additional arguments used by the certificate
3127 replace sub command
3128 @param session: the active session to use
3129 """
Brad Bishop5da038f2020-07-10 14:21:43 -04003130 cert = open(args.fileloc, 'r').read()
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003131 try:
3132 if redfishSupportPresent(host, session):
3133 httpHeader = {'Content-Type': 'application/json'}
3134 httpHeader.update(xAuthHeader)
3135 url = "";
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003136 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3137 return "Invalid service type"
3138 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3139 return "Invalid service type"
3140 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3141 return "Invalid service type"
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003142 if(args.type.lower() == 'server'):
3143 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3144 elif(args.type.lower() == 'client'):
3145 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
3146 elif(args.type.lower() == 'authority'):
3147 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3148 replaceUrl = "https://" + host + \
3149 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
3150 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
3151 "CertificateString":cert}
3152 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
3153 else:
3154 httpHeader = {'Content-Type': 'application/octet-stream'}
3155 httpHeader.update(xAuthHeader)
3156 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3157 args.type.lower() + "/" + args.service.lower()
3158 resp = session.delete(url, headers=httpHeader)
3159 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
3160 except(requests.exceptions.Timeout):
3161 return(connectionErrHandler(args.json, "Timeout", None))
3162 except(requests.exceptions.ConnectionError) as err:
3163 return connectionErrHandler(args.json, "ConnectionError", err)
3164 if resp.status_code != 200:
3165 print(resp.text)
3166 return "Failed to replace the certificate"
3167 else:
3168 print("Replace complete.")
3169 return resp.text
3170
Marri Devender Rao34646402019-07-01 05:46:03 -05003171def certificateDisplay(host, args, session):
3172 """
3173 Called by certificate management function. display server/client/
3174 authority certificates
3175 Example:
3176 certificate display server
3177 certificate display authority
3178 certificate display client
3179 @param host: string, the hostname or IP address of the bmc
3180 @param args: contains additional arguments used by the certificate
3181 display sub command
3182 @param session: the active session to use
3183 """
3184 if not redfishSupportPresent(host, session):
3185 return "Not supported";
3186
3187 httpHeader = {'Content-Type': 'application/octet-stream'}
3188 httpHeader.update(xAuthHeader)
3189 if(args.type.lower() == 'server'):
3190 url = "https://" + host + \
3191 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3192 elif(args.type.lower() == 'client'):
3193 url = "https://" + host + \
3194 "/redfish/v1/AccountService/LDAP/Certificates/1"
3195 elif(args.type.lower() == 'authority'):
3196 url = "https://" + host + \
3197 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3198 try:
3199 resp = session.get(url, headers=httpHeader, verify=False)
3200 except(requests.exceptions.Timeout):
3201 return(connectionErrHandler(args.json, "Timeout", None))
3202 except(requests.exceptions.ConnectionError) as err:
3203 return connectionErrHandler(args.json, "ConnectionError", err)
3204 if resp.status_code != 200:
3205 print(resp.text)
3206 return "Failed to display the certificate"
3207 else:
3208 print("Display complete.")
3209 return resp.text
3210
Marri Devender Raoa208ff82019-07-01 05:51:27 -05003211def certificateList(host, args, session):
3212 """
3213 Called by certificate management function.
3214 Example:
3215 certificate list
3216 @param host: string, the hostname or IP address of the bmc
3217 @param args: contains additional arguments used by the certificate
3218 list sub command
3219 @param session: the active session to use
3220 """
3221 if not redfishSupportPresent(host, session):
3222 return "Not supported";
3223
3224 httpHeader = {'Content-Type': 'application/octet-stream'}
3225 httpHeader.update(xAuthHeader)
3226 url = "https://" + host + \
3227 "/redfish/v1/CertificateService/CertificateLocations/"
3228 try:
3229 resp = session.get(url, headers=httpHeader, verify=False)
3230 except(requests.exceptions.Timeout):
3231 return(connectionErrHandler(args.json, "Timeout", None))
3232 except(requests.exceptions.ConnectionError) as err:
3233 return connectionErrHandler(args.json, "ConnectionError", err)
3234 if resp.status_code != 200:
3235 print(resp.text)
3236 return "Failed to list certificates"
3237 else:
3238 print("List certificates complete.")
3239 return resp.text
3240
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003241def certificateGenerateCSR(host, args, session):
3242 """
3243 Called by certificate management function. Generate CSR for server/
3244 client certificates
3245 Example:
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003246 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
3247 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 -05003248 @param host: string, the hostname or IP address of the bmc
3249 @param args: contains additional arguments used by the certificate replace sub command
3250 @param session: the active session to use
3251 """
3252 if not redfishSupportPresent(host, session):
3253 return "Not supported";
3254
3255 httpHeader = {'Content-Type': 'application/octet-stream'}
3256 httpHeader.update(xAuthHeader)
3257 url = "";
3258 if(args.type.lower() == 'server'):
3259 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003260 usage_list = ["ServerAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003261 elif(args.type.lower() == 'client'):
3262 url = "/redfish/v1/AccountService/LDAP/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003263 usage_list = ["ClientAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003264 elif(args.type.lower() == 'authority'):
3265 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
3266 print("Generating CSR url=" + url)
3267 generateCSRUrl = "https://" + host + \
3268 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
3269 try:
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003270 alt_name_list = args.alternativeNames.split(",")
3271 data ={"CertificateCollection":{"@odata.id":url},
3272 "CommonName":args.commonName, "City":args.city,
3273 "Country":args.country, "Organization":args.organization,
3274 "OrganizationalUnit":args.organizationUnit, "State":args.state,
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003275 "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003276 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
3277 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
3278 "KeyUsage":usage_list, "Surname":args.surname,
3279 "UnstructuredName":args.unstructuredname}
3280 resp = session.post(generateCSRUrl, headers=httpHeader,
3281 json=data, verify=False)
3282 except(requests.exceptions.Timeout):
3283 return(connectionErrHandler(args.json, "Timeout", None))
3284 except(requests.exceptions.ConnectionError) as err:
3285 return connectionErrHandler(args.json, "ConnectionError", err)
3286 if resp.status_code != 200:
3287 print(resp.text)
3288 return "Failed to generate CSR"
3289 else:
3290 print("GenerateCSR complete.")
3291 return resp.text
3292
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003293def enableLDAPConfig(host, args, session):
Ratan Gupta9166cd22018-10-01 18:09:40 +05303294 """
3295 Called by the ldap function. Configures LDAP.
3296
3297 @param host: string, the hostname or IP address of the bmc
3298 @param args: contains additional arguments used by the ldap subcommand
3299 @param session: the active session to use
3300 @param args.json: boolean, if this flag is set to true, the output will
3301 be provided in json format for programmatic consumption
3302 """
3303
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003304 if(isRedfishSupport):
3305 return enableLDAP(host, args, session)
3306 else:
3307 return enableLegacyLDAP(host, args, session)
3308
3309def enableLegacyLDAP(host, args, session):
3310 """
3311 Called by the ldap function. Configures LDAP on Lagecy systems.
3312
3313 @param host: string, the hostname or IP address of the bmc
3314 @param args: contains additional arguments used by the ldap subcommand
3315 @param session: the active session to use
3316 @param args.json: boolean, if this flag is set to true, the output will
3317 be provided in json format for programmatic consumption
3318 """
3319
Ratan Gupta9166cd22018-10-01 18:09:40 +05303320 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303321 scope = {
3322 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
3323 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
3324 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
3325 }
3326
3327 serverType = {
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003328 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
3329 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303330 }
3331
3332 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
3333
3334 try:
Justin Thaler27197622019-01-23 14:42:11 -06003335 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303336 except(requests.exceptions.Timeout):
3337 return(connectionErrHandler(args.json, "Timeout", None))
3338 except(requests.exceptions.ConnectionError) as err:
3339 return connectionErrHandler(args.json, "ConnectionError", err)
3340
3341 return res.text
3342
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003343def enableLDAP(host, args, session):
3344 """
3345 Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
3346
3347 @param host: string, the hostname or IP address of the bmc
3348 @param args: contains additional arguments used by the ldap subcommand
3349 @param session: the active session to use
3350 @param args.json: boolean, if this flag is set to true, the output will
3351 be provided in json format for programmatic consumption
3352 """
3353
3354 scope = {
3355 'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
3356 'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
3357 'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
3358 }
3359
3360 serverType = {
3361 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
3362 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
3363 }
3364
3365 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3366
3367 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3368 serverTypeToBeEnabled = args.serverType
3369
3370 #If the given LDAP type is already enabled, then return
3371 if (serverTypeToBeEnabled == serverTypeEnabled):
3372 return("Server type " + serverTypeToBeEnabled + " is already enabled...")
3373
3374 try:
3375
3376 # Copy the role map from the currently enabled LDAP server type
3377 # to the newly enabled server type
3378 # Disable the currently enabled LDAP server type. Unless
3379 # it is disabled, we cannot enable a new LDAP server type
3380 if (serverTypeEnabled is not None):
3381
3382 if (serverTypeToBeEnabled != serverTypeEnabled):
3383 res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
3384
3385 data = "{\"data\": 0 }"
3386 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3387
3388 data = {"data": args.baseDN}
3389 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3390 if (res.status_code != requests.codes.ok):
3391 print("Updates to the property LDAPBaseDN failed...")
3392 return(res.text)
3393
3394 data = {"data": args.bindDN}
3395 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3396 if (res.status_code != requests.codes.ok):
3397 print("Updates to the property LDAPBindDN failed...")
3398 return(res.text)
3399
3400 data = {"data": args.bindPassword}
3401 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3402 if (res.status_code != requests.codes.ok):
3403 print("Updates to the property LDAPBindDNPassword failed...")
3404 return(res.text)
3405
3406 data = {"data": scope[args.scope]}
3407 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3408 if (res.status_code != requests.codes.ok):
3409 print("Updates to the property LDAPSearchScope failed...")
3410 return(res.text)
3411
3412 data = {"data": args.uri}
3413 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3414 if (res.status_code != requests.codes.ok):
3415 print("Updates to the property LDAPServerURI failed...")
3416 return(res.text)
3417
3418 data = {"data": args.groupAttrName}
3419 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3420 if (res.status_code != requests.codes.ok):
3421 print("Updates to the property GroupNameAttribute failed...")
3422 return(res.text)
3423
3424 data = {"data": args.userAttrName}
3425 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3426 if (res.status_code != requests.codes.ok):
3427 print("Updates to the property UserNameAttribute failed...")
3428 return(res.text)
3429
3430 #After updating the properties, enable the new server type
3431 data = "{\"data\": 1 }"
3432 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3433
3434 except(requests.exceptions.Timeout):
3435 return(connectionErrHandler(args.json, "Timeout", None))
3436 except(requests.exceptions.ConnectionError) as err:
3437 return connectionErrHandler(args.json, "ConnectionError", err)
3438 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303439
3440def disableLDAP(host, args, session):
3441 """
3442 Called by the ldap function. Deletes the LDAP Configuration.
3443
3444 @param host: string, the hostname or IP address of the bmc
3445 @param args: contains additional arguments used by the ldap subcommand
3446 @param session: the active session to use
3447 @param args.json: boolean, if this flag is set to true, the output
3448 will be provided in json format for programmatic consumption
3449 """
3450
Ratan Gupta9166cd22018-10-01 18:09:40 +05303451 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003452 if (isRedfishSupport) :
3453
3454 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3455
3456 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3457
3458 if (serverTypeEnabled is not None):
3459 #To keep the role map in sync,
3460 #If the server type being disabled has role map, then
3461 # - copy the role map to the other server type(s)
3462 for serverType in serverTypeMap.keys():
3463 if (serverType != serverTypeEnabled):
3464 res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
3465
3466 #Disable the currently enabled LDAP server type
3467 data = "{\"data\": 0 }"
3468 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3469
3470 else:
3471 return("LDAP server has not been enabled...")
3472
3473 else :
3474 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
3475 data = {"data": []}
3476 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3477
Ratan Gupta9166cd22018-10-01 18:09:40 +05303478 except(requests.exceptions.Timeout):
3479 return(connectionErrHandler(args.json, "Timeout", None))
3480 except(requests.exceptions.ConnectionError) as err:
3481 return connectionErrHandler(args.json, "ConnectionError", err)
3482
3483 return res.text
3484
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003485def enableDHCP(host, args, session):
3486
3487 """
3488 Called by the network function. Enables DHCP.
3489
3490 @param host: string, the hostname or IP address of the bmc
3491 @param args: contains additional arguments used by the ldap subcommand
3492 args.json: boolean, if this flag is set to true, the output
3493 will be provided in json format for programmatic consumption
3494 @param session: the active session to use
3495 """
3496
3497 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3498 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003499 data = "{\"data\": 1 }"
3500 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003501 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003502 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003503
3504 except(requests.exceptions.Timeout):
3505 return(connectionErrHandler(args.json, "Timeout", None))
3506 except(requests.exceptions.ConnectionError) as err:
3507 return connectionErrHandler(args.json, "ConnectionError", err)
3508 if res.status_code == 403:
3509 return "The specified Interface"+"("+args.Interface+")"+\
3510 " doesn't exist"
3511
3512 return res.text
3513
3514
3515def disableDHCP(host, args, session):
3516 """
3517 Called by the network function. Disables DHCP.
3518
3519 @param host: string, the hostname or IP address of the bmc
3520 @param args: contains additional arguments used by the ldap subcommand
3521 args.json: boolean, if this flag is set to true, the output
3522 will be provided in json format for programmatic consumption
3523 @param session: the active session to use
3524 """
3525
3526 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3527 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003528 data = "{\"data\": 0 }"
3529 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003530 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003531 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003532 except(requests.exceptions.Timeout):
3533 return(connectionErrHandler(args.json, "Timeout", None))
3534 except(requests.exceptions.ConnectionError) as err:
3535 return connectionErrHandler(args.json, "ConnectionError", err)
3536 if res.status_code == 403:
3537 return "The specified Interface"+"("+args.Interface+")"+\
3538 " doesn't exist"
3539 return res.text
3540
3541
3542def getHostname(host, args, session):
3543
3544 """
3545 Called by the network function. Prints out the Hostname.
3546
3547 @param host: string, the hostname or IP address of the bmc
3548 @param args: contains additional arguments used by the ldap subcommand
3549 args.json: boolean, if this flag is set to true, the output
3550 will be provided in json format for programmatic consumption
3551 @param session: the active session to use
3552 """
3553
3554 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003555
3556 try:
Justin Thaler27197622019-01-23 14:42:11 -06003557 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003558 except(requests.exceptions.Timeout):
3559 return(connectionErrHandler(args.json, "Timeout", None))
3560 except(requests.exceptions.ConnectionError) as err:
3561 return connectionErrHandler(args.json, "ConnectionError", err)
3562
3563 return res.text
3564
3565
3566def setHostname(host, args, session):
3567 """
3568 Called by the network function. Sets the Hostname.
3569
3570 @param host: string, the hostname or IP address of the bmc
3571 @param args: contains additional arguments used by the ldap subcommand
3572 args.json: boolean, if this flag is set to true, the output
3573 will be provided in json format for programmatic consumption
3574 @param session: the active session to use
3575 """
3576
3577 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003578
3579 data = {"data": args.HostName}
3580
3581 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003582 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003583 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003584 except(requests.exceptions.Timeout):
3585 return(connectionErrHandler(args.json, "Timeout", None))
3586 except(requests.exceptions.ConnectionError) as err:
3587 return connectionErrHandler(args.json, "ConnectionError", err)
3588
3589 return res.text
3590
3591
3592def getDomainName(host, args, session):
3593
3594 """
3595 Called by the network function. Prints out the DomainName.
3596
3597 @param host: string, the hostname or IP address of the bmc
3598 @param args: contains additional arguments used by the ldap subcommand
3599 args.json: boolean, if this flag is set to true, the output
3600 will be provided in json format for programmatic consumption
3601 @param session: the active session to use
3602 """
3603
3604 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3605 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003606
3607 try:
Justin Thaler27197622019-01-23 14:42:11 -06003608 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003609 except(requests.exceptions.Timeout):
3610 return(connectionErrHandler(args.json, "Timeout", None))
3611 except(requests.exceptions.ConnectionError) as err:
3612 return connectionErrHandler(args.json, "ConnectionError", err)
3613 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003614 return "The DomainName is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003615
3616 return res.text
3617
3618
3619def setDomainName(host, args, session):
3620 """
3621 Called by the network function. Sets the DomainName.
3622
3623 @param host: string, the hostname or IP address of the bmc
3624 @param args: contains additional arguments used by the ldap subcommand
3625 args.json: boolean, if this flag is set to true, the output
3626 will be provided in json format for programmatic consumption
3627 @param session: the active session to use
3628 """
3629
3630 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3631 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003632
3633 data = {"data": args.DomainName.split(",")}
3634
3635 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003636 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003637 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003638 except(requests.exceptions.Timeout):
3639 return(connectionErrHandler(args.json, "Timeout", None))
3640 except(requests.exceptions.ConnectionError) as err:
3641 return connectionErrHandler(args.json, "ConnectionError", err)
3642 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003643 return "Failed to set Domain Name"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003644
3645 return res.text
3646
3647
3648def getMACAddress(host, args, session):
3649
3650 """
3651 Called by the network function. Prints out the MACAddress.
3652
3653 @param host: string, the hostname or IP address of the bmc
3654 @param args: contains additional arguments used by the ldap subcommand
3655 args.json: boolean, if this flag is set to true, the output
3656 will be provided in json format for programmatic consumption
3657 @param session: the active session to use
3658 """
3659
3660 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3661 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003662
3663 try:
Justin Thaler27197622019-01-23 14:42:11 -06003664 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003665 except(requests.exceptions.Timeout):
3666 return(connectionErrHandler(args.json, "Timeout", None))
3667 except(requests.exceptions.ConnectionError) as err:
3668 return connectionErrHandler(args.json, "ConnectionError", err)
3669 if res.status_code == 404:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003670 return "Failed to get MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003671
3672 return res.text
3673
3674
3675def setMACAddress(host, args, session):
3676 """
3677 Called by the network function. Sets the MACAddress.
3678
3679 @param host: string, the hostname or IP address of the bmc
3680 @param args: contains additional arguments used by the ldap subcommand
3681 args.json: boolean, if this flag is set to true, the output
3682 will be provided in json format for programmatic consumption
3683 @param session: the active session to use
3684 """
3685
3686 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3687 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003688
3689 data = {"data": args.MACAddress}
3690
3691 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003692 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003693 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003694 except(requests.exceptions.Timeout):
3695 return(connectionErrHandler(args.json, "Timeout", None))
3696 except(requests.exceptions.ConnectionError) as err:
3697 return connectionErrHandler(args.json, "ConnectionError", err)
3698 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003699 return "Failed to set MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003700
3701 return res.text
3702
3703
3704def getDefaultGateway(host, args, session):
3705
3706 """
3707 Called by the network function. Prints out the DefaultGateway.
3708
3709 @param host: string, the hostname or IP address of the bmc
3710 @param args: contains additional arguments used by the ldap subcommand
3711 args.json: boolean, if this flag is set to true, the output
3712 will be provided in json format for programmatic consumption
3713 @param session: the active session to use
3714 """
3715
3716 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003717
3718 try:
Justin Thaler27197622019-01-23 14:42:11 -06003719 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003720 except(requests.exceptions.Timeout):
3721 return(connectionErrHandler(args.json, "Timeout", None))
3722 except(requests.exceptions.ConnectionError) as err:
3723 return connectionErrHandler(args.json, "ConnectionError", err)
3724 if res.status_code == 404:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003725 return "Failed to get Default Gateway info"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003726
3727 return res.text
3728
3729
3730def setDefaultGateway(host, args, session):
3731 """
3732 Called by the network function. Sets the DefaultGateway.
3733
3734 @param host: string, the hostname or IP address of the bmc
3735 @param args: contains additional arguments used by the ldap subcommand
3736 args.json: boolean, if this flag is set to true, the output
3737 will be provided in json format for programmatic consumption
3738 @param session: the active session to use
3739 """
3740
3741 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003742
3743 data = {"data": args.DefaultGW}
3744
3745 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003746 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003747 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003748 except(requests.exceptions.Timeout):
3749 return(connectionErrHandler(args.json, "Timeout", None))
3750 except(requests.exceptions.ConnectionError) as err:
3751 return connectionErrHandler(args.json, "ConnectionError", err)
3752 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003753 return "Failed to set Default Gateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003754
3755 return res.text
3756
3757
3758def viewNWConfig(host, args, session):
3759 """
3760 Called by the ldap function. Prints out network configured properties
3761
3762 @param host: string, the hostname or IP address of the bmc
3763 @param args: contains additional arguments used by the ldap subcommand
3764 args.json: boolean, if this flag is set to true, the output
3765 will be provided in json format for programmatic consumption
3766 @param session: the active session to use
3767 @return returns LDAP's configured properties.
3768 """
3769 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003770 try:
Justin Thaler27197622019-01-23 14:42:11 -06003771 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003772 except(requests.exceptions.Timeout):
3773 return(connectionErrHandler(args.json, "Timeout", None))
3774 except(requests.exceptions.ConnectionError) as err:
3775 return connectionErrHandler(args.json, "ConnectionError", err)
3776 except(requests.exceptions.RequestException) as err:
3777 return connectionErrHandler(args.json, "RequestException", err)
3778 if res.status_code == 404:
3779 return "LDAP server config has not been created"
3780 return res.text
3781
3782
3783def getDNS(host, args, session):
3784
3785 """
3786 Called by the network function. Prints out DNS servers on the interface
3787
3788 @param host: string, the hostname or IP address of the bmc
3789 @param args: contains additional arguments used by the ldap subcommand
3790 args.json: boolean, if this flag is set to true, the output
3791 will be provided in json format for programmatic consumption
3792 @param session: the active session to use
3793 """
3794
3795 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3796 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003797
3798 try:
Justin Thaler27197622019-01-23 14:42:11 -06003799 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003800 except(requests.exceptions.Timeout):
3801 return(connectionErrHandler(args.json, "Timeout", None))
3802 except(requests.exceptions.ConnectionError) as err:
3803 return connectionErrHandler(args.json, "ConnectionError", err)
3804 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003805 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003806
3807 return res.text
3808
3809
3810def setDNS(host, args, session):
3811 """
3812 Called by the network function. Sets DNS servers on the interface.
3813
3814 @param host: string, the hostname or IP address of the bmc
3815 @param args: contains additional arguments used by the ldap subcommand
3816 args.json: boolean, if this flag is set to true, the output
3817 will be provided in json format for programmatic consumption
3818 @param session: the active session to use
3819 """
3820
3821 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3822 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003823
3824 data = {"data": args.DNSServers.split(",")}
3825
3826 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003827 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003828 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003829 except(requests.exceptions.Timeout):
3830 return(connectionErrHandler(args.json, "Timeout", None))
3831 except(requests.exceptions.ConnectionError) as err:
3832 return connectionErrHandler(args.json, "ConnectionError", err)
3833 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003834 return "Failed to set DNS"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003835
3836 return res.text
3837
3838
3839def getNTP(host, args, session):
3840
3841 """
3842 Called by the network function. Prints out NTP servers on the interface
3843
3844 @param host: string, the hostname or IP address of the bmc
3845 @param args: contains additional arguments used by the ldap subcommand
3846 args.json: boolean, if this flag is set to true, the output
3847 will be provided in json format for programmatic consumption
3848 @param session: the active session to use
3849 """
3850
3851 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3852 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003853 try:
Justin Thaler27197622019-01-23 14:42:11 -06003854 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003855 except(requests.exceptions.Timeout):
3856 return(connectionErrHandler(args.json, "Timeout", None))
3857 except(requests.exceptions.ConnectionError) as err:
3858 return connectionErrHandler(args.json, "ConnectionError", err)
3859 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003860 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003861
3862 return res.text
3863
3864
3865def setNTP(host, args, session):
3866 """
3867 Called by the network function. Sets NTP servers on the interface.
3868
3869 @param host: string, the hostname or IP address of the bmc
3870 @param args: contains additional arguments used by the ldap subcommand
3871 args.json: boolean, if this flag is set to true, the output
3872 will be provided in json format for programmatic consumption
3873 @param session: the active session to use
3874 """
3875
3876 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3877 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003878
3879 data = {"data": args.NTPServers.split(",")}
3880
3881 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003882 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003883 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003884 except(requests.exceptions.Timeout):
3885 return(connectionErrHandler(args.json, "Timeout", None))
3886 except(requests.exceptions.ConnectionError) as err:
3887 return connectionErrHandler(args.json, "ConnectionError", err)
3888 if res.status_code == 403:
Sunitha Harishca5c9572020-08-12 00:24:53 -05003889 return "Failed to set NTP"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003890
3891 return res.text
3892
3893
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003894def addIP(host, args, session):
3895 """
3896 Called by the network function. Configures IP address on given interface
3897
3898 @param host: string, the hostname or IP address of the bmc
3899 @param args: contains additional arguments used by the ldap subcommand
3900 args.json: boolean, if this flag is set to true, the output
3901 will be provided in json format for programmatic consumption
3902 @param session: the active session to use
3903 """
3904
3905 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3906 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003907 protocol = {
3908 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3909 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3910 }
3911
3912 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3913 args.gateway]}
3914
3915 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003916 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003917 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003918 except(requests.exceptions.Timeout):
3919 return(connectionErrHandler(args.json, "Timeout", None))
3920 except(requests.exceptions.ConnectionError) as err:
3921 return connectionErrHandler(args.json, "ConnectionError", err)
3922 if res.status_code == 404:
3923 return "The specified Interface" + "(" + args.Interface + ")" +\
3924 " doesn't exist"
3925
3926 return res.text
3927
3928
3929def getIP(host, args, session):
3930 """
3931 Called by the network function. Prints out IP address of given interface
3932
3933 @param host: string, the hostname or IP address of the bmc
3934 @param args: contains additional arguments used by the ldap subcommand
3935 args.json: boolean, if this flag is set to true, the output
3936 will be provided in json format for programmatic consumption
3937 @param session: the active session to use
3938 """
3939
3940 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3941 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003942 try:
Justin Thaler27197622019-01-23 14:42:11 -06003943 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003944 except(requests.exceptions.Timeout):
3945 return(connectionErrHandler(args.json, "Timeout", None))
3946 except(requests.exceptions.ConnectionError) as err:
3947 return connectionErrHandler(args.json, "ConnectionError", err)
3948 if res.status_code == 404:
3949 return "The specified Interface" + "(" + args.Interface + ")" +\
3950 " doesn't exist"
3951
3952 return res.text
3953
3954
3955def deleteIP(host, args, session):
3956 """
3957 Called by the network function. Deletes the IP address from given Interface
3958
3959 @param host: string, the hostname or IP address of the bmc
3960 @param args: contains additional arguments used by the ldap subcommand
3961 @param session: the active session to use
3962 @param args.json: boolean, if this flag is set to true, the output
3963 will be provided in json format for programmatic consumption
3964 """
3965
3966 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3967 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003968 data = {"data": []}
3969 try:
Justin Thaler27197622019-01-23 14:42:11 -06003970 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003971 except(requests.exceptions.Timeout):
3972 return(connectionErrHandler(args.json, "Timeout", None))
3973 except(requests.exceptions.ConnectionError) as err:
3974 return connectionErrHandler(args.json, "ConnectionError", err)
3975 if res.status_code == 404:
3976 return "The specified Interface" + "(" + args.Interface + ")" +\
3977 " doesn't exist"
3978 objDict = json.loads(res.text)
3979 if not objDict['data']:
3980 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003981 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003982 try:
3983 if args.address in objDict['data'][obj]['Address']:
3984 url = "https://"+host+obj+"/action/Delete"
3985 try:
3986 res = session.post(url, headers=jsonHeader, json=data,
3987 verify=False, timeout=baseTimeout)
3988 except(requests.exceptions.Timeout):
3989 return(connectionErrHandler(args.json, "Timeout", None))
3990 except(requests.exceptions.ConnectionError) as err:
3991 return connectionErrHandler(args.json, "ConnectionError", err)
3992 return res.text
3993 else:
3994 continue
3995 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003996 continue
3997 return "No object found for address " + args.address + \
3998 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003999
4000
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004001def addVLAN(host, args, session):
4002 """
4003 Called by the network function. Creates VLAN on given interface.
4004
4005 @param host: string, the hostname or IP address of the bmc
4006 @param args: contains additional arguments used by the ldap subcommand
4007 args.json: boolean, if this flag is set to true, the output
4008 will be provided in json format for programmatic consumption
4009 @param session: the active session to use
4010 """
4011
4012 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004013
Sunitha Harish0baf6372019-07-31 03:59:03 -05004014 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004015 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004016 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004017 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004018 except(requests.exceptions.Timeout):
4019 return(connectionErrHandler(args.json, "Timeout", None))
4020 except(requests.exceptions.ConnectionError) as err:
4021 return connectionErrHandler(args.json, "ConnectionError", err)
4022 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05004023 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
4024 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004025
4026 return res.text
4027
4028
4029def deleteVLAN(host, args, session):
4030 """
4031 Called by the network function. Creates VLAN on given interface.
4032
4033 @param host: string, the hostname or IP address of the bmc
4034 @param args: contains additional arguments used by the ldap subcommand
4035 args.json: boolean, if this flag is set to true, the output
4036 will be provided in json format for programmatic consumption
4037 @param session: the active session to use
4038 """
4039
Sunitha Harish577a5032019-08-08 06:27:40 -05004040 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004041 data = {"data": []}
4042
4043 try:
Justin Thaler27197622019-01-23 14:42:11 -06004044 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004045 except(requests.exceptions.Timeout):
4046 return(connectionErrHandler(args.json, "Timeout", None))
4047 except(requests.exceptions.ConnectionError) as err:
4048 return connectionErrHandler(args.json, "ConnectionError", err)
4049 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05004050 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004051
4052 return res.text
4053
4054
4055def viewDHCPConfig(host, args, session):
4056 """
4057 Called by the network function. Shows DHCP configured Properties.
4058
4059 @param host: string, the hostname or IP address of the bmc
4060 @param args: contains additional arguments used by the ldap subcommand
4061 args.json: boolean, if this flag is set to true, the output
4062 will be provided in json format for programmatic consumption
4063 @param session: the active session to use
4064 """
4065
4066 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004067
4068 try:
Justin Thaler27197622019-01-23 14:42:11 -06004069 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004070 except(requests.exceptions.Timeout):
4071 return(connectionErrHandler(args.json, "Timeout", None))
4072 except(requests.exceptions.ConnectionError) as err:
4073 return connectionErrHandler(args.json, "ConnectionError", err)
4074
4075 return res.text
4076
4077
4078def configureDHCP(host, args, session):
4079 """
4080 Called by the network function. Configures/updates DHCP Properties.
4081
4082 @param host: string, the hostname or IP address of the bmc
4083 @param args: contains additional arguments used by the ldap subcommand
4084 args.json: boolean, if this flag is set to true, the output
4085 will be provided in json format for programmatic consumption
4086 @param session: the active session to use
4087 """
4088
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004089
4090 try:
4091 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
4092 if(args.DNSEnabled == True):
4093 data = '{"data": 1}'
4094 else:
4095 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004096 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004097 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004098 if(args.HostNameEnabled == True):
4099 data = '{"data": 1}'
4100 else:
4101 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004102 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004103 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004104 if(args.NTPEnabled == True):
4105 data = '{"data": 1}'
4106 else:
4107 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004108 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004109 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004110 if(args.SendHostNameEnabled == True):
4111 data = '{"data": 1}'
4112 else:
4113 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004114 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004115 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004116 except(requests.exceptions.Timeout):
4117 return(connectionErrHandler(args.json, "Timeout", None))
4118 except(requests.exceptions.ConnectionError) as err:
4119 return connectionErrHandler(args.json, "ConnectionError", err)
4120
4121 return res.text
4122
4123
4124def nwReset(host, args, session):
4125
4126 """
4127 Called by the network function. Resets networks setting to factory defaults.
4128
4129 @param host: string, the hostname or IP address of the bmc
4130 @param args: contains additional arguments used by the ldap subcommand
4131 args.json: boolean, if this flag is set to true, the output
4132 will be provided in json format for programmatic consumption
4133 @param session: the active session to use
4134 """
4135
4136 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004137 data = '{"data":[] }'
4138 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004139 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004140 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004141
4142 except(requests.exceptions.Timeout):
4143 return(connectionErrHandler(args.json, "Timeout", None))
4144 except(requests.exceptions.ConnectionError) as err:
4145 return connectionErrHandler(args.json, "ConnectionError", err)
4146
4147 return res.text
4148
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004149def getLDAPTypeEnabled(host,session):
4150
4151 """
4152 Called by LDAP related functions to find the LDAP server type that has been enabled.
4153 Returns None if LDAP has not been configured.
4154
4155 @param host: string, the hostname or IP address of the bmc
4156 @param session: the active session to use
4157 """
4158
4159 enabled = False
4160 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4161 for key,value in serverTypeMap.items():
4162 data = {"data": []}
4163 try:
4164 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4165 except(requests.exceptions.Timeout):
4166 print(connectionErrHandler(args.json, "Timeout", None))
4167 return
4168 except(requests.exceptions.ConnectionError) as err:
4169 print(connectionErrHandler(args.json, "ConnectionError", err))
4170 return
4171
4172 enabled = res.json()['data']
4173 if (enabled):
4174 return key
4175
4176def syncRoleMap(host,args,session,fromServerType,toServerType):
4177
4178 """
4179 Called by LDAP related functions to sync the role maps
4180 Returns False if LDAP has not been configured.
4181
4182 @param host: string, the hostname or IP address of the bmc
4183 @param session: the active session to use
4184 @param fromServerType : Server type whose role map has to be copied
4185 @param toServerType : Server type to which role map has to be copied
4186 """
4187
4188 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4189
4190 try:
4191 #Note: If the fromServerType has no role map, then
4192 #the toServerType will not have any role map.
4193
4194 #delete the privilege mapping from the toServerType and
4195 #then copy the privilege mapping from fromServerType to
4196 #toServerType.
4197 args.serverType = toServerType
4198 res = deleteAllPrivilegeMapping(host, args, session)
4199
4200 data = {"data": []}
4201 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4202 #Previously enabled server type has no role map
4203 if (res.status_code != requests.codes.ok):
4204
4205 #fromServerType has no role map; So, no need to copy
4206 #role map to toServerType.
4207 return
4208
4209 objDict = json.loads(res.text)
4210 dataDict = objDict['data']
4211 for key,value in dataDict.items():
4212 data = {"data": [value["GroupName"], value["Privilege"]]}
4213 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4214
4215 except(requests.exceptions.Timeout):
4216 return(connectionErrHandler(args.json, "Timeout", None))
4217 except(requests.exceptions.ConnectionError) as err:
4218 return connectionErrHandler(args.json, "ConnectionError", err)
4219 return res.text
4220
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004221
Ratan Guptafeee6372018-10-17 23:25:51 +05304222def createPrivilegeMapping(host, args, session):
4223 """
4224 Called by the ldap function. Creates the group and the privilege mapping.
4225
4226 @param host: string, the hostname or IP address of the bmc
4227 @param args: contains additional arguments used by the ldap subcommand
4228 @param session: the active session to use
4229 @param args.json: boolean, if this flag is set to true, the output
4230 will be provided in json format for programmatic consumption
4231 """
4232
Ratan Guptafeee6372018-10-17 23:25:51 +05304233 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004234 if (isRedfishSupport):
4235 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4236
4237 #To maintain the interface compatibility between op930 and op940, the server type has been made
4238 #optional. If the server type is not specified, then create the role-mapper for the currently
4239 #enabled server type.
4240 serverType = args.serverType
4241 if (serverType is None):
4242 serverType = getLDAPTypeEnabled(host,session)
4243 if (serverType is None):
4244 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4245
4246 data = {"data": [args.groupName,args.privilege]}
4247 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4248
4249 else:
4250 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4251 data = {"data": [args.groupName,args.privilege]}
4252 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4253
Ratan Guptafeee6372018-10-17 23:25:51 +05304254 except(requests.exceptions.Timeout):
4255 return(connectionErrHandler(args.json, "Timeout", None))
4256 except(requests.exceptions.ConnectionError) as err:
4257 return connectionErrHandler(args.json, "ConnectionError", err)
4258 return res.text
4259
4260def listPrivilegeMapping(host, args, session):
4261 """
4262 Called by the ldap function. Lists the group and the privilege mapping.
4263
4264 @param host: string, the hostname or IP address of the bmc
4265 @param args: contains additional arguments used by the ldap subcommand
4266 @param session: the active session to use
4267 @param args.json: boolean, if this flag is set to true, the output
4268 will be provided in json format for programmatic consumption
4269 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004270
4271 if (isRedfishSupport):
4272 serverType = args.serverType
4273 if (serverType is None):
4274 serverType = getLDAPTypeEnabled(host,session)
4275 if (serverType is None):
4276 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4277
4278 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4279
4280 else:
4281 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4282
Ratan Guptafeee6372018-10-17 23:25:51 +05304283 data = {"data": []}
4284
4285 try:
Justin Thaler27197622019-01-23 14:42:11 -06004286 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304287 except(requests.exceptions.Timeout):
4288 return(connectionErrHandler(args.json, "Timeout", None))
4289 except(requests.exceptions.ConnectionError) as err:
4290 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004291
Ratan Guptafeee6372018-10-17 23:25:51 +05304292 return res.text
4293
4294def deletePrivilegeMapping(host, args, session):
4295 """
4296 Called by the ldap function. Deletes the mapping associated with the group.
4297
4298 @param host: string, the hostname or IP address of the bmc
4299 @param args: contains additional arguments used by the ldap subcommand
4300 @param session: the active session to use
4301 @param args.json: boolean, if this flag is set to true, the output
4302 will be provided in json format for programmatic consumption
4303 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004304
4305 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304306 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4307 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304308 data = {"data": []}
4309
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004310 if (isRedfishSupport):
4311 if (args.serverType is None):
4312 serverType = getLDAPTypeEnabled(host,session)
4313 if (serverType is None):
4314 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4315 # search for the object having the mapping for the given group
4316 for key,value in ldapNameSpaceObjects.items():
4317 if value['GroupName'] == args.groupName:
4318 path = key
4319 break
4320
4321 if path == '':
4322 return "No privilege mapping found for this group."
4323
4324 # delete the object
4325 url = 'https://'+host+path+'/action/Delete'
4326
4327 else:
4328 # not interested in the config objet
4329 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4330
4331 # search for the object having the mapping for the given group
4332 for key,value in ldapNameSpaceObjects.items():
4333 if value['GroupName'] == args.groupName:
4334 path = key
4335 break
4336
4337 if path == '':
4338 return "No privilege mapping found for this group."
4339
4340 # delete the object
4341 url = 'https://'+host+path+'/action/delete'
4342
Ratan Guptafeee6372018-10-17 23:25:51 +05304343 try:
Justin Thaler27197622019-01-23 14:42:11 -06004344 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304345 except(requests.exceptions.Timeout):
4346 return(connectionErrHandler(args.json, "Timeout", None))
4347 except(requests.exceptions.ConnectionError) as err:
4348 return connectionErrHandler(args.json, "ConnectionError", err)
4349 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304350
Sivas SRR78835272018-11-27 05:27:19 -06004351def deleteAllPrivilegeMapping(host, args, session):
4352 """
4353 Called by the ldap function. Deletes all the privilege mapping and group defined.
4354 @param host: string, the hostname or IP address of the bmc
4355 @param args: contains additional arguments used by the ldap subcommand
4356 @param session: the active session to use
4357 @param args.json: boolean, if this flag is set to true, the output
4358 will be provided in json format for programmatic consumption
4359 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004360
Sivas SRR78835272018-11-27 05:27:19 -06004361 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4362 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4363 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004364 data = {"data": []}
4365
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004366 if (isRedfishSupport):
4367 if (args.serverType is None):
4368 serverType = getLDAPTypeEnabled(host,session)
4369 if (serverType is None):
4370 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4371
4372 else:
4373 # Remove the config object.
4374 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4375
Sivas SRR78835272018-11-27 05:27:19 -06004376 try:
4377 # search for GroupName property and delete if it is available.
4378 for path in ldapNameSpaceObjects.keys():
4379 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004380 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004381 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004382
Sivas SRR78835272018-11-27 05:27:19 -06004383 except(requests.exceptions.Timeout):
4384 return(connectionErrHandler(args.json, "Timeout", None))
4385 except(requests.exceptions.ConnectionError) as err:
4386 return connectionErrHandler(args.json, "ConnectionError", err)
4387 return res.text
4388
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004389def viewLDAPConfig(host, args, session):
4390 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004391 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004392
4393 @param host: string, the hostname or IP address of the bmc
4394 @param args: contains additional arguments used by the ldap subcommand
4395 args.json: boolean, if this flag is set to true, the output
4396 will be provided in json format for programmatic consumption
4397 @param session: the active session to use
4398 @return returns LDAP's configured properties.
4399 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004400
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004401 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004402 if (isRedfishSupport):
4403
4404 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4405
4406 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4407
4408 if (serverTypeEnabled is not None):
4409 data = {"data": []}
4410 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4411 else:
4412 return("LDAP server has not been enabled...")
4413
4414 else :
4415 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4416 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4417
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004418 except(requests.exceptions.Timeout):
4419 return(connectionErrHandler(args.json, "Timeout", None))
4420 except(requests.exceptions.ConnectionError) as err:
4421 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004422 if res.status_code == 404:
4423 return "LDAP server config has not been created"
4424 return res.text
4425
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004426def str2bool(v):
4427 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4428 return True
4429 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4430 return False
4431 else:
4432 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004433
Matt Spinler7d426c22018-09-24 14:42:07 -05004434def localUsers(host, args, session):
4435 """
4436 Enables and disables local BMC users.
4437
4438 @param host: string, the hostname or IP address of the bmc
4439 @param args: contains additional arguments used by the logging sub command
4440 @param session: the active session to use
4441 """
4442
Matt Spinler7d426c22018-09-24 14:42:07 -05004443 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4444 try:
Justin Thaler27197622019-01-23 14:42:11 -06004445 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004446 except(requests.exceptions.Timeout):
4447 return(connectionErrHandler(args.json, "Timeout", None))
4448 usersDict = json.loads(res.text)
4449
4450 if not usersDict['data']:
4451 return "No users found"
4452
4453 output = ""
4454 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004455
4456 # Skip LDAP and another non-local users
4457 if 'UserEnabled' not in usersDict['data'][user]:
4458 continue
4459
Matt Spinler7d426c22018-09-24 14:42:07 -05004460 name = user.split('/')[-1]
4461 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4462
4463 if args.local_users == "queryenabled":
4464 try:
Justin Thaler27197622019-01-23 14:42:11 -06004465 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004466 except(requests.exceptions.Timeout):
4467 return(connectionErrHandler(args.json, "Timeout", None))
4468
4469 result = json.loads(res.text)
4470 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4471
4472 elif args.local_users in ["enableall", "disableall"]:
4473 action = ""
4474 if args.local_users == "enableall":
4475 data = '{"data": true}'
4476 action = "Enabling"
4477 else:
4478 data = '{"data": false}'
4479 action = "Disabling"
4480
4481 output += "{action} {name}\n".format(action=action, name=name)
4482
4483 try:
Justin Thaler27197622019-01-23 14:42:11 -06004484 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004485 except(requests.exceptions.Timeout):
4486 return connectionErrHandler(args.json, "Timeout", None)
4487 except(requests.exceptions.ConnectionError) as err:
4488 return connectionErrHandler(args.json, "ConnectionError", err)
4489 else:
4490 return "Invalid local users argument"
4491
4492 return output
4493
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004494def setPassword(host, args, session):
4495 """
4496 Set local user password
4497 @param host: string, the hostname or IP address of the bmc
4498 @param args: contains additional arguments used by the logging sub
4499 command
4500 @param session: the active session to use
4501 @param args.json: boolean, if this flag is set to true, the output
4502 will be provided in json format for programmatic consumption
4503 @return: Session object
4504 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004505 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004506 if(isRedfishSupport):
4507 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4508 args.user
4509 data = {"Password":args.password}
4510 res = session.patch(url, headers=jsonHeader, json=data,
4511 verify=False, timeout=baseTimeout)
4512 else:
4513 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4514 "/action/SetPassword"
4515 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004516 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004517 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004518 except(requests.exceptions.Timeout):
4519 return(connectionErrHandler(args.json, "Timeout", None))
4520 except(requests.exceptions.ConnectionError) as err:
4521 return connectionErrHandler(args.json, "ConnectionError", err)
4522 except(requests.exceptions.RequestException) as err:
4523 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004524 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004525
4526def getThermalZones(host, args, session):
4527 """
4528 Get the available thermal control zones
4529 @param host: string, the hostname or IP address of the bmc
4530 @param args: contains additional arguments used to get the thermal
4531 control zones
4532 @param session: the active session to use
4533 @return: Session object
4534 """
4535 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4536
4537 try:
4538 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4539 except(requests.exceptions.Timeout):
4540 return(connectionErrHandler(args.json, "Timeout", None))
4541 except(requests.exceptions.ConnectionError) as err:
4542 return connectionErrHandler(args.json, "ConnectionError", err)
4543 except(requests.exceptions.RequestException) as err:
4544 return connectionErrHandler(args.json, "RequestException", err)
4545
4546 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004547 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004548
4549 zonesDict = json.loads(res.text)
4550 if not zonesDict['data']:
4551 return "No thermal control zones found"
4552 for zone in zonesDict['data']:
4553 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4554
4555 return "Zones: [ " + z + " ]"
4556
4557
4558def getThermalMode(host, args, session):
4559 """
4560 Get thermal control mode
4561 @param host: string, the hostname or IP address of the bmc
4562 @param args: contains additional arguments used to get the thermal
4563 control mode
4564 @param session: the active session to use
4565 @param args.zone: the zone to get the mode on
4566 @return: Session object
4567 """
4568 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4569 args.zone
4570
4571 try:
4572 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4573 except(requests.exceptions.Timeout):
4574 return(connectionErrHandler(args.json, "Timeout", None))
4575 except(requests.exceptions.ConnectionError) as err:
4576 return connectionErrHandler(args.json, "ConnectionError", err)
4577 except(requests.exceptions.RequestException) as err:
4578 return connectionErrHandler(args.json, "RequestException", err)
4579
4580 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004581 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004582
4583 propsDict = json.loads(res.text)
4584 if not propsDict['data']:
4585 return "No thermal control properties found on zone(" + args.zone + ")"
4586 curMode = "Current"
4587 supModes = "Supported"
4588 result = "\n"
4589 for prop in propsDict['data']:
4590 if (prop.casefold() == curMode.casefold()):
4591 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4592 if (prop.casefold() == supModes.casefold()):
4593 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4594 result += supModes + " Modes: [ " + s + " ]\n"
4595
4596 return result
4597
4598def setThermalMode(host, args, session):
4599 """
4600 Set thermal control mode
4601 @param host: string, the hostname or IP address of the bmc
4602 @param args: contains additional arguments used for setting the thermal
4603 control mode
4604 @param session: the active session to use
4605 @param args.zone: the zone to set the mode on
4606 @param args.mode: the mode to enable
4607 @return: Session object
4608 """
4609 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4610 args.zone + "/attr/Current"
4611
4612 # Check args.mode against supported modes using `getThermalMode` output
4613 modes = getThermalMode(host, args, session)
4614 modes = os.linesep.join([m for m in modes.splitlines() if m])
4615 modes = modes.replace("\n", ";").strip()
4616 modesDict = dict(m.split(': ') for m in modes.split(';'))
4617 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4618 if args.mode.casefold() not in \
4619 (m.casefold() for m in sModes.split(',')) or not args.mode:
4620 result = ("Unsupported mode('" + args.mode + "') given, " +
4621 "select a supported mode: \n" +
4622 getThermalMode(host, args, session))
4623 return result
4624
4625 data = '{"data":"' + args.mode + '"}'
4626 try:
4627 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4628 except(requests.exceptions.Timeout):
4629 return(connectionErrHandler(args.json, "Timeout", None))
4630 except(requests.exceptions.ConnectionError) as err:
4631 return connectionErrHandler(args.json, "ConnectionError", err)
4632 except(requests.exceptions.RequestException) as err:
4633 return connectionErrHandler(args.json, "RequestException", err)
4634
4635 if (data and res.status_code != 404):
4636 try:
4637 res = session.put(url, headers=jsonHeader,
4638 data=data, verify=False,
4639 timeout=30)
4640 except(requests.exceptions.Timeout):
4641 return(connectionErrHandler(args.json, "Timeout", None))
4642 except(requests.exceptions.ConnectionError) as err:
4643 return connectionErrHandler(args.json, "ConnectionError", err)
4644 except(requests.exceptions.RequestException) as err:
4645 return connectionErrHandler(args.json, "RequestException", err)
4646
4647 if res.status_code == 403:
4648 return "The specified thermal control zone(" + args.zone + ")" + \
4649 " does not exist"
4650
4651 return res.text
4652 else:
4653 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004654 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004655
4656
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004657def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004658 """
4659 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004660
Justin Thalere412dc22018-01-12 16:28:24 -06004661 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004662 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004663 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004664 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4665 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004666 group = parser.add_mutually_exclusive_group()
4667 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4668 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004669 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004670 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4671 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4672 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4673 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004674 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4675 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004676
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004677 #fru command
4678 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004679 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 -05004680 inv_subparser.required = True
4681 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004682 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4683 inv_print.set_defaults(func=fruPrint)
4684 #fru list [0....n]
4685 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4686 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4687 inv_list.set_defaults(func=fruList)
4688 #fru status
4689 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004690 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004691 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004692
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004693 #sensors command
4694 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004695 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 -05004696 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004697 #sensor print
4698 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4699 sens_print.set_defaults(func=sensor)
4700 #sensor list[0...n]
4701 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4702 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4703 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004704
Matthew Barth368e83c2019-02-01 13:48:25 -06004705 #thermal control commands
4706 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4707 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')
4708 #thermal control zones
4709 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4710 parser_thermZones.set_defaults(func=getThermalZones)
4711 #thermal control modes
4712 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4713 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4714 #get thermal control mode
4715 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4716 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4717 parser_getThermMode.set_defaults(func=getThermalMode)
4718 #set thermal control mode
4719 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4720 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4721 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4722 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004723
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004724 #sel command
4725 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004726 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 -05004727 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004728 #sel print
4729 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4730 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4731 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4732 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4733 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004734
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004735 #sel list
4736 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")
4737 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4738 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004739
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004740 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4741 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4742 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004743
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004744 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4745 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004746
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004747 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004748 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4749 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4750 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4751 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004752 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004753
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004754 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004755 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004756
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004757 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4758 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004759
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004760 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 -06004761 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 -06004762 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004763
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004764 #control the chassis identify led
4765 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4766 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4767 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004768
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004769 #collect service data
4770 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4771 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4772 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004773
Justin Thalere412dc22018-01-12 16:28:24 -06004774 #system quick health check
4775 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4776 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004777
Ravi Tejad8be0b42020-03-18 14:31:46 -05004778 #work with dumps
4779 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4780 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004781 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004782 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004783 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4784 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004785
Ravi Tejad8be0b42020-03-18 14:31:46 -05004786 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4787 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004788
Ravi Tejad8be0b42020-03-18 14:31:46 -05004789 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004790 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004791 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004792
Justin Thalere412dc22018-01-12 16:28:24 -06004793 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004794 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4795 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004796
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004797 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004798 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4799 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4800 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004801
Justin Thaler22b1bb52018-03-15 13:31:32 -05004802 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004803 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004804 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004805 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4806 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 -06004807 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.")
4808 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004809
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004810 #add alias to the bmc command
4811 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004812 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004813 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4814 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4815 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4816 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 -06004817 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004818 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004819
Justin Thalere412dc22018-01-12 16:28:24 -06004820 #gard clear
4821 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4822 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004823
Justin Thalere412dc22018-01-12 16:28:24 -06004824 #firmware_flash
4825 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4826 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 -05004827 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004828
Justin Thalere412dc22018-01-12 16:28:24 -06004829 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4830 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4831 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4832 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004833
Justin Thaler22b1bb52018-03-15 13:31:32 -05004834 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004835 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4836 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004837
Justin Thaler22b1bb52018-03-15 13:31:32 -05004838 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4839 fwActivateStatus.set_defaults(func=activateStatus)
4840
Justin Thaler3d71d402018-07-24 14:35:39 -05004841 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4842 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4843 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004844
Justin Thaler3d71d402018-07-24 14:35:39 -05004845 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4846 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4847 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004848
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004849 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4850 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4851 fwDelete.set_defaults(func=deleteFWVersion)
4852
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004853 #logging
4854 parser_logging = subparsers.add_parser("logging", help="logging controls")
4855 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004856
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004857 #turn rest api logging on/off
4858 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4859 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4860 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004861
4862 #remote logging
4863 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4864 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4865 parser_remote_logging.set_defaults(func=remoteLogging)
4866
4867 #configure remote logging
4868 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4869 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4870 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4871 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004872
4873 #certificate management
4874 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4875 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4876
4877 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4878 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4879 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4880 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4881 certUpdate.set_defaults(func=certificateUpdate)
4882
4883 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4884 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4885 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4886 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004887
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004888 certReplace = certMgmt_subproc.add_parser('replace',
4889 help="Replace the certificate")
4890 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4891 help="certificate type to replace")
4892 certReplace.add_argument('service', choices=['https', 'ldap'],
4893 help="Service to replace the certificate")
4894 certReplace.add_argument('-f', '--fileloc', required=True,
4895 help="The absolute path to the certificate file")
4896 certReplace.set_defaults(func=certificateReplace)
4897
Marri Devender Rao34646402019-07-01 05:46:03 -05004898 certDisplay = certMgmt_subproc.add_parser('display',
4899 help="Print the certificate")
4900 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4901 help="certificate type to display")
4902 certDisplay.set_defaults(func=certificateDisplay)
4903
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004904 certList = certMgmt_subproc.add_parser('list',
4905 help="Certificate list")
4906 certList.set_defaults(func=certificateList)
4907
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004908 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4909 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4910 help="Generate CSR")
4911 certGenerateCSR.add_argument('city',
4912 help="The city or locality of the organization making the request")
4913 certGenerateCSR.add_argument('commonName',
4914 help="The fully qualified domain name of the component that is being secured.")
4915 certGenerateCSR.add_argument('country',
4916 help="The country of the organization making the request")
4917 certGenerateCSR.add_argument('organization',
4918 help="The name of the organization making the request.")
4919 certGenerateCSR.add_argument('organizationUnit',
4920 help="The name of the unit or division of the organization making the request.")
4921 certGenerateCSR.add_argument('state',
4922 help="The state, province, or region of the organization making the request.")
4923 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4924 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004925 certGenerateCSR.add_argument('keyCurveId',
4926 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4927 certGenerateCSR.add_argument('contactPerson',
4928 help="The name of the user making the request")
4929 certGenerateCSR.add_argument('email',
4930 help="The email address of the contact within the organization")
4931 certGenerateCSR.add_argument('alternativeNames',
4932 help="Additional hostnames of the component that is being secured")
4933 certGenerateCSR.add_argument('givenname',
4934 help="The given name of the user making the request")
4935 certGenerateCSR.add_argument('surname',
4936 help="The surname of the user making the request")
4937 certGenerateCSR.add_argument('unstructuredname',
4938 help="he unstructured name of the subject")
4939 certGenerateCSR.add_argument('initials',
4940 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004941 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4942
Matt Spinler7d426c22018-09-24 14:42:07 -05004943 # local users
4944 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4945 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4946 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4947 parser_users.set_defaults(func=localUsers)
4948
Ratan Gupta9166cd22018-10-01 18:09:40 +05304949 #LDAP
4950 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4951 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4952
4953 #configure and enable LDAP
4954 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4955 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4956 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4957 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4958 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4959 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4960 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004961 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304962 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004963 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4964 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4965 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304966
4967 # disable LDAP
4968 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4969 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004970 # view-config
4971 parser_ldap_config = \
4972 ldap_sub.add_parser("view-config", help="prints out a list of all \
4973 LDAPS's configured properties")
4974 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304975
Ratan Guptafeee6372018-10-17 23:25:51 +05304976 #create group privilege mapping
4977 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4978 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4979 help="sub-command help", dest='command')
4980
4981 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 -05004982 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4983 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304984 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004985 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 +05304986 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4987
4988 #list group privilege mapping
4989 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004990 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4991 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304992 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4993
4994 #delete group privilege mapping
4995 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004996 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4997 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304998 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
4999 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
5000
Sivas SRR78835272018-11-27 05:27:19 -06005001 #deleteAll group privilege mapping
5002 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005003 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5004 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06005005 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
5006
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06005007 # set local user password
5008 parser_set_password = subparsers.add_parser("set_password",
5009 help="Set password of local user")
5010 parser_set_password.add_argument( "-p", "--password", required=True,
5011 help="Password of local user")
5012 parser_set_password.set_defaults(func=setPassword)
5013
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005014 # network
5015 parser_nw = subparsers.add_parser("network", help="network controls")
5016 nw_sub = parser_nw.add_subparsers(title='subcommands',
5017 description='valid subcommands',
5018 help="sub-command help",
5019 dest='command')
5020
5021 # enable DHCP
5022 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
5023 help="enables the DHCP on given "
5024 "Interface")
5025 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005026 help="Name of the ethernet interface(it can"
5027 "be obtained by the "
5028 "command:network view-config)"
5029 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005030 parser_enable_dhcp.set_defaults(func=enableDHCP)
5031
5032 # disable DHCP
5033 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
5034 help="disables the DHCP on given "
5035 "Interface")
5036 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005037 help="Name of the ethernet interface(it can"
5038 "be obtained by the "
5039 "command:network view-config)"
5040 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005041 parser_disable_dhcp.set_defaults(func=disableDHCP)
5042
5043 # get HostName
5044 parser_gethostname = nw_sub.add_parser("getHostName",
5045 help="prints out HostName")
5046 parser_gethostname.set_defaults(func=getHostname)
5047
5048 # set HostName
5049 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
5050 parser_sethostname.add_argument("-H", "--HostName", required=True,
5051 help="A HostName for the BMC")
5052 parser_sethostname.set_defaults(func=setHostname)
5053
5054 # get domainname
5055 parser_getdomainname = nw_sub.add_parser("getDomainName",
5056 help="prints out DomainName of "
5057 "given Interface")
5058 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005059 help="Name of the ethernet interface(it "
5060 "can be obtained by the "
5061 "command:network view-config)"
5062 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005063 parser_getdomainname.set_defaults(func=getDomainName)
5064
5065 # set domainname
5066 parser_setdomainname = nw_sub.add_parser("setDomainName",
5067 help="sets DomainName of given "
5068 "Interface")
5069 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
5070 help="Ex: DomainName=Domain1,Domain2,...")
5071 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005072 help="Name of the ethernet interface(it "
5073 "can be obtained by the "
5074 "command:network view-config)"
5075 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005076 parser_setdomainname.set_defaults(func=setDomainName)
5077
5078 # get MACAddress
5079 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
5080 help="prints out MACAddress the "
5081 "given Interface")
5082 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005083 help="Name of the ethernet interface(it "
5084 "can be obtained by the "
5085 "command:network view-config)"
5086 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005087 parser_getmacaddress.set_defaults(func=getMACAddress)
5088
5089 # set MACAddress
5090 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
5091 help="sets MACAddress")
5092 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
5093 help="A MACAddress for the given "
5094 "Interface")
5095 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005096 help="Name of the ethernet interface(it can"
5097 "be obtained by the "
5098 "command:network view-config)"
5099 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005100 parser_setmacaddress.set_defaults(func=setMACAddress)
5101
5102 # get DefaultGW
5103 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
5104 help="prints out DefaultGateway "
5105 "the BMC")
5106 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
5107
5108 # set DefaultGW
5109 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
5110 help="sets DefaultGW")
5111 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
5112 help="A DefaultGateway for the BMC")
5113 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
5114
5115 # view network Config
5116 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
5117 "list of all network's configured "
5118 "properties")
5119 parser_ldap_config.set_defaults(func=viewNWConfig)
5120
5121 # get DNS
5122 parser_getDNS = nw_sub.add_parser("getDNS",
5123 help="prints out DNS servers on the "
5124 "given interface")
5125 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005126 help="Name of the ethernet interface(it can"
5127 "be obtained by the "
5128 "command:network view-config)"
5129 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005130 parser_getDNS.set_defaults(func=getDNS)
5131
5132 # set DNS
5133 parser_setDNS = nw_sub.add_parser("setDNS",
5134 help="sets DNS servers on the given "
5135 "interface")
5136 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5137 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5138 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005139 help="Name of the ethernet interface(it can"
5140 "be obtained by the "
5141 "command:network view-config)"
5142 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005143 parser_setDNS.set_defaults(func=setDNS)
5144
5145 # get NTP
5146 parser_getNTP = nw_sub.add_parser("getNTP",
5147 help="prints out NTP servers on the "
5148 "given interface")
5149 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005150 help="Name of the ethernet interface(it can"
5151 "be obtained by the "
5152 "command:network view-config)"
5153 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005154 parser_getNTP.set_defaults(func=getNTP)
5155
5156 # set NTP
5157 parser_setNTP = nw_sub.add_parser("setNTP",
5158 help="sets NTP servers on the given "
5159 "interface")
5160 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5161 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5162 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005163 help="Name of the ethernet interface(it can"
5164 "be obtained by the "
5165 "command:network view-config)"
5166 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005167 parser_setNTP.set_defaults(func=setNTP)
5168
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005169 # configure IP
5170 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5171 "given interface")
5172 parser_ip_config.add_argument("-a", "--address", required=True,
5173 help="IP address of given interface")
5174 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5175 help="The gateway for given interface")
5176 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5177 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005178 parser_ip_config.add_argument("-p", "--type", required=True,
5179 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005180 help="The protocol type of the given"
5181 "IP address")
5182 parser_ip_config.add_argument("-I", "--Interface", required=True,
5183 help="Name of the ethernet interface(it can"
5184 "be obtained by the "
5185 "command:network view-config)"
5186 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5187 parser_ip_config.set_defaults(func=addIP)
5188
5189 # getIP
5190 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5191 "of given interface")
5192 parser_getIP.add_argument("-I", "--Interface", required=True,
5193 help="Name of the ethernet interface(it can"
5194 "be obtained by the command:network view-config)"
5195 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5196 parser_getIP.set_defaults(func=getIP)
5197
5198 # rmIP
5199 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5200 "of given interface")
5201 parser_rmIP.add_argument("-a", "--address", required=True,
5202 help="IP address to remove form given Interface")
5203 parser_rmIP.add_argument("-I", "--Interface", required=True,
5204 help="Name of the ethernet interface(it can"
5205 "be obtained by the command:network view-config)"
5206 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5207 parser_rmIP.set_defaults(func=deleteIP)
5208
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005209 # add VLAN
5210 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5211 "on given interface with given "
5212 "VLAN Identifier")
5213 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5214 choices=['eth0', 'eth1'],
5215 help="Name of the ethernet interface")
5216 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5217 help="VLAN Identifier")
5218 parser_create_vlan.set_defaults(func=addVLAN)
5219
5220 # delete VLAN
5221 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5222 "on given interface with given "
5223 "VLAN Identifier")
5224 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5225 help="Name of the ethernet interface(it can"
5226 "be obtained by the "
5227 "command:network view-config)"
5228 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5229 parser_delete_vlan.set_defaults(func=deleteVLAN)
5230
5231 # viewDHCPConfig
5232 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5233 help="Shows DHCP configured "
5234 "Properties")
5235 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5236
5237 # configureDHCP
5238 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5239 help="Configures/updates DHCP "
5240 "Properties")
5241 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5242 required=True, help="Sets DNSEnabled property")
5243 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5244 required=True,
5245 help="Sets HostNameEnabled property")
5246 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5247 required=True,
5248 help="Sets NTPEnabled property")
5249 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5250 required=True,
5251 help="Sets SendHostNameEnabled property")
5252 parser_configDHCP.set_defaults(func=configureDHCP)
5253
5254 # network factory reset
5255 parser_nw_reset = nw_sub.add_parser("nwReset",
5256 help="Resets networks setting to "
5257 "factory defaults. "
5258 "note:Reset settings will be applied "
5259 "after BMC reboot")
5260 parser_nw_reset.set_defaults(func=nwReset)
5261
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005262 return parser
5263
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005264def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005265 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005266 main function for running the command line utility as a sub application
5267 """
5268 global toolVersion
Justin Thalerc42e4e52020-05-13 12:04:24 -05005269 toolVersion = "1.19"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005270 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005271
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005272 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005273 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005274
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005275 totTimeStart = int(round(time.time()*1000))
5276
5277 if(sys.version_info < (3,0)):
5278 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5279 if sys.version_info >= (3,0):
5280 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005281 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005282 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005283 sys.exit(0)
5284 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005285 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005286 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005287 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005288 if(hasattr(args, 'host') and hasattr(args,'user')):
5289 if (args.askpw):
5290 pw = getpass.getpass()
5291 elif(args.PW is not None):
5292 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005293 elif(args.PWenvvar):
5294 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005295 else:
5296 print("You must specify a password")
5297 sys.exit()
5298 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005299 mysess = login(args.host, args.user, pw, args.json,
5300 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005301 if(mysess == None):
5302 print("Login Failed!")
5303 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005304 if(sys.version_info < (3,0)):
5305 if isinstance(mysess, basestring):
5306 print(mysess)
5307 sys.exit(1)
5308 elif sys.version_info >= (3,0):
5309 if isinstance(mysess, str):
5310 print(mysess)
5311 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005312 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005313 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005314 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005315 output = args.func(args.host, args, mysess)
5316 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005317 if isinstance(output, dict):
5318 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5319 else:
5320 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005321 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005322 logout(args.host, args.user, pw, mysess, args.json)
5323 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005324 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5325 print("loginTime: " + str(logintimeStop - logintimeStart))
5326 print("command Time: " + str(commandTimeStop - commandTimeStart))
5327 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005328 print("usage:\n"
5329 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5330 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005331 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005332 "\t{fru,sensors,sel,chassis,collect_service_data, \
5333 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005334 "\t...\n" +
5335 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005336 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005337
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005338if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005339 """
5340 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005341
5342 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005343 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005344
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005345 isTTY = sys.stdout.isatty()
5346 assert sys.version_info >= (2,7)
5347 main()